@prisma-next/cli 0.6.0-dev.1 → 0.6.0-dev.11
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/dist/cli.mjs +5 -5
- package/dist/{client-qVH-rEgd.mjs → client-BCnP7cHo.mjs} +9 -119
- package/dist/client-BCnP7cHo.mjs.map +1 -0
- package/dist/commands/contract-infer.mjs +1 -1
- package/dist/commands/db-init.mjs +3 -3
- package/dist/commands/db-schema.mjs +1 -1
- package/dist/commands/db-sign.mjs +1 -1
- package/dist/commands/db-update.mjs +3 -3
- package/dist/commands/db-verify.mjs +1 -1
- package/dist/commands/migration-apply.d.mts +1 -1
- package/dist/commands/migration-apply.mjs +2 -2
- package/dist/commands/migration-plan.d.mts.map +1 -1
- package/dist/commands/migration-plan.mjs +1 -1
- package/dist/commands/migration-show.d.mts +55 -7
- package/dist/commands/migration-show.d.mts.map +1 -1
- package/dist/commands/migration-show.mjs +153 -46
- package/dist/commands/migration-show.mjs.map +1 -1
- package/dist/commands/migration-status.d.mts.map +1 -1
- package/dist/commands/migration-status.mjs +1 -1
- package/dist/{contract-infer-BK9YFGEG.mjs → contract-infer-ByxhPjpW.mjs} +2 -2
- package/dist/{contract-infer-BK9YFGEG.mjs.map → contract-infer-ByxhPjpW.mjs.map} +1 -1
- package/dist/contract-space-aggregate-loader-BrwKK6Q6.mjs +160 -0
- package/dist/contract-space-aggregate-loader-BrwKK6Q6.mjs.map +1 -0
- package/dist/{db-verify-C0y1PCO2.mjs → db-verify-Czm5T-J4.mjs} +2 -2
- package/dist/{db-verify-C0y1PCO2.mjs.map → db-verify-Czm5T-J4.mjs.map} +1 -1
- package/dist/exports/control-api.d.mts +1 -1
- package/dist/exports/control-api.mjs +1 -1
- package/dist/{init-DETSgw3h.mjs → init-BRKnARU6.mjs} +125 -25
- package/dist/init-BRKnARU6.mjs.map +1 -0
- package/dist/{inspect-live-schema-CWYxGKlb.mjs → inspect-live-schema-DxdBd4Er.mjs} +2 -2
- package/dist/{inspect-live-schema-CWYxGKlb.mjs.map → inspect-live-schema-DxdBd4Er.mjs.map} +1 -1
- package/dist/{migration-command-scaffold-B5dORFEv.mjs → migration-command-scaffold-BdV8JYXV.mjs} +2 -2
- package/dist/{migration-command-scaffold-B5dORFEv.mjs.map → migration-command-scaffold-BdV8JYXV.mjs.map} +1 -1
- package/dist/{migration-plan-C6lVaHsO.mjs → migration-plan-mRu5K81L.mjs} +89 -149
- package/dist/migration-plan-mRu5K81L.mjs.map +1 -0
- package/dist/{migration-status-CZ-D5k7k.mjs → migration-status-By9G5p2H.mjs} +6 -8
- package/dist/{migration-status-CZ-D5k7k.mjs.map → migration-status-By9G5p2H.mjs.map} +1 -1
- package/dist/{migrations-D_UJnpuW.mjs → migrations-CTsyBXCA.mjs} +42 -29
- package/dist/migrations-CTsyBXCA.mjs.map +1 -0
- package/dist/{types-D7x-IFLO.d.mts → types-LItU7E4l.d.mts} +7 -9
- package/dist/{types-D7x-IFLO.d.mts.map → types-LItU7E4l.d.mts.map} +1 -1
- package/package.json +15 -15
- package/src/commands/init/detect-package-manager.ts +28 -4
- package/src/commands/init/errors.ts +0 -16
- package/src/commands/init/exit-codes.ts +1 -1
- package/src/commands/init/hygiene-package-scripts.ts +77 -0
- package/src/commands/init/init.ts +81 -13
- package/src/commands/migration-plan.ts +45 -47
- package/src/commands/migration-show.ts +245 -60
- package/src/commands/migration-status.ts +17 -9
- package/src/control-api/operations/db-apply-aggregate.ts +12 -10
- package/src/control-api/operations/migration-apply.ts +7 -1
- package/src/control-api/types.ts +6 -8
- package/src/utils/contract-space-aggregate-loader.ts +7 -34
- package/src/utils/contract-space-seed-phase.ts +201 -0
- package/src/utils/extension-pack-inputs.ts +47 -55
- package/src/utils/formatters/migrations.ts +80 -38
- package/dist/client-qVH-rEgd.mjs.map +0 -1
- package/dist/extension-pack-inputs-C7xgE-vv.mjs +0 -74
- package/dist/extension-pack-inputs-C7xgE-vv.mjs.map +0 -1
- package/dist/init-DETSgw3h.mjs.map +0 -1
- package/dist/migration-plan-C6lVaHsO.mjs.map +0 -1
- package/dist/migrations-D_UJnpuW.mjs.map +0 -1
- package/src/utils/contract-space-extension-migrations-pass.ts +0 -120
- package/src/utils/contract-space-migrate-pass.ts +0 -156
|
@@ -3,9 +3,9 @@ import { cyan, green, yellow } from "colorette";
|
|
|
3
3
|
//#region src/utils/formatters/migrations.ts
|
|
4
4
|
/**
|
|
5
5
|
* Render a single statement of an `OperationPreview` for the human-readable
|
|
6
|
-
* preview block. SQL statements get a trailing `;` if missing
|
|
7
|
-
* legacy `string[]`-based renderer
|
|
8
|
-
* languages (`'mongodb-shell'`) render verbatim.
|
|
6
|
+
* preview block. SQL statements get a trailing `;` if missing so the rendered
|
|
7
|
+
* preview is byte-identical to the legacy `string[]`-based renderer for SQL
|
|
8
|
+
* targets. Other languages (`'mongodb-shell'`) render verbatim.
|
|
9
9
|
*/
|
|
10
10
|
function renderPreviewStatement(text, language) {
|
|
11
11
|
const trimmed = text.trim();
|
|
@@ -15,9 +15,10 @@ function renderPreviewStatement(text, language) {
|
|
|
15
15
|
}
|
|
16
16
|
/**
|
|
17
17
|
* Choose the header label for a preview block. SQL-only previews keep the
|
|
18
|
-
* legacy `DDL preview` label
|
|
19
|
-
*
|
|
20
|
-
* non-SQL language — use the family-agnostic `Operation preview`
|
|
18
|
+
* legacy `DDL preview` label so the rendered output is byte-identical to the
|
|
19
|
+
* pre-aggregate SQL CLI; previews from any other family — or a mix that
|
|
20
|
+
* includes any non-SQL language — use the family-agnostic `Operation preview`
|
|
21
|
+
* label.
|
|
21
22
|
*
|
|
22
23
|
* An empty `statements` array deliberately renders as `Operation preview`
|
|
23
24
|
* rather than `DDL preview`: `Array.prototype.every` is vacuously true for
|
|
@@ -29,10 +30,9 @@ function previewBlockHeader(preview) {
|
|
|
29
30
|
}
|
|
30
31
|
/**
|
|
31
32
|
* Render the shared per-space execution block consumed by the `db init`
|
|
32
|
-
* / `db update` / `migration apply` summaries
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
* hash (when known).
|
|
33
|
+
* / `db update` / `migration apply` summaries. Always shows: space
|
|
34
|
+
* label (`Extension space: <id>` or `App space`) → per-op lines under
|
|
35
|
+
* each space → per-space marker hash (when known).
|
|
36
36
|
*
|
|
37
37
|
* `mode` controls the marker label phrasing — `'apply'` shows
|
|
38
38
|
* `marker → <hash>` (post-apply), `'plan'` omits the marker line
|
|
@@ -136,42 +136,55 @@ function formatMigrationApplyCommandOutput(result, flags) {
|
|
|
136
136
|
}
|
|
137
137
|
return lines.join("\n");
|
|
138
138
|
}
|
|
139
|
-
function
|
|
140
|
-
if (flags.quiet) return "";
|
|
141
|
-
const lines = [];
|
|
142
|
-
const useColor = flags.color !== false;
|
|
139
|
+
function formatSpaceShowBlock(space, useColor) {
|
|
143
140
|
const formatGreen = createColorFormatter(useColor, green);
|
|
144
141
|
const formatYellow = createColorFormatter(useColor, yellow);
|
|
145
142
|
const formatDimText = (text) => formatDim(useColor, text);
|
|
146
|
-
lines
|
|
147
|
-
lines.push(`${
|
|
148
|
-
lines.push(`${formatDimText(`
|
|
149
|
-
lines.push(`${formatDimText(`
|
|
150
|
-
lines.push(`${formatDimText(`
|
|
143
|
+
const lines = [];
|
|
144
|
+
lines.push(`${formatGreen("✔")} ${space.dirName}`);
|
|
145
|
+
lines.push(`${formatDimText(` from: ${space.from ?? "(baseline)"}`)}`);
|
|
146
|
+
lines.push(`${formatDimText(` to: ${space.to}`)}`);
|
|
147
|
+
lines.push(`${formatDimText(` migrationHash: ${space.migrationHash}`)}`);
|
|
148
|
+
lines.push(`${formatDimText(` created: ${space.createdAt}`)}`);
|
|
151
149
|
lines.push("");
|
|
152
|
-
lines.push(`${
|
|
153
|
-
if (
|
|
150
|
+
lines.push(`${space.operations.length} operation(s)`);
|
|
151
|
+
if (space.operations.length > 0) {
|
|
154
152
|
lines.push(`${formatDimText("│")}`);
|
|
155
|
-
for (let i = 0; i <
|
|
156
|
-
const op =
|
|
157
|
-
const treeChar = i ===
|
|
153
|
+
for (let i = 0; i < space.operations.length; i++) {
|
|
154
|
+
const op = space.operations[i];
|
|
155
|
+
const treeChar = i === space.operations.length - 1 ? "└" : "├";
|
|
158
156
|
const destructiveMarker = op.operationClass === "destructive" ? ` ${formatYellow("(destructive)")}` : "";
|
|
159
157
|
lines.push(`${formatDimText(treeChar)}─ ${op.label}${destructiveMarker}`);
|
|
160
158
|
}
|
|
161
|
-
if (
|
|
159
|
+
if (space.operations.some((op) => op.operationClass === "destructive")) {
|
|
162
160
|
lines.push("");
|
|
163
161
|
lines.push(`${formatYellow("⚠")} This migration contains destructive operations that may cause data loss.`);
|
|
164
162
|
}
|
|
165
163
|
}
|
|
166
|
-
if (
|
|
164
|
+
if (space.preview.statements.length > 0) {
|
|
167
165
|
lines.push("");
|
|
168
|
-
lines.push(`${formatDimText(previewBlockHeader(
|
|
166
|
+
lines.push(`${formatDimText(previewBlockHeader(space.preview))}`);
|
|
169
167
|
lines.push("");
|
|
170
|
-
for (const statement of
|
|
168
|
+
for (const statement of space.preview.statements) {
|
|
171
169
|
const rendered = renderPreviewStatement(statement.text, statement.language);
|
|
172
170
|
if (rendered) lines.push(rendered);
|
|
173
171
|
}
|
|
174
172
|
}
|
|
173
|
+
return lines;
|
|
174
|
+
}
|
|
175
|
+
function formatMigrationShowOutput(result, flags) {
|
|
176
|
+
if (flags.quiet) return "";
|
|
177
|
+
const useColor = flags.color !== false;
|
|
178
|
+
const formatDimText = (text) => formatDim(useColor, text);
|
|
179
|
+
const multipleSpaces = result.spaces.length > 1;
|
|
180
|
+
const lines = [];
|
|
181
|
+
for (let i = 0; i < result.spaces.length; i++) {
|
|
182
|
+
const space = result.spaces[i];
|
|
183
|
+
if (multipleSpaces) lines.push(formatDimText(`── ${space.spaceId} ──`));
|
|
184
|
+
if (space.kind === "missing") lines.push(formatDimText(` ${space.summary}`));
|
|
185
|
+
else for (const line of formatSpaceShowBlock(space, useColor)) lines.push(line);
|
|
186
|
+
if (i < result.spaces.length - 1) lines.push("");
|
|
187
|
+
}
|
|
175
188
|
return lines.join("\n");
|
|
176
189
|
}
|
|
177
190
|
/**
|
|
@@ -213,4 +226,4 @@ function formatMigrationJson(result) {
|
|
|
213
226
|
//#endregion
|
|
214
227
|
export { formatMigrationShowOutput as a, formatMigrationPlanOutput as i, formatMigrationApplyOutput as n, formatMigrationJson as r, formatMigrationApplyCommandOutput as t };
|
|
215
228
|
|
|
216
|
-
//# sourceMappingURL=migrations-
|
|
229
|
+
//# sourceMappingURL=migrations-CTsyBXCA.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrations-CTsyBXCA.mjs","names":[],"sources":["../src/utils/formatters/migrations.ts"],"sourcesContent":["import type { OperationPreview } from '@prisma-next/framework-components/control';\nimport { cyan, green, yellow } from 'colorette';\n\nimport type { AggregatePerSpaceExecutionEntry } from '../../control-api/types';\nimport type { GlobalFlags } from '../global-flags';\nimport { createColorFormatter, formatDim, isVerbose } from './helpers';\n\n/**\n * Render a single statement of an `OperationPreview` for the human-readable\n * preview block. SQL statements get a trailing `;` if missing so the rendered\n * preview is byte-identical to the legacy `string[]`-based renderer for SQL\n * targets. Other languages (`'mongodb-shell'`) render verbatim.\n */\nfunction renderPreviewStatement(text: string, language: string): string | undefined {\n const trimmed = text.trim();\n if (!trimmed) return undefined;\n if (language === 'sql') {\n return trimmed.endsWith(';') ? trimmed : `${trimmed};`;\n }\n return trimmed;\n}\n\n/**\n * Choose the header label for a preview block. SQL-only previews keep the\n * legacy `DDL preview` label so the rendered output is byte-identical to the\n * pre-aggregate SQL CLI; previews from any other family — or a mix that\n * includes any non-SQL language — use the family-agnostic `Operation preview`\n * label.\n *\n * An empty `statements` array deliberately renders as `Operation preview`\n * rather than `DDL preview`: `Array.prototype.every` is vacuously true for\n * empty arrays, but we have no evidence the preview is SQL-only when no\n * statements are present, so the family-agnostic label is the safer default.\n */\nexport function previewBlockHeader(preview: OperationPreview): string {\n const allSql =\n preview.statements.length > 0 && preview.statements.every((s) => s.language === 'sql');\n return allSql ? 'DDL preview' : 'Operation preview';\n}\n\n// ============================================================================\n// Migration Command Output Formatters (shared by db init and db update)\n// ============================================================================\n\n/**\n * Shared CLI output type for migration commands (db init, db update).\n */\nexport interface MigrationCommandResult {\n readonly ok: true;\n readonly mode: 'plan' | 'apply';\n readonly plan: {\n readonly targetId: string;\n readonly destination: {\n readonly storageHash: string;\n readonly profileHash?: string;\n };\n readonly operations: readonly {\n readonly id: string;\n readonly label: string;\n readonly operationClass: string;\n }[];\n /**\n * Family-agnostic textual preview of the planned operations. Replaces the\n * previous `sql?: readonly string[]`. Consumers should read\n * `plan.preview?.statements`.\n */\n readonly preview?: OperationPreview;\n };\n readonly execution?: {\n readonly operationsPlanned: number;\n readonly operationsExecuted: number;\n };\n readonly marker?: {\n readonly storageHash: string;\n readonly profileHash?: string;\n };\n /**\n * Per-space execution breakdown in canonical schedule order\n * (extensions alphabetically, then app). Surfaces per-space markers\n * and the ops grouped by space, so the CLI summary can name which\n * space each op and marker belongs to instead of flattening them\n * into a single ambiguous list. See {@link AggregatePerSpaceExecutionEntry}.\n */\n readonly perSpace?: ReadonlyArray<AggregatePerSpaceExecutionEntry>;\n readonly summary: string;\n readonly timings: {\n readonly total: number;\n };\n}\n\n/**\n * Render the shared per-space execution block consumed by the `db init`\n * / `db update` / `migration apply` summaries. Always shows: space\n * label (`Extension space: <id>` or `App space`) → per-op lines under\n * each space → per-space marker hash (when known).\n *\n * `mode` controls the marker label phrasing — `'apply'` shows\n * `marker → <hash>` (post-apply), `'plan'` omits the marker line\n * entirely (no marker has been written yet).\n */\nexport function formatPerSpaceBlock(\n perSpace: ReadonlyArray<AggregatePerSpaceExecutionEntry>,\n mode: 'plan' | 'apply',\n useColor: boolean,\n): readonly string[] {\n const formatYellow = createColorFormatter(useColor, yellow);\n const formatCyan = createColorFormatter(useColor, cyan);\n const formatDimText = (text: string) => formatDim(useColor, text);\n\n const lines: string[] = [];\n for (let s = 0; s < perSpace.length; s++) {\n const space = perSpace[s]!;\n if (s > 0) lines.push('');\n const header =\n space.kind === 'app'\n ? formatCyan('App space')\n : formatCyan(`Extension space: ${space.spaceId}`);\n lines.push(header);\n if (space.operations.length === 0) {\n lines.push(` ${formatDimText('(no operations)')}`);\n } else {\n for (let i = 0; i < space.operations.length; i++) {\n const op = space.operations[i]!;\n const isLast = i === space.operations.length - 1;\n const treeChar = isLast ? '└' : '├';\n const destructiveMarker =\n op.operationClass === 'destructive' ? ` ${formatYellow('(destructive)')}` : '';\n lines.push(` ${formatDimText(treeChar)}─ ${op.label}${destructiveMarker}`);\n }\n }\n if (mode === 'apply' && space.marker) {\n lines.push(` ${formatDimText(`marker: ${space.marker.storageHash}`)}`);\n }\n }\n return lines;\n}\n\n/**\n * Formats human-readable output for migration commands (db init, db update) in plan mode.\n */\nexport function formatMigrationPlanOutput(\n result: MigrationCommandResult,\n flags: GlobalFlags,\n): string {\n if (flags.quiet) {\n return '';\n }\n\n const lines: string[] = [];\n\n const useColor = flags.color !== false;\n const formatGreen = createColorFormatter(useColor, green);\n const formatDimText = (text: string) => formatDim(useColor, text);\n\n // Plan summary\n const operationCount = result.plan?.operations.length ?? 0;\n const spaceCount = result.perSpace?.length ?? 0;\n if (spaceCount > 0) {\n lines.push(\n `${formatGreen('✔')} Planned ${operationCount} operation(s) across ${spaceCount} contract space${spaceCount === 1 ? '' : 's'}`,\n );\n } else {\n lines.push(`${formatGreen('✔')} Planned ${operationCount} operation(s)`);\n }\n\n const formatYellow = createColorFormatter(useColor, yellow);\n\n // Per-space breakdown takes precedence over the flat ops tree when\n // the aggregate flow surfaced one.\n if (result.perSpace && result.perSpace.length > 0) {\n lines.push('');\n lines.push(...formatPerSpaceBlock(result.perSpace, 'plan', useColor));\n const hasDestructive = result.perSpace.some((s) =>\n s.operations.some((op) => op.operationClass === 'destructive'),\n );\n if (hasDestructive) {\n lines.push('');\n lines.push(\n `${formatYellow('⚠')} This migration contains destructive operations that may cause data loss.`,\n );\n }\n } else if (result.plan?.operations && result.plan.operations.length > 0) {\n // Single-space fallback (no aggregate breakdown). Same flat tree\n // we've always rendered.\n lines.push(`${formatDimText('│')}`);\n for (let i = 0; i < result.plan.operations.length; i++) {\n const op = result.plan.operations[i];\n if (!op) continue;\n const isLast = i === result.plan.operations.length - 1;\n const treeChar = isLast ? '└' : '├';\n const destructiveMarker =\n op.operationClass === 'destructive' ? ` ${formatYellow('(destructive)')}` : '';\n lines.push(`${formatDimText(treeChar)}─ ${op.label}${destructiveMarker}`);\n }\n\n const hasDestructive = result.plan.operations.some((op) => op.operationClass === 'destructive');\n if (hasDestructive) {\n lines.push('');\n lines.push(\n `${formatYellow('⚠')} This migration contains destructive operations that may cause data loss.`,\n );\n }\n }\n\n // Destination hash\n if (result.plan?.destination) {\n lines.push('');\n lines.push(`${formatDimText(`Destination hash: ${result.plan.destination.storageHash}`)}`);\n }\n\n // Statement preview (any family that implements OperationPreviewCapable)\n const preview = result.plan?.preview;\n if (preview) {\n lines.push('');\n lines.push(`${formatDimText(previewBlockHeader(preview))}`);\n if (preview.statements.length === 0) {\n lines.push(`${formatDimText('No operations.')}`);\n } else {\n lines.push('');\n for (const statement of preview.statements) {\n const rendered = renderPreviewStatement(statement.text, statement.language);\n if (rendered) {\n lines.push(rendered);\n }\n }\n }\n }\n\n // Timings in verbose mode\n if (isVerbose(flags, 1)) {\n lines.push(`${formatDimText(`Total time: ${result.timings.total}ms`)}`);\n }\n\n // Note about dry run\n lines.push('');\n lines.push(`${formatDimText('This is a dry run. No changes were applied.')}`);\n lines.push(`${formatDimText('Run without --dry-run to apply changes.')}`);\n\n return lines.join('\\n');\n}\n\nexport interface MigrationApplyCommandOutputResult {\n readonly migrationsApplied: number;\n readonly markerHash: string;\n readonly applied: readonly {\n readonly spaceId: string;\n readonly dirName?: string;\n readonly migrationHash?: string;\n readonly from?: string;\n readonly to?: string;\n readonly operationsExecuted: number;\n }[];\n readonly summary: string;\n /**\n * Per-space breakdown in canonical schedule order (extensions\n * alphabetically, then app). Always present for the aggregate-walking\n * `migration apply` command.\n */\n readonly perSpace: readonly AggregatePerSpaceExecutionEntry[];\n readonly timings?: {\n readonly total: number;\n };\n}\n\nexport function formatMigrationApplyCommandOutput(\n result: MigrationApplyCommandOutputResult,\n flags: GlobalFlags,\n): string {\n if (flags.quiet) {\n return '';\n }\n\n const lines: string[] = [];\n const useColor = flags.color !== false;\n const formatGreen = createColorFormatter(useColor, green);\n const formatDimText = (text: string) => formatDim(useColor, text);\n\n lines.push(`${formatGreen('✔')} ${result.summary}`);\n\n if (result.perSpace.length > 0) {\n lines.push('');\n for (const line of formatPerSpaceBlock(result.perSpace, 'apply', useColor)) {\n lines.push(line);\n }\n }\n\n lines.push('');\n lines.push(formatDimText('Next: prisma-next migration status'));\n\n if (isVerbose(flags, 1) && result.timings) {\n lines.push('');\n lines.push(formatDimText(`Total time: ${result.timings.total}ms`));\n }\n\n return lines.join('\\n');\n}\n\ninterface MigrationShowSpacePresent {\n readonly kind: 'present';\n readonly spaceId: string;\n readonly dirName: string;\n readonly dirPath: string;\n readonly from: string | null;\n readonly to: string;\n readonly migrationHash: string;\n readonly createdAt: string;\n readonly operations: readonly {\n readonly id: string;\n readonly label: string;\n readonly operationClass: string;\n }[];\n readonly preview: OperationPreview;\n readonly summary: string;\n}\n\ninterface MigrationShowSpaceMissing {\n readonly kind: 'missing';\n readonly spaceId: string;\n readonly summary: string;\n}\n\ntype MigrationShowSpaceResult = MigrationShowSpacePresent | MigrationShowSpaceMissing;\n\ninterface MigrationShowResult {\n readonly spaces: readonly MigrationShowSpaceResult[];\n}\n\nfunction formatSpaceShowBlock(\n space: MigrationShowSpacePresent,\n useColor: boolean,\n): readonly string[] {\n const formatGreen = createColorFormatter(useColor, green);\n const formatYellow = createColorFormatter(useColor, yellow);\n const formatDimText = (text: string) => formatDim(useColor, text);\n\n const lines: string[] = [];\n lines.push(`${formatGreen('✔')} ${space.dirName}`);\n lines.push(`${formatDimText(` from: ${space.from ?? '(baseline)'}`)}`);\n lines.push(`${formatDimText(` to: ${space.to}`)}`);\n lines.push(`${formatDimText(` migrationHash: ${space.migrationHash}`)}`);\n lines.push(`${formatDimText(` created: ${space.createdAt}`)}`);\n\n lines.push('');\n lines.push(`${space.operations.length} operation(s)`);\n\n if (space.operations.length > 0) {\n lines.push(`${formatDimText('│')}`);\n for (let i = 0; i < space.operations.length; i++) {\n const op = space.operations[i]!;\n const isLast = i === space.operations.length - 1;\n const treeChar = isLast ? '└' : '├';\n const destructiveMarker =\n op.operationClass === 'destructive' ? ` ${formatYellow('(destructive)')}` : '';\n lines.push(`${formatDimText(treeChar)}─ ${op.label}${destructiveMarker}`);\n }\n\n const hasDestructive = space.operations.some((op) => op.operationClass === 'destructive');\n if (hasDestructive) {\n lines.push('');\n lines.push(\n `${formatYellow('⚠')} This migration contains destructive operations that may cause data loss.`,\n );\n }\n }\n\n if (space.preview.statements.length > 0) {\n lines.push('');\n lines.push(`${formatDimText(previewBlockHeader(space.preview))}`);\n lines.push('');\n for (const statement of space.preview.statements) {\n const rendered = renderPreviewStatement(statement.text, statement.language);\n if (rendered) {\n lines.push(rendered);\n }\n }\n }\n\n return lines;\n}\n\nexport function formatMigrationShowOutput(result: MigrationShowResult, flags: GlobalFlags): string {\n if (flags.quiet) {\n return '';\n }\n\n const useColor = flags.color !== false;\n const formatDimText = (text: string) => formatDim(useColor, text);\n const multipleSpaces = result.spaces.length > 1;\n const lines: string[] = [];\n\n for (let i = 0; i < result.spaces.length; i++) {\n const space = result.spaces[i]!;\n if (multipleSpaces) {\n lines.push(formatDimText(`── ${space.spaceId} ──`));\n }\n if (space.kind === 'missing') {\n lines.push(formatDimText(` ${space.summary}`));\n } else {\n for (const line of formatSpaceShowBlock(space, useColor)) {\n lines.push(line);\n }\n }\n if (i < result.spaces.length - 1) {\n lines.push('');\n }\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Formats human-readable output for migration commands (db init, db update) in apply mode.\n */\nexport function formatMigrationApplyOutput(\n result: MigrationCommandResult,\n flags: GlobalFlags,\n): string {\n if (flags.quiet) {\n return '';\n }\n\n const lines: string[] = [];\n\n const useColor = flags.color !== false;\n const formatGreen = createColorFormatter(useColor, green);\n const formatDimText = (text: string) => formatDim(useColor, text);\n\n if (result.ok) {\n // Success summary\n const executed = result.execution?.operationsExecuted ?? 0;\n const spaceCount = result.perSpace?.length ?? 0;\n\n if (executed === 0) {\n const acrossClause =\n spaceCount > 0 ? ` across ${spaceCount} contract space${spaceCount === 1 ? '' : 's'}` : '';\n lines.push(`${formatGreen('✔')} Database already matches contract${acrossClause}`);\n } else if (spaceCount > 0) {\n lines.push(\n `${formatGreen('✔')} Applied ${executed} operation(s) across ${spaceCount} contract space${spaceCount === 1 ? '' : 's'}`,\n );\n } else {\n lines.push(`${formatGreen('✔')} Applied ${executed} operation(s)`);\n }\n\n // Per-space breakdown — replaces the single ambiguous `Signature:`\n // line with a per-space marker + ops listing.\n if (result.perSpace && result.perSpace.length > 0) {\n lines.push('');\n lines.push(...formatPerSpaceBlock(result.perSpace, 'apply', useColor));\n lines.push('');\n lines.push(\n formatDimText(\n `Run 'prisma-next migration status' to confirm ${\n spaceCount === 1 ? 'the space is' : 'all spaces are'\n } up to date.`,\n ),\n );\n } else if (result.marker) {\n // Single-space fallback (no aggregate breakdown surfaced — e.g.\n // older callers / non-aggregate code paths). The label is\n // `App-space marker` (not `Signature`) so that when only one\n // marker is observable we still name what it covers explicitly.\n lines.push(`${formatDimText(` App-space marker: ${result.marker.storageHash}`)}`);\n if (result.marker.profileHash) {\n lines.push(`${formatDimText(` Profile hash: ${result.marker.profileHash}`)}`);\n }\n }\n\n // Timings in verbose mode\n if (isVerbose(flags, 1)) {\n lines.push(`${formatDimText(` Total time: ${result.timings.total}ms`)}`);\n }\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Formats JSON output for migration commands (db init, db update).\n */\nexport function formatMigrationJson(result: MigrationCommandResult): string {\n return JSON.stringify(result, null, 2);\n}\n"],"mappings":"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"}
|
|
@@ -316,10 +316,10 @@ interface EmitOptions {
|
|
|
316
316
|
* then app — together with the operations attributed to each space and,
|
|
317
317
|
* when the run was applied, the resulting per-space marker hash.
|
|
318
318
|
*
|
|
319
|
-
*
|
|
320
|
-
*
|
|
321
|
-
*
|
|
322
|
-
*
|
|
319
|
+
* Every space involved in a run is observable in the success summary,
|
|
320
|
+
* including its post-apply marker — the per-space marker is visible
|
|
321
|
+
* to the user instead of being collapsed into a single ambiguous
|
|
322
|
+
* top-level hash.
|
|
323
323
|
*/
|
|
324
324
|
interface AggregatePerSpaceExecutionEntry {
|
|
325
325
|
readonly spaceId: string;
|
|
@@ -516,8 +516,6 @@ type EmitResult = Result<EmitSuccess, EmitFailure>;
|
|
|
516
516
|
* through the shared `applyAggregate` primitive. The CLI command
|
|
517
517
|
* just resolves the descriptor surface (config, refs, contract
|
|
518
518
|
* envelope, app-space migration packages) and hands the inputs in.
|
|
519
|
-
*
|
|
520
|
-
* Sub-spec § `migration apply` semantics + § Required changes 1.
|
|
521
519
|
*/
|
|
522
520
|
interface MigrationApplyOptions {
|
|
523
521
|
/** Already-validated app contract (the canonical "where we are heading" hash). */
|
|
@@ -582,8 +580,8 @@ interface MigrationApplyAppliedEntry {
|
|
|
582
580
|
* Successful migrationApply result. Carries both the legacy
|
|
583
581
|
* single-space fields (`markerHash` is the **app member's** post-apply
|
|
584
582
|
* marker, surfaced for back-compat with single-space callers) and the
|
|
585
|
-
* per-space breakdown (`perSpace` — markers / operations
|
|
586
|
-
* order
|
|
583
|
+
* per-space breakdown (`perSpace` — markers / operations in canonical
|
|
584
|
+
* schedule order).
|
|
587
585
|
*/
|
|
588
586
|
/**
|
|
589
587
|
* Path-decision summary for the **app member** post-apply. Surfaced
|
|
@@ -855,4 +853,4 @@ interface ControlClient {
|
|
|
855
853
|
}
|
|
856
854
|
//#endregion
|
|
857
855
|
export { ExecuteDbVerifyOptions as A, EmitSuccess as C, SchemaVerifyOptions as D, OnControlProgress as E, executeDbVerify as M, SignOptions as O, EmitResult as S, MigrationApplyPathDecision as T, DbUpdateSuccess as _, ControlClient as a, EmitFailureCode as b, DbInitFailure as c, DbInitResult as d, DbInitSuccess as f, DbUpdateResult as g, DbUpdateOptions as h, ControlActionName as i, ExecuteDbVerifyResult as j, VerifyOptions as k, DbInitFailureCode as l, DbUpdateFailureCode as m, ContractEmitOptions as n, ControlClientOptions as o, DbUpdateFailure as p, ContractEmitResult as r, ControlProgressEvent as s, AggregatePerSpaceExecutionEntry as t, DbInitOptions as u, EmitContractConfig as v, IntrospectOptions as w, EmitOptions as x, EmitFailure as y };
|
|
858
|
-
//# sourceMappingURL=types-
|
|
856
|
+
//# sourceMappingURL=types-LItU7E4l.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types-
|
|
1
|
+
{"version":3,"file":"types-LItU7E4l.d.mts","names":[],"sources":["../src/control-api/operations/db-verify.ts","../src/control-api/types.ts"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma-next/cli",
|
|
3
|
-
"version": "0.6.0-dev.
|
|
3
|
+
"version": "0.6.0-dev.11",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -27,27 +27,27 @@
|
|
|
27
27
|
"string-width": "^8.2.1",
|
|
28
28
|
"strip-ansi": "^7.2.0",
|
|
29
29
|
"wrap-ansi": "^10.0.0",
|
|
30
|
-
"@prisma-next/config": "0.6.0-dev.
|
|
31
|
-
"@prisma-next/
|
|
32
|
-
"@prisma-next/
|
|
33
|
-
"@prisma-next/
|
|
34
|
-
"@prisma-next/framework-components": "0.6.0-dev.
|
|
35
|
-
"@prisma-next/
|
|
36
|
-
"@prisma-next/
|
|
37
|
-
"@prisma-next/utils": "0.6.0-dev.
|
|
30
|
+
"@prisma-next/config": "0.6.0-dev.11",
|
|
31
|
+
"@prisma-next/emitter": "0.6.0-dev.11",
|
|
32
|
+
"@prisma-next/contract": "0.6.0-dev.11",
|
|
33
|
+
"@prisma-next/errors": "0.6.0-dev.11",
|
|
34
|
+
"@prisma-next/framework-components": "0.6.0-dev.11",
|
|
35
|
+
"@prisma-next/migration-tools": "0.6.0-dev.11",
|
|
36
|
+
"@prisma-next/psl-printer": "0.6.0-dev.11",
|
|
37
|
+
"@prisma-next/utils": "0.6.0-dev.11"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@types/node": "24.10.4",
|
|
41
41
|
"tsdown": "0.22.0",
|
|
42
42
|
"typescript": "5.9.3",
|
|
43
43
|
"vitest": "4.1.5",
|
|
44
|
-
"@prisma-next/sql-contract
|
|
45
|
-
"@prisma-next/sql-contract-
|
|
46
|
-
"@prisma-next/sql-contract": "0.6.0-dev.
|
|
47
|
-
"@prisma-next/sql-operations": "0.6.0-dev.
|
|
48
|
-
"@prisma-next/sql-runtime": "0.6.0-dev.
|
|
49
|
-
"@prisma-next/test-utils": "0.0.1",
|
|
44
|
+
"@prisma-next/sql-contract": "0.6.0-dev.11",
|
|
45
|
+
"@prisma-next/sql-contract-emitter": "0.6.0-dev.11",
|
|
46
|
+
"@prisma-next/sql-contract-ts": "0.6.0-dev.11",
|
|
47
|
+
"@prisma-next/sql-operations": "0.6.0-dev.11",
|
|
48
|
+
"@prisma-next/sql-runtime": "0.6.0-dev.11",
|
|
50
49
|
"@prisma-next/tsconfig": "0.0.0",
|
|
50
|
+
"@prisma-next/test-utils": "0.0.1",
|
|
51
51
|
"@prisma-next/tsdown": "0.0.0"
|
|
52
52
|
},
|
|
53
53
|
"exports": {
|
|
@@ -1,15 +1,39 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs';
|
|
2
|
-
import { detect } from 'package-manager-detector/detect';
|
|
2
|
+
import { detect, getUserAgent } from 'package-manager-detector/detect';
|
|
3
3
|
import { join } from 'pathe';
|
|
4
4
|
|
|
5
5
|
export type PackageManager = 'pnpm' | 'npm' | 'yarn' | 'bun' | 'deno';
|
|
6
6
|
|
|
7
7
|
const KNOWN: ReadonlySet<string> = new Set<PackageManager>(['pnpm', 'npm', 'yarn', 'bun', 'deno']);
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Resolves the package manager `init` should drive for `add` / `install`
|
|
11
|
+
* commands. Tries, in order:
|
|
12
|
+
*
|
|
13
|
+
* 1. **`detect()`** — walks up from `cwd` looking for a lockfile, the
|
|
14
|
+
* `packageManager` field, the `devEngines.packageManager` field, or
|
|
15
|
+
* install metadata. This is the right answer whenever the user is
|
|
16
|
+
* anywhere inside an existing project, including a deep workspace
|
|
17
|
+
* subdirectory.
|
|
18
|
+
*
|
|
19
|
+
* 2. **`getUserAgent()`** — parses `npm_config_user_agent`, the env var
|
|
20
|
+
* every PM sets when it spawns a script. This catches the
|
|
21
|
+
* bare-directory case where there's no project to walk up to but the
|
|
22
|
+
* user invoked us via `pnpm dlx prisma-next init` / `bunx
|
|
23
|
+
* prisma-next init` / `yarn dlx …`. Same signal used by every
|
|
24
|
+
* `create-*` tool in the ecosystem (`create-vite`, `create-next-app`,
|
|
25
|
+
* `create-astro`, `@antfu/ni`, …).
|
|
26
|
+
*
|
|
27
|
+
* 3. **`npm`** — final fallback. Always present alongside Node.
|
|
28
|
+
*/
|
|
9
29
|
export async function detectPackageManager(cwd: string): Promise<PackageManager> {
|
|
10
|
-
const
|
|
11
|
-
if (
|
|
12
|
-
return
|
|
30
|
+
const detected = await detect({ cwd });
|
|
31
|
+
if (detected && KNOWN.has(detected.name)) {
|
|
32
|
+
return detected.name as PackageManager;
|
|
33
|
+
}
|
|
34
|
+
const userAgent = getUserAgent();
|
|
35
|
+
if (userAgent !== null && KNOWN.has(userAgent)) {
|
|
36
|
+
return userAgent as PackageManager;
|
|
13
37
|
}
|
|
14
38
|
return 'npm';
|
|
15
39
|
}
|
|
@@ -1,21 +1,5 @@
|
|
|
1
1
|
import { CliStructuredError } from '../../utils/cli-errors';
|
|
2
2
|
|
|
3
|
-
/**
|
|
4
|
-
* No `package.json` / `deno.json` / `deno.jsonc` in the target directory.
|
|
5
|
-
*
|
|
6
|
-
* `init` cannot bootstrap a fresh project from a bare directory (NG1) — that
|
|
7
|
-
* gap is tracked separately. The fix is for the user to run `npm init` (or
|
|
8
|
-
* the equivalent for their package manager) first.
|
|
9
|
-
*/
|
|
10
|
-
export function errorInitMissingManifest(): CliStructuredError {
|
|
11
|
-
return new CliStructuredError('5001', 'No project manifest found', {
|
|
12
|
-
domain: 'CLI',
|
|
13
|
-
why: 'No package.json or deno.json found in the target directory. `prisma-next init` requires an existing project to attach to.',
|
|
14
|
-
fix: 'Initialize your project first (e.g. `npm init -y` or `deno init`), then re-run `prisma-next init`.',
|
|
15
|
-
docsUrl: 'https://prisma-next.dev/docs/cli/init',
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
|
|
19
3
|
/**
|
|
20
4
|
* Re-init in non-interactive mode without `--force`. Distinct from the
|
|
21
5
|
* decline-the-prompt path (which is `errorInitUserAborted`) because here
|
|
@@ -27,9 +27,9 @@ export const INIT_EXIT_INTERNAL_ERROR = 1;
|
|
|
27
27
|
/**
|
|
28
28
|
* Preconditions not met. The caller asked for something we cannot do
|
|
29
29
|
* without more input or a different environment. Examples:
|
|
30
|
-
* - missing `package.json` / `deno.json`
|
|
31
30
|
* - non-interactive mode without enough flags to proceed
|
|
32
31
|
* - re-init without `--force` in non-interactive mode
|
|
32
|
+
* - malformed `package.json` / `tsconfig.json`
|
|
33
33
|
*/
|
|
34
34
|
export const INIT_EXIT_PRECONDITION = 2;
|
|
35
35
|
|
|
@@ -89,3 +89,80 @@ export function mergePackageScripts(
|
|
|
89
89
|
const trailingNewline = existing.endsWith('\n') ? '\n' : '';
|
|
90
90
|
return { content: `${JSON.stringify(parsed, null, 2)}${trailingNewline}`, warnings };
|
|
91
91
|
}
|
|
92
|
+
|
|
93
|
+
export interface EsmModuleTypeResult {
|
|
94
|
+
/**
|
|
95
|
+
* The new package.json content. `null` when no change is required —
|
|
96
|
+
* either `"type": "module"` is already set, or the user has explicitly
|
|
97
|
+
* opted into a different module type (in which case `warning` is set).
|
|
98
|
+
*/
|
|
99
|
+
readonly content: string | null;
|
|
100
|
+
/**
|
|
101
|
+
* Structured warning raised when `"type"` is already set to a value
|
|
102
|
+
* other than `"module"`. The user's explicit choice is preserved, but
|
|
103
|
+
* the scaffolded `db.ts` uses the ESM-only `with { type: 'json' }`
|
|
104
|
+
* import attribute and will not load under CJS resolution.
|
|
105
|
+
*/
|
|
106
|
+
readonly warning: string | null;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Idempotently sets `"type": "module"` on a `package.json` so the
|
|
111
|
+
* scaffolded `prisma/db.ts` — which uses the ESM-only `with { type: 'json' }`
|
|
112
|
+
* import attribute — loads as ES module under Node's loader (TML-2494).
|
|
113
|
+
*
|
|
114
|
+
* Without this field Node either:
|
|
115
|
+
*
|
|
116
|
+
* - emits `MODULE_TYPELESS_PACKAGE_JSON` and reparses the file as ESM
|
|
117
|
+
* with a perf penalty (Node 22+ with `--experimental-strip-types`), or
|
|
118
|
+
* - hard-fails with `ERR_*` because the CJS loader cannot parse the
|
|
119
|
+
* import-attribute syntax (older Node, or any tool that doesn't
|
|
120
|
+
* reparse).
|
|
121
|
+
*
|
|
122
|
+
* Behaviour:
|
|
123
|
+
*
|
|
124
|
+
* - **Field missing** → set to `"module"`. New entry is inserted right
|
|
125
|
+
* after `"name"` (when present) so the diff lands in a conventional
|
|
126
|
+
* spot for human review; falls through to the natural append position
|
|
127
|
+
* otherwise.
|
|
128
|
+
* - **Field already `"module"`** → no-op (idempotent).
|
|
129
|
+
* - **Field set to anything else** (e.g. `"commonjs"`) → leave it alone
|
|
130
|
+
* and surface a structured warning. The user explicitly opted out of
|
|
131
|
+
* ESM and we don't silently overwrite that.
|
|
132
|
+
*/
|
|
133
|
+
export function ensureEsmModuleType(existing: string): EsmModuleTypeResult {
|
|
134
|
+
const parsed = JSON.parse(existing) as Record<string, unknown>;
|
|
135
|
+
const currentType = parsed['type'];
|
|
136
|
+
|
|
137
|
+
if (currentType === 'module') {
|
|
138
|
+
return { content: null, warning: null };
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (typeof currentType === 'string' && currentType !== 'module') {
|
|
142
|
+
return {
|
|
143
|
+
content: null,
|
|
144
|
+
warning: `package.json declares "type": "${currentType}" — keeping yours, but the scaffolded prisma/db.ts uses an ESM-only import attribute (\`with { type: 'json' }\`) and will not load under that module type.\nIf you want the default, set "type": "module" in package.json.`,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const next: Record<string, unknown> = {};
|
|
149
|
+
let inserted = false;
|
|
150
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
151
|
+
// A non-string `type` slipped past the early-return guards above
|
|
152
|
+
// (those only fire for `'module'` and other strings). Skip it so the
|
|
153
|
+
// normalised `'module'` we inject below cannot be overwritten when
|
|
154
|
+
// `type` appears after `name` in key order.
|
|
155
|
+
if (key === 'type') continue;
|
|
156
|
+
next[key] = value;
|
|
157
|
+
if (!inserted && key === 'name') {
|
|
158
|
+
next['type'] = 'module';
|
|
159
|
+
inserted = true;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
if (!inserted) {
|
|
163
|
+
next['type'] = 'module';
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const trailingNewline = existing.endsWith('\n') ? '\n' : '';
|
|
167
|
+
return { content: `${JSON.stringify(next, null, 2)}${trailingNewline}`, warning: null };
|
|
168
|
+
}
|
|
@@ -2,7 +2,7 @@ import { execFile } from 'node:child_process';
|
|
|
2
2
|
import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
3
3
|
import { promisify } from 'node:util';
|
|
4
4
|
import * as clack from '@clack/prompts';
|
|
5
|
-
import { dirname, isAbsolute, join } from 'pathe';
|
|
5
|
+
import { basename, dirname, isAbsolute, join } from 'pathe';
|
|
6
6
|
import { CliStructuredError } from '../../utils/cli-errors';
|
|
7
7
|
import { formatErrorJson, formatErrorOutput } from '../../utils/formatters/errors';
|
|
8
8
|
import type { GlobalFlags } from '../../utils/global-flags';
|
|
@@ -21,7 +21,6 @@ import {
|
|
|
21
21
|
errorInitInstallFailed,
|
|
22
22
|
errorInitInvalidManifest,
|
|
23
23
|
errorInitInvalidTsconfig,
|
|
24
|
-
errorInitMissingManifest,
|
|
25
24
|
errorInitProbeFailed,
|
|
26
25
|
} from './errors';
|
|
27
26
|
import {
|
|
@@ -34,7 +33,11 @@ import {
|
|
|
34
33
|
} from './exit-codes';
|
|
35
34
|
import { mergeGitattributes, requiredGitattributesLines } from './hygiene-gitattributes';
|
|
36
35
|
import { mergeGitignore } from './hygiene-gitignore';
|
|
37
|
-
import {
|
|
36
|
+
import {
|
|
37
|
+
ensureEsmModuleType,
|
|
38
|
+
mergePackageScripts,
|
|
39
|
+
REQUIRED_SCRIPTS,
|
|
40
|
+
} from './hygiene-package-scripts';
|
|
38
41
|
import { type InitFlagOptions, type ResolvedInitInputs, resolveInitInputs } from './inputs';
|
|
39
42
|
import {
|
|
40
43
|
buildNextSteps,
|
|
@@ -115,10 +118,6 @@ export async function runInit(
|
|
|
115
118
|
clack.intro('prisma-next init', { output: process.stderr });
|
|
116
119
|
}
|
|
117
120
|
|
|
118
|
-
if (!hasProjectManifest(baseDir)) {
|
|
119
|
-
return emitError(ui, flags, errorInitMissingManifest());
|
|
120
|
-
}
|
|
121
|
-
|
|
122
121
|
let inputs: ResolvedInitInputs;
|
|
123
122
|
try {
|
|
124
123
|
inputs = await resolveInitInputs({ baseDir, options, flags, canPrompt });
|
|
@@ -244,10 +243,21 @@ export async function runInit(
|
|
|
244
243
|
// the FR2.1 `@types/node`-presence check. A malformed manifest is
|
|
245
244
|
// mapped to a structured precondition error (5010) rather than the
|
|
246
245
|
// generic INTERNAL_ERROR fallback so CI/agents can branch on it.
|
|
246
|
+
//
|
|
247
|
+
// When neither `package.json` nor a `deno.json[c]` is present, init
|
|
248
|
+
// synthesises a minimal `package.json` (TML-2496) — running
|
|
249
|
+
// `npm init -y` first was friction with no upside, since we always
|
|
250
|
+
// edit the file anyway. A `deno.json[c]` project is left alone:
|
|
251
|
+
// creating a `package.json` next to it would fork the project's
|
|
252
|
+
// dependency graph.
|
|
247
253
|
const packageJsonPath = join(baseDir, 'package.json');
|
|
254
|
+
const packageJsonExisted = existsSync(packageJsonPath);
|
|
255
|
+
const synthesisePackageJson = !packageJsonExisted && !hasProjectManifest(baseDir);
|
|
248
256
|
let parsedPackageJson: Record<string, unknown> | null = null;
|
|
249
|
-
if (
|
|
250
|
-
const pkgRaw =
|
|
257
|
+
if (packageJsonExisted || synthesisePackageJson) {
|
|
258
|
+
const pkgRaw = packageJsonExisted
|
|
259
|
+
? readFileSync(packageJsonPath, 'utf-8')
|
|
260
|
+
: defaultPackageJsonContent(basename(baseDir));
|
|
251
261
|
try {
|
|
252
262
|
parsedPackageJson = JSON.parse(pkgRaw) as Record<string, unknown>;
|
|
253
263
|
} catch (err) {
|
|
@@ -262,11 +272,16 @@ export async function runInit(
|
|
|
262
272
|
}
|
|
263
273
|
|
|
264
274
|
// package.json edits are chained: FR9.2 facade-dep removal first
|
|
265
|
-
// (so the
|
|
275
|
+
// (so the later passes see the cleaned `dependencies` and we round
|
|
266
276
|
// out a single re-stringification), then FR3.5 / FR9.3 idempotent
|
|
267
|
-
// scripts merge with collision detection
|
|
277
|
+
// scripts merge with collision detection, then `"type": "module"`
|
|
278
|
+
// alignment so the ESM-only `with { type: 'json' }` import attribute
|
|
279
|
+
// in the scaffolded `prisma/db.ts` loads cleanly under Node's
|
|
280
|
+
// loader (TML-2494).
|
|
268
281
|
let workingPkg = pkgRaw;
|
|
269
|
-
|
|
282
|
+
// A synthesised manifest is always a write — the file does not
|
|
283
|
+
// exist on disk yet.
|
|
284
|
+
let pkgChanged = synthesisePackageJson;
|
|
270
285
|
if (inputs.removePreviousFacade !== null) {
|
|
271
286
|
const next = removeDependency(workingPkg, inputs.removePreviousFacade);
|
|
272
287
|
if (next !== null) {
|
|
@@ -282,10 +297,23 @@ export async function runInit(
|
|
|
282
297
|
workingPkg = nextPkg;
|
|
283
298
|
pkgChanged = true;
|
|
284
299
|
}
|
|
300
|
+
const { content: typedPkg, warning: typeWarning } = ensureEsmModuleType(workingPkg);
|
|
301
|
+
if (typedPkg !== null) {
|
|
302
|
+
workingPkg = typedPkg;
|
|
303
|
+
pkgChanged = true;
|
|
304
|
+
}
|
|
285
305
|
if (pkgChanged) {
|
|
286
306
|
filesToWrite.push({ path: 'package.json', content: workingPkg });
|
|
287
307
|
}
|
|
288
308
|
warnings.push(...scriptWarnings);
|
|
309
|
+
if (typeWarning !== null) {
|
|
310
|
+
warnings.push(typeWarning);
|
|
311
|
+
}
|
|
312
|
+
if (synthesisePackageJson) {
|
|
313
|
+
warnings.push(
|
|
314
|
+
'No package.json found in the target directory; created a minimal one. Edit `name` / `version` to taste.',
|
|
315
|
+
);
|
|
316
|
+
}
|
|
289
317
|
}
|
|
290
318
|
|
|
291
319
|
// -----------------------------------------------------------------
|
|
@@ -481,7 +509,6 @@ function emitError(ui: TerminalUI, flags: GlobalFlags, error: CliStructuredError
|
|
|
481
509
|
*/
|
|
482
510
|
export function exitCodeForError(error: { readonly code: string }): number {
|
|
483
511
|
switch (error.code) {
|
|
484
|
-
case '5001': // missing manifest — precondition
|
|
485
512
|
case '5002': // re-init needs --force — precondition
|
|
486
513
|
case '5003': // missing flags — precondition
|
|
487
514
|
case '5004': // invalid flag value — precondition
|
|
@@ -823,3 +850,44 @@ function causeMessage(err: unknown): string {
|
|
|
823
850
|
if (err instanceof Error) return err.message;
|
|
824
851
|
return String(err);
|
|
825
852
|
}
|
|
853
|
+
|
|
854
|
+
/**
|
|
855
|
+
* Minimal `package.json` content used when init runs in a directory
|
|
856
|
+
* that has no project manifest (TML-2496). Mirrors the npm 11 `init -y`
|
|
857
|
+
* defaults, with two deliberate deviations:
|
|
858
|
+
*
|
|
859
|
+
* - `"private": true` so a stray `npm publish` cannot leak the
|
|
860
|
+
* placeholder. Users who want to publish have to opt in by removing
|
|
861
|
+
* the field.
|
|
862
|
+
* - `"type": "module"` so the scaffolded ESM imports in
|
|
863
|
+
* `prisma-next.config.ts` and `db.ts` typecheck and run without
|
|
864
|
+
* additional tsconfig coercion.
|
|
865
|
+
*
|
|
866
|
+
* Exported for unit tests so the canonical shape is asserted in one
|
|
867
|
+
* place rather than re-derived at every call site.
|
|
868
|
+
*/
|
|
869
|
+
export function defaultPackageJsonContent(rawName: string): string {
|
|
870
|
+
return `${JSON.stringify(
|
|
871
|
+
{
|
|
872
|
+
name: sanitisePackageName(rawName),
|
|
873
|
+
version: '0.0.0',
|
|
874
|
+
private: true,
|
|
875
|
+
type: 'module',
|
|
876
|
+
},
|
|
877
|
+
null,
|
|
878
|
+
2,
|
|
879
|
+
)}\n`;
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
/**
|
|
883
|
+
* npm package names are restricted to lowercase, no leading dot/underscore,
|
|
884
|
+
* and a small URL-safe character set. `basename(cwd)` happily returns
|
|
885
|
+
* "My Project" or ".hidden" — both rejected by `npm install` validation.
|
|
886
|
+
* Coerce to a safe fallback rather than emit a manifest npm refuses to
|
|
887
|
+
* read.
|
|
888
|
+
*/
|
|
889
|
+
function sanitisePackageName(raw: string): string {
|
|
890
|
+
const lowered = raw.toLowerCase().replace(/[^a-z0-9._~-]/g, '-');
|
|
891
|
+
const trimmed = lowered.replace(/^[._-]+/, '').replace(/-+/g, '-');
|
|
892
|
+
return trimmed.length > 0 ? trimmed : 'my-app';
|
|
893
|
+
}
|