@prisma-next/errors 0.4.0-dev.6 → 0.4.0-dev.8

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.
@@ -1,5 +1,28 @@
1
1
  //#region src/control.ts
2
2
  /**
3
+ * Domain prefix for structured CLI error codes.
4
+ *
5
+ * The full envelope code is rendered as `PN-<domain>-<code>` (see
6
+ * `CliStructuredError.toEnvelope`). The supported domains follow the
7
+ * taxonomy documented in `docs/CLI Style Guide.md`:
8
+ *
9
+ * - `CLI` — CLI command processing (config, validation, planning)
10
+ * - `MIG` — Migration subsystem (authoring, planning conflicts, runner)
11
+ * - `RUN` — Application runtime (query execution, streaming)
12
+ * - `CON` — Contract subsystem (validation, normalization)
13
+ * - `SCHEMA` — Schema subsystem
14
+ *
15
+ * Sub-clustering within a domain is conveyed by the numeric code range; see
16
+ * the per-domain source files for reserved ranges.
17
+ */
18
+ const CLI_ERROR_DOMAINS = [
19
+ "CLI",
20
+ "RUN",
21
+ "MIG",
22
+ "CON",
23
+ "SCHEMA"
24
+ ];
25
+ /**
3
26
  * Structured CLI error that contains all information needed for error envelopes.
4
27
  * Call sites throw these errors with full context.
5
28
  */
@@ -33,11 +56,7 @@ var CliStructuredError = class extends Error {
33
56
  toEnvelope() {
34
57
  return {
35
58
  ok: false,
36
- code: `${{
37
- CLI: "PN-CLI-",
38
- RUN: "PN-RUN-",
39
- MIG: "PN-MIG-"
40
- }[this.domain]}${this.code}`,
59
+ code: `PN-${this.domain}-${this.code}`,
41
60
  domain: this.domain,
42
61
  severity: this.severity,
43
62
  summary: this.message,
@@ -55,9 +74,13 @@ var CliStructuredError = class extends Error {
55
74
  static is(error) {
56
75
  if (!(error instanceof Error)) return false;
57
76
  const candidate = error;
58
- return candidate.name === "CliStructuredError" && typeof candidate.code === "string" && (candidate.domain === "CLI" || candidate.domain === "RUN" || candidate.domain === "MIG") && typeof candidate.toEnvelope === "function";
77
+ return candidate.name === "CliStructuredError" && typeof candidate.code === "string" && isCliErrorDomain(candidate.domain) && typeof candidate.toEnvelope === "function";
59
78
  }
60
79
  };
80
+ const CLI_ERROR_DOMAIN_SET = new Set(CLI_ERROR_DOMAINS);
81
+ function isCliErrorDomain(value) {
82
+ return typeof value === "string" && CLI_ERROR_DOMAIN_SET.has(value);
83
+ }
61
84
  /**
62
85
  * Config file not found or missing.
63
86
  */
@@ -230,4 +253,4 @@ function errorUnexpected(message, options) {
230
253
 
231
254
  //#endregion
232
255
  export { errorContractMissingExtensionPacks as a, errorDriverRequired as c, errorJsonFormatNotSupported as d, errorMigrationPlanningFailed as f, errorUnexpected as h, errorContractConfigMissing as i, errorFamilyReadMarkerSqlRequired as l, errorTargetMigrationNotSupported as m, errorConfigFileNotFound as n, errorContractValidationFailed as o, errorQueryRunnerFactoryRequired as p, errorConfigValidation as r, errorDatabaseConnectionRequired as s, CliStructuredError as t, errorFileNotFound as u };
233
- //# sourceMappingURL=control-BHDp3kOD.mjs.map
256
+ //# sourceMappingURL=control-CjD1SB2D.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"control-CjD1SB2D.mjs","names":["CLI_ERROR_DOMAIN_SET: ReadonlySet<CliErrorDomain>"],"sources":["../src/control.ts"],"sourcesContent":["/**\n * CLI error envelope for output formatting.\n * This is the serialized form of a CliStructuredError.\n */\nexport interface CliErrorEnvelope {\n readonly ok: false;\n readonly code: string;\n readonly domain: string;\n readonly severity: 'error' | 'warn' | 'info';\n readonly summary: string;\n readonly why: string | undefined;\n readonly fix: string | undefined;\n readonly where:\n | {\n readonly path: string | undefined;\n readonly line: number | undefined;\n }\n | undefined;\n readonly meta: Record<string, unknown> | undefined;\n readonly docsUrl: string | undefined;\n}\n\n/**\n * Minimal conflict data structure expected by CLI output.\n */\nexport interface CliErrorConflict {\n readonly kind: string;\n readonly summary: string;\n readonly why?: string;\n}\n\n/**\n * Domain prefix for structured CLI error codes.\n *\n * The full envelope code is rendered as `PN-<domain>-<code>` (see\n * `CliStructuredError.toEnvelope`). The supported domains follow the\n * taxonomy documented in `docs/CLI Style Guide.md`:\n *\n * - `CLI` — CLI command processing (config, validation, planning)\n * - `MIG` — Migration subsystem (authoring, planning conflicts, runner)\n * - `RUN` — Application runtime (query execution, streaming)\n * - `CON` — Contract subsystem (validation, normalization)\n * - `SCHEMA` — Schema subsystem\n *\n * Sub-clustering within a domain is conveyed by the numeric code range; see\n * the per-domain source files for reserved ranges.\n */\nconst CLI_ERROR_DOMAINS = ['CLI', 'RUN', 'MIG', 'CON', 'SCHEMA'] as const;\n\nexport type CliErrorDomain = (typeof CLI_ERROR_DOMAINS)[number];\n\n/**\n * Structured CLI error that contains all information needed for error envelopes.\n * Call sites throw these errors with full context.\n */\nexport class CliStructuredError extends Error {\n readonly code: string;\n readonly domain: CliErrorDomain;\n readonly severity: 'error' | 'warn' | 'info';\n readonly why: string | undefined;\n readonly fix: string | undefined;\n readonly where:\n | {\n readonly path: string | undefined;\n readonly line: number | undefined;\n }\n | undefined;\n readonly meta: Record<string, unknown> | undefined;\n readonly docsUrl: string | undefined;\n\n constructor(\n code: string,\n summary: string,\n options?: {\n readonly domain?: CliErrorDomain;\n readonly severity?: 'error' | 'warn' | 'info';\n readonly why?: string;\n readonly fix?: string;\n readonly where?: { readonly path?: string; readonly line?: number };\n readonly meta?: Record<string, unknown>;\n readonly docsUrl?: string;\n },\n ) {\n super(summary);\n this.name = 'CliStructuredError';\n this.code = code;\n this.domain = options?.domain ?? 'CLI';\n this.severity = options?.severity ?? 'error';\n this.why = options?.why;\n this.fix = options?.fix === options?.why ? undefined : options?.fix;\n this.where = options?.where\n ? {\n path: options.where.path,\n line: options.where.line,\n }\n : undefined;\n this.meta = options?.meta;\n this.docsUrl = options?.docsUrl;\n }\n\n /**\n * Converts this error to a CLI error envelope for output formatting.\n */\n toEnvelope(): CliErrorEnvelope {\n return {\n ok: false as const,\n code: `PN-${this.domain}-${this.code}`,\n domain: this.domain,\n severity: this.severity,\n summary: this.message,\n why: this.why,\n fix: this.fix,\n where: this.where,\n meta: this.meta,\n docsUrl: this.docsUrl,\n };\n }\n\n /**\n * Type guard to check if an error is a CliStructuredError.\n * Uses duck-typing to work across module boundaries where instanceof may fail.\n */\n static is(error: unknown): error is CliStructuredError {\n if (!(error instanceof Error)) {\n return false;\n }\n const candidate = error as CliStructuredError;\n return (\n candidate.name === 'CliStructuredError' &&\n typeof candidate.code === 'string' &&\n isCliErrorDomain(candidate.domain) &&\n typeof candidate.toEnvelope === 'function'\n );\n }\n}\n\nconst CLI_ERROR_DOMAIN_SET: ReadonlySet<CliErrorDomain> = new Set(CLI_ERROR_DOMAINS);\n\nfunction isCliErrorDomain(value: unknown): value is CliErrorDomain {\n return typeof value === 'string' && CLI_ERROR_DOMAIN_SET.has(value as CliErrorDomain);\n}\n\n// ============================================================================\n// Config Errors (PN-CLI-4001-4007)\n// ============================================================================\n\n/**\n * Config file not found or missing.\n */\nexport function errorConfigFileNotFound(\n configPath?: string,\n options?: {\n readonly why?: string;\n },\n): CliStructuredError {\n return new CliStructuredError('4001', 'Config file not found', {\n domain: 'CLI',\n ...(options?.why ? { why: options.why } : { why: 'Config file not found' }),\n fix: \"Run 'prisma-next init' to create a config file\",\n docsUrl: 'https://prisma-next.dev/docs/cli/config',\n ...(configPath ? { where: { path: configPath } } : {}),\n });\n}\n\n/**\n * Contract configuration missing from config.\n */\nexport function errorContractConfigMissing(options?: {\n readonly why?: string;\n}): CliStructuredError {\n return new CliStructuredError('4002', 'Contract configuration missing', {\n domain: 'CLI',\n why: options?.why ?? 'The contract configuration is required for emit',\n fix: 'Add contract configuration to your prisma-next.config.ts',\n docsUrl: 'https://prisma-next.dev/docs/cli/contract-emit',\n });\n}\n\n/**\n * Contract validation failed.\n */\nexport function errorContractValidationFailed(\n reason: string,\n options?: {\n readonly where?: { readonly path?: string; readonly line?: number };\n },\n): CliStructuredError {\n return new CliStructuredError('4003', 'Contract validation failed', {\n domain: 'CLI',\n why: reason,\n fix: 'Re-run `prisma-next contract emit`, or fix the contract file and try again',\n docsUrl: 'https://prisma-next.dev/docs/contracts',\n ...(options?.where ? { where: options.where } : {}),\n });\n}\n\n/**\n * File not found.\n */\nexport function errorFileNotFound(\n filePath: string,\n options?: {\n readonly why?: string;\n readonly fix?: string;\n readonly docsUrl?: string;\n },\n): CliStructuredError {\n return new CliStructuredError('4004', 'File not found', {\n domain: 'CLI',\n why: options?.why ?? `File not found: ${filePath}`,\n fix: options?.fix ?? 'Check that the file path is correct',\n where: { path: filePath },\n ...(options?.docsUrl ? { docsUrl: options.docsUrl } : {}),\n });\n}\n\n/**\n * Database connection is required but not provided.\n */\nexport function errorDatabaseConnectionRequired(options?: {\n readonly why?: string;\n readonly commandName?: string;\n readonly retryCommand?: string;\n}): CliStructuredError {\n const runHint = options?.retryCommand\n ? `Run \\`${options.retryCommand}\\``\n : options?.commandName\n ? `Run \\`prisma-next ${options.commandName} --db <url>\\``\n : 'Provide `--db <url>`';\n return new CliStructuredError('4005', 'Database connection is required', {\n domain: 'CLI',\n why: options?.why ?? 'Database connection is required for this command',\n fix: `${runHint}, or set \\`db: { connection: \"postgres://…\" }\\` in prisma-next.config.ts`,\n });\n}\n\n/**\n * Query runner factory is required but not provided in config.\n */\nexport function errorQueryRunnerFactoryRequired(options?: {\n readonly why?: string;\n}): CliStructuredError {\n return new CliStructuredError('4006', 'Query runner factory is required', {\n domain: 'CLI',\n why: options?.why ?? 'Config.db.queryRunnerFactory is required for db verify',\n fix: 'Add db.queryRunnerFactory to prisma-next.config.ts',\n docsUrl: 'https://prisma-next.dev/docs/cli/db-verify',\n });\n}\n\n/**\n * Family verify.readMarker is required but not provided.\n */\nexport function errorFamilyReadMarkerSqlRequired(options?: {\n readonly why?: string;\n}): CliStructuredError {\n return new CliStructuredError('4007', 'Family readMarker() is required', {\n domain: 'CLI',\n why: options?.why ?? 'Family verify.readMarker is required for db verify',\n fix: 'Ensure family.verify.readMarker() is exported by your family package',\n docsUrl: 'https://prisma-next.dev/docs/cli/db-verify',\n });\n}\n\n/**\n * JSON output format not supported.\n */\nexport function errorJsonFormatNotSupported(options: {\n readonly command: string;\n readonly format: string;\n readonly supportedFormats: readonly string[];\n}): CliStructuredError {\n return new CliStructuredError('4008', 'Unsupported JSON format', {\n domain: 'CLI',\n why: `The ${options.command} command does not support --json ${options.format}`,\n fix: `Use --json ${options.supportedFormats.join(' or ')}, or omit --json for human output`,\n meta: {\n command: options.command,\n format: options.format,\n supportedFormats: options.supportedFormats,\n },\n });\n}\n\n/**\n * Driver is required for DB-connected commands but not provided.\n */\nexport function errorDriverRequired(options?: { readonly why?: string }): CliStructuredError {\n return new CliStructuredError('4010', 'Driver is required for DB-connected commands', {\n domain: 'CLI',\n why: options?.why ?? 'Config.driver is required for DB-connected commands',\n fix: 'Add a control-plane driver to prisma-next.config.ts (e.g. import a driver descriptor and set `driver: postgresDriver`)',\n docsUrl: 'https://prisma-next.dev/docs/cli/config',\n });\n}\n\n/**\n * Contract requires extension packs that are not provided by config descriptors.\n */\nexport function errorContractMissingExtensionPacks(options: {\n readonly missingExtensionPacks: readonly string[];\n readonly providedComponentIds: readonly string[];\n}): CliStructuredError {\n const missing = [...options.missingExtensionPacks].sort();\n return new CliStructuredError('4011', 'Missing extension packs in config', {\n domain: 'CLI',\n why:\n missing.length === 1\n ? `Contract requires extension pack '${missing[0]}', but CLI config does not provide a matching descriptor.`\n : `Contract requires extension packs ${missing.map((p) => `'${p}'`).join(', ')}, but CLI config does not provide matching descriptors.`,\n fix: 'Add the missing extension descriptors to `extensions` in prisma-next.config.ts',\n docsUrl: 'https://prisma-next.dev/docs/cli/config',\n meta: {\n missingExtensionPacks: missing,\n providedComponentIds: [...options.providedComponentIds].sort(),\n },\n });\n}\n\n/**\n * Migration planning failed due to conflicts.\n */\nexport function errorMigrationPlanningFailed(options: {\n readonly conflicts: readonly CliErrorConflict[];\n readonly why?: string;\n}): CliStructuredError {\n const conflictSummaries = options.conflicts.map((c) => c.summary);\n const computedWhy = options.why ?? conflictSummaries.join('\\n');\n\n const conflictFixes = options.conflicts\n .map((c) => c.why)\n .filter((why): why is string => typeof why === 'string');\n const computedFix =\n conflictFixes.length > 0\n ? conflictFixes.join('\\n')\n : 'Use `db verify --schema-only` to inspect conflicts, or ensure the database is empty';\n\n return new CliStructuredError('4020', 'Migration planning failed', {\n domain: 'CLI',\n why: computedWhy,\n fix: computedFix,\n meta: { conflicts: options.conflicts },\n docsUrl: 'https://prisma-next.dev/docs/cli/db-init',\n });\n}\n\n/**\n * Target does not support migrations (missing createPlanner/createRunner).\n */\nexport function errorTargetMigrationNotSupported(options?: {\n readonly why?: string;\n}): CliStructuredError {\n return new CliStructuredError('4021', 'Target does not support migrations', {\n domain: 'CLI',\n why: options?.why ?? 'The configured target does not provide migration planner/runner',\n fix: 'Select a target that provides migrations (it must export `target.migrations` for db init)',\n docsUrl: 'https://prisma-next.dev/docs/cli/db-init',\n });\n}\n\n/**\n * Config validation error (missing required fields).\n */\nexport function errorConfigValidation(\n field: string,\n options?: {\n readonly why?: string;\n },\n): CliStructuredError {\n return new CliStructuredError('4009', 'Config validation error', {\n domain: 'CLI',\n why: options?.why ?? `Config must have a \"${field}\" field`,\n fix: 'Check your prisma-next.config.ts and ensure all required fields are provided',\n docsUrl: 'https://prisma-next.dev/docs/cli/config',\n });\n}\n\n// ============================================================================\n// Generic Error\n// ============================================================================\n\n/**\n * Generic unexpected error.\n */\nexport function errorUnexpected(\n message: string,\n options?: {\n readonly why?: string;\n readonly fix?: string;\n },\n): CliStructuredError {\n return new CliStructuredError('4999', 'Unexpected error', {\n domain: 'CLI',\n why: options?.why ?? message,\n fix: options?.fix ?? 'Check the error message and try again',\n });\n}\n"],"mappings":"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"}
@@ -26,13 +26,31 @@ interface CliErrorConflict {
26
26
  readonly summary: string;
27
27
  readonly why?: string;
28
28
  }
29
+ /**
30
+ * Domain prefix for structured CLI error codes.
31
+ *
32
+ * The full envelope code is rendered as `PN-<domain>-<code>` (see
33
+ * `CliStructuredError.toEnvelope`). The supported domains follow the
34
+ * taxonomy documented in `docs/CLI Style Guide.md`:
35
+ *
36
+ * - `CLI` — CLI command processing (config, validation, planning)
37
+ * - `MIG` — Migration subsystem (authoring, planning conflicts, runner)
38
+ * - `RUN` — Application runtime (query execution, streaming)
39
+ * - `CON` — Contract subsystem (validation, normalization)
40
+ * - `SCHEMA` — Schema subsystem
41
+ *
42
+ * Sub-clustering within a domain is conveyed by the numeric code range; see
43
+ * the per-domain source files for reserved ranges.
44
+ */
45
+ declare const CLI_ERROR_DOMAINS: readonly ["CLI", "RUN", "MIG", "CON", "SCHEMA"];
46
+ type CliErrorDomain = (typeof CLI_ERROR_DOMAINS)[number];
29
47
  /**
30
48
  * Structured CLI error that contains all information needed for error envelopes.
31
49
  * Call sites throw these errors with full context.
32
50
  */
33
51
  declare class CliStructuredError extends Error {
34
52
  readonly code: string;
35
- readonly domain: 'CLI' | 'RUN' | 'MIG';
53
+ readonly domain: CliErrorDomain;
36
54
  readonly severity: 'error' | 'warn' | 'info';
37
55
  readonly why: string | undefined;
38
56
  readonly fix: string | undefined;
@@ -43,7 +61,7 @@ declare class CliStructuredError extends Error {
43
61
  readonly meta: Record<string, unknown> | undefined;
44
62
  readonly docsUrl: string | undefined;
45
63
  constructor(code: string, summary: string, options?: {
46
- readonly domain?: 'CLI' | 'RUN' | 'MIG';
64
+ readonly domain?: CliErrorDomain;
47
65
  readonly severity?: 'error' | 'warn' | 'info';
48
66
  readonly why?: string;
49
67
  readonly fix?: string;
@@ -162,4 +180,4 @@ declare function errorUnexpected(message: string, options?: {
162
180
  }): CliStructuredError;
163
181
  //#endregion
164
182
  export { errorUnexpected as _, errorConfigValidation as a, errorContractValidationFailed as c, errorFamilyReadMarkerSqlRequired as d, errorFileNotFound as f, errorTargetMigrationNotSupported as g, errorQueryRunnerFactoryRequired as h, errorConfigFileNotFound as i, errorDatabaseConnectionRequired as l, errorMigrationPlanningFailed as m, CliErrorEnvelope as n, errorContractConfigMissing as o, errorJsonFormatNotSupported as p, CliStructuredError as r, errorContractMissingExtensionPacks as s, CliErrorConflict as t, errorDriverRequired as u };
165
- //# sourceMappingURL=control-C16uWwh2.d.mts.map
183
+ //# sourceMappingURL=control-M7-bPTyk.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"control-M7-bPTyk.d.mts","names":[],"sources":["../src/control.ts"],"sourcesContent":[],"mappings":";;AAIA;AAqBA;AAIC;AAoBW,UA7CK,gBAAA,CA6CoB;EAMxB,SAAA,EAAA,EAAA,KAAA;EAEM,SAAA,IAAA,EAAA,MAAA;EAUF,SAAA,MAAA,EAAA,MAAA;EAOO,SAAA,QAAA,EAAA,OAAA,GAAA,MAAA,GAAA,MAAA;EAKF,SAAA,OAAA,EAAA,MAAA;EAwBN,SAAA,GAAA,EAAA,MAAA,GAAA,SAAA;EAmBsB,SAAA,GAAA,EAAA,MAAA,GAAA,SAAA;EAnEE,SAAA,KAAA,EAAA;IAAK,SAAA,IAAA,EAAA,MAAA,GAAA,SAAA;IA8F7B,SAAA,IAAA,EAAA,MAAA,GAAuB,SAKpC;EAaa,CAAA,GAAA,SAAA;EAcA,SAAA,IAAA,EAnKC,MAmKD,CAAA,MAAA,EAAA,OAA6B,CAAA,GAAA,SAK1C;EAaa,SAAA,OAAA,EAAA,MAAiB,GAAA,SAO9B;AAaH;AAoBA;AAcA;AAcA;AAoBgB,UAtQC,gBAAA,CAsQkB;EAYnB,SAAA,IAAA,EAAA,MAAA;EAuBA,SAAA,OAAA,EAAA,MAAA;EA2BA,SAAA,GAAA,CAAA,EAAA,MAAA;AAchB;AAqBA;;;;;;;;;;;;;;;;cAjVM;KAEM,cAAA,WAAyB;;;;;cAMxB,kBAAA,SAA2B,KAAA;;mBAErB;;;;;;;;iBAUF;;;sBAOO;;;;;;;;oBAKF;;;;;;gBAwBN;;;;;sCAmBsB;;;;;iBA2BtB,uBAAA;;IAKb;;;;iBAaa,0BAAA;;IAEZ;;;;iBAYY,6BAAA;;;;;IAKb;;;;iBAaa,iBAAA;;;;IAOb;;;;iBAaa,+BAAA;;;;IAIZ;;;;iBAgBY,+BAAA;;IAEZ;;;;iBAYY,gCAAA;;IAEZ;;;;iBAYY,2BAAA;;;;IAIZ;;;;iBAgBY,mBAAA;;IAA0D;;;;iBAY1D,kCAAA;;;IAGZ;;;;iBAoBY,4BAAA;+BACe;;IAE3B;;;;iBAwBY,gCAAA;;IAEZ;;;;iBAYY,qBAAA;;IAKb;;;;iBAgBa,eAAA;;;IAMb"}
@@ -1,2 +1,2 @@
1
- import { _ as errorUnexpected, a as errorConfigValidation, c as errorContractValidationFailed, d as errorFamilyReadMarkerSqlRequired, f as errorFileNotFound, g as errorTargetMigrationNotSupported, h as errorQueryRunnerFactoryRequired, i as errorConfigFileNotFound, l as errorDatabaseConnectionRequired, m as errorMigrationPlanningFailed, n as CliErrorEnvelope, o as errorContractConfigMissing, p as errorJsonFormatNotSupported, r as CliStructuredError, s as errorContractMissingExtensionPacks, t as CliErrorConflict, u as errorDriverRequired } from "./control-C16uWwh2.mjs";
1
+ import { _ as errorUnexpected, a as errorConfigValidation, c as errorContractValidationFailed, d as errorFamilyReadMarkerSqlRequired, f as errorFileNotFound, g as errorTargetMigrationNotSupported, h as errorQueryRunnerFactoryRequired, i as errorConfigFileNotFound, l as errorDatabaseConnectionRequired, m as errorMigrationPlanningFailed, n as CliErrorEnvelope, o as errorContractConfigMissing, p as errorJsonFormatNotSupported, r as CliStructuredError, s as errorContractMissingExtensionPacks, t as CliErrorConflict, u as errorDriverRequired } from "./control-M7-bPTyk.mjs";
2
2
  export { type CliErrorConflict, type CliErrorEnvelope, CliStructuredError, errorConfigFileNotFound, errorConfigValidation, errorContractConfigMissing, errorContractMissingExtensionPacks, errorContractValidationFailed, errorDatabaseConnectionRequired, errorDriverRequired, errorFamilyReadMarkerSqlRequired, errorFileNotFound, errorJsonFormatNotSupported, errorMigrationPlanningFailed, errorQueryRunnerFactoryRequired, errorTargetMigrationNotSupported, errorUnexpected };
package/dist/control.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import { a as errorContractMissingExtensionPacks, c as errorDriverRequired, d as errorJsonFormatNotSupported, f as errorMigrationPlanningFailed, h as errorUnexpected, i as errorContractConfigMissing, l as errorFamilyReadMarkerSqlRequired, m as errorTargetMigrationNotSupported, n as errorConfigFileNotFound, o as errorContractValidationFailed, p as errorQueryRunnerFactoryRequired, r as errorConfigValidation, s as errorDatabaseConnectionRequired, t as CliStructuredError, u as errorFileNotFound } from "./control-BHDp3kOD.mjs";
1
+ import { a as errorContractMissingExtensionPacks, c as errorDriverRequired, d as errorJsonFormatNotSupported, f as errorMigrationPlanningFailed, h as errorUnexpected, i as errorContractConfigMissing, l as errorFamilyReadMarkerSqlRequired, m as errorTargetMigrationNotSupported, n as errorConfigFileNotFound, o as errorContractValidationFailed, p as errorQueryRunnerFactoryRequired, r as errorConfigValidation, s as errorDatabaseConnectionRequired, t as CliStructuredError, u as errorFileNotFound } from "./control-CjD1SB2D.mjs";
2
2
 
3
3
  export { CliStructuredError, errorConfigFileNotFound, errorConfigValidation, errorContractConfigMissing, errorContractMissingExtensionPacks, errorContractValidationFailed, errorDatabaseConnectionRequired, errorDriverRequired, errorFamilyReadMarkerSqlRequired, errorFileNotFound, errorJsonFormatNotSupported, errorMigrationPlanningFailed, errorQueryRunnerFactoryRequired, errorTargetMigrationNotSupported, errorUnexpected };
@@ -1,4 +1,4 @@
1
- import { r as CliStructuredError } from "./control-C16uWwh2.mjs";
1
+ import { r as CliStructuredError } from "./control-M7-bPTyk.mjs";
2
2
  import { SchemaIssue, VerifyDatabaseSchemaResult } from "@prisma-next/framework-components/control";
3
3
 
4
4
  //#region src/execution.d.ts
@@ -1,4 +1,4 @@
1
- import { t as CliStructuredError } from "./control-BHDp3kOD.mjs";
1
+ import { t as CliStructuredError } from "./control-CjD1SB2D.mjs";
2
2
  import { ifDefined } from "@prisma-next/utils/defined";
3
3
 
4
4
  //#region src/execution.ts
@@ -1,7 +1,25 @@
1
- import { r as CliStructuredError } from "./control-C16uWwh2.mjs";
1
+ import { r as CliStructuredError } from "./control-M7-bPTyk.mjs";
2
2
 
3
3
  //#region src/migration.d.ts
4
4
 
5
+ /**
6
+ * A scaffolded migration contains a placeholder slot that was never filled in.
7
+ *
8
+ * Thrown at emit time (when `check.source()` or `run()` is invoked) via the
9
+ * `placeholder(...)` utility. The `slot` identifies the exact location the
10
+ * author still needs to edit, e.g. `"backfill-product-status:check.source"`.
11
+ */
12
+ declare function errorUnfilledPlaceholder(slot: string): CliStructuredError;
13
+ /**
14
+ * Scaffolded `migration.ts` files call this wherever the scaffolder couldn't
15
+ * emit a real query and the author is expected to fill one in. Always throws
16
+ * a structured migration error (`PN-MIG-2001`).
17
+ *
18
+ * The return type `never` makes it assignable to any expected return type, so
19
+ * a scaffolded `() => placeholder('...')` satisfies signatures like
20
+ * `() => MongoQueryPlan` without polluting them with a sentinel union arm.
21
+ */
22
+ declare function placeholder(slot: string): never;
5
23
  /**
6
24
  * `migration.ts` was expected at the given package directory but could not be
7
25
  * located. Thrown by `emitMigration` (and, as a belt-and-suspenders, by
@@ -11,16 +29,39 @@ declare function errorMigrationFileMissing(dir: string): CliStructuredError;
11
29
  /**
12
30
  * The `migration.ts` at the given package directory does not default-export a
13
31
  * valid migration shape. Two shapes are accepted: a `Migration` subclass, or a
14
- * factory function returning an object with a `plan()` method. Thrown when the
32
+ * factory function returning a `MigrationPlan`-shaped object (with at least
33
+ * an `operations` array, plus `targetId` and `destination`). Thrown when the
15
34
  * default export is missing, is not a constructor/function, does not extend
16
- * `Migration`, or (for factory functions) returns a value without `plan()`.
35
+ * `Migration`, or (for factory functions) returns a value that is not
36
+ * `MigrationPlan`-shaped.
17
37
  */
18
38
  declare function errorMigrationInvalidDefaultExport(dir: string, actualExportDescription?: string): CliStructuredError;
19
39
  /**
20
- * A class-flow `Migration.plan()` returned a value that is not an array. Used
21
- * by class-flow emit capabilities after instantiating the authored migration.
40
+ * A class-flow `Migration.operations` getter returned a value that is not an
41
+ * array. Used by class-flow emit capabilities after instantiating the
42
+ * authored migration.
22
43
  */
23
44
  declare function errorMigrationPlanNotArray(dir: string, actualValueDescription?: string): CliStructuredError;
45
+ /**
46
+ * A target's migrations capability registers neither `resolveDescriptors`
47
+ * (descriptor flow) nor `emit` (class flow). Surfaced by the strategy
48
+ * selector when it is unable to choose a flow for the target. This is an
49
+ * internal wiring error: every migration-supporting target must implement
50
+ * exactly one of the two flows.
51
+ */
52
+ declare function errorTargetHasIncompleteMigrationCapabilities(options: {
53
+ readonly targetId: string;
54
+ }): CliStructuredError;
55
+ /**
56
+ * A migration plan was asked to render itself back to TypeScript but the
57
+ * target does not support authoring-surface rendering. Thrown by Postgres's
58
+ * descriptor-flow plan when `renderTypeScript()` is invoked (the CLI only
59
+ * calls it in the class-flow branch of `migration plan`, so this acts as a
60
+ * safety rail rather than a user-visible error in normal use).
61
+ */
62
+ declare function errorPlanDoesNotSupportAuthoringSurface(options: {
63
+ readonly targetId: string;
64
+ }): CliStructuredError;
24
65
  //#endregion
25
- export { errorMigrationFileMissing, errorMigrationInvalidDefaultExport, errorMigrationPlanNotArray };
66
+ export { errorMigrationFileMissing, errorMigrationInvalidDefaultExport, errorMigrationPlanNotArray, errorPlanDoesNotSupportAuthoringSurface, errorTargetHasIncompleteMigrationCapabilities, errorUnfilledPlaceholder, placeholder };
26
67
  //# sourceMappingURL=migration.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"migration.d.mts","names":[],"sources":["../src/migration.ts"],"sourcesContent":[],"mappings":";;;;;;AAgBA;AAgBA;AAsBA;iBAtCgB,yBAAA,eAAwC;;;;;;;;iBAgBxC,kCAAA,iDAGb;;;;;iBAmBa,0BAAA,gDAGb"}
1
+ {"version":3,"file":"migration.d.mts","names":[],"sources":["../src/migration.ts"],"sourcesContent":[],"mappings":";;;;;;AAkBA;AAkBA;AASA;AAkBA;AAuBA;AAyBgB,iBA7FA,wBAAA,CA6FA,IAA6C,EAAA,MAAA,CAAA,EA7FL,kBA+FpD;AAgBJ;;;;;;;;;iBA7FgB,WAAA;;;;;;iBASA,yBAAA,eAAwC;;;;;;;;;;iBAkBxC,kCAAA,iDAGb;;;;;;iBAoBa,0BAAA,gDAGb;;;;;;;;iBAsBa,6CAAA;;IAEZ;;;;;;;;iBAgBY,uCAAA;;IAEZ"}
@@ -1,7 +1,34 @@
1
- import { t as CliStructuredError } from "./control-BHDp3kOD.mjs";
1
+ import { t as CliStructuredError } from "./control-CjD1SB2D.mjs";
2
2
 
3
3
  //#region src/migration.ts
4
4
  /**
5
+ * A scaffolded migration contains a placeholder slot that was never filled in.
6
+ *
7
+ * Thrown at emit time (when `check.source()` or `run()` is invoked) via the
8
+ * `placeholder(...)` utility. The `slot` identifies the exact location the
9
+ * author still needs to edit, e.g. `"backfill-product-status:check.source"`.
10
+ */
11
+ function errorUnfilledPlaceholder(slot) {
12
+ return new CliStructuredError("2001", "Unfilled migration placeholder", {
13
+ domain: "MIG",
14
+ why: `The migration contains a placeholder that has not been filled in: ${slot}`,
15
+ fix: "Open migration.ts and replace the `placeholder(...)` call with your actual query.",
16
+ meta: { slot }
17
+ });
18
+ }
19
+ /**
20
+ * Scaffolded `migration.ts` files call this wherever the scaffolder couldn't
21
+ * emit a real query and the author is expected to fill one in. Always throws
22
+ * a structured migration error (`PN-MIG-2001`).
23
+ *
24
+ * The return type `never` makes it assignable to any expected return type, so
25
+ * a scaffolded `() => placeholder('...')` satisfies signatures like
26
+ * `() => MongoQueryPlan` without polluting them with a sentinel union arm.
27
+ */
28
+ function placeholder(slot) {
29
+ throw errorUnfilledPlaceholder(slot);
30
+ }
31
+ /**
5
32
  * `migration.ts` was expected at the given package directory but could not be
6
33
  * located. Thrown by `emitMigration` (and, as a belt-and-suspenders, by
7
34
  * class-flow `emit` capabilities) when the file is missing.
@@ -17,15 +44,17 @@ function errorMigrationFileMissing(dir) {
17
44
  /**
18
45
  * The `migration.ts` at the given package directory does not default-export a
19
46
  * valid migration shape. Two shapes are accepted: a `Migration` subclass, or a
20
- * factory function returning an object with a `plan()` method. Thrown when the
47
+ * factory function returning a `MigrationPlan`-shaped object (with at least
48
+ * an `operations` array, plus `targetId` and `destination`). Thrown when the
21
49
  * default export is missing, is not a constructor/function, does not extend
22
- * `Migration`, or (for factory functions) returns a value without `plan()`.
50
+ * `Migration`, or (for factory functions) returns a value that is not
51
+ * `MigrationPlan`-shaped.
23
52
  */
24
53
  function errorMigrationInvalidDefaultExport(dir, actualExportDescription) {
25
54
  return new CliStructuredError("2003", "migration.ts default export is not a valid migration", {
26
55
  domain: "MIG",
27
- why: actualExportDescription !== void 0 ? `migration.ts at "${dir}" must default-export a Migration subclass or a factory function returning { plan() }; got ${actualExportDescription}` : `migration.ts at "${dir}" must default-export a Migration subclass or a factory function returning { plan() }.`,
28
- fix: "Use `export default class extends Migration { ... }` or `export default () => ({ plan() { return [...] } })`.",
56
+ why: actualExportDescription !== void 0 ? `migration.ts at "${dir}" must default-export a Migration subclass or a factory function returning a MigrationPlan-shaped object; got ${actualExportDescription}` : `migration.ts at "${dir}" must default-export a Migration subclass or a factory function returning a MigrationPlan-shaped object.`,
57
+ fix: "Use `export default class extends Migration { ... }` or `export default () => ({ targetId, destination, operations })`.",
29
58
  meta: {
30
59
  dir,
31
60
  ...actualExportDescription !== void 0 ? { actualExport: actualExportDescription } : {}
@@ -33,21 +62,52 @@ function errorMigrationInvalidDefaultExport(dir, actualExportDescription) {
33
62
  });
34
63
  }
35
64
  /**
36
- * A class-flow `Migration.plan()` returned a value that is not an array. Used
37
- * by class-flow emit capabilities after instantiating the authored migration.
65
+ * A class-flow `Migration.operations` getter returned a value that is not an
66
+ * array. Used by class-flow emit capabilities after instantiating the
67
+ * authored migration.
38
68
  */
39
69
  function errorMigrationPlanNotArray(dir, actualValueDescription) {
40
- return new CliStructuredError("2004", "Migration.plan() must return an array of operations", {
70
+ return new CliStructuredError("2004", "Migration.operations must be an array of operations", {
41
71
  domain: "MIG",
42
- why: actualValueDescription !== void 0 ? `Migration.plan() for migration.ts at "${dir}" returned ${actualValueDescription}; an array of operations is required.` : `Migration.plan() for migration.ts at "${dir}" did not return an array of operations.`,
43
- fix: "Ensure your `plan()` method returns an array of operations; see the data-migrations authoring guide.",
72
+ why: actualValueDescription !== void 0 ? `Migration.operations for migration.ts at "${dir}" was ${actualValueDescription}; an array of operations is required.` : `Migration.operations for migration.ts at "${dir}" is not an array of operations.`,
73
+ fix: "Ensure your `operations` getter returns an array of operations; see the data-migrations authoring guide.",
44
74
  meta: {
45
75
  dir,
46
76
  ...actualValueDescription !== void 0 ? { actualValue: actualValueDescription } : {}
47
77
  }
48
78
  });
49
79
  }
80
+ /**
81
+ * A target's migrations capability registers neither `resolveDescriptors`
82
+ * (descriptor flow) nor `emit` (class flow). Surfaced by the strategy
83
+ * selector when it is unable to choose a flow for the target. This is an
84
+ * internal wiring error: every migration-supporting target must implement
85
+ * exactly one of the two flows.
86
+ */
87
+ function errorTargetHasIncompleteMigrationCapabilities(options) {
88
+ return new CliStructuredError("2011", "Target migrations capability is incomplete", {
89
+ domain: "MIG",
90
+ why: `Target "${options.targetId}" registers a migrations capability but implements neither \`resolveDescriptors\` (descriptor flow) nor \`emit\` (class flow); the CLI cannot choose an authoring strategy.`,
91
+ fix: "This is an internal wiring error. Report it — the target descriptor must implement exactly one of the two migration flows.",
92
+ meta: { targetId: options.targetId }
93
+ });
94
+ }
95
+ /**
96
+ * A migration plan was asked to render itself back to TypeScript but the
97
+ * target does not support authoring-surface rendering. Thrown by Postgres's
98
+ * descriptor-flow plan when `renderTypeScript()` is invoked (the CLI only
99
+ * calls it in the class-flow branch of `migration plan`, so this acts as a
100
+ * safety rail rather than a user-visible error in normal use).
101
+ */
102
+ function errorPlanDoesNotSupportAuthoringSurface(options) {
103
+ return new CliStructuredError("2010", "Migration plan does not support TypeScript authoring surface", {
104
+ domain: "MIG",
105
+ why: `Target "${options.targetId}" produced a descriptor-flow plan; descriptor-flow plans cannot be rendered back to TypeScript via renderTypeScript().`,
106
+ fix: "This is an internal wiring error. Report it — the CLI should route descriptor-flow targets through renderDescriptorTypeScript, not renderTypeScript.",
107
+ meta: { targetId: options.targetId }
108
+ });
109
+ }
50
110
 
51
111
  //#endregion
52
- export { errorMigrationFileMissing, errorMigrationInvalidDefaultExport, errorMigrationPlanNotArray };
112
+ export { errorMigrationFileMissing, errorMigrationInvalidDefaultExport, errorMigrationPlanNotArray, errorPlanDoesNotSupportAuthoringSurface, errorTargetHasIncompleteMigrationCapabilities, errorUnfilledPlaceholder, placeholder };
53
113
  //# sourceMappingURL=migration.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"migration.mjs","names":[],"sources":["../src/migration.ts"],"sourcesContent":["import { CliStructuredError } from './control';\n\n// ============================================================================\n// Migration Errors (PN-MIG-2000-2999)\n//\n// Errors raised by the migration subsystem (authoring, planning, emit).\n// Domain `MIG` distinguishes these from generic application runtime errors\n// (`RUN`) and from CLI argument/config errors (`CLI`). See\n// `docs/CLI Style Guide.md` for the canonical domain taxonomy.\n// ============================================================================\n\n/**\n * `migration.ts` was expected at the given package directory but could not be\n * located. Thrown by `emitMigration` (and, as a belt-and-suspenders, by\n * class-flow `emit` capabilities) when the file is missing.\n */\nexport function errorMigrationFileMissing(dir: string): CliStructuredError {\n return new CliStructuredError('2002', 'migration.ts not found', {\n domain: 'MIG',\n why: `No migration.ts file was found at \"${dir}\"`,\n fix: 'Scaffold one with `prisma-next migration new` or `prisma-next migration plan`.',\n meta: { dir },\n });\n}\n\n/**\n * The `migration.ts` at the given package directory does not default-export a\n * valid migration shape. Two shapes are accepted: a `Migration` subclass, or a\n * factory function returning an object with a `plan()` method. Thrown when the\n * default export is missing, is not a constructor/function, does not extend\n * `Migration`, or (for factory functions) returns a value without `plan()`.\n */\nexport function errorMigrationInvalidDefaultExport(\n dir: string,\n actualExportDescription?: string,\n): CliStructuredError {\n return new CliStructuredError('2003', 'migration.ts default export is not a valid migration', {\n domain: 'MIG',\n why:\n actualExportDescription !== undefined\n ? `migration.ts at \"${dir}\" must default-export a Migration subclass or a factory function returning { plan() }; got ${actualExportDescription}`\n : `migration.ts at \"${dir}\" must default-export a Migration subclass or a factory function returning { plan() }.`,\n fix: 'Use `export default class extends Migration { ... }` or `export default () => ({ plan() { return [...] } })`.',\n meta: {\n dir,\n ...(actualExportDescription !== undefined ? { actualExport: actualExportDescription } : {}),\n },\n });\n}\n\n/**\n * A class-flow `Migration.plan()` returned a value that is not an array. Used\n * by class-flow emit capabilities after instantiating the authored migration.\n */\nexport function errorMigrationPlanNotArray(\n dir: string,\n actualValueDescription?: string,\n): CliStructuredError {\n return new CliStructuredError('2004', 'Migration.plan() must return an array of operations', {\n domain: 'MIG',\n why:\n actualValueDescription !== undefined\n ? `Migration.plan() for migration.ts at \"${dir}\" returned ${actualValueDescription}; an array of operations is required.`\n : `Migration.plan() for migration.ts at \"${dir}\" did not return an array of operations.`,\n fix: 'Ensure your `plan()` method returns an array of operations; see the data-migrations authoring guide.',\n meta: {\n dir,\n ...(actualValueDescription !== undefined ? { actualValue: actualValueDescription } : {}),\n },\n });\n}\n"],"mappings":";;;;;;;;AAgBA,SAAgB,0BAA0B,KAAiC;AACzE,QAAO,IAAI,mBAAmB,QAAQ,0BAA0B;EAC9D,QAAQ;EACR,KAAK,sCAAsC,IAAI;EAC/C,KAAK;EACL,MAAM,EAAE,KAAK;EACd,CAAC;;;;;;;;;AAUJ,SAAgB,mCACd,KACA,yBACoB;AACpB,QAAO,IAAI,mBAAmB,QAAQ,wDAAwD;EAC5F,QAAQ;EACR,KACE,4BAA4B,SACxB,oBAAoB,IAAI,6FAA6F,4BACrH,oBAAoB,IAAI;EAC9B,KAAK;EACL,MAAM;GACJ;GACA,GAAI,4BAA4B,SAAY,EAAE,cAAc,yBAAyB,GAAG,EAAE;GAC3F;EACF,CAAC;;;;;;AAOJ,SAAgB,2BACd,KACA,wBACoB;AACpB,QAAO,IAAI,mBAAmB,QAAQ,uDAAuD;EAC3F,QAAQ;EACR,KACE,2BAA2B,SACvB,yCAAyC,IAAI,aAAa,uBAAuB,yCACjF,yCAAyC,IAAI;EACnD,KAAK;EACL,MAAM;GACJ;GACA,GAAI,2BAA2B,SAAY,EAAE,aAAa,wBAAwB,GAAG,EAAE;GACxF;EACF,CAAC"}
1
+ {"version":3,"file":"migration.mjs","names":[],"sources":["../src/migration.ts"],"sourcesContent":["import { CliStructuredError } from './control';\n\n// ============================================================================\n// Migration Errors (PN-MIG-2000-2999)\n//\n// Errors raised by the migration subsystem (authoring, planning, emit).\n// Domain `MIG` distinguishes these from generic application runtime errors\n// (`RUN`) and from CLI argument/config errors (`CLI`). See\n// `docs/CLI Style Guide.md` for the canonical domain taxonomy.\n// ============================================================================\n\n/**\n * A scaffolded migration contains a placeholder slot that was never filled in.\n *\n * Thrown at emit time (when `check.source()` or `run()` is invoked) via the\n * `placeholder(...)` utility. The `slot` identifies the exact location the\n * author still needs to edit, e.g. `\"backfill-product-status:check.source\"`.\n */\nexport function errorUnfilledPlaceholder(slot: string): CliStructuredError {\n return new CliStructuredError('2001', 'Unfilled migration placeholder', {\n domain: 'MIG',\n why: `The migration contains a placeholder that has not been filled in: ${slot}`,\n fix: 'Open migration.ts and replace the `placeholder(...)` call with your actual query.',\n meta: { slot },\n });\n}\n\n/**\n * Scaffolded `migration.ts` files call this wherever the scaffolder couldn't\n * emit a real query and the author is expected to fill one in. Always throws\n * a structured migration error (`PN-MIG-2001`).\n *\n * The return type `never` makes it assignable to any expected return type, so\n * a scaffolded `() => placeholder('...')` satisfies signatures like\n * `() => MongoQueryPlan` without polluting them with a sentinel union arm.\n */\nexport function placeholder(slot: string): never {\n throw errorUnfilledPlaceholder(slot);\n}\n\n/**\n * `migration.ts` was expected at the given package directory but could not be\n * located. Thrown by `emitMigration` (and, as a belt-and-suspenders, by\n * class-flow `emit` capabilities) when the file is missing.\n */\nexport function errorMigrationFileMissing(dir: string): CliStructuredError {\n return new CliStructuredError('2002', 'migration.ts not found', {\n domain: 'MIG',\n why: `No migration.ts file was found at \"${dir}\"`,\n fix: 'Scaffold one with `prisma-next migration new` or `prisma-next migration plan`.',\n meta: { dir },\n });\n}\n\n/**\n * The `migration.ts` at the given package directory does not default-export a\n * valid migration shape. Two shapes are accepted: a `Migration` subclass, or a\n * factory function returning a `MigrationPlan`-shaped object (with at least\n * an `operations` array, plus `targetId` and `destination`). Thrown when the\n * default export is missing, is not a constructor/function, does not extend\n * `Migration`, or (for factory functions) returns a value that is not\n * `MigrationPlan`-shaped.\n */\nexport function errorMigrationInvalidDefaultExport(\n dir: string,\n actualExportDescription?: string,\n): CliStructuredError {\n return new CliStructuredError('2003', 'migration.ts default export is not a valid migration', {\n domain: 'MIG',\n why:\n actualExportDescription !== undefined\n ? `migration.ts at \"${dir}\" must default-export a Migration subclass or a factory function returning a MigrationPlan-shaped object; got ${actualExportDescription}`\n : `migration.ts at \"${dir}\" must default-export a Migration subclass or a factory function returning a MigrationPlan-shaped object.`,\n fix: 'Use `export default class extends Migration { ... }` or `export default () => ({ targetId, destination, operations })`.',\n meta: {\n dir,\n ...(actualExportDescription !== undefined ? { actualExport: actualExportDescription } : {}),\n },\n });\n}\n\n/**\n * A class-flow `Migration.operations` getter returned a value that is not an\n * array. Used by class-flow emit capabilities after instantiating the\n * authored migration.\n */\nexport function errorMigrationPlanNotArray(\n dir: string,\n actualValueDescription?: string,\n): CliStructuredError {\n return new CliStructuredError('2004', 'Migration.operations must be an array of operations', {\n domain: 'MIG',\n why:\n actualValueDescription !== undefined\n ? `Migration.operations for migration.ts at \"${dir}\" was ${actualValueDescription}; an array of operations is required.`\n : `Migration.operations for migration.ts at \"${dir}\" is not an array of operations.`,\n fix: 'Ensure your `operations` getter returns an array of operations; see the data-migrations authoring guide.',\n meta: {\n dir,\n ...(actualValueDescription !== undefined ? { actualValue: actualValueDescription } : {}),\n },\n });\n}\n\n/**\n * A target's migrations capability registers neither `resolveDescriptors`\n * (descriptor flow) nor `emit` (class flow). Surfaced by the strategy\n * selector when it is unable to choose a flow for the target. This is an\n * internal wiring error: every migration-supporting target must implement\n * exactly one of the two flows.\n */\nexport function errorTargetHasIncompleteMigrationCapabilities(options: {\n readonly targetId: string;\n}): CliStructuredError {\n return new CliStructuredError('2011', 'Target migrations capability is incomplete', {\n domain: 'MIG',\n why: `Target \"${options.targetId}\" registers a migrations capability but implements neither \\`resolveDescriptors\\` (descriptor flow) nor \\`emit\\` (class flow); the CLI cannot choose an authoring strategy.`,\n fix: 'This is an internal wiring error. Report it — the target descriptor must implement exactly one of the two migration flows.',\n meta: { targetId: options.targetId },\n });\n}\n\n/**\n * A migration plan was asked to render itself back to TypeScript but the\n * target does not support authoring-surface rendering. Thrown by Postgres's\n * descriptor-flow plan when `renderTypeScript()` is invoked (the CLI only\n * calls it in the class-flow branch of `migration plan`, so this acts as a\n * safety rail rather than a user-visible error in normal use).\n */\nexport function errorPlanDoesNotSupportAuthoringSurface(options: {\n readonly targetId: string;\n}): CliStructuredError {\n return new CliStructuredError(\n '2010',\n 'Migration plan does not support TypeScript authoring surface',\n {\n domain: 'MIG',\n why: `Target \"${options.targetId}\" produced a descriptor-flow plan; descriptor-flow plans cannot be rendered back to TypeScript via renderTypeScript().`,\n fix: 'This is an internal wiring error. Report it — the CLI should route descriptor-flow targets through renderDescriptorTypeScript, not renderTypeScript.',\n meta: { targetId: options.targetId },\n },\n );\n}\n"],"mappings":";;;;;;;;;;AAkBA,SAAgB,yBAAyB,MAAkC;AACzE,QAAO,IAAI,mBAAmB,QAAQ,kCAAkC;EACtE,QAAQ;EACR,KAAK,qEAAqE;EAC1E,KAAK;EACL,MAAM,EAAE,MAAM;EACf,CAAC;;;;;;;;;;;AAYJ,SAAgB,YAAY,MAAqB;AAC/C,OAAM,yBAAyB,KAAK;;;;;;;AAQtC,SAAgB,0BAA0B,KAAiC;AACzE,QAAO,IAAI,mBAAmB,QAAQ,0BAA0B;EAC9D,QAAQ;EACR,KAAK,sCAAsC,IAAI;EAC/C,KAAK;EACL,MAAM,EAAE,KAAK;EACd,CAAC;;;;;;;;;;;AAYJ,SAAgB,mCACd,KACA,yBACoB;AACpB,QAAO,IAAI,mBAAmB,QAAQ,wDAAwD;EAC5F,QAAQ;EACR,KACE,4BAA4B,SACxB,oBAAoB,IAAI,gHAAgH,4BACxI,oBAAoB,IAAI;EAC9B,KAAK;EACL,MAAM;GACJ;GACA,GAAI,4BAA4B,SAAY,EAAE,cAAc,yBAAyB,GAAG,EAAE;GAC3F;EACF,CAAC;;;;;;;AAQJ,SAAgB,2BACd,KACA,wBACoB;AACpB,QAAO,IAAI,mBAAmB,QAAQ,uDAAuD;EAC3F,QAAQ;EACR,KACE,2BAA2B,SACvB,6CAA6C,IAAI,QAAQ,uBAAuB,yCAChF,6CAA6C,IAAI;EACvD,KAAK;EACL,MAAM;GACJ;GACA,GAAI,2BAA2B,SAAY,EAAE,aAAa,wBAAwB,GAAG,EAAE;GACxF;EACF,CAAC;;;;;;;;;AAUJ,SAAgB,8CAA8C,SAEvC;AACrB,QAAO,IAAI,mBAAmB,QAAQ,8CAA8C;EAClF,QAAQ;EACR,KAAK,WAAW,QAAQ,SAAS;EACjC,KAAK;EACL,MAAM,EAAE,UAAU,QAAQ,UAAU;EACrC,CAAC;;;;;;;;;AAUJ,SAAgB,wCAAwC,SAEjC;AACrB,QAAO,IAAI,mBACT,QACA,gEACA;EACE,QAAQ;EACR,KAAK,WAAW,QAAQ,SAAS;EACjC,KAAK;EACL,MAAM,EAAE,UAAU,QAAQ,UAAU;EACrC,CACF"}
package/package.json CHANGED
@@ -1,19 +1,19 @@
1
1
  {
2
2
  "name": "@prisma-next/errors",
3
- "version": "0.4.0-dev.6",
3
+ "version": "0.4.0-dev.8",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "description": "Structured error types for Prisma Next control and execution planes",
7
7
  "dependencies": {
8
- "@prisma-next/utils": "0.4.0-dev.6",
9
- "@prisma-next/framework-components": "0.4.0-dev.6"
8
+ "@prisma-next/utils": "0.4.0-dev.8",
9
+ "@prisma-next/framework-components": "0.4.0-dev.8"
10
10
  },
11
11
  "devDependencies": {
12
12
  "tsdown": "0.18.4",
13
13
  "typescript": "5.9.3",
14
14
  "vitest": "4.0.17",
15
- "@prisma-next/tsconfig": "0.0.0",
16
- "@prisma-next/tsdown": "0.0.0"
15
+ "@prisma-next/tsdown": "0.0.0",
16
+ "@prisma-next/tsconfig": "0.0.0"
17
17
  },
18
18
  "files": [
19
19
  "dist",
package/src/control.ts CHANGED
@@ -29,13 +29,33 @@ export interface CliErrorConflict {
29
29
  readonly why?: string;
30
30
  }
31
31
 
32
+ /**
33
+ * Domain prefix for structured CLI error codes.
34
+ *
35
+ * The full envelope code is rendered as `PN-<domain>-<code>` (see
36
+ * `CliStructuredError.toEnvelope`). The supported domains follow the
37
+ * taxonomy documented in `docs/CLI Style Guide.md`:
38
+ *
39
+ * - `CLI` — CLI command processing (config, validation, planning)
40
+ * - `MIG` — Migration subsystem (authoring, planning conflicts, runner)
41
+ * - `RUN` — Application runtime (query execution, streaming)
42
+ * - `CON` — Contract subsystem (validation, normalization)
43
+ * - `SCHEMA` — Schema subsystem
44
+ *
45
+ * Sub-clustering within a domain is conveyed by the numeric code range; see
46
+ * the per-domain source files for reserved ranges.
47
+ */
48
+ const CLI_ERROR_DOMAINS = ['CLI', 'RUN', 'MIG', 'CON', 'SCHEMA'] as const;
49
+
50
+ export type CliErrorDomain = (typeof CLI_ERROR_DOMAINS)[number];
51
+
32
52
  /**
33
53
  * Structured CLI error that contains all information needed for error envelopes.
34
54
  * Call sites throw these errors with full context.
35
55
  */
36
56
  export class CliStructuredError extends Error {
37
57
  readonly code: string;
38
- readonly domain: 'CLI' | 'RUN' | 'MIG';
58
+ readonly domain: CliErrorDomain;
39
59
  readonly severity: 'error' | 'warn' | 'info';
40
60
  readonly why: string | undefined;
41
61
  readonly fix: string | undefined;
@@ -52,7 +72,7 @@ export class CliStructuredError extends Error {
52
72
  code: string,
53
73
  summary: string,
54
74
  options?: {
55
- readonly domain?: 'CLI' | 'RUN' | 'MIG';
75
+ readonly domain?: CliErrorDomain;
56
76
  readonly severity?: 'error' | 'warn' | 'info';
57
77
  readonly why?: string;
58
78
  readonly fix?: string;
@@ -82,11 +102,9 @@ export class CliStructuredError extends Error {
82
102
  * Converts this error to a CLI error envelope for output formatting.
83
103
  */
84
104
  toEnvelope(): CliErrorEnvelope {
85
- const domainPrefixes = { CLI: 'PN-CLI-', RUN: 'PN-RUN-', MIG: 'PN-MIG-' } as const;
86
- const codePrefix = domainPrefixes[this.domain];
87
105
  return {
88
106
  ok: false as const,
89
- code: `${codePrefix}${this.code}`,
107
+ code: `PN-${this.domain}-${this.code}`,
90
108
  domain: this.domain,
91
109
  severity: this.severity,
92
110
  summary: this.message,
@@ -110,12 +128,18 @@ export class CliStructuredError extends Error {
110
128
  return (
111
129
  candidate.name === 'CliStructuredError' &&
112
130
  typeof candidate.code === 'string' &&
113
- (candidate.domain === 'CLI' || candidate.domain === 'RUN' || candidate.domain === 'MIG') &&
131
+ isCliErrorDomain(candidate.domain) &&
114
132
  typeof candidate.toEnvelope === 'function'
115
133
  );
116
134
  }
117
135
  }
118
136
 
137
+ const CLI_ERROR_DOMAIN_SET: ReadonlySet<CliErrorDomain> = new Set(CLI_ERROR_DOMAINS);
138
+
139
+ function isCliErrorDomain(value: unknown): value is CliErrorDomain {
140
+ return typeof value === 'string' && CLI_ERROR_DOMAIN_SET.has(value as CliErrorDomain);
141
+ }
142
+
119
143
  // ============================================================================
120
144
  // Config Errors (PN-CLI-4001-4007)
121
145
  // ============================================================================
@@ -2,4 +2,8 @@ export {
2
2
  errorMigrationFileMissing,
3
3
  errorMigrationInvalidDefaultExport,
4
4
  errorMigrationPlanNotArray,
5
+ errorPlanDoesNotSupportAuthoringSurface,
6
+ errorTargetHasIncompleteMigrationCapabilities,
7
+ errorUnfilledPlaceholder,
8
+ placeholder,
5
9
  } from '../migration';
package/src/migration.ts CHANGED
@@ -9,6 +9,35 @@ import { CliStructuredError } from './control';
9
9
  // `docs/CLI Style Guide.md` for the canonical domain taxonomy.
10
10
  // ============================================================================
11
11
 
12
+ /**
13
+ * A scaffolded migration contains a placeholder slot that was never filled in.
14
+ *
15
+ * Thrown at emit time (when `check.source()` or `run()` is invoked) via the
16
+ * `placeholder(...)` utility. The `slot` identifies the exact location the
17
+ * author still needs to edit, e.g. `"backfill-product-status:check.source"`.
18
+ */
19
+ export function errorUnfilledPlaceholder(slot: string): CliStructuredError {
20
+ return new CliStructuredError('2001', 'Unfilled migration placeholder', {
21
+ domain: 'MIG',
22
+ why: `The migration contains a placeholder that has not been filled in: ${slot}`,
23
+ fix: 'Open migration.ts and replace the `placeholder(...)` call with your actual query.',
24
+ meta: { slot },
25
+ });
26
+ }
27
+
28
+ /**
29
+ * Scaffolded `migration.ts` files call this wherever the scaffolder couldn't
30
+ * emit a real query and the author is expected to fill one in. Always throws
31
+ * a structured migration error (`PN-MIG-2001`).
32
+ *
33
+ * The return type `never` makes it assignable to any expected return type, so
34
+ * a scaffolded `() => placeholder('...')` satisfies signatures like
35
+ * `() => MongoQueryPlan` without polluting them with a sentinel union arm.
36
+ */
37
+ export function placeholder(slot: string): never {
38
+ throw errorUnfilledPlaceholder(slot);
39
+ }
40
+
12
41
  /**
13
42
  * `migration.ts` was expected at the given package directory but could not be
14
43
  * located. Thrown by `emitMigration` (and, as a belt-and-suspenders, by
@@ -26,9 +55,11 @@ export function errorMigrationFileMissing(dir: string): CliStructuredError {
26
55
  /**
27
56
  * The `migration.ts` at the given package directory does not default-export a
28
57
  * valid migration shape. Two shapes are accepted: a `Migration` subclass, or a
29
- * factory function returning an object with a `plan()` method. Thrown when the
58
+ * factory function returning a `MigrationPlan`-shaped object (with at least
59
+ * an `operations` array, plus `targetId` and `destination`). Thrown when the
30
60
  * default export is missing, is not a constructor/function, does not extend
31
- * `Migration`, or (for factory functions) returns a value without `plan()`.
61
+ * `Migration`, or (for factory functions) returns a value that is not
62
+ * `MigrationPlan`-shaped.
32
63
  */
33
64
  export function errorMigrationInvalidDefaultExport(
34
65
  dir: string,
@@ -38,9 +69,9 @@ export function errorMigrationInvalidDefaultExport(
38
69
  domain: 'MIG',
39
70
  why:
40
71
  actualExportDescription !== undefined
41
- ? `migration.ts at "${dir}" must default-export a Migration subclass or a factory function returning { plan() }; got ${actualExportDescription}`
42
- : `migration.ts at "${dir}" must default-export a Migration subclass or a factory function returning { plan() }.`,
43
- fix: 'Use `export default class extends Migration { ... }` or `export default () => ({ plan() { return [...] } })`.',
72
+ ? `migration.ts at "${dir}" must default-export a Migration subclass or a factory function returning a MigrationPlan-shaped object; got ${actualExportDescription}`
73
+ : `migration.ts at "${dir}" must default-export a Migration subclass or a factory function returning a MigrationPlan-shaped object.`,
74
+ fix: 'Use `export default class extends Migration { ... }` or `export default () => ({ targetId, destination, operations })`.',
44
75
  meta: {
45
76
  dir,
46
77
  ...(actualExportDescription !== undefined ? { actualExport: actualExportDescription } : {}),
@@ -49,23 +80,64 @@ export function errorMigrationInvalidDefaultExport(
49
80
  }
50
81
 
51
82
  /**
52
- * A class-flow `Migration.plan()` returned a value that is not an array. Used
53
- * by class-flow emit capabilities after instantiating the authored migration.
83
+ * A class-flow `Migration.operations` getter returned a value that is not an
84
+ * array. Used by class-flow emit capabilities after instantiating the
85
+ * authored migration.
54
86
  */
55
87
  export function errorMigrationPlanNotArray(
56
88
  dir: string,
57
89
  actualValueDescription?: string,
58
90
  ): CliStructuredError {
59
- return new CliStructuredError('2004', 'Migration.plan() must return an array of operations', {
91
+ return new CliStructuredError('2004', 'Migration.operations must be an array of operations', {
60
92
  domain: 'MIG',
61
93
  why:
62
94
  actualValueDescription !== undefined
63
- ? `Migration.plan() for migration.ts at "${dir}" returned ${actualValueDescription}; an array of operations is required.`
64
- : `Migration.plan() for migration.ts at "${dir}" did not return an array of operations.`,
65
- fix: 'Ensure your `plan()` method returns an array of operations; see the data-migrations authoring guide.',
95
+ ? `Migration.operations for migration.ts at "${dir}" was ${actualValueDescription}; an array of operations is required.`
96
+ : `Migration.operations for migration.ts at "${dir}" is not an array of operations.`,
97
+ fix: 'Ensure your `operations` getter returns an array of operations; see the data-migrations authoring guide.',
66
98
  meta: {
67
99
  dir,
68
100
  ...(actualValueDescription !== undefined ? { actualValue: actualValueDescription } : {}),
69
101
  },
70
102
  });
71
103
  }
104
+
105
+ /**
106
+ * A target's migrations capability registers neither `resolveDescriptors`
107
+ * (descriptor flow) nor `emit` (class flow). Surfaced by the strategy
108
+ * selector when it is unable to choose a flow for the target. This is an
109
+ * internal wiring error: every migration-supporting target must implement
110
+ * exactly one of the two flows.
111
+ */
112
+ export function errorTargetHasIncompleteMigrationCapabilities(options: {
113
+ readonly targetId: string;
114
+ }): CliStructuredError {
115
+ return new CliStructuredError('2011', 'Target migrations capability is incomplete', {
116
+ domain: 'MIG',
117
+ why: `Target "${options.targetId}" registers a migrations capability but implements neither \`resolveDescriptors\` (descriptor flow) nor \`emit\` (class flow); the CLI cannot choose an authoring strategy.`,
118
+ fix: 'This is an internal wiring error. Report it — the target descriptor must implement exactly one of the two migration flows.',
119
+ meta: { targetId: options.targetId },
120
+ });
121
+ }
122
+
123
+ /**
124
+ * A migration plan was asked to render itself back to TypeScript but the
125
+ * target does not support authoring-surface rendering. Thrown by Postgres's
126
+ * descriptor-flow plan when `renderTypeScript()` is invoked (the CLI only
127
+ * calls it in the class-flow branch of `migration plan`, so this acts as a
128
+ * safety rail rather than a user-visible error in normal use).
129
+ */
130
+ export function errorPlanDoesNotSupportAuthoringSurface(options: {
131
+ readonly targetId: string;
132
+ }): CliStructuredError {
133
+ return new CliStructuredError(
134
+ '2010',
135
+ 'Migration plan does not support TypeScript authoring surface',
136
+ {
137
+ domain: 'MIG',
138
+ why: `Target "${options.targetId}" produced a descriptor-flow plan; descriptor-flow plans cannot be rendered back to TypeScript via renderTypeScript().`,
139
+ fix: 'This is an internal wiring error. Report it — the CLI should route descriptor-flow targets through renderDescriptorTypeScript, not renderTypeScript.',
140
+ meta: { targetId: options.targetId },
141
+ },
142
+ );
143
+ }
@@ -1 +0,0 @@
1
- {"version":3,"file":"control-BHDp3kOD.mjs","names":[],"sources":["../src/control.ts"],"sourcesContent":["/**\n * CLI error envelope for output formatting.\n * This is the serialized form of a CliStructuredError.\n */\nexport interface CliErrorEnvelope {\n readonly ok: false;\n readonly code: string;\n readonly domain: string;\n readonly severity: 'error' | 'warn' | 'info';\n readonly summary: string;\n readonly why: string | undefined;\n readonly fix: string | undefined;\n readonly where:\n | {\n readonly path: string | undefined;\n readonly line: number | undefined;\n }\n | undefined;\n readonly meta: Record<string, unknown> | undefined;\n readonly docsUrl: string | undefined;\n}\n\n/**\n * Minimal conflict data structure expected by CLI output.\n */\nexport interface CliErrorConflict {\n readonly kind: string;\n readonly summary: string;\n readonly why?: string;\n}\n\n/**\n * Structured CLI error that contains all information needed for error envelopes.\n * Call sites throw these errors with full context.\n */\nexport class CliStructuredError extends Error {\n readonly code: string;\n readonly domain: 'CLI' | 'RUN' | 'MIG';\n readonly severity: 'error' | 'warn' | 'info';\n readonly why: string | undefined;\n readonly fix: string | undefined;\n readonly where:\n | {\n readonly path: string | undefined;\n readonly line: number | undefined;\n }\n | undefined;\n readonly meta: Record<string, unknown> | undefined;\n readonly docsUrl: string | undefined;\n\n constructor(\n code: string,\n summary: string,\n options?: {\n readonly domain?: 'CLI' | 'RUN' | 'MIG';\n readonly severity?: 'error' | 'warn' | 'info';\n readonly why?: string;\n readonly fix?: string;\n readonly where?: { readonly path?: string; readonly line?: number };\n readonly meta?: Record<string, unknown>;\n readonly docsUrl?: string;\n },\n ) {\n super(summary);\n this.name = 'CliStructuredError';\n this.code = code;\n this.domain = options?.domain ?? 'CLI';\n this.severity = options?.severity ?? 'error';\n this.why = options?.why;\n this.fix = options?.fix === options?.why ? undefined : options?.fix;\n this.where = options?.where\n ? {\n path: options.where.path,\n line: options.where.line,\n }\n : undefined;\n this.meta = options?.meta;\n this.docsUrl = options?.docsUrl;\n }\n\n /**\n * Converts this error to a CLI error envelope for output formatting.\n */\n toEnvelope(): CliErrorEnvelope {\n const domainPrefixes = { CLI: 'PN-CLI-', RUN: 'PN-RUN-', MIG: 'PN-MIG-' } as const;\n const codePrefix = domainPrefixes[this.domain];\n return {\n ok: false as const,\n code: `${codePrefix}${this.code}`,\n domain: this.domain,\n severity: this.severity,\n summary: this.message,\n why: this.why,\n fix: this.fix,\n where: this.where,\n meta: this.meta,\n docsUrl: this.docsUrl,\n };\n }\n\n /**\n * Type guard to check if an error is a CliStructuredError.\n * Uses duck-typing to work across module boundaries where instanceof may fail.\n */\n static is(error: unknown): error is CliStructuredError {\n if (!(error instanceof Error)) {\n return false;\n }\n const candidate = error as CliStructuredError;\n return (\n candidate.name === 'CliStructuredError' &&\n typeof candidate.code === 'string' &&\n (candidate.domain === 'CLI' || candidate.domain === 'RUN' || candidate.domain === 'MIG') &&\n typeof candidate.toEnvelope === 'function'\n );\n }\n}\n\n// ============================================================================\n// Config Errors (PN-CLI-4001-4007)\n// ============================================================================\n\n/**\n * Config file not found or missing.\n */\nexport function errorConfigFileNotFound(\n configPath?: string,\n options?: {\n readonly why?: string;\n },\n): CliStructuredError {\n return new CliStructuredError('4001', 'Config file not found', {\n domain: 'CLI',\n ...(options?.why ? { why: options.why } : { why: 'Config file not found' }),\n fix: \"Run 'prisma-next init' to create a config file\",\n docsUrl: 'https://prisma-next.dev/docs/cli/config',\n ...(configPath ? { where: { path: configPath } } : {}),\n });\n}\n\n/**\n * Contract configuration missing from config.\n */\nexport function errorContractConfigMissing(options?: {\n readonly why?: string;\n}): CliStructuredError {\n return new CliStructuredError('4002', 'Contract configuration missing', {\n domain: 'CLI',\n why: options?.why ?? 'The contract configuration is required for emit',\n fix: 'Add contract configuration to your prisma-next.config.ts',\n docsUrl: 'https://prisma-next.dev/docs/cli/contract-emit',\n });\n}\n\n/**\n * Contract validation failed.\n */\nexport function errorContractValidationFailed(\n reason: string,\n options?: {\n readonly where?: { readonly path?: string; readonly line?: number };\n },\n): CliStructuredError {\n return new CliStructuredError('4003', 'Contract validation failed', {\n domain: 'CLI',\n why: reason,\n fix: 'Re-run `prisma-next contract emit`, or fix the contract file and try again',\n docsUrl: 'https://prisma-next.dev/docs/contracts',\n ...(options?.where ? { where: options.where } : {}),\n });\n}\n\n/**\n * File not found.\n */\nexport function errorFileNotFound(\n filePath: string,\n options?: {\n readonly why?: string;\n readonly fix?: string;\n readonly docsUrl?: string;\n },\n): CliStructuredError {\n return new CliStructuredError('4004', 'File not found', {\n domain: 'CLI',\n why: options?.why ?? `File not found: ${filePath}`,\n fix: options?.fix ?? 'Check that the file path is correct',\n where: { path: filePath },\n ...(options?.docsUrl ? { docsUrl: options.docsUrl } : {}),\n });\n}\n\n/**\n * Database connection is required but not provided.\n */\nexport function errorDatabaseConnectionRequired(options?: {\n readonly why?: string;\n readonly commandName?: string;\n readonly retryCommand?: string;\n}): CliStructuredError {\n const runHint = options?.retryCommand\n ? `Run \\`${options.retryCommand}\\``\n : options?.commandName\n ? `Run \\`prisma-next ${options.commandName} --db <url>\\``\n : 'Provide `--db <url>`';\n return new CliStructuredError('4005', 'Database connection is required', {\n domain: 'CLI',\n why: options?.why ?? 'Database connection is required for this command',\n fix: `${runHint}, or set \\`db: { connection: \"postgres://…\" }\\` in prisma-next.config.ts`,\n });\n}\n\n/**\n * Query runner factory is required but not provided in config.\n */\nexport function errorQueryRunnerFactoryRequired(options?: {\n readonly why?: string;\n}): CliStructuredError {\n return new CliStructuredError('4006', 'Query runner factory is required', {\n domain: 'CLI',\n why: options?.why ?? 'Config.db.queryRunnerFactory is required for db verify',\n fix: 'Add db.queryRunnerFactory to prisma-next.config.ts',\n docsUrl: 'https://prisma-next.dev/docs/cli/db-verify',\n });\n}\n\n/**\n * Family verify.readMarker is required but not provided.\n */\nexport function errorFamilyReadMarkerSqlRequired(options?: {\n readonly why?: string;\n}): CliStructuredError {\n return new CliStructuredError('4007', 'Family readMarker() is required', {\n domain: 'CLI',\n why: options?.why ?? 'Family verify.readMarker is required for db verify',\n fix: 'Ensure family.verify.readMarker() is exported by your family package',\n docsUrl: 'https://prisma-next.dev/docs/cli/db-verify',\n });\n}\n\n/**\n * JSON output format not supported.\n */\nexport function errorJsonFormatNotSupported(options: {\n readonly command: string;\n readonly format: string;\n readonly supportedFormats: readonly string[];\n}): CliStructuredError {\n return new CliStructuredError('4008', 'Unsupported JSON format', {\n domain: 'CLI',\n why: `The ${options.command} command does not support --json ${options.format}`,\n fix: `Use --json ${options.supportedFormats.join(' or ')}, or omit --json for human output`,\n meta: {\n command: options.command,\n format: options.format,\n supportedFormats: options.supportedFormats,\n },\n });\n}\n\n/**\n * Driver is required for DB-connected commands but not provided.\n */\nexport function errorDriverRequired(options?: { readonly why?: string }): CliStructuredError {\n return new CliStructuredError('4010', 'Driver is required for DB-connected commands', {\n domain: 'CLI',\n why: options?.why ?? 'Config.driver is required for DB-connected commands',\n fix: 'Add a control-plane driver to prisma-next.config.ts (e.g. import a driver descriptor and set `driver: postgresDriver`)',\n docsUrl: 'https://prisma-next.dev/docs/cli/config',\n });\n}\n\n/**\n * Contract requires extension packs that are not provided by config descriptors.\n */\nexport function errorContractMissingExtensionPacks(options: {\n readonly missingExtensionPacks: readonly string[];\n readonly providedComponentIds: readonly string[];\n}): CliStructuredError {\n const missing = [...options.missingExtensionPacks].sort();\n return new CliStructuredError('4011', 'Missing extension packs in config', {\n domain: 'CLI',\n why:\n missing.length === 1\n ? `Contract requires extension pack '${missing[0]}', but CLI config does not provide a matching descriptor.`\n : `Contract requires extension packs ${missing.map((p) => `'${p}'`).join(', ')}, but CLI config does not provide matching descriptors.`,\n fix: 'Add the missing extension descriptors to `extensions` in prisma-next.config.ts',\n docsUrl: 'https://prisma-next.dev/docs/cli/config',\n meta: {\n missingExtensionPacks: missing,\n providedComponentIds: [...options.providedComponentIds].sort(),\n },\n });\n}\n\n/**\n * Migration planning failed due to conflicts.\n */\nexport function errorMigrationPlanningFailed(options: {\n readonly conflicts: readonly CliErrorConflict[];\n readonly why?: string;\n}): CliStructuredError {\n const conflictSummaries = options.conflicts.map((c) => c.summary);\n const computedWhy = options.why ?? conflictSummaries.join('\\n');\n\n const conflictFixes = options.conflicts\n .map((c) => c.why)\n .filter((why): why is string => typeof why === 'string');\n const computedFix =\n conflictFixes.length > 0\n ? conflictFixes.join('\\n')\n : 'Use `db verify --schema-only` to inspect conflicts, or ensure the database is empty';\n\n return new CliStructuredError('4020', 'Migration planning failed', {\n domain: 'CLI',\n why: computedWhy,\n fix: computedFix,\n meta: { conflicts: options.conflicts },\n docsUrl: 'https://prisma-next.dev/docs/cli/db-init',\n });\n}\n\n/**\n * Target does not support migrations (missing createPlanner/createRunner).\n */\nexport function errorTargetMigrationNotSupported(options?: {\n readonly why?: string;\n}): CliStructuredError {\n return new CliStructuredError('4021', 'Target does not support migrations', {\n domain: 'CLI',\n why: options?.why ?? 'The configured target does not provide migration planner/runner',\n fix: 'Select a target that provides migrations (it must export `target.migrations` for db init)',\n docsUrl: 'https://prisma-next.dev/docs/cli/db-init',\n });\n}\n\n/**\n * Config validation error (missing required fields).\n */\nexport function errorConfigValidation(\n field: string,\n options?: {\n readonly why?: string;\n },\n): CliStructuredError {\n return new CliStructuredError('4009', 'Config validation error', {\n domain: 'CLI',\n why: options?.why ?? `Config must have a \"${field}\" field`,\n fix: 'Check your prisma-next.config.ts and ensure all required fields are provided',\n docsUrl: 'https://prisma-next.dev/docs/cli/config',\n });\n}\n\n// ============================================================================\n// Generic Error\n// ============================================================================\n\n/**\n * Generic unexpected error.\n */\nexport function errorUnexpected(\n message: string,\n options?: {\n readonly why?: string;\n readonly fix?: string;\n },\n): CliStructuredError {\n return new CliStructuredError('4999', 'Unexpected error', {\n domain: 'CLI',\n why: options?.why ?? message,\n fix: options?.fix ?? 'Check the error message and try again',\n });\n}\n"],"mappings":";;;;;AAmCA,IAAa,qBAAb,cAAwC,MAAM;CAC5C,AAAS;CACT,AAAS;CACT,AAAS;CACT,AAAS;CACT,AAAS;CACT,AAAS;CAMT,AAAS;CACT,AAAS;CAET,YACE,MACA,SACA,SASA;AACA,QAAM,QAAQ;AACd,OAAK,OAAO;AACZ,OAAK,OAAO;AACZ,OAAK,SAAS,SAAS,UAAU;AACjC,OAAK,WAAW,SAAS,YAAY;AACrC,OAAK,MAAM,SAAS;AACpB,OAAK,MAAM,SAAS,QAAQ,SAAS,MAAM,SAAY,SAAS;AAChE,OAAK,QAAQ,SAAS,QAClB;GACE,MAAM,QAAQ,MAAM;GACpB,MAAM,QAAQ,MAAM;GACrB,GACD;AACJ,OAAK,OAAO,SAAS;AACrB,OAAK,UAAU,SAAS;;;;;CAM1B,aAA+B;AAG7B,SAAO;GACL,IAAI;GACJ,MAAM,GAJe;IAAE,KAAK;IAAW,KAAK;IAAW,KAAK;IAAW,CACvC,KAAK,UAGf,KAAK;GAC3B,QAAQ,KAAK;GACb,UAAU,KAAK;GACf,SAAS,KAAK;GACd,KAAK,KAAK;GACV,KAAK,KAAK;GACV,OAAO,KAAK;GACZ,MAAM,KAAK;GACX,SAAS,KAAK;GACf;;;;;;CAOH,OAAO,GAAG,OAA6C;AACrD,MAAI,EAAE,iBAAiB,OACrB,QAAO;EAET,MAAM,YAAY;AAClB,SACE,UAAU,SAAS,wBACnB,OAAO,UAAU,SAAS,aACzB,UAAU,WAAW,SAAS,UAAU,WAAW,SAAS,UAAU,WAAW,UAClF,OAAO,UAAU,eAAe;;;;;;AAYtC,SAAgB,wBACd,YACA,SAGoB;AACpB,QAAO,IAAI,mBAAmB,QAAQ,yBAAyB;EAC7D,QAAQ;EACR,GAAI,SAAS,MAAM,EAAE,KAAK,QAAQ,KAAK,GAAG,EAAE,KAAK,yBAAyB;EAC1E,KAAK;EACL,SAAS;EACT,GAAI,aAAa,EAAE,OAAO,EAAE,MAAM,YAAY,EAAE,GAAG,EAAE;EACtD,CAAC;;;;;AAMJ,SAAgB,2BAA2B,SAEpB;AACrB,QAAO,IAAI,mBAAmB,QAAQ,kCAAkC;EACtE,QAAQ;EACR,KAAK,SAAS,OAAO;EACrB,KAAK;EACL,SAAS;EACV,CAAC;;;;;AAMJ,SAAgB,8BACd,QACA,SAGoB;AACpB,QAAO,IAAI,mBAAmB,QAAQ,8BAA8B;EAClE,QAAQ;EACR,KAAK;EACL,KAAK;EACL,SAAS;EACT,GAAI,SAAS,QAAQ,EAAE,OAAO,QAAQ,OAAO,GAAG,EAAE;EACnD,CAAC;;;;;AAMJ,SAAgB,kBACd,UACA,SAKoB;AACpB,QAAO,IAAI,mBAAmB,QAAQ,kBAAkB;EACtD,QAAQ;EACR,KAAK,SAAS,OAAO,mBAAmB;EACxC,KAAK,SAAS,OAAO;EACrB,OAAO,EAAE,MAAM,UAAU;EACzB,GAAI,SAAS,UAAU,EAAE,SAAS,QAAQ,SAAS,GAAG,EAAE;EACzD,CAAC;;;;;AAMJ,SAAgB,gCAAgC,SAIzB;CACrB,MAAM,UAAU,SAAS,eACrB,SAAS,QAAQ,aAAa,MAC9B,SAAS,cACP,qBAAqB,QAAQ,YAAY,iBACzC;AACN,QAAO,IAAI,mBAAmB,QAAQ,mCAAmC;EACvE,QAAQ;EACR,KAAK,SAAS,OAAO;EACrB,KAAK,GAAG,QAAQ;EACjB,CAAC;;;;;AAMJ,SAAgB,gCAAgC,SAEzB;AACrB,QAAO,IAAI,mBAAmB,QAAQ,oCAAoC;EACxE,QAAQ;EACR,KAAK,SAAS,OAAO;EACrB,KAAK;EACL,SAAS;EACV,CAAC;;;;;AAMJ,SAAgB,iCAAiC,SAE1B;AACrB,QAAO,IAAI,mBAAmB,QAAQ,mCAAmC;EACvE,QAAQ;EACR,KAAK,SAAS,OAAO;EACrB,KAAK;EACL,SAAS;EACV,CAAC;;;;;AAMJ,SAAgB,4BAA4B,SAIrB;AACrB,QAAO,IAAI,mBAAmB,QAAQ,2BAA2B;EAC/D,QAAQ;EACR,KAAK,OAAO,QAAQ,QAAQ,mCAAmC,QAAQ;EACvE,KAAK,cAAc,QAAQ,iBAAiB,KAAK,OAAO,CAAC;EACzD,MAAM;GACJ,SAAS,QAAQ;GACjB,QAAQ,QAAQ;GAChB,kBAAkB,QAAQ;GAC3B;EACF,CAAC;;;;;AAMJ,SAAgB,oBAAoB,SAAyD;AAC3F,QAAO,IAAI,mBAAmB,QAAQ,gDAAgD;EACpF,QAAQ;EACR,KAAK,SAAS,OAAO;EACrB,KAAK;EACL,SAAS;EACV,CAAC;;;;;AAMJ,SAAgB,mCAAmC,SAG5B;CACrB,MAAM,UAAU,CAAC,GAAG,QAAQ,sBAAsB,CAAC,MAAM;AACzD,QAAO,IAAI,mBAAmB,QAAQ,qCAAqC;EACzE,QAAQ;EACR,KACE,QAAQ,WAAW,IACf,qCAAqC,QAAQ,GAAG,6DAChD,qCAAqC,QAAQ,KAAK,MAAM,IAAI,EAAE,GAAG,CAAC,KAAK,KAAK,CAAC;EACnF,KAAK;EACL,SAAS;EACT,MAAM;GACJ,uBAAuB;GACvB,sBAAsB,CAAC,GAAG,QAAQ,qBAAqB,CAAC,MAAM;GAC/D;EACF,CAAC;;;;;AAMJ,SAAgB,6BAA6B,SAGtB;CACrB,MAAM,oBAAoB,QAAQ,UAAU,KAAK,MAAM,EAAE,QAAQ;CACjE,MAAM,cAAc,QAAQ,OAAO,kBAAkB,KAAK,KAAK;CAE/D,MAAM,gBAAgB,QAAQ,UAC3B,KAAK,MAAM,EAAE,IAAI,CACjB,QAAQ,QAAuB,OAAO,QAAQ,SAAS;AAM1D,QAAO,IAAI,mBAAmB,QAAQ,6BAA6B;EACjE,QAAQ;EACR,KAAK;EACL,KAPA,cAAc,SAAS,IACnB,cAAc,KAAK,KAAK,GACxB;EAMJ,MAAM,EAAE,WAAW,QAAQ,WAAW;EACtC,SAAS;EACV,CAAC;;;;;AAMJ,SAAgB,iCAAiC,SAE1B;AACrB,QAAO,IAAI,mBAAmB,QAAQ,sCAAsC;EAC1E,QAAQ;EACR,KAAK,SAAS,OAAO;EACrB,KAAK;EACL,SAAS;EACV,CAAC;;;;;AAMJ,SAAgB,sBACd,OACA,SAGoB;AACpB,QAAO,IAAI,mBAAmB,QAAQ,2BAA2B;EAC/D,QAAQ;EACR,KAAK,SAAS,OAAO,uBAAuB,MAAM;EAClD,KAAK;EACL,SAAS;EACV,CAAC;;;;;AAUJ,SAAgB,gBACd,SACA,SAIoB;AACpB,QAAO,IAAI,mBAAmB,QAAQ,oBAAoB;EACxD,QAAQ;EACR,KAAK,SAAS,OAAO;EACrB,KAAK,SAAS,OAAO;EACtB,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"control-C16uWwh2.d.mts","names":[],"sources":["../src/control.ts"],"sourcesContent":[],"mappings":";;AAIA;AAqBA;AAUA;AAYiB,UA3CA,gBAAA,CA2CA;EAYK,SAAA,EAAA,EAAA,KAAA;EAwBN,SAAA,IAAA,EAAA,MAAA;EAqBsB,SAAA,MAAA,EAAA,MAAA;EArEE,SAAA,QAAA,EAAA,OAAA,GAAA,MAAA,GAAA,MAAA;EAAK,SAAA,OAAA,EAAA,MAAA;EA0F7B,SAAA,GAAA,EAAA,MAAA,GAAA,SAAuB;EAkBvB,SAAA,GAAA,EAAA,MAAA,GAAA,SAA0B;EAc1B,SAAA,KAAA,EAAA;IAkBA,SAAA,IAAA,EAAA,MAAiB,GAAA,SAO9B;IAaa,SAAA,IAAA,EAAA,MAAA,GAAA,SAA+B;EAoB/B,CAAA,GAAA,SAAA;EAcA,SAAA,IAAA,EAnNC,MAmND,CAAA,MAAA,EAAA,OAAgC,CAAA,GAAA,SAE5C;EAYY,SAAA,OAAA,EAAA,MAAA,GAAA,SAA2B;AAoB3C;AAYA;AAuBA;AA2BA;AAcgB,UA1TC,gBAAA,CA0ToB;EAqBrB,SAAA,IAAA,EAAA,MAAe;;;;;;;;cArUlB,kBAAA,SAA2B,KAAA;;;;;;;;;;iBAYvB;;;;;;;;;;;oBAYK;;;;;;gBAwBN;;;;;sCAqBsB;;;;;iBAqBtB,uBAAA;;IAKb;;;;iBAaa,0BAAA;;IAEZ;;;;iBAYY,6BAAA;;;;;IAKb;;;;iBAaa,iBAAA;;;;IAOb;;;;iBAaa,+BAAA;;;;IAIZ;;;;iBAgBY,+BAAA;;IAEZ;;;;iBAYY,gCAAA;;IAEZ;;;;iBAYY,2BAAA;;;;IAIZ;;;;iBAgBY,mBAAA;;IAA0D;;;;iBAY1D,kCAAA;;;IAGZ;;;;iBAoBY,4BAAA;+BACe;;IAE3B;;;;iBAwBY,gCAAA;;IAEZ;;;;iBAYY,qBAAA;;IAKb;;;;iBAgBa,eAAA;;;IAMb"}