/** * Schema routing for the core transform. * * The schema transform historically rewrote every reference to a source * schema to a single target schema (`Map`). That is the * degenerate, whole-schema case of a more general question asked at every * schema-qualified occurrence: * * given a reference to `(schema, name)` in namespace `ns`, what schema * should it live in now? * * A {@link SchemaRouter} answers exactly that. It unifies two dimensions: * * - **schema-level** default: move everything in a source schema to one target * (the classic `Map` behaviour), and * - **object-level** routes: send a specific object — a table, a function, a * type — to its own target schema, independent of its siblings. * * Object routes are bucketed by PostgreSQL namespace (`relations`, `functions`, * `types` — matching `pg_class` / `pg_proc` / `pg_type`), mirroring the routing * model already used by {@link qualifyUnqualified}. Resolution is * object-route-first, then the schema-level default, then "leave unchanged". * * An object route may also *rebind* — change the object's **name**, not just * the schema it lives in. Routing preserves identity (the same function, a new * address); rebinding repoints a reference at a *different* object, which is * what lets one implementation of a contract be substituted for another: * * ```ts * { auth: { functions: { uid: { schema: null, name: 'current_user_id' } } } } * // auth.uid() -> current_user_id() * ``` * * A `null` target schema de-qualifies the reference (relying on `search_path`), * matching the convention used by the extension router. */ /** PostgreSQL object namespaces relevant to schema routing. */ export type ObjectNamespace = 'relation' | 'function' | 'type'; /** * A namespace hint for a schema-qualified occurrence. `schema` marks an * operation on the schema itself (CREATE/DROP/GRANT ON SCHEMA, search_path); * `unknown` marks a site whose namespace cannot be determined statically, in * which case only the schema-level default applies. */ export type RouteNamespace = ObjectNamespace | 'schema' | 'unknown'; /** * Where a specific object should be reached instead. Either field may be * omitted: omitting `schema` keeps the schema-level default (or the current * schema when the route has none), and omitting `name` keeps the object's own * name — so `{ name }` alone is a pure rebind and `{ schema }` alone is * equivalent to the shorthand string form. */ export interface ObjectRoute { /** Target schema, or `null` to make the reference unqualified. */ schema?: string | null; /** Target object name — rebinds the reference to a different object. */ name?: string; } /** * An object route target. The shorthand `string` form is the target schema, * identical to `{ schema: target }`. */ export type ObjectRouteTarget = string | ObjectRoute; /** Per-source-schema routing: a schema-level default plus per-object routes. */ export interface SchemaRoute { /** * Schema-level default: every object in this source schema that has no more * specific object route moves here. Omit to route *only* the named objects * and leave the rest (and the schema itself) untouched. */ schema?: string; /** Relation name (table/view/sequence/matview) → target schema or rebind. */ relations?: Record; /** Function/procedure/aggregate name → target schema or rebind. */ functions?: Record; /** Type/domain name → target schema or rebind. */ types?: Record; } /** The full routing specification: one {@link SchemaRoute} per source schema. */ export type RouteSpec = Record; /** * Resolves the target schema for any schema-qualified occurrence, unifying the * whole-schema `Map` behaviour and per-object routing behind one `resolve`. */ export declare class SchemaRouter { private readonly routes; constructor(routes?: RouteSpec | Map); /** Build a router from the classic whole-schema `Map`. */ static fromSchemaMap(mapping: Map | Record): SchemaRouter; /** Coerce a `Map`, plain mapping, or existing router into a router. */ static from(source: SchemaRouter | Map | Record): SchemaRouter; /** True when this router might rewrite something in `sourceSchema`. */ has(sourceSchema: string | undefined | null): boolean; /** True when the router carries no routes at all. */ get size(): number; /** * True when any route targets individual objects (as opposed to whole * schemas). Object routes require AST-precise rewriting of opaque function * bodies; whole-schema routes are handled by the cheaper string passes. */ hasObjectRoutes(): boolean; /** * True when any object route changes a name or de-qualifies (rather than * only moving between schemas). Such rewrites cannot be expressed by the * string-level passes at all, so callers use this to require the AST path. */ hasNameRebinds(): boolean; /** * Every object route that rebinds a name or de-qualifies, keyed by source * schema and namespace. Callers use this to report or verify substitutions. */ nameRebinds(): Array<{ schema: string; ns: ObjectNamespace; from: string; to: ObjectRoute; }>; /** Every source schema this router may touch. */ sourceSchemas(): string[]; /** * Resolve the target schema for `(sourceSchema, name)` in namespace `ns`, * or `undefined` to leave it unchanged. Object routes win over the * schema-level default; the default applies to schema-level operations and * to any object without a specific route. */ resolve(sourceSchema: string | undefined | null, name?: string, ns?: RouteNamespace): string | undefined; /** * Resolve the full target for `(sourceSchema, name)` in namespace `ns` — both * the schema the reference should live in and, when the route rebinds, the * name it should be reached by. Returns `undefined` to leave it unchanged. * * In the result, `schema` is `null` when the reference should become * unqualified and `undefined` when only the name changes; `name` is * `undefined` when only the schema changes. */ resolveObject(sourceSchema: string | undefined | null, name?: string, ns?: RouteNamespace): ObjectRoute | undefined; /** * Source schemas whose *every* object is guaranteed to move — i.e. those * with a schema-level default. After a transform, none of these should * survive as a qualifier; partially-routed schemas may legitimately remain, * so they are excluded from the strict leftover check. */ fullyMovedSchemas(): Map; /** * A flat schema-level view (`oldSchema → newSchema`) for legacy string-level * passes and comment/verify/JSON rewrites that operate per source schema. * Only schema-level defaults are included; object-only routes carry no single * schema answer and are omitted. */ schemaLevelMap(): Map; }