import { type Logger } from "../directives/options.js"; export type ReferenceKind = "server" | "client"; /** A loaded module — exports keyed by name. */ export type ModuleExports = Record; export type ReferenceEntry = { /** Hosted id (the loader's `moduleID` output) — the manifest key. */ id: string; /** * Importer bound to the REAL module discovered at transform/build time. * Never built from the incoming client id. May return the exports * synchronously (an emitted manifest binds statically-imported namespaces) * or as a promise (`() => import(realUrl)`). */ load: () => ModuleExports | Promise; kind: ReferenceKind; /** * Optional per-export allowlist (v2). When present, only these export names * resolve for this module — an id naming any other export is rejected even if * that export is a real registered reference at runtime. This makes the * build-time enumeration the source of truth, narrowing the surface from "any * reference export of a registered module" to "exactly the references the * build saw". Omit it to allow any reference export (v1 behaviour). */ exportNames?: readonly string[]; }; export type GateMode = "open" | "sealed"; export interface ReferenceGateOptions { /** * `"sealed"` (production): an unregistered id throws. `"open"` (development): * an unregistered id falls back to `devResolve` if provided, else throws. * Defaults to `"open"`. */ mode?: GateMode; logger?: Logger; /** * Open-mode only. Resolves a hosted id that was never registered, by * importing it on demand against the live module graph. This is the dev * convenience that keeps the no-bundler workflow working before a build pass * has enumerated everything. It is NOT a security boundary: only wire it in * dev. Even then, the named export is still verified to be a real registered * reference before use. */ devResolve?: (id: string) => Promise; } export interface ReferenceGate { /** Register a reference. Throws if the gate is already sealed. */ register(entry: ReferenceEntry): void; /** Close the set: registration is rejected and unknown ids always throw. */ seal(): void; /** Resolve a `"use server"` action id to its callable reference. */ resolveServerReference(id: string): Promise; /** Resolve a `"use client"` reference id to its client-reference value. */ resolveClientReference(id: string): Promise; /** True when `id`'s module key is registered. */ has(id: string): boolean; readonly mode: GateMode; readonly sealed: boolean; readonly size: number; } /** * Build a reference gate. Populate it with {@link ReferenceGate.register} (from * a build pass or the loader's `onTransform` hook), {@link ReferenceGate.seal} * it in production, then resolve incoming ids through * {@link ReferenceGate.resolveServerReference} / * {@link ReferenceGate.resolveClientReference} instead of importing the id's * path directly. */ export declare function createReferenceGate(options?: ReferenceGateOptions): ReferenceGate; //# sourceMappingURL=gate.d.ts.map