import type { ResolvedConfig } from './config/load.js'; import type { ResolvedDatabase } from './config/load.js'; import type { BlueprintInput } from './config/schema.js'; import type { EnvDefs, ResolveEnvDefs } from './config/env-types.js'; import type { ManagedConnection, ConnectionRole } from '../data/db/pool.js'; import type { Surface } from './surface/types.js'; import type { LifecycleConfig } from './lifecycle/types.js'; /** The application instance — holds config, connection pools, surfaces, and lifecycle. */ export interface Manifold { /** Resolved configuration derived from the Blueprint passed to createManifold. */ readonly config: ResolvedConfig; /** Typed environment variables resolved from the `env` config field. */ readonly env: Readonly>; /** Database connection pool manager — use `pool.getOrCreate(config.database(name))` outside managed contexts. */ readonly pool: PoolState; /** Test isolation lifecycle tracker — used internally by pipework/test. */ readonly isolation: IsolationState; /** Connection leak detector — tracks active connections for assertNoLeaks(). */ readonly connections: ConnectionTracker; /** Returns the names of all registered surfaces (http, worker, script). */ surfaceNames(): readonly string[]; /** Returns a copy of the surface map keyed by surface name. */ surfaceMap(): Readonly>; /** Starts all surfaces and installs SIGTERM/SIGINT handlers. Throws if already started. */ start(): Promise; /** Gracefully shuts down surfaces, runs pre-shutdown hooks, and closes all pools. */ stop(): Promise; /** Runs a callback in a managed job context — the canonical entry point for seed scripts and one-off tasks. */ seed(fn: () => T | Promise, options?: SeedOptions): Promise; } /** ALS context the {@link Manifold.seed} callback runs under — tenant scope, auth principal, and job type. */ export interface SeedOptions { tenant?: string | null; auth?: unknown; jobType?: string; } /** Manages database connection pools keyed by database name. */ export interface PoolState { /** Returns existing pool or creates one for this database config and role (default `owner`). The `app` role connects via `config.appUrl` (falling back to `url` when unset). */ getOrCreate(config: ResolvedDatabase, role?: ConnectionRole): ManagedConnection; /** Returns pool by name, or undefined if not yet created. */ get(name: string): ManagedConnection | undefined; /** True when a test-harness override is registered for this database — collapsed (transaction-isolation) mode, where every role shares the single rolled-back connection. */ isOverridden(name: string): boolean; /** Closes all managed connections. */ closeAll(): Promise; /** Number of active connection pools. */ count(): number; /** Registers a test-mode connection override. getOrCreate() returns overrides before creating new connections. */ override(name: string, conn: ManagedConnection): void; /** Removes all test-mode connection overrides. */ clearOverrides(): void; } /** Tracks test isolation lifecycle — detects leaked isolation contexts. */ export interface IsolationState { /** Marks the start of an isolation context (e.g. BEGIN in a test). */ markBegin(): void; /** Marks the end of an isolation context (e.g. ROLLBACK in a test). */ markEnd(): void; /** Throws InvariantViolation if any isolation contexts are still active. */ assertClean(): void; /** Returns counts of active, total begins, and total ends. */ stats(): { active: number; totalBegins: number; totalEnds: number; }; /** Resets all counters — only for test infrastructure. */ reset(): void; } /** Tracks active database connections for leak detection. */ export interface ConnectionTracker { /** Records a new active connection with its origin context. */ track(id: string, name: string, context: string): void; /** Marks a connection as released. */ release(id: string): void; /** Number of currently tracked connections. */ activeCount(): number; /** Throws InvariantViolation if active connections exceed maxExpected. */ assertNoLeaks(maxExpected: number): void; } /** * Creates the Pipework application instance. This is the entry point for every Pipework app. * Define in `pipework.config.ts` and export as default. * * The `env` field declares the app's environment variables — the canonical * home for runtime config (ports, service tokens, bucket names, flags) in * place of scattered `process.env` reads. Each variable is read once at config * load, validated and coerced to its declared type (loud error on a bad or * missing-required value), and exposed typed on `manifold.env`. * * @example * const manifold = createManifold({ * databases: { app: { url: 'DATABASE_URL', testUrl: 'DATABASE_URL_TEST' } }, * env: { * PORT: { type: 'number', defaults: { development: '3000', test: '0' } }, * S3_BUCKET: { type: 'string', required: true }, * API_TOKEN: { type: 'string', required: true, sensitive: true }, * }, * }) * manifold.env.PORT // number — from process.env.PORT, or the per-environment default * manifold.env.S3_BUCKET // string — startup fails loudly if unset * export default manifold */ export declare function createManifold(raw: Omit & { env?: TEnv | undefined; surfaces?: Record; lifecycle?: LifecycleConfig; }): Manifold; //# sourceMappingURL=pipework.d.ts.map