@prisma/orm-toolchain 8.0.0-rc.1-dev.35 → 8.0.0-rc.1-dev.37
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/bin__prisma-next.mjs +5 -5
- package/dist/bin__prisma-next.mjs.map +1 -1
- package/dist/{cli-errors-f5PRtVdm-C6xVKeQn.d.mts → cli-errors-WMw54cyq-DC2OYnd7.d.mts} +5 -3
- package/dist/{cli-errors-f5PRtVdm-C6xVKeQn.d.mts.map → cli-errors-WMw54cyq-DC2OYnd7.d.mts.map} +1 -1
- package/dist/cli.mjs +472 -20
- package/dist/cli.mjs.map +1 -1
- package/dist/cli__commands__contract-emit.mjs +1 -1
- package/dist/cli__commands__migrate.d.mts +2 -2
- package/dist/cli__commands__migration-graph.d.mts +1 -1
- package/dist/cli__commands__migration-list.d.mts +1 -1
- package/dist/cli__commands__migration-log.d.mts +1 -1
- package/dist/cli__commands__migration-plan.d.mts +1 -1
- package/dist/cli__commands__migration-status.d.mts +1 -1
- package/dist/cli__control-api.d.mts +3 -3
- package/dist/cli__control-api.mjs +2 -2
- package/dist/cli__control-api__testing.d.mts +1 -1
- package/dist/contract-emit-BHZYuA91-wlnU7OrE.mjs +2 -0
- package/dist/{contract-emit-BlvUNMHM-BEioUVR5.mjs → contract-emit-Cpj5Qz7z-BXt3HGPC.mjs} +3 -3
- package/dist/{contract-emit-BlvUNMHM-BEioUVR5.mjs.map → contract-emit-Cpj5Qz7z-BXt3HGPC.mjs.map} +1 -1
- package/dist/{contract-emit-CrYO0A8x-60BOqXFr.mjs → contract-emit-Dp1pe06_-Cdpvh5DH.mjs} +3 -3
- package/dist/{contract-emit-CrYO0A8x-60BOqXFr.mjs.map → contract-emit-Dp1pe06_-Cdpvh5DH.mjs.map} +1 -1
- package/dist/{format-D5x0jz7q-xalz6Fkn.mjs → format-DceifGAK-BJhTdkcO.mjs} +8 -5
- package/dist/format-DceifGAK-BJhTdkcO.mjs.map +1 -0
- package/dist/{init-CWI_P7Cj-BXq9iChN.mjs → init-DMiJjbrC-C7-PvDyK.mjs} +3 -3
- package/dist/{init-CWI_P7Cj-BXq9iChN.mjs.map → init-DMiJjbrC-C7-PvDyK.mjs.map} +1 -1
- package/dist/{migrate-show-DutwCc2F-BhGfH7D-.d.mts → migrate-show-DRfCIamX-BK6CN3RI.d.mts} +3 -3
- package/dist/{migrate-show-DutwCc2F-BhGfH7D-.d.mts.map → migrate-show-DRfCIamX-BK6CN3RI.d.mts.map} +1 -1
- package/dist/{migration-plan-4cnnP6yM-DXzRfi_A.d.mts → migration-plan-DPp3Orhx-6edvA2e2.d.mts} +3 -3
- package/dist/{migration-plan-4cnnP6yM-DXzRfi_A.d.mts.map → migration-plan-DPp3Orhx-6edvA2e2.d.mts.map} +1 -1
- package/dist/vite-plugin-contract-emit.mjs +1 -1
- package/package.json +12 -12
- package/dist/contract-emit-Csa6R0gt-DvxFlS0O.mjs +0 -2
- package/dist/format-D5x0jz7q-xalz6Fkn.mjs.map +0 -1
package/dist/cli.mjs
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { i as loadConfig } from "./exports-BZLNbtkY.mjs";
|
|
2
|
-
import { F as requireLiveDatabase, I as runCommandAction, N as errorUnexpected, a as errorConfigValidation$1, b as errorNoMigrations, c as errorDatabaseConnectionRequired, d as errorFileNotFound, h as errorLegendHumanOnly, j as errorTargetMigrationNotSupported, s as errorContractValidationFailed, t as CliStructuredError$1$1, u as errorDriverRequired, v as errorMigrationPackageNotFound } from "./cli-errors-C6_pH59O-CzD4SYcJ.mjs";
|
|
2
|
+
import { F as requireLiveDatabase, I as runCommandAction, N as errorUnexpected, O as errorRuntime$1, a as errorConfigValidation$1, b as errorNoMigrations, c as errorDatabaseConnectionRequired, d as errorFileNotFound, h as errorLegendHumanOnly, j as errorTargetMigrationNotSupported, s as errorContractValidationFailed, t as CliStructuredError$1$1, u as errorDriverRequired, v as errorMigrationPackageNotFound } from "./cli-errors-C6_pH59O-CzD4SYcJ.mjs";
|
|
3
3
|
import { r as getEmittedArtifactPaths } from "./exports-BCLg4CiV-05kuwcb0.mjs";
|
|
4
|
+
import { n as executeContractEmit } from "./contract-emit-Dp1pe06_-Cdpvh5DH.mjs";
|
|
4
5
|
import { h as renderPreviewStatement, m as previewBlockHeader } from "./terminal-ui-Cqz4LVL7-B0mcVdLy.mjs";
|
|
5
6
|
import { c as spaceMigrationDirectory } from "./verify-contract-spaces-DhJTb0zM-_oh6W6lp.mjs";
|
|
6
7
|
import { S as targetSupportsMigrations, f as maskConnectionUrl, n as closeQuietly, v as sanitizeErrorMessage } from "./command-helpers-kD9CO1hd-BPhnkBin.mjs";
|
|
7
|
-
import { t as createContractEmitCommand } from "./contract-emit-
|
|
8
|
-
import { t as createFormatCommand } from "./format-
|
|
8
|
+
import { t as createContractEmitCommand } from "./contract-emit-Cpj5Qz7z-BXt3HGPC.mjs";
|
|
9
|
+
import { n as executeFormat, t as createFormatCommand } from "./format-DceifGAK-BJhTdkcO.mjs";
|
|
9
10
|
import { a as loadContractSpaceAggregateForCli, r as buildReadAggregate, s as refuseContractSpaceIntegrity, u as toDeclaredExtensionsFromRaw } from "./contract-space-aggregate-loader-BpdB-mHG-BiU0IUeb.mjs";
|
|
10
11
|
import { t as createControlClient } from "./client-BqhVohc5-DFRVWFps.mjs";
|
|
11
12
|
import { a as readContractIR, o as resolveRefAdvancementFields, t as advanceRefSafely } from "./ref-advancement-DaZBzm7m-WoqnFAyr.mjs";
|
|
@@ -22,25 +23,27 @@ import { n as looksLikePath, r as resolveAppTargetPath, t as findPackageByDirPat
|
|
|
22
23
|
import { t as buildMigrationSpaceGraphEntries } from "./migration-graph-DmdVVJoZ-DDBKjUMz.mjs";
|
|
23
24
|
import { n as renderMigrationGraphDot, r as renderMigrationGraphSections, t as buildMigrationGraphTreeSections } from "./migration-graph-sections-BWcFCOL6-_G0Wb4QR.mjs";
|
|
24
25
|
import { a as sortLedgerEntries, i as serializeLedgerEntriesForJson, n as formatLedgerAppliedAt, o as styleHashTransition, t as MIGRATION_LOG_EMPTY_MESSAGE } from "./migration-log-table-DRiOnvzf-zTQBThqe.mjs";
|
|
26
|
+
import { n as executeRefListCommand, r as executeRefSetCommand, t as executeRefDeleteCommand } from "./ref-CVD6j3jA-BAgpZLNM.mjs";
|
|
25
27
|
import { CliStructuredError } from "@prisma/orm-framework/errors/control";
|
|
26
28
|
import { ifDefined } from "@prisma/orm-framework/utils/defined";
|
|
27
|
-
import { join, normalize, relative, resolve } from "pathe";
|
|
29
|
+
import { basename, dirname, join, normalize, relative, resolve } from "pathe";
|
|
28
30
|
import { existsSync, unlinkSync, writeFileSync } from "node:fs";
|
|
29
31
|
import { DOCS_BASE, isStructuredError } from "@prisma/orm-framework/utils/structured-error";
|
|
30
32
|
import { blindCast, castAs } from "@prisma/orm-framework/utils/casts";
|
|
31
33
|
import { InternalError } from "@prisma/orm-framework/utils/internal-error";
|
|
32
|
-
import { readFile } from "node:fs/promises";
|
|
34
|
+
import { mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
|
|
33
35
|
import { APP_SPACE_ID, createControlStack } from "@prisma/orm-framework/components/control";
|
|
34
36
|
import { collectConfigIssues } from "@prisma/orm-framework/config/config-validation";
|
|
35
37
|
import { tmpdir } from "node:os";
|
|
38
|
+
import { printPsl } from "@prisma/orm-framework/psl-printer";
|
|
36
39
|
import { defineCommand, defineCommandFamily, defineConfigSection, flag, positional } from "@prisma/cli-engine";
|
|
37
40
|
import { CliStructuredError as CliStructuredError$1, notOk, ok } from "@prisma/cli-engine/protocol";
|
|
38
41
|
import { pathToFileURL } from "node:url";
|
|
39
42
|
import { build } from "esbuild";
|
|
40
|
-
//#region ../../../1-framework/3-tooling/cli/dist/load-config-
|
|
43
|
+
//#region ../../../1-framework/3-tooling/cli/dist/load-config-Db2bTG_C.mjs
|
|
41
44
|
const MISSING_CONFIG_ACTION = {
|
|
42
45
|
kind: "run-command",
|
|
43
|
-
label: "Create a
|
|
46
|
+
label: "Create a config file",
|
|
44
47
|
command: "prisma-next init"
|
|
45
48
|
};
|
|
46
49
|
function editConfigAction(field) {
|
|
@@ -260,16 +263,6 @@ function defineOrmCommand(def) {
|
|
|
260
263
|
}
|
|
261
264
|
});
|
|
262
265
|
}
|
|
263
|
-
/**
|
|
264
|
-
* The database connection override, declared from here by every command that
|
|
265
|
-
* accepts one so its brief and placeholder cannot drift apart. Resolution
|
|
266
|
-
* order is the flag, then `config.db.connection`, then
|
|
267
|
-
* `CONFIG.DB_CONNECTION_REQUIRED`.
|
|
268
|
-
*/
|
|
269
|
-
const dbFlag = flag.string({
|
|
270
|
-
brief: "Database connection string",
|
|
271
|
-
placeholder: "url"
|
|
272
|
-
});
|
|
273
266
|
const OUTCOMES = {
|
|
274
267
|
ok: "ok",
|
|
275
268
|
skipped: "skipped",
|
|
@@ -302,6 +295,267 @@ function controlProgressReporter(report) {
|
|
|
302
295
|
});
|
|
303
296
|
};
|
|
304
297
|
}
|
|
298
|
+
function hashRows(document) {
|
|
299
|
+
return {
|
|
300
|
+
kind: "fields",
|
|
301
|
+
rows: [
|
|
302
|
+
{
|
|
303
|
+
label: "storageHash",
|
|
304
|
+
value: [{
|
|
305
|
+
text: document.storageHash,
|
|
306
|
+
tone: "identifier"
|
|
307
|
+
}]
|
|
308
|
+
},
|
|
309
|
+
...document.executionHash === void 0 ? [] : [{
|
|
310
|
+
label: "executionHash",
|
|
311
|
+
value: [{
|
|
312
|
+
text: document.executionHash,
|
|
313
|
+
tone: "identifier"
|
|
314
|
+
}]
|
|
315
|
+
}],
|
|
316
|
+
{
|
|
317
|
+
label: "profileHash",
|
|
318
|
+
value: [{
|
|
319
|
+
text: document.profileHash,
|
|
320
|
+
tone: "identifier"
|
|
321
|
+
}]
|
|
322
|
+
}
|
|
323
|
+
]
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
function emitPresentations(inputs) {
|
|
327
|
+
const { document, cwd } = inputs;
|
|
328
|
+
return {
|
|
329
|
+
human: () => [
|
|
330
|
+
{
|
|
331
|
+
kind: "fields",
|
|
332
|
+
rail: true,
|
|
333
|
+
rows: [{
|
|
334
|
+
label: "contract",
|
|
335
|
+
value: relative(cwd, document.files.json)
|
|
336
|
+
}, {
|
|
337
|
+
label: "types",
|
|
338
|
+
value: relative(cwd, document.files.dts)
|
|
339
|
+
}]
|
|
340
|
+
},
|
|
341
|
+
{
|
|
342
|
+
kind: "summary",
|
|
343
|
+
status: "ok",
|
|
344
|
+
text: "Emitted contract.json and contract.d.ts"
|
|
345
|
+
},
|
|
346
|
+
hashRows(document)
|
|
347
|
+
],
|
|
348
|
+
stdout: () => [document.files.json, document.files.dts],
|
|
349
|
+
json: () => document
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
function createContractEmitCommand$1({ executeContractEmit }) {
|
|
353
|
+
return defineOrmCommand({
|
|
354
|
+
help: {
|
|
355
|
+
summary: "Emit your contract artifacts",
|
|
356
|
+
description: "Reads your contract source (TypeScript or Prisma schema) and emits\ncontract.json and contract.d.ts. The contract.json contains the canonical\ncontract structure, and contract.d.ts provides TypeScript types for\ntype-safe query building. Offline — does not consult the database.",
|
|
357
|
+
examples: [
|
|
358
|
+
"contract emit",
|
|
359
|
+
"contract emit --output-path ./generated",
|
|
360
|
+
"contract emit --json"
|
|
361
|
+
]
|
|
362
|
+
},
|
|
363
|
+
args: { flags: { outputPath: flag.string({
|
|
364
|
+
brief: "Directory to write contract.json and contract.d.ts into",
|
|
365
|
+
placeholder: "dir"
|
|
366
|
+
}) } },
|
|
367
|
+
needs: { config: ormConfigSection },
|
|
368
|
+
handler: async (args, ctx) => {
|
|
369
|
+
const startedAt = Date.now();
|
|
370
|
+
const outputPath = args.flags.outputPath === void 0 ? void 0 : resolve(ctx.cwd, args.flags.outputPath);
|
|
371
|
+
const result = await executeContractEmit({
|
|
372
|
+
config: ctx.config,
|
|
373
|
+
cwd: ctx.cwd,
|
|
374
|
+
onProgress: controlProgressReporter(ctx.report),
|
|
375
|
+
signal: ctx.signal,
|
|
376
|
+
...ifDefined("outputPath", outputPath)
|
|
377
|
+
});
|
|
378
|
+
if (result.validationWarning !== void 0) ctx.report({
|
|
379
|
+
kind: "message",
|
|
380
|
+
severity: "warn",
|
|
381
|
+
text: result.validationWarning
|
|
382
|
+
});
|
|
383
|
+
const document = {
|
|
384
|
+
ok: true,
|
|
385
|
+
storageHash: result.storageHash,
|
|
386
|
+
...ifDefined("executionHash", result.executionHash),
|
|
387
|
+
profileHash: result.profileHash,
|
|
388
|
+
outDir: dirname(result.files.json),
|
|
389
|
+
files: result.files,
|
|
390
|
+
timings: { total: Date.now() - startedAt }
|
|
391
|
+
};
|
|
392
|
+
ctx.report({
|
|
393
|
+
kind: "message",
|
|
394
|
+
severity: "verbose",
|
|
395
|
+
text: `Total time: ${document.timings.total}ms`
|
|
396
|
+
});
|
|
397
|
+
return ok(ctx.present({ data: document }, emitPresentations({
|
|
398
|
+
document,
|
|
399
|
+
cwd: ctx.cwd
|
|
400
|
+
})));
|
|
401
|
+
}
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
const contractEmitCommand = createContractEmitCommand$1({ executeContractEmit });
|
|
405
|
+
/**
|
|
406
|
+
* Writes a generated file the way `contract emit` publishes its pair: the
|
|
407
|
+
* bytes land in a temporary file beside the target and are renamed over it, so
|
|
408
|
+
* a run interrupted mid-write leaves the previous file intact rather than a
|
|
409
|
+
* truncated one.
|
|
410
|
+
*/
|
|
411
|
+
async function publishTextArtifact(inputs) {
|
|
412
|
+
const directory = dirname(inputs.path);
|
|
413
|
+
const tempPath = join(directory, `.${basename(inputs.path)}.${process.pid}.${inputs.publicationToken}.next.tmp`);
|
|
414
|
+
await mkdir(directory, { recursive: true });
|
|
415
|
+
try {
|
|
416
|
+
await writeFile(tempPath, inputs.content, "utf-8");
|
|
417
|
+
await rename(tempPath, inputs.path);
|
|
418
|
+
} finally {
|
|
419
|
+
await rm(tempPath, { force: true });
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* The database connection override, declared from here by every command that
|
|
424
|
+
* accepts one so its brief and placeholder cannot drift apart. Resolution
|
|
425
|
+
* order is the flag, then `config.db.connection`, then
|
|
426
|
+
* `CONFIG.DB_CONNECTION_REQUIRED`.
|
|
427
|
+
*/
|
|
428
|
+
const dbFlag = flag.string({
|
|
429
|
+
brief: "Database connection string",
|
|
430
|
+
placeholder: "url"
|
|
431
|
+
});
|
|
432
|
+
/** The file `contract infer` writes when nothing names another. */
|
|
433
|
+
const INFERRED_CONTRACT_FILENAME = "contract.prisma";
|
|
434
|
+
/**
|
|
435
|
+
* Where `contract infer` writes the PSL it inferred: `--output`, else
|
|
436
|
+
* `contract.prisma` beside the emitted contract, else `contract.prisma` in the
|
|
437
|
+
* invocation directory.
|
|
438
|
+
*/
|
|
439
|
+
function inferredContractPathFor(inputs) {
|
|
440
|
+
if (inputs.output !== void 0) return resolve(inputs.cwd, inputs.output);
|
|
441
|
+
const contractOutput = inputs.config.contract?.output;
|
|
442
|
+
if (contractOutput !== void 0) return join(dirname(resolve(inputs.cwd, contractOutput)), INFERRED_CONTRACT_FILENAME);
|
|
443
|
+
return join(inputs.cwd, INFERRED_CONTRACT_FILENAME);
|
|
444
|
+
}
|
|
445
|
+
function inferPresentations(inputs) {
|
|
446
|
+
const { document, database } = inputs;
|
|
447
|
+
return {
|
|
448
|
+
human: () => [...database === void 0 ? [] : [{
|
|
449
|
+
kind: "fields",
|
|
450
|
+
rail: true,
|
|
451
|
+
rows: [{
|
|
452
|
+
label: "database",
|
|
453
|
+
value: database
|
|
454
|
+
}]
|
|
455
|
+
}], {
|
|
456
|
+
kind: "summary",
|
|
457
|
+
status: "ok",
|
|
458
|
+
text: [{ text: "Contract written to " }, {
|
|
459
|
+
text: document.psl.path,
|
|
460
|
+
tone: "identifier"
|
|
461
|
+
}]
|
|
462
|
+
}],
|
|
463
|
+
json: () => document
|
|
464
|
+
};
|
|
465
|
+
}
|
|
466
|
+
function createContractInferCommand({ createControlClient, printPsl }) {
|
|
467
|
+
return defineOrmCommand({
|
|
468
|
+
help: {
|
|
469
|
+
summary: "Infer a PSL contract from the live database schema",
|
|
470
|
+
description: "Reads the live database schema and writes an inferred PSL contract to\ndisk. This command stops at contract.prisma; follow it with\n`contract emit` and `db sign` as separate steps. An existing file at the\noutput path is overwritten, with a warning.",
|
|
471
|
+
examples: [
|
|
472
|
+
"contract infer --db $DATABASE_URL",
|
|
473
|
+
"contract infer --db $DATABASE_URL --output ./src/prisma/contract.prisma",
|
|
474
|
+
"contract infer --json"
|
|
475
|
+
]
|
|
476
|
+
},
|
|
477
|
+
args: { flags: {
|
|
478
|
+
db: dbFlag,
|
|
479
|
+
output: flag.string({
|
|
480
|
+
brief: "Write the inferred PSL contract to the specified path",
|
|
481
|
+
placeholder: "path"
|
|
482
|
+
})
|
|
483
|
+
} },
|
|
484
|
+
needs: { config: ormConfigSection },
|
|
485
|
+
handler: async (args, ctx) => {
|
|
486
|
+
const startedAt = Date.now();
|
|
487
|
+
const dbConnection = args.flags.db ?? ctx.config.db?.connection;
|
|
488
|
+
if (dbConnection === void 0) return notOk(normalizeError(errorDatabaseConnectionRequired({
|
|
489
|
+
why: "Database connection is required for contract infer (set db.connection in prisma-next.config.ts, or pass --db <url>)",
|
|
490
|
+
commandName: "contract infer",
|
|
491
|
+
missingFlags: ["--db"]
|
|
492
|
+
})));
|
|
493
|
+
if (ctx.config.driver === void 0) return notOk(normalizeError(errorDriverRequired({ why: "Config.driver is required for contract infer" })));
|
|
494
|
+
const client = createControlClient({
|
|
495
|
+
family: ctx.config.family,
|
|
496
|
+
target: ctx.config.target,
|
|
497
|
+
adapter: ctx.config.adapter,
|
|
498
|
+
driver: ctx.config.driver,
|
|
499
|
+
extensions: ctx.config.extensions ?? []
|
|
500
|
+
});
|
|
501
|
+
let pslContent;
|
|
502
|
+
try {
|
|
503
|
+
const schema = await client.introspect({
|
|
504
|
+
connection: dbConnection,
|
|
505
|
+
onProgress: controlProgressReporter(ctx.report)
|
|
506
|
+
});
|
|
507
|
+
const pslContractAst = client.inferPslContract(schema);
|
|
508
|
+
if (pslContractAst === void 0) return notOk(normalizeError(errorRuntime$1("CONTRACT.INFER_UNSUPPORTED", "contract infer is not supported for this family", {
|
|
509
|
+
why: "The configured family does not implement the PslContractInferCapable capability, so an inferred PSL contract cannot be produced from the live database schema.",
|
|
510
|
+
fix: "Use a family that supports contract inference (e.g. SQL/Postgres)."
|
|
511
|
+
})));
|
|
512
|
+
pslContent = printPsl(pslContractAst, { pslBlockDescriptors: client.getPslBlockDescriptors() });
|
|
513
|
+
} catch (error) {
|
|
514
|
+
if (CliStructuredError$1$1.is(error)) return notOk(normalizeError(error));
|
|
515
|
+
const safeMessage = sanitizeErrorMessage(error instanceof Error ? error.message : String(error), typeof dbConnection === "string" ? dbConnection : void 0);
|
|
516
|
+
return notOk(normalizeError(errorUnexpected(safeMessage, { why: `Unexpected error during contract infer: ${safeMessage}` })));
|
|
517
|
+
} finally {
|
|
518
|
+
await closeQuietly(client);
|
|
519
|
+
}
|
|
520
|
+
const outputPath = inferredContractPathFor({
|
|
521
|
+
config: ctx.config,
|
|
522
|
+
cwd: ctx.cwd,
|
|
523
|
+
output: args.flags.output
|
|
524
|
+
});
|
|
525
|
+
const displayPath = relative(ctx.cwd, outputPath);
|
|
526
|
+
if (existsSync(outputPath)) ctx.report({
|
|
527
|
+
kind: "message",
|
|
528
|
+
severity: "warn",
|
|
529
|
+
text: `Overwriting existing file: ${displayPath}`
|
|
530
|
+
});
|
|
531
|
+
await publishTextArtifact({
|
|
532
|
+
path: outputPath,
|
|
533
|
+
content: pslContent,
|
|
534
|
+
publicationToken: String(process.hrtime.bigint())
|
|
535
|
+
});
|
|
536
|
+
const database = typeof dbConnection === "string" ? maskConnectionUrl(dbConnection) : void 0;
|
|
537
|
+
const document = {
|
|
538
|
+
ok: true,
|
|
539
|
+
summary: "Contract inferred successfully",
|
|
540
|
+
target: {
|
|
541
|
+
familyId: ctx.config.family.familyId,
|
|
542
|
+
id: ctx.config.target.targetId
|
|
543
|
+
},
|
|
544
|
+
psl: { path: displayPath },
|
|
545
|
+
meta: { ...ifDefined("dbUrl", database) },
|
|
546
|
+
timings: { total: Date.now() - startedAt }
|
|
547
|
+
};
|
|
548
|
+
return ok(ctx.present({ data: document }, inferPresentations({
|
|
549
|
+
document,
|
|
550
|
+
database
|
|
551
|
+
})));
|
|
552
|
+
}
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
const contractInferCommand = createContractInferCommand({
|
|
556
|
+
createControlClient,
|
|
557
|
+
printPsl
|
|
558
|
+
});
|
|
305
559
|
function operationNode(operation) {
|
|
306
560
|
return operation.operationClass === "destructive" ? {
|
|
307
561
|
label: operation.label,
|
|
@@ -903,6 +1157,44 @@ function createDbSchemaCommand(createClient) {
|
|
|
903
1157
|
});
|
|
904
1158
|
}
|
|
905
1159
|
const dbSchemaCommand = createDbSchemaCommand(createControlClient);
|
|
1160
|
+
const NOTHING_TO_FORMAT = "Nothing to format (contract source is not PSL).";
|
|
1161
|
+
function formatPresentations(document, cwd) {
|
|
1162
|
+
const path = document.path;
|
|
1163
|
+
return {
|
|
1164
|
+
human: () => document.formatted && path !== void 0 ? [{
|
|
1165
|
+
kind: "summary",
|
|
1166
|
+
status: "ok",
|
|
1167
|
+
text: [{ text: "Formatted " }, {
|
|
1168
|
+
text: relative(cwd, path),
|
|
1169
|
+
tone: "identifier"
|
|
1170
|
+
}]
|
|
1171
|
+
}] : [{
|
|
1172
|
+
kind: "summary",
|
|
1173
|
+
status: "info",
|
|
1174
|
+
text: NOTHING_TO_FORMAT
|
|
1175
|
+
}],
|
|
1176
|
+
json: () => document
|
|
1177
|
+
};
|
|
1178
|
+
}
|
|
1179
|
+
function createFormatCommand$1(execute = executeFormat) {
|
|
1180
|
+
return defineOrmCommand({
|
|
1181
|
+
help: {
|
|
1182
|
+
summary: "Format your PSL contract source",
|
|
1183
|
+
description: "Formats the Prisma schema (PSL) contract source declared in your config\n(contract.source.inputs[0]) in place. Only runs when contract.source.format\nis 'psl'; a TypeScript or unset source is left untouched. Indent and newline\nare read from the optional formatter config section, defaulting to two\nspaces and the system newline.",
|
|
1184
|
+
examples: ["format", "format --json"]
|
|
1185
|
+
},
|
|
1186
|
+
needs: { config: ormConfigSection },
|
|
1187
|
+
handler: async (_args, ctx) => {
|
|
1188
|
+
const result = await execute({
|
|
1189
|
+
config: ctx.config,
|
|
1190
|
+
cwd: ctx.cwd
|
|
1191
|
+
});
|
|
1192
|
+
if (!result.ok) return notOk(normalizeError(result.failure));
|
|
1193
|
+
return ok(ctx.present({ data: result.value }, formatPresentations(result.value, ctx.cwd)));
|
|
1194
|
+
}
|
|
1195
|
+
});
|
|
1196
|
+
}
|
|
1197
|
+
const formatCommand = createFormatCommand$1();
|
|
906
1198
|
const STATUS_ACTION = runCommandAction("Check every space against the database", "prisma-next migration status");
|
|
907
1199
|
/**
|
|
908
1200
|
* The route the migration will take. The graph is a drawing — the engine cannot
|
|
@@ -1337,7 +1629,7 @@ const migrationGraphCommand = defineOrmCommand({
|
|
|
1337
1629
|
})));
|
|
1338
1630
|
}
|
|
1339
1631
|
});
|
|
1340
|
-
function listPresentations(inputs) {
|
|
1632
|
+
function listPresentations$1(inputs) {
|
|
1341
1633
|
const legend = inputs.legend;
|
|
1342
1634
|
return {
|
|
1343
1635
|
human: () => [
|
|
@@ -1410,7 +1702,7 @@ const migrationListCommand = defineOrmCommand({
|
|
|
1410
1702
|
styler,
|
|
1411
1703
|
palette: TONE_MIGRATION_GRAPH_PALETTE
|
|
1412
1704
|
}) : void 0;
|
|
1413
|
-
return ok(ctx.present({ data: listed.value }, listPresentations({
|
|
1705
|
+
return ok(ctx.present({ data: listed.value }, listPresentations$1({
|
|
1414
1706
|
list: listed.value,
|
|
1415
1707
|
tree,
|
|
1416
1708
|
migrationsDir: displayPath(migrationsDir, ctx.cwd),
|
|
@@ -1761,6 +2053,160 @@ const migrationShowCommand = defineOrmCommand({
|
|
|
1761
2053
|
})));
|
|
1762
2054
|
}
|
|
1763
2055
|
});
|
|
2056
|
+
function deletePresentations(document) {
|
|
2057
|
+
return {
|
|
2058
|
+
human: () => [{
|
|
2059
|
+
kind: "summary",
|
|
2060
|
+
status: "ok",
|
|
2061
|
+
text: [
|
|
2062
|
+
{ text: "Deleted ref \"" },
|
|
2063
|
+
{
|
|
2064
|
+
text: document.ref,
|
|
2065
|
+
tone: "ref"
|
|
2066
|
+
},
|
|
2067
|
+
{ text: "\"" }
|
|
2068
|
+
]
|
|
2069
|
+
}],
|
|
2070
|
+
json: () => document
|
|
2071
|
+
};
|
|
2072
|
+
}
|
|
2073
|
+
function createRefDeleteCommand(execute = executeRefDeleteCommand) {
|
|
2074
|
+
return defineOrmCommand({
|
|
2075
|
+
help: {
|
|
2076
|
+
summary: "Delete a ref",
|
|
2077
|
+
description: "Removes migrations/app/refs/<name>.json. The contract the ref pointed at\nis untouched: a ref is a pointer, and its target survives the deletion.",
|
|
2078
|
+
examples: ["ref delete staging", "ref delete staging --json"]
|
|
2079
|
+
},
|
|
2080
|
+
args: { positionals: { name: positional.string({
|
|
2081
|
+
brief: "Ref name to delete",
|
|
2082
|
+
placeholder: "name"
|
|
2083
|
+
}) } },
|
|
2084
|
+
needs: { config: ormConfigSection },
|
|
2085
|
+
handler: async (args, ctx) => {
|
|
2086
|
+
const result = await execute(args.positionals.name, {
|
|
2087
|
+
config: ctx.config,
|
|
2088
|
+
cwd: ctx.cwd
|
|
2089
|
+
});
|
|
2090
|
+
if (!result.ok) return notOk(normalizeError(result.failure));
|
|
2091
|
+
return ok(ctx.present({ data: result.value }, deletePresentations(result.value)));
|
|
2092
|
+
}
|
|
2093
|
+
});
|
|
2094
|
+
}
|
|
2095
|
+
const refDeleteCommand = createRefDeleteCommand();
|
|
2096
|
+
const HEADING_REF = "Ref";
|
|
2097
|
+
const HEADING_CONTRACT = "Contract";
|
|
2098
|
+
const HEADING_INVARIANTS = "Invariants";
|
|
2099
|
+
const EMPTY_MESSAGE = "No refs defined";
|
|
2100
|
+
/**
|
|
2101
|
+
* The refs as a grid the engine sizes. The invariants heading appears only
|
|
2102
|
+
* when a ref carries any, as the commander shell appended them only then.
|
|
2103
|
+
*/
|
|
2104
|
+
function refsGrid(refs) {
|
|
2105
|
+
const entries = Object.entries(refs);
|
|
2106
|
+
const showInvariants = entries.some(([, entry]) => entry.invariants.length > 0);
|
|
2107
|
+
return {
|
|
2108
|
+
kind: "table",
|
|
2109
|
+
columns: showInvariants ? [
|
|
2110
|
+
HEADING_REF,
|
|
2111
|
+
HEADING_CONTRACT,
|
|
2112
|
+
HEADING_INVARIANTS
|
|
2113
|
+
] : [HEADING_REF, HEADING_CONTRACT],
|
|
2114
|
+
rows: entries.map(([name, entry]) => {
|
|
2115
|
+
const cells = [[{
|
|
2116
|
+
text: name,
|
|
2117
|
+
tone: "ref"
|
|
2118
|
+
}], [{
|
|
2119
|
+
text: entry.hash,
|
|
2120
|
+
tone: "identifier"
|
|
2121
|
+
}]];
|
|
2122
|
+
if (showInvariants) cells.push(entry.invariants.join(", "));
|
|
2123
|
+
return cells;
|
|
2124
|
+
})
|
|
2125
|
+
};
|
|
2126
|
+
}
|
|
2127
|
+
function listPresentations(document) {
|
|
2128
|
+
return {
|
|
2129
|
+
human: () => Object.keys(document.refs).length === 0 ? [{
|
|
2130
|
+
kind: "summary",
|
|
2131
|
+
status: "info",
|
|
2132
|
+
text: EMPTY_MESSAGE
|
|
2133
|
+
}] : [refsGrid(document.refs)],
|
|
2134
|
+
json: () => document
|
|
2135
|
+
};
|
|
2136
|
+
}
|
|
2137
|
+
function createRefListCommand(execute = executeRefListCommand) {
|
|
2138
|
+
return defineOrmCommand({
|
|
2139
|
+
help: {
|
|
2140
|
+
summary: "List every named ref",
|
|
2141
|
+
description: "Reads migrations/app/refs/ and reports each ref with the contract hash it\npoints at and the invariants recorded against it. Offline — does not\nconsult the database.",
|
|
2142
|
+
examples: ["ref list", "ref list --json"]
|
|
2143
|
+
},
|
|
2144
|
+
needs: { config: ormConfigSection },
|
|
2145
|
+
handler: async (_args, ctx) => {
|
|
2146
|
+
const result = await execute({
|
|
2147
|
+
config: ctx.config,
|
|
2148
|
+
cwd: ctx.cwd
|
|
2149
|
+
});
|
|
2150
|
+
if (!result.ok) return notOk(normalizeError(result.failure));
|
|
2151
|
+
return ok(ctx.present({ data: result.value }, listPresentations(result.value)));
|
|
2152
|
+
}
|
|
2153
|
+
});
|
|
2154
|
+
}
|
|
2155
|
+
const refListCommand = createRefListCommand();
|
|
2156
|
+
function setPresentations(document) {
|
|
2157
|
+
return {
|
|
2158
|
+
human: () => [{
|
|
2159
|
+
kind: "summary",
|
|
2160
|
+
status: "ok",
|
|
2161
|
+
text: [
|
|
2162
|
+
{ text: "Set ref \"" },
|
|
2163
|
+
{
|
|
2164
|
+
text: document.ref,
|
|
2165
|
+
tone: "ref"
|
|
2166
|
+
},
|
|
2167
|
+
{ text: "\" → " },
|
|
2168
|
+
{
|
|
2169
|
+
text: document.hash,
|
|
2170
|
+
tone: "identifier"
|
|
2171
|
+
}
|
|
2172
|
+
]
|
|
2173
|
+
}],
|
|
2174
|
+
json: () => document
|
|
2175
|
+
};
|
|
2176
|
+
}
|
|
2177
|
+
function createRefSetCommand(execute = executeRefSetCommand) {
|
|
2178
|
+
return defineOrmCommand({
|
|
2179
|
+
help: {
|
|
2180
|
+
summary: "Point a ref at a contract",
|
|
2181
|
+
description: "Writes migrations/app/refs/<name>.json so a logical environment name\nresolves to a contract hash. The contract is given as a hash or prefix,\nanother ref name, a migration directory name, or <dir>^ for that\nmigration's source contract. Offline — the contract must already be a\nnode of the on-disk migration graph, with its snapshot present.",
|
|
2182
|
+
examples: [
|
|
2183
|
+
"ref set staging 4cb4256",
|
|
2184
|
+
"ref set production 20260101T1000_add_user",
|
|
2185
|
+
"ref set staging production --json"
|
|
2186
|
+
]
|
|
2187
|
+
},
|
|
2188
|
+
args: { positionals: {
|
|
2189
|
+
name: positional.string({
|
|
2190
|
+
brief: "Ref name (e.g. staging, production)",
|
|
2191
|
+
placeholder: "name"
|
|
2192
|
+
}),
|
|
2193
|
+
contract: positional.string({
|
|
2194
|
+
brief: "Contract reference: hash, prefix, ref name, migration dir name, or <dir>^",
|
|
2195
|
+
placeholder: "contract"
|
|
2196
|
+
})
|
|
2197
|
+
} },
|
|
2198
|
+
needs: { config: ormConfigSection },
|
|
2199
|
+
handler: async (args, ctx) => {
|
|
2200
|
+
const result = await execute(args.positionals.name, args.positionals.contract, {
|
|
2201
|
+
config: ctx.config,
|
|
2202
|
+
cwd: ctx.cwd
|
|
2203
|
+
});
|
|
2204
|
+
if (!result.ok) return notOk(normalizeError(result.failure));
|
|
2205
|
+
return ok(ctx.present({ data: result.value }, setPresentations(result.value)));
|
|
2206
|
+
}
|
|
2207
|
+
});
|
|
2208
|
+
}
|
|
2209
|
+
const refSetCommand = createRefSetCommand();
|
|
1764
2210
|
/**
|
|
1765
2211
|
* The engine derives each diagnostic's docs link from this base plus the
|
|
1766
2212
|
* dotted code.
|
|
@@ -1774,13 +2220,19 @@ const DOCS_BASE_URL = `${DOCS_BASE}/`;
|
|
|
1774
2220
|
const ormCommandFamily = defineCommandFamily({
|
|
1775
2221
|
configSection: ormConfigSection,
|
|
1776
2222
|
commands: {
|
|
2223
|
+
"contract emit": contractEmitCommand,
|
|
2224
|
+
"contract infer": contractInferCommand,
|
|
1777
2225
|
"db init": dbInitCommand,
|
|
1778
2226
|
"db schema": dbSchemaCommand,
|
|
2227
|
+
format: formatCommand,
|
|
1779
2228
|
migrate: migrateCommand,
|
|
1780
2229
|
"migration graph": migrationGraphCommand,
|
|
1781
2230
|
"migration list": migrationListCommand,
|
|
1782
2231
|
"migration log": migrationLogCommand,
|
|
1783
|
-
"migration show": migrationShowCommand
|
|
2232
|
+
"migration show": migrationShowCommand,
|
|
2233
|
+
"ref delete": refDeleteCommand,
|
|
2234
|
+
"ref list": refListCommand,
|
|
2235
|
+
"ref set": refSetCommand
|
|
1784
2236
|
},
|
|
1785
2237
|
docsBaseUrl: DOCS_BASE_URL,
|
|
1786
2238
|
redirects: [{
|