@prisma-next/cli 0.3.0-dev.6 → 0.3.0-dev.63

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 (180) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +314 -80
  3. package/dist/cli-errors-JlPTsazx.mjs +3 -0
  4. package/dist/cli.d.mts +1 -0
  5. package/dist/cli.js +1 -2376
  6. package/dist/cli.mjs +198 -0
  7. package/dist/cli.mjs.map +1 -0
  8. package/dist/client-PimzSD1f.mjs +981 -0
  9. package/dist/client-PimzSD1f.mjs.map +1 -0
  10. package/dist/commands/contract-emit.d.mts +7 -0
  11. package/dist/commands/contract-emit.d.mts.map +1 -0
  12. package/dist/commands/contract-emit.mjs +150 -0
  13. package/dist/commands/contract-emit.mjs.map +1 -0
  14. package/dist/commands/db-init.d.mts +7 -0
  15. package/dist/commands/db-init.d.mts.map +1 -0
  16. package/dist/commands/db-init.mjs +132 -0
  17. package/dist/commands/db-init.mjs.map +1 -0
  18. package/dist/commands/db-introspect.d.mts +7 -0
  19. package/dist/commands/db-introspect.d.mts.map +1 -0
  20. package/dist/commands/db-introspect.mjs +117 -0
  21. package/dist/commands/db-introspect.mjs.map +1 -0
  22. package/dist/commands/db-schema-verify.d.mts +7 -0
  23. package/dist/commands/db-schema-verify.d.mts.map +1 -0
  24. package/dist/commands/db-schema-verify.mjs +119 -0
  25. package/dist/commands/db-schema-verify.mjs.map +1 -0
  26. package/dist/commands/db-sign.d.mts +7 -0
  27. package/dist/commands/db-sign.d.mts.map +1 -0
  28. package/dist/commands/db-sign.mjs +141 -0
  29. package/dist/commands/db-sign.mjs.map +1 -0
  30. package/dist/commands/db-update.d.mts +7 -0
  31. package/dist/commands/db-update.d.mts.map +1 -0
  32. package/dist/commands/db-update.mjs +121 -0
  33. package/dist/commands/db-update.mjs.map +1 -0
  34. package/dist/commands/db-verify.d.mts +7 -0
  35. package/dist/commands/db-verify.d.mts.map +1 -0
  36. package/dist/commands/db-verify.mjs +132 -0
  37. package/dist/commands/db-verify.mjs.map +1 -0
  38. package/dist/commands/migration-apply.d.mts +23 -0
  39. package/dist/commands/migration-apply.d.mts.map +1 -0
  40. package/dist/commands/migration-apply.mjs +249 -0
  41. package/dist/commands/migration-apply.mjs.map +1 -0
  42. package/dist/commands/migration-plan.d.mts +25 -0
  43. package/dist/commands/migration-plan.d.mts.map +1 -0
  44. package/dist/commands/migration-plan.mjs +266 -0
  45. package/dist/commands/migration-plan.mjs.map +1 -0
  46. package/dist/commands/migration-show.d.mts +28 -0
  47. package/dist/commands/migration-show.d.mts.map +1 -0
  48. package/dist/commands/migration-show.mjs +138 -0
  49. package/dist/commands/migration-show.mjs.map +1 -0
  50. package/dist/commands/migration-status.d.mts +35 -0
  51. package/dist/commands/migration-status.d.mts.map +1 -0
  52. package/dist/commands/migration-status.mjs +259 -0
  53. package/dist/commands/migration-status.mjs.map +1 -0
  54. package/dist/commands/migration-verify.d.mts +16 -0
  55. package/dist/commands/migration-verify.d.mts.map +1 -0
  56. package/dist/commands/migration-verify.mjs +86 -0
  57. package/dist/commands/migration-verify.mjs.map +1 -0
  58. package/dist/config-loader-PPf4CtDj.mjs +43 -0
  59. package/dist/config-loader-PPf4CtDj.mjs.map +1 -0
  60. package/dist/{config-loader.d.ts → config-loader.d.mts} +8 -3
  61. package/dist/config-loader.d.mts.map +1 -0
  62. package/dist/config-loader.mjs +3 -0
  63. package/dist/exports/config-types.d.mts +2 -0
  64. package/dist/exports/config-types.mjs +3 -0
  65. package/dist/exports/control-api.d.mts +621 -0
  66. package/dist/exports/control-api.d.mts.map +1 -0
  67. package/dist/exports/control-api.mjs +97 -0
  68. package/dist/exports/control-api.mjs.map +1 -0
  69. package/dist/{load-ts-contract.d.ts → exports/index.d.mts} +10 -5
  70. package/dist/exports/index.d.mts.map +1 -0
  71. package/dist/exports/index.mjs +130 -0
  72. package/dist/exports/index.mjs.map +1 -0
  73. package/dist/extract-sql-ddl-BmlKvk4o.mjs +26 -0
  74. package/dist/extract-sql-ddl-BmlKvk4o.mjs.map +1 -0
  75. package/dist/framework-components-CjV_jD8f.mjs +59 -0
  76. package/dist/framework-components-CjV_jD8f.mjs.map +1 -0
  77. package/dist/migration-command-scaffold-DfY_F3ev.mjs +97 -0
  78. package/dist/migration-command-scaffold-DfY_F3ev.mjs.map +1 -0
  79. package/dist/progress-adapter-DENrzF6I.mjs +49 -0
  80. package/dist/progress-adapter-DENrzF6I.mjs.map +1 -0
  81. package/dist/result-handler-iA9JtUC7.mjs +1186 -0
  82. package/dist/result-handler-iA9JtUC7.mjs.map +1 -0
  83. package/package.json +75 -38
  84. package/src/cli.ts +43 -0
  85. package/src/commands/contract-emit.ts +221 -111
  86. package/src/commands/db-init.ts +217 -426
  87. package/src/commands/db-introspect.ts +148 -185
  88. package/src/commands/db-schema-verify.ts +162 -149
  89. package/src/commands/db-sign.ts +215 -202
  90. package/src/commands/db-update.ts +220 -0
  91. package/src/commands/db-verify.ts +193 -156
  92. package/src/commands/migration-apply.ts +431 -0
  93. package/src/commands/migration-plan.ts +446 -0
  94. package/src/commands/migration-show.ts +255 -0
  95. package/src/commands/migration-status.ts +436 -0
  96. package/src/commands/migration-verify.ts +151 -0
  97. package/src/config-loader.ts +13 -3
  98. package/src/control-api/client.ts +605 -0
  99. package/src/control-api/errors.ts +9 -0
  100. package/src/control-api/operations/contract-emit.ts +161 -0
  101. package/src/control-api/operations/db-init.ts +286 -0
  102. package/src/control-api/operations/db-update.ts +221 -0
  103. package/src/control-api/operations/extract-sql-ddl.ts +47 -0
  104. package/src/control-api/operations/migration-apply.ts +195 -0
  105. package/src/control-api/operations/migration-helpers.ts +49 -0
  106. package/src/control-api/types.ts +687 -0
  107. package/src/exports/config-types.ts +3 -3
  108. package/src/exports/control-api.ts +53 -0
  109. package/src/load-ts-contract.ts +16 -11
  110. package/src/utils/cli-errors.ts +3 -1
  111. package/src/utils/command-helpers.ts +92 -3
  112. package/src/utils/framework-components.ts +11 -30
  113. package/src/utils/migration-command-scaffold.ts +190 -0
  114. package/src/utils/output.ts +363 -25
  115. package/src/utils/progress-adapter.ts +86 -0
  116. package/dist/chunk-464LNZCE.js +0 -134
  117. package/dist/chunk-464LNZCE.js.map +0 -1
  118. package/dist/chunk-BZMBKEEQ.js +0 -997
  119. package/dist/chunk-BZMBKEEQ.js.map +0 -1
  120. package/dist/chunk-HWYQOCAJ.js +0 -47
  121. package/dist/chunk-HWYQOCAJ.js.map +0 -1
  122. package/dist/chunk-ZKYEJROM.js +0 -94
  123. package/dist/chunk-ZKYEJROM.js.map +0 -1
  124. package/dist/cli.d.ts +0 -2
  125. package/dist/cli.d.ts.map +0 -1
  126. package/dist/cli.js.map +0 -1
  127. package/dist/commands/contract-emit.d.ts +0 -3
  128. package/dist/commands/contract-emit.d.ts.map +0 -1
  129. package/dist/commands/contract-emit.js +0 -9
  130. package/dist/commands/contract-emit.js.map +0 -1
  131. package/dist/commands/db-init.d.ts +0 -3
  132. package/dist/commands/db-init.d.ts.map +0 -1
  133. package/dist/commands/db-init.js +0 -341
  134. package/dist/commands/db-init.js.map +0 -1
  135. package/dist/commands/db-introspect.d.ts +0 -3
  136. package/dist/commands/db-introspect.d.ts.map +0 -1
  137. package/dist/commands/db-introspect.js +0 -190
  138. package/dist/commands/db-introspect.js.map +0 -1
  139. package/dist/commands/db-schema-verify.d.ts +0 -3
  140. package/dist/commands/db-schema-verify.d.ts.map +0 -1
  141. package/dist/commands/db-schema-verify.js +0 -164
  142. package/dist/commands/db-schema-verify.js.map +0 -1
  143. package/dist/commands/db-sign.d.ts +0 -3
  144. package/dist/commands/db-sign.d.ts.map +0 -1
  145. package/dist/commands/db-sign.js +0 -199
  146. package/dist/commands/db-sign.js.map +0 -1
  147. package/dist/commands/db-verify.d.ts +0 -3
  148. package/dist/commands/db-verify.d.ts.map +0 -1
  149. package/dist/commands/db-verify.js +0 -173
  150. package/dist/commands/db-verify.js.map +0 -1
  151. package/dist/config-loader.d.ts.map +0 -1
  152. package/dist/config-loader.js +0 -7
  153. package/dist/config-loader.js.map +0 -1
  154. package/dist/exports/config-types.d.ts +0 -3
  155. package/dist/exports/config-types.d.ts.map +0 -1
  156. package/dist/exports/config-types.js +0 -6
  157. package/dist/exports/config-types.js.map +0 -1
  158. package/dist/exports/index.d.ts +0 -4
  159. package/dist/exports/index.d.ts.map +0 -1
  160. package/dist/exports/index.js +0 -175
  161. package/dist/exports/index.js.map +0 -1
  162. package/dist/load-ts-contract.d.ts.map +0 -1
  163. package/dist/utils/action.d.ts +0 -16
  164. package/dist/utils/action.d.ts.map +0 -1
  165. package/dist/utils/cli-errors.d.ts +0 -7
  166. package/dist/utils/cli-errors.d.ts.map +0 -1
  167. package/dist/utils/command-helpers.d.ts +0 -12
  168. package/dist/utils/command-helpers.d.ts.map +0 -1
  169. package/dist/utils/framework-components.d.ts +0 -81
  170. package/dist/utils/framework-components.d.ts.map +0 -1
  171. package/dist/utils/global-flags.d.ts +0 -25
  172. package/dist/utils/global-flags.d.ts.map +0 -1
  173. package/dist/utils/output.d.ts +0 -142
  174. package/dist/utils/output.d.ts.map +0 -1
  175. package/dist/utils/result-handler.d.ts +0 -15
  176. package/dist/utils/result-handler.d.ts.map +0 -1
  177. package/dist/utils/spinner.d.ts +0 -29
  178. package/dist/utils/spinner.d.ts.map +0 -1
  179. package/src/utils/action.ts +0 -43
  180. package/src/utils/spinner.ts +0 -67
@@ -0,0 +1,47 @@
1
+ import type { MigrationPlanOperation } from '@prisma-next/core-control-plane/types';
2
+
3
+ /**
4
+ * Shape of an SQL execute step on SqlMigrationPlanOperation.
5
+ * Used for runtime type narrowing without importing the concrete SQL type.
6
+ */
7
+ interface SqlExecuteStep {
8
+ readonly sql: string;
9
+ }
10
+
11
+ function isDdlStatement(sqlStatement: string): boolean {
12
+ const trimmed = sqlStatement.trim().toLowerCase();
13
+ return (
14
+ trimmed.startsWith('create ') || trimmed.startsWith('alter ') || trimmed.startsWith('drop ')
15
+ );
16
+ }
17
+
18
+ function hasExecuteSteps(
19
+ operation: MigrationPlanOperation,
20
+ ): operation is MigrationPlanOperation & { readonly execute: readonly SqlExecuteStep[] } {
21
+ const candidate = operation as unknown as Record<string, unknown>;
22
+ if (!('execute' in candidate) || !Array.isArray(candidate['execute'])) {
23
+ return false;
24
+ }
25
+ return candidate['execute'].every(
26
+ (step: unknown) => typeof step === 'object' && step !== null && 'sql' in step,
27
+ );
28
+ }
29
+
30
+ /**
31
+ * Extracts a best-effort SQL DDL preview for CLI plan output.
32
+ * This helper is presentation-only and is never used to decide migration correctness.
33
+ */
34
+ export function extractSqlDdl(operations: readonly MigrationPlanOperation[]): string[] {
35
+ const statements: string[] = [];
36
+ for (const operation of operations) {
37
+ if (!hasExecuteSteps(operation)) {
38
+ continue;
39
+ }
40
+ for (const step of operation.execute) {
41
+ if (typeof step.sql === 'string' && isDdlStatement(step.sql)) {
42
+ statements.push(step.sql.trim());
43
+ }
44
+ }
45
+ }
46
+ return statements;
47
+ }
@@ -0,0 +1,195 @@
1
+ import type { TargetBoundComponentDescriptor } from '@prisma-next/contract/framework-components';
2
+ import type { ContractIR } from '@prisma-next/contract/ir';
3
+ import { EMPTY_CONTRACT_HASH } from '@prisma-next/core-control-plane/constants';
4
+ import type {
5
+ ControlDriverInstance,
6
+ ControlFamilyInstance,
7
+ MigrationPlanOperation,
8
+ MigrationRunnerResult,
9
+ TargetMigrationsCapability,
10
+ } from '@prisma-next/core-control-plane/types';
11
+ import { notOk, ok } from '@prisma-next/utils/result';
12
+ import type {
13
+ MigrationApplyAppliedEntry,
14
+ MigrationApplyResult,
15
+ MigrationApplyStep,
16
+ OnControlProgress,
17
+ } from '../types';
18
+
19
+ export interface ExecuteMigrationApplyOptions<TFamilyId extends string, TTargetId extends string> {
20
+ readonly driver: ControlDriverInstance<TFamilyId, TTargetId>;
21
+ readonly familyInstance: ControlFamilyInstance<TFamilyId>;
22
+ readonly originHash: string;
23
+ readonly destinationHash: string;
24
+ readonly pendingMigrations: readonly MigrationApplyStep[];
25
+ readonly migrations: TargetMigrationsCapability<
26
+ TFamilyId,
27
+ TTargetId,
28
+ ControlFamilyInstance<TFamilyId>
29
+ >;
30
+ readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<TFamilyId, TTargetId>>;
31
+ readonly targetId: string;
32
+ readonly onProgress?: OnControlProgress;
33
+ }
34
+
35
+ export async function executeMigrationApply<TFamilyId extends string, TTargetId extends string>(
36
+ options: ExecuteMigrationApplyOptions<TFamilyId, TTargetId>,
37
+ ): Promise<MigrationApplyResult> {
38
+ const {
39
+ driver,
40
+ familyInstance,
41
+ originHash,
42
+ destinationHash,
43
+ pendingMigrations,
44
+ migrations,
45
+ frameworkComponents,
46
+ targetId,
47
+ onProgress,
48
+ } = options;
49
+
50
+ if (pendingMigrations.length === 0) {
51
+ if (originHash !== destinationHash) {
52
+ return notOk({
53
+ code: 'MIGRATION_PATH_NOT_FOUND' as const,
54
+ summary: 'No migrations provided for requested origin and destination',
55
+ why: `Requested ${originHash} -> ${destinationHash} but pendingMigrations is empty`,
56
+ meta: { originHash, destinationHash },
57
+ });
58
+ }
59
+ return ok({
60
+ migrationsApplied: 0,
61
+ markerHash: originHash,
62
+ applied: [],
63
+ summary: 'Already up to date',
64
+ });
65
+ }
66
+
67
+ const firstMigration = pendingMigrations[0]!;
68
+ const lastMigration = pendingMigrations[pendingMigrations.length - 1]!;
69
+ if (firstMigration.from !== originHash || lastMigration.to !== destinationHash) {
70
+ return notOk({
71
+ code: 'MIGRATION_PATH_NOT_FOUND' as const,
72
+ summary: 'Migration apply path does not match requested origin and destination',
73
+ why: `Path resolved as ${firstMigration.from} -> ${lastMigration.to}, but requested ${originHash} -> ${destinationHash}`,
74
+ meta: {
75
+ originHash,
76
+ destinationHash,
77
+ pathOrigin: firstMigration.from,
78
+ pathDestination: lastMigration.to,
79
+ },
80
+ });
81
+ }
82
+
83
+ for (let i = 1; i < pendingMigrations.length; i++) {
84
+ const previous = pendingMigrations[i - 1]!;
85
+ const current = pendingMigrations[i]!;
86
+ if (previous.to !== current.from) {
87
+ return notOk({
88
+ code: 'MIGRATION_PATH_NOT_FOUND' as const,
89
+ summary: 'Migration apply path contains a discontinuity between adjacent migrations',
90
+ why: `Migration "${previous.dirName}" ends at ${previous.to}, but next migration "${current.dirName}" starts at ${current.from}`,
91
+ meta: {
92
+ originHash,
93
+ destinationHash,
94
+ previousDirName: previous.dirName,
95
+ previousTo: previous.to,
96
+ currentDirName: current.dirName,
97
+ currentFrom: current.from,
98
+ discontinuityIndex: i,
99
+ },
100
+ });
101
+ }
102
+ }
103
+
104
+ const runner = migrations.createRunner(familyInstance);
105
+ const applied: MigrationApplyAppliedEntry[] = [];
106
+
107
+ for (const migration of pendingMigrations) {
108
+ const migrationSpanId = `migration:${migration.dirName}`;
109
+ onProgress?.({
110
+ action: 'migrationApply',
111
+ kind: 'spanStart',
112
+ spanId: migrationSpanId,
113
+ label: `Applying ${migration.dirName}`,
114
+ });
115
+
116
+ const operations = migration.operations as readonly MigrationPlanOperation[];
117
+
118
+ // Allow all operation classes. The policy gate belongs at plan time, not
119
+ // apply time — the planner already decided what to emit. Restricting here
120
+ // would be a tautology (the allowed set would just mirror what's in ops).
121
+ const policy = {
122
+ allowedOperationClasses: ['additive', 'widening', 'destructive'] as const,
123
+ };
124
+
125
+ // EMPTY_CONTRACT_HASH means "no prior state" — the runner expects origin: null
126
+ // for a fresh database (no marker present).
127
+ const plan = {
128
+ targetId,
129
+ origin: migration.from === EMPTY_CONTRACT_HASH ? null : { storageHash: migration.from },
130
+ destination: { storageHash: migration.to },
131
+ operations,
132
+ };
133
+
134
+ const destinationContract = familyInstance.validateContractIR(
135
+ migration.toContract as ContractIR,
136
+ );
137
+
138
+ const runnerResult: MigrationRunnerResult = await runner.execute({
139
+ plan,
140
+ driver,
141
+ destinationContract,
142
+ policy,
143
+ executionChecks: {
144
+ prechecks: true,
145
+ postchecks: true,
146
+ idempotencyChecks: true,
147
+ },
148
+ frameworkComponents,
149
+ });
150
+
151
+ if (!runnerResult.ok) {
152
+ onProgress?.({
153
+ action: 'migrationApply',
154
+ kind: 'spanEnd',
155
+ spanId: migrationSpanId,
156
+ outcome: 'error',
157
+ });
158
+ return notOk({
159
+ code: 'RUNNER_FAILED' as const,
160
+ summary: runnerResult.failure.summary,
161
+ why: runnerResult.failure.why,
162
+ meta: {
163
+ migration: migration.dirName,
164
+ from: migration.from,
165
+ to: migration.to,
166
+ ...(runnerResult.failure.meta ?? {}),
167
+ },
168
+ });
169
+ }
170
+
171
+ onProgress?.({
172
+ action: 'migrationApply',
173
+ kind: 'spanEnd',
174
+ spanId: migrationSpanId,
175
+ outcome: 'ok',
176
+ });
177
+
178
+ applied.push({
179
+ dirName: migration.dirName,
180
+ from: migration.from,
181
+ to: migration.to,
182
+ operationsExecuted: runnerResult.value.operationsExecuted,
183
+ });
184
+ }
185
+
186
+ const finalHash = pendingMigrations[pendingMigrations.length - 1]!.to;
187
+ const totalOps = applied.reduce((sum, a) => sum + a.operationsExecuted, 0);
188
+
189
+ return ok({
190
+ migrationsApplied: applied.length,
191
+ markerHash: finalHash,
192
+ applied,
193
+ summary: `Applied ${applied.length} migration(s) (${totalOps} operation(s)), marker at ${finalHash}`,
194
+ });
195
+ }
@@ -0,0 +1,49 @@
1
+ import type { MigrationPlanOperation } from '@prisma-next/core-control-plane/types';
2
+ import type { ControlActionName, OnControlProgress } from '../types';
3
+
4
+ /**
5
+ * Strips operation objects to their public shape (id, label, operationClass).
6
+ * Used at the API boundary to avoid leaking internal fields (precheck, execute, postcheck, etc.).
7
+ */
8
+ export function stripOperations(
9
+ operations: readonly MigrationPlanOperation[],
10
+ ): ReadonlyArray<{ readonly id: string; readonly label: string; readonly operationClass: string }> {
11
+ return operations.map((op) => ({
12
+ id: op.id,
13
+ label: op.label,
14
+ operationClass: op.operationClass,
15
+ }));
16
+ }
17
+
18
+ /**
19
+ * Creates per-operation progress callbacks for the runner.
20
+ * Returns undefined when no onProgress callback is provided.
21
+ */
22
+ export function createOperationCallbacks(
23
+ onProgress: OnControlProgress | undefined,
24
+ action: ControlActionName,
25
+ parentSpanId: string,
26
+ ) {
27
+ if (!onProgress) {
28
+ return undefined;
29
+ }
30
+ return {
31
+ onOperationStart: (op: MigrationPlanOperation) => {
32
+ onProgress({
33
+ action,
34
+ kind: 'spanStart',
35
+ spanId: `operation:${op.id}`,
36
+ parentSpanId,
37
+ label: op.label,
38
+ });
39
+ },
40
+ onOperationComplete: (op: MigrationPlanOperation) => {
41
+ onProgress({
42
+ action,
43
+ kind: 'spanEnd',
44
+ spanId: `operation:${op.id}`,
45
+ outcome: 'ok',
46
+ });
47
+ },
48
+ };
49
+ }