import { t as MigrationOps } from "../package-CWicKzNs.mjs"; import { a as VerifyContractSpacesResult, i as VerifyContractSpacesInputs, n as SpaceMarkerRecord, o as listContractSpaceDirectories, r as SpaceVerifierViolation, s as verifyContractSpaces, t as ContractSpaceHeadRecord } from "../verify-contract-spaces-CnXNGpBV.mjs"; import { PreserveEmptyPredicate, StorageSort } from "@prisma-next/contract/hashing"; import { APP_SPACE_ID, ContractSpace, ContractSpaceHeadRef, ContractSpaceHeadRef as ContractSpaceHeadRef$1 } from "@prisma-next/framework-components/control"; import { Contract } from "@prisma-next/contract/types"; //#region src/assert-descriptor-self-consistency.d.ts /** * Inputs the helper needs to recompute the descriptor's storage hash and * compare it to the published `headRef.hash`. Kept structural so the SQL * family (and any future target family) can compose the check without * coupling to its own descriptor types. */ interface DescriptorSelfConsistencyInputs { readonly extensionId: string; readonly target: string; readonly targetFamily: string; /** * Family-specific storage object. Typed as `unknown` so callers can * pass their own narrow storage shape (e.g. `SqlStorage`) without an * inline cast — the helper canonicalises through `JSON.stringify` * inside {@link computeStorageHash} and only requires a plain * record-shaped value at runtime. */ readonly storage: unknown; readonly headRefHash: string; readonly shouldPreserveEmpty?: PreserveEmptyPredicate; readonly sortStorage?: StorageSort; } /** * Assert that an extension descriptor is self-consistent: the * `headRef.hash` it publishes must match the canonical hash recomputed * from its `contractSpace.contractJson`. * * Recomputes via {@link computeStorageHash} — the same canonical-JSON * pipeline the descriptor's own emit pipeline produced the hash with — * over `(target, targetFamily, storage)`. Mismatch indicates the * extension author bumped `contractJson` without rerunning emit, leaving * the descriptor's `headRef.hash` stale; the consumer-side helpers * (drift detection, on-disk artefact emission, runner marker writes) all * trust `headRef.hash` as the canonical identity, so a stale value would * silently corrupt every downstream boundary. * * Synchronous, pure, no I/O. Throws * `MIGRATION.DESCRIPTOR_HEAD_HASH_MISMATCH` on failure with both the * recomputed and published hashes in `details` so callers can surface a * clear remediation hint without re-deriving them. */ declare function assertDescriptorSelfConsistency(inputs: DescriptorSelfConsistencyInputs): void; //#endregion //#region src/read-contract-space-head-ref.d.ts /** * Read the head ref (`hash` + `invariants`) for a contract space from * `//refs/head.json`. * * Returns `null` when the file does not exist (first emit). Surfaces * `MIGRATION.INVALID_JSON` / `MIGRATION.INVALID_REF_FILE` on a corrupt * `refs/head.json` so callers can distinguish "no head ref on disk" * (returns `null`) from "head ref present but unreadable" (throws). * * Validates the space id against `[a-z][a-z0-9_-]{0,63}` for the same * filesystem-safety reasons as the rest of the per-space helpers. The * helper is uniform across the app and extension spaces. */ declare function readContractSpaceHeadRef(projectMigrationsDir: string, spaceId: string): Promise; //#endregion //#region src/compute-extension-space-apply-path.d.ts /** * Outcome of {@link computeExtensionSpaceApplyPath} — a discriminated union * mirroring {@link import('./migration-graph').FindPathOutcome} so callers * can map structural / invariant failures to their preferred CLI envelope * without re-running pathfinding. */ type ExtensionSpaceApplyPathOutcome = { readonly kind: 'ok'; readonly contractSpaceHeadRef: ContractSpaceHeadRef; /** * Sorted, deduplicated invariant ids covered by the walked path. * Mirrors the on-disk `providedInvariants` summed across edges and * canonicalised — what the runner stamps on the marker after apply. */ readonly providedInvariants: readonly string[]; /** * Path operations in apply order. Empty when the marker is already * at the recorded head (no-op). */ readonly pathOps: MigrationOps; /** * Migration directory names walked, in order. Mirrors `pathOps`'s * structure but at the package granularity — useful for surfacing * "applied N migration(s)" messages. */ readonly walkedMigrationDirs: readonly string[]; } | { readonly kind: 'unreachable'; readonly contractSpaceHeadRef: ContractSpaceHeadRef; } | { readonly kind: 'unsatisfiable'; readonly contractSpaceHeadRef: ContractSpaceHeadRef; readonly missing: readonly string[]; readonly structuralPath: readonly { readonly dirName: string; readonly to: string; }[]; } | { readonly kind: 'contractSpaceHeadRefMissing'; }; /** * Inputs to {@link computeExtensionSpaceApplyPath}. The helper is * deliberately framework-neutral and consumes only on-disk state: * * - `projectMigrationsDir` is the project's top-level `migrations/` dir. * - `spaceId` selects the per-space subdirectory under it. * - `currentMarkerHash` / `currentMarkerInvariants` come from the live * marker row keyed by `space = `. `null` hash = no marker yet * (the pathfinder treats this as the empty-contract sentinel per ADR * 208). */ interface ComputeExtensionSpaceApplyPathInputs { readonly projectMigrationsDir: string; readonly spaceId: string; readonly currentMarkerHash: string | null; readonly currentMarkerInvariants: readonly string[]; } /** * Compute the apply path for an extension contract space — the shortest * sequence of on-disk migration packages that walks the live marker * forward to the on-disk head ref hash, covering every required * invariant. * * Reads only on-disk artefacts (`migrations//refs/head.json` * and the per-space migration packages). **Does not import any * extension descriptor module** — `db init` / `db update` must remain * runnable without the descriptor source on disk. * * Behaviour: * - Returns `{ kind: 'ok', pathOps: [], … }` when the marker is already * at the recorded head and no required invariants are missing. * - Returns `{ kind: 'unreachable' }` when the marker hash is not * structurally connected to the recorded head in the graph. * - Returns `{ kind: 'unsatisfiable', missing, … }` when the marker is * reachable but no path covers the required invariants. * - Returns `{ kind: 'contractSpaceHeadRefMissing' }` when the per-space * `refs/head.json` is absent — the precheck verifier should already * have rejected this case, but the helper is defensive so callers can * surface a coherent error rather than throw. */ declare function computeExtensionSpaceApplyPath(inputs: ComputeExtensionSpaceApplyPathInputs): Promise; //#endregion //#region src/concatenate-space-apply-inputs.d.ts /** * Per-space input the runner consumes when applying a migration. * * The shape is target-agnostic: callers (today the SQL family; later * any other family) bind `TOp` to their own per-target operation type * (e.g. `SqlMigrationPlanOperation` for the SQL family) * and the helper preserves it through the concatenation. * * - `migrationDirectory` is the on-disk migration directory for the * space — `/migrations/` (uniform; the app * subspaces under its own `/` directory). * - `currentMarkerHash` and `currentMarkerInvariants` are the values * read from the `prisma_contract.marker` row keyed by `space = ` * (T1.1). `null` hash = no marker row yet. * - `path` is the per-space operation list resolved from * `findPathWithDecision(currentMarker, ref.hash, effectiveRequired)` * per ADR 208, materialised against the on-disk migration packages. * * @see specs/framework-mechanism.spec.md § 4 — Runner. */ interface SpaceApplyInput { readonly spaceId: string; readonly migrationDirectory: string; readonly currentMarkerHash: string | null; readonly currentMarkerInvariants: readonly string[]; readonly path: readonly TOp[]; } //#endregion //#region src/contract-space-from-json.d.ts /** * Materialise a typed {@link ContractSpace} from the JSON artefacts a * contract-space extension package emits to disk. * * Extension descriptors wire `contract.json`, per-migration * `migration.json` / `ops.json`, and `refs/head.json` to the framework's * typed surfaces. TypeScript widens JSON imports to a structural record * that does not preserve readonly modifiers or branded scalars (e.g. * `StorageHashBase<'sha256:...'>`), so authoring the descriptor inline * forces every wiring site to cast through `unknown`. This helper * encapsulates the single narrowing point: descriptor sources stay * cast-free, and the (necessary) coercion is colocated with the * documentation explaining why it is safe. * * Safety: the JSON files passed here are produced by the framework's own * emit pipeline (`prisma-next contract emit` and `MigrationCLI.run`) * and re-validated downstream by the runner / verifier. The descriptor * is a pass-through wiring layer — no descriptor consumer treats the * narrowed types as a stronger guarantee than "these came from the * canonical emit pipeline". * * The helper does not introspect or schema-validate the inputs; runtime * validation is the responsibility of `family.deserializeContract` * (codec-aware, invoked at control-stack construction) and the * per-migration `readMigrationPackage` reader used when loading * from disk. JSON-imported packages flow through the descriptor without * a disk read, so the equivalent runtime guarantee comes from the emit * pipeline that produced the JSON in the first place. */ declare function contractSpaceFromJson(inputs: { readonly contractJson: unknown; readonly migrations: ReadonlyArray<{ readonly dirName: string; readonly metadata: unknown; readonly ops: unknown; }>; readonly headRef: ContractSpaceHeadRef$1; }): ContractSpace; //#endregion //#region src/emit-contract-space-artefacts.d.ts /** * Inputs for {@link emitContractSpaceArtefacts}. * * - `contract` is the canonical contract value the framework just emitted * for the space; it is serialised through {@link canonicalizeJson}, so * it must be a JSON-compatible value (objects / arrays / primitives). * Typed as `unknown` rather than the SQL-family `Contract` * to keep `migration-tools` framework-neutral; SQL-family callers pass * their typed value through unchanged. * * - `contractDts` is the pre-rendered `.d.ts` text. Rendering happens in * the SQL family (which owns the codec / typemap input the renderer * needs), so this helper accepts the text verbatim and writes it out * without further transformation. * * - `headRef` is the head reference for the space. * `invariants` are sorted alphabetically before serialisation so two * callers passing the same set in different orders produce * byte-identical `refs/head.json`. */ interface ContractSpaceArtefactInputs { readonly contract: unknown; readonly contractDts: string; readonly headRef: ContractSpaceHeadRef; } /** * Emit the per-space artefacts (`contract.json`, `contract.d.ts`, * `refs/head.json`) under `//`. * * Always-overwrite: the framework owns these files; running `migrate` * twice with the same inputs is a no-op observably (idempotent), but the * helper does not check pre-existing contents — re-emit always wins. * * Path layout matches the convention in * [`spaceMigrationDirectory`](./space-layout.ts). The space id is * validated against `[a-z][a-z0-9_-]{0,63}` via * {@link assertValidSpaceId} for filesystem-safety reasons; the helper * accepts every space uniformly (including the app space, default * `'app'`). * * The migrations directory and space subdirectory are created if they * do not yet exist (`mkdir { recursive: true }`). */ declare function emitContractSpaceArtefacts(projectMigrationsDir: string, spaceId: string, inputs: ContractSpaceArtefactInputs): Promise; //#endregion //#region src/gather-disk-contract-space-state.d.ts /** * Disk-side inputs to {@link import('./verify-contract-spaces').verifyContractSpaces} * — gathered without touching the live database. The caller composes * this with the marker rows it reads from the runtime to invoke the * verifier. */ interface DiskContractSpaceState { /** Contract-space directory names observed under `/`. */ readonly spaceDirsOnDisk: readonly string[]; /** Head-ref `(hash, invariants)` per extension space. */ readonly headRefsBySpace: ReadonlyMap; } /** * Read the on-disk state the per-space verifier needs: * * - The list of contract-space directories under * `/` (via * {@link import('./verify-contract-spaces').listContractSpaceDirectories}). * - The on-disk head ref `(hash, invariants)` for each declared extension space * (via {@link readContractSpaceHeadRef}; missing on-disk artefacts are simply * omitted — the verifier reports them as `declaredButUnmigrated`). * * Synchronous in spirit but async due to filesystem reads. Reads only * the user's repo. **Does not import any extension descriptor module.** * * Composition convention: pure target-agnostic primitive in * `1-framework`; the SQL family (and any future target family) wires * it into its `dbInit` / `verify` flows alongside its own marker-row * read before invoking `verifyContractSpaces`. */ declare function gatherDiskContractSpaceState(args: { readonly projectMigrationsDir: string; /** * Set of space ids the project declares: `'app'` plus each entry in * `extensionPacks` whose descriptor exposes a `contractSpace`. The * helper reads on-disk head data only for the extension members. */ readonly loadedSpaceIds: ReadonlySet; }): Promise; //#endregion //#region src/plan-all-spaces.d.ts /** * Per-space input for {@link planAllSpaces}. One entry per loaded * contract space (the application's `'app'` plus each extension that * exposes a `contractSpace`). * * - `priorContract` is `null` for a space that has never been emitted * (no `migrations//contract.json` on disk yet); otherwise it * is the canonical contract value emitted for that space. * - `newContract` is the canonical contract value the planner is about * to emit for that space — for app-space, the just-emitted root * `contract.json`; for an extension space, the descriptor's * `contractSpace.contractJson`. */ interface SpacePlanInput { readonly spaceId: string; readonly priorContract: TContract | null; readonly newContract: TContract; } interface SpacePlanOutput { readonly spaceId: string; readonly migrationPackages: readonly TPackage[]; } /** * Iterate the per-space planner across a set of loaded contract spaces * and return a deterministic shape regardless of declaration order. * * Behaviour: * * - The output is sorted alphabetically by `spaceId`. Two callers * passing the same set of inputs in different orders observe * byte-identical outputs. * - The per-space planner (`planSpace`) is called exactly once per * input, in alphabetical-by-spaceId order. Its return value is * attached to the corresponding output entry verbatim. * - Duplicate `spaceId`s in the input array throw * `MIGRATION.DUPLICATE_SPACE_ID` before any `planSpace` call runs, * keeping the planner pure when the input is malformed. * * The signature is generic over `TContract` and `TPackage` because the * shape is framework-neutral (SQL family today, Mongo family * eventually). Callers wire in whatever contract value and migration * package shape their family already speaks. * * Synchronous: the underlying per-space planner (target's * `MigrationPlanner.plan(...)`) is synchronous; callers that need to * resolve async I/O (e.g. reading on-disk `contract.json` from disk) * resolve it before calling `planAllSpaces` and pass the materialised * inputs through. */ declare function planAllSpaces(inputs: readonly SpacePlanInput[], planSpace: (input: SpacePlanInput) => readonly TPackage[]): readonly SpacePlanOutput[]; //#endregion //#region src/read-contract-space-contract.d.ts /** * Read the on-disk contract value for a contract space * (`//contract.json`). Returns the parsed * JSON value as `unknown` — callers that need a typed contract validate * via their family's `deserializeContract` to surface schema issues. * * Companion to {@link import('./read-contract-space-head-ref').readContractSpaceHeadRef} * — same ENOENT-throws / corrupt-file-error semantics. Returns the * canonical-JSON value the framework wrote during emit, so re-running * this helper across machines / runs yields a byte-identical value. */ declare function readContractSpaceContract(projectMigrationsDir: string, spaceId: string): Promise; //#endregion //#region src/space-layout.d.ts /** * Branded string carrying a compile-time guarantee that the value has * been validated by {@link assertValidSpaceId}. Downstream filesystem * helpers (e.g. {@link spaceMigrationDirectory}) accept this type to * make "validated" tracking visible at the type level rather than * relying purely on a runtime check. */ type ValidSpaceId = string & { readonly __brand: 'ValidSpaceId'; }; declare function isValidSpaceId(spaceId: string): spaceId is ValidSpaceId; declare function assertValidSpaceId(spaceId: string): asserts spaceId is ValidSpaceId; /** * Resolve the migrations subdirectory for a given contract space. * * Every contract space — including the app space (default `'app'`) — * lands under `//`. The space id is * validated against {@link SPACE_ID_PATTERN} because it becomes a * filesystem directory name verbatim. * * `projectMigrationsDir` is the project's top-level `migrations/` * directory; the helper does not assume anything about its absolute / * relative shape and is symmetric with `pathe.join`. */ declare function spaceMigrationDirectory(projectMigrationsDir: string, spaceId: string): string; /** * Per-space subdirectory name reserved for the ref store * (`migrations///*.json`). Single source of * truth: every helper that composes a per-space refs path imports this * constant, and the enumerator uses it (via * {@link RESERVED_SPACE_SUBDIR_NAMES}) to exclude reserved names from * the contract-space candidate list. */ declare const SPACE_REFS_DIRNAME = "refs"; /** * Names reserved as per-space subdirectories of `migrations//`. * Used by the enumerator to filter contract-space candidates so a * reserved name (e.g. a top-level `migrations/refs/` left in the wrong * place) is never enumerated as a phantom contract space. Currently * holds `SPACE_REFS_DIRNAME`; extend if future per-space layouts add * more reserved subdirectories. */ declare const RESERVED_SPACE_SUBDIR_NAMES: ReadonlySet; /** * Resolve the per-space refs directory for `spaceMigrationsDir` * (typically the value returned by {@link spaceMigrationDirectory}). * Composes the canonical {@link SPACE_REFS_DIRNAME} so callers do not * hard-code the literal. */ declare function spaceRefsDirectory(spaceMigrationsDir: string): string; //#endregion export { APP_SPACE_ID, type ComputeExtensionSpaceApplyPathInputs, type ContractSpaceArtefactInputs, type ContractSpaceHeadRecord, type ContractSpaceHeadRef, type DescriptorSelfConsistencyInputs, type DiskContractSpaceState, type ExtensionSpaceApplyPathOutcome, RESERVED_SPACE_SUBDIR_NAMES, SPACE_REFS_DIRNAME, type SpaceApplyInput, type SpaceMarkerRecord, type SpacePlanInput, type SpacePlanOutput, type SpaceVerifierViolation, type ValidSpaceId, type VerifyContractSpacesInputs, type VerifyContractSpacesResult, assertDescriptorSelfConsistency, assertValidSpaceId, computeExtensionSpaceApplyPath, contractSpaceFromJson, emitContractSpaceArtefacts, gatherDiskContractSpaceState, isValidSpaceId, listContractSpaceDirectories, planAllSpaces, readContractSpaceContract, readContractSpaceHeadRef, spaceMigrationDirectory, spaceRefsDirectory, verifyContractSpaces }; //# sourceMappingURL=spaces.d.mts.map