@prisma-next/migration-tools 0.11.0-dev.64 → 0.11.0-dev.66

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -360,7 +360,7 @@ interface ContractMarkerRecordLike {
360
360
  //#endregion
361
361
  //#region src/aggregate/planner-types.d.ts
362
362
  /**
363
- * Caller-provided policy for {@link planAggregate}. Today this carries
363
+ * Caller-provided policy for {@link planMigration}. Today this carries
364
364
  * just one knob:
365
365
  *
366
366
  * - `ignoreGraphFor`: `Set<spaceId>`. For listed members, the planner
@@ -399,7 +399,7 @@ interface AggregateCurrentDBState {
399
399
  readonly schemaIntrospection: unknown;
400
400
  }
401
401
  /**
402
- * Inputs to {@link planAggregate}.
402
+ * Inputs to {@link planMigration}.
403
403
  *
404
404
  * The planner is target-agnostic but family-aware: per-member synth
405
405
  * delegates to the family's `createPlanner(familyInstance).plan(...)`,
@@ -408,11 +408,11 @@ interface AggregateCurrentDBState {
408
408
  * threaded through. (`frameworkComponents` is passed verbatim into
409
409
  * `planner.plan(...)` per ADR 212; the planner does not interpret it.)
410
410
  *
411
- * The aggregate planner does **not** receive a `targetId` separately —
411
+ * The planner does **not** receive a `targetId` separately —
412
412
  * it reads `aggregate.targetId` and stamps it onto every emitted
413
413
  * `MigrationPlan` from construction. No placeholder, no patch step.
414
414
  */
415
- interface AggregatePlannerInput<TFamilyId extends string, TTargetId extends string> {
415
+ interface PlannerInput<TFamilyId extends string, TTargetId extends string> {
416
416
  readonly aggregate: ContractSpaceAggregate;
417
417
  readonly currentDBState: AggregateCurrentDBState;
418
418
  readonly familyInstance: ControlFamilyInstance<TFamilyId, unknown>;
@@ -422,7 +422,7 @@ interface AggregatePlannerInput<TFamilyId extends string, TTargetId extends stri
422
422
  readonly operationPolicy: MigrationOperationPolicy;
423
423
  }
424
424
  /**
425
- * Per-member output of the aggregate planner. The runner ingests this
425
+ * Per-member output of the planner. The runner ingests this
426
426
  * shape directly via a thin `toRunnerInput` adapter at the CLI.
427
427
  *
428
428
  * - `plan`: ready-to-execute `MigrationPlan` with `targetId` already
@@ -438,8 +438,8 @@ interface AggregatePlannerInput<TFamilyId extends string, TTargetId extends stri
438
438
  /**
439
439
  * Per-edge metadata for the chain assembled by the graph-walk
440
440
  * strategy. Lets `migrate` surface a per-migration `applied[]`
441
- * entry (preserving the single-space `migrationsApplied` count
442
- * semantics) without re-walking the graph.
441
+ * entry (preserving the `migrationsApplied` count semantics) without
442
+ * re-walking the graph.
443
443
  *
444
444
  * `synth`-produced plans leave this absent — synthesised plans don't
445
445
  * have authored edges to surface.
@@ -451,7 +451,7 @@ interface AggregateMigrationEdgeRef {
451
451
  readonly to: string;
452
452
  readonly operationCount: number;
453
453
  }
454
- interface AggregatePerSpacePlan {
454
+ interface PerSpacePlan {
455
455
  readonly plan: MigrationPlan;
456
456
  readonly displayOps: readonly MigrationPlanOperation[];
457
457
  readonly destinationContract: Contract;
@@ -473,24 +473,24 @@ interface AggregatePerSpacePlan {
473
473
  */
474
474
  readonly pathDecision?: PathDecision;
475
475
  }
476
- interface AggregatePlannerSuccess {
477
- readonly perSpace: ReadonlyMap<string, AggregatePerSpacePlan>;
476
+ interface PlannerSuccess {
477
+ readonly perSpace: ReadonlyMap<string, PerSpacePlan>;
478
478
  /**
479
479
  * `applyOrder` is the order the runner must walk per-space inputs.
480
480
  * Mirrors the existing `concatenateSpaceApplyInputs` convention:
481
481
  * extensions alphabetically by `spaceId`, then the app. Tests assert
482
- * on `MultiSpaceRunnerFailure.failingSpace`, which is positional in
482
+ * on `MigrationRunnerFailure.failingSpace`, which is positional in
483
483
  * the runner's input array — preserving the literal ordering keeps
484
484
  * `failingSpace` attribution byte-for-byte.
485
485
  */
486
486
  readonly applyOrder: readonly string[];
487
487
  }
488
488
  /**
489
- * Discriminated failure variants for {@link planAggregate}. Each
489
+ * Discriminated failure variants for {@link planMigration}. Each
490
490
  * variant short-circuits the plan; per-member errors carry the
491
491
  * `spaceId` so the CLI can surface a precise envelope.
492
492
  */
493
- type AggregatePlannerError = {
493
+ type PlannerError = {
494
494
  readonly kind: 'extensionPathUnreachable';
495
495
  readonly spaceId: string;
496
496
  readonly target: string;
@@ -507,7 +507,7 @@ type AggregatePlannerError = {
507
507
  readonly spaceId: string;
508
508
  readonly detail: string;
509
509
  };
510
- type AggregatePlannerOutput = Result<AggregatePlannerSuccess, AggregatePlannerError>;
510
+ type PlannerOutput = Result<PlannerSuccess, PlannerError>;
511
511
  //#endregion
512
512
  //#region src/aggregate/planner.d.ts
513
513
  /**
@@ -527,12 +527,12 @@ type AggregatePlannerOutput = Result<AggregatePlannerSuccess, AggregatePlannerEr
527
527
  * Output `applyOrder` is `[...aggregate.extensions.map(spaceId), aggregate.app.spaceId]`
528
528
  * — extensions alphabetical, then app — matching today's
529
529
  * `concatenateSpaceApplyInputs` ordering. This preserves
530
- * `MultiSpaceRunnerFailure.failingSpace` attribution byte-for-byte.
530
+ * `MigrationRunnerFailure.failingSpace` attribution byte-for-byte.
531
531
  *
532
532
  * Every emitted `MigrationPlan` has `targetId = aggregate.targetId`.
533
533
  * No placeholder cast; no patch step.
534
534
  */
535
- declare function planAggregate<TFamilyId extends string, TTargetId extends string>(input: AggregatePlannerInput<TFamilyId, TTargetId>): Promise<AggregatePlannerOutput>;
535
+ declare function planMigration<TFamilyId extends string, TTargetId extends string>(input: PlannerInput<TFamilyId, TTargetId>): Promise<PlannerOutput>;
536
536
  //#endregion
537
537
  //#region src/aggregate/project-schema-to-space.d.ts
538
538
  /**
@@ -597,12 +597,12 @@ declare function projectSchemaToSpace(schema: unknown, member: ContractSpaceMemb
597
597
  * {@link import('../../compute-extension-space-apply-path').ExtensionSpaceApplyPathOutcome}
598
598
  * but operates against the member's lazily-reconstructed `graph()`
599
599
  * instead of re-reading from disk. The aggregate planner converts
600
- * these into {@link import('../planner-types').AggregatePlannerError}
600
+ * these into {@link import('../planner-types').PlannerError}
601
601
  * variants.
602
602
  */
603
603
  type GraphWalkOutcome = {
604
604
  readonly kind: 'ok';
605
- readonly result: AggregatePerSpacePlan;
605
+ readonly result: PerSpacePlan;
606
606
  } | {
607
607
  readonly kind: 'unreachable';
608
608
  } | {
@@ -640,12 +640,12 @@ declare function graphWalkStrategy(input: GraphWalkStrategyInputs): GraphWalkOut
640
640
  //#endregion
641
641
  //#region src/aggregate/verifier.d.ts
642
642
  /**
643
- * Caller policy for the aggregate verifier. Today's only knob is
643
+ * Caller policy for the verifier. Today's only knob is
644
644
  * `mode`: `strict` treats orphan elements (live tables not claimed by
645
645
  * any aggregate member) as errors; `lenient` treats them as
646
646
  * informational. Maps directly to `db verify --strict`.
647
647
  */
648
- interface AggregateVerifierInput<TSchemaResult> {
648
+ interface VerifierInput<TSchemaResult> {
649
649
  readonly aggregate: ContractSpaceAggregate;
650
650
  readonly markersBySpaceId: ReadonlyMap<string, ContractMarkerRecordLike | null>;
651
651
  readonly schemaIntrospection: unknown;
@@ -653,7 +653,7 @@ interface AggregateVerifierInput<TSchemaResult> {
653
653
  /**
654
654
  * Caller-supplied per-space schema verifier. The CLI wires this to
655
655
  * the family's `verifySqlSchema` (SQL) / equivalent (other
656
- * families). The aggregate verifier projects the schema to the
656
+ * families). The verifier projects the schema to the
657
657
  * member's slice via {@link projectSchemaToSpace} before invoking
658
658
  * the callback, so single-contract semantics are preserved.
659
659
  *
@@ -691,7 +691,7 @@ interface MarkerCheckSection {
691
691
  }
692
692
  /**
693
693
  * A live storage element (today: a top-level table) not claimed by any
694
- * member of the aggregate. The aggregate verifier always reports these;
694
+ * member of the aggregate. The verifier always reports these;
695
695
  * the caller decides what to do — `db verify --strict` treats them as
696
696
  * errors, the lenient default treats them as informational.
697
697
  *
@@ -711,15 +711,15 @@ interface SchemaCheckSection<TSchemaResult> {
711
711
  */
712
712
  readonly orphanElements: readonly OrphanElement[];
713
713
  }
714
- interface AggregateVerifierSuccess<TSchemaResult> {
714
+ interface VerifierSuccess<TSchemaResult> {
715
715
  readonly markerCheck: MarkerCheckSection;
716
716
  readonly schemaCheck: SchemaCheckSection<TSchemaResult>;
717
717
  }
718
- type AggregateVerifierError = {
718
+ type VerifierError = {
719
719
  readonly kind: 'introspectionFailure';
720
720
  readonly detail: string;
721
721
  };
722
- type AggregateVerifierOutput<TSchemaResult> = Result<AggregateVerifierSuccess<TSchemaResult>, AggregateVerifierError>;
722
+ type VerifierOutput<TSchemaResult> = Result<VerifierSuccess<TSchemaResult>, VerifierError>;
723
723
  /**
724
724
  * Verify a {@link ContractSpaceAggregate} against the live database
725
725
  * state. Bundles two checks:
@@ -742,7 +742,7 @@ type AggregateVerifierOutput<TSchemaResult> = Result<AggregateVerifierSuccess<TS
742
742
  * Pure synchronous function; no I/O. The caller (CLI) gathers
743
743
  * `markersBySpaceId` and `schemaIntrospection` ahead of the call.
744
744
  */
745
- declare function verifyAggregate<TSchemaResult>(input: AggregateVerifierInput<TSchemaResult>): AggregateVerifierOutput<TSchemaResult>;
745
+ declare function verifyMigration<TSchemaResult>(input: VerifierInput<TSchemaResult>): VerifierOutput<TSchemaResult>;
746
746
  //#endregion
747
- export { type AggregateCurrentDBState, type AggregateMigrationEdgeRef, type AggregatePerSpacePlan, type AggregatePlannerError, type AggregatePlannerInput, type AggregatePlannerOutput, type AggregatePlannerSuccess, type AggregateVerifierError, type AggregateVerifierInput, type AggregateVerifierOutput, type AggregateVerifierSuccess, type CallerPolicy, type ContractAtOptions, type ContractAtResult, type ContractMarkerRecordLike, type ContractSpaceAggregate, type ContractSpaceMember, type DeclaredExtensionEntry, type GraphWalkOutcome, type GraphWalkStrategyInputs, type IntegrityComputationInput, type IntegrityQueryOptions, type IntegritySpaceState, type IntegrityViolation, type LoadAggregateInput, type MarkerCheckResult, type MarkerCheckSection, type OrphanElement, type SchemaCheckSection, computeIntegrityViolations, createContractSpaceAggregate, createContractSpaceMember, graphWalkStrategy, loadContractSpaceAggregate, loadProblemToViolation, planAggregate, projectSchemaToSpace, requireHeadRef, verifyAggregate };
747
+ export { type AggregateCurrentDBState, type AggregateMigrationEdgeRef, type CallerPolicy, type ContractAtOptions, type ContractAtResult, type ContractMarkerRecordLike, type ContractSpaceAggregate, type ContractSpaceMember, type DeclaredExtensionEntry, type GraphWalkOutcome, type GraphWalkStrategyInputs, type IntegrityComputationInput, type IntegrityQueryOptions, type IntegritySpaceState, type IntegrityViolation, type LoadAggregateInput, type MarkerCheckResult, type MarkerCheckSection, type OrphanElement, type PerSpacePlan, type PlannerError, type PlannerInput, type PlannerOutput, type PlannerSuccess, type SchemaCheckSection, type VerifierError, type VerifierInput, type VerifierOutput, type VerifierSuccess, computeIntegrityViolations, createContractSpaceAggregate, createContractSpaceMember, graphWalkStrategy, loadContractSpaceAggregate, loadProblemToViolation, planMigration, projectSchemaToSpace, requireHeadRef, verifyMigration };
748
748
  //# sourceMappingURL=aggregate.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"aggregate.d.mts","names":[],"sources":["../../src/integrity-violation.ts","../../src/aggregate/types.ts","../../src/aggregate/aggregate.ts","../../src/aggregate/check-integrity.ts","../../src/aggregate/loader.ts","../../src/aggregate/marker-types.ts","../../src/aggregate/planner-types.ts","../../src/aggregate/planner.ts","../../src/aggregate/project-schema-to-space.ts","../../src/aggregate/strategies/graph-walk.ts","../../src/aggregate/verifier.ts"],"mappings":"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"}
1
+ {"version":3,"file":"aggregate.d.mts","names":[],"sources":["../../src/integrity-violation.ts","../../src/aggregate/types.ts","../../src/aggregate/aggregate.ts","../../src/aggregate/check-integrity.ts","../../src/aggregate/loader.ts","../../src/aggregate/marker-types.ts","../../src/aggregate/planner-types.ts","../../src/aggregate/planner.ts","../../src/aggregate/project-schema-to-space.ts","../../src/aggregate/strategies/graph-walk.ts","../../src/aggregate/verifier.ts"],"mappings":"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"}
@@ -732,12 +732,12 @@ async function synthStrategy(input) {
732
732
  * Output `applyOrder` is `[...aggregate.extensions.map(spaceId), aggregate.app.spaceId]`
733
733
  * — extensions alphabetical, then app — matching today's
734
734
  * `concatenateSpaceApplyInputs` ordering. This preserves
735
- * `MultiSpaceRunnerFailure.failingSpace` attribution byte-for-byte.
735
+ * `MigrationRunnerFailure.failingSpace` attribution byte-for-byte.
736
736
  *
737
737
  * Every emitted `MigrationPlan` has `targetId = aggregate.targetId`.
738
738
  * No placeholder cast; no patch step.
739
739
  */
740
- async function planAggregate(input) {
740
+ async function planMigration(input) {
741
741
  const { aggregate, currentDBState, callerPolicy } = input;
742
742
  const allMembers = [aggregate.app, ...aggregate.extensions];
743
743
  const perSpace = /* @__PURE__ */ new Map();
@@ -844,9 +844,9 @@ async function planAggregate(input) {
844
844
  * Pure synchronous function; no I/O. The caller (CLI) gathers
845
845
  * `markersBySpaceId` and `schemaIntrospection` ahead of the call.
846
846
  */
847
- function verifyAggregate(input) {
847
+ function verifyMigration(input) {
848
848
  try {
849
- return runVerifyAggregate(input);
849
+ return runVerifyMigration(input);
850
850
  } catch (error) {
851
851
  return notOk({
852
852
  kind: "introspectionFailure",
@@ -854,7 +854,7 @@ function verifyAggregate(input) {
854
854
  });
855
855
  }
856
856
  }
857
- function runVerifyAggregate(input) {
857
+ function runVerifyMigration(input) {
858
858
  const { aggregate, markersBySpaceId, schemaIntrospection, mode, verifySchemaForMember } = input;
859
859
  const allMembers = [aggregate.app, ...aggregate.extensions];
860
860
  const memberSpaceIds = new Set(allMembers.map((m) => m.spaceId));
@@ -931,6 +931,6 @@ function detectOrphanElements(schemaIntrospection, members) {
931
931
  return orphans;
932
932
  }
933
933
  //#endregion
934
- export { computeIntegrityViolations, createContractSpaceAggregate, createContractSpaceMember, graphWalkStrategy, loadContractSpaceAggregate, loadProblemToViolation, planAggregate, projectSchemaToSpace, requireHeadRef, verifyAggregate };
934
+ export { computeIntegrityViolations, createContractSpaceAggregate, createContractSpaceMember, graphWalkStrategy, loadContractSpaceAggregate, loadProblemToViolation, planMigration, projectSchemaToSpace, requireHeadRef, verifyMigration };
935
935
 
936
936
  //# sourceMappingURL=aggregate.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"aggregate.mjs","names":["detailOf"],"sources":["../../src/aggregate/aggregate.ts","../../src/aggregate/check-integrity.ts","../../src/aggregate/loader.ts","../../src/aggregate/strategies/graph-walk.ts","../../src/aggregate/project-schema-to-space.ts","../../src/aggregate/strategies/synth.ts","../../src/aggregate/planner.ts","../../src/aggregate/verifier.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport type { Contract } from '@prisma-next/contract/types';\nimport { join } from 'pathe';\nimport {\n errorBundleNotFoundForGraphNode,\n errorContractDeserializationFailed,\n errorHashNotInGraph,\n errorInvalidJson,\n errorMissingFile,\n errorSnapshotMissing,\n MigrationToolsError,\n} from '../errors';\nimport type { MigrationGraph } from '../graph';\nimport { isGraphNode } from '../graph-membership';\nimport type { IntegrityQueryOptions, IntegrityViolation } from '../integrity-violation';\nimport { reconstructGraph } from '../migration-graph';\nimport type { OnDiskMigrationPackage } from '../package';\nimport type { Refs } from '../refs';\nimport { readRefSnapshot } from '../refs/snapshot';\nimport type { ContractSpaceHeadRecord } from '../verify-contract-spaces';\nimport type {\n ContractAtOptions,\n ContractAtResult,\n ContractSpaceAggregate,\n ContractSpaceMember,\n} from './types';\n\nfunction hasErrnoCode(error: unknown, code: string): boolean {\n return error instanceof Error && (error as { code?: string }).code === code;\n}\n\nfunction contractAtMemoKey(hash: string, refName: string | undefined): string {\n return `${hash}\\0${refName ?? ''}`;\n}\n\nfunction deserializeContractAtPath(\n filePath: string,\n contractJson: unknown,\n deserializeContract: (raw: unknown) => Contract,\n): Contract {\n try {\n return deserializeContract(contractJson);\n } catch (error) {\n if (MigrationToolsError.is(error)) {\n throw error;\n }\n const message = error instanceof Error ? error.message : String(error);\n throw errorContractDeserializationFailed(filePath, message);\n }\n}\n\nasync function readGraphNodeEndContract(\n packageDir: string,\n deserializeContract: (raw: unknown) => Contract,\n): Promise<{ contractJson: unknown; contractDts: string; contract: Contract }> {\n const jsonPath = join(packageDir, 'end-contract.json');\n const dtsPath = join(packageDir, 'end-contract.d.ts');\n\n let rawJson: string;\n try {\n rawJson = await readFile(jsonPath, 'utf-8');\n } catch (error) {\n if (hasErrnoCode(error, 'ENOENT')) {\n throw errorMissingFile('end-contract.json', packageDir);\n }\n throw error;\n }\n\n let contractJson: unknown;\n try {\n contractJson = JSON.parse(rawJson);\n } catch (error) {\n throw errorInvalidJson(jsonPath, error instanceof Error ? error.message : String(error));\n }\n\n let contractDts: string;\n try {\n contractDts = await readFile(dtsPath, 'utf-8');\n } catch (error) {\n if (hasErrnoCode(error, 'ENOENT')) {\n throw errorMissingFile('end-contract.d.ts', packageDir);\n }\n throw error;\n }\n\n const contract = deserializeContractAtPath(jsonPath, contractJson, deserializeContract);\n return { contractJson, contractDts, contract };\n}\n\nasync function resolveContractAt(args: {\n readonly hash: string;\n readonly opts: ContractAtOptions | undefined;\n readonly refsDir: string;\n readonly packages: readonly OnDiskMigrationPackage[];\n readonly graph: MigrationGraph;\n readonly deserializeContract: (raw: unknown) => Contract;\n}): Promise<ContractAtResult> {\n const { hash, opts, refsDir, packages, graph, deserializeContract } = args;\n const refName = opts?.refName;\n\n if (refName !== undefined) {\n const snapshot = await readRefSnapshot(refsDir, refName);\n if (snapshot) {\n const jsonPath = join(refsDir, `${refName}.contract.json`);\n return {\n hash,\n contractJson: snapshot.contract,\n contractDts: snapshot.contractDts,\n contract: deserializeContractAtPath(jsonPath, snapshot.contract, deserializeContract),\n provenance: 'snapshot',\n };\n }\n\n if (isGraphNode(hash, graph)) {\n return resolveGraphNodeContractAt({\n hash,\n packages,\n deserializeContract,\n explicitLabel: refName,\n });\n }\n\n throw errorSnapshotMissing(refName);\n }\n\n if (isGraphNode(hash, graph)) {\n return resolveGraphNodeContractAt({ hash, packages, deserializeContract });\n }\n\n throw errorHashNotInGraph(hash, graph);\n}\n\nasync function resolveGraphNodeContractAt(args: {\n readonly hash: string;\n readonly packages: readonly OnDiskMigrationPackage[];\n readonly deserializeContract: (raw: unknown) => Contract;\n readonly explicitLabel?: string;\n}): Promise<ContractAtResult> {\n const { hash, packages, deserializeContract, explicitLabel } = args;\n const matchingBundle = packages.find((pkg) => pkg.metadata.to === hash);\n if (!matchingBundle) {\n throw errorBundleNotFoundForGraphNode(hash, explicitLabel);\n }\n\n const { contractJson, contractDts, contract } = await readGraphNodeEndContract(\n matchingBundle.dirPath,\n deserializeContract,\n );\n return {\n hash,\n contractJson,\n contractDts,\n contract,\n provenance: 'graph-node',\n sourceDir: matchingBundle.dirPath,\n };\n}\n\n/**\n * Resolve a member's head ref, asserting it is present. The apply/verify\n * engine only runs after `checkIntegrity` has refused on `headRefMissing`,\n * so a member reaching the planner / verifier without a head ref is a\n * programming error (the integrity gate was skipped), not a user-facing\n * state. The app member's head ref is always synthesised, so this only\n * ever guards an ungated extension space.\n */\nexport function requireHeadRef(member: ContractSpaceMember): ContractSpaceHeadRecord {\n if (member.headRef === null) {\n throw new Error(\n `Contract space \"${member.spaceId}\" has no head ref; the integrity gate must refuse a missing head ref before planning or verifying.`,\n );\n }\n return member.headRef;\n}\n\n/**\n * Build a {@link ContractSpaceMember} with lazily-memoised `graph()`,\n * `contract()`, and `contractAt()` facets.\n *\n * `graph()` reconstructs the migration graph from `packages` on first\n * call and caches it. `contract()` calls `resolveContract` on first call\n * and caches the result; a throwing `resolveContract` (e.g. a missing or\n * undeserializable on-disk contract) re-throws on each call rather than\n * caching a value — `checkIntegrity` surfaces that as `contractUnreadable`.\n * `contractAt()` materializes the contract at an arbitrary graph node with\n * the same resolution order as plan-time ref resolution: ref snapshot first\n * (when `opts.refName` is set), else the matching package's `end-contract.*`.\n */\nexport function createContractSpaceMember(args: {\n readonly spaceId: string;\n readonly packages: readonly OnDiskMigrationPackage[];\n readonly refs: Refs;\n readonly headRef: ContractSpaceHeadRecord | null;\n readonly refsDir: string;\n readonly resolveContract: () => Contract;\n readonly deserializeContract: (raw: unknown) => Contract;\n}): ContractSpaceMember {\n const { spaceId, packages, refs, headRef, refsDir, resolveContract, deserializeContract } = args;\n let graphMemo: MigrationGraph | undefined;\n let contractMemo: Contract | undefined;\n const contractAtMemo = new Map<string, ContractAtResult>();\n\n function memberGraph(): MigrationGraph {\n graphMemo ??= reconstructGraph(packages);\n return graphMemo;\n }\n\n return {\n spaceId,\n packages,\n refs,\n headRef,\n graph: memberGraph,\n contract() {\n contractMemo ??= resolveContract();\n return contractMemo;\n },\n async contractAt(hash, opts) {\n const key = contractAtMemoKey(hash, opts?.refName);\n const cached = contractAtMemo.get(key);\n if (cached) {\n return cached;\n }\n\n const result = await resolveContractAt({\n hash,\n opts,\n refsDir,\n packages,\n graph: memberGraph(),\n deserializeContract,\n });\n contractAtMemo.set(key, result);\n return result;\n },\n };\n}\n\n/**\n * Assemble a {@link ContractSpaceAggregate} value from its members and a\n * `checkIntegrity` implementation. The query methods (`listSpaces` /\n * `hasSpace` / `space` / `spaces`) are derived here so every aggregate —\n * loader-built or test-built — shares one query surface: `app` first,\n * then `extensions` in the order supplied (the loader sorts them\n * lex-ascending by `spaceId`).\n */\nexport function createContractSpaceAggregate(args: {\n readonly targetId: string;\n readonly app: ContractSpaceMember;\n readonly extensions: readonly ContractSpaceMember[];\n readonly checkIntegrity: (opts?: IntegrityQueryOptions) => readonly IntegrityViolation[];\n}): ContractSpaceAggregate {\n const { targetId, app, extensions, checkIntegrity } = args;\n const ordered: readonly ContractSpaceMember[] = [app, ...extensions];\n const byId = new Map(ordered.map((m) => [m.spaceId, m]));\n return {\n targetId,\n app,\n extensions,\n listSpaces: () => ordered.map((m) => m.spaceId),\n hasSpace: (id) => byId.has(id),\n space: (id) => byId.get(id),\n spaces: () => ordered,\n checkIntegrity,\n };\n}\n","import { elementCoordinates } from '@prisma-next/framework-components/ir';\nimport { EMPTY_CONTRACT_HASH } from '../constants';\nimport { MigrationToolsError } from '../errors';\nimport type {\n DeclaredExtensionEntry,\n IntegrityQueryOptions,\n IntegrityViolation,\n} from '../integrity-violation';\nimport type { PackageLoadProblem } from '../io';\nimport type { OnDiskMigrationPackage } from '../package';\nimport type { RefLoadProblem } from '../refs';\nimport type { ContractSpaceMember } from './types';\n\n/**\n * One space's load-time facts that `checkIntegrity` judges: the loaded\n * member, the load-time problems `readMigrationsDir` surfaced for it, and\n * whether it is the app space (the app head ref is synthesised, so the\n * head-ref checks are skipped for it).\n */\nexport interface IntegritySpaceState {\n readonly member: ContractSpaceMember;\n readonly problems: readonly PackageLoadProblem[];\n /** Per-ref problems: a user ref `*.json` that exists but is unparseable. */\n readonly refProblems: readonly RefLoadProblem[];\n /**\n * The space's `refs/head.json` problem when it exists but is unparseable.\n * `null` means the head ref was read cleanly or is genuinely absent —\n * the absent case is judged `headRefMissing`, the corrupt case here is\n * judged `refUnreadable` (and suppresses `headRefMissing`).\n */\n readonly headRefProblem: RefLoadProblem | null;\n readonly isApp: boolean;\n}\n\nexport interface IntegrityComputationInput {\n readonly targetId: string;\n readonly spaces: readonly IntegritySpaceState[];\n}\n\n/**\n * Walk the loaded model and return **every** integrity violation — never\n * bailing at the first. Structurally-derivable violations (load-time\n * problems, self-edges, missing / unreachable head refs) are always\n * produced; layout-drift checks require `declaredExtensions`, and\n * contract / target / disjointness checks require `checkContracts`.\n */\nexport function computeIntegrityViolations(\n input: IntegrityComputationInput,\n opts?: IntegrityQueryOptions,\n): readonly IntegrityViolation[] {\n const violations: IntegrityViolation[] = [];\n\n for (const { member, problems, refProblems, headRefProblem, isApp } of input.spaces) {\n const { spaceId } = member;\n\n for (const problem of problems) {\n violations.push(loadProblemToViolation(spaceId, problem));\n }\n\n for (const refProblem of refProblems) {\n violations.push({\n kind: 'refUnreadable',\n spaceId,\n refName: refProblem.refName,\n detail: refProblem.detail,\n });\n }\n if (headRefProblem !== null) {\n violations.push({\n kind: 'refUnreadable',\n spaceId,\n refName: headRefProblem.refName,\n detail: headRefProblem.detail,\n });\n }\n\n for (const pkg of member.packages) {\n const from = pkg.metadata.from ?? EMPTY_CONTRACT_HASH;\n const isSelfEdge = from === pkg.metadata.to;\n const hasDataOp = pkg.ops.some((op) => op.operationClass === 'data');\n if (isSelfEdge && !hasDataOp) {\n violations.push({ kind: 'sameSourceAndTarget', spaceId, dirName: pkg.dirName, hash: from });\n }\n }\n\n violations.push(...duplicateMigrationHashViolations(spaceId, member.packages));\n\n // The app head ref is synthesised from the live contract, so it is\n // always present and reachable; only extension spaces read their head\n // ref from disk and can be missing or point outside the graph. A head\n // ref that exists but is unparseable is already surfaced above as\n // `refUnreadable`, so it is not also reported as `headRefMissing`.\n if (!isApp && headRefProblem === null) {\n if (member.headRef === null) {\n violations.push({ kind: 'headRefMissing', spaceId });\n } else if (!headRefPresentInGraph(member, member.headRef.hash)) {\n violations.push({ kind: 'headRefNotInGraph', spaceId, hash: member.headRef.hash });\n }\n }\n }\n\n if (opts?.declaredExtensions !== undefined) {\n violations.push(...layoutViolations(input.spaces, opts.declaredExtensions));\n }\n\n if (opts?.checkContracts === true) {\n violations.push(...contractViolations(input));\n }\n\n return violations;\n}\n\nexport function loadProblemToViolation(\n spaceId: string,\n problem: PackageLoadProblem,\n): IntegrityViolation {\n switch (problem.kind) {\n case 'hashMismatch':\n return {\n kind: 'hashMismatch',\n spaceId,\n dirName: problem.dirName,\n stored: problem.stored,\n computed: problem.computed,\n };\n case 'providedInvariantsMismatch':\n return { kind: 'providedInvariantsMismatch', spaceId, dirName: problem.dirName };\n case 'packageUnloadable':\n return {\n kind: 'packageUnloadable',\n spaceId,\n dirName: problem.dirName,\n detail: problem.detail,\n };\n }\n}\n\nfunction duplicateMigrationHashViolations(\n spaceId: string,\n packages: readonly OnDiskMigrationPackage[],\n): readonly IntegrityViolation[] {\n const dirNamesByHash = new Map<string, string[]>();\n for (const pkg of packages) {\n const hash = pkg.metadata.migrationHash;\n const dirNames = dirNamesByHash.get(hash);\n if (dirNames) dirNames.push(pkg.dirName);\n else dirNamesByHash.set(hash, [pkg.dirName]);\n }\n\n const out: IntegrityViolation[] = [];\n for (const [migrationHash, dirNames] of dirNamesByHash) {\n if (dirNames.length > 1) {\n out.push({\n kind: 'duplicateMigrationHash',\n spaceId,\n migrationHash,\n dirNames: [...dirNames].sort(),\n });\n }\n }\n return out;\n}\n\n/**\n * Whether a space's head-ref hash is present in its reconstructed graph.\n * An empty graph is reachable only by the empty-contract sentinel.\n */\nfunction headRefPresentInGraph(member: ContractSpaceMember, headHash: string): boolean {\n const graph = member.graph();\n if (graph.nodes.size === 0) {\n return headHash === EMPTY_CONTRACT_HASH;\n }\n return graph.nodes.has(headHash);\n}\n\nfunction layoutViolations(\n spaces: readonly IntegritySpaceState[],\n declaredExtensions: readonly DeclaredExtensionEntry[],\n): readonly IntegrityViolation[] {\n const out: IntegrityViolation[] = [];\n const extensionSpaceIds = new Set(spaces.filter((s) => !s.isApp).map((s) => s.member.spaceId));\n const declaredIds = new Set(declaredExtensions.map((d) => d.id));\n\n for (const id of [...extensionSpaceIds].sort()) {\n if (!declaredIds.has(id)) {\n out.push({ kind: 'orphanSpaceDir', spaceId: id });\n }\n }\n for (const id of [...declaredIds].sort()) {\n if (!extensionSpaceIds.has(id)) {\n out.push({ kind: 'declaredButUnmigrated', spaceId: id });\n }\n }\n return out;\n}\n\nfunction contractViolations(input: IntegrityComputationInput): readonly IntegrityViolation[] {\n const out: IntegrityViolation[] = [];\n const elementClaimedBy = new Map<string, string[]>();\n\n for (const { member } of input.spaces) {\n let contract: ReturnType<ContractSpaceMember['contract']>;\n try {\n contract = member.contract();\n } catch (error) {\n out.push({ kind: 'contractUnreadable', spaceId: member.spaceId, detail: detailOf(error) });\n continue;\n }\n\n if (contract.target !== input.targetId) {\n out.push({\n kind: 'targetMismatch',\n spaceId: member.spaceId,\n expected: input.targetId,\n actual: contract.target,\n });\n }\n\n for (const { entityName: elementName } of elementCoordinates(contract.storage)) {\n const claimers = elementClaimedBy.get(elementName);\n if (claimers) claimers.push(member.spaceId);\n else elementClaimedBy.set(elementName, [member.spaceId]);\n }\n }\n\n const disjointness: IntegrityViolation[] = [];\n for (const [element, claimedBy] of elementClaimedBy) {\n if (claimedBy.length > 1) {\n disjointness.push({ kind: 'disjointness', element, claimedBy: [...claimedBy].sort() });\n }\n }\n disjointness.sort((a, b) =>\n a.kind === 'disjointness' && b.kind === 'disjointness' ? a.element.localeCompare(b.element) : 0,\n );\n out.push(...disjointness);\n return out;\n}\n\nfunction detailOf(error: unknown): string {\n if (MigrationToolsError.is(error)) return error.why;\n if (error instanceof Error) return error.message;\n return String(error);\n}\n","import type { Contract } from '@prisma-next/contract/types';\nimport { MigrationToolsError } from '../errors';\nimport { readMigrationsDir } from '../io';\nimport { readContractSpaceContract } from '../read-contract-space-contract';\nimport { readContractSpaceHeadRef } from '../read-contract-space-head-ref';\nimport { HEAD_REF_NAME, type RefLoadProblem, readRefsTolerant } from '../refs';\nimport {\n APP_SPACE_ID,\n isValidSpaceId,\n RESERVED_SPACE_SUBDIR_NAMES,\n spaceMigrationDirectory,\n spaceRefsDirectory,\n} from '../space-layout';\nimport { listContractSpaceDirectories } from '../verify-contract-spaces';\nimport { createContractSpaceAggregate, createContractSpaceMember } from './aggregate';\nimport { computeIntegrityViolations, type IntegritySpaceState } from './check-integrity';\nimport type { ContractSpaceAggregate } from './types';\n\nexport type { DeclaredExtensionEntry } from '../integrity-violation';\n\n/**\n * Inputs for {@link loadContractSpaceAggregate}.\n *\n * Construction reads migration **state** from disk (`migrations/<space>/`\n * packages + refs + head refs). The app's *live* contract is not a disk\n * artefact — in Prisma Next it is always compiled from the project's\n * central contract, so the caller always has it and threads it in as\n * `appContract`. `deserializeContract` is held and called lazily only for\n * the on-disk extension contracts (`migrations/<ext>/contract.json`).\n */\nexport interface LoadAggregateInput {\n readonly migrationsDir: string;\n readonly deserializeContract: (raw: unknown) => Contract;\n readonly appContract: Contract;\n}\n\n/**\n * Build a tolerant, queryable {@link ContractSpaceAggregate} from on-disk\n * migration state plus the caller's live app contract.\n *\n * Building **never throws on disk content**: a hash- or\n * invariants-mismatched package is retained, an unparseable package is\n * omitted, a missing extension head ref leaves `headRef: null`, and an\n * unreadable on-disk contract defers its failure to `member.contract()`.\n * Every such problem is judged by {@link ContractSpaceAggregate.checkIntegrity}\n * rather than aborting the load. The only rejections are catastrophic I/O\n * (a `migrations/` that exists but is unreadable for reasons other than\n * absence).\n *\n * The app space's head ref is synthesised from the live contract's\n * storage hash (the app contract is authored independently of the\n * migration graph), and `app.contract()` returns the supplied contract.\n * Extension spaces read their contract, refs, and head ref from disk.\n */\nexport async function loadContractSpaceAggregate(\n input: LoadAggregateInput,\n): Promise<ContractSpaceAggregate> {\n const { migrationsDir, deserializeContract, appContract } = input;\n const targetId = appContract.target;\n\n const appState = await loadAppSpace(migrationsDir, appContract, deserializeContract);\n const extensionStates = await loadExtensionSpaces(migrationsDir, deserializeContract);\n\n const spaces: readonly IntegritySpaceState[] = [appState, ...extensionStates];\n\n return createContractSpaceAggregate({\n targetId,\n app: appState.member,\n extensions: extensionStates.map((state) => state.member),\n checkIntegrity: (opts) => computeIntegrityViolations({ targetId, spaces }, opts),\n });\n}\n\nasync function loadAppSpace(\n migrationsDir: string,\n appContract: Contract,\n deserializeContract: (raw: unknown) => Contract,\n): Promise<IntegritySpaceState> {\n const spaceDir = spaceMigrationDirectory(migrationsDir, APP_SPACE_ID);\n const { packages, problems } = await readMigrationsDir(spaceDir);\n const { refs, problems: refProblems } = await readRefsTolerant(spaceRefsDirectory(spaceDir));\n\n const member = createContractSpaceMember({\n spaceId: APP_SPACE_ID,\n packages,\n refs,\n headRef: { hash: appContract.storage.storageHash, invariants: [] },\n refsDir: spaceRefsDirectory(spaceDir),\n resolveContract: () => appContract,\n deserializeContract,\n });\n\n // The app head ref is synthesised from the live contract, so there is\n // no on-disk head.json to be missing or corrupt for it.\n return { member, problems, refProblems, headRefProblem: null, isApp: true };\n}\n\nasync function loadExtensionSpaces(\n migrationsDir: string,\n deserializeContract: (raw: unknown) => Contract,\n): Promise<readonly IntegritySpaceState[]> {\n const candidateDirs = await listContractSpaceDirectories(migrationsDir);\n const extensionIds = candidateDirs\n .filter((name) => name !== APP_SPACE_ID)\n .filter((name) => !RESERVED_SPACE_SUBDIR_NAMES.has(name))\n .filter(isValidSpaceId)\n .sort();\n\n const states: IntegritySpaceState[] = [];\n for (const spaceId of extensionIds) {\n states.push(await loadExtensionSpace(migrationsDir, spaceId, deserializeContract));\n }\n return states;\n}\n\nasync function loadExtensionSpace(\n migrationsDir: string,\n spaceId: string,\n deserializeContract: (raw: unknown) => Contract,\n): Promise<IntegritySpaceState> {\n const spaceDir = spaceMigrationDirectory(migrationsDir, spaceId);\n const { packages, problems } = await readMigrationsDir(spaceDir);\n const { refs, problems: refProblems } = await readRefsTolerant(spaceRefsDirectory(spaceDir));\n const { headRef, problem: headRefProblem } = await readHeadRefTolerant(migrationsDir, spaceId);\n const rawContract = await readRawContractDeferred(migrationsDir, spaceId);\n\n const member = createContractSpaceMember({\n spaceId,\n packages,\n refs,\n headRef,\n refsDir: spaceRefsDirectory(spaceDir),\n resolveContract: () => deserializeContract(rawContract()),\n deserializeContract,\n });\n\n return { member, problems, refProblems, headRefProblem, isApp: false };\n}\n\n/**\n * The result of resolving an extension's `refs/head.json`: the parsed\n * head ref (or `null` when the file is absent or corrupt) plus a problem\n * when the file exists but cannot be parsed.\n */\ninterface HeadRefReadResult {\n readonly headRef: Awaited<ReturnType<typeof readContractSpaceHeadRef>>;\n readonly problem: RefLoadProblem | null;\n}\n\n/**\n * Read an extension's head ref, distinguishing a *genuinely absent*\n * `head.json` (`headRef: null`, no problem — judged `headRefMissing`)\n * from one that *exists but cannot be parsed* (`headRef: null` plus a\n * problem — judged `refUnreadable`, not `headRefMissing`).\n * `readContractSpaceHeadRef` already returns `null` only for ENOENT and\n * throws for unparseable / schema-invalid content, so the throw is the\n * corruption signal. Construction never throws on disk content.\n */\nfunction isToleratedRefHeadReadError(error: unknown): boolean {\n if (MigrationToolsError.is(error)) return true;\n if (!(error instanceof Error)) return false;\n const code = (error as NodeJS.ErrnoException).code;\n return code === 'ENOENT' || code === 'EISDIR';\n}\n\nasync function readHeadRefTolerant(\n migrationsDir: string,\n spaceId: string,\n): Promise<HeadRefReadResult> {\n try {\n const headRef = await readContractSpaceHeadRef(migrationsDir, spaceId);\n return { headRef, problem: null };\n } catch (error) {\n if (!isToleratedRefHeadReadError(error)) {\n throw error;\n }\n return { headRef: null, problem: { refName: HEAD_REF_NAME, detail: detailOf(error) } };\n }\n}\n\nfunction detailOf(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n/**\n * Read the raw on-disk contract eagerly (cheap I/O) but defer its\n * (throwing) failure to call time, so a missing or unparseable\n * `contract.json` becomes a `contract()` throw — surfaced as\n * `contractUnreadable` — rather than a construction failure.\n */\nasync function readRawContractDeferred(\n migrationsDir: string,\n spaceId: string,\n): Promise<() => unknown> {\n try {\n const raw = await readContractSpaceContract(migrationsDir, spaceId);\n return () => raw;\n } catch (error) {\n return () => {\n throw error;\n };\n }\n}\n","import type { MigrationPlan } from '@prisma-next/framework-components/control';\nimport { EMPTY_CONTRACT_HASH } from '../../constants';\nimport { findPathWithDecision } from '../../migration-graph';\nimport type { MigrationOps, OnDiskMigrationPackage } from '../../package';\nimport { requireHeadRef } from '../aggregate';\nimport type { ContractMarkerRecordLike } from '../marker-types';\nimport type { AggregatePerSpacePlan } from '../planner-types';\nimport type { ContractSpaceMember } from '../types';\n\n/**\n * Outcome variants for the graph-walk strategy. Mirrors\n * {@link import('../../compute-extension-space-apply-path').ExtensionSpaceApplyPathOutcome}\n * but operates against the member's lazily-reconstructed `graph()`\n * instead of re-reading from disk. The aggregate planner converts\n * these into {@link import('../planner-types').AggregatePlannerError}\n * variants.\n */\nexport type GraphWalkOutcome =\n | { readonly kind: 'ok'; readonly result: AggregatePerSpacePlan }\n | { readonly kind: 'unreachable' }\n | { readonly kind: 'unsatisfiable'; readonly missing: readonly string[] };\n\nexport interface GraphWalkStrategyInputs {\n readonly aggregateTargetId: string;\n readonly member: ContractSpaceMember;\n readonly currentMarker: ContractMarkerRecordLike | null;\n /**\n * Optional ref name to decorate the resulting `PathDecision`. Used by\n * `migrate` to surface the user-supplied `--to <name>` in\n * structured-progress events and invariant-path error envelopes. The\n * strategy itself does not interpret it.\n */\n readonly refName?: string;\n}\n\n/**\n * Walk a member's hydrated migration graph from the live marker to\n * `member.headRef.hash`, covering every required invariant.\n *\n * Pure synchronous function — no I/O. The aggregate's loader has\n * already integrity-checked every package and reconstructed the graph;\n * this strategy just looks up ops by `migrationHash` and assembles a\n * `MigrationPlan` with `targetId` set from the aggregate (no\n * placeholder cast).\n *\n * Required invariants are computed as `headRef.invariants \\ marker.invariants`\n * — the marker already declares some invariants satisfied; the path\n * only needs to provide the remainder. Mirrors today's\n * `computeExtensionSpaceApplyPath` semantics.\n */\nexport function graphWalkStrategy(input: GraphWalkStrategyInputs): GraphWalkOutcome {\n const { aggregateTargetId, member, currentMarker, refName } = input;\n const headRef = requireHeadRef(member);\n const graph = member.graph();\n const packagesByMigrationHash = new Map<string, OnDiskMigrationPackage>(\n member.packages.map((pkg) => [pkg.metadata.migrationHash, pkg]),\n );\n\n const fromHash = currentMarker?.storageHash ?? EMPTY_CONTRACT_HASH;\n const markerInvariants = new Set(currentMarker?.invariants ?? []);\n const required = new Set(headRef.invariants.filter((id) => !markerInvariants.has(id)));\n\n const outcome = findPathWithDecision(graph, fromHash, headRef.hash, {\n required,\n ...(refName !== undefined ? { refName } : {}),\n });\n\n if (outcome.kind === 'unreachable') {\n return { kind: 'unreachable' };\n }\n if (outcome.kind === 'unsatisfiable') {\n return { kind: 'unsatisfiable', missing: outcome.missing };\n }\n\n const pathOps: MigrationOps[number][] = [];\n const providedInvariantsSet = new Set<string>();\n const edgeRefs: Array<{\n migrationHash: string;\n dirName: string;\n from: string;\n to: string;\n operationCount: number;\n }> = [];\n for (const edge of outcome.decision.selectedPath) {\n const pkg = packagesByMigrationHash.get(edge.migrationHash);\n if (!pkg) {\n throw new Error(\n `Migration package missing for edge ${edge.migrationHash} in space \"${member.spaceId}\". The hydrated migration graph and packagesByMigrationHash map are out of sync — this should be unreachable; report.`,\n );\n }\n for (const op of pkg.ops) pathOps.push(op);\n for (const invariant of pkg.metadata.providedInvariants) providedInvariantsSet.add(invariant);\n edgeRefs.push({\n migrationHash: edge.migrationHash,\n dirName: edge.dirName,\n from: edge.from,\n to: edge.to,\n operationCount: pkg.ops.length,\n });\n }\n\n const plan: MigrationPlan = {\n targetId: aggregateTargetId,\n spaceId: member.spaceId,\n origin: currentMarker === null ? null : { storageHash: currentMarker.storageHash },\n destination: { storageHash: headRef.hash },\n operations: pathOps,\n providedInvariants: [...providedInvariantsSet].sort(),\n };\n\n return {\n kind: 'ok',\n result: {\n plan,\n displayOps: pathOps,\n destinationContract: member.contract(),\n strategy: 'graph-walk',\n migrationEdges: edgeRefs,\n pathDecision: outcome.decision,\n },\n };\n}\n","import { elementCoordinates } from '@prisma-next/framework-components/ir';\nimport type { ContractSpaceMember } from './types';\n\n/**\n * Project the **introspected live schema** to the slice claimed by a\n * single contract-space member.\n *\n * \"Schema\" here means the live introspected database state — the\n * planner / verifier sees this object as a `MongoSchemaIR` (Mongo) or\n * `SqlSchemaIR` (SQL). It is **not** a database schema in the SQL\n * `CREATE SCHEMA` sense, nor a contract-space namespace. The\n * function's job is to filter that introspected state down to the\n * elements claimed by one space, so a per-space verify pass doesn't\n * see another space's storage as \"extras\".\n *\n * Returns the same `schema` value with every top-level storage element\n * (table or collection) claimed by **other** members of the aggregate\n * removed. Elements not claimed by any member flow through unchanged —\n * the planner / verifier sees them as orphans (extras in strict mode).\n *\n * Used by:\n *\n * - The aggregate planner's **synth strategy**: when synthesising a\n * plan against a member's contract, the live schema must be projected\n * to that member's slice so the planner doesn't treat elements claimed\n * by other members as \"extras\" and emit destructive ops to drop them.\n * - The aggregate verifier's **schemaCheck**: projects per member so the\n * single-contract verify only sees the slice claimed by the member it\n * is checking. Closes the architectural concern that a multi-member\n * deployment makes each member's elements look like extras to every\n * other member's verify pass.\n *\n * **Duck-typing semantics**: the helper operates on `unknown` for the\n * schema and falls through structurally if the shape doesn't match.\n * Two storage shapes are recognised today:\n *\n * - SQL families expose `storage.tables: Record<string, ...>` on\n * contracts and the introspected schema mirrors the same record shape.\n * Pruning iterates the record entries.\n * - Mongo exposes `storage.collections: Record<string, ...>` on\n * contracts; the introspected `MongoSchemaIR` exposes\n * `collections: ReadonlyArray<{name: string, ...}>`. Pruning iterates\n * the array on the schema side and the record's keys on the\n * other-member side.\n *\n * Schemas of unrecognised shape are returned unchanged. The function\n * never imports family classes (`SqlSchemaIR`, `MongoSchemaIR`); the\n * projected schema is a plain object — `{...schema, tables: pruned}` or\n * `{...schema, collections: pruned}` — that downstream consumers\n * duck-type. A future family with a different storage shape gets the\n * schema returned unchanged rather than blowing up the aggregate\n * planner.\n *\n * Record-shape detection guards against arrays (`!Array.isArray`) so\n * an unrecognised array-shaped value falls through unchanged rather\n * than being pruned by numeric keys.\n */\nexport function projectSchemaToSpace(\n schema: unknown,\n member: ContractSpaceMember,\n otherMembers: ReadonlyArray<ContractSpaceMember>,\n): unknown {\n if (typeof schema !== 'object' || schema === null) return schema;\n\n const ownedByOthers = collectOwnedNames(member, otherMembers);\n if (ownedByOthers.size === 0) return schema;\n\n const schemaObj = schema as { readonly tables?: unknown; readonly collections?: unknown };\n\n if (\n typeof schemaObj.tables === 'object' &&\n schemaObj.tables !== null &&\n !Array.isArray(schemaObj.tables)\n ) {\n return pruneRecord(schemaObj, 'tables', ownedByOthers);\n }\n\n if (Array.isArray(schemaObj.collections)) {\n return pruneCollectionsArray(schemaObj, ownedByOthers);\n }\n\n if (\n typeof schemaObj.collections === 'object' &&\n schemaObj.collections !== null &&\n !Array.isArray(schemaObj.collections)\n ) {\n return pruneRecord(schemaObj, 'collections', ownedByOthers);\n }\n\n return schema;\n}\n\nfunction collectOwnedNames(\n member: ContractSpaceMember,\n otherMembers: ReadonlyArray<ContractSpaceMember>,\n): Set<string> {\n const owned = new Set<string>();\n for (const other of otherMembers) {\n if (other.spaceId === member.spaceId) continue;\n for (const { entityName } of elementCoordinates(other.contract().storage)) {\n owned.add(entityName);\n }\n }\n return owned;\n}\n\nfunction pruneRecord(\n schemaObj: { readonly tables?: unknown; readonly collections?: unknown },\n field: 'tables' | 'collections',\n ownedByOthers: ReadonlySet<string>,\n): unknown {\n const source = schemaObj[field] as Record<string, unknown>;\n let removed = false;\n const pruned: Record<string, unknown> = {};\n for (const [name, value] of Object.entries(source)) {\n if (ownedByOthers.has(name)) {\n removed = true;\n } else {\n pruned[name] = value;\n }\n }\n if (!removed) return schemaObj;\n return { ...schemaObj, [field]: pruned };\n}\n\nfunction pruneCollectionsArray(\n schemaObj: { readonly collections?: unknown },\n ownedByOthers: ReadonlySet<string>,\n): unknown {\n const source = schemaObj.collections as ReadonlyArray<unknown>;\n let removed = false;\n const pruned: unknown[] = [];\n for (const entry of source) {\n if (typeof entry === 'object' && entry !== null) {\n const name = (entry as { readonly name?: unknown }).name;\n if (typeof name === 'string' && ownedByOthers.has(name)) {\n removed = true;\n continue;\n }\n }\n pruned.push(entry);\n }\n if (!removed) return schemaObj;\n return { ...schemaObj, collections: pruned };\n}\n","import type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';\nimport type {\n ControlFamilyInstance,\n MigrationOperationPolicy,\n MigrationPlan,\n MigrationPlannerConflict,\n MigrationPlannerResult,\n TargetMigrationsCapability,\n} from '@prisma-next/framework-components/control';\nimport type { AggregatePerSpacePlan } from '../planner-types';\nimport { projectSchemaToSpace } from '../project-schema-to-space';\nimport type { ContractSpaceMember } from '../types';\n\nexport interface SynthStrategyInputs<TFamilyId extends string, TTargetId extends string> {\n readonly aggregateTargetId: string;\n readonly member: ContractSpaceMember;\n readonly otherMembers: ReadonlyArray<ContractSpaceMember>;\n readonly schemaIntrospection: unknown;\n readonly familyInstance: ControlFamilyInstance<TFamilyId, unknown>;\n readonly migrations: TargetMigrationsCapability<\n TFamilyId,\n TTargetId,\n ControlFamilyInstance<TFamilyId, unknown>\n >;\n readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<TFamilyId, TTargetId>>;\n readonly operationPolicy: MigrationOperationPolicy;\n}\n\nexport type SynthStrategyOutcome =\n | { readonly kind: 'ok'; readonly result: AggregatePerSpacePlan }\n | { readonly kind: 'failure'; readonly conflicts: readonly MigrationPlannerConflict[] };\n\n/**\n * The {@link MigrationPlanner.plan} interface is declared as synchronous,\n * but historical and test fixture call sites have always invoked it\n * with `await` (see prior `db-apply-per-space.ts`). Tolerating a\n * Promise here keeps existing test mocks working without changing the\n * declared family SPI.\n */\ntype MaybeAsyncPlannerResult = MigrationPlannerResult | Promise<MigrationPlannerResult>;\n\n/**\n * Synthesise a migration plan for a single member by projecting the\n * live schema down to that member's claimed slice and delegating to\n * the family's `createPlanner(...).plan(...)`.\n *\n * Pre-projection (via {@link projectSchemaToSpace}) closes the F23\n * concern: without it, the family's planner sees other members'\n * tables as \"extras\" and emits destructive ops to drop them. With it,\n * the planner only sees the slice this member claims.\n *\n * The synthesised plan's `targetId` is set from `aggregateTargetId`\n * (the aggregate's ambient target). The family's planner does not\n * stamp `targetId` on the produced plan; the aggregate planner is\n * the single point that knows the target.\n *\n * Used by:\n *\n * - The app member by default (CLI policy\n * `ignoreGraphFor: { app.spaceId }`).\n * - Any extension member whose `headRef.invariants` is empty (the\n * strategy selector falls back to synth when graph-walk isn't\n * required).\n */\nexport async function synthStrategy<TFamilyId extends string, TTargetId extends string>(\n input: SynthStrategyInputs<TFamilyId, TTargetId>,\n): Promise<SynthStrategyOutcome> {\n const projectedSchema = projectSchemaToSpace(\n input.schemaIntrospection,\n input.member,\n input.otherMembers,\n );\n\n const planner = input.migrations.createPlanner(input.familyInstance);\n const plannerResult: MigrationPlannerResult = await (planner.plan({\n contract: input.member.contract(),\n schema: projectedSchema,\n policy: input.operationPolicy,\n fromContract: null,\n frameworkComponents: input.frameworkComponents,\n spaceId: input.member.spaceId,\n }) as MaybeAsyncPlannerResult);\n\n if (plannerResult.kind === 'failure') {\n return { kind: 'failure', conflicts: plannerResult.conflicts };\n }\n\n const synthedPlan = plannerResult.plan;\n // The family planner returns a class-instance-shaped plan whose\n // `destination` / `operations` are accessors on the prototype, often\n // backed by private fields. A naive spread (`{ ...synthedPlan }`)\n // would lose those accessors and produce a plan with\n // `destination: undefined`; rebinding the prototype on a plain\n // object would break private-field access. We instead wrap the plan\n // in a Proxy that forwards every read except `targetId`, which is\n // stamped from the aggregate's ambient target. This preserves the\n // planner's class semantics while keeping the aggregate the single\n // source of truth for `targetId`.\n const plan: MigrationPlan = new Proxy(synthedPlan, {\n get(target, prop) {\n if (prop === 'targetId') return input.aggregateTargetId;\n // Forward `this` as the original target so prototype-bound\n // private fields (#destination, #operations, …) resolve.\n return Reflect.get(target, prop, target);\n },\n has(target, prop) {\n if (prop === 'targetId') return true;\n return Reflect.has(target, prop);\n },\n });\n\n return {\n kind: 'ok',\n result: {\n plan,\n displayOps: synthedPlan.operations,\n destinationContract: input.member.contract(),\n strategy: 'synth',\n },\n };\n}\n","import { notOk, ok } from '@prisma-next/utils/result';\nimport { requireHeadRef } from './aggregate';\nimport type {\n AggregatePerSpacePlan,\n AggregatePlannerError,\n AggregatePlannerInput,\n AggregatePlannerOutput,\n} from './planner-types';\nimport { graphWalkStrategy } from './strategies/graph-walk';\nimport { synthStrategy } from './strategies/synth';\nimport type { ContractSpaceMember } from './types';\n\nexport type {\n AggregateCurrentDBState,\n AggregateMigrationEdgeRef,\n AggregatePerSpacePlan,\n AggregatePlannerError,\n AggregatePlannerInput,\n AggregatePlannerOutput,\n AggregatePlannerSuccess,\n CallerPolicy,\n} from './planner-types';\n\n/**\n * Plan a migration across every member of a {@link ContractSpaceAggregate}.\n *\n * Strategy selection per member, in order; first match wins:\n *\n * 1. If `callerPolicy.ignoreGraphFor.has(member.spaceId)`:\n * - If `member.headRef.invariants` is empty → synth.\n * - Else → `policyConflict` (synth cannot satisfy authored invariants).\n * 2. Else if `member.graph()` is non-empty AND graph-walk\n * succeeds → graph-walk.\n * 3. Else if `member.headRef.invariants` is empty → synth.\n * 4. Else → graph-walk failure → `extensionPathUnreachable` /\n * `extensionPathUnsatisfiable`.\n *\n * Output `applyOrder` is `[...aggregate.extensions.map(spaceId), aggregate.app.spaceId]`\n * — extensions alphabetical, then app — matching today's\n * `concatenateSpaceApplyInputs` ordering. This preserves\n * `MultiSpaceRunnerFailure.failingSpace` attribution byte-for-byte.\n *\n * Every emitted `MigrationPlan` has `targetId = aggregate.targetId`.\n * No placeholder cast; no patch step.\n */\nexport async function planAggregate<TFamilyId extends string, TTargetId extends string>(\n input: AggregatePlannerInput<TFamilyId, TTargetId>,\n): Promise<AggregatePlannerOutput> {\n const { aggregate, currentDBState, callerPolicy } = input;\n const allMembers: ReadonlyArray<ContractSpaceMember> = [aggregate.app, ...aggregate.extensions];\n\n const perSpace = new Map<string, AggregatePerSpacePlan>();\n\n // Iterate in apply order so a per-member error short-circuits the\n // walk in the same order the runner would walk inputs.\n const orderedMembers: ReadonlyArray<ContractSpaceMember> = [\n ...aggregate.extensions,\n aggregate.app,\n ];\n\n for (const member of orderedMembers) {\n const otherMembers = allMembers.filter((m) => m.spaceId !== member.spaceId);\n const currentMarker = currentDBState.markersBySpaceId.get(member.spaceId) ?? null;\n const headRef = requireHeadRef(member);\n\n const ignoreGraph = callerPolicy.ignoreGraphFor.has(member.spaceId);\n const invariantsRequired = headRef.invariants.length > 0;\n\n if (ignoreGraph && invariantsRequired) {\n const conflict: AggregatePlannerError = {\n kind: 'policyConflict',\n spaceId: member.spaceId,\n detail: `\\`callerPolicy.ignoreGraphFor\\` requested for space \"${member.spaceId}\", but the member declares non-empty head-ref invariants (${headRef.invariants.join(', ')}). Synthesising a plan from the contract IR cannot satisfy authored invariants — the graph must be walked. Either remove \"${member.spaceId}\" from \\`ignoreGraphFor\\` or amend the on-disk head ref to declare zero invariants.`,\n };\n return notOk(conflict);\n }\n\n if (ignoreGraph) {\n const synthOutcome = await synthStrategy({\n aggregateTargetId: aggregate.targetId,\n member,\n otherMembers,\n schemaIntrospection: currentDBState.schemaIntrospection,\n familyInstance: input.familyInstance,\n migrations: input.migrations,\n frameworkComponents: input.frameworkComponents,\n operationPolicy: input.operationPolicy,\n });\n if (synthOutcome.kind === 'failure') {\n return notOk({\n kind: 'appSynthFailure',\n spaceId: member.spaceId,\n conflicts: synthOutcome.conflicts,\n });\n }\n perSpace.set(member.spaceId, synthOutcome.result);\n continue;\n }\n\n // Try graph-walk first when the graph has nodes; fall back to synth\n // when the graph is empty AND no invariants are required.\n if (member.graph().nodes.size > 0) {\n const walked = graphWalkStrategy({\n aggregateTargetId: aggregate.targetId,\n member,\n currentMarker,\n });\n if (walked.kind === 'ok') {\n perSpace.set(member.spaceId, walked.result);\n continue;\n }\n if (walked.kind === 'unreachable') {\n return notOk({\n kind: 'extensionPathUnreachable',\n spaceId: member.spaceId,\n target: headRef.hash,\n });\n }\n // unsatisfiable — surface\n return notOk({\n kind: 'extensionPathUnsatisfiable',\n spaceId: member.spaceId,\n missingInvariants: walked.missing,\n });\n }\n\n // Empty graph: synth is the only option, and it can only satisfy\n // empty-invariant members.\n if (invariantsRequired) {\n return notOk({\n kind: 'extensionPathUnsatisfiable',\n spaceId: member.spaceId,\n missingInvariants: [...headRef.invariants].sort(),\n });\n }\n\n const synthOutcome = await synthStrategy({\n aggregateTargetId: aggregate.targetId,\n member,\n otherMembers,\n schemaIntrospection: currentDBState.schemaIntrospection,\n familyInstance: input.familyInstance,\n migrations: input.migrations,\n frameworkComponents: input.frameworkComponents,\n operationPolicy: input.operationPolicy,\n });\n if (synthOutcome.kind === 'failure') {\n return notOk({\n kind: 'appSynthFailure',\n spaceId: member.spaceId,\n conflicts: synthOutcome.conflicts,\n });\n }\n perSpace.set(member.spaceId, synthOutcome.result);\n }\n\n return ok({\n perSpace,\n applyOrder: [...aggregate.extensions.map((m) => m.spaceId), aggregate.app.spaceId],\n });\n}\n","import { elementCoordinates } from '@prisma-next/framework-components/ir';\nimport type { Result } from '@prisma-next/utils/result';\nimport { notOk, ok } from '@prisma-next/utils/result';\nimport { requireHeadRef } from './aggregate';\nimport type { ContractMarkerRecordLike } from './marker-types';\nimport { projectSchemaToSpace } from './project-schema-to-space';\nimport type { ContractSpaceAggregate, ContractSpaceMember } from './types';\n\n/**\n * Caller policy for the aggregate verifier. Today's only knob is\n * `mode`: `strict` treats orphan elements (live tables not claimed by\n * any aggregate member) as errors; `lenient` treats them as\n * informational. Maps directly to `db verify --strict`.\n */\nexport interface AggregateVerifierInput<TSchemaResult> {\n readonly aggregate: ContractSpaceAggregate;\n readonly markersBySpaceId: ReadonlyMap<string, ContractMarkerRecordLike | null>;\n readonly schemaIntrospection: unknown;\n readonly mode: 'strict' | 'lenient';\n /**\n * Caller-supplied per-space schema verifier. The CLI wires this to\n * the family's `verifySqlSchema` (SQL) / equivalent (other\n * families). The aggregate verifier projects the schema to the\n * member's slice via {@link projectSchemaToSpace} before invoking\n * the callback, so single-contract semantics are preserved.\n *\n * Typed structurally with a generic `TSchemaResult` so the\n * migration-tools layer doesn't depend on the SQL family's\n * `VerifySqlSchemaResult`. CLI callers pass the family's type\n * through unchanged.\n */\n readonly verifySchemaForMember: (\n projectedSchema: unknown,\n member: ContractSpaceMember,\n mode: 'strict' | 'lenient',\n ) => TSchemaResult;\n}\n\n/**\n * Marker-check result per member. Mirrors the four cases the\n * `verifyContractSpaces` primitive surfaces today, plus an `'absent'`\n * case for greenfield spaces (no marker row written yet — `db init`\n * not run).\n */\nexport type MarkerCheckResult =\n | { readonly kind: 'ok' }\n | { readonly kind: 'absent' }\n | {\n readonly kind: 'hashMismatch';\n readonly markerHash: string;\n readonly expected: string;\n }\n | { readonly kind: 'missingInvariants'; readonly missing: readonly string[] };\n\nexport interface MarkerCheckSection {\n readonly perSpace: ReadonlyMap<string, MarkerCheckResult>;\n readonly orphanMarkers: readonly {\n readonly spaceId: string;\n readonly row: ContractMarkerRecordLike;\n }[];\n}\n\n/**\n * A live storage element (today: a top-level table) not claimed by any\n * member of the aggregate. The aggregate verifier always reports these;\n * the caller decides what to do — `db verify --strict` treats them as\n * errors, the lenient default treats them as informational.\n *\n * Today only `kind: 'table'` exists. The discriminated shape leaves\n * room for orphan columns / indexes / sequences in the future without\n * breaking the type contract.\n */\nexport type OrphanElement = { readonly kind: 'table'; readonly name: string };\n\nexport interface SchemaCheckSection<TSchemaResult> {\n readonly perSpace: ReadonlyMap<string, TSchemaResult>;\n /**\n * Live elements present in the introspected schema that are not\n * claimed by **any** aggregate member. Sorted alphabetically by name.\n */\n readonly orphanElements: readonly OrphanElement[];\n}\n\nexport interface AggregateVerifierSuccess<TSchemaResult> {\n readonly markerCheck: MarkerCheckSection;\n readonly schemaCheck: SchemaCheckSection<TSchemaResult>;\n}\n\nexport type AggregateVerifierError = {\n readonly kind: 'introspectionFailure';\n readonly detail: string;\n};\n\nexport type AggregateVerifierOutput<TSchemaResult> = Result<\n AggregateVerifierSuccess<TSchemaResult>,\n AggregateVerifierError\n>;\n\n/**\n * Verify a {@link ContractSpaceAggregate} against the live database\n * state. Bundles two checks:\n *\n * - `markerCheck` per member: compare the live marker row against the\n * member's `headRef.hash` + `headRef.invariants`. Absence is a\n * distinct kind, not an error (callers — `db verify` strict vs\n * `db init` precondition — choose how to interpret it).\n * - `schemaCheck` per member: project the live schema to the slice\n * the member claims via {@link projectSchemaToSpace}, then delegate\n * to the caller-supplied `verifySchemaForMember`. The pre-projection\n * means the family's single-contract verifier no longer sees other\n * members' tables as `extras`, so a multi-member deployment never\n * surfaces cross-member tables as orphaned schema elements.\n *\n * `markerCheck.orphanMarkers` lists every marker row whose `space` is\n * not a member of the aggregate. `db verify` callers reject orphans;\n * future tooling may not.\n *\n * Pure synchronous function; no I/O. The caller (CLI) gathers\n * `markersBySpaceId` and `schemaIntrospection` ahead of the call.\n */\nexport function verifyAggregate<TSchemaResult>(\n input: AggregateVerifierInput<TSchemaResult>,\n): AggregateVerifierOutput<TSchemaResult> {\n try {\n return runVerifyAggregate(input);\n } catch (error) {\n return notOk({\n kind: 'introspectionFailure',\n detail: error instanceof Error ? error.message : String(error),\n });\n }\n}\n\nfunction runVerifyAggregate<TSchemaResult>(\n input: AggregateVerifierInput<TSchemaResult>,\n): AggregateVerifierOutput<TSchemaResult> {\n const { aggregate, markersBySpaceId, schemaIntrospection, mode, verifySchemaForMember } = input;\n const allMembers: ReadonlyArray<ContractSpaceMember> = [aggregate.app, ...aggregate.extensions];\n const memberSpaceIds = new Set(allMembers.map((m) => m.spaceId));\n\n // Marker check per member.\n const markerPerSpace = new Map<string, MarkerCheckResult>();\n for (const member of allMembers) {\n const marker = markersBySpaceId.get(member.spaceId) ?? null;\n if (marker === null) {\n markerPerSpace.set(member.spaceId, { kind: 'absent' });\n continue;\n }\n const headRef = requireHeadRef(member);\n if (marker.storageHash !== headRef.hash) {\n markerPerSpace.set(member.spaceId, {\n kind: 'hashMismatch',\n markerHash: marker.storageHash,\n expected: headRef.hash,\n });\n continue;\n }\n const markerInvariants = new Set(marker.invariants);\n const missing = headRef.invariants.filter((id) => !markerInvariants.has(id));\n if (missing.length > 0) {\n markerPerSpace.set(member.spaceId, {\n kind: 'missingInvariants',\n missing: [...missing].sort(),\n });\n continue;\n }\n markerPerSpace.set(member.spaceId, { kind: 'ok' });\n }\n\n // Orphan markers: entries in markersBySpaceId whose spaceId is not a\n // member of the aggregate.\n const orphanMarkers: { spaceId: string; row: ContractMarkerRecordLike }[] = [];\n for (const [spaceId, row] of markersBySpaceId) {\n if (row !== null && !memberSpaceIds.has(spaceId)) {\n orphanMarkers.push({ spaceId, row });\n }\n }\n orphanMarkers.sort((a, b) => a.spaceId.localeCompare(b.spaceId));\n\n // Schema check per member (with per-space pre-projection).\n const schemaPerSpace = new Map<string, TSchemaResult>();\n for (const member of allMembers) {\n const others = allMembers.filter((m) => m.spaceId !== member.spaceId);\n const projected = projectSchemaToSpace(schemaIntrospection, member, others);\n schemaPerSpace.set(member.spaceId, verifySchemaForMember(projected, member, mode));\n }\n\n return ok({\n markerCheck: {\n perSpace: markerPerSpace,\n orphanMarkers,\n },\n schemaCheck: {\n perSpace: schemaPerSpace,\n orphanElements: detectOrphanElements(schemaIntrospection, allMembers),\n },\n });\n}\n\n/**\n * Live tables not claimed by any aggregate member. Duck-typed against\n * the introspected schema's `tables` map; schemas whose shape doesn't\n * match return an empty list (consistent with\n * {@link projectSchemaToSpace}'s fall-through).\n */\nfunction detectOrphanElements(\n schemaIntrospection: unknown,\n members: ReadonlyArray<ContractSpaceMember>,\n): readonly OrphanElement[] {\n if (typeof schemaIntrospection !== 'object' || schemaIntrospection === null) return [];\n const liveTables = (schemaIntrospection as { readonly tables?: unknown }).tables;\n if (typeof liveTables !== 'object' || liveTables === null) return [];\n\n const claimedTables = new Set<string>();\n for (const member of members) {\n const contract = member.contract();\n for (const { entityName } of elementCoordinates(contract.storage)) {\n claimedTables.add(entityName);\n }\n }\n\n const orphans: OrphanElement[] = [];\n for (const tableName of Object.keys(liveTables as Record<string, unknown>)) {\n if (!claimedTables.has(tableName)) {\n orphans.push({ kind: 'table', name: tableName });\n }\n }\n orphans.sort((a, b) => a.name.localeCompare(b.name));\n return orphans;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"aggregate.mjs","names":["detailOf"],"sources":["../../src/aggregate/aggregate.ts","../../src/aggregate/check-integrity.ts","../../src/aggregate/loader.ts","../../src/aggregate/strategies/graph-walk.ts","../../src/aggregate/project-schema-to-space.ts","../../src/aggregate/strategies/synth.ts","../../src/aggregate/planner.ts","../../src/aggregate/verifier.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport type { Contract } from '@prisma-next/contract/types';\nimport { join } from 'pathe';\nimport {\n errorBundleNotFoundForGraphNode,\n errorContractDeserializationFailed,\n errorHashNotInGraph,\n errorInvalidJson,\n errorMissingFile,\n errorSnapshotMissing,\n MigrationToolsError,\n} from '../errors';\nimport type { MigrationGraph } from '../graph';\nimport { isGraphNode } from '../graph-membership';\nimport type { IntegrityQueryOptions, IntegrityViolation } from '../integrity-violation';\nimport { reconstructGraph } from '../migration-graph';\nimport type { OnDiskMigrationPackage } from '../package';\nimport type { Refs } from '../refs';\nimport { readRefSnapshot } from '../refs/snapshot';\nimport type { ContractSpaceHeadRecord } from '../verify-contract-spaces';\nimport type {\n ContractAtOptions,\n ContractAtResult,\n ContractSpaceAggregate,\n ContractSpaceMember,\n} from './types';\n\nfunction hasErrnoCode(error: unknown, code: string): boolean {\n return error instanceof Error && (error as { code?: string }).code === code;\n}\n\nfunction contractAtMemoKey(hash: string, refName: string | undefined): string {\n return `${hash}\\0${refName ?? ''}`;\n}\n\nfunction deserializeContractAtPath(\n filePath: string,\n contractJson: unknown,\n deserializeContract: (raw: unknown) => Contract,\n): Contract {\n try {\n return deserializeContract(contractJson);\n } catch (error) {\n if (MigrationToolsError.is(error)) {\n throw error;\n }\n const message = error instanceof Error ? error.message : String(error);\n throw errorContractDeserializationFailed(filePath, message);\n }\n}\n\nasync function readGraphNodeEndContract(\n packageDir: string,\n deserializeContract: (raw: unknown) => Contract,\n): Promise<{ contractJson: unknown; contractDts: string; contract: Contract }> {\n const jsonPath = join(packageDir, 'end-contract.json');\n const dtsPath = join(packageDir, 'end-contract.d.ts');\n\n let rawJson: string;\n try {\n rawJson = await readFile(jsonPath, 'utf-8');\n } catch (error) {\n if (hasErrnoCode(error, 'ENOENT')) {\n throw errorMissingFile('end-contract.json', packageDir);\n }\n throw error;\n }\n\n let contractJson: unknown;\n try {\n contractJson = JSON.parse(rawJson);\n } catch (error) {\n throw errorInvalidJson(jsonPath, error instanceof Error ? error.message : String(error));\n }\n\n let contractDts: string;\n try {\n contractDts = await readFile(dtsPath, 'utf-8');\n } catch (error) {\n if (hasErrnoCode(error, 'ENOENT')) {\n throw errorMissingFile('end-contract.d.ts', packageDir);\n }\n throw error;\n }\n\n const contract = deserializeContractAtPath(jsonPath, contractJson, deserializeContract);\n return { contractJson, contractDts, contract };\n}\n\nasync function resolveContractAt(args: {\n readonly hash: string;\n readonly opts: ContractAtOptions | undefined;\n readonly refsDir: string;\n readonly packages: readonly OnDiskMigrationPackage[];\n readonly graph: MigrationGraph;\n readonly deserializeContract: (raw: unknown) => Contract;\n}): Promise<ContractAtResult> {\n const { hash, opts, refsDir, packages, graph, deserializeContract } = args;\n const refName = opts?.refName;\n\n if (refName !== undefined) {\n const snapshot = await readRefSnapshot(refsDir, refName);\n if (snapshot) {\n const jsonPath = join(refsDir, `${refName}.contract.json`);\n return {\n hash,\n contractJson: snapshot.contract,\n contractDts: snapshot.contractDts,\n contract: deserializeContractAtPath(jsonPath, snapshot.contract, deserializeContract),\n provenance: 'snapshot',\n };\n }\n\n if (isGraphNode(hash, graph)) {\n return resolveGraphNodeContractAt({\n hash,\n packages,\n deserializeContract,\n explicitLabel: refName,\n });\n }\n\n throw errorSnapshotMissing(refName);\n }\n\n if (isGraphNode(hash, graph)) {\n return resolveGraphNodeContractAt({ hash, packages, deserializeContract });\n }\n\n throw errorHashNotInGraph(hash, graph);\n}\n\nasync function resolveGraphNodeContractAt(args: {\n readonly hash: string;\n readonly packages: readonly OnDiskMigrationPackage[];\n readonly deserializeContract: (raw: unknown) => Contract;\n readonly explicitLabel?: string;\n}): Promise<ContractAtResult> {\n const { hash, packages, deserializeContract, explicitLabel } = args;\n const matchingBundle = packages.find((pkg) => pkg.metadata.to === hash);\n if (!matchingBundle) {\n throw errorBundleNotFoundForGraphNode(hash, explicitLabel);\n }\n\n const { contractJson, contractDts, contract } = await readGraphNodeEndContract(\n matchingBundle.dirPath,\n deserializeContract,\n );\n return {\n hash,\n contractJson,\n contractDts,\n contract,\n provenance: 'graph-node',\n sourceDir: matchingBundle.dirPath,\n };\n}\n\n/**\n * Resolve a member's head ref, asserting it is present. The apply/verify\n * engine only runs after `checkIntegrity` has refused on `headRefMissing`,\n * so a member reaching the planner / verifier without a head ref is a\n * programming error (the integrity gate was skipped), not a user-facing\n * state. The app member's head ref is always synthesised, so this only\n * ever guards an ungated extension space.\n */\nexport function requireHeadRef(member: ContractSpaceMember): ContractSpaceHeadRecord {\n if (member.headRef === null) {\n throw new Error(\n `Contract space \"${member.spaceId}\" has no head ref; the integrity gate must refuse a missing head ref before planning or verifying.`,\n );\n }\n return member.headRef;\n}\n\n/**\n * Build a {@link ContractSpaceMember} with lazily-memoised `graph()`,\n * `contract()`, and `contractAt()` facets.\n *\n * `graph()` reconstructs the migration graph from `packages` on first\n * call and caches it. `contract()` calls `resolveContract` on first call\n * and caches the result; a throwing `resolveContract` (e.g. a missing or\n * undeserializable on-disk contract) re-throws on each call rather than\n * caching a value — `checkIntegrity` surfaces that as `contractUnreadable`.\n * `contractAt()` materializes the contract at an arbitrary graph node with\n * the same resolution order as plan-time ref resolution: ref snapshot first\n * (when `opts.refName` is set), else the matching package's `end-contract.*`.\n */\nexport function createContractSpaceMember(args: {\n readonly spaceId: string;\n readonly packages: readonly OnDiskMigrationPackage[];\n readonly refs: Refs;\n readonly headRef: ContractSpaceHeadRecord | null;\n readonly refsDir: string;\n readonly resolveContract: () => Contract;\n readonly deserializeContract: (raw: unknown) => Contract;\n}): ContractSpaceMember {\n const { spaceId, packages, refs, headRef, refsDir, resolveContract, deserializeContract } = args;\n let graphMemo: MigrationGraph | undefined;\n let contractMemo: Contract | undefined;\n const contractAtMemo = new Map<string, ContractAtResult>();\n\n function memberGraph(): MigrationGraph {\n graphMemo ??= reconstructGraph(packages);\n return graphMemo;\n }\n\n return {\n spaceId,\n packages,\n refs,\n headRef,\n graph: memberGraph,\n contract() {\n contractMemo ??= resolveContract();\n return contractMemo;\n },\n async contractAt(hash, opts) {\n const key = contractAtMemoKey(hash, opts?.refName);\n const cached = contractAtMemo.get(key);\n if (cached) {\n return cached;\n }\n\n const result = await resolveContractAt({\n hash,\n opts,\n refsDir,\n packages,\n graph: memberGraph(),\n deserializeContract,\n });\n contractAtMemo.set(key, result);\n return result;\n },\n };\n}\n\n/**\n * Assemble a {@link ContractSpaceAggregate} value from its members and a\n * `checkIntegrity` implementation. The query methods (`listSpaces` /\n * `hasSpace` / `space` / `spaces`) are derived here so every aggregate —\n * loader-built or test-built — shares one query surface: `app` first,\n * then `extensions` in the order supplied (the loader sorts them\n * lex-ascending by `spaceId`).\n */\nexport function createContractSpaceAggregate(args: {\n readonly targetId: string;\n readonly app: ContractSpaceMember;\n readonly extensions: readonly ContractSpaceMember[];\n readonly checkIntegrity: (opts?: IntegrityQueryOptions) => readonly IntegrityViolation[];\n}): ContractSpaceAggregate {\n const { targetId, app, extensions, checkIntegrity } = args;\n const ordered: readonly ContractSpaceMember[] = [app, ...extensions];\n const byId = new Map(ordered.map((m) => [m.spaceId, m]));\n return {\n targetId,\n app,\n extensions,\n listSpaces: () => ordered.map((m) => m.spaceId),\n hasSpace: (id) => byId.has(id),\n space: (id) => byId.get(id),\n spaces: () => ordered,\n checkIntegrity,\n };\n}\n","import { elementCoordinates } from '@prisma-next/framework-components/ir';\nimport { EMPTY_CONTRACT_HASH } from '../constants';\nimport { MigrationToolsError } from '../errors';\nimport type {\n DeclaredExtensionEntry,\n IntegrityQueryOptions,\n IntegrityViolation,\n} from '../integrity-violation';\nimport type { PackageLoadProblem } from '../io';\nimport type { OnDiskMigrationPackage } from '../package';\nimport type { RefLoadProblem } from '../refs';\nimport type { ContractSpaceMember } from './types';\n\n/**\n * One space's load-time facts that `checkIntegrity` judges: the loaded\n * member, the load-time problems `readMigrationsDir` surfaced for it, and\n * whether it is the app space (the app head ref is synthesised, so the\n * head-ref checks are skipped for it).\n */\nexport interface IntegritySpaceState {\n readonly member: ContractSpaceMember;\n readonly problems: readonly PackageLoadProblem[];\n /** Per-ref problems: a user ref `*.json` that exists but is unparseable. */\n readonly refProblems: readonly RefLoadProblem[];\n /**\n * The space's `refs/head.json` problem when it exists but is unparseable.\n * `null` means the head ref was read cleanly or is genuinely absent —\n * the absent case is judged `headRefMissing`, the corrupt case here is\n * judged `refUnreadable` (and suppresses `headRefMissing`).\n */\n readonly headRefProblem: RefLoadProblem | null;\n readonly isApp: boolean;\n}\n\nexport interface IntegrityComputationInput {\n readonly targetId: string;\n readonly spaces: readonly IntegritySpaceState[];\n}\n\n/**\n * Walk the loaded model and return **every** integrity violation — never\n * bailing at the first. Structurally-derivable violations (load-time\n * problems, self-edges, missing / unreachable head refs) are always\n * produced; layout-drift checks require `declaredExtensions`, and\n * contract / target / disjointness checks require `checkContracts`.\n */\nexport function computeIntegrityViolations(\n input: IntegrityComputationInput,\n opts?: IntegrityQueryOptions,\n): readonly IntegrityViolation[] {\n const violations: IntegrityViolation[] = [];\n\n for (const { member, problems, refProblems, headRefProblem, isApp } of input.spaces) {\n const { spaceId } = member;\n\n for (const problem of problems) {\n violations.push(loadProblemToViolation(spaceId, problem));\n }\n\n for (const refProblem of refProblems) {\n violations.push({\n kind: 'refUnreadable',\n spaceId,\n refName: refProblem.refName,\n detail: refProblem.detail,\n });\n }\n if (headRefProblem !== null) {\n violations.push({\n kind: 'refUnreadable',\n spaceId,\n refName: headRefProblem.refName,\n detail: headRefProblem.detail,\n });\n }\n\n for (const pkg of member.packages) {\n const from = pkg.metadata.from ?? EMPTY_CONTRACT_HASH;\n const isSelfEdge = from === pkg.metadata.to;\n const hasDataOp = pkg.ops.some((op) => op.operationClass === 'data');\n if (isSelfEdge && !hasDataOp) {\n violations.push({ kind: 'sameSourceAndTarget', spaceId, dirName: pkg.dirName, hash: from });\n }\n }\n\n violations.push(...duplicateMigrationHashViolations(spaceId, member.packages));\n\n // The app head ref is synthesised from the live contract, so it is\n // always present and reachable; only extension spaces read their head\n // ref from disk and can be missing or point outside the graph. A head\n // ref that exists but is unparseable is already surfaced above as\n // `refUnreadable`, so it is not also reported as `headRefMissing`.\n if (!isApp && headRefProblem === null) {\n if (member.headRef === null) {\n violations.push({ kind: 'headRefMissing', spaceId });\n } else if (!headRefPresentInGraph(member, member.headRef.hash)) {\n violations.push({ kind: 'headRefNotInGraph', spaceId, hash: member.headRef.hash });\n }\n }\n }\n\n if (opts?.declaredExtensions !== undefined) {\n violations.push(...layoutViolations(input.spaces, opts.declaredExtensions));\n }\n\n if (opts?.checkContracts === true) {\n violations.push(...contractViolations(input));\n }\n\n return violations;\n}\n\nexport function loadProblemToViolation(\n spaceId: string,\n problem: PackageLoadProblem,\n): IntegrityViolation {\n switch (problem.kind) {\n case 'hashMismatch':\n return {\n kind: 'hashMismatch',\n spaceId,\n dirName: problem.dirName,\n stored: problem.stored,\n computed: problem.computed,\n };\n case 'providedInvariantsMismatch':\n return { kind: 'providedInvariantsMismatch', spaceId, dirName: problem.dirName };\n case 'packageUnloadable':\n return {\n kind: 'packageUnloadable',\n spaceId,\n dirName: problem.dirName,\n detail: problem.detail,\n };\n }\n}\n\nfunction duplicateMigrationHashViolations(\n spaceId: string,\n packages: readonly OnDiskMigrationPackage[],\n): readonly IntegrityViolation[] {\n const dirNamesByHash = new Map<string, string[]>();\n for (const pkg of packages) {\n const hash = pkg.metadata.migrationHash;\n const dirNames = dirNamesByHash.get(hash);\n if (dirNames) dirNames.push(pkg.dirName);\n else dirNamesByHash.set(hash, [pkg.dirName]);\n }\n\n const out: IntegrityViolation[] = [];\n for (const [migrationHash, dirNames] of dirNamesByHash) {\n if (dirNames.length > 1) {\n out.push({\n kind: 'duplicateMigrationHash',\n spaceId,\n migrationHash,\n dirNames: [...dirNames].sort(),\n });\n }\n }\n return out;\n}\n\n/**\n * Whether a space's head-ref hash is present in its reconstructed graph.\n * An empty graph is reachable only by the empty-contract sentinel.\n */\nfunction headRefPresentInGraph(member: ContractSpaceMember, headHash: string): boolean {\n const graph = member.graph();\n if (graph.nodes.size === 0) {\n return headHash === EMPTY_CONTRACT_HASH;\n }\n return graph.nodes.has(headHash);\n}\n\nfunction layoutViolations(\n spaces: readonly IntegritySpaceState[],\n declaredExtensions: readonly DeclaredExtensionEntry[],\n): readonly IntegrityViolation[] {\n const out: IntegrityViolation[] = [];\n const extensionSpaceIds = new Set(spaces.filter((s) => !s.isApp).map((s) => s.member.spaceId));\n const declaredIds = new Set(declaredExtensions.map((d) => d.id));\n\n for (const id of [...extensionSpaceIds].sort()) {\n if (!declaredIds.has(id)) {\n out.push({ kind: 'orphanSpaceDir', spaceId: id });\n }\n }\n for (const id of [...declaredIds].sort()) {\n if (!extensionSpaceIds.has(id)) {\n out.push({ kind: 'declaredButUnmigrated', spaceId: id });\n }\n }\n return out;\n}\n\nfunction contractViolations(input: IntegrityComputationInput): readonly IntegrityViolation[] {\n const out: IntegrityViolation[] = [];\n const elementClaimedBy = new Map<string, string[]>();\n\n for (const { member } of input.spaces) {\n let contract: ReturnType<ContractSpaceMember['contract']>;\n try {\n contract = member.contract();\n } catch (error) {\n out.push({ kind: 'contractUnreadable', spaceId: member.spaceId, detail: detailOf(error) });\n continue;\n }\n\n if (contract.target !== input.targetId) {\n out.push({\n kind: 'targetMismatch',\n spaceId: member.spaceId,\n expected: input.targetId,\n actual: contract.target,\n });\n }\n\n for (const { entityName: elementName } of elementCoordinates(contract.storage)) {\n const claimers = elementClaimedBy.get(elementName);\n if (claimers) claimers.push(member.spaceId);\n else elementClaimedBy.set(elementName, [member.spaceId]);\n }\n }\n\n const disjointness: IntegrityViolation[] = [];\n for (const [element, claimedBy] of elementClaimedBy) {\n if (claimedBy.length > 1) {\n disjointness.push({ kind: 'disjointness', element, claimedBy: [...claimedBy].sort() });\n }\n }\n disjointness.sort((a, b) =>\n a.kind === 'disjointness' && b.kind === 'disjointness' ? a.element.localeCompare(b.element) : 0,\n );\n out.push(...disjointness);\n return out;\n}\n\nfunction detailOf(error: unknown): string {\n if (MigrationToolsError.is(error)) return error.why;\n if (error instanceof Error) return error.message;\n return String(error);\n}\n","import type { Contract } from '@prisma-next/contract/types';\nimport { MigrationToolsError } from '../errors';\nimport { readMigrationsDir } from '../io';\nimport { readContractSpaceContract } from '../read-contract-space-contract';\nimport { readContractSpaceHeadRef } from '../read-contract-space-head-ref';\nimport { HEAD_REF_NAME, type RefLoadProblem, readRefsTolerant } from '../refs';\nimport {\n APP_SPACE_ID,\n isValidSpaceId,\n RESERVED_SPACE_SUBDIR_NAMES,\n spaceMigrationDirectory,\n spaceRefsDirectory,\n} from '../space-layout';\nimport { listContractSpaceDirectories } from '../verify-contract-spaces';\nimport { createContractSpaceAggregate, createContractSpaceMember } from './aggregate';\nimport { computeIntegrityViolations, type IntegritySpaceState } from './check-integrity';\nimport type { ContractSpaceAggregate } from './types';\n\nexport type { DeclaredExtensionEntry } from '../integrity-violation';\n\n/**\n * Inputs for {@link loadContractSpaceAggregate}.\n *\n * Construction reads migration **state** from disk (`migrations/<space>/`\n * packages + refs + head refs). The app's *live* contract is not a disk\n * artefact — in Prisma Next it is always compiled from the project's\n * central contract, so the caller always has it and threads it in as\n * `appContract`. `deserializeContract` is held and called lazily only for\n * the on-disk extension contracts (`migrations/<ext>/contract.json`).\n */\nexport interface LoadAggregateInput {\n readonly migrationsDir: string;\n readonly deserializeContract: (raw: unknown) => Contract;\n readonly appContract: Contract;\n}\n\n/**\n * Build a tolerant, queryable {@link ContractSpaceAggregate} from on-disk\n * migration state plus the caller's live app contract.\n *\n * Building **never throws on disk content**: a hash- or\n * invariants-mismatched package is retained, an unparseable package is\n * omitted, a missing extension head ref leaves `headRef: null`, and an\n * unreadable on-disk contract defers its failure to `member.contract()`.\n * Every such problem is judged by {@link ContractSpaceAggregate.checkIntegrity}\n * rather than aborting the load. The only rejections are catastrophic I/O\n * (a `migrations/` that exists but is unreadable for reasons other than\n * absence).\n *\n * The app space's head ref is synthesised from the live contract's\n * storage hash (the app contract is authored independently of the\n * migration graph), and `app.contract()` returns the supplied contract.\n * Extension spaces read their contract, refs, and head ref from disk.\n */\nexport async function loadContractSpaceAggregate(\n input: LoadAggregateInput,\n): Promise<ContractSpaceAggregate> {\n const { migrationsDir, deserializeContract, appContract } = input;\n const targetId = appContract.target;\n\n const appState = await loadAppSpace(migrationsDir, appContract, deserializeContract);\n const extensionStates = await loadExtensionSpaces(migrationsDir, deserializeContract);\n\n const spaces: readonly IntegritySpaceState[] = [appState, ...extensionStates];\n\n return createContractSpaceAggregate({\n targetId,\n app: appState.member,\n extensions: extensionStates.map((state) => state.member),\n checkIntegrity: (opts) => computeIntegrityViolations({ targetId, spaces }, opts),\n });\n}\n\nasync function loadAppSpace(\n migrationsDir: string,\n appContract: Contract,\n deserializeContract: (raw: unknown) => Contract,\n): Promise<IntegritySpaceState> {\n const spaceDir = spaceMigrationDirectory(migrationsDir, APP_SPACE_ID);\n const { packages, problems } = await readMigrationsDir(spaceDir);\n const { refs, problems: refProblems } = await readRefsTolerant(spaceRefsDirectory(spaceDir));\n\n const member = createContractSpaceMember({\n spaceId: APP_SPACE_ID,\n packages,\n refs,\n headRef: { hash: appContract.storage.storageHash, invariants: [] },\n refsDir: spaceRefsDirectory(spaceDir),\n resolveContract: () => appContract,\n deserializeContract,\n });\n\n // The app head ref is synthesised from the live contract, so there is\n // no on-disk head.json to be missing or corrupt for it.\n return { member, problems, refProblems, headRefProblem: null, isApp: true };\n}\n\nasync function loadExtensionSpaces(\n migrationsDir: string,\n deserializeContract: (raw: unknown) => Contract,\n): Promise<readonly IntegritySpaceState[]> {\n const candidateDirs = await listContractSpaceDirectories(migrationsDir);\n const extensionIds = candidateDirs\n .filter((name) => name !== APP_SPACE_ID)\n .filter((name) => !RESERVED_SPACE_SUBDIR_NAMES.has(name))\n .filter(isValidSpaceId)\n .sort();\n\n const states: IntegritySpaceState[] = [];\n for (const spaceId of extensionIds) {\n states.push(await loadExtensionSpace(migrationsDir, spaceId, deserializeContract));\n }\n return states;\n}\n\nasync function loadExtensionSpace(\n migrationsDir: string,\n spaceId: string,\n deserializeContract: (raw: unknown) => Contract,\n): Promise<IntegritySpaceState> {\n const spaceDir = spaceMigrationDirectory(migrationsDir, spaceId);\n const { packages, problems } = await readMigrationsDir(spaceDir);\n const { refs, problems: refProblems } = await readRefsTolerant(spaceRefsDirectory(spaceDir));\n const { headRef, problem: headRefProblem } = await readHeadRefTolerant(migrationsDir, spaceId);\n const rawContract = await readRawContractDeferred(migrationsDir, spaceId);\n\n const member = createContractSpaceMember({\n spaceId,\n packages,\n refs,\n headRef,\n refsDir: spaceRefsDirectory(spaceDir),\n resolveContract: () => deserializeContract(rawContract()),\n deserializeContract,\n });\n\n return { member, problems, refProblems, headRefProblem, isApp: false };\n}\n\n/**\n * The result of resolving an extension's `refs/head.json`: the parsed\n * head ref (or `null` when the file is absent or corrupt) plus a problem\n * when the file exists but cannot be parsed.\n */\ninterface HeadRefReadResult {\n readonly headRef: Awaited<ReturnType<typeof readContractSpaceHeadRef>>;\n readonly problem: RefLoadProblem | null;\n}\n\n/**\n * Read an extension's head ref, distinguishing a *genuinely absent*\n * `head.json` (`headRef: null`, no problem — judged `headRefMissing`)\n * from one that *exists but cannot be parsed* (`headRef: null` plus a\n * problem — judged `refUnreadable`, not `headRefMissing`).\n * `readContractSpaceHeadRef` already returns `null` only for ENOENT and\n * throws for unparseable / schema-invalid content, so the throw is the\n * corruption signal. Construction never throws on disk content.\n */\nfunction isToleratedRefHeadReadError(error: unknown): boolean {\n if (MigrationToolsError.is(error)) return true;\n if (!(error instanceof Error)) return false;\n const code = (error as NodeJS.ErrnoException).code;\n return code === 'ENOENT' || code === 'EISDIR';\n}\n\nasync function readHeadRefTolerant(\n migrationsDir: string,\n spaceId: string,\n): Promise<HeadRefReadResult> {\n try {\n const headRef = await readContractSpaceHeadRef(migrationsDir, spaceId);\n return { headRef, problem: null };\n } catch (error) {\n if (!isToleratedRefHeadReadError(error)) {\n throw error;\n }\n return { headRef: null, problem: { refName: HEAD_REF_NAME, detail: detailOf(error) } };\n }\n}\n\nfunction detailOf(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n/**\n * Read the raw on-disk contract eagerly (cheap I/O) but defer its\n * (throwing) failure to call time, so a missing or unparseable\n * `contract.json` becomes a `contract()` throw — surfaced as\n * `contractUnreadable` — rather than a construction failure.\n */\nasync function readRawContractDeferred(\n migrationsDir: string,\n spaceId: string,\n): Promise<() => unknown> {\n try {\n const raw = await readContractSpaceContract(migrationsDir, spaceId);\n return () => raw;\n } catch (error) {\n return () => {\n throw error;\n };\n }\n}\n","import type { MigrationPlan } from '@prisma-next/framework-components/control';\nimport { EMPTY_CONTRACT_HASH } from '../../constants';\nimport { findPathWithDecision } from '../../migration-graph';\nimport type { MigrationOps, OnDiskMigrationPackage } from '../../package';\nimport { requireHeadRef } from '../aggregate';\nimport type { ContractMarkerRecordLike } from '../marker-types';\nimport type { PerSpacePlan } from '../planner-types';\nimport type { ContractSpaceMember } from '../types';\n\n/**\n * Outcome variants for the graph-walk strategy. Mirrors\n * {@link import('../../compute-extension-space-apply-path').ExtensionSpaceApplyPathOutcome}\n * but operates against the member's lazily-reconstructed `graph()`\n * instead of re-reading from disk. The aggregate planner converts\n * these into {@link import('../planner-types').PlannerError}\n * variants.\n */\nexport type GraphWalkOutcome =\n | { readonly kind: 'ok'; readonly result: PerSpacePlan }\n | { readonly kind: 'unreachable' }\n | { readonly kind: 'unsatisfiable'; readonly missing: readonly string[] };\n\nexport interface GraphWalkStrategyInputs {\n readonly aggregateTargetId: string;\n readonly member: ContractSpaceMember;\n readonly currentMarker: ContractMarkerRecordLike | null;\n /**\n * Optional ref name to decorate the resulting `PathDecision`. Used by\n * `migrate` to surface the user-supplied `--to <name>` in\n * structured-progress events and invariant-path error envelopes. The\n * strategy itself does not interpret it.\n */\n readonly refName?: string;\n}\n\n/**\n * Walk a member's hydrated migration graph from the live marker to\n * `member.headRef.hash`, covering every required invariant.\n *\n * Pure synchronous function — no I/O. The aggregate's loader has\n * already integrity-checked every package and reconstructed the graph;\n * this strategy just looks up ops by `migrationHash` and assembles a\n * `MigrationPlan` with `targetId` set from the aggregate (no\n * placeholder cast).\n *\n * Required invariants are computed as `headRef.invariants \\ marker.invariants`\n * — the marker already declares some invariants satisfied; the path\n * only needs to provide the remainder. Mirrors today's\n * `computeExtensionSpaceApplyPath` semantics.\n */\nexport function graphWalkStrategy(input: GraphWalkStrategyInputs): GraphWalkOutcome {\n const { aggregateTargetId, member, currentMarker, refName } = input;\n const headRef = requireHeadRef(member);\n const graph = member.graph();\n const packagesByMigrationHash = new Map<string, OnDiskMigrationPackage>(\n member.packages.map((pkg) => [pkg.metadata.migrationHash, pkg]),\n );\n\n const fromHash = currentMarker?.storageHash ?? EMPTY_CONTRACT_HASH;\n const markerInvariants = new Set(currentMarker?.invariants ?? []);\n const required = new Set(headRef.invariants.filter((id) => !markerInvariants.has(id)));\n\n const outcome = findPathWithDecision(graph, fromHash, headRef.hash, {\n required,\n ...(refName !== undefined ? { refName } : {}),\n });\n\n if (outcome.kind === 'unreachable') {\n return { kind: 'unreachable' };\n }\n if (outcome.kind === 'unsatisfiable') {\n return { kind: 'unsatisfiable', missing: outcome.missing };\n }\n\n const pathOps: MigrationOps[number][] = [];\n const providedInvariantsSet = new Set<string>();\n const edgeRefs: Array<{\n migrationHash: string;\n dirName: string;\n from: string;\n to: string;\n operationCount: number;\n }> = [];\n for (const edge of outcome.decision.selectedPath) {\n const pkg = packagesByMigrationHash.get(edge.migrationHash);\n if (!pkg) {\n throw new Error(\n `Migration package missing for edge ${edge.migrationHash} in space \"${member.spaceId}\". The hydrated migration graph and packagesByMigrationHash map are out of sync — this should be unreachable; report.`,\n );\n }\n for (const op of pkg.ops) pathOps.push(op);\n for (const invariant of pkg.metadata.providedInvariants) providedInvariantsSet.add(invariant);\n edgeRefs.push({\n migrationHash: edge.migrationHash,\n dirName: edge.dirName,\n from: edge.from,\n to: edge.to,\n operationCount: pkg.ops.length,\n });\n }\n\n const plan: MigrationPlan = {\n targetId: aggregateTargetId,\n spaceId: member.spaceId,\n origin: currentMarker === null ? null : { storageHash: currentMarker.storageHash },\n destination: { storageHash: headRef.hash },\n operations: pathOps,\n providedInvariants: [...providedInvariantsSet].sort(),\n };\n\n return {\n kind: 'ok',\n result: {\n plan,\n displayOps: pathOps,\n destinationContract: member.contract(),\n strategy: 'graph-walk',\n migrationEdges: edgeRefs,\n pathDecision: outcome.decision,\n },\n };\n}\n","import { elementCoordinates } from '@prisma-next/framework-components/ir';\nimport type { ContractSpaceMember } from './types';\n\n/**\n * Project the **introspected live schema** to the slice claimed by a\n * single contract-space member.\n *\n * \"Schema\" here means the live introspected database state — the\n * planner / verifier sees this object as a `MongoSchemaIR` (Mongo) or\n * `SqlSchemaIR` (SQL). It is **not** a database schema in the SQL\n * `CREATE SCHEMA` sense, nor a contract-space namespace. The\n * function's job is to filter that introspected state down to the\n * elements claimed by one space, so a per-space verify pass doesn't\n * see another space's storage as \"extras\".\n *\n * Returns the same `schema` value with every top-level storage element\n * (table or collection) claimed by **other** members of the aggregate\n * removed. Elements not claimed by any member flow through unchanged —\n * the planner / verifier sees them as orphans (extras in strict mode).\n *\n * Used by:\n *\n * - The aggregate planner's **synth strategy**: when synthesising a\n * plan against a member's contract, the live schema must be projected\n * to that member's slice so the planner doesn't treat elements claimed\n * by other members as \"extras\" and emit destructive ops to drop them.\n * - The aggregate verifier's **schemaCheck**: projects per member so the\n * single-contract verify only sees the slice claimed by the member it\n * is checking. Closes the architectural concern that a multi-member\n * deployment makes each member's elements look like extras to every\n * other member's verify pass.\n *\n * **Duck-typing semantics**: the helper operates on `unknown` for the\n * schema and falls through structurally if the shape doesn't match.\n * Two storage shapes are recognised today:\n *\n * - SQL families expose `storage.tables: Record<string, ...>` on\n * contracts and the introspected schema mirrors the same record shape.\n * Pruning iterates the record entries.\n * - Mongo exposes `storage.collections: Record<string, ...>` on\n * contracts; the introspected `MongoSchemaIR` exposes\n * `collections: ReadonlyArray<{name: string, ...}>`. Pruning iterates\n * the array on the schema side and the record's keys on the\n * other-member side.\n *\n * Schemas of unrecognised shape are returned unchanged. The function\n * never imports family classes (`SqlSchemaIR`, `MongoSchemaIR`); the\n * projected schema is a plain object — `{...schema, tables: pruned}` or\n * `{...schema, collections: pruned}` — that downstream consumers\n * duck-type. A future family with a different storage shape gets the\n * schema returned unchanged rather than blowing up the aggregate\n * planner.\n *\n * Record-shape detection guards against arrays (`!Array.isArray`) so\n * an unrecognised array-shaped value falls through unchanged rather\n * than being pruned by numeric keys.\n */\nexport function projectSchemaToSpace(\n schema: unknown,\n member: ContractSpaceMember,\n otherMembers: ReadonlyArray<ContractSpaceMember>,\n): unknown {\n if (typeof schema !== 'object' || schema === null) return schema;\n\n const ownedByOthers = collectOwnedNames(member, otherMembers);\n if (ownedByOthers.size === 0) return schema;\n\n const schemaObj = schema as { readonly tables?: unknown; readonly collections?: unknown };\n\n if (\n typeof schemaObj.tables === 'object' &&\n schemaObj.tables !== null &&\n !Array.isArray(schemaObj.tables)\n ) {\n return pruneRecord(schemaObj, 'tables', ownedByOthers);\n }\n\n if (Array.isArray(schemaObj.collections)) {\n return pruneCollectionsArray(schemaObj, ownedByOthers);\n }\n\n if (\n typeof schemaObj.collections === 'object' &&\n schemaObj.collections !== null &&\n !Array.isArray(schemaObj.collections)\n ) {\n return pruneRecord(schemaObj, 'collections', ownedByOthers);\n }\n\n return schema;\n}\n\nfunction collectOwnedNames(\n member: ContractSpaceMember,\n otherMembers: ReadonlyArray<ContractSpaceMember>,\n): Set<string> {\n const owned = new Set<string>();\n for (const other of otherMembers) {\n if (other.spaceId === member.spaceId) continue;\n for (const { entityName } of elementCoordinates(other.contract().storage)) {\n owned.add(entityName);\n }\n }\n return owned;\n}\n\nfunction pruneRecord(\n schemaObj: { readonly tables?: unknown; readonly collections?: unknown },\n field: 'tables' | 'collections',\n ownedByOthers: ReadonlySet<string>,\n): unknown {\n const source = schemaObj[field] as Record<string, unknown>;\n let removed = false;\n const pruned: Record<string, unknown> = {};\n for (const [name, value] of Object.entries(source)) {\n if (ownedByOthers.has(name)) {\n removed = true;\n } else {\n pruned[name] = value;\n }\n }\n if (!removed) return schemaObj;\n return { ...schemaObj, [field]: pruned };\n}\n\nfunction pruneCollectionsArray(\n schemaObj: { readonly collections?: unknown },\n ownedByOthers: ReadonlySet<string>,\n): unknown {\n const source = schemaObj.collections as ReadonlyArray<unknown>;\n let removed = false;\n const pruned: unknown[] = [];\n for (const entry of source) {\n if (typeof entry === 'object' && entry !== null) {\n const name = (entry as { readonly name?: unknown }).name;\n if (typeof name === 'string' && ownedByOthers.has(name)) {\n removed = true;\n continue;\n }\n }\n pruned.push(entry);\n }\n if (!removed) return schemaObj;\n return { ...schemaObj, collections: pruned };\n}\n","import type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';\nimport type {\n ControlFamilyInstance,\n MigrationOperationPolicy,\n MigrationPlan,\n MigrationPlannerConflict,\n MigrationPlannerResult,\n TargetMigrationsCapability,\n} from '@prisma-next/framework-components/control';\nimport type { PerSpacePlan } from '../planner-types';\nimport { projectSchemaToSpace } from '../project-schema-to-space';\nimport type { ContractSpaceMember } from '../types';\n\nexport interface SynthStrategyInputs<TFamilyId extends string, TTargetId extends string> {\n readonly aggregateTargetId: string;\n readonly member: ContractSpaceMember;\n readonly otherMembers: ReadonlyArray<ContractSpaceMember>;\n readonly schemaIntrospection: unknown;\n readonly familyInstance: ControlFamilyInstance<TFamilyId, unknown>;\n readonly migrations: TargetMigrationsCapability<\n TFamilyId,\n TTargetId,\n ControlFamilyInstance<TFamilyId, unknown>\n >;\n readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<TFamilyId, TTargetId>>;\n readonly operationPolicy: MigrationOperationPolicy;\n}\n\nexport type SynthStrategyOutcome =\n | { readonly kind: 'ok'; readonly result: PerSpacePlan }\n | { readonly kind: 'failure'; readonly conflicts: readonly MigrationPlannerConflict[] };\n\n/**\n * The {@link MigrationPlanner.plan} interface is declared as synchronous,\n * but historical and test fixture call sites have always invoked it\n * with `await` (see prior `db-apply-per-space.ts`). Tolerating a\n * Promise here keeps existing test mocks working without changing the\n * declared family SPI.\n */\ntype MaybeAsyncPlannerResult = MigrationPlannerResult | Promise<MigrationPlannerResult>;\n\n/**\n * Synthesise a migration plan for a single member by projecting the\n * live schema down to that member's claimed slice and delegating to\n * the family's `createPlanner(...).plan(...)`.\n *\n * Pre-projection (via {@link projectSchemaToSpace}) closes the F23\n * concern: without it, the family's planner sees other members'\n * tables as \"extras\" and emits destructive ops to drop them. With it,\n * the planner only sees the slice this member claims.\n *\n * The synthesised plan's `targetId` is set from `aggregateTargetId`\n * (the aggregate's ambient target). The family's planner does not\n * stamp `targetId` on the produced plan; the aggregate planner is\n * the single point that knows the target.\n *\n * Used by:\n *\n * - The app member by default (CLI policy\n * `ignoreGraphFor: { app.spaceId }`).\n * - Any extension member whose `headRef.invariants` is empty (the\n * strategy selector falls back to synth when graph-walk isn't\n * required).\n */\nexport async function synthStrategy<TFamilyId extends string, TTargetId extends string>(\n input: SynthStrategyInputs<TFamilyId, TTargetId>,\n): Promise<SynthStrategyOutcome> {\n const projectedSchema = projectSchemaToSpace(\n input.schemaIntrospection,\n input.member,\n input.otherMembers,\n );\n\n const planner = input.migrations.createPlanner(input.familyInstance);\n const plannerResult: MigrationPlannerResult = await (planner.plan({\n contract: input.member.contract(),\n schema: projectedSchema,\n policy: input.operationPolicy,\n fromContract: null,\n frameworkComponents: input.frameworkComponents,\n spaceId: input.member.spaceId,\n }) as MaybeAsyncPlannerResult);\n\n if (plannerResult.kind === 'failure') {\n return { kind: 'failure', conflicts: plannerResult.conflicts };\n }\n\n const synthedPlan = plannerResult.plan;\n // The family planner returns a class-instance-shaped plan whose\n // `destination` / `operations` are accessors on the prototype, often\n // backed by private fields. A naive spread (`{ ...synthedPlan }`)\n // would lose those accessors and produce a plan with\n // `destination: undefined`; rebinding the prototype on a plain\n // object would break private-field access. We instead wrap the plan\n // in a Proxy that forwards every read except `targetId`, which is\n // stamped from the aggregate's ambient target. This preserves the\n // planner's class semantics while keeping the aggregate the single\n // source of truth for `targetId`.\n const plan: MigrationPlan = new Proxy(synthedPlan, {\n get(target, prop) {\n if (prop === 'targetId') return input.aggregateTargetId;\n // Forward `this` as the original target so prototype-bound\n // private fields (#destination, #operations, …) resolve.\n return Reflect.get(target, prop, target);\n },\n has(target, prop) {\n if (prop === 'targetId') return true;\n return Reflect.has(target, prop);\n },\n });\n\n return {\n kind: 'ok',\n result: {\n plan,\n displayOps: synthedPlan.operations,\n destinationContract: input.member.contract(),\n strategy: 'synth',\n },\n };\n}\n","import { notOk, ok } from '@prisma-next/utils/result';\nimport { requireHeadRef } from './aggregate';\nimport type { PerSpacePlan, PlannerError, PlannerInput, PlannerOutput } from './planner-types';\nimport { graphWalkStrategy } from './strategies/graph-walk';\nimport { synthStrategy } from './strategies/synth';\nimport type { ContractSpaceMember } from './types';\n\nexport type {\n AggregateCurrentDBState,\n AggregateMigrationEdgeRef,\n CallerPolicy,\n PerSpacePlan,\n PlannerError,\n PlannerInput,\n PlannerOutput,\n PlannerSuccess,\n} from './planner-types';\n\n/**\n * Plan a migration across every member of a {@link ContractSpaceAggregate}.\n *\n * Strategy selection per member, in order; first match wins:\n *\n * 1. If `callerPolicy.ignoreGraphFor.has(member.spaceId)`:\n * - If `member.headRef.invariants` is empty → synth.\n * - Else → `policyConflict` (synth cannot satisfy authored invariants).\n * 2. Else if `member.graph()` is non-empty AND graph-walk\n * succeeds → graph-walk.\n * 3. Else if `member.headRef.invariants` is empty → synth.\n * 4. Else → graph-walk failure → `extensionPathUnreachable` /\n * `extensionPathUnsatisfiable`.\n *\n * Output `applyOrder` is `[...aggregate.extensions.map(spaceId), aggregate.app.spaceId]`\n * — extensions alphabetical, then app — matching today's\n * `concatenateSpaceApplyInputs` ordering. This preserves\n * `MigrationRunnerFailure.failingSpace` attribution byte-for-byte.\n *\n * Every emitted `MigrationPlan` has `targetId = aggregate.targetId`.\n * No placeholder cast; no patch step.\n */\nexport async function planMigration<TFamilyId extends string, TTargetId extends string>(\n input: PlannerInput<TFamilyId, TTargetId>,\n): Promise<PlannerOutput> {\n const { aggregate, currentDBState, callerPolicy } = input;\n const allMembers: ReadonlyArray<ContractSpaceMember> = [aggregate.app, ...aggregate.extensions];\n\n const perSpace = new Map<string, PerSpacePlan>();\n\n // Iterate in apply order so a per-member error short-circuits the\n // walk in the same order the runner would walk inputs.\n const orderedMembers: ReadonlyArray<ContractSpaceMember> = [\n ...aggregate.extensions,\n aggregate.app,\n ];\n\n for (const member of orderedMembers) {\n const otherMembers = allMembers.filter((m) => m.spaceId !== member.spaceId);\n const currentMarker = currentDBState.markersBySpaceId.get(member.spaceId) ?? null;\n const headRef = requireHeadRef(member);\n\n const ignoreGraph = callerPolicy.ignoreGraphFor.has(member.spaceId);\n const invariantsRequired = headRef.invariants.length > 0;\n\n if (ignoreGraph && invariantsRequired) {\n const conflict: PlannerError = {\n kind: 'policyConflict',\n spaceId: member.spaceId,\n detail: `\\`callerPolicy.ignoreGraphFor\\` requested for space \"${member.spaceId}\", but the member declares non-empty head-ref invariants (${headRef.invariants.join(', ')}). Synthesising a plan from the contract IR cannot satisfy authored invariants — the graph must be walked. Either remove \"${member.spaceId}\" from \\`ignoreGraphFor\\` or amend the on-disk head ref to declare zero invariants.`,\n };\n return notOk(conflict);\n }\n\n if (ignoreGraph) {\n const synthOutcome = await synthStrategy({\n aggregateTargetId: aggregate.targetId,\n member,\n otherMembers,\n schemaIntrospection: currentDBState.schemaIntrospection,\n familyInstance: input.familyInstance,\n migrations: input.migrations,\n frameworkComponents: input.frameworkComponents,\n operationPolicy: input.operationPolicy,\n });\n if (synthOutcome.kind === 'failure') {\n return notOk({\n kind: 'appSynthFailure',\n spaceId: member.spaceId,\n conflicts: synthOutcome.conflicts,\n });\n }\n perSpace.set(member.spaceId, synthOutcome.result);\n continue;\n }\n\n // Try graph-walk first when the graph has nodes; fall back to synth\n // when the graph is empty AND no invariants are required.\n if (member.graph().nodes.size > 0) {\n const walked = graphWalkStrategy({\n aggregateTargetId: aggregate.targetId,\n member,\n currentMarker,\n });\n if (walked.kind === 'ok') {\n perSpace.set(member.spaceId, walked.result);\n continue;\n }\n if (walked.kind === 'unreachable') {\n return notOk({\n kind: 'extensionPathUnreachable',\n spaceId: member.spaceId,\n target: headRef.hash,\n });\n }\n // unsatisfiable — surface\n return notOk({\n kind: 'extensionPathUnsatisfiable',\n spaceId: member.spaceId,\n missingInvariants: walked.missing,\n });\n }\n\n // Empty graph: synth is the only option, and it can only satisfy\n // empty-invariant members.\n if (invariantsRequired) {\n return notOk({\n kind: 'extensionPathUnsatisfiable',\n spaceId: member.spaceId,\n missingInvariants: [...headRef.invariants].sort(),\n });\n }\n\n const synthOutcome = await synthStrategy({\n aggregateTargetId: aggregate.targetId,\n member,\n otherMembers,\n schemaIntrospection: currentDBState.schemaIntrospection,\n familyInstance: input.familyInstance,\n migrations: input.migrations,\n frameworkComponents: input.frameworkComponents,\n operationPolicy: input.operationPolicy,\n });\n if (synthOutcome.kind === 'failure') {\n return notOk({\n kind: 'appSynthFailure',\n spaceId: member.spaceId,\n conflicts: synthOutcome.conflicts,\n });\n }\n perSpace.set(member.spaceId, synthOutcome.result);\n }\n\n return ok({\n perSpace,\n applyOrder: [...aggregate.extensions.map((m) => m.spaceId), aggregate.app.spaceId],\n });\n}\n","import { elementCoordinates } from '@prisma-next/framework-components/ir';\nimport type { Result } from '@prisma-next/utils/result';\nimport { notOk, ok } from '@prisma-next/utils/result';\nimport { requireHeadRef } from './aggregate';\nimport type { ContractMarkerRecordLike } from './marker-types';\nimport { projectSchemaToSpace } from './project-schema-to-space';\nimport type { ContractSpaceAggregate, ContractSpaceMember } from './types';\n\n/**\n * Caller policy for the verifier. Today's only knob is\n * `mode`: `strict` treats orphan elements (live tables not claimed by\n * any aggregate member) as errors; `lenient` treats them as\n * informational. Maps directly to `db verify --strict`.\n */\nexport interface VerifierInput<TSchemaResult> {\n readonly aggregate: ContractSpaceAggregate;\n readonly markersBySpaceId: ReadonlyMap<string, ContractMarkerRecordLike | null>;\n readonly schemaIntrospection: unknown;\n readonly mode: 'strict' | 'lenient';\n /**\n * Caller-supplied per-space schema verifier. The CLI wires this to\n * the family's `verifySqlSchema` (SQL) / equivalent (other\n * families). The verifier projects the schema to the\n * member's slice via {@link projectSchemaToSpace} before invoking\n * the callback, so single-contract semantics are preserved.\n *\n * Typed structurally with a generic `TSchemaResult` so the\n * migration-tools layer doesn't depend on the SQL family's\n * `VerifySqlSchemaResult`. CLI callers pass the family's type\n * through unchanged.\n */\n readonly verifySchemaForMember: (\n projectedSchema: unknown,\n member: ContractSpaceMember,\n mode: 'strict' | 'lenient',\n ) => TSchemaResult;\n}\n\n/**\n * Marker-check result per member. Mirrors the four cases the\n * `verifyContractSpaces` primitive surfaces today, plus an `'absent'`\n * case for greenfield spaces (no marker row written yet — `db init`\n * not run).\n */\nexport type MarkerCheckResult =\n | { readonly kind: 'ok' }\n | { readonly kind: 'absent' }\n | {\n readonly kind: 'hashMismatch';\n readonly markerHash: string;\n readonly expected: string;\n }\n | { readonly kind: 'missingInvariants'; readonly missing: readonly string[] };\n\nexport interface MarkerCheckSection {\n readonly perSpace: ReadonlyMap<string, MarkerCheckResult>;\n readonly orphanMarkers: readonly {\n readonly spaceId: string;\n readonly row: ContractMarkerRecordLike;\n }[];\n}\n\n/**\n * A live storage element (today: a top-level table) not claimed by any\n * member of the aggregate. The verifier always reports these;\n * the caller decides what to do — `db verify --strict` treats them as\n * errors, the lenient default treats them as informational.\n *\n * Today only `kind: 'table'` exists. The discriminated shape leaves\n * room for orphan columns / indexes / sequences in the future without\n * breaking the type contract.\n */\nexport type OrphanElement = { readonly kind: 'table'; readonly name: string };\n\nexport interface SchemaCheckSection<TSchemaResult> {\n readonly perSpace: ReadonlyMap<string, TSchemaResult>;\n /**\n * Live elements present in the introspected schema that are not\n * claimed by **any** aggregate member. Sorted alphabetically by name.\n */\n readonly orphanElements: readonly OrphanElement[];\n}\n\nexport interface VerifierSuccess<TSchemaResult> {\n readonly markerCheck: MarkerCheckSection;\n readonly schemaCheck: SchemaCheckSection<TSchemaResult>;\n}\n\nexport type VerifierError = {\n readonly kind: 'introspectionFailure';\n readonly detail: string;\n};\n\nexport type VerifierOutput<TSchemaResult> = Result<VerifierSuccess<TSchemaResult>, VerifierError>;\n\n/**\n * Verify a {@link ContractSpaceAggregate} against the live database\n * state. Bundles two checks:\n *\n * - `markerCheck` per member: compare the live marker row against the\n * member's `headRef.hash` + `headRef.invariants`. Absence is a\n * distinct kind, not an error (callers — `db verify` strict vs\n * `db init` precondition — choose how to interpret it).\n * - `schemaCheck` per member: project the live schema to the slice\n * the member claims via {@link projectSchemaToSpace}, then delegate\n * to the caller-supplied `verifySchemaForMember`. The pre-projection\n * means the family's single-contract verifier no longer sees other\n * members' tables as `extras`, so a multi-member deployment never\n * surfaces cross-member tables as orphaned schema elements.\n *\n * `markerCheck.orphanMarkers` lists every marker row whose `space` is\n * not a member of the aggregate. `db verify` callers reject orphans;\n * future tooling may not.\n *\n * Pure synchronous function; no I/O. The caller (CLI) gathers\n * `markersBySpaceId` and `schemaIntrospection` ahead of the call.\n */\nexport function verifyMigration<TSchemaResult>(\n input: VerifierInput<TSchemaResult>,\n): VerifierOutput<TSchemaResult> {\n try {\n return runVerifyMigration(input);\n } catch (error) {\n return notOk({\n kind: 'introspectionFailure',\n detail: error instanceof Error ? error.message : String(error),\n });\n }\n}\n\nfunction runVerifyMigration<TSchemaResult>(\n input: VerifierInput<TSchemaResult>,\n): VerifierOutput<TSchemaResult> {\n const { aggregate, markersBySpaceId, schemaIntrospection, mode, verifySchemaForMember } = input;\n const allMembers: ReadonlyArray<ContractSpaceMember> = [aggregate.app, ...aggregate.extensions];\n const memberSpaceIds = new Set(allMembers.map((m) => m.spaceId));\n\n // Marker check per member.\n const markerPerSpace = new Map<string, MarkerCheckResult>();\n for (const member of allMembers) {\n const marker = markersBySpaceId.get(member.spaceId) ?? null;\n if (marker === null) {\n markerPerSpace.set(member.spaceId, { kind: 'absent' });\n continue;\n }\n const headRef = requireHeadRef(member);\n if (marker.storageHash !== headRef.hash) {\n markerPerSpace.set(member.spaceId, {\n kind: 'hashMismatch',\n markerHash: marker.storageHash,\n expected: headRef.hash,\n });\n continue;\n }\n const markerInvariants = new Set(marker.invariants);\n const missing = headRef.invariants.filter((id) => !markerInvariants.has(id));\n if (missing.length > 0) {\n markerPerSpace.set(member.spaceId, {\n kind: 'missingInvariants',\n missing: [...missing].sort(),\n });\n continue;\n }\n markerPerSpace.set(member.spaceId, { kind: 'ok' });\n }\n\n // Orphan markers: entries in markersBySpaceId whose spaceId is not a\n // member of the aggregate.\n const orphanMarkers: { spaceId: string; row: ContractMarkerRecordLike }[] = [];\n for (const [spaceId, row] of markersBySpaceId) {\n if (row !== null && !memberSpaceIds.has(spaceId)) {\n orphanMarkers.push({ spaceId, row });\n }\n }\n orphanMarkers.sort((a, b) => a.spaceId.localeCompare(b.spaceId));\n\n // Schema check per member (with per-space pre-projection).\n const schemaPerSpace = new Map<string, TSchemaResult>();\n for (const member of allMembers) {\n const others = allMembers.filter((m) => m.spaceId !== member.spaceId);\n const projected = projectSchemaToSpace(schemaIntrospection, member, others);\n schemaPerSpace.set(member.spaceId, verifySchemaForMember(projected, member, mode));\n }\n\n return ok({\n markerCheck: {\n perSpace: markerPerSpace,\n orphanMarkers,\n },\n schemaCheck: {\n perSpace: schemaPerSpace,\n orphanElements: detectOrphanElements(schemaIntrospection, allMembers),\n },\n });\n}\n\n/**\n * Live tables not claimed by any aggregate member. Duck-typed against\n * the introspected schema's `tables` map; schemas whose shape doesn't\n * match return an empty list (consistent with\n * {@link projectSchemaToSpace}'s fall-through).\n */\nfunction detectOrphanElements(\n schemaIntrospection: unknown,\n members: ReadonlyArray<ContractSpaceMember>,\n): readonly OrphanElement[] {\n if (typeof schemaIntrospection !== 'object' || schemaIntrospection === null) return [];\n const liveTables = (schemaIntrospection as { readonly tables?: unknown }).tables;\n if (typeof liveTables !== 'object' || liveTables === null) return [];\n\n const claimedTables = new Set<string>();\n for (const member of members) {\n const contract = member.contract();\n for (const { entityName } of elementCoordinates(contract.storage)) {\n claimedTables.add(entityName);\n }\n }\n\n const orphans: OrphanElement[] = [];\n for (const tableName of Object.keys(liveTables as Record<string, unknown>)) {\n if (!claimedTables.has(tableName)) {\n orphans.push({ kind: 'table', name: tableName });\n }\n }\n orphans.sort((a, b) => a.name.localeCompare(b.name));\n return orphans;\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,21 +1,21 @@
1
1
  {
2
2
  "name": "@prisma-next/migration-tools",
3
- "version": "0.11.0-dev.64",
3
+ "version": "0.11.0-dev.66",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "sideEffects": false,
7
7
  "description": "On-disk migration persistence, hash verification, and chain reconstruction for Prisma Next",
8
8
  "dependencies": {
9
- "@prisma-next/contract": "0.11.0-dev.64",
10
- "@prisma-next/framework-components": "0.11.0-dev.64",
11
- "@prisma-next/utils": "0.11.0-dev.64",
9
+ "@prisma-next/contract": "0.11.0-dev.66",
10
+ "@prisma-next/framework-components": "0.11.0-dev.66",
11
+ "@prisma-next/utils": "0.11.0-dev.66",
12
12
  "arktype": "^2.2.0",
13
13
  "pathe": "^2.0.3",
14
14
  "prettier": "^3.8.3"
15
15
  },
16
16
  "devDependencies": {
17
- "@prisma-next/tsconfig": "0.11.0-dev.64",
18
- "@prisma-next/tsdown": "0.11.0-dev.64",
17
+ "@prisma-next/tsconfig": "0.11.0-dev.66",
18
+ "@prisma-next/tsdown": "0.11.0-dev.66",
19
19
  "tsdown": "0.22.0",
20
20
  "typescript": "5.9.3",
21
21
  "vitest": "4.1.6"
@@ -14,7 +14,7 @@ import type { ContractMarkerRecordLike } from './marker-types';
14
14
  import type { ContractSpaceAggregate } from './types';
15
15
 
16
16
  /**
17
- * Caller-provided policy for {@link planAggregate}. Today this carries
17
+ * Caller-provided policy for {@link planMigration}. Today this carries
18
18
  * just one knob:
19
19
  *
20
20
  * - `ignoreGraphFor`: `Set<spaceId>`. For listed members, the planner
@@ -55,7 +55,7 @@ export interface AggregateCurrentDBState {
55
55
  }
56
56
 
57
57
  /**
58
- * Inputs to {@link planAggregate}.
58
+ * Inputs to {@link planMigration}.
59
59
  *
60
60
  * The planner is target-agnostic but family-aware: per-member synth
61
61
  * delegates to the family's `createPlanner(familyInstance).plan(...)`,
@@ -64,11 +64,11 @@ export interface AggregateCurrentDBState {
64
64
  * threaded through. (`frameworkComponents` is passed verbatim into
65
65
  * `planner.plan(...)` per ADR 212; the planner does not interpret it.)
66
66
  *
67
- * The aggregate planner does **not** receive a `targetId` separately —
67
+ * The planner does **not** receive a `targetId` separately —
68
68
  * it reads `aggregate.targetId` and stamps it onto every emitted
69
69
  * `MigrationPlan` from construction. No placeholder, no patch step.
70
70
  */
71
- export interface AggregatePlannerInput<TFamilyId extends string, TTargetId extends string> {
71
+ export interface PlannerInput<TFamilyId extends string, TTargetId extends string> {
72
72
  readonly aggregate: ContractSpaceAggregate;
73
73
  readonly currentDBState: AggregateCurrentDBState;
74
74
  readonly familyInstance: ControlFamilyInstance<TFamilyId, unknown>;
@@ -83,7 +83,7 @@ export interface AggregatePlannerInput<TFamilyId extends string, TTargetId exten
83
83
  }
84
84
 
85
85
  /**
86
- * Per-member output of the aggregate planner. The runner ingests this
86
+ * Per-member output of the planner. The runner ingests this
87
87
  * shape directly via a thin `toRunnerInput` adapter at the CLI.
88
88
  *
89
89
  * - `plan`: ready-to-execute `MigrationPlan` with `targetId` already
@@ -99,8 +99,8 @@ export interface AggregatePlannerInput<TFamilyId extends string, TTargetId exten
99
99
  /**
100
100
  * Per-edge metadata for the chain assembled by the graph-walk
101
101
  * strategy. Lets `migrate` surface a per-migration `applied[]`
102
- * entry (preserving the single-space `migrationsApplied` count
103
- * semantics) without re-walking the graph.
102
+ * entry (preserving the `migrationsApplied` count semantics) without
103
+ * re-walking the graph.
104
104
  *
105
105
  * `synth`-produced plans leave this absent — synthesised plans don't
106
106
  * have authored edges to surface.
@@ -113,7 +113,7 @@ export interface AggregateMigrationEdgeRef {
113
113
  readonly operationCount: number;
114
114
  }
115
115
 
116
- export interface AggregatePerSpacePlan {
116
+ export interface PerSpacePlan {
117
117
  readonly plan: MigrationPlan;
118
118
  readonly displayOps: readonly MigrationPlanOperation[];
119
119
  readonly destinationContract: Contract;
@@ -136,13 +136,13 @@ export interface AggregatePerSpacePlan {
136
136
  readonly pathDecision?: PathDecision;
137
137
  }
138
138
 
139
- export interface AggregatePlannerSuccess {
140
- readonly perSpace: ReadonlyMap<string, AggregatePerSpacePlan>;
139
+ export interface PlannerSuccess {
140
+ readonly perSpace: ReadonlyMap<string, PerSpacePlan>;
141
141
  /**
142
142
  * `applyOrder` is the order the runner must walk per-space inputs.
143
143
  * Mirrors the existing `concatenateSpaceApplyInputs` convention:
144
144
  * extensions alphabetically by `spaceId`, then the app. Tests assert
145
- * on `MultiSpaceRunnerFailure.failingSpace`, which is positional in
145
+ * on `MigrationRunnerFailure.failingSpace`, which is positional in
146
146
  * the runner's input array — preserving the literal ordering keeps
147
147
  * `failingSpace` attribution byte-for-byte.
148
148
  */
@@ -150,11 +150,11 @@ export interface AggregatePlannerSuccess {
150
150
  }
151
151
 
152
152
  /**
153
- * Discriminated failure variants for {@link planAggregate}. Each
153
+ * Discriminated failure variants for {@link planMigration}. Each
154
154
  * variant short-circuits the plan; per-member errors carry the
155
155
  * `spaceId` so the CLI can surface a precise envelope.
156
156
  */
157
- export type AggregatePlannerError =
157
+ export type PlannerError =
158
158
  | { readonly kind: 'extensionPathUnreachable'; readonly spaceId: string; readonly target: string }
159
159
  | {
160
160
  readonly kind: 'extensionPathUnsatisfiable';
@@ -168,4 +168,4 @@ export type AggregatePlannerError =
168
168
  }
169
169
  | { readonly kind: 'policyConflict'; readonly spaceId: string; readonly detail: string };
170
170
 
171
- export type AggregatePlannerOutput = Result<AggregatePlannerSuccess, AggregatePlannerError>;
171
+ export type PlannerOutput = Result<PlannerSuccess, PlannerError>;
@@ -1,11 +1,6 @@
1
1
  import { notOk, ok } from '@prisma-next/utils/result';
2
2
  import { requireHeadRef } from './aggregate';
3
- import type {
4
- AggregatePerSpacePlan,
5
- AggregatePlannerError,
6
- AggregatePlannerInput,
7
- AggregatePlannerOutput,
8
- } from './planner-types';
3
+ import type { PerSpacePlan, PlannerError, PlannerInput, PlannerOutput } from './planner-types';
9
4
  import { graphWalkStrategy } from './strategies/graph-walk';
10
5
  import { synthStrategy } from './strategies/synth';
11
6
  import type { ContractSpaceMember } from './types';
@@ -13,12 +8,12 @@ import type { ContractSpaceMember } from './types';
13
8
  export type {
14
9
  AggregateCurrentDBState,
15
10
  AggregateMigrationEdgeRef,
16
- AggregatePerSpacePlan,
17
- AggregatePlannerError,
18
- AggregatePlannerInput,
19
- AggregatePlannerOutput,
20
- AggregatePlannerSuccess,
21
11
  CallerPolicy,
12
+ PerSpacePlan,
13
+ PlannerError,
14
+ PlannerInput,
15
+ PlannerOutput,
16
+ PlannerSuccess,
22
17
  } from './planner-types';
23
18
 
24
19
  /**
@@ -38,18 +33,18 @@ export type {
38
33
  * Output `applyOrder` is `[...aggregate.extensions.map(spaceId), aggregate.app.spaceId]`
39
34
  * — extensions alphabetical, then app — matching today's
40
35
  * `concatenateSpaceApplyInputs` ordering. This preserves
41
- * `MultiSpaceRunnerFailure.failingSpace` attribution byte-for-byte.
36
+ * `MigrationRunnerFailure.failingSpace` attribution byte-for-byte.
42
37
  *
43
38
  * Every emitted `MigrationPlan` has `targetId = aggregate.targetId`.
44
39
  * No placeholder cast; no patch step.
45
40
  */
46
- export async function planAggregate<TFamilyId extends string, TTargetId extends string>(
47
- input: AggregatePlannerInput<TFamilyId, TTargetId>,
48
- ): Promise<AggregatePlannerOutput> {
41
+ export async function planMigration<TFamilyId extends string, TTargetId extends string>(
42
+ input: PlannerInput<TFamilyId, TTargetId>,
43
+ ): Promise<PlannerOutput> {
49
44
  const { aggregate, currentDBState, callerPolicy } = input;
50
45
  const allMembers: ReadonlyArray<ContractSpaceMember> = [aggregate.app, ...aggregate.extensions];
51
46
 
52
- const perSpace = new Map<string, AggregatePerSpacePlan>();
47
+ const perSpace = new Map<string, PerSpacePlan>();
53
48
 
54
49
  // Iterate in apply order so a per-member error short-circuits the
55
50
  // walk in the same order the runner would walk inputs.
@@ -67,7 +62,7 @@ export async function planAggregate<TFamilyId extends string, TTargetId extends
67
62
  const invariantsRequired = headRef.invariants.length > 0;
68
63
 
69
64
  if (ignoreGraph && invariantsRequired) {
70
- const conflict: AggregatePlannerError = {
65
+ const conflict: PlannerError = {
71
66
  kind: 'policyConflict',
72
67
  spaceId: member.spaceId,
73
68
  detail: `\`callerPolicy.ignoreGraphFor\` requested for space "${member.spaceId}", but the member declares non-empty head-ref invariants (${headRef.invariants.join(', ')}). Synthesising a plan from the contract IR cannot satisfy authored invariants — the graph must be walked. Either remove "${member.spaceId}" from \`ignoreGraphFor\` or amend the on-disk head ref to declare zero invariants.`,
@@ -4,7 +4,7 @@ import { findPathWithDecision } from '../../migration-graph';
4
4
  import type { MigrationOps, OnDiskMigrationPackage } from '../../package';
5
5
  import { requireHeadRef } from '../aggregate';
6
6
  import type { ContractMarkerRecordLike } from '../marker-types';
7
- import type { AggregatePerSpacePlan } from '../planner-types';
7
+ import type { PerSpacePlan } from '../planner-types';
8
8
  import type { ContractSpaceMember } from '../types';
9
9
 
10
10
  /**
@@ -12,11 +12,11 @@ import type { ContractSpaceMember } from '../types';
12
12
  * {@link import('../../compute-extension-space-apply-path').ExtensionSpaceApplyPathOutcome}
13
13
  * but operates against the member's lazily-reconstructed `graph()`
14
14
  * instead of re-reading from disk. The aggregate planner converts
15
- * these into {@link import('../planner-types').AggregatePlannerError}
15
+ * these into {@link import('../planner-types').PlannerError}
16
16
  * variants.
17
17
  */
18
18
  export type GraphWalkOutcome =
19
- | { readonly kind: 'ok'; readonly result: AggregatePerSpacePlan }
19
+ | { readonly kind: 'ok'; readonly result: PerSpacePlan }
20
20
  | { readonly kind: 'unreachable' }
21
21
  | { readonly kind: 'unsatisfiable'; readonly missing: readonly string[] };
22
22
 
@@ -7,7 +7,7 @@ import type {
7
7
  MigrationPlannerResult,
8
8
  TargetMigrationsCapability,
9
9
  } from '@prisma-next/framework-components/control';
10
- import type { AggregatePerSpacePlan } from '../planner-types';
10
+ import type { PerSpacePlan } from '../planner-types';
11
11
  import { projectSchemaToSpace } from '../project-schema-to-space';
12
12
  import type { ContractSpaceMember } from '../types';
13
13
 
@@ -27,7 +27,7 @@ export interface SynthStrategyInputs<TFamilyId extends string, TTargetId extends
27
27
  }
28
28
 
29
29
  export type SynthStrategyOutcome =
30
- | { readonly kind: 'ok'; readonly result: AggregatePerSpacePlan }
30
+ | { readonly kind: 'ok'; readonly result: PerSpacePlan }
31
31
  | { readonly kind: 'failure'; readonly conflicts: readonly MigrationPlannerConflict[] };
32
32
 
33
33
  /**
@@ -7,12 +7,12 @@ import { projectSchemaToSpace } from './project-schema-to-space';
7
7
  import type { ContractSpaceAggregate, ContractSpaceMember } from './types';
8
8
 
9
9
  /**
10
- * Caller policy for the aggregate verifier. Today's only knob is
10
+ * Caller policy for the verifier. Today's only knob is
11
11
  * `mode`: `strict` treats orphan elements (live tables not claimed by
12
12
  * any aggregate member) as errors; `lenient` treats them as
13
13
  * informational. Maps directly to `db verify --strict`.
14
14
  */
15
- export interface AggregateVerifierInput<TSchemaResult> {
15
+ export interface VerifierInput<TSchemaResult> {
16
16
  readonly aggregate: ContractSpaceAggregate;
17
17
  readonly markersBySpaceId: ReadonlyMap<string, ContractMarkerRecordLike | null>;
18
18
  readonly schemaIntrospection: unknown;
@@ -20,7 +20,7 @@ export interface AggregateVerifierInput<TSchemaResult> {
20
20
  /**
21
21
  * Caller-supplied per-space schema verifier. The CLI wires this to
22
22
  * the family's `verifySqlSchema` (SQL) / equivalent (other
23
- * families). The aggregate verifier projects the schema to the
23
+ * families). The verifier projects the schema to the
24
24
  * member's slice via {@link projectSchemaToSpace} before invoking
25
25
  * the callback, so single-contract semantics are preserved.
26
26
  *
@@ -62,7 +62,7 @@ export interface MarkerCheckSection {
62
62
 
63
63
  /**
64
64
  * A live storage element (today: a top-level table) not claimed by any
65
- * member of the aggregate. The aggregate verifier always reports these;
65
+ * member of the aggregate. The verifier always reports these;
66
66
  * the caller decides what to do — `db verify --strict` treats them as
67
67
  * errors, the lenient default treats them as informational.
68
68
  *
@@ -81,20 +81,17 @@ export interface SchemaCheckSection<TSchemaResult> {
81
81
  readonly orphanElements: readonly OrphanElement[];
82
82
  }
83
83
 
84
- export interface AggregateVerifierSuccess<TSchemaResult> {
84
+ export interface VerifierSuccess<TSchemaResult> {
85
85
  readonly markerCheck: MarkerCheckSection;
86
86
  readonly schemaCheck: SchemaCheckSection<TSchemaResult>;
87
87
  }
88
88
 
89
- export type AggregateVerifierError = {
89
+ export type VerifierError = {
90
90
  readonly kind: 'introspectionFailure';
91
91
  readonly detail: string;
92
92
  };
93
93
 
94
- export type AggregateVerifierOutput<TSchemaResult> = Result<
95
- AggregateVerifierSuccess<TSchemaResult>,
96
- AggregateVerifierError
97
- >;
94
+ export type VerifierOutput<TSchemaResult> = Result<VerifierSuccess<TSchemaResult>, VerifierError>;
98
95
 
99
96
  /**
100
97
  * Verify a {@link ContractSpaceAggregate} against the live database
@@ -118,11 +115,11 @@ export type AggregateVerifierOutput<TSchemaResult> = Result<
118
115
  * Pure synchronous function; no I/O. The caller (CLI) gathers
119
116
  * `markersBySpaceId` and `schemaIntrospection` ahead of the call.
120
117
  */
121
- export function verifyAggregate<TSchemaResult>(
122
- input: AggregateVerifierInput<TSchemaResult>,
123
- ): AggregateVerifierOutput<TSchemaResult> {
118
+ export function verifyMigration<TSchemaResult>(
119
+ input: VerifierInput<TSchemaResult>,
120
+ ): VerifierOutput<TSchemaResult> {
124
121
  try {
125
- return runVerifyAggregate(input);
122
+ return runVerifyMigration(input);
126
123
  } catch (error) {
127
124
  return notOk({
128
125
  kind: 'introspectionFailure',
@@ -131,9 +128,9 @@ export function verifyAggregate<TSchemaResult>(
131
128
  }
132
129
  }
133
130
 
134
- function runVerifyAggregate<TSchemaResult>(
135
- input: AggregateVerifierInput<TSchemaResult>,
136
- ): AggregateVerifierOutput<TSchemaResult> {
131
+ function runVerifyMigration<TSchemaResult>(
132
+ input: VerifierInput<TSchemaResult>,
133
+ ): VerifierOutput<TSchemaResult> {
137
134
  const { aggregate, markersBySpaceId, schemaIntrospection, mode, verifySchemaForMember } = input;
138
135
  const allMembers: ReadonlyArray<ContractSpaceMember> = [aggregate.app, ...aggregate.extensions];
139
136
  const memberSpaceIds = new Set(allMembers.map((m) => m.spaceId));
@@ -14,13 +14,13 @@ export type { ContractMarkerRecordLike } from '../aggregate/marker-types';
14
14
  export {
15
15
  type AggregateCurrentDBState,
16
16
  type AggregateMigrationEdgeRef,
17
- type AggregatePerSpacePlan,
18
- type AggregatePlannerError,
19
- type AggregatePlannerInput,
20
- type AggregatePlannerOutput,
21
- type AggregatePlannerSuccess,
22
17
  type CallerPolicy,
23
- planAggregate,
18
+ type PerSpacePlan,
19
+ type PlannerError,
20
+ type PlannerInput,
21
+ type PlannerOutput,
22
+ type PlannerSuccess,
23
+ planMigration,
24
24
  } from '../aggregate/planner';
25
25
  export { projectSchemaToSpace } from '../aggregate/project-schema-to-space';
26
26
  export {
@@ -35,15 +35,15 @@ export type {
35
35
  ContractSpaceMember,
36
36
  } from '../aggregate/types';
37
37
  export {
38
- type AggregateVerifierError,
39
- type AggregateVerifierInput,
40
- type AggregateVerifierOutput,
41
- type AggregateVerifierSuccess,
42
38
  type MarkerCheckResult,
43
39
  type MarkerCheckSection,
44
40
  type OrphanElement,
45
41
  type SchemaCheckSection,
46
- verifyAggregate,
42
+ type VerifierError,
43
+ type VerifierInput,
44
+ type VerifierOutput,
45
+ type VerifierSuccess,
46
+ verifyMigration,
47
47
  } from '../aggregate/verifier';
48
48
  export type {
49
49
  DeclaredExtensionEntry,