@prisma-next/cli 0.4.0-dev.9 → 0.5.0-dev.1

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 (116) hide show
  1. package/README.md +26 -18
  2. package/dist/cli-errors-C0JhVj0c.d.mts +4 -0
  3. package/dist/cli-errors-DHq6GQGu.mjs +5 -0
  4. package/dist/cli.mjs +7 -18
  5. package/dist/cli.mjs.map +1 -1
  6. package/dist/{client-CJxHfhze.mjs → client-TG7rbCWT.mjs} +7 -6
  7. package/dist/{client-CJxHfhze.mjs.map → client-TG7rbCWT.mjs.map} +1 -1
  8. package/dist/commands/contract-emit.d.mts.map +1 -1
  9. package/dist/commands/contract-emit.mjs +2 -7
  10. package/dist/commands/contract-infer.mjs +2 -8
  11. package/dist/commands/db-init.mjs +6 -7
  12. package/dist/commands/db-init.mjs.map +1 -1
  13. package/dist/commands/db-schema.mjs +4 -7
  14. package/dist/commands/db-schema.mjs.map +1 -1
  15. package/dist/commands/db-sign.mjs +5 -6
  16. package/dist/commands/db-sign.mjs.map +1 -1
  17. package/dist/commands/db-update.mjs +6 -7
  18. package/dist/commands/db-update.mjs.map +1 -1
  19. package/dist/commands/db-verify.mjs +6 -7
  20. package/dist/commands/db-verify.mjs.map +1 -1
  21. package/dist/commands/migration-apply.d.mts +1 -1
  22. package/dist/commands/migration-apply.d.mts.map +1 -1
  23. package/dist/commands/migration-apply.mjs +33 -25
  24. package/dist/commands/migration-apply.mjs.map +1 -1
  25. package/dist/commands/migration-new.d.mts.map +1 -1
  26. package/dist/commands/migration-new.mjs +47 -22
  27. package/dist/commands/migration-new.mjs.map +1 -1
  28. package/dist/commands/migration-plan.d.mts +6 -1
  29. package/dist/commands/migration-plan.d.mts.map +1 -1
  30. package/dist/commands/migration-plan.mjs +92 -69
  31. package/dist/commands/migration-plan.mjs.map +1 -1
  32. package/dist/commands/migration-ref.d.mts +1 -1
  33. package/dist/commands/migration-ref.mjs +4 -4
  34. package/dist/commands/migration-show.d.mts +2 -2
  35. package/dist/commands/migration-show.d.mts.map +1 -1
  36. package/dist/commands/migration-show.mjs +9 -14
  37. package/dist/commands/migration-show.mjs.map +1 -1
  38. package/dist/commands/migration-status.d.mts +4 -5
  39. package/dist/commands/migration-status.d.mts.map +1 -1
  40. package/dist/commands/migration-status.mjs +2 -7
  41. package/dist/config-loader-_W4T21X1.mjs +90 -0
  42. package/dist/config-loader-_W4T21X1.mjs.map +1 -0
  43. package/dist/config-loader.d.mts.map +1 -1
  44. package/dist/config-loader.mjs +1 -1
  45. package/dist/{contract-emit-gpJNLGs7.mjs → contract-emit-CNYyzJwF.mjs} +18 -14
  46. package/dist/contract-emit-CNYyzJwF.mjs.map +1 -0
  47. package/dist/{contract-emit-CKig_Lra.mjs → contract-emit-CQfj7xJn.mjs} +24 -20
  48. package/dist/contract-emit-CQfj7xJn.mjs.map +1 -0
  49. package/dist/contract-emit-fhNwwhkQ.mjs +4 -0
  50. package/dist/{contract-infer-BDJgg7Xb.mjs → contract-infer-BP3DrGgz.mjs} +3 -3
  51. package/dist/{contract-infer-BDJgg7Xb.mjs.map → contract-infer-BP3DrGgz.mjs.map} +1 -1
  52. package/dist/exports/control-api.d.mts +2 -2
  53. package/dist/exports/control-api.d.mts.map +1 -1
  54. package/dist/exports/control-api.mjs +3 -5
  55. package/dist/exports/index.mjs +2 -7
  56. package/dist/exports/index.mjs.map +1 -1
  57. package/dist/{framework-components-Bsr1GaIj.mjs → framework-components-DfZKQBQ2.mjs} +2 -2
  58. package/dist/{framework-components-Bsr1GaIj.mjs.map → framework-components-DfZKQBQ2.mjs.map} +1 -1
  59. package/dist/{init-DZWvhEP0.mjs → init-CQfo_4Ro.mjs} +2 -2
  60. package/dist/{init-DZWvhEP0.mjs.map → init-CQfo_4Ro.mjs.map} +1 -1
  61. package/dist/{inspect-live-schema-ChqrALmw.mjs → inspect-live-schema-DWzf4Q_m.mjs} +5 -5
  62. package/dist/{inspect-live-schema-ChqrALmw.mjs.map → inspect-live-schema-DWzf4Q_m.mjs.map} +1 -1
  63. package/dist/migration-cli.d.mts +50 -0
  64. package/dist/migration-cli.d.mts.map +1 -0
  65. package/dist/migration-cli.mjs +184 -0
  66. package/dist/migration-cli.mjs.map +1 -0
  67. package/dist/{migration-command-scaffold-B0oH_hyB.mjs → migration-command-scaffold-CLMD302g.mjs} +6 -6
  68. package/dist/{migration-command-scaffold-B0oH_hyB.mjs.map → migration-command-scaffold-CLMD302g.mjs.map} +1 -1
  69. package/dist/{migration-status-CPamfEPj.mjs → migration-status-B0HLF7So.mjs} +18 -34
  70. package/dist/migration-status-B0HLF7So.mjs.map +1 -0
  71. package/dist/{migrations-BIsjFjSV.mjs → migrations-B0dOQlk0.mjs} +4 -15
  72. package/dist/migrations-B0dOQlk0.mjs.map +1 -0
  73. package/dist/{result-handler-AFK4hxyX.mjs → result-handler-CIyu0Pdt.mjs} +22 -11
  74. package/dist/result-handler-CIyu0Pdt.mjs.map +1 -0
  75. package/dist/{validate-contract-deps-DBH6iTAD.mjs → validate-contract-deps-esa-VQ0h.mjs} +1 -1
  76. package/dist/{validate-contract-deps-DBH6iTAD.mjs.map → validate-contract-deps-esa-VQ0h.mjs.map} +1 -1
  77. package/dist/{verify-C56CuQc7.mjs → verify-BxiVp50b.mjs} +2 -2
  78. package/dist/{verify-C56CuQc7.mjs.map → verify-BxiVp50b.mjs.map} +1 -1
  79. package/package.json +19 -19
  80. package/src/cli.ts +1 -5
  81. package/src/commands/contract-emit.ts +9 -10
  82. package/src/commands/migration-apply.ts +34 -23
  83. package/src/commands/migration-new.ts +39 -17
  84. package/src/commands/migration-plan.ts +119 -104
  85. package/src/commands/migration-show.ts +6 -16
  86. package/src/commands/migration-status.ts +14 -34
  87. package/src/config-loader.ts +35 -29
  88. package/src/config-path-validation.ts +75 -0
  89. package/src/control-api/client.ts +2 -1
  90. package/src/control-api/operations/contract-emit.ts +24 -23
  91. package/src/control-api/types.ts +1 -1
  92. package/src/migration-cli.ts +254 -0
  93. package/src/utils/cli-errors.ts +1 -0
  94. package/src/utils/command-helpers.ts +15 -19
  95. package/src/utils/formatters/graph-migration-mapper.ts +5 -14
  96. package/src/utils/formatters/help.ts +0 -1
  97. package/src/utils/formatters/migrations.ts +2 -29
  98. package/dist/cli-errors-BUuJr6py.mjs +0 -5
  99. package/dist/cli-errors-Dic2eADK.d.mts +0 -4
  100. package/dist/commands/migration-emit.d.mts +0 -38
  101. package/dist/commands/migration-emit.d.mts.map +0 -1
  102. package/dist/commands/migration-emit.mjs +0 -81
  103. package/dist/commands/migration-emit.mjs.map +0 -1
  104. package/dist/config-loader-C4VXKl8f.mjs +0 -43
  105. package/dist/config-loader-C4VXKl8f.mjs.map +0 -1
  106. package/dist/contract-emit-CKig_Lra.mjs.map +0 -1
  107. package/dist/contract-emit-CU-SYNe4.mjs +0 -6
  108. package/dist/contract-emit-gpJNLGs7.mjs.map +0 -1
  109. package/dist/migration-emit-Du4DBMqz.mjs +0 -125
  110. package/dist/migration-emit-Du4DBMqz.mjs.map +0 -1
  111. package/dist/migration-status-CPamfEPj.mjs.map +0 -1
  112. package/dist/migrations-BIsjFjSV.mjs.map +0 -1
  113. package/dist/result-handler-AFK4hxyX.mjs.map +0 -1
  114. package/src/commands/migration-emit.ts +0 -134
  115. package/src/lib/migration-emit.ts +0 -125
  116. package/src/lib/migration-strategy.ts +0 -49
@@ -1,134 +0,0 @@
1
- import { MigrationToolsError } from '@prisma-next/migration-tools/types';
2
- import { notOk, ok, type Result } from '@prisma-next/utils/result';
3
- import { Command } from 'commander';
4
- import { loadConfig } from '../config-loader';
5
- import { emitMigration } from '../lib/migration-emit';
6
- import {
7
- CliStructuredError,
8
- errorRuntime,
9
- errorTargetMigrationNotSupported,
10
- errorUnexpected,
11
- } from '../utils/cli-errors';
12
- import {
13
- addGlobalOptions,
14
- getTargetMigrations,
15
- setCommandDescriptions,
16
- setCommandExamples,
17
- } from '../utils/command-helpers';
18
- import { formatMigrationEmitCommandOutput } from '../utils/formatters/migrations';
19
- import { formatStyledHeader } from '../utils/formatters/styled';
20
- import { assertFrameworkComponentsCompatible } from '../utils/framework-components';
21
- import type { CommonCommandOptions } from '../utils/global-flags';
22
- import { type GlobalFlags, parseGlobalFlags } from '../utils/global-flags';
23
- import { handleResult } from '../utils/result-handler';
24
- import { TerminalUI } from '../utils/terminal-ui';
25
-
26
- export interface MigrationEmitOptions extends CommonCommandOptions {
27
- readonly dir: string;
28
- readonly config?: string;
29
- }
30
-
31
- export interface MigrationEmitResult {
32
- readonly ok: boolean;
33
- readonly dir: string;
34
- readonly migrationId: string;
35
- readonly summary: string;
36
- }
37
-
38
- async function executeMigrationEmitCommand(
39
- options: MigrationEmitOptions,
40
- flags: GlobalFlags,
41
- ui: TerminalUI,
42
- ): Promise<Result<MigrationEmitResult, CliStructuredError>> {
43
- const dir = options.dir;
44
-
45
- if (!flags.json && !flags.quiet) {
46
- const header = formatStyledHeader({
47
- command: 'migration emit',
48
- description: 'Emit ops.json from migration.ts and compute migrationId',
49
- details: [{ label: 'dir', value: dir }],
50
- flags,
51
- });
52
- ui.stderr(header);
53
- }
54
-
55
- try {
56
- const config = await loadConfig(options.config);
57
- const migrations = getTargetMigrations(config.target);
58
- if (!migrations) {
59
- throw errorTargetMigrationNotSupported({
60
- why: `Target "${config.target.id}" does not support migrations`,
61
- });
62
- }
63
- const frameworkComponents = assertFrameworkComponentsCompatible(
64
- config.family.familyId,
65
- config.target.targetId,
66
- [config.target, config.adapter, ...(config.extensionPacks ?? [])],
67
- );
68
-
69
- const { migrationId } = await emitMigration(dir, {
70
- targetId: config.target.targetId,
71
- migrations,
72
- frameworkComponents,
73
- });
74
-
75
- return ok({
76
- ok: true,
77
- dir,
78
- migrationId,
79
- summary: `Emitted ops.json and attested migrationId: ${migrationId}`,
80
- });
81
- } catch (error) {
82
- if (CliStructuredError.is(error)) {
83
- return notOk(error);
84
- }
85
- if (MigrationToolsError.is(error)) {
86
- return notOk(
87
- errorRuntime(error.message, {
88
- why: error.why,
89
- fix: error.fix,
90
- meta: { code: error.code, ...(error.details ?? {}) },
91
- }),
92
- );
93
- }
94
- return notOk(
95
- errorUnexpected(error instanceof Error ? error.message : String(error), {
96
- why: `Failed to emit migration: ${error instanceof Error ? error.message : String(error)}`,
97
- }),
98
- );
99
- }
100
- }
101
-
102
- export function createMigrationEmitCommand(): Command {
103
- const command = new Command('emit');
104
- setCommandDescriptions(
105
- command,
106
- 'Emit ops.json from migration.ts and compute migrationId',
107
- 'Evaluates migration.ts in the package directory, resolves it to ops.json,\n' +
108
- 'then computes and persists the content-addressed migrationId in migration.json.\n' +
109
- 'If the file contains unfilled placeholder() slots, emit fails with PN-MIG-2001\n' +
110
- 'and reports the slot to fill in.',
111
- );
112
- setCommandExamples(command, ['prisma-next migration emit --dir migrations/20250101-add-users']);
113
- addGlobalOptions(command)
114
- .requiredOption('--dir <path>', 'Path to the migration package directory')
115
- .option('--config <path>', 'Path to prisma-next.config.ts')
116
- .action(async (options: MigrationEmitOptions) => {
117
- const flags = parseGlobalFlags(options);
118
- const ui = new TerminalUI({ color: flags.color, interactive: flags.interactive });
119
-
120
- const result = await executeMigrationEmitCommand(options, flags, ui);
121
-
122
- const exitCode = handleResult(result, flags, ui, (emitResult) => {
123
- if (flags.json) {
124
- ui.output(JSON.stringify(emitResult, null, 2));
125
- } else if (!flags.quiet) {
126
- ui.log(formatMigrationEmitCommandOutput(emitResult, flags));
127
- }
128
- });
129
-
130
- process.exit(exitCode);
131
- });
132
-
133
- return command;
134
- }
@@ -1,125 +0,0 @@
1
- /**
2
- * Shared helper for emitting `ops.json` and attesting `migration.json` for a
3
- * migration package's `migration.ts`.
4
- *
5
- * Two flows are dispatched here:
6
- * - Descriptor flow (Postgres): the framework evaluates `migration.ts`
7
- * (which re-exports the planner's descriptor list), calls the target's
8
- * `resolveDescriptors` to produce display-oriented operations, writes
9
- * `ops.json`, and attests `migration.json`.
10
- * - Class flow (Mongo): the target's `emit` capability dynamic-imports
11
- * `migration.ts`, instantiates the default-exported `Migration` subclass
12
- * (or invokes the default-exported factory function), reads `operations`,
13
- * and writes `ops.json`. This helper then attests `migration.json` once
14
- * the capability returns.
15
- *
16
- * In both cases attestation is owned by this helper so the on-disk artifacts
17
- * are guaranteed to be fully attested when emit returns.
18
- *
19
- * Note that this helper is the CLI-driven emit path. Class-flow `migration.ts`
20
- * files are also self-emitting via `Migration.run(...)` when run directly;
21
- * that path attests inside `Migration.run` and produces byte-identical
22
- * artifacts. This helper exists primarily to bridge descriptor-flow targets
23
- * and to give `migration plan` a single in-process emit dispatch.
24
- *
25
- * Used by `migration emit` (always) and `migration plan` (always, after
26
- * scaffolding `migration.ts`). Both flows run in-process so that structured
27
- * errors thrown during evaluation (notably `errorUnfilledPlaceholder` with
28
- * code `PN-MIG-2001`) propagate as real exceptions and the CLI's error
29
- * envelope renders them with full structured metadata.
30
- */
31
-
32
- import assert from 'node:assert/strict';
33
- import type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';
34
- import type {
35
- MigrationPlanOperation,
36
- OperationDescriptor,
37
- TargetMigrationsCapability,
38
- } from '@prisma-next/framework-components/control';
39
- import { attestMigration } from '@prisma-next/migration-tools/attestation';
40
- import { readMigrationPackage, writeMigrationOps } from '@prisma-next/migration-tools/io';
41
- import { evaluateMigrationTs, hasMigrationTs } from '@prisma-next/migration-tools/migration-ts';
42
- import { errorMigrationFileMissing, errorTargetMigrationNotSupported } from '../utils/cli-errors';
43
- import { migrationStrategy } from './migration-strategy';
44
-
45
- /**
46
- * Context passed to `emitMigration`. Captures everything the helper needs to
47
- * dispatch to the right flow without re-loading the config.
48
- */
49
- export interface EmitMigrationContext {
50
- readonly targetId: string;
51
- readonly migrations: TargetMigrationsCapability;
52
- readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<string, string>>;
53
- }
54
-
55
- /**
56
- * Result of a successful emit: the operations that were written to `ops.json`
57
- * (display-oriented shape) and the content-addressed migrationId persisted to
58
- * `migration.json`.
59
- */
60
- export interface EmitMigrationResult {
61
- readonly operations: readonly MigrationPlanOperation[];
62
- readonly migrationId: string;
63
- }
64
-
65
- /**
66
- * Emit `ops.json` and attest `migrationId` for the migration package at `dir`.
67
- *
68
- * Dispatches to descriptor flow when the target implements `resolveDescriptors`,
69
- * otherwise to the target's `emit` capability. Throws a structured error if
70
- * `migration.ts` is missing or the target supports neither flow. Other
71
- * structured errors thrown during evaluation propagate unchanged.
72
- */
73
- export async function emitMigration(
74
- dir: string,
75
- ctx: EmitMigrationContext,
76
- ): Promise<EmitMigrationResult> {
77
- if (!(await hasMigrationTs(dir))) {
78
- throw errorMigrationFileMissing(dir);
79
- }
80
-
81
- const strategy = migrationStrategy(ctx.migrations, ctx.targetId);
82
-
83
- if (strategy === 'descriptor') {
84
- return emitDescriptorFlow(dir, ctx.migrations, ctx);
85
- }
86
-
87
- if (!ctx.migrations.emit) {
88
- throw errorTargetMigrationNotSupported({
89
- why: `Target "${ctx.targetId}" does not implement the class-flow \`emit\` capability; cannot emit a migration package`,
90
- });
91
- }
92
-
93
- const operations = await ctx.migrations.emit({
94
- dir,
95
- frameworkComponents: ctx.frameworkComponents,
96
- });
97
- const migrationId = await attestMigration(dir);
98
- return { operations, migrationId };
99
- }
100
-
101
- /**
102
- * Descriptor flow: evaluate `migration.ts` to obtain a list of operation
103
- * descriptors, hand them to the target's `resolveDescriptors` along with the
104
- * manifest's contract bookends, then persist `ops.json` and attest the package.
105
- */
106
- async function emitDescriptorFlow(
107
- dir: string,
108
- migrations: TargetMigrationsCapability,
109
- ctx: EmitMigrationContext,
110
- ): Promise<EmitMigrationResult> {
111
- assert(
112
- migrations.resolveDescriptors,
113
- 'emitDescriptorFlow requires resolveDescriptors; gated by caller',
114
- );
115
- const pkg = await readMigrationPackage(dir);
116
- const descriptors = await evaluateMigrationTs(dir);
117
- const operations = migrations.resolveDescriptors(descriptors as OperationDescriptor[], {
118
- fromContract: pkg.manifest.fromContract,
119
- toContract: pkg.manifest.toContract,
120
- frameworkComponents: ctx.frameworkComponents,
121
- });
122
- await writeMigrationOps(dir, operations);
123
- const migrationId = await attestMigration(dir);
124
- return { operations, migrationId };
125
- }
@@ -1,49 +0,0 @@
1
- /**
2
- * Migration authoring strategy selector.
3
- *
4
- * Targets currently use one of two strategies to author `migration.ts`:
5
- *
6
- * - **Descriptor flow** — the planner produces an `OperationDescriptor[]`
7
- * and `migration.ts` is a `export default () => [...]` file that the CLI
8
- * later replays through `resolveDescriptors` at emit time. Postgres uses
9
- * this today.
10
- * - **Class flow** — the planner produces a `MigrationPlanWithAuthoringSurface`
11
- * that renders itself as a `class M extends Migration { ... }` file. The
12
- * CLI dispatches to the target's `emit` capability at emit time. Mongo
13
- * uses this today.
14
- *
15
- * The two are mutually exclusive at the target level: a migrations capability
16
- * either implements the descriptor-flow trio (`planWithDescriptors`,
17
- * `resolveDescriptors`, `renderDescriptorTypeScript`) or the class-flow
18
- * `emit` hook. `migrationStrategy` discriminates between them by observing
19
- * which hooks are present, and is consumed by `migration new`, `migration
20
- * plan`, and `migration emit` to keep strategy-specific branching in one
21
- * place.
22
- */
23
-
24
- import { errorTargetHasIncompleteMigrationCapabilities } from '@prisma-next/errors/migration';
25
- import type { TargetMigrationsCapability } from '@prisma-next/framework-components/control';
26
-
27
- export type MigrationStrategy = 'descriptor' | 'class-based';
28
-
29
- /**
30
- * Determine which authoring strategy a target uses, based on the shape of
31
- * its `TargetMigrationsCapability`. Callers that need strategy-specific
32
- * guarantees (e.g. that `resolveDescriptors` is present) should narrow on
33
- * the returned tag and trust the capability fields directly rather than
34
- * re-probing.
35
- *
36
- * Throws `errorTargetHasIncompleteMigrationCapabilities` (PN-MIG-2011) when
37
- * the capability registers neither flow. We diagnose this here rather than
38
- * deferring to the dispatch site so a misconfigured target gets an honest
39
- * "incomplete capability" error instead of being silently routed to one
40
- * flow and reported as missing the *other* flow's hook.
41
- */
42
- export function migrationStrategy(
43
- migrations: TargetMigrationsCapability,
44
- targetId: string,
45
- ): MigrationStrategy {
46
- if (migrations.resolveDescriptors) return 'descriptor';
47
- if (migrations.emit) return 'class-based';
48
- throw errorTargetHasIncompleteMigrationCapabilities({ targetId });
49
- }