@prisma-next/cli 0.6.0-dev.3 → 0.6.0-dev.4

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.
Files changed (57) hide show
  1. package/dist/cli.mjs +4 -4
  2. package/dist/{client-qVH-rEgd.mjs → client-BCnP7cHo.mjs} +9 -119
  3. package/dist/client-BCnP7cHo.mjs.map +1 -0
  4. package/dist/commands/contract-infer.mjs +1 -1
  5. package/dist/commands/db-init.mjs +3 -3
  6. package/dist/commands/db-schema.mjs +1 -1
  7. package/dist/commands/db-sign.mjs +1 -1
  8. package/dist/commands/db-update.mjs +3 -3
  9. package/dist/commands/db-verify.mjs +1 -1
  10. package/dist/commands/migration-apply.d.mts +1 -1
  11. package/dist/commands/migration-apply.mjs +2 -2
  12. package/dist/commands/migration-plan.d.mts.map +1 -1
  13. package/dist/commands/migration-plan.mjs +1 -1
  14. package/dist/commands/migration-show.d.mts +55 -7
  15. package/dist/commands/migration-show.d.mts.map +1 -1
  16. package/dist/commands/migration-show.mjs +153 -46
  17. package/dist/commands/migration-show.mjs.map +1 -1
  18. package/dist/commands/migration-status.d.mts.map +1 -1
  19. package/dist/commands/migration-status.mjs +1 -1
  20. package/dist/{contract-infer-BK9YFGEG.mjs → contract-infer-ByxhPjpW.mjs} +2 -2
  21. package/dist/{contract-infer-BK9YFGEG.mjs.map → contract-infer-ByxhPjpW.mjs.map} +1 -1
  22. package/dist/contract-space-aggregate-loader-BrwKK6Q6.mjs +160 -0
  23. package/dist/contract-space-aggregate-loader-BrwKK6Q6.mjs.map +1 -0
  24. package/dist/{db-verify-C0y1PCO2.mjs → db-verify-Czm5T-J4.mjs} +2 -2
  25. package/dist/{db-verify-C0y1PCO2.mjs.map → db-verify-Czm5T-J4.mjs.map} +1 -1
  26. package/dist/exports/control-api.d.mts +1 -1
  27. package/dist/exports/control-api.mjs +1 -1
  28. package/dist/{inspect-live-schema-CWYxGKlb.mjs → inspect-live-schema-DxdBd4Er.mjs} +2 -2
  29. package/dist/{inspect-live-schema-CWYxGKlb.mjs.map → inspect-live-schema-DxdBd4Er.mjs.map} +1 -1
  30. package/dist/{migration-command-scaffold-B5dORFEv.mjs → migration-command-scaffold-BdV8JYXV.mjs} +2 -2
  31. package/dist/{migration-command-scaffold-B5dORFEv.mjs.map → migration-command-scaffold-BdV8JYXV.mjs.map} +1 -1
  32. package/dist/{migration-plan-C6lVaHsO.mjs → migration-plan-mRu5K81L.mjs} +89 -149
  33. package/dist/migration-plan-mRu5K81L.mjs.map +1 -0
  34. package/dist/{migration-status-CZ-D5k7k.mjs → migration-status-By9G5p2H.mjs} +6 -8
  35. package/dist/{migration-status-CZ-D5k7k.mjs.map → migration-status-By9G5p2H.mjs.map} +1 -1
  36. package/dist/{migrations-D_UJnpuW.mjs → migrations-CTsyBXCA.mjs} +42 -29
  37. package/dist/migrations-CTsyBXCA.mjs.map +1 -0
  38. package/dist/{types-D7x-IFLO.d.mts → types-LItU7E4l.d.mts} +7 -9
  39. package/dist/{types-D7x-IFLO.d.mts.map → types-LItU7E4l.d.mts.map} +1 -1
  40. package/package.json +14 -14
  41. package/src/commands/migration-plan.ts +45 -47
  42. package/src/commands/migration-show.ts +245 -60
  43. package/src/commands/migration-status.ts +17 -9
  44. package/src/control-api/operations/db-apply-aggregate.ts +12 -10
  45. package/src/control-api/operations/migration-apply.ts +7 -1
  46. package/src/control-api/types.ts +6 -8
  47. package/src/utils/contract-space-aggregate-loader.ts +7 -34
  48. package/src/utils/contract-space-seed-phase.ts +201 -0
  49. package/src/utils/extension-pack-inputs.ts +47 -55
  50. package/src/utils/formatters/migrations.ts +80 -38
  51. package/dist/client-qVH-rEgd.mjs.map +0 -1
  52. package/dist/extension-pack-inputs-C7xgE-vv.mjs +0 -74
  53. package/dist/extension-pack-inputs-C7xgE-vv.mjs.map +0 -1
  54. package/dist/migration-plan-C6lVaHsO.mjs.map +0 -1
  55. package/dist/migrations-D_UJnpuW.mjs.map +0 -1
  56. package/src/utils/contract-space-extension-migrations-pass.ts +0 -120
  57. package/src/utils/contract-space-migrate-pass.ts +0 -156
@@ -1,120 +0,0 @@
1
- import { materialiseExtensionMigrationPackageIfMissing } from '@prisma-next/migration-tools/io';
2
- import type { MigrationMetadata } from '@prisma-next/migration-tools/metadata';
3
- import type { MigrationOps } from '@prisma-next/migration-tools/package';
4
- import {
5
- planAllSpaces,
6
- type SpacePlanOutput,
7
- spaceMigrationDirectory,
8
- } from '@prisma-next/migration-tools/spaces';
9
-
10
- /**
11
- * In-memory authored migration package shipped by an extension descriptor.
12
- * Mirrors `MigrationPackage` from `@prisma-next/migration-tools/io`
13
- * (the on-disk shape minus `dirPath`); redeclared structurally here so
14
- * the CLI helper does not couple to the SQL family's `ExtensionMigrationPackage`
15
- * type — any family that ships pre-built migration packages can pass them
16
- * through unchanged.
17
- */
18
- export interface DescriptorMigrationPackage {
19
- readonly dirName: string;
20
- readonly metadata: MigrationMetadata;
21
- readonly ops: MigrationOps;
22
- }
23
-
24
- /**
25
- * Minimal descriptor view consumed by the migration-materialisation pass.
26
- * Mirrors {@link import('./contract-space-migrate-pass').MigrateExtensionInput}
27
- * but adds the `migrations` field — the canonical set of pre-built
28
- * migration packages the extension ships.
29
- */
30
- export interface ExtensionMigrationsExtensionInput {
31
- readonly id: string;
32
- readonly contractSpace?: {
33
- readonly contractJson: unknown;
34
- readonly migrations: readonly DescriptorMigrationPackage[];
35
- readonly headRef: { readonly hash: string; readonly invariants: readonly string[] };
36
- };
37
- }
38
-
39
- export interface ContractSpaceExtensionMigrationsPassInputs {
40
- readonly migrationsDir: string;
41
- readonly extensionPacks: ReadonlyArray<ExtensionMigrationsExtensionInput>;
42
- }
43
-
44
- export interface ContractSpaceExtensionMigrationsPassResult {
45
- readonly emitted: readonly { readonly spaceId: string; readonly dirName: string }[];
46
- readonly skipped: readonly { readonly spaceId: string; readonly dirName: string }[];
47
- }
48
-
49
- /**
50
- * Materialise an extension's pre-built migration packages onto disk
51
- * under `migrations/<spaceId>/<dirName>/` for every package that does
52
- * not yet exist there.
53
- *
54
- * Helper-location pattern — the per-space "planner" for extension
55
- * spaces is a no-op that just returns the descriptor's `migrations`
56
- * verbatim; the value `planAllSpaces` brings to this consumer site is
57
- * **deterministic ordering** (alphabetical by spaceId) and
58
- * **duplicate-spaceId detection**. The actual write is performed via
59
- * `materialiseMigrationPackage` per package.
60
- *
61
- * Idempotent: an existing `migrations/<spaceId>/<dirName>/` is left
62
- * untouched and reported in `result.skipped` — the helper never
63
- * overwrites authored migration content, ensuring re-running
64
- * `migrate` does not corrupt or churn extension migration packages.
65
- *
66
- * Per-space artefacts (`contract.json`, `contract.d.ts`,
67
- * `refs/head.json`) are emitted by
68
- * {@link import('./contract-space-migrate-pass').runContractSpaceMigratePass}
69
- * separately — they cover the head-pointer side of the ledger. This
70
- * helper covers the migration-graph side.
71
- */
72
- export async function runContractSpaceExtensionMigrationsPass(
73
- inputs: ContractSpaceExtensionMigrationsPassInputs,
74
- ): Promise<ContractSpaceExtensionMigrationsPassResult> {
75
- const planInputs = inputs.extensionPacks
76
- .filter(
77
- (
78
- pack,
79
- ): pack is ExtensionMigrationsExtensionInput & {
80
- contractSpace: NonNullable<ExtensionMigrationsExtensionInput['contractSpace']>;
81
- } => pack.contractSpace !== undefined,
82
- )
83
- .map((pack) => ({
84
- spaceId: pack.id,
85
- priorContract: null,
86
- newContract: pack.contractSpace.contractJson,
87
- __migrations: pack.contractSpace.migrations,
88
- }));
89
-
90
- // Threading the descriptor's pre-built migrations into the
91
- // `planAllSpaces` callback by piggybacking on the input shape.
92
- // The framework helper is generic over the per-space planner output;
93
- // here the "planner" is a no-op that returns the descriptor's
94
- // `migrations` array. The benefit of routing through `planAllSpaces`
95
- // is duplicate-spaceId detection + alphabetical ordering — failures
96
- // there throw `MIGRATION.DUPLICATE_SPACE_ID` before any write.
97
- const planned: readonly SpacePlanOutput<DescriptorMigrationPackage>[] = planAllSpaces(
98
- planInputs,
99
- (input) =>
100
- (input as typeof input & { readonly __migrations: readonly DescriptorMigrationPackage[] })
101
- .__migrations,
102
- );
103
-
104
- const emitted: { spaceId: string; dirName: string }[] = [];
105
- const skipped: { spaceId: string; dirName: string }[] = [];
106
-
107
- for (const space of planned) {
108
- const spaceDir = spaceMigrationDirectory(inputs.migrationsDir, space.spaceId);
109
- for (const pkg of space.migrationPackages) {
110
- const { written } = await materialiseExtensionMigrationPackageIfMissing(spaceDir, pkg);
111
- if (written) {
112
- emitted.push({ spaceId: space.spaceId, dirName: pkg.dirName });
113
- } else {
114
- skipped.push({ spaceId: space.spaceId, dirName: pkg.dirName });
115
- }
116
- }
117
- }
118
-
119
- return { emitted, skipped };
120
- }
@@ -1,156 +0,0 @@
1
- import {
2
- detectSpaceContractDrift,
3
- emitContractSpaceArtefacts,
4
- readContractSpaceHeadRef,
5
- type SpaceContractDriftResult,
6
- } from '@prisma-next/migration-tools/spaces';
7
-
8
- /**
9
- * Minimal descriptor view consumed by the migrate-time per-space pass.
10
- *
11
- * The CLI receives descriptors typed against the SQL family (or any other
12
- * family in the future); this helper only needs the structural shape of
13
- * `contractSpace`, so it accepts an `unknown`-typed `contractJson` and
14
- * a structurally-typed `headRef`. SQL-family callers pass the same
15
- * `Contract<SqlStorage>` value through unchanged — `emitContractSpaceArtefacts`
16
- * already serialises through `canonicalizeJson` and is framework-neutral.
17
- *
18
- * @see specs/framework-mechanism.spec.md § 3 — Per-space helper location.
19
- */
20
- export interface MigrateExtensionInput {
21
- readonly id: string;
22
- readonly contractSpace?: {
23
- readonly contractJson: unknown;
24
- readonly headRef: { readonly hash: string; readonly invariants: readonly string[] };
25
- };
26
- }
27
-
28
- /**
29
- * Inputs needed to compose the migrate-time per-space pass at the CLI
30
- * surface — typically called once after the app-space migration package
31
- * has been written, regardless of whether the app-space had structural
32
- * changes (an extension bump alone should still re-pin its artefacts).
33
- */
34
- export interface ContractSpaceMigratePassInputs {
35
- readonly migrationsDir: string;
36
- readonly extensionPacks: ReadonlyArray<MigrateExtensionInput>;
37
- }
38
-
39
- export interface ContractSpaceMigratePassResult {
40
- readonly drifts: readonly SpaceContractDriftResult[];
41
- readonly emittedSpaceIds: readonly string[];
42
- }
43
-
44
- /**
45
- * Run drift detection + on-disk artefact emission for every loaded
46
- * extension space at `migrate` time.
47
- *
48
- * Per sub-spec § 3:
49
- *
50
- * - For each declared extension that exposes a `contractSpace`:
51
- * - Read the on-disk head hash from `migrations/<spaceId>/refs/head.json`
52
- * (returns `null` on first emit).
53
- * - Compare against the descriptor's `headRef.hash` via
54
- * `detectSpaceContractDrift`. The `kind` discriminant decides whether
55
- * the user sees a warning (`drift`), a no-op silent emit (`firstEmit`,
56
- * `noDrift`), or nothing at all.
57
- * - Always re-emit the on-disk artefacts (`contract.json`, `contract.d.ts`,
58
- * `refs/head.json`). The framework owns these files and the helper is
59
- * idempotent.
60
- *
61
- * Drift warnings are returned to the caller for formatting (TerminalUI,
62
- * structured-output envelope, etc.) — the helper does not print directly,
63
- * keeping it framework-neutral and unit-testable.
64
- *
65
- * Extension migration packages (the descriptor's pre-canned `migrations`
66
- * array → `migrations/<spaceId>/<dirName>/`) are intentionally not
67
- * materialised here — that interaction will be wired in a follow-on round
68
- * once the runner-side single-tx slice (sub-spec § 6) is in place.
69
- * On-disk artefacts are sufficient to lock the drift-warning behaviour
70
- * and the always-on re-emit AC for R2.
71
- *
72
- * @see specs/framework-mechanism.spec.md § 3 — Drift detection (T1.9).
73
- */
74
- export async function runContractSpaceMigratePass(
75
- inputs: ContractSpaceMigratePassInputs,
76
- ): Promise<ContractSpaceMigratePassResult> {
77
- const drifts: SpaceContractDriftResult[] = [];
78
- const emittedSpaceIds: string[] = [];
79
-
80
- for (const pack of inputs.extensionPacks) {
81
- if (pack.contractSpace === undefined) continue;
82
- const { contractJson, headRef } = pack.contractSpace;
83
-
84
- const onDiskHeadRef = await readContractSpaceHeadRef(inputs.migrationsDir, pack.id);
85
- const drift = detectSpaceContractDrift(pack.id, {
86
- descriptorHash: headRef.hash,
87
- priorHeadHash: onDiskHeadRef?.hash ?? null,
88
- });
89
- drifts.push(drift);
90
-
91
- await emitContractSpaceArtefacts(inputs.migrationsDir, pack.id, {
92
- contract: contractJson,
93
- contractDts: buildPlaceholderContractDts(pack.id),
94
- headRef: { hash: headRef.hash, invariants: headRef.invariants },
95
- });
96
- emittedSpaceIds.push(pack.id);
97
- }
98
-
99
- return { drifts, emittedSpaceIds };
100
- }
101
-
102
- /**
103
- * Format the user-facing drift warning for a single space. Callers
104
- * funnel this through their preferred output channel (TerminalUI line,
105
- * structured-output envelope `warnings[]`, etc.).
106
- *
107
- * Locks AM7 — drift warning surfaces the extension name and the diff
108
- * direction (descriptor → on-disk head).
109
- */
110
- export function formatContractSpaceDriftWarning(drift: SpaceContractDriftResult): string {
111
- if (drift.kind !== 'drift') {
112
- throw new Error(`formatContractSpaceDriftWarning called with non-drift result: ${drift.kind}`);
113
- }
114
- return (
115
- `Contract-space drift detected for "${drift.spaceId}": descriptor hash ` +
116
- `${drift.descriptorHash} differs from on-disk head hash ${drift.priorHeadHash ?? '<none>'}. ` +
117
- `The on-disk artefacts under migrations/${drift.spaceId}/ will be refreshed to match the descriptor.`
118
- );
119
- }
120
-
121
- /**
122
- * Placeholder `.d.ts` content for an extension space's on-disk mirror.
123
- *
124
- * Rendering a fully-typed `.d.ts` for an extension contract requires the
125
- * SQL-family renderer with the codec / typemap registry threaded
126
- * through; that integration is tracked under sub-spec Open Question 3
127
- * (see `projects/extension-contract-spaces/specs/framework-mechanism.spec.md`).
128
- *
129
- * Until that ships, the on-disk `.d.ts` is a `@ts-nocheck` stub. The
130
- * spec gap closing alongside the typed renderer is **AC2 / AC14**
131
- * (byte-equivalence of per-space artefacts under `migrate`):
132
- * a placeholder cannot be byte-equal to a fully-rendered `.d.ts` from
133
- * the same descriptor, so AC2 / AC14 are PARTIAL today and become
134
- * fully-PASS once OQ3 closes.
135
- *
136
- * Scheduled to close in **M3** (cipherstash editor tooling) — that's
137
- * the milestone where the typed renderer gets its first real
138
- * extension-space consumer and the byte-equivalence guarantee is
139
- * practically required.
140
- */
141
- function buildPlaceholderContractDts(spaceId: string): string {
142
- return [
143
- '// @ts-nocheck',
144
- '/**',
145
- ` * Placeholder \`.d.ts\` for extension space "${spaceId}".`,
146
- ' *',
147
- ' * The framework re-emits this file on every `migrate` run alongside',
148
- ' * `contract.json` and `refs/head.json`. A typed `.d.ts` rendering',
149
- " * pass for extension contracts is tracked under the project's open",
150
- ' * questions; until that ships, consumers should import',
151
- ' * `contract.json` directly with `validateContract<…>(…)`.',
152
- ' */',
153
- 'export {};',
154
- '',
155
- ].join('\n');
156
- }