@prisma-next/cli 0.12.0-dev.4 → 0.12.0-dev.40
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.
- package/README.md +2 -2
- package/dist/cli.mjs +180 -163
- package/dist/cli.mjs.map +1 -1
- package/dist/{client-KgJorIvG.mjs → client-BNdG504y.mjs} +80 -56
- package/dist/client-BNdG504y.mjs.map +1 -0
- package/dist/{command-helpers-Bbw1GbwL.mjs → command-helpers-xvg9oq4T.mjs} +301 -23
- package/dist/command-helpers-xvg9oq4T.mjs.map +1 -0
- package/dist/commands/contract-emit.mjs +1 -1
- package/dist/commands/contract-infer.mjs +1 -1
- package/dist/commands/db-init.mjs +4 -5
- package/dist/commands/db-init.mjs.map +1 -1
- package/dist/commands/db-schema.mjs +3 -3
- package/dist/commands/db-sign.mjs +4 -4
- package/dist/commands/db-update.d.mts.map +1 -1
- package/dist/commands/db-update.mjs +10 -7
- package/dist/commands/db-update.mjs.map +1 -1
- package/dist/commands/db-verify.mjs +1 -1
- package/dist/commands/migrate.d.mts +2 -2
- package/dist/commands/migrate.d.mts.map +1 -1
- package/dist/commands/migrate.mjs +6 -8
- package/dist/commands/migrate.mjs.map +1 -1
- package/dist/commands/migration-check.d.mts +55 -1
- package/dist/commands/migration-check.d.mts.map +1 -1
- package/dist/commands/migration-check.mjs +2 -2
- package/dist/commands/migration-graph.d.mts +25 -7
- package/dist/commands/migration-graph.d.mts.map +1 -1
- package/dist/commands/migration-graph.mjs +170 -2
- package/dist/commands/migration-graph.mjs.map +1 -0
- package/dist/commands/migration-list.d.mts +24 -26
- package/dist/commands/migration-list.d.mts.map +1 -1
- package/dist/commands/migration-list.mjs +2 -190
- package/dist/commands/migration-log.d.mts +20 -15
- package/dist/commands/migration-log.d.mts.map +1 -1
- package/dist/commands/migration-log.mjs +1 -137
- package/dist/commands/migration-new.mjs +3 -3
- package/dist/commands/migration-plan.d.mts +1 -1
- package/dist/commands/migration-plan.mjs +1 -1
- package/dist/commands/migration-show.d.mts +1 -4
- package/dist/commands/migration-show.d.mts.map +1 -1
- package/dist/commands/migration-show.mjs +13 -25
- package/dist/commands/migration-show.mjs.map +1 -1
- package/dist/commands/migration-status.d.mts +41 -141
- package/dist/commands/migration-status.d.mts.map +1 -1
- package/dist/commands/migration-status.mjs +2 -759
- package/dist/commands/ref.d.mts +1 -1
- package/dist/commands/ref.mjs +3 -3
- package/dist/commands/telemetry/index.d.mts +7 -0
- package/dist/commands/telemetry/index.d.mts.map +1 -0
- package/dist/commands/telemetry/index.mjs +2 -0
- package/dist/{contract-at-errors-BxP-TOMl.mjs → contract-at-errors-Wj3u4Xco.mjs} +2 -2
- package/dist/{contract-at-errors-BxP-TOMl.mjs.map → contract-at-errors-Wj3u4Xco.mjs.map} +1 -1
- package/dist/{contract-emit-DxcGl4Uq.mjs → contract-emit-COg18szA.mjs} +3 -3
- package/dist/{contract-emit-DxcGl4Uq.mjs.map → contract-emit-COg18szA.mjs.map} +1 -1
- package/dist/{contract-emit-D-4jrNve.mjs → contract-emit-KyJNQK5-.mjs} +3 -3
- package/dist/{contract-emit-D-4jrNve.mjs.map → contract-emit-KyJNQK5-.mjs.map} +1 -1
- package/dist/{contract-infer-D8uEbJuu.mjs → contract-infer-IEp0227u.mjs} +3 -3
- package/dist/{contract-infer-D8uEbJuu.mjs.map → contract-infer-IEp0227u.mjs.map} +1 -1
- package/dist/{contract-space-aggregate-loader-DvZwdkrr.mjs → contract-space-aggregate-loader-BdRPfM3Q.mjs} +63 -5
- package/dist/{contract-space-aggregate-loader-DvZwdkrr.mjs.map → contract-space-aggregate-loader-BdRPfM3Q.mjs.map} +1 -1
- package/dist/{db-verify-v_vUKXTU.mjs → db-verify-C9k5KAyI.mjs} +4 -4
- package/dist/{db-verify-v_vUKXTU.mjs.map → db-verify-C9k5KAyI.mjs.map} +1 -1
- package/dist/exports/control-api.d.mts +2 -2
- package/dist/exports/control-api.d.mts.map +1 -1
- package/dist/exports/control-api.mjs +2 -2
- package/dist/exports/index.mjs +1 -1
- package/dist/exports/init-output.mjs +1 -1
- package/dist/{framework-components-fYXjz_in.mjs → framework-components-Be4inY3I.mjs} +2 -2
- package/dist/{framework-components-fYXjz_in.mjs.map → framework-components-Be4inY3I.mjs.map} +1 -1
- package/dist/{global-flags-DEHjV8_s.d.mts → global-flags-DG4uY5tV.d.mts} +1 -1
- package/dist/{global-flags-DEHjV8_s.d.mts.map → global-flags-DG4uY5tV.d.mts.map} +1 -1
- package/dist/{init-Cv9UzWL5.mjs → init-BIxw3l7t.mjs} +5 -58
- package/dist/init-BIxw3l7t.mjs.map +1 -0
- package/dist/{inspect-live-schema-C6ohV_oQ.mjs → inspect-live-schema-DXUFGQDe.mjs} +3 -3
- package/dist/{inspect-live-schema-C6ohV_oQ.mjs.map → inspect-live-schema-DXUFGQDe.mjs.map} +1 -1
- package/dist/{migration-check-BiBJoYYW.mjs → migration-check-CUavU7U9.mjs} +236 -88
- package/dist/migration-check-CUavU7U9.mjs.map +1 -0
- package/dist/{migration-command-scaffold-CjvwO6at.mjs → migration-command-scaffold-omgKpt3K.mjs} +3 -3
- package/dist/{migration-command-scaffold-CjvwO6at.mjs.map → migration-command-scaffold-omgKpt3K.mjs.map} +1 -1
- package/dist/migration-graph-space-render-ByJ83gxp.mjs +1966 -0
- package/dist/migration-graph-space-render-ByJ83gxp.mjs.map +1 -0
- package/dist/migration-list-jK6QeczE.mjs +228 -0
- package/dist/migration-list-jK6QeczE.mjs.map +1 -0
- package/dist/migration-list-types-DS63IdFd.d.mts +23 -0
- package/dist/migration-list-types-DS63IdFd.d.mts.map +1 -0
- package/dist/migration-log-CW0EjxSr.mjs +215 -0
- package/dist/migration-log-CW0EjxSr.mjs.map +1 -0
- package/dist/migration-path-target-DqcrbOis.mjs +24 -0
- package/dist/migration-path-target-DqcrbOis.mjs.map +1 -0
- package/dist/{migration-plan-9DJ7q7_z.mjs → migration-plan-NHdlUwPG.mjs} +5 -6
- package/dist/{migration-plan-9DJ7q7_z.mjs.map → migration-plan-NHdlUwPG.mjs.map} +1 -1
- package/dist/migration-status-GZ6XfbWs.mjs +439 -0
- package/dist/migration-status-GZ6XfbWs.mjs.map +1 -0
- package/dist/{output-B60Gw5fu.mjs → output-CF_hqzI-.mjs} +1 -1
- package/dist/{output-B60Gw5fu.mjs.map → output-CF_hqzI-.mjs.map} +1 -1
- package/dist/{ref-advancement-DUZqsue6.mjs → ref-advancement-CJY9zOv7.mjs} +1 -1
- package/dist/{ref-advancement-DUZqsue6.mjs.map → ref-advancement-CJY9zOv7.mjs.map} +1 -1
- package/dist/telemetry-DQP0BvKv.mjs +122 -0
- package/dist/telemetry-DQP0BvKv.mjs.map +1 -0
- package/dist/{types-Dt_SfqFm.d.mts → types-Cculk5KV.d.mts} +44 -31
- package/dist/types-Cculk5KV.d.mts.map +1 -0
- package/dist/{verify-DCA9Sldu.mjs → verify-tvHRBBVP.mjs} +2 -2
- package/dist/{verify-DCA9Sldu.mjs.map → verify-tvHRBBVP.mjs.map} +1 -1
- package/package.json +22 -19
- package/src/cli.ts +5 -0
- package/src/commands/db-update.ts +7 -1
- package/src/commands/init/index.ts +6 -35
- package/src/commands/init/init.ts +1 -14
- package/src/commands/init/inputs.ts +0 -75
- package/src/commands/migrate.ts +6 -6
- package/src/commands/migration-check.ts +340 -117
- package/src/commands/migration-graph.ts +163 -90
- package/src/commands/migration-list.ts +55 -25
- package/src/commands/migration-log.ts +49 -98
- package/src/commands/migration-show.ts +10 -38
- package/src/commands/migration-status-overlay.ts +61 -0
- package/src/commands/migration-status.ts +440 -1056
- package/src/commands/telemetry/index.ts +107 -0
- package/src/commands/telemetry/status.ts +67 -0
- package/src/control-api/client.ts +17 -7
- package/src/control-api/operations/db-init.ts +3 -3
- package/src/control-api/operations/{db-apply.ts → db-run.ts} +37 -10
- package/src/control-api/operations/db-update.ts +4 -4
- package/src/control-api/operations/{migration-apply.ts → migrate.ts} +32 -24
- package/src/control-api/operations/{apply.ts → run-migration.ts} +33 -27
- package/src/control-api/types.ts +46 -29
- package/src/utils/cli-errors.ts +47 -2
- package/src/utils/formatters/errors.ts +11 -0
- package/src/utils/formatters/migration-graph-lane-colors.ts +194 -0
- package/src/utils/formatters/migration-graph-layout.ts +51 -7
- package/src/utils/formatters/migration-graph-rows.ts +128 -15
- package/src/utils/formatters/migration-graph-space-render.ts +138 -0
- package/src/utils/formatters/migration-graph-tree-render.ts +405 -77
- package/src/utils/formatters/migration-list-data-column.ts +4 -91
- package/src/utils/formatters/migration-list-graph-topology.ts +68 -90
- package/src/utils/formatters/migration-list-render.ts +122 -70
- package/src/utils/formatters/migration-list-styler.ts +48 -5
- package/src/utils/formatters/migration-log-table.ts +200 -0
- package/src/utils/formatters/migrations.ts +25 -1
- package/src/utils/global-flags.ts +35 -0
- package/src/utils/legend.ts +38 -0
- package/src/utils/migration-path-target.ts +39 -0
- package/src/utils/telemetry.ts +68 -32
- package/dist/client-KgJorIvG.mjs.map +0 -1
- package/dist/command-helpers-Bbw1GbwL.mjs.map +0 -1
- package/dist/commands/migration-list.mjs.map +0 -1
- package/dist/commands/migration-log.mjs.map +0 -1
- package/dist/commands/migration-status.mjs.map +0 -1
- package/dist/extension-pack-inputs-IDvjRCi3.mjs +0 -62
- package/dist/extension-pack-inputs-IDvjRCi3.mjs.map +0 -1
- package/dist/graph-render-rFAqZujX.mjs +0 -1081
- package/dist/graph-render-rFAqZujX.mjs.map +0 -1
- package/dist/init-Cv9UzWL5.mjs.map +0 -1
- package/dist/migration-check-BiBJoYYW.mjs.map +0 -1
- package/dist/migration-graph-D7DVUElV.mjs +0 -1232
- package/dist/migration-graph-D7DVUElV.mjs.map +0 -1
- package/dist/migration-list-styler-BRwF4-gy.mjs +0 -399
- package/dist/migration-list-styler-BRwF4-gy.mjs.map +0 -1
- package/dist/migration-types-D2FW63pr.d.mts +0 -15
- package/dist/migration-types-D2FW63pr.d.mts.map +0 -1
- package/dist/migrations-Cv2jxNNK.mjs +0 -228
- package/dist/migrations-Cv2jxNNK.mjs.map +0 -1
- package/dist/types-Dt_SfqFm.d.mts.map +0 -1
- package/src/utils/formatters/graph-migration-mapper.ts +0 -235
- package/src/utils/formatters/graph-render.ts +0 -1323
- package/src/utils/formatters/graph-types.ts +0 -120
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { userConfigPath, writeUserConfig } from '@prisma-next/cli-telemetry';
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import {
|
|
4
|
+
addGlobalOptions,
|
|
5
|
+
setCommandDescriptions,
|
|
6
|
+
setCommandExamples,
|
|
7
|
+
} from '../../utils/command-helpers';
|
|
8
|
+
import { formatCommandHelp } from '../../utils/formatters/help';
|
|
9
|
+
import {
|
|
10
|
+
type CommonCommandOptions,
|
|
11
|
+
parseGlobalFlags,
|
|
12
|
+
parseGlobalFlagsOrExit,
|
|
13
|
+
} from '../../utils/global-flags';
|
|
14
|
+
import { isCI } from '../../utils/is-ci';
|
|
15
|
+
import { createTerminalUI } from '../../utils/terminal-ui';
|
|
16
|
+
import { formatTelemetryStatusLines, resolveTelemetryStatus } from './status';
|
|
17
|
+
|
|
18
|
+
function createTelemetryStatusCommand(): Command {
|
|
19
|
+
const command = new Command('status');
|
|
20
|
+
setCommandDescriptions(
|
|
21
|
+
command,
|
|
22
|
+
'Show whether anonymous CLI telemetry is enabled and why',
|
|
23
|
+
'Reports whether telemetry is currently enabled or disabled and the reason\n' +
|
|
24
|
+
'(default-on, stored opt-out, environment opt-out, or CI), the path to your\n' +
|
|
25
|
+
'user-level config file, and whether an installation ID has been stored.\n' +
|
|
26
|
+
'Read-only: never sends an event, never mints an ID, never writes anything.',
|
|
27
|
+
);
|
|
28
|
+
return addGlobalOptions(command).action((options: CommonCommandOptions) => {
|
|
29
|
+
const flags = parseGlobalFlagsOrExit(options);
|
|
30
|
+
const ui = createTerminalUI(flags);
|
|
31
|
+
const status = resolveTelemetryStatus({ env: process.env, inCI: isCI() });
|
|
32
|
+
if (flags.json) {
|
|
33
|
+
ui.output(JSON.stringify(status));
|
|
34
|
+
} else {
|
|
35
|
+
for (const line of formatTelemetryStatusLines(status)) {
|
|
36
|
+
ui.output(line);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
process.exit(0);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function createTelemetryEnableCommand(): Command {
|
|
44
|
+
const command = new Command('enable');
|
|
45
|
+
setCommandDescriptions(
|
|
46
|
+
command,
|
|
47
|
+
'Enable anonymous CLI telemetry',
|
|
48
|
+
'Stores "enableTelemetry": true in your user-level config and mints an\n' +
|
|
49
|
+
'installation ID if one is not already stored.',
|
|
50
|
+
);
|
|
51
|
+
return addGlobalOptions(command).action((options: CommonCommandOptions) => {
|
|
52
|
+
const flags = parseGlobalFlagsOrExit(options);
|
|
53
|
+
writeUserConfig({ enableTelemetry: true });
|
|
54
|
+
const ui = createTerminalUI(flags);
|
|
55
|
+
if (flags.json) {
|
|
56
|
+
ui.output(JSON.stringify({ enableTelemetry: true, configPath: userConfigPath() }));
|
|
57
|
+
} else {
|
|
58
|
+
ui.output(`Telemetry enabled. Preference stored in ${userConfigPath()}.`);
|
|
59
|
+
}
|
|
60
|
+
process.exit(0);
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function createTelemetryDisableCommand(): Command {
|
|
65
|
+
const command = new Command('disable');
|
|
66
|
+
setCommandDescriptions(
|
|
67
|
+
command,
|
|
68
|
+
'Disable anonymous CLI telemetry',
|
|
69
|
+
'Stores "enableTelemetry": false in your user-level config. No installation\n' +
|
|
70
|
+
'ID is minted and no event is sent.',
|
|
71
|
+
);
|
|
72
|
+
return addGlobalOptions(command).action((options: CommonCommandOptions) => {
|
|
73
|
+
const flags = parseGlobalFlagsOrExit(options);
|
|
74
|
+
writeUserConfig({ enableTelemetry: false });
|
|
75
|
+
const ui = createTerminalUI(flags);
|
|
76
|
+
if (flags.json) {
|
|
77
|
+
ui.output(JSON.stringify({ enableTelemetry: false, configPath: userConfigPath() }));
|
|
78
|
+
} else {
|
|
79
|
+
ui.output(`Telemetry disabled. Preference stored in ${userConfigPath()}.`);
|
|
80
|
+
}
|
|
81
|
+
process.exit(0);
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function createTelemetryCommand(): Command {
|
|
86
|
+
const command = new Command('telemetry');
|
|
87
|
+
setCommandDescriptions(
|
|
88
|
+
command,
|
|
89
|
+
'Inspect and change anonymous CLI telemetry',
|
|
90
|
+
'Show telemetry status, or enable / disable anonymous CLI usage data.\n' +
|
|
91
|
+
'Telemetry is on by default (opt-out); see https://prisma-next.dev/docs/cli/telemetry\n' +
|
|
92
|
+
'for what is collected and why.',
|
|
93
|
+
);
|
|
94
|
+
setCommandExamples(command, [
|
|
95
|
+
'prisma-next telemetry status',
|
|
96
|
+
'prisma-next telemetry disable',
|
|
97
|
+
'prisma-next telemetry enable',
|
|
98
|
+
]);
|
|
99
|
+
command.configureHelp({
|
|
100
|
+
formatHelp: (cmd) => formatCommandHelp({ command: cmd, flags: parseGlobalFlags({}) }),
|
|
101
|
+
subcommandDescription: () => '',
|
|
102
|
+
});
|
|
103
|
+
command.addCommand(createTelemetryStatusCommand());
|
|
104
|
+
command.addCommand(createTelemetryEnableCommand());
|
|
105
|
+
command.addCommand(createTelemetryDisableCommand());
|
|
106
|
+
return command;
|
|
107
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { readUserConfig, resolveGating, userConfigPath } from '@prisma-next/cli-telemetry';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Why telemetry resolves the way it does, in the order the CLI's
|
|
5
|
+
* `resolveTelemetryGate` evaluates: CI hard-disables first, then the env
|
|
6
|
+
* opt-outs, then the stored `enableTelemetry`, then the opt-out default.
|
|
7
|
+
*/
|
|
8
|
+
export type TelemetryStatusReason =
|
|
9
|
+
| 'ci'
|
|
10
|
+
| 'env-opt-out'
|
|
11
|
+
| 'stored-opt-out'
|
|
12
|
+
| 'stored-opt-in'
|
|
13
|
+
| 'default-on';
|
|
14
|
+
|
|
15
|
+
export interface TelemetryStatus {
|
|
16
|
+
readonly enabled: boolean;
|
|
17
|
+
readonly reason: TelemetryStatusReason;
|
|
18
|
+
readonly configPath: string;
|
|
19
|
+
readonly installationIdStored: boolean;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Resolves the same gate the runtime uses (CI check + `resolveGating`) and
|
|
24
|
+
* projects it into a user-facing status. Pure read: never mints, never
|
|
25
|
+
* writes. The `installationId` value itself is never surfaced — only its
|
|
26
|
+
* presence — so `status` discloses nothing identifying.
|
|
27
|
+
*/
|
|
28
|
+
export function resolveTelemetryStatus(inputs: {
|
|
29
|
+
readonly env: Readonly<Record<string, string | undefined>>;
|
|
30
|
+
readonly inCI: boolean;
|
|
31
|
+
}): TelemetryStatus {
|
|
32
|
+
const config = readUserConfig();
|
|
33
|
+
const configPath = userConfigPath();
|
|
34
|
+
const installationIdStored =
|
|
35
|
+
typeof config.installationId === 'string' && config.installationId.length > 0;
|
|
36
|
+
|
|
37
|
+
if (inputs.inCI) {
|
|
38
|
+
return { enabled: false, reason: 'ci', configPath, installationIdStored };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const gating = resolveGating({ env: inputs.env, config });
|
|
42
|
+
if (!gating.enabled) {
|
|
43
|
+
const reason: TelemetryStatusReason =
|
|
44
|
+
gating.reason === 'env-override' ? 'env-opt-out' : 'stored-opt-out';
|
|
45
|
+
return { enabled: false, reason, configPath, installationIdStored };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const reason: TelemetryStatusReason =
|
|
49
|
+
config.enableTelemetry === true ? 'stored-opt-in' : 'default-on';
|
|
50
|
+
return { enabled: true, reason, configPath, installationIdStored };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const REASON_EXPLANATION: Record<TelemetryStatusReason, string> = {
|
|
54
|
+
ci: 'CI environment detected — telemetry is hard-disabled.',
|
|
55
|
+
'env-opt-out': 'an environment opt-out is set (DO_NOT_TRACK / PRISMA_NEXT_DISABLE_TELEMETRY).',
|
|
56
|
+
'stored-opt-out': '"enableTelemetry": false is stored in your config.',
|
|
57
|
+
'stored-opt-in': '"enableTelemetry": true is stored in your config.',
|
|
58
|
+
'default-on': 'no explicit choice is stored, so the opt-out default applies.',
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export function formatTelemetryStatusLines(status: TelemetryStatus): string[] {
|
|
62
|
+
return [
|
|
63
|
+
`Telemetry is ${status.enabled ? 'enabled' : 'disabled'}: ${REASON_EXPLANATION[status.reason]}`,
|
|
64
|
+
`Config file: ${status.configPath}`,
|
|
65
|
+
`Installation ID: ${status.installationIdStored ? 'stored' : 'not stored'}`,
|
|
66
|
+
];
|
|
67
|
+
}
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
Contract,
|
|
3
|
+
ContractMarkerRecord,
|
|
4
|
+
LedgerEntryRecord,
|
|
5
|
+
} from '@prisma-next/contract/types';
|
|
2
6
|
import { emit as emitContractArtifacts } from '@prisma-next/emitter';
|
|
3
7
|
import type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';
|
|
4
8
|
import type {
|
|
@@ -29,7 +33,7 @@ import { ContractValidationError } from './errors';
|
|
|
29
33
|
import { executeDbInit } from './operations/db-init';
|
|
30
34
|
import { executeDbUpdate } from './operations/db-update';
|
|
31
35
|
import { type ExecuteDbVerifyResult, executeDbVerify } from './operations/db-verify';
|
|
32
|
-
import {
|
|
36
|
+
import { executeMigrate } from './operations/migrate';
|
|
33
37
|
|
|
34
38
|
import type {
|
|
35
39
|
ControlActionName,
|
|
@@ -43,8 +47,8 @@ import type {
|
|
|
43
47
|
EmitOptions,
|
|
44
48
|
EmitResult,
|
|
45
49
|
IntrospectOptions,
|
|
46
|
-
|
|
47
|
-
|
|
50
|
+
MigrateOptions,
|
|
51
|
+
MigrateResult,
|
|
48
52
|
OnControlProgress,
|
|
49
53
|
SchemaVerifyOptions,
|
|
50
54
|
SignOptions,
|
|
@@ -447,9 +451,15 @@ class ControlClientImpl implements ControlClient {
|
|
|
447
451
|
return familyInstance.readAllMarkers({ driver });
|
|
448
452
|
}
|
|
449
453
|
|
|
450
|
-
|
|
454
|
+
/** Reads the per-migration journal; omit `space` to return every space. */
|
|
455
|
+
async readLedger(space?: string): Promise<readonly LedgerEntryRecord[]> {
|
|
456
|
+
const { driver, familyInstance } = await this.ensureConnected();
|
|
457
|
+
return familyInstance.readLedger({ driver, ...ifDefined('space', space) });
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
async migrate(options: MigrateOptions): Promise<MigrateResult> {
|
|
451
461
|
const { onProgress } = options;
|
|
452
|
-
await this.connectWithProgress(options.connection, '
|
|
462
|
+
await this.connectWithProgress(options.connection, 'migrate', onProgress);
|
|
453
463
|
const { driver, familyInstance, frameworkComponents } = await this.ensureConnected();
|
|
454
464
|
|
|
455
465
|
if (!hasMigrations(this.options.target)) {
|
|
@@ -464,7 +474,7 @@ class ControlClientImpl implements ControlClient {
|
|
|
464
474
|
throw new ContractValidationError(message, error);
|
|
465
475
|
}
|
|
466
476
|
|
|
467
|
-
return
|
|
477
|
+
return executeMigrate({
|
|
468
478
|
driver,
|
|
469
479
|
familyInstance,
|
|
470
480
|
contract,
|
|
@@ -8,14 +8,14 @@ import type {
|
|
|
8
8
|
} from '@prisma-next/framework-components/control';
|
|
9
9
|
import { ifDefined } from '@prisma-next/utils/defined';
|
|
10
10
|
import type { DbInitResult, OnControlProgress } from '../types';
|
|
11
|
-
import {
|
|
11
|
+
import { executeRun } from './db-run';
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Options for executing the `db init` operation.
|
|
15
15
|
*
|
|
16
16
|
* `db init` runs the loader → planner → runner pipeline:
|
|
17
17
|
*
|
|
18
|
-
* 1. {@link
|
|
18
|
+
* 1. {@link executeRun} loads a `ContractSpaceAggregate` via
|
|
19
19
|
* {@link import('@prisma-next/migration-tools/aggregate').loadContractSpaceAggregate}
|
|
20
20
|
* from the supplied descriptor set + on-disk on-disk artefacts.
|
|
21
21
|
* 2. The aggregate planner runs with `callerPolicy.ignoreGraphFor`
|
|
@@ -68,7 +68,7 @@ export interface ExecuteDbInitOptions<TFamilyId extends string, TTargetId extend
|
|
|
68
68
|
export async function executeDbInit<TFamilyId extends string, TTargetId extends string>(
|
|
69
69
|
options: ExecuteDbInitOptions<TFamilyId, TTargetId>,
|
|
70
70
|
): Promise<DbInitResult> {
|
|
71
|
-
const result = await
|
|
71
|
+
const result = await executeRun<TFamilyId, TTargetId>({
|
|
72
72
|
driver: options.driver,
|
|
73
73
|
familyInstance: options.familyInstance,
|
|
74
74
|
contract: options.contract,
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Backs `db init` / `db update`. Strategy: introspect → planMigration; synth-for-app + graph-walk-extensions; plan-mode + orphan-marker preflight.
|
|
3
|
+
*/
|
|
4
|
+
|
|
1
5
|
import type { Contract } from '@prisma-next/contract/types';
|
|
2
6
|
import type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';
|
|
3
7
|
import type {
|
|
@@ -5,6 +9,7 @@ import type {
|
|
|
5
9
|
ControlExtensionDescriptor,
|
|
6
10
|
ControlFamilyInstance,
|
|
7
11
|
MigrationOperationPolicy,
|
|
12
|
+
MigrationPlannerConflict,
|
|
8
13
|
MigrationPlanOperation,
|
|
9
14
|
OperationPreview,
|
|
10
15
|
TargetMigrationsCapability,
|
|
@@ -32,14 +37,19 @@ import type {
|
|
|
32
37
|
OnControlProgress,
|
|
33
38
|
PerSpaceExecutionEntry,
|
|
34
39
|
} from '../types';
|
|
35
|
-
import { applyMigration, buildPerSpaceBreakdown, collectOrdered } from './apply';
|
|
36
40
|
import { stripOperations } from './migration-helpers';
|
|
41
|
+
import {
|
|
42
|
+
buildPerSpaceBreakdown,
|
|
43
|
+
collectOrdered,
|
|
44
|
+
type OrderedResolution,
|
|
45
|
+
runMigration,
|
|
46
|
+
} from './run-migration';
|
|
37
47
|
|
|
38
48
|
/**
|
|
39
|
-
* Span IDs emitted via `onProgress` during the
|
|
49
|
+
* Span IDs emitted via `onProgress` during the run flow.
|
|
40
50
|
* Stable identifiers consumed by the structured-output renderer and by
|
|
41
51
|
* tests asserting on span ids. The `apply` span itself is owned by
|
|
42
|
-
* the {@link
|
|
52
|
+
* the {@link runMigration} primitive — only the introspect / plan
|
|
43
53
|
* spans are emitted directly here.
|
|
44
54
|
*/
|
|
45
55
|
const SPAN_IDS = {
|
|
@@ -48,13 +58,13 @@ const SPAN_IDS = {
|
|
|
48
58
|
} as const;
|
|
49
59
|
|
|
50
60
|
/**
|
|
51
|
-
* Inputs shared by `db init` and `db update`
|
|
61
|
+
* Inputs shared by `db init` and `db update` run flows.
|
|
52
62
|
*
|
|
53
63
|
* Accepts the already-validated app contract + descriptor list — the
|
|
54
64
|
* loader gathers the rest from disk + descriptors. The CLI is the
|
|
55
65
|
* descriptor-import boundary; everything downstream is descriptor-free.
|
|
56
66
|
*/
|
|
57
|
-
export interface
|
|
67
|
+
export interface ExecuteRunOptions<TFamilyId extends string, TTargetId extends string> {
|
|
58
68
|
readonly driver: ControlDriverInstance<TFamilyId, TTargetId>;
|
|
59
69
|
readonly familyInstance: ControlFamilyInstance<TFamilyId, unknown>;
|
|
60
70
|
readonly contract: Contract;
|
|
@@ -92,8 +102,8 @@ export interface ExecuteApplyOptions<TFamilyId extends string, TTargetId extends
|
|
|
92
102
|
* transaction across every space; failure on any space rolls back
|
|
93
103
|
* every space's writes.
|
|
94
104
|
*/
|
|
95
|
-
export async function
|
|
96
|
-
options:
|
|
105
|
+
export async function executeRun<TFamilyId extends string, TTargetId extends string>(
|
|
106
|
+
options: ExecuteRunOptions<TFamilyId, TTargetId>,
|
|
97
107
|
): Promise<DbInitResult | DbUpdateResult> {
|
|
98
108
|
const {
|
|
99
109
|
driver,
|
|
@@ -175,6 +185,7 @@ export async function executeApply<TFamilyId extends string, TTargetId extends s
|
|
|
175
185
|
onProgress?.({ action, kind: 'spanEnd', spanId: SPAN_IDS.plan, outcome: 'ok' });
|
|
176
186
|
|
|
177
187
|
const orderedResolutions = collectOrdered(planResult.value.applyOrder, planResult.value.perSpace);
|
|
188
|
+
const plannerWarnings = aggregatePlannerWarnings(orderedResolutions);
|
|
178
189
|
|
|
179
190
|
// The destination's structural shape comes from the app's plan — its
|
|
180
191
|
// `destination` is the storage hash users see in CLI output.
|
|
@@ -202,16 +213,17 @@ export async function executeApply<TFamilyId extends string, TTargetId extends s
|
|
|
202
213
|
preview,
|
|
203
214
|
perSpace,
|
|
204
215
|
summary,
|
|
216
|
+
...ifDefined('warnings', plannerWarnings),
|
|
205
217
|
});
|
|
206
218
|
}
|
|
207
219
|
|
|
208
|
-
// 5.
|
|
220
|
+
// 5. Run mode: hand off to the shared `runMigration` primitive.
|
|
209
221
|
// The runner-driving tail is identical for `db init` / `db update` /
|
|
210
222
|
// `migrate` — only how each caller produces `perSpacePlans`
|
|
211
223
|
// differs (synth + graph-walk via planMigration here; graph-walk
|
|
212
224
|
// only for migrate). Each caller produces perSpacePlans differently;
|
|
213
|
-
// this helper handles the shared
|
|
214
|
-
const applied = await
|
|
225
|
+
// this helper handles the shared run tail.
|
|
226
|
+
const applied = await runMigration({
|
|
215
227
|
aggregate,
|
|
216
228
|
perSpacePlans: planResult.value.perSpace,
|
|
217
229
|
applyOrder: planResult.value.applyOrder,
|
|
@@ -228,6 +240,7 @@ export async function executeApply<TFamilyId extends string, TTargetId extends s
|
|
|
228
240
|
summary: applied.failure.summary,
|
|
229
241
|
...ifDefined('why', applied.failure.why),
|
|
230
242
|
meta: applied.failure.meta,
|
|
243
|
+
...ifDefined('warnings', plannerWarnings),
|
|
231
244
|
});
|
|
232
245
|
}
|
|
233
246
|
|
|
@@ -246,9 +259,17 @@ export async function executeApply<TFamilyId extends string, TTargetId extends s
|
|
|
246
259
|
operationsExecuted: applied.value.totalOpsExecuted,
|
|
247
260
|
perSpace: applied.value.perSpace,
|
|
248
261
|
summary,
|
|
262
|
+
...ifDefined('warnings', plannerWarnings),
|
|
249
263
|
});
|
|
250
264
|
}
|
|
251
265
|
|
|
266
|
+
function aggregatePlannerWarnings(
|
|
267
|
+
orderedResolutions: readonly OrderedResolution[],
|
|
268
|
+
): readonly MigrationPlannerConflict[] | undefined {
|
|
269
|
+
const warnings = orderedResolutions.flatMap((r) => r.entry.warnings ?? []);
|
|
270
|
+
return warnings.length > 0 ? warnings : undefined;
|
|
271
|
+
}
|
|
272
|
+
|
|
252
273
|
/**
|
|
253
274
|
* Compare the live `_prisma_marker` rows against the aggregate's
|
|
254
275
|
* declared members. Any marker row whose `space` is not a member of
|
|
@@ -339,6 +360,7 @@ function wrapPlanResult(args: {
|
|
|
339
360
|
readonly preview: OperationPreview | undefined;
|
|
340
361
|
readonly perSpace: readonly PerSpaceExecutionEntry[];
|
|
341
362
|
readonly summary: string;
|
|
363
|
+
readonly warnings?: readonly MigrationPlannerConflict[];
|
|
342
364
|
}): DbInitResult | DbUpdateResult {
|
|
343
365
|
const success: DbInitSuccess | DbUpdateSuccess = {
|
|
344
366
|
mode: 'plan',
|
|
@@ -352,6 +374,7 @@ function wrapPlanResult(args: {
|
|
|
352
374
|
},
|
|
353
375
|
perSpace: args.perSpace,
|
|
354
376
|
summary: args.summary,
|
|
377
|
+
...ifDefined('warnings', args.warnings),
|
|
355
378
|
};
|
|
356
379
|
return ok(success);
|
|
357
380
|
}
|
|
@@ -363,6 +386,7 @@ function wrapApplyResult(args: {
|
|
|
363
386
|
readonly operationsExecuted: number;
|
|
364
387
|
readonly perSpace: readonly PerSpaceExecutionEntry[];
|
|
365
388
|
readonly summary: string;
|
|
389
|
+
readonly warnings?: readonly MigrationPlannerConflict[];
|
|
366
390
|
}): DbInitResult | DbUpdateResult {
|
|
367
391
|
const success: DbInitSuccess | DbUpdateSuccess = {
|
|
368
392
|
mode: 'apply',
|
|
@@ -380,6 +404,7 @@ function wrapApplyResult(args: {
|
|
|
380
404
|
: { storageHash: args.destination.storageHash },
|
|
381
405
|
perSpace: args.perSpace,
|
|
382
406
|
summary: args.summary,
|
|
407
|
+
...ifDefined('warnings', args.warnings),
|
|
383
408
|
};
|
|
384
409
|
return ok(success);
|
|
385
410
|
}
|
|
@@ -388,6 +413,7 @@ function buildRunnerFailure(args: {
|
|
|
388
413
|
readonly summary: string;
|
|
389
414
|
readonly why?: string;
|
|
390
415
|
readonly meta: Record<string, unknown>;
|
|
416
|
+
readonly warnings?: readonly MigrationPlannerConflict[];
|
|
391
417
|
}): DbInitResult | DbUpdateResult {
|
|
392
418
|
const failure: DbInitFailure | DbUpdateFailure = {
|
|
393
419
|
code: 'RUNNER_FAILED',
|
|
@@ -395,6 +421,7 @@ function buildRunnerFailure(args: {
|
|
|
395
421
|
why: args.why,
|
|
396
422
|
meta: args.meta,
|
|
397
423
|
conflicts: undefined,
|
|
424
|
+
...ifDefined('warnings', args.warnings),
|
|
398
425
|
};
|
|
399
426
|
return notOk(failure) as DbInitResult | DbUpdateResult;
|
|
400
427
|
}
|
|
@@ -9,7 +9,7 @@ import type {
|
|
|
9
9
|
import { ifDefined } from '@prisma-next/utils/defined';
|
|
10
10
|
import { notOk } from '@prisma-next/utils/result';
|
|
11
11
|
import type { DbUpdateResult, OnControlProgress } from '../types';
|
|
12
|
-
import {
|
|
12
|
+
import { executeRun } from './db-run';
|
|
13
13
|
|
|
14
14
|
const DB_UPDATE_POLICY = {
|
|
15
15
|
allowedOperationClasses: ['additive', 'widening', 'destructive'] as const,
|
|
@@ -71,7 +71,7 @@ export async function executeDbUpdate<TFamilyId extends string, TTargetId extend
|
|
|
71
71
|
const gate = await guardDestructiveChanges<TFamilyId, TTargetId>(sharedInputs);
|
|
72
72
|
if (gate !== null) return gate;
|
|
73
73
|
}
|
|
74
|
-
return (await
|
|
74
|
+
return (await executeRun<TFamilyId, TTargetId>({
|
|
75
75
|
...sharedInputs,
|
|
76
76
|
mode: options.mode,
|
|
77
77
|
})) as DbUpdateResult;
|
|
@@ -85,9 +85,9 @@ export async function executeDbUpdate<TFamilyId extends string, TTargetId extend
|
|
|
85
85
|
* run.
|
|
86
86
|
*/
|
|
87
87
|
async function guardDestructiveChanges<TFamilyId extends string, TTargetId extends string>(
|
|
88
|
-
sharedInputs: Omit<Parameters<typeof
|
|
88
|
+
sharedInputs: Omit<Parameters<typeof executeRun<TFamilyId, TTargetId>>[0], 'mode'>,
|
|
89
89
|
): Promise<DbUpdateResult | null> {
|
|
90
|
-
const planResult = (await
|
|
90
|
+
const planResult = (await executeRun<TFamilyId, TTargetId>({
|
|
91
91
|
...sharedInputs,
|
|
92
92
|
mode: 'plan',
|
|
93
93
|
})) as DbUpdateResult;
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Backs the `migrate` command. Strategy: graph-walk-all-members, replay-only (no introspect/synth/planner).
|
|
3
|
+
*/
|
|
4
|
+
|
|
1
5
|
import type { Contract } from '@prisma-next/contract/types';
|
|
2
6
|
import type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';
|
|
3
7
|
import type {
|
|
@@ -7,6 +11,7 @@ import type {
|
|
|
7
11
|
TargetMigrationsCapability,
|
|
8
12
|
} from '@prisma-next/framework-components/control';
|
|
9
13
|
import {
|
|
14
|
+
buildSynthMigrationEdge,
|
|
10
15
|
type ContractMarkerRecordLike,
|
|
11
16
|
type ContractSpaceAggregate,
|
|
12
17
|
type ContractSpaceMember,
|
|
@@ -24,14 +29,14 @@ import {
|
|
|
24
29
|
buildContractSpaceAggregate,
|
|
25
30
|
} from '../../utils/contract-space-aggregate-loader';
|
|
26
31
|
import type {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
32
|
+
MigrateFailure,
|
|
33
|
+
MigratePathDecision,
|
|
34
|
+
MigrateResult,
|
|
35
|
+
MigrateSuccess,
|
|
31
36
|
OnControlProgress,
|
|
32
37
|
PerSpaceExecutionEntry,
|
|
33
38
|
} from '../types';
|
|
34
|
-
import {
|
|
39
|
+
import { buildPerSpaceBreakdown, runMigration } from './run-migration';
|
|
35
40
|
|
|
36
41
|
/**
|
|
37
42
|
* Inputs for the aggregate-walking `migrate` control-api
|
|
@@ -42,7 +47,7 @@ import { applyMigration, buildPerSpaceBreakdown } from './apply';
|
|
|
42
47
|
* is the single descriptor-free seam between the CLI and the
|
|
43
48
|
* aggregate runtime.
|
|
44
49
|
*/
|
|
45
|
-
export interface
|
|
50
|
+
export interface ExecuteMigrateOptions<TFamilyId extends string, TTargetId extends string> {
|
|
46
51
|
readonly driver: ControlDriverInstance<TFamilyId, TTargetId>;
|
|
47
52
|
readonly familyInstance: ControlFamilyInstance<TFamilyId, unknown>;
|
|
48
53
|
/** Already-validated app contract (the canonical "where we are heading" hash). */
|
|
@@ -95,16 +100,16 @@ export interface ExecuteMigrationApplyOptions<TFamilyId extends string, TTargetI
|
|
|
95
100
|
* marker to `member.headRef.hash` (or `refHash` for the app
|
|
96
101
|
* member when provided). Empty-graph members fail loudly — a
|
|
97
102
|
* "never planned" space is a user-error condition for replay.
|
|
98
|
-
* 4. Hand off to {@link
|
|
103
|
+
* 4. Hand off to {@link runMigration} (the runner-driving tail
|
|
99
104
|
* shared with `db init` / `db update`). Marker advancement is
|
|
100
105
|
* inside the per-space transaction.
|
|
101
106
|
*
|
|
102
107
|
* Encodes the replay-only contract: every contract space must have an
|
|
103
108
|
* authored migration graph on disk before this operation can advance it.
|
|
104
109
|
*/
|
|
105
|
-
export async function
|
|
106
|
-
options:
|
|
107
|
-
): Promise<
|
|
110
|
+
export async function executeMigrate<TFamilyId extends string, TTargetId extends string>(
|
|
111
|
+
options: ExecuteMigrateOptions<TFamilyId, TTargetId>,
|
|
112
|
+
): Promise<MigrateResult> {
|
|
108
113
|
const {
|
|
109
114
|
driver,
|
|
110
115
|
familyInstance,
|
|
@@ -276,7 +281,7 @@ export async function executeMigrationApply<TFamilyId extends string, TTargetId
|
|
|
276
281
|
);
|
|
277
282
|
}
|
|
278
283
|
|
|
279
|
-
const applied = await
|
|
284
|
+
const applied = await runMigration({
|
|
280
285
|
aggregate,
|
|
281
286
|
perSpacePlans,
|
|
282
287
|
applyOrder,
|
|
@@ -285,12 +290,12 @@ export async function executeMigrationApply<TFamilyId extends string, TTargetId
|
|
|
285
290
|
migrations,
|
|
286
291
|
frameworkComponents,
|
|
287
292
|
policy: { allowedOperationClasses: ['additive', 'widening', 'destructive', 'data'] },
|
|
288
|
-
action: '
|
|
293
|
+
action: 'migrate',
|
|
289
294
|
...ifDefined('onProgress', onProgress),
|
|
290
295
|
});
|
|
291
296
|
|
|
292
297
|
if (!applied.ok) {
|
|
293
|
-
const failure:
|
|
298
|
+
const failure: MigrateFailure = {
|
|
294
299
|
code: 'RUNNER_FAILED',
|
|
295
300
|
summary: applied.failure.summary,
|
|
296
301
|
why: applied.failure.why,
|
|
@@ -319,7 +324,7 @@ export async function executeMigrationApply<TFamilyId extends string, TTargetId
|
|
|
319
324
|
includeMarkers: true,
|
|
320
325
|
});
|
|
321
326
|
const totalMigrationsApplied = applied.value.orderedResolutions.reduce(
|
|
322
|
-
(sum, r) => sum +
|
|
327
|
+
(sum, r) => sum + r.entry.migrationEdges.length,
|
|
323
328
|
0,
|
|
324
329
|
);
|
|
325
330
|
const summary = `Applied ${totalMigrationsApplied} migration(s) (${applied.value.totalOpsExecuted} operation(s)) across ${orderedAll.length} contract space(s)`;
|
|
@@ -361,7 +366,13 @@ function buildAtHeadResolution(args: {
|
|
|
361
366
|
displayOps: [],
|
|
362
367
|
destinationContract: member.contract(),
|
|
363
368
|
strategy: 'graph-walk',
|
|
364
|
-
migrationEdges: [
|
|
369
|
+
migrationEdges: [
|
|
370
|
+
buildSynthMigrationEdge({
|
|
371
|
+
currentMarkerStorageHash: liveMarker?.storageHash,
|
|
372
|
+
destinationStorageHash: targetHash,
|
|
373
|
+
operationCount: 0,
|
|
374
|
+
}),
|
|
375
|
+
],
|
|
365
376
|
};
|
|
366
377
|
}
|
|
367
378
|
|
|
@@ -389,9 +400,9 @@ interface BuildSuccessArgs {
|
|
|
389
400
|
readonly summary: string;
|
|
390
401
|
}
|
|
391
402
|
|
|
392
|
-
function buildSuccess(args: BuildSuccessArgs):
|
|
403
|
+
function buildSuccess(args: BuildSuccessArgs): MigrateSuccess {
|
|
393
404
|
// The marker hash surfaced at the top level is the **app member's**
|
|
394
|
-
// post-
|
|
405
|
+
// post-migrate marker (the top-level `markerHash` field).
|
|
395
406
|
// Per-space markers live on `perSpace[].marker.storageHash`.
|
|
396
407
|
const appResolution = args.orderedResolutions.find(
|
|
397
408
|
(r) => r.spaceId === args.aggregate.app.spaceId,
|
|
@@ -404,7 +415,7 @@ function buildSuccess(args: BuildSuccessArgs): MigrationApplySuccess {
|
|
|
404
415
|
// JSON-shape consumers (e.g. `parsed.applied.length` in integration
|
|
405
416
|
// tests). The aggregate per-space breakdown lives on `perSpace[]`.
|
|
406
417
|
const applied = args.orderedResolutions.flatMap((r) => {
|
|
407
|
-
const edges = r.entry.migrationEdges
|
|
418
|
+
const edges = r.entry.migrationEdges;
|
|
408
419
|
return edges.map((edge) => ({
|
|
409
420
|
spaceId: r.spaceId,
|
|
410
421
|
dirName: edge.dirName,
|
|
@@ -416,7 +427,7 @@ function buildSuccess(args: BuildSuccessArgs): MigrationApplySuccess {
|
|
|
416
427
|
});
|
|
417
428
|
|
|
418
429
|
const appPlan = appResolution?.entry;
|
|
419
|
-
const pathDecision:
|
|
430
|
+
const pathDecision: MigratePathDecision | undefined = appPlan?.pathDecision
|
|
420
431
|
? {
|
|
421
432
|
fromHash: appPlan.pathDecision.fromHash,
|
|
422
433
|
toHash: appPlan.pathDecision.toHash,
|
|
@@ -455,10 +466,7 @@ function buildSuccess(args: BuildSuccessArgs): MigrationApplySuccess {
|
|
|
455
466
|
*
|
|
456
467
|
* @internal Exported for testing only.
|
|
457
468
|
*/
|
|
458
|
-
export function buildNeverPlannedFailure(
|
|
459
|
-
spaceId: string,
|
|
460
|
-
targetHash: string,
|
|
461
|
-
): MigrationApplyFailure {
|
|
469
|
+
export function buildNeverPlannedFailure(spaceId: string, targetHash: string): MigrateFailure {
|
|
462
470
|
return {
|
|
463
471
|
code: 'MIGRATION_PATH_NOT_FOUND',
|
|
464
472
|
summary: `No on-disk migrations for contract space "${spaceId}"`,
|
|
@@ -481,7 +489,7 @@ export function buildPathNotFoundFailure(
|
|
|
481
489
|
spaceId: string,
|
|
482
490
|
marker: ContractMarkerRecordLike | null,
|
|
483
491
|
targetHash: string,
|
|
484
|
-
):
|
|
492
|
+
): MigrateFailure {
|
|
485
493
|
const fromHash = marker?.storageHash ?? '<empty>';
|
|
486
494
|
// The app-case phrasing names the user-visible condition (a
|
|
487
495
|
// contract has been emitted that no on-disk migration reaches) so
|