@prisma-next/cli 0.5.0-dev.36 → 0.5.0-dev.38
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 +13 -5
- package/dist/cli.mjs.map +1 -1
- package/dist/{client-Buy8_40Y.mjs → client-1JqqkiC7.mjs} +3 -2
- package/dist/client-1JqqkiC7.mjs.map +1 -0
- package/dist/commands/contract-emit.mjs +6 -1
- package/dist/commands/contract-infer.mjs +7 -1
- package/dist/commands/db-init.mjs +4 -3
- package/dist/commands/db-init.mjs.map +1 -1
- package/dist/commands/db-schema.mjs +5 -2
- package/dist/commands/db-schema.mjs.map +1 -1
- package/dist/commands/db-sign.mjs +3 -2
- package/dist/commands/db-sign.mjs.map +1 -1
- package/dist/commands/db-update.mjs +4 -3
- package/dist/commands/db-update.mjs.map +1 -1
- package/dist/commands/db-verify.mjs +3 -2
- package/dist/commands/db-verify.mjs.map +1 -1
- package/dist/commands/migration-apply.d.mts +3 -0
- package/dist/commands/migration-apply.d.mts.map +1 -1
- package/dist/commands/migration-apply.mjs +47 -23
- package/dist/commands/migration-apply.mjs.map +1 -1
- package/dist/commands/migration-new.mjs +3 -3
- package/dist/commands/migration-new.mjs.map +1 -1
- package/dist/commands/migration-plan.mjs +1 -1
- package/dist/commands/migration-ref.mjs +1 -1
- package/dist/commands/migration-show.mjs +3 -2
- package/dist/commands/migration-show.mjs.map +1 -1
- package/dist/commands/migration-status.d.mts +18 -1
- package/dist/commands/migration-status.d.mts.map +1 -1
- package/dist/commands/migration-status.mjs +7 -2
- package/dist/{contract-emit-LjzCoicC.mjs → contract-emit-DS5NzZh2.mjs} +2 -0
- package/dist/{contract-emit-DWtGQYCD.mjs → contract-emit-rt_Nmdwq.mjs} +2 -2
- package/dist/{contract-emit-DWtGQYCD.mjs.map → contract-emit-rt_Nmdwq.mjs.map} +1 -1
- package/dist/{contract-infer-DmLiksNp.mjs → contract-infer-Cf5J2wVg.mjs} +3 -3
- package/dist/{contract-infer-DmLiksNp.mjs.map → contract-infer-Cf5J2wVg.mjs.map} +1 -1
- package/dist/exports/control-api.d.mts +8 -0
- package/dist/exports/control-api.d.mts.map +1 -1
- package/dist/exports/control-api.mjs +3 -1
- package/dist/exports/index.mjs +6 -1
- package/dist/exports/index.mjs.map +1 -1
- package/dist/{init-C7dE9KOJ.mjs → init-DAbQMxIR.mjs} +2 -2
- package/dist/{init-C7dE9KOJ.mjs.map → init-DAbQMxIR.mjs.map} +1 -1
- package/dist/{inspect-live-schema-6nsKS6m5.mjs → inspect-live-schema-LWtXfxm_.mjs} +3 -3
- package/dist/{inspect-live-schema-6nsKS6m5.mjs.map → inspect-live-schema-LWtXfxm_.mjs.map} +1 -1
- package/dist/{migration-command-scaffold-Ck1_lcsf.mjs → migration-command-scaffold-CU452v9h.mjs} +3 -3
- package/dist/{migration-command-scaffold-Ck1_lcsf.mjs.map → migration-command-scaffold-CU452v9h.mjs.map} +1 -1
- package/dist/{migration-status-DYJIRnK3.mjs → migration-status-DoPrFIOQ.mjs} +103 -34
- package/dist/migration-status-DoPrFIOQ.mjs.map +1 -0
- package/dist/{result-handler-BmVh8AeV.mjs → result-handler-Ch6hVnOo.mjs} +26 -3
- package/dist/{result-handler-BmVh8AeV.mjs.map → result-handler-Ch6hVnOo.mjs.map} +1 -1
- package/package.json +14 -14
- package/src/commands/migration-apply.ts +72 -16
- package/src/commands/migration-new.ts +2 -2
- package/src/commands/migration-status.ts +171 -23
- package/src/control-api/operations/migration-apply.ts +1 -0
- package/src/control-api/types.ts +8 -0
- package/src/utils/command-helpers.ts +36 -1
- package/src/utils/formatters/graph-migration-mapper.ts +5 -1
- package/dist/client-Buy8_40Y.mjs.map +0 -1
- package/dist/migration-status-DYJIRnK3.mjs.map +0 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { t as loadConfig } from "./config-loader-ih8ViDb_.mjs";
|
|
2
2
|
import { _ as errorUnexpected, c as errorDriverRequired, o as errorDatabaseConnectionRequired, t as CliStructuredError } from "./cli-errors-By1iVE3z.mjs";
|
|
3
|
-
import {
|
|
3
|
+
import { o as maskConnectionUrl, u as sanitizeErrorMessage, y as formatStyledHeader } from "./result-handler-Ch6hVnOo.mjs";
|
|
4
4
|
import { t as createProgressAdapter } from "./progress-adapter-DgRGldpT.mjs";
|
|
5
|
-
import { t as createControlClient } from "./client-
|
|
5
|
+
import { t as createControlClient } from "./client-1JqqkiC7.mjs";
|
|
6
6
|
import { notOk, ok } from "@prisma-next/utils/result";
|
|
7
7
|
import { relative, resolve } from "pathe";
|
|
8
8
|
|
|
@@ -88,4 +88,4 @@ async function inspectLiveSchema(options, flags, ui, startTime, context) {
|
|
|
88
88
|
|
|
89
89
|
//#endregion
|
|
90
90
|
export { inspectLiveSchema as t };
|
|
91
|
-
//# sourceMappingURL=inspect-live-schema-
|
|
91
|
+
//# sourceMappingURL=inspect-live-schema-LWtXfxm_.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inspect-live-schema-
|
|
1
|
+
{"version":3,"file":"inspect-live-schema-LWtXfxm_.mjs","names":["config: LoadedCliConfig","details: Array<{ label: string; value: string }>"],"sources":["../src/commands/inspect-live-schema.ts"],"sourcesContent":["import type { CoreSchemaView } from '@prisma-next/framework-components/control';\nimport type { PslDocumentAst } from '@prisma-next/framework-components/psl-ast';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { relative, resolve } from 'pathe';\nimport { loadConfig } from '../config-loader';\nimport { createControlClient } from '../control-api/client';\nimport {\n CliStructuredError,\n errorDatabaseConnectionRequired,\n errorDriverRequired,\n errorUnexpected,\n} from '../utils/cli-errors';\nimport { maskConnectionUrl, sanitizeErrorMessage } from '../utils/command-helpers';\nimport { formatStyledHeader } from '../utils/formatters/styled';\nimport type { CommonCommandOptions, GlobalFlags } from '../utils/global-flags';\nimport { createProgressAdapter } from '../utils/progress-adapter';\nimport type { TerminalUI } from '../utils/terminal-ui';\n\nexport interface InspectLiveSchemaOptions extends CommonCommandOptions {\n readonly db?: string;\n readonly config?: string;\n}\n\ninterface InspectLiveSchemaContext {\n readonly commandName: string;\n readonly description: string;\n readonly url: string;\n}\n\ntype LoadedCliConfig = Awaited<ReturnType<typeof loadConfig>>;\n\nexport interface InspectLiveSchemaResult {\n readonly config: LoadedCliConfig;\n readonly schema: unknown;\n readonly schemaView: CoreSchemaView | undefined;\n /**\n * PSL AST inferred from the introspected schema, when the configured family\n * implements `PslContractInferCapable`. `undefined` for families that do not\n * support inference (e.g. Mongo today).\n */\n readonly pslContractAst: PslDocumentAst | undefined;\n readonly target: {\n readonly familyId: string;\n readonly id: string;\n };\n readonly meta: {\n readonly configPath?: string;\n readonly dbUrl?: string;\n };\n readonly timings: {\n readonly total: number;\n };\n}\n\nexport async function inspectLiveSchema(\n options: InspectLiveSchemaOptions,\n flags: GlobalFlags,\n ui: TerminalUI,\n startTime: number,\n context: InspectLiveSchemaContext,\n): Promise<Result<InspectLiveSchemaResult, CliStructuredError>> {\n let config: LoadedCliConfig;\n try {\n config = await loadConfig(options.config);\n } catch (error) {\n if (CliStructuredError.is(error)) {\n return notOk(error);\n }\n\n return notOk(\n errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: 'Failed to load config',\n }),\n );\n }\n\n const configPath = options.config\n ? relative(process.cwd(), resolve(options.config))\n : 'prisma-next.config.ts';\n\n if (!flags.json && !flags.quiet) {\n const details: Array<{ label: string; value: string }> = [\n { label: 'config', value: configPath },\n ];\n\n if (options.db) {\n details.push({ label: 'database', value: maskConnectionUrl(options.db) });\n } else if (config.db?.connection && typeof config.db.connection === 'string') {\n details.push({ label: 'database', value: maskConnectionUrl(config.db.connection) });\n }\n\n ui.stderr(\n formatStyledHeader({\n command: context.commandName,\n description: context.description,\n url: context.url,\n details,\n flags,\n }),\n );\n }\n\n const dbConnection = options.db ?? config.db?.connection;\n if (!dbConnection) {\n return notOk(\n errorDatabaseConnectionRequired({\n why: `Database connection is required for ${context.commandName} (set db.connection in ${configPath}, or pass --db <url>)`,\n commandName: context.commandName,\n }),\n );\n }\n\n if (!config.driver) {\n return notOk(\n errorDriverRequired({\n why: `Config.driver is required for ${context.commandName}`,\n }),\n );\n }\n\n const client = createControlClient({\n family: config.family,\n target: config.target,\n adapter: config.adapter,\n driver: config.driver,\n extensionPacks: config.extensionPacks ?? [],\n });\n const onProgress = createProgressAdapter({ ui, flags });\n\n try {\n const schema = await client.introspect({\n connection: dbConnection,\n onProgress,\n });\n const schemaView = client.toSchemaView(schema);\n const pslContractAst = client.inferPslContract(schema);\n\n const dbUrl = typeof dbConnection === 'string' ? maskConnectionUrl(dbConnection) : undefined;\n\n return ok({\n config,\n schema,\n schemaView,\n pslContractAst,\n target: {\n familyId: config.family.familyId,\n id: config.target.targetId,\n },\n meta: {\n configPath,\n ...(dbUrl ? { dbUrl } : {}),\n },\n timings: {\n total: Date.now() - startTime,\n },\n });\n } catch (error) {\n if (CliStructuredError.is(error)) {\n return notOk(error);\n }\n\n const rawMessage = error instanceof Error ? error.message : String(error);\n const safeMessage = sanitizeErrorMessage(\n rawMessage,\n typeof dbConnection === 'string' ? dbConnection : undefined,\n );\n return notOk(\n errorUnexpected(safeMessage, {\n why: `Unexpected error during ${context.commandName}: ${safeMessage}`,\n }),\n );\n } finally {\n await client.close();\n }\n}\n"],"mappings":";;;;;;;;;AAsDA,eAAsB,kBACpB,SACA,OACA,IACA,WACA,SAC8D;CAC9D,IAAIA;AACJ,KAAI;AACF,WAAS,MAAM,WAAW,QAAQ,OAAO;UAClC,OAAO;AACd,MAAI,mBAAmB,GAAG,MAAM,CAC9B,QAAO,MAAM,MAAM;AAGrB,SAAO,MACL,gBAAgB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,EAAE,EACtE,KAAK,yBACN,CAAC,CACH;;CAGH,MAAM,aAAa,QAAQ,SACvB,SAAS,QAAQ,KAAK,EAAE,QAAQ,QAAQ,OAAO,CAAC,GAChD;AAEJ,KAAI,CAAC,MAAM,QAAQ,CAAC,MAAM,OAAO;EAC/B,MAAMC,UAAmD,CACvD;GAAE,OAAO;GAAU,OAAO;GAAY,CACvC;AAED,MAAI,QAAQ,GACV,SAAQ,KAAK;GAAE,OAAO;GAAY,OAAO,kBAAkB,QAAQ,GAAG;GAAE,CAAC;WAChE,OAAO,IAAI,cAAc,OAAO,OAAO,GAAG,eAAe,SAClE,SAAQ,KAAK;GAAE,OAAO;GAAY,OAAO,kBAAkB,OAAO,GAAG,WAAW;GAAE,CAAC;AAGrF,KAAG,OACD,mBAAmB;GACjB,SAAS,QAAQ;GACjB,aAAa,QAAQ;GACrB,KAAK,QAAQ;GACb;GACA;GACD,CAAC,CACH;;CAGH,MAAM,eAAe,QAAQ,MAAM,OAAO,IAAI;AAC9C,KAAI,CAAC,aACH,QAAO,MACL,gCAAgC;EAC9B,KAAK,uCAAuC,QAAQ,YAAY,yBAAyB,WAAW;EACpG,aAAa,QAAQ;EACtB,CAAC,CACH;AAGH,KAAI,CAAC,OAAO,OACV,QAAO,MACL,oBAAoB,EAClB,KAAK,iCAAiC,QAAQ,eAC/C,CAAC,CACH;CAGH,MAAM,SAAS,oBAAoB;EACjC,QAAQ,OAAO;EACf,QAAQ,OAAO;EACf,SAAS,OAAO;EAChB,QAAQ,OAAO;EACf,gBAAgB,OAAO,kBAAkB,EAAE;EAC5C,CAAC;CACF,MAAM,aAAa,sBAAsB;EAAE;EAAI;EAAO,CAAC;AAEvD,KAAI;EACF,MAAM,SAAS,MAAM,OAAO,WAAW;GACrC,YAAY;GACZ;GACD,CAAC;EACF,MAAM,aAAa,OAAO,aAAa,OAAO;EAC9C,MAAM,iBAAiB,OAAO,iBAAiB,OAAO;EAEtD,MAAM,QAAQ,OAAO,iBAAiB,WAAW,kBAAkB,aAAa,GAAG;AAEnF,SAAO,GAAG;GACR;GACA;GACA;GACA;GACA,QAAQ;IACN,UAAU,OAAO,OAAO;IACxB,IAAI,OAAO,OAAO;IACnB;GACD,MAAM;IACJ;IACA,GAAI,QAAQ,EAAE,OAAO,GAAG,EAAE;IAC3B;GACD,SAAS,EACP,OAAO,KAAK,KAAK,GAAG,WACrB;GACF,CAAC;UACK,OAAO;AACd,MAAI,mBAAmB,GAAG,MAAM,CAC9B,QAAO,MAAM,MAAM;EAIrB,MAAM,cAAc,qBADD,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,EAGvE,OAAO,iBAAiB,WAAW,eAAe,OACnD;AACD,SAAO,MACL,gBAAgB,aAAa,EAC3B,KAAK,2BAA2B,QAAQ,YAAY,IAAI,eACzD,CAAC,CACH;WACO;AACR,QAAM,OAAO,OAAO"}
|
package/dist/{migration-command-scaffold-Ck1_lcsf.mjs → migration-command-scaffold-CU452v9h.mjs}
RENAMED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { t as loadConfig } from "./config-loader-ih8ViDb_.mjs";
|
|
2
2
|
import { _ as errorUnexpected, a as errorContractValidationFailed, c as errorDriverRequired, h as errorTargetMigrationNotSupported, l as errorFileNotFound, o as errorDatabaseConnectionRequired } from "./cli-errors-By1iVE3z.mjs";
|
|
3
|
-
import {
|
|
3
|
+
import { c as resolveContractPath, n as addGlobalOptions, o as maskConnectionUrl, y as formatStyledHeader } from "./result-handler-Ch6hVnOo.mjs";
|
|
4
4
|
import { t as createProgressAdapter } from "./progress-adapter-DgRGldpT.mjs";
|
|
5
|
-
import { t as createControlClient } from "./client-
|
|
5
|
+
import { t as createControlClient } from "./client-1JqqkiC7.mjs";
|
|
6
6
|
import { notOk, ok } from "@prisma-next/utils/result";
|
|
7
7
|
import { readFile } from "node:fs/promises";
|
|
8
8
|
import { hasMigrations } from "@prisma-next/framework-components/control";
|
|
@@ -102,4 +102,4 @@ function addMigrationCommandOptions(command) {
|
|
|
102
102
|
|
|
103
103
|
//#endregion
|
|
104
104
|
export { prepareMigrationContext as n, addMigrationCommandOptions as t };
|
|
105
|
-
//# sourceMappingURL=migration-command-scaffold-
|
|
105
|
+
//# sourceMappingURL=migration-command-scaffold-CU452v9h.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migration-command-scaffold-
|
|
1
|
+
{"version":3,"file":"migration-command-scaffold-CU452v9h.mjs","names":["details: Array<{ label: string; value: string }>","contractJsonContent: string","contractJson: Record<string, unknown>"],"sources":["../src/utils/migration-command-scaffold.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport { relative, resolve } from 'node:path';\nimport { hasMigrations } from '@prisma-next/framework-components/control';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport type { Command } from 'commander';\nimport { loadConfig } from '../config-loader';\nimport { createControlClient } from '../control-api/client';\nimport type { ControlClient } from '../control-api/types';\nimport {\n type CliStructuredError,\n errorContractValidationFailed,\n errorDatabaseConnectionRequired,\n errorDriverRequired,\n errorFileNotFound,\n errorTargetMigrationNotSupported,\n errorUnexpected,\n} from './cli-errors';\nimport { addGlobalOptions, maskConnectionUrl, resolveContractPath } from './command-helpers';\nimport { formatStyledHeader } from './formatters/styled';\nimport type { GlobalFlags } from './global-flags';\nimport { createProgressAdapter } from './progress-adapter';\nimport type { TerminalUI } from './terminal-ui';\n\n/**\n * Resolved context for a migration command.\n * Contains everything needed to invoke a control-api operation.\n */\nexport interface MigrationContext {\n readonly client: ControlClient;\n readonly contractJson: Record<string, unknown>;\n readonly dbConnection: unknown;\n readonly onProgress: ReturnType<typeof createProgressAdapter>;\n readonly configPath: string;\n readonly contractPath: string;\n readonly contractPathAbsolute: string;\n readonly config: Awaited<ReturnType<typeof loadConfig>>;\n}\n\n/**\n * Command-specific configuration for the shared scaffold.\n */\nexport interface MigrationCommandDescriptor {\n readonly commandName: string;\n readonly description: string;\n readonly url: string;\n}\n\n/**\n * Prepares the shared context for migration commands (db init, db update).\n *\n * Handles: config loading, contract file reading, JSON parsing, connection resolution,\n * driver/migration-support validation, client creation, and header output.\n *\n * Returns a Result with either the resolved context or a structured error.\n */\nexport async function prepareMigrationContext(\n options: { readonly db?: string; readonly config?: string; readonly dryRun?: boolean },\n flags: GlobalFlags,\n ui: TerminalUI,\n descriptor: MigrationCommandDescriptor,\n): Promise<Result<MigrationContext, CliStructuredError>> {\n // Load config\n const config = await loadConfig(options.config);\n const configPath = options.config\n ? relative(process.cwd(), resolve(options.config))\n : 'prisma-next.config.ts';\n const contractPathAbsolute = resolveContractPath(config);\n const contractPath = relative(process.cwd(), contractPathAbsolute);\n\n // Output header to stderr (decoration)\n if (!flags.json && !flags.quiet) {\n const details: Array<{ label: string; value: string }> = [\n { label: 'config', value: configPath },\n { label: 'contract', value: contractPath },\n ];\n if (options.db) {\n details.push({ label: 'database', value: maskConnectionUrl(options.db) });\n }\n if (options.dryRun) {\n details.push({ label: 'mode', value: 'dry run' });\n }\n const header = formatStyledHeader({\n command: descriptor.commandName,\n description: descriptor.description,\n url: descriptor.url,\n details,\n flags,\n });\n ui.stderr(header);\n }\n\n // Load contract file\n let contractJsonContent: string;\n try {\n contractJsonContent = await readFile(contractPathAbsolute, 'utf-8');\n } catch (error) {\n if (error instanceof Error && (error as { code?: string }).code === 'ENOENT') {\n return notOk(\n errorFileNotFound(contractPathAbsolute, {\n why: `Contract file not found at ${contractPathAbsolute}`,\n fix: `Run \\`prisma-next contract emit\\` to generate ${contractPath}, or update \\`config.contract.output\\` in ${configPath}`,\n }),\n );\n }\n return notOk(\n errorUnexpected(error instanceof Error ? error.message : String(error), {\n why: `Failed to read contract file: ${error instanceof Error ? error.message : String(error)}`,\n }),\n );\n }\n\n // Parse contract JSON\n let contractJson: Record<string, unknown>;\n try {\n contractJson = JSON.parse(contractJsonContent) as Record<string, unknown>;\n } catch (error) {\n return notOk(\n errorContractValidationFailed(\n `Contract JSON is invalid: ${error instanceof Error ? error.message : String(error)}`,\n { where: { path: contractPathAbsolute } },\n ),\n );\n }\n\n // Resolve database connection (--db flag or config.db.connection)\n const dbConnection = options.db ?? config.db?.connection;\n if (!dbConnection) {\n return notOk(\n errorDatabaseConnectionRequired({\n why: `Database connection is required for ${descriptor.commandName} (set db.connection in ${configPath}, or pass --db <url>)`,\n commandName: descriptor.commandName,\n }),\n );\n }\n\n // Check for driver\n if (!config.driver) {\n return notOk(\n errorDriverRequired({ why: `Config.driver is required for ${descriptor.commandName}` }),\n );\n }\n\n if (!hasMigrations(config.target)) {\n return notOk(\n errorTargetMigrationNotSupported({\n why: `Target \"${config.target.id}\" does not support migrations`,\n }),\n );\n }\n\n // Create control client\n const client = createControlClient({\n family: config.family,\n target: config.target,\n adapter: config.adapter,\n driver: config.driver,\n extensionPacks: config.extensionPacks ?? [],\n });\n\n // Create progress adapter\n const onProgress = createProgressAdapter({ ui, flags });\n\n return ok({\n client,\n contractJson,\n dbConnection,\n onProgress,\n configPath,\n contractPath,\n contractPathAbsolute,\n config,\n });\n}\n\n/**\n * Registers the shared CLI options for migration commands (db init, db update).\n */\nexport function addMigrationCommandOptions(command: Command): Command {\n addGlobalOptions(command);\n return command\n .option('--db <url>', 'Database connection string')\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .option('--dry-run', 'Preview planned operations without applying', false);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAuDA,eAAsB,wBACpB,SACA,OACA,IACA,YACuD;CAEvD,MAAM,SAAS,MAAM,WAAW,QAAQ,OAAO;CAC/C,MAAM,aAAa,QAAQ,SACvB,SAAS,QAAQ,KAAK,EAAE,QAAQ,QAAQ,OAAO,CAAC,GAChD;CACJ,MAAM,uBAAuB,oBAAoB,OAAO;CACxD,MAAM,eAAe,SAAS,QAAQ,KAAK,EAAE,qBAAqB;AAGlE,KAAI,CAAC,MAAM,QAAQ,CAAC,MAAM,OAAO;EAC/B,MAAMA,UAAmD,CACvD;GAAE,OAAO;GAAU,OAAO;GAAY,EACtC;GAAE,OAAO;GAAY,OAAO;GAAc,CAC3C;AACD,MAAI,QAAQ,GACV,SAAQ,KAAK;GAAE,OAAO;GAAY,OAAO,kBAAkB,QAAQ,GAAG;GAAE,CAAC;AAE3E,MAAI,QAAQ,OACV,SAAQ,KAAK;GAAE,OAAO;GAAQ,OAAO;GAAW,CAAC;EAEnD,MAAM,SAAS,mBAAmB;GAChC,SAAS,WAAW;GACpB,aAAa,WAAW;GACxB,KAAK,WAAW;GAChB;GACA;GACD,CAAC;AACF,KAAG,OAAO,OAAO;;CAInB,IAAIC;AACJ,KAAI;AACF,wBAAsB,MAAM,SAAS,sBAAsB,QAAQ;UAC5D,OAAO;AACd,MAAI,iBAAiB,SAAU,MAA4B,SAAS,SAClE,QAAO,MACL,kBAAkB,sBAAsB;GACtC,KAAK,8BAA8B;GACnC,KAAK,iDAAiD,aAAa,4CAA4C;GAChH,CAAC,CACH;AAEH,SAAO,MACL,gBAAgB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,EAAE,EACtE,KAAK,iCAAiC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,IAC7F,CAAC,CACH;;CAIH,IAAIC;AACJ,KAAI;AACF,iBAAe,KAAK,MAAM,oBAAoB;UACvC,OAAO;AACd,SAAO,MACL,8BACE,6BAA6B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,IACnF,EAAE,OAAO,EAAE,MAAM,sBAAsB,EAAE,CAC1C,CACF;;CAIH,MAAM,eAAe,QAAQ,MAAM,OAAO,IAAI;AAC9C,KAAI,CAAC,aACH,QAAO,MACL,gCAAgC;EAC9B,KAAK,uCAAuC,WAAW,YAAY,yBAAyB,WAAW;EACvG,aAAa,WAAW;EACzB,CAAC,CACH;AAIH,KAAI,CAAC,OAAO,OACV,QAAO,MACL,oBAAoB,EAAE,KAAK,iCAAiC,WAAW,eAAe,CAAC,CACxF;AAGH,KAAI,CAAC,cAAc,OAAO,OAAO,CAC/B,QAAO,MACL,iCAAiC,EAC/B,KAAK,WAAW,OAAO,OAAO,GAAG,gCAClC,CAAC,CACH;CAIH,MAAM,SAAS,oBAAoB;EACjC,QAAQ,OAAO;EACf,QAAQ,OAAO;EACf,SAAS,OAAO;EAChB,QAAQ,OAAO;EACf,gBAAgB,OAAO,kBAAkB,EAAE;EAC5C,CAAC;CAGF,MAAM,aAAa,sBAAsB;EAAE;EAAI;EAAO,CAAC;AAEvD,QAAO,GAAG;EACR;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CAAC;;;;;AAMJ,SAAgB,2BAA2B,SAA2B;AACpE,kBAAiB,QAAQ;AACzB,QAAO,QACJ,OAAO,cAAc,6BAA6B,CAClD,OAAO,mBAAmB,gCAAgC,CAC1D,OAAO,aAAa,+CAA+C,MAAM"}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { t as loadConfig } from "./config-loader-ih8ViDb_.mjs";
|
|
2
2
|
import { _ as errorUnexpected, m as errorRuntime, v as mapMigrationToolsError } from "./cli-errors-By1iVE3z.mjs";
|
|
3
3
|
import { t as TerminalUI } from "./terminal-ui-u2YgKghu.mjs";
|
|
4
|
-
import {
|
|
5
|
-
import { t as createControlClient } from "./client-
|
|
4
|
+
import { a as loadMigrationPackages, d as setCommandDescriptions, f as setCommandExamples, g as parseGlobalFlags, h as toStructuralEdge, l as resolveMigrationPaths, m as toPathDecisionResult, n as addGlobalOptions, o as maskConnectionUrl, r as collectDeclaredInvariants, s as readContractEnvelope, t as handleResult, y as formatStyledHeader } from "./result-handler-Ch6hVnOo.mjs";
|
|
5
|
+
import { t as createControlClient } from "./client-1JqqkiC7.mjs";
|
|
6
6
|
import { Command } from "commander";
|
|
7
7
|
import { ifDefined } from "@prisma-next/utils/defined";
|
|
8
8
|
import { notOk, ok } from "@prisma-next/utils/result";
|
|
9
9
|
import { findPath, findPathWithDecision, findReachableLeaves } from "@prisma-next/migration-tools/migration-graph";
|
|
10
10
|
import { bold, cyan, dim, magenta, yellow } from "colorette";
|
|
11
11
|
import { EMPTY_CONTRACT_HASH } from "@prisma-next/migration-tools/constants";
|
|
12
|
-
import { MigrationToolsError } from "@prisma-next/migration-tools/errors";
|
|
12
|
+
import { MigrationToolsError, errorNoInvariantPath, errorUnknownInvariant } from "@prisma-next/migration-tools/errors";
|
|
13
13
|
import { readRefs, resolveRef } from "@prisma-next/migration-tools/refs";
|
|
14
14
|
import dagre from "@dagrejs/dagre";
|
|
15
15
|
|
|
@@ -100,7 +100,8 @@ function migrationGraphToRenderInput(input) {
|
|
|
100
100
|
for (const [, entries] of graph.forwardChain) for (const entry of entries) {
|
|
101
101
|
const status = statusByDirName.get(entry.dirName);
|
|
102
102
|
const icon = status ? STATUS_ICON[status] : "";
|
|
103
|
-
const
|
|
103
|
+
const invariantsSuffix = entry.invariants.length > 0 ? ` provides [${entry.invariants.map((id) => JSON.stringify(id)).join(", ")}]` : "";
|
|
104
|
+
const label = `${entry.dirName}${icon}${invariantsSuffix}`;
|
|
104
105
|
edgeList.push({
|
|
105
106
|
from: toShortId(entry.from),
|
|
106
107
|
to: toShortId(entry.to),
|
|
@@ -1246,6 +1247,7 @@ async function executeMigrationStatusCommand(options, flags, ui) {
|
|
|
1246
1247
|
const hasDriver = !!config.driver;
|
|
1247
1248
|
let activeRefName;
|
|
1248
1249
|
let activeRefHash;
|
|
1250
|
+
let activeRefEntry;
|
|
1249
1251
|
let allRefs = {};
|
|
1250
1252
|
try {
|
|
1251
1253
|
allRefs = await readRefs(refsDir);
|
|
@@ -1256,12 +1258,14 @@ async function executeMigrationStatusCommand(options, flags, ui) {
|
|
|
1256
1258
|
if (options.ref) {
|
|
1257
1259
|
activeRefName = options.ref;
|
|
1258
1260
|
try {
|
|
1259
|
-
|
|
1261
|
+
activeRefEntry = resolveRef(allRefs, activeRefName);
|
|
1262
|
+
activeRefHash = activeRefEntry.hash;
|
|
1260
1263
|
} catch (error) {
|
|
1261
1264
|
if (MigrationToolsError.is(error)) return notOk(mapMigrationToolsError(error));
|
|
1262
1265
|
throw error;
|
|
1263
1266
|
}
|
|
1264
1267
|
}
|
|
1268
|
+
const requiredInvariants = [...activeRefEntry?.invariants ?? []].sort();
|
|
1265
1269
|
const statusRefs = Object.entries(allRefs).map(([name, entry]) => ({
|
|
1266
1270
|
name,
|
|
1267
1271
|
hash: entry.hash,
|
|
@@ -1283,6 +1287,10 @@ async function executeMigrationStatusCommand(options, flags, ui) {
|
|
|
1283
1287
|
label: "ref",
|
|
1284
1288
|
value: activeRefName
|
|
1285
1289
|
});
|
|
1290
|
+
if (activeRefEntry && activeRefEntry.invariants.length > 0) details.push({
|
|
1291
|
+
label: "required",
|
|
1292
|
+
value: formatInvariantList(activeRefEntry.invariants)
|
|
1293
|
+
});
|
|
1286
1294
|
const header = formatStyledHeader({
|
|
1287
1295
|
command: "migration status",
|
|
1288
1296
|
description: "Show migration history and applied status",
|
|
@@ -1325,7 +1333,8 @@ async function executeMigrationStatusCommand(options, flags, ui) {
|
|
|
1325
1333
|
targetHash: EMPTY_CONTRACT_HASH,
|
|
1326
1334
|
contractHash,
|
|
1327
1335
|
summary: "No migrations found",
|
|
1328
|
-
diagnostics
|
|
1336
|
+
diagnostics,
|
|
1337
|
+
requiredInvariants
|
|
1329
1338
|
});
|
|
1330
1339
|
}
|
|
1331
1340
|
let targetHash;
|
|
@@ -1342,6 +1351,7 @@ async function executeMigrationStatusCommand(options, flags, ui) {
|
|
|
1342
1351
|
});
|
|
1343
1352
|
}
|
|
1344
1353
|
let markerHash;
|
|
1354
|
+
let markerInvariants = [];
|
|
1345
1355
|
let mode = "offline";
|
|
1346
1356
|
if (dbConnection && hasDriver) {
|
|
1347
1357
|
const client = createControlClient({
|
|
@@ -1353,7 +1363,9 @@ async function executeMigrationStatusCommand(options, flags, ui) {
|
|
|
1353
1363
|
});
|
|
1354
1364
|
try {
|
|
1355
1365
|
await client.connect(dbConnection);
|
|
1356
|
-
|
|
1366
|
+
const marker = await client.readMarker();
|
|
1367
|
+
markerHash = marker?.storageHash;
|
|
1368
|
+
markerInvariants = marker?.invariants ?? [];
|
|
1357
1369
|
mode = "online";
|
|
1358
1370
|
} catch {
|
|
1359
1371
|
if (!flags.json && !flags.quiet) ui.warn("Could not connect to database — showing offline status");
|
|
@@ -1361,6 +1373,17 @@ async function executeMigrationStatusCommand(options, flags, ui) {
|
|
|
1361
1373
|
await client.close();
|
|
1362
1374
|
}
|
|
1363
1375
|
}
|
|
1376
|
+
if (activeRefEntry && activeRefEntry.invariants.length > 0) {
|
|
1377
|
+
const declared = collectDeclaredInvariants(graph);
|
|
1378
|
+
const known = new Set(declared);
|
|
1379
|
+
if (mode === "online") for (const id of markerInvariants) known.add(id);
|
|
1380
|
+
const unknown = activeRefEntry.invariants.filter((id) => !known.has(id));
|
|
1381
|
+
if (unknown.length > 0) return notOk(mapMigrationToolsError(errorUnknownInvariant({
|
|
1382
|
+
...ifDefined("refName", activeRefName),
|
|
1383
|
+
unknown,
|
|
1384
|
+
declared: [...declared].sort()
|
|
1385
|
+
})));
|
|
1386
|
+
}
|
|
1364
1387
|
if (mode === "online" && markerHash !== void 0 && !graph.nodes.has(markerHash) && markerHash !== contractHash) {
|
|
1365
1388
|
const hints = [];
|
|
1366
1389
|
if (graph.nodes.has(contractHash)) hints.push("Run 'prisma-next db sign' to overwrite the marker if the database already matches the contract", "Run 'prisma-next db update' to push the current contract to the database", "Run 'prisma-next contract infer' to make your contract match the database", "Run 'prisma-next db verify' to inspect the database state");
|
|
@@ -1380,6 +1403,7 @@ async function executeMigrationStatusCommand(options, flags, ui) {
|
|
|
1380
1403
|
summary: `${bundles.length} migration(s) on disk`,
|
|
1381
1404
|
diagnostics,
|
|
1382
1405
|
markerHash,
|
|
1406
|
+
requiredInvariants,
|
|
1383
1407
|
...statusRefs.length > 0 ? { refs: statusRefs } : {}
|
|
1384
1408
|
});
|
|
1385
1409
|
}
|
|
@@ -1404,6 +1428,7 @@ async function executeMigrationStatusCommand(options, flags, ui) {
|
|
|
1404
1428
|
summary: `${bundles.length} migration(s) on disk`,
|
|
1405
1429
|
diagnostics,
|
|
1406
1430
|
...ifDefined("markerHash", markerHash),
|
|
1431
|
+
requiredInvariants,
|
|
1407
1432
|
...statusRefs.length > 0 ? { refs: statusRefs } : {},
|
|
1408
1433
|
graph,
|
|
1409
1434
|
bundles,
|
|
@@ -1418,35 +1443,68 @@ async function executeMigrationStatusCommand(options, flags, ui) {
|
|
|
1418
1443
|
const entries = buildMigrationEntries(chain, bundles, mode, markerHash, edgeStatuses);
|
|
1419
1444
|
const pendingCount = edgeStatuses.filter((e) => e.status === "pending").length;
|
|
1420
1445
|
const appliedCount = edgeStatuses.filter((e) => e.status === "applied").length;
|
|
1446
|
+
let appliedInvariants;
|
|
1447
|
+
let missingInvariants;
|
|
1448
|
+
let effectiveRequired = /* @__PURE__ */ new Set();
|
|
1449
|
+
if (mode === "online") {
|
|
1450
|
+
const markerSet = new Set(markerInvariants);
|
|
1451
|
+
effectiveRequired = new Set(requiredInvariants.filter((id) => !markerSet.has(id)));
|
|
1452
|
+
appliedInvariants = requiredInvariants.filter((id) => markerSet.has(id));
|
|
1453
|
+
missingInvariants = [...effectiveRequired].sort();
|
|
1454
|
+
}
|
|
1455
|
+
const hasInvariantWork = effectiveRequired.size > 0;
|
|
1456
|
+
const missingList = [...effectiveRequired].sort().join(", ");
|
|
1421
1457
|
let summary;
|
|
1422
1458
|
if (mode === "online") if (markerHash !== void 0 && !graph.nodes.has(markerHash) && markerHash === contractHash) summary = `${bundles.length} migration(s) on disk`;
|
|
1423
|
-
else if (activeRefHash && markerHash !== void 0)
|
|
1424
|
-
|
|
1459
|
+
else if (activeRefHash && markerHash !== void 0) {
|
|
1460
|
+
const distance = summarizeRefDistance(graph, markerHash, activeRefHash, activeRefName);
|
|
1461
|
+
summary = hasInvariantWork ? `${distance} — missing invariant(s): ${missingList}` : distance;
|
|
1462
|
+
} else if (pendingCount === 0 && !hasInvariantWork) summary = `Database is up to date (${appliedCount} migration${appliedCount !== 1 ? "s" : ""} applied)`;
|
|
1463
|
+
else if (pendingCount === 0 && hasInvariantWork) summary = `Missing invariant(s): ${missingList} — run 'prisma-next migration apply --ref ${activeRefName ?? "<ref>"}' to apply`;
|
|
1425
1464
|
else if (markerHash === void 0) summary = `${pendingCount} pending migration(s) — database has no marker`;
|
|
1426
1465
|
else summary = `${pendingCount} pending migration(s) — run 'prisma-next migration apply' to apply`;
|
|
1427
1466
|
else summary = `${entries.length} migration(s) on disk`;
|
|
1428
|
-
if (mode === "online") if (markerHash !== void 0 && !graph.nodes.has(markerHash) && markerHash === contractHash) diagnostics.push({
|
|
1429
|
-
code: "MIGRATION.MARKER_NOT_IN_HISTORY",
|
|
1430
|
-
severity: "warn",
|
|
1431
|
-
message: "Database matches the current contract but was updated directly (not via migration apply)",
|
|
1432
|
-
hints: ["Run 'prisma-next migration plan' to plan a migration to your current contract"]
|
|
1433
|
-
});
|
|
1434
|
-
else if (pendingCount > 0) diagnostics.push({
|
|
1435
|
-
code: "MIGRATION.DATABASE_BEHIND",
|
|
1436
|
-
severity: "info",
|
|
1437
|
-
message: `${pendingCount} migration(s) pending`,
|
|
1438
|
-
hints: ["Run 'prisma-next migration apply' to apply pending migrations"]
|
|
1439
|
-
});
|
|
1440
|
-
else diagnostics.push({
|
|
1441
|
-
code: "MIGRATION.UP_TO_DATE",
|
|
1442
|
-
severity: "info",
|
|
1443
|
-
message: "Database is up to date",
|
|
1444
|
-
hints: []
|
|
1445
|
-
});
|
|
1446
1467
|
let pathDecision;
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1468
|
+
let routingUnreachable = false;
|
|
1469
|
+
if (mode === "online") {
|
|
1470
|
+
const outcome = findPathWithDecision(graph, markerHash ?? EMPTY_CONTRACT_HASH, targetHash, {
|
|
1471
|
+
...ifDefined("refName", activeRefName),
|
|
1472
|
+
required: effectiveRequired
|
|
1473
|
+
});
|
|
1474
|
+
if (outcome.kind === "ok") pathDecision = toPathDecisionResult(outcome.decision);
|
|
1475
|
+
else if (outcome.kind === "unsatisfiable") return notOk(mapMigrationToolsError(errorNoInvariantPath({
|
|
1476
|
+
...ifDefined("refName", activeRefName),
|
|
1477
|
+
required: [...effectiveRequired].sort(),
|
|
1478
|
+
missing: outcome.missing,
|
|
1479
|
+
structuralPath: outcome.structuralPath.map(toStructuralEdge)
|
|
1480
|
+
})));
|
|
1481
|
+
else routingUnreachable = true;
|
|
1482
|
+
}
|
|
1483
|
+
if (mode === "online") {
|
|
1484
|
+
if (markerHash !== void 0 && !graph.nodes.has(markerHash) && markerHash === contractHash) diagnostics.push({
|
|
1485
|
+
code: "MIGRATION.MARKER_NOT_IN_HISTORY",
|
|
1486
|
+
severity: "warn",
|
|
1487
|
+
message: "Database matches the current contract but was updated directly (not via migration apply)",
|
|
1488
|
+
hints: ["Run 'prisma-next migration plan' to plan a migration to your current contract"]
|
|
1489
|
+
});
|
|
1490
|
+
else if (pendingCount > 0) diagnostics.push({
|
|
1491
|
+
code: "MIGRATION.DATABASE_BEHIND",
|
|
1492
|
+
severity: "info",
|
|
1493
|
+
message: `${pendingCount} migration(s) pending`,
|
|
1494
|
+
hints: ["Run 'prisma-next migration apply' to apply pending migrations"]
|
|
1495
|
+
});
|
|
1496
|
+
else if (hasInvariantWork) diagnostics.push({
|
|
1497
|
+
code: "MIGRATION.INVARIANTS_PENDING",
|
|
1498
|
+
severity: "info",
|
|
1499
|
+
message: `Missing required invariant(s): ${missingList}`,
|
|
1500
|
+
hints: [`Run 'prisma-next migration apply --ref ${activeRefName ?? "<ref>"}' to apply a path that covers the required invariants`]
|
|
1501
|
+
});
|
|
1502
|
+
else if (!routingUnreachable) diagnostics.push({
|
|
1503
|
+
code: "MIGRATION.UP_TO_DATE",
|
|
1504
|
+
severity: "info",
|
|
1505
|
+
message: "Database is up to date",
|
|
1506
|
+
hints: []
|
|
1507
|
+
});
|
|
1450
1508
|
}
|
|
1451
1509
|
return ok({
|
|
1452
1510
|
ok: true,
|
|
@@ -1457,6 +1515,9 @@ async function executeMigrationStatusCommand(options, flags, ui) {
|
|
|
1457
1515
|
summary,
|
|
1458
1516
|
diagnostics,
|
|
1459
1517
|
...ifDefined("markerHash", markerHash),
|
|
1518
|
+
requiredInvariants,
|
|
1519
|
+
...ifDefined("appliedInvariants", appliedInvariants),
|
|
1520
|
+
...ifDefined("missingInvariants", missingInvariants),
|
|
1460
1521
|
...statusRefs.length > 0 ? { refs: statusRefs } : {},
|
|
1461
1522
|
...ifDefined("pathDecision", pathDecision),
|
|
1462
1523
|
graph,
|
|
@@ -1478,7 +1539,7 @@ function createMigrationStatusCommand() {
|
|
|
1478
1539
|
});
|
|
1479
1540
|
const exitCode = handleResult(await executeMigrationStatusCommand(options, flags, ui), flags, ui, (statusResult) => {
|
|
1480
1541
|
if (flags.json) {
|
|
1481
|
-
const { graph:
|
|
1542
|
+
const { graph: _graph, bundles: _bundles, edgeStatuses: _edgeStatuses, activeRefHash: _activeRefHash, activeRefName: _activeRefName, diverged: _diverged, ...jsonResult } = statusResult;
|
|
1482
1543
|
ui.output(JSON.stringify(jsonResult, null, 2));
|
|
1483
1544
|
} else if (!flags.quiet) {
|
|
1484
1545
|
const colorize = flags.color !== false;
|
|
@@ -1528,10 +1589,15 @@ function formatStatusSummary(result, colorize) {
|
|
|
1528
1589
|
const hasUnknown = result.migrations.some((e) => e.status === "unknown");
|
|
1529
1590
|
const pendingCount = result.migrations.filter((e) => e.status === "pending").length;
|
|
1530
1591
|
const hasWarnings = result.diagnostics?.some((d) => d.severity === "warn") ?? false;
|
|
1592
|
+
const hasInvariantPending = result.diagnostics?.some((d) => d.code === "MIGRATION.INVARIANTS_PENDING") ?? false;
|
|
1531
1593
|
if (result.mode === "online") if (hasUnknown || hasWarnings) lines.push(`${c(yellow, "⚠")} ${result.summary}`);
|
|
1532
|
-
else if (pendingCount === 0) lines.push(`${c(cyan, "✔")} ${result.summary}`);
|
|
1594
|
+
else if (pendingCount === 0 && !hasInvariantPending) lines.push(`${c(cyan, "✔")} ${result.summary}`);
|
|
1533
1595
|
else lines.push(`${c(yellow, "⧗")} ${result.summary}`);
|
|
1534
1596
|
else lines.push(result.summary);
|
|
1597
|
+
if (result.requiredInvariants.length > 0) if (result.appliedInvariants !== void 0 && result.missingInvariants !== void 0) {
|
|
1598
|
+
lines.push(`${c(dim, "applied ")}${formatInvariantList(result.appliedInvariants)}`);
|
|
1599
|
+
lines.push(`${c(dim, "missing ")}${formatInvariantList(result.missingInvariants)}`);
|
|
1600
|
+
} else lines.push(`${c(dim, "applied ")}(unknown — connect a database to evaluate)`);
|
|
1535
1601
|
const warnings = result.diagnostics?.filter((d) => d.severity === "warn") ?? [];
|
|
1536
1602
|
for (const diag of warnings) {
|
|
1537
1603
|
lines.push(`${c(yellow, "⚠")} ${diag.message}`);
|
|
@@ -1539,6 +1605,9 @@ function formatStatusSummary(result, colorize) {
|
|
|
1539
1605
|
}
|
|
1540
1606
|
return lines.join("\n");
|
|
1541
1607
|
}
|
|
1608
|
+
function formatInvariantList(ids) {
|
|
1609
|
+
return ids.length === 0 ? "(none)" : ids.join(", ");
|
|
1610
|
+
}
|
|
1542
1611
|
function summarizeRefDistance(graph, markerHash, refHash, refName) {
|
|
1543
1612
|
if (markerHash === refHash) return `At ref "${refName}" target`;
|
|
1544
1613
|
const pathToRef = findPath(graph, markerHash, refHash);
|
|
@@ -1549,5 +1618,5 @@ function summarizeRefDistance(graph, markerHash, refHash, refName) {
|
|
|
1549
1618
|
}
|
|
1550
1619
|
|
|
1551
1620
|
//#endregion
|
|
1552
|
-
export { deriveEdgeStatuses as n, createMigrationStatusCommand as t };
|
|
1553
|
-
//# sourceMappingURL=migration-status-
|
|
1621
|
+
export { deriveEdgeStatuses as n, formatStatusSummary as r, createMigrationStatusCommand as t };
|
|
1622
|
+
//# sourceMappingURL=migration-status-DoPrFIOQ.mjs.map
|