import type { OnDemandSitesConfig, SiteRouteTemplate } from './types';
/** Expand a leading `~` (or `~/…`) to the resolved home directory. */
export declare function expandHome(p: string, home: string): string;
/** A registry-safe id derived from a host (`a.localhost` → `a.localhost`). */
export declare function siteIdForHost(host: string): string;
/**
 * The host's single project label for convention discovery: `<name>.<tld>` →
 * `name`. Multi-label hosts (`docs.app.localhost`) and bare TLDs don't discover —
 * point those at an explicit `sites` entry. Returns `null` when no TLD matches.
 */
export declare function projectNameFromHost(host: string, tlds: string[]): string | null;
/**
 * Read a per-project {@link SiteManifest} so users can define the dev startup
 * manually. Checked sources, in order: a `rpx.site.json` file in the project,
 * then a `"rpx"` key in its `package.json`. Returns `null` when neither exists
 * (or both are malformed).
 */
export declare function readSiteManifest(dir: string, deps: ResolverProbes): SiteManifest | null;
/*` dependency in
 *   `package.json`. Boots frontend (`/`), API (`/api`) and docs (`/docs`) with
 *   the conventional `PORT`/`PORT_API`/`PORT_DOCS` env, deferring proxy + TLS to
 *   rpx (`STACKS_PROXY_MANAGED=1`) and taking its public origin via `APP_URL`.
 * - **Generic** — any `package.json` with a `dev` script: a single `bun run dev`
 *   backend on `PORT`.
 * - Otherwise `null`.
 */
export declare function detectProjectPreset(dir: string, deps: ResolverProbes): SitePreset | null;
/**
 * Build a {@link SiteResolver} over an {@link OnDemandSitesConfig}. Explicit
 * `sites` are matched first (exact host, then wildcard), then convention
 * discovery under `roots`.
 */
export declare function createSiteResolver(config: OnDemandSitesConfig, deps?: SiteResolverDeps): SiteResolver;
/**
 * Enumerate the sites rpx can currently boot — explicit non-wildcard
 * {@link SiteConfig}s plus every project discovered by scanning the configured
 * roots. Powers `rpx sites`. Each entry is a fully-resolved {@link ResolvedSite}
 * (so the caller sees the dir, command, and host it would serve).
 */
export declare function listDiscoverableSites(config: OnDemandSitesConfig, deps?: SiteResolverDeps): ResolvedSite[];
/** A fully-resolved site, ready for the supervisor to boot and route. */
export declare interface ResolvedSite {
  host: string
  id: string
  dir: string
  command: string
  env: Record<string, string>
  routes: SiteRouteTemplate[]
  selfRegisters: boolean
  idleTimeoutMs: number
  source: 'config' | 'discovered'
}
/**
 * The dev-command shape for a recognized project kind. Returned by a
 * {@link SiteDetector}; the resolver folds it into a {@link ResolvedSite}.
 */
export declare interface SitePreset {
  command: string
  env?: Record<string, string>
  routes?: SiteRouteTemplate[]
  selfRegisters?: boolean
  urlEnv?: string[]
}
/**
 * A per-project override of how rpx boots a site — so the dev startup can be
 * defined **manually** instead of relying on auto-detection. Read from a
 * `rpx.site.json` file in the project, or a `"rpx"` key in its `package.json`.
 * A manifest with a `command` fully defines the preset (and makes even a
 * directory that isn't otherwise a recognized project bootable).
 *
 * ```jsonc
 * // rpx.site.json
 * {
 *   "command": "pnpm dev",
 *   "env": { "NODE_ENV": "development" },
 *   "routes": [
 *     { "path": "/", "portEnv": "PORT", "defaultPort": 5173, "readyGate": true },
 *     { "path": "/api", "portEnv": "API_PORT", "defaultPort": 4000 }
 *   ]
 * }
 * ```
 */
export declare interface SiteManifest {
  command?: string
  env?: Record<string, string>
  routes?: SiteRouteTemplate[]
  selfRegisters?: boolean
  urlEnv?: string[]
}
/** Filesystem probes the resolver and detector use — injected for tests. */
export declare interface ResolverProbes {
  dirExists: (p: string) => boolean
  fileExists: (p: string) => boolean
  readText: (p: string) => string | null
}
export declare interface SiteResolverDeps extends Partial<ResolverProbes> {
  detect?: SiteDetector
  homeDir?: string
  readdir?: (p: string) => string[]
}
/** Resolve a host to a site (or `null`). Construct once, call per request. */
export declare interface SiteResolver {
  resolve: (host: string) => ResolvedSite | null
}
/** Detect a project kind from its directory. Returns `null` for "not a dev project". */
export type SiteDetector = (dir: string, deps: ResolverProbes) => SitePreset | null;
