import type { SqlFragment } from "./sql.js"; export { isHostedFunctionInvocationRuntime, isProductionServerlessFunctionRuntime, } from "./migration-runtime.js"; export interface DbExecQuery { sql: string; args?: unknown[]; timeoutMs?: number; maxAttempts?: number; } export type DbExecStatement = string | DbExecQuery; export type DbExecInput = DbExecStatement | SqlFragment; export interface DbExec { execute(sql: DbExecInput): Promise<{ rows: any[]; rowsAffected: number; }>; transaction?(fn: (tx: DbExec) => Promise): Promise; atomicBatch?(statements: readonly DbExecStatement[]): Promise>; close?(): Promise; } export interface DbExecConfig { url?: string; } export declare function getActivePgliteTransactionClient(url: string): any | undefined; export declare function getDatabaseUrl(fallback?: string, options?: { explicitOnly?: boolean; }): string; export declare function getIsolatedTestDatabaseUrl(): string | undefined; export declare function getRuntimeDatabaseUrl(fallback?: string): string; export declare function getLocalDatabaseUrl(fallback?: string): string; export declare function getRuntimeDatabaseSource(fallback?: string): string; export declare function getMigrationDatabaseUrl(): string; export declare function isPgliteUrl(url: string): boolean; export declare function pgliteDataDirFromUrl(url: string): string; export declare function pgliteRuntimeDataDir(dataDir: string): string; export declare function pgliteClientKeyFromUrl(url: string): string; export declare function loadPglitePackage(): Promise<{ PGlite: any; }>; export declare function loadPgliteDrizzle(): Promise<{ PGlite: any; drizzle: any; }>; export declare function onDbClientsClosing(hook: () => void): void; export declare function beginPgliteClientShutdown(): void; export declare function resumePgliteClientAccess(): void; export declare function waitForPgliteClientOperations(): Promise; export declare function pgliteProcessLockPath(dataDir: string): string; export declare function isProcessAlive(pid: number): boolean; export declare function readPgliteProcessLockOwner(fs: typeof import("fs"), lockPath: string, dataDir: string): { pid: number; token: string; }; export declare function getPgliteClient(url: string): Promise; export declare function closePgliteClients(): Promise; /** * Parse a JSON-serialized column value defensively. A malformed row — from a * hand-edit, dirty migration, or a misbehaving agent that wrote raw SQL — * must not break an entire list endpoint. Callers supply a fallback for the * malformed path; null/undefined values also fall back. */ export declare function safeJsonParse(value: unknown, fallback: T): T; export { retryOnDdlRace } from "./runtime-facts.js"; export declare function isUniqueViolation(e: any): boolean; export declare function isLocalDatabase(): boolean; export declare function toPostgresParams(sql: string, parameterOffsets?: readonly number[]): string; export declare function hasExplicitDbTimeout(statement: DbExecInput): boolean; export declare function postgresStatementTimeoutMs(clientTimeoutMs: number): number; export declare function dbExecQueryBudget(statement: DbExecInput): { timeoutMs: number; maxAttempts: number; }; export declare function isConnectionError(err: any): boolean; export declare function isTransientDatabaseError(err: unknown): boolean; export declare function hasRetryBudgetFor(startedAt: number): boolean; export declare function retryOnConnectionError(fn: () => Promise, maxAttempts?: number): Promise; export declare function dbOpTimeoutMs(): number; export declare function withDbTimeout(op: string, run: () => Promise, ms?: number, onTimeout?: () => void | Promise, query?: { sql: string; }): Promise; export declare function isServerlessRuntime(): boolean; export { isDeployedServerRuntime } from "./server-runtime.js"; export declare class HostedRuntimeLocalDatabaseError extends Error { readonly code = "DEPLOY_SETTINGS_REQUIRED"; constructor(source: string); } /** * The one decision behind the refusal: the database source this process must * refuse (the env key that resolved to local PGlite, or `"default"` when none * is set), or null when local PGlite is allowed. `assertHostedRuntimeDatabase()` * throws on it, and the setup page that replaces sign-in and the * `/_agent-native/ping?configuration=1` probe report it, so none of them can * disagree with the refusal. Do not give any caller its own copy of these * rules. * * The order is load-bearing: * * - `isMigrationAuthorizedRuntime()` comes first: release scripts and durable * background workers can be a real hosted invocation (a Netlify background * function still gets `NETLIFY_FUNCTION_NAME`) and may touch PGlite under * `withMigrationRuntime()`, which `assertReleaseMigrationTargetsRemoteDatabase()` * guards separately. * - A hosted function invocation refuses before `isEmbeddedRuntimeAuthorized()` * is consulted: Netlify/Vercel/Lambda/Cloudflare are never a legitimate * home for an intentionally embedded desktop app, so an embedded host that * ends up running as one hits the same per-instance failure either way. * - The embedded exemption covers only the bare Node/Docker rule below: * `createAgentNativeEmbeddedPlugin()` hosts (packaged/desktop installs) * deliberately pass a `pglite:` `databaseUrl`, and * `configureAgentNativeEmbeddedEnvironment()` claims the duty when they do. * - Bare Node/Docker has no platform marker, so it refuses when a production * server bundle is actually serving. Never gate this on `NODE_ENV`: build * steps set `NODE_ENV=production` and `node .output/server/index.mjs` runs * without it (see db/server-runtime.ts). */ export declare function getRefusedLocalDatabaseSource(): string | null; export declare function assertHostedRuntimeDatabase(): void; export declare function isSchemaMutationStatement(statement: DbExecInput): boolean; /** * Request functions must never be able to prepare or mutate schema. Throwing * here makes an unconverted ensureTable path fail loudly instead of silently * reporting success against a missing table. The release migration wrapper * is the only supported production opt-in. */ export declare function assertSchemaMutationAllowed(statement: DbExecInput): void; export declare function pgPoolOptions(url: string): Record; export declare function neonPoolOptions(): { max: number; idle_in_transaction_session_timeout?: number; }; export declare function neonPoolMax(): number; export declare function isBackgroundFunctionPoolContext(): boolean; export declare function describeDbError(err: unknown): string; export declare class DbConnectCooldownError extends Error { code: string; constructor(remainingMs: number, refusedBy: string); } export declare function guardNeonPool(pool: unknown, url: string, label?: string): void; interface ClosablePool { end(): Promise; } export declare function resolveSharedDbPool(driver: string, url: string, pool: T): T; /** * One connection pool per (driver, URL) on long-lived runtimes. Cloudflare * gets a stable facade that routes operations to a pool owned by each request. * * Opening a connection to a remote database costs a full TCP + TLS + auth * round-trip chain (~300-800ms measured against Neon in-region), and it used * to be paid once per CONSUMER: the `getDbExec` singleton, Better Auth, and one * more for every `createGetDb()` schema module (four in core alone, plus each * app's). Their `max` values also multiplied against the provider's connection * cap, which forced each pool down to a size too small to run a request's reads * concurrently. * * TRAP: only consumers that live as long as the process may share on * long-lived runtimes. Anything handed a `close()` — `createDbExec()`, the * migration exec on the direct endpoint — must keep a private pool, or closing * it takes the whole process's database access down with it. */ export declare function sharedDbPool(driver: string, url: string, create: () => T): T; export declare function replaceSharedDbPool(driver: string, url: string, previous: T, next: T): void; export declare function onSharedDbPoolReplaced(driver: string, url: string, hook: () => void): void; export declare function onSharedDbPoolsClosed(hook: () => void): void; export declare function closeSharedDbPools(): Promise; export declare function pgliteDrizzleClient(url: string, client: any): any; export declare function createDbExec(config?: DbExecConfig): Promise; export declare function annotateMissingTable(err: unknown, sql: unknown): unknown; export declare function withDbExec(exec: DbExec, run: () => T): T; export declare function getScopedDbExec(): DbExec | undefined; export declare function getScopedTransactionDbExec(): DbExec | undefined; /** * True while a `getDbExec().transaction()` callback runs. That callback leaves * `getScopedDbExec()` unset, so code that must not run inside a caller's * transaction asks this as well. */ export declare function insideDbTransactionCallback(): boolean; export declare function getDbExec(): DbExec; export declare function closeDbExec(): Promise;