@prisma-next/cli 0.16.0-dev.30 → 0.16.0-dev.32

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.
Files changed (95) hide show
  1. package/dist/cli.mjs +13 -13
  2. package/dist/{client-CMusjGV5.mjs → client-B1UjQc_x.mjs} +30 -37
  3. package/dist/client-B1UjQc_x.mjs.map +1 -0
  4. package/dist/{command-helpers-CVn3U9Uz.mjs → command-helpers-D-jBl0Qt.mjs} +5 -5
  5. package/dist/command-helpers-D-jBl0Qt.mjs.map +1 -0
  6. package/dist/commands/contract-emit.mjs +1 -1
  7. package/dist/commands/contract-infer.mjs +1 -1
  8. package/dist/commands/db-init.d.mts.map +1 -1
  9. package/dist/commands/db-init.mjs +6 -5
  10. package/dist/commands/db-init.mjs.map +1 -1
  11. package/dist/commands/db-schema.mjs +3 -3
  12. package/dist/commands/db-sign.mjs +6 -5
  13. package/dist/commands/db-sign.mjs.map +1 -1
  14. package/dist/commands/db-update.d.mts.map +1 -1
  15. package/dist/commands/db-update.mjs +7 -6
  16. package/dist/commands/db-update.mjs.map +1 -1
  17. package/dist/commands/db-verify.mjs +1 -1
  18. package/dist/commands/migrate.mjs +6 -6
  19. package/dist/commands/migration-check.mjs +1 -1
  20. package/dist/commands/migration-graph.mjs +4 -4
  21. package/dist/commands/migration-list.mjs +1 -1
  22. package/dist/commands/migration-log.mjs +1 -1
  23. package/dist/commands/migration-new.mjs +3 -3
  24. package/dist/commands/migration-plan.mjs +1 -1
  25. package/dist/commands/migration-show.mjs +3 -3
  26. package/dist/commands/migration-status.mjs +1 -1
  27. package/dist/commands/ref.mjs +2 -2
  28. package/dist/commands/telemetry/index.mjs +1 -1
  29. package/dist/{contract-at-errors-C-l4-JEY.mjs → contract-at-errors-DvZ_DzJK.mjs} +2 -2
  30. package/dist/{contract-at-errors-C-l4-JEY.mjs.map → contract-at-errors-DvZ_DzJK.mjs.map} +1 -1
  31. package/dist/{contract-emit-PaY3qRdN.mjs → contract-emit-BT46Mu8Q.mjs} +3 -3
  32. package/dist/{contract-emit-PaY3qRdN.mjs.map → contract-emit-BT46Mu8Q.mjs.map} +1 -1
  33. package/dist/{contract-emit-CfIbTnsR.mjs → contract-emit-hVdlaF2U.mjs} +3 -3
  34. package/dist/{contract-emit-CfIbTnsR.mjs.map → contract-emit-hVdlaF2U.mjs.map} +1 -1
  35. package/dist/{contract-infer-DCju2fTk.mjs → contract-infer-DpqTQECL.mjs} +3 -3
  36. package/dist/{contract-infer-DCju2fTk.mjs.map → contract-infer-DpqTQECL.mjs.map} +1 -1
  37. package/dist/{contract-space-aggregate-loader-B6E9LGa6.mjs → contract-space-aggregate-loader-CNd-ZB6C.mjs} +2 -2
  38. package/dist/{contract-space-aggregate-loader-B6E9LGa6.mjs.map → contract-space-aggregate-loader-CNd-ZB6C.mjs.map} +1 -1
  39. package/dist/{db-verify-B_dKu6Yp.mjs → db-verify-FEN6k1m7.mjs} +9 -7
  40. package/dist/db-verify-FEN6k1m7.mjs.map +1 -0
  41. package/dist/exports/control-api.d.mts.map +1 -1
  42. package/dist/exports/control-api.mjs +2 -2
  43. package/dist/exports/index.d.mts +2 -1
  44. package/dist/exports/index.d.mts.map +1 -1
  45. package/dist/exports/index.mjs +61 -21
  46. package/dist/exports/index.mjs.map +1 -1
  47. package/dist/{format-cCyDfmRE.mjs → format-DI5qVr22.mjs} +3 -3
  48. package/dist/{format-cCyDfmRE.mjs.map → format-DI5qVr22.mjs.map} +1 -1
  49. package/dist/{framework-components-DUN-TYDg.mjs → framework-components-C4XACYNB.mjs} +2 -2
  50. package/dist/{framework-components-DUN-TYDg.mjs.map → framework-components-C4XACYNB.mjs.map} +1 -1
  51. package/dist/{init-C9U3ffHH.mjs → init-ClrRkbwd.mjs} +25 -23
  52. package/dist/init-ClrRkbwd.mjs.map +1 -0
  53. package/dist/{inspect-live-schema-DHXE7skX.mjs → inspect-live-schema-C0Rgdtw_.mjs} +3 -3
  54. package/dist/{inspect-live-schema-DHXE7skX.mjs.map → inspect-live-schema-C0Rgdtw_.mjs.map} +1 -1
  55. package/dist/{migration-check-W5XEx4d-.mjs → migration-check-zEkHpPDT.mjs} +4 -4
  56. package/dist/{migration-check-W5XEx4d-.mjs.map → migration-check-zEkHpPDT.mjs.map} +1 -1
  57. package/dist/{migration-command-scaffold-hI5cnoGe.mjs → migration-command-scaffold-CkNsp9g1.mjs} +3 -3
  58. package/dist/{migration-command-scaffold-hI5cnoGe.mjs.map → migration-command-scaffold-CkNsp9g1.mjs.map} +1 -1
  59. package/dist/{migration-graph-command-render-DgQg5App.mjs → migration-graph-command-render-DEwFpx-w.mjs} +3 -2
  60. package/dist/migration-graph-command-render-DEwFpx-w.mjs.map +1 -0
  61. package/dist/{migration-list-ClkEaoL8.mjs → migration-list-BkafFVXS.mjs} +4 -4
  62. package/dist/{migration-list-ClkEaoL8.mjs.map → migration-list-BkafFVXS.mjs.map} +1 -1
  63. package/dist/{migration-log-CjafbZ2Z.mjs → migration-log-BxhAtbhA.mjs} +4 -4
  64. package/dist/{migration-log-CjafbZ2Z.mjs.map → migration-log-BxhAtbhA.mjs.map} +1 -1
  65. package/dist/{migration-path-target-C0TQuV5n.mjs → migration-path-target-B5HkjSTO.mjs} +2 -2
  66. package/dist/{migration-path-target-C0TQuV5n.mjs.map → migration-path-target-B5HkjSTO.mjs.map} +1 -1
  67. package/dist/{migration-plan-Pc4hCF1H.mjs → migration-plan-Bk2pbPQH.mjs} +5 -5
  68. package/dist/{migration-plan-Pc4hCF1H.mjs.map → migration-plan-Bk2pbPQH.mjs.map} +1 -1
  69. package/dist/{migration-status-CqAdRzs8.mjs → migration-status-BzlARseq.mjs} +6 -6
  70. package/dist/{migration-status-CqAdRzs8.mjs.map → migration-status-BzlARseq.mjs.map} +1 -1
  71. package/dist/{telemetry-BEyNMfco.mjs → telemetry-BbniBUbP.mjs} +2 -2
  72. package/dist/{telemetry-BEyNMfco.mjs.map → telemetry-BbniBUbP.mjs.map} +1 -1
  73. package/dist/{verify-C4RazDE1.mjs → verify-BSaNeaSL.mjs} +2 -2
  74. package/dist/{verify-C4RazDE1.mjs.map → verify-BSaNeaSL.mjs.map} +1 -1
  75. package/package.json +21 -21
  76. package/src/commands/db-init.ts +4 -3
  77. package/src/commands/db-sign.ts +2 -2
  78. package/src/commands/db-update.ts +4 -3
  79. package/src/commands/db-verify.ts +3 -3
  80. package/src/commands/init/probe-db.ts +9 -2
  81. package/src/commands/init/templates/render.ts +2 -1
  82. package/src/control-api/client.ts +36 -17
  83. package/src/control-api/operations/db-run.ts +2 -1
  84. package/src/control-api/operations/migrate.ts +3 -2
  85. package/src/control-api/operations/run-migration.ts +2 -1
  86. package/src/load-ts-contract.ts +81 -16
  87. package/src/utils/combine-verify-results.ts +2 -1
  88. package/src/utils/command-helpers.ts +15 -5
  89. package/src/utils/formatters/migration-graph-grid-layout.ts +2 -1
  90. package/dist/client-CMusjGV5.mjs.map +0 -1
  91. package/dist/command-helpers-CVn3U9Uz.mjs.map +0 -1
  92. package/dist/db-verify-B_dKu6Yp.mjs.map +0 -1
  93. package/dist/init-C9U3ffHH.mjs.map +0 -1
  94. package/dist/migration-graph-command-render-DgQg5App.mjs.map +0 -1
  95. package/src/control-api/errors.ts +0 -9
@@ -1,11 +1,18 @@
1
- import { t as createContractEmitCommand } from "../contract-emit-PaY3qRdN.mjs";
2
- import { t as createFormatCommand } from "../format-cCyDfmRE.mjs";
1
+ import { t as createContractEmitCommand } from "../contract-emit-BT46Mu8Q.mjs";
2
+ import { t as createFormatCommand } from "../format-DI5qVr22.mjs";
3
+ import { CliStructuredError } from "@prisma-next/errors/control";
3
4
  import { join, resolve } from "pathe";
4
5
  import { existsSync, unlinkSync, writeFileSync } from "node:fs";
6
+ import { InternalError } from "@prisma-next/utils/internal-error";
5
7
  import { tmpdir } from "node:os";
6
8
  import { pathToFileURL } from "node:url";
7
9
  import { build } from "esbuild";
8
10
  //#region src/load-ts-contract.ts
11
+ function contractSourceError(code, message, options) {
12
+ const error = new CliStructuredError(code, message, options?.meta !== void 0 ? { meta: options.meta } : void 0);
13
+ if (options?.cause !== void 0) error.cause = options.cause;
14
+ return error;
15
+ }
9
16
  const DEFAULT_ALLOWLIST = ["@prisma-next/*", "node:crypto"];
10
17
  function isAllowedImport(importPath, allowlist) {
11
18
  for (const pattern of allowlist) if (pattern.endsWith("/*")) {
@@ -17,18 +24,29 @@ function isAllowedImport(importPath, allowlist) {
17
24
  } else if (importPath === pattern) return true;
18
25
  return false;
19
26
  }
20
- function validatePurity(value) {
27
+ function validatePurity(value, entryPath) {
21
28
  if (typeof value !== "object" || value === null) return;
22
29
  const path = /* @__PURE__ */ new WeakSet();
23
30
  function check(value) {
24
31
  if (value === null || typeof value !== "object") return;
25
- if (path.has(value)) throw new Error("Contract export contains circular references");
32
+ if (path.has(value)) throw contractSourceError("CONTRACT.EXPORT_INVALID", "Contract export contains circular references", { meta: {
33
+ path: entryPath,
34
+ reason: "circular"
35
+ } });
26
36
  path.add(value);
27
37
  try {
28
38
  for (const key in value) {
29
39
  const descriptor = Object.getOwnPropertyDescriptor(value, key);
30
- if (descriptor && (descriptor.get || descriptor.set)) throw new Error(`Contract export contains getter/setter at key "${key}"`);
31
- if (descriptor && typeof descriptor.value === "function") throw new Error(`Contract export contains function at key "${key}"`);
40
+ if (descriptor && (descriptor.get || descriptor.set)) throw contractSourceError("CONTRACT.EXPORT_INVALID", `Contract export contains getter/setter at key "${key}"`, { meta: {
41
+ path: entryPath,
42
+ reason: "getter",
43
+ key
44
+ } });
45
+ if (descriptor && typeof descriptor.value === "function") throw contractSourceError("CONTRACT.EXPORT_INVALID", `Contract export contains function at key "${key}"`, { meta: {
46
+ path: entryPath,
47
+ reason: "function",
48
+ key
49
+ } });
32
50
  check(value[key]);
33
51
  }
34
52
  } finally {
@@ -41,9 +59,18 @@ function validatePurity(value) {
41
59
  } catch (error) {
42
60
  if (error instanceof Error) {
43
61
  if (error.message.includes("getter") || error.message.includes("circular")) throw error;
44
- throw new Error(`Contract export is not JSON-serializable: ${error.message}`);
62
+ throw contractSourceError("CONTRACT.EXPORT_INVALID", `Contract export is not JSON-serializable: ${error.message}`, {
63
+ meta: {
64
+ path: entryPath,
65
+ reason: "not-json-serializable"
66
+ },
67
+ cause: error
68
+ });
45
69
  }
46
- throw new Error("Contract export is not JSON-serializable");
70
+ throw contractSourceError("CONTRACT.EXPORT_INVALID", "Contract export is not JSON-serializable", { meta: {
71
+ path: entryPath,
72
+ reason: "not-json-serializable"
73
+ } });
47
74
  }
48
75
  }
49
76
  function createImportAllowlistPlugin(allowlist, entryPath, collected) {
@@ -81,11 +108,12 @@ function createImportAllowlistPlugin(allowlist, entryPath, collected) {
81
108
  * @param entryPath - Path to the TypeScript contract file
82
109
  * @param options - Optional configuration (import allowlist)
83
110
  * @returns The contract as Contract (should already be normalized)
84
- * @throws Error if the contract cannot be loaded or is not JSON-serializable
111
+ * @throws structured errors: `CLI.FILE_NOT_FOUND`, `CONTRACT.SOURCE_LOAD_FAILED`,
112
+ * `CONTRACT.SOURCE_IMPORT_DISALLOWED`, `CONTRACT.MODULE_EXPORT_MISSING`, `CONTRACT.EXPORT_INVALID`
85
113
  */
86
114
  async function loadContractFromTs(entryPath, options) {
87
115
  const allowlist = options?.allowlist ?? DEFAULT_ALLOWLIST;
88
- if (!existsSync(entryPath)) throw new Error(`Contract file not found: ${entryPath}`);
116
+ if (!existsSync(entryPath)) throw new CliStructuredError("CLI.FILE_NOT_FOUND", `Contract file not found: ${entryPath}`, { where: { path: entryPath } });
89
117
  const tempFile = join(tmpdir(), `prisma-next-contract-${Date.now()}-${Math.random().toString(36).slice(2)}.mjs`);
90
118
  const disallowedFromEntry = /* @__PURE__ */ new Set();
91
119
  try {
@@ -101,14 +129,17 @@ async function loadContractFromTs(entryPath, options) {
101
129
  plugins: [createImportAllowlistPlugin(allowlist, entryPath, disallowedFromEntry)],
102
130
  logLevel: "error"
103
131
  });
104
- if (result.errors.length > 0) {
105
- const errorMessages = result.errors.map((e) => e.text).join("\n");
106
- throw new Error(`Failed to bundle contract file: ${errorMessages}`);
107
- }
108
- if (!result.outputFiles || result.outputFiles.length === 0) throw new Error("No output files generated from bundling");
109
- if (disallowedFromEntry.size > 0) throw new Error(`Disallowed imports detected. Only imports matching the allowlist are permitted:\n Allowlist: ${allowlist.join(", ")}\n Disallowed imports: ${[...disallowedFromEntry].join(", ")}`);
132
+ if (result.errors.length > 0) throw contractSourceError("CONTRACT.SOURCE_LOAD_FAILED", `Failed to bundle contract file: ${result.errors.map((e) => e.text).join("\n")}`, { meta: {
133
+ path: entryPath,
134
+ stage: "bundle"
135
+ } });
136
+ if (!result.outputFiles || result.outputFiles.length === 0) throw new InternalError("No output files generated from bundling");
137
+ if (disallowedFromEntry.size > 0) throw contractSourceError("CONTRACT.SOURCE_IMPORT_DISALLOWED", `Disallowed imports detected. Only imports matching the allowlist are permitted:\n Allowlist: ${allowlist.join(", ")}\n Disallowed imports: ${[...disallowedFromEntry].join(", ")}`, { meta: {
138
+ allowlist: [...allowlist],
139
+ disallowed: [...disallowedFromEntry]
140
+ } });
110
141
  const bundleContent = result.outputFiles[0]?.text;
111
- if (bundleContent === void 0) throw new Error("Bundle content is undefined");
142
+ if (bundleContent === void 0) throw new InternalError("Bundle content is undefined");
112
143
  writeFileSync(tempFile, bundleContent, "utf-8");
113
144
  const module = await import(
114
145
  /* @vite-ignore */
@@ -118,16 +149,25 @@ async function loadContractFromTs(entryPath, options) {
118
149
  let contract;
119
150
  if (module.default !== void 0) contract = module.default;
120
151
  else if (module.contract !== void 0) contract = module.contract;
121
- else throw new Error(`Contract file must export a contract as default export or named export 'contract'. Found exports: ${Object.keys(module).join(", ") || "none"}`);
122
- if (typeof contract !== "object" || contract === null) throw new Error(`Contract export must be an object, got ${typeof contract}`);
123
- validatePurity(contract);
152
+ else throw new CliStructuredError("CONTRACT.MODULE_EXPORT_MISSING", `Contract file must export a contract as default export or named export 'contract'. Found exports: ${Object.keys(module).join(", ") || "none"}`, { where: { path: entryPath } });
153
+ if (typeof contract !== "object" || contract === null) throw contractSourceError("CONTRACT.EXPORT_INVALID", `Contract export must be an object, got ${typeof contract}`, { meta: {
154
+ path: entryPath,
155
+ reason: "not-object"
156
+ } });
157
+ validatePurity(contract, entryPath);
124
158
  return contract;
125
159
  } catch (error) {
126
160
  try {
127
161
  if (tempFile) unlinkSync(tempFile);
128
162
  } catch {}
129
163
  if (error instanceof Error) throw error;
130
- throw new Error(`Failed to load contract from ${entryPath}: ${String(error)}`);
164
+ throw contractSourceError("CONTRACT.SOURCE_LOAD_FAILED", `Failed to load contract from ${entryPath}: ${String(error)}`, {
165
+ meta: {
166
+ path: entryPath,
167
+ stage: "import"
168
+ },
169
+ cause: error
170
+ });
131
171
  }
132
172
  }
133
173
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["resolvePath"],"sources":["../../src/load-ts-contract.ts"],"sourcesContent":["import { existsSync, unlinkSync, writeFileSync } from 'node:fs';\nimport { tmpdir } from 'node:os';\nimport { pathToFileURL } from 'node:url';\nimport type { Contract } from '@prisma-next/contract/types';\nimport type { Plugin } from 'esbuild';\nimport { build } from 'esbuild';\nimport { join, resolve as resolvePath } from 'pathe';\n\nexport interface LoadTsContractOptions {\n readonly allowlist?: ReadonlyArray<string>;\n}\n\nconst DEFAULT_ALLOWLIST = ['@prisma-next/*', 'node:crypto'];\n\nfunction isAllowedImport(importPath: string, allowlist: ReadonlyArray<string>): boolean {\n for (const pattern of allowlist) {\n if (pattern.endsWith('/*')) {\n const prefix = pattern.slice(0, -2);\n if (importPath === prefix || importPath.startsWith(`${prefix}/`)) {\n return true;\n }\n } else if (pattern.endsWith('*')) {\n const prefix = pattern.slice(0, -1);\n if (importPath.startsWith(prefix)) {\n return true;\n }\n } else if (importPath === pattern) {\n return true;\n }\n }\n return false;\n}\n\nfunction validatePurity(value: unknown): void {\n if (typeof value !== 'object' || value === null) {\n return;\n }\n\n const path = new WeakSet();\n\n function check(value: unknown): void {\n if (value === null || typeof value !== 'object') {\n return;\n }\n\n if (path.has(value)) {\n throw new Error('Contract export contains circular references');\n }\n path.add(value);\n\n try {\n for (const key in value) {\n const descriptor = Object.getOwnPropertyDescriptor(value, key);\n if (descriptor && (descriptor.get || descriptor.set)) {\n throw new Error(`Contract export contains getter/setter at key \"${key}\"`);\n }\n if (descriptor && typeof descriptor.value === 'function') {\n throw new Error(`Contract export contains function at key \"${key}\"`);\n }\n check((value as Record<string, unknown>)[key]);\n }\n } finally {\n path.delete(value);\n }\n }\n\n try {\n check(value);\n JSON.stringify(value);\n } catch (error) {\n if (error instanceof Error) {\n if (error.message.includes('getter') || error.message.includes('circular')) {\n throw error;\n }\n throw new Error(`Contract export is not JSON-serializable: ${error.message}`);\n }\n throw new Error('Contract export is not JSON-serializable');\n }\n}\n\nfunction createImportAllowlistPlugin(\n allowlist: ReadonlyArray<string>,\n entryPath: string,\n collected: Set<string>,\n): Plugin {\n // Match against several path forms that esbuild may use as the importer:\n // the absolute resolved entry, the value the caller passed (which may be\n // relative), and the conventional `<stdin>` placeholder. This is more\n // forgiving than `===` against a single form, which broke when esbuild\n // resolved the entry to an absolute path while the caller passed a\n // relative one (or vice versa).\n const entryAbs = resolvePath(entryPath);\n function isFromEntry(importer: string): boolean {\n return importer === entryAbs || importer === entryPath || importer === '<stdin>';\n }\n return {\n name: 'import-allowlist',\n setup(build) {\n build.onResolve({ filter: /.*/ }, (args) => {\n if (args.kind === 'entry-point') {\n return undefined;\n }\n if (args.path.startsWith('.') || args.path.startsWith('/')) {\n return undefined;\n }\n if (isFromEntry(args.importer) && !isAllowedImport(args.path, allowlist)) {\n collected.add(args.path);\n return {\n path: args.path,\n external: true,\n };\n }\n return undefined;\n });\n },\n };\n}\n\n/**\n * Loads a contract from a TypeScript file and returns it as Contract.\n *\n * **Responsibility: Parsing Only**\n * This function loads and parses a TypeScript contract file. It does NOT normalize the contract.\n * The contract should already be normalized if it was built using the contract builder.\n *\n * Normalization must happen in the contract builder when the contract is created.\n * This function only validates that the contract is JSON-serializable and returns it as-is.\n *\n * @param entryPath - Path to the TypeScript contract file\n * @param options - Optional configuration (import allowlist)\n * @returns The contract as Contract (should already be normalized)\n * @throws Error if the contract cannot be loaded or is not JSON-serializable\n */\nexport async function loadContractFromTs(\n entryPath: string,\n options?: LoadTsContractOptions,\n): Promise<Contract> {\n const allowlist = options?.allowlist ?? DEFAULT_ALLOWLIST;\n\n if (!existsSync(entryPath)) {\n throw new Error(`Contract file not found: ${entryPath}`);\n }\n\n const tempFile = join(\n tmpdir(),\n `prisma-next-contract-${Date.now()}-${Math.random().toString(36).slice(2)}.mjs`,\n );\n\n // Disallowed imports are collected by the allowlist resolver plugin itself,\n // which has the `importer` context to distinguish entry-direct imports from\n // transitive imports made inside allowlisted (`@prisma-next/*`) dependencies.\n // The metafile is intentionally not re-walked: it would surface internal\n // `node:*` imports inside framework code as false positives.\n const disallowedFromEntry = new Set<string>();\n\n try {\n const result = await build({\n entryPoints: [entryPath],\n bundle: true,\n format: 'esm',\n platform: 'node',\n target: 'es2022',\n outfile: tempFile,\n write: false,\n metafile: true,\n plugins: [createImportAllowlistPlugin(allowlist, entryPath, disallowedFromEntry)],\n logLevel: 'error',\n });\n\n if (result.errors.length > 0) {\n const errorMessages = result.errors.map((e: { text: string }) => e.text).join('\\n');\n throw new Error(`Failed to bundle contract file: ${errorMessages}`);\n }\n\n if (!result.outputFiles || result.outputFiles.length === 0) {\n throw new Error('No output files generated from bundling');\n }\n\n if (disallowedFromEntry.size > 0) {\n throw new Error(\n `Disallowed imports detected. Only imports matching the allowlist are permitted:\\n Allowlist: ${allowlist.join(', ')}\\n Disallowed imports: ${[...disallowedFromEntry].join(', ')}`,\n );\n }\n\n const bundleContent = result.outputFiles[0]?.text;\n if (bundleContent === undefined) {\n throw new Error('Bundle content is undefined');\n }\n writeFileSync(tempFile, bundleContent, 'utf-8');\n\n const module = (await import(/* @vite-ignore */ pathToFileURL(tempFile).href)) as {\n default?: unknown;\n contract?: unknown;\n };\n unlinkSync(tempFile);\n\n let contract: unknown;\n\n if (module.default !== undefined) {\n contract = module.default;\n } else if (module.contract !== undefined) {\n contract = module.contract;\n } else {\n throw new Error(\n `Contract file must export a contract as default export or named export 'contract'. Found exports: ${Object.keys(module as Record<string, unknown>).join(', ') || 'none'}`,\n );\n }\n\n if (typeof contract !== 'object' || contract === null) {\n throw new Error(`Contract export must be an object, got ${typeof contract}`);\n }\n\n validatePurity(contract);\n\n // Blind cast: the loaded module was authored by user code\n // (typically via `defineContract` / a contract builder) and\n // its runtime shape is structurally a `Contract`, but the\n // dynamic import collapses the source typing. The contract\n // structural validation that asserts the shape happens\n // downstream at the `familyInstance.deserializeContract` seam\n // (e.g. in `executeContractEmit`); this helper only checks\n // purity here.\n return contract as unknown as Contract;\n } catch (error) {\n try {\n if (tempFile) {\n unlinkSync(tempFile);\n }\n } catch {\n // Ignore cleanup errors\n }\n\n if (error instanceof Error) {\n throw error;\n }\n throw new Error(`Failed to load contract from ${entryPath}: ${String(error)}`);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["resolvePath"],"sources":["../../src/load-ts-contract.ts"],"sourcesContent":["import { existsSync, unlinkSync, writeFileSync } from 'node:fs';\nimport { tmpdir } from 'node:os';\nimport { pathToFileURL } from 'node:url';\nimport type { Contract } from '@prisma-next/contract/types';\nimport { CliStructuredError } from '@prisma-next/errors/control';\nimport { InternalError } from '@prisma-next/utils/internal-error';\nimport type { Plugin } from 'esbuild';\nimport { build } from 'esbuild';\nimport { join, resolve as resolvePath } from 'pathe';\n\nexport interface LoadTsContractOptions {\n readonly allowlist?: ReadonlyArray<string>;\n}\n\ntype ContractSourceErrorCode =\n | 'CONTRACT.EXPORT_INVALID'\n | 'CONTRACT.SOURCE_LOAD_FAILED'\n | 'CONTRACT.SOURCE_IMPORT_DISALLOWED';\n\nfunction contractSourceError(\n code: ContractSourceErrorCode,\n message: string,\n options?: {\n readonly meta?: Record<string, unknown>;\n readonly cause?: unknown;\n },\n): CliStructuredError {\n const error = new CliStructuredError(\n code,\n message,\n options?.meta !== undefined ? { meta: options.meta } : undefined,\n );\n if (options?.cause !== undefined) {\n error.cause = options.cause;\n }\n return error;\n}\n\nconst DEFAULT_ALLOWLIST = ['@prisma-next/*', 'node:crypto'];\n\nfunction isAllowedImport(importPath: string, allowlist: ReadonlyArray<string>): boolean {\n for (const pattern of allowlist) {\n if (pattern.endsWith('/*')) {\n const prefix = pattern.slice(0, -2);\n if (importPath === prefix || importPath.startsWith(`${prefix}/`)) {\n return true;\n }\n } else if (pattern.endsWith('*')) {\n const prefix = pattern.slice(0, -1);\n if (importPath.startsWith(prefix)) {\n return true;\n }\n } else if (importPath === pattern) {\n return true;\n }\n }\n return false;\n}\n\nfunction validatePurity(value: unknown, entryPath: string): void {\n if (typeof value !== 'object' || value === null) {\n return;\n }\n\n const path = new WeakSet();\n\n function check(value: unknown): void {\n if (value === null || typeof value !== 'object') {\n return;\n }\n\n if (path.has(value)) {\n throw contractSourceError(\n 'CONTRACT.EXPORT_INVALID',\n 'Contract export contains circular references',\n { meta: { path: entryPath, reason: 'circular' } },\n );\n }\n path.add(value);\n\n try {\n for (const key in value) {\n const descriptor = Object.getOwnPropertyDescriptor(value, key);\n if (descriptor && (descriptor.get || descriptor.set)) {\n throw contractSourceError(\n 'CONTRACT.EXPORT_INVALID',\n `Contract export contains getter/setter at key \"${key}\"`,\n { meta: { path: entryPath, reason: 'getter', key } },\n );\n }\n if (descriptor && typeof descriptor.value === 'function') {\n throw contractSourceError(\n 'CONTRACT.EXPORT_INVALID',\n `Contract export contains function at key \"${key}\"`,\n { meta: { path: entryPath, reason: 'function', key } },\n );\n }\n check((value as Record<string, unknown>)[key]);\n }\n } finally {\n path.delete(value);\n }\n }\n\n try {\n check(value);\n JSON.stringify(value);\n } catch (error) {\n if (error instanceof Error) {\n if (error.message.includes('getter') || error.message.includes('circular')) {\n throw error;\n }\n throw contractSourceError(\n 'CONTRACT.EXPORT_INVALID',\n `Contract export is not JSON-serializable: ${error.message}`,\n { meta: { path: entryPath, reason: 'not-json-serializable' }, cause: error },\n );\n }\n throw contractSourceError(\n 'CONTRACT.EXPORT_INVALID',\n 'Contract export is not JSON-serializable',\n { meta: { path: entryPath, reason: 'not-json-serializable' } },\n );\n }\n}\n\nfunction createImportAllowlistPlugin(\n allowlist: ReadonlyArray<string>,\n entryPath: string,\n collected: Set<string>,\n): Plugin {\n // Match against several path forms that esbuild may use as the importer:\n // the absolute resolved entry, the value the caller passed (which may be\n // relative), and the conventional `<stdin>` placeholder. This is more\n // forgiving than `===` against a single form, which broke when esbuild\n // resolved the entry to an absolute path while the caller passed a\n // relative one (or vice versa).\n const entryAbs = resolvePath(entryPath);\n function isFromEntry(importer: string): boolean {\n return importer === entryAbs || importer === entryPath || importer === '<stdin>';\n }\n return {\n name: 'import-allowlist',\n setup(build) {\n build.onResolve({ filter: /.*/ }, (args) => {\n if (args.kind === 'entry-point') {\n return undefined;\n }\n if (args.path.startsWith('.') || args.path.startsWith('/')) {\n return undefined;\n }\n if (isFromEntry(args.importer) && !isAllowedImport(args.path, allowlist)) {\n collected.add(args.path);\n return {\n path: args.path,\n external: true,\n };\n }\n return undefined;\n });\n },\n };\n}\n\n/**\n * Loads a contract from a TypeScript file and returns it as Contract.\n *\n * **Responsibility: Parsing Only**\n * This function loads and parses a TypeScript contract file. It does NOT normalize the contract.\n * The contract should already be normalized if it was built using the contract builder.\n *\n * Normalization must happen in the contract builder when the contract is created.\n * This function only validates that the contract is JSON-serializable and returns it as-is.\n *\n * @param entryPath - Path to the TypeScript contract file\n * @param options - Optional configuration (import allowlist)\n * @returns The contract as Contract (should already be normalized)\n * @throws structured errors: `CLI.FILE_NOT_FOUND`, `CONTRACT.SOURCE_LOAD_FAILED`,\n * `CONTRACT.SOURCE_IMPORT_DISALLOWED`, `CONTRACT.MODULE_EXPORT_MISSING`, `CONTRACT.EXPORT_INVALID`\n */\nexport async function loadContractFromTs(\n entryPath: string,\n options?: LoadTsContractOptions,\n): Promise<Contract> {\n const allowlist = options?.allowlist ?? DEFAULT_ALLOWLIST;\n\n if (!existsSync(entryPath)) {\n throw new CliStructuredError('CLI.FILE_NOT_FOUND', `Contract file not found: ${entryPath}`, {\n where: { path: entryPath },\n });\n }\n\n const tempFile = join(\n tmpdir(),\n `prisma-next-contract-${Date.now()}-${Math.random().toString(36).slice(2)}.mjs`,\n );\n\n // Disallowed imports are collected by the allowlist resolver plugin itself,\n // which has the `importer` context to distinguish entry-direct imports from\n // transitive imports made inside allowlisted (`@prisma-next/*`) dependencies.\n // The metafile is intentionally not re-walked: it would surface internal\n // `node:*` imports inside framework code as false positives.\n const disallowedFromEntry = new Set<string>();\n\n try {\n const result = await build({\n entryPoints: [entryPath],\n bundle: true,\n format: 'esm',\n platform: 'node',\n target: 'es2022',\n outfile: tempFile,\n write: false,\n metafile: true,\n plugins: [createImportAllowlistPlugin(allowlist, entryPath, disallowedFromEntry)],\n logLevel: 'error',\n });\n\n if (result.errors.length > 0) {\n const errorMessages = result.errors.map((e: { text: string }) => e.text).join('\\n');\n throw contractSourceError(\n 'CONTRACT.SOURCE_LOAD_FAILED',\n `Failed to bundle contract file: ${errorMessages}`,\n { meta: { path: entryPath, stage: 'bundle' } },\n );\n }\n\n if (!result.outputFiles || result.outputFiles.length === 0) {\n throw new InternalError('No output files generated from bundling');\n }\n\n if (disallowedFromEntry.size > 0) {\n throw contractSourceError(\n 'CONTRACT.SOURCE_IMPORT_DISALLOWED',\n `Disallowed imports detected. Only imports matching the allowlist are permitted:\\n Allowlist: ${allowlist.join(', ')}\\n Disallowed imports: ${[...disallowedFromEntry].join(', ')}`,\n { meta: { allowlist: [...allowlist], disallowed: [...disallowedFromEntry] } },\n );\n }\n\n const bundleContent = result.outputFiles[0]?.text;\n if (bundleContent === undefined) {\n throw new InternalError('Bundle content is undefined');\n }\n writeFileSync(tempFile, bundleContent, 'utf-8');\n\n const module = (await import(/* @vite-ignore */ pathToFileURL(tempFile).href)) as {\n default?: unknown;\n contract?: unknown;\n };\n unlinkSync(tempFile);\n\n let contract: unknown;\n\n if (module.default !== undefined) {\n contract = module.default;\n } else if (module.contract !== undefined) {\n contract = module.contract;\n } else {\n throw new CliStructuredError(\n 'CONTRACT.MODULE_EXPORT_MISSING',\n `Contract file must export a contract as default export or named export 'contract'. Found exports: ${Object.keys(module as Record<string, unknown>).join(', ') || 'none'}`,\n { where: { path: entryPath } },\n );\n }\n\n if (typeof contract !== 'object' || contract === null) {\n throw contractSourceError(\n 'CONTRACT.EXPORT_INVALID',\n `Contract export must be an object, got ${typeof contract}`,\n { meta: { path: entryPath, reason: 'not-object' } },\n );\n }\n\n validatePurity(contract, entryPath);\n\n // Blind cast: the loaded module was authored by user code\n // (typically via `defineContract` / a contract builder) and\n // its runtime shape is structurally a `Contract`, but the\n // dynamic import collapses the source typing. The contract\n // structural validation that asserts the shape happens\n // downstream at the `familyInstance.deserializeContract` seam\n // (e.g. in `executeContractEmit`); this helper only checks\n // purity here.\n return contract as unknown as Contract;\n } catch (error) {\n try {\n if (tempFile) {\n unlinkSync(tempFile);\n }\n } catch {\n // Ignore cleanup errors\n }\n\n if (error instanceof Error) {\n throw error;\n }\n throw contractSourceError(\n 'CONTRACT.SOURCE_LOAD_FAILED',\n `Failed to load contract from ${entryPath}: ${String(error)}`,\n { meta: { path: entryPath, stage: 'import' }, cause: error },\n );\n }\n}\n"],"mappings":"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"}
@@ -1,13 +1,13 @@
1
- import { A as formatStyledHeader, F as CliStructuredError, _ as createTerminalUI, ct as errorUnexpected, g as parseGlobalFlagsOrExit, l as setCommandDescriptions, rt as errorRuntime, t as addGlobalOptions, u as setCommandExamples, y as handleResult } from "./command-helpers-CVn3U9Uz.mjs";
1
+ import { A as formatStyledHeader, F as CliStructuredError, _ as createTerminalUI, ct as errorUnexpected, g as parseGlobalFlagsOrExit, l as setCommandDescriptions, rt as errorRuntime, t as addGlobalOptions, u as setCommandExamples, y as handleResult } from "./command-helpers-D-jBl0Qt.mjs";
2
2
  import { Command } from "commander";
3
3
  import { loadConfig } from "@prisma-next/config-loader";
4
4
  import { ifDefined } from "@prisma-next/utils/defined";
5
5
  import { notOk, ok } from "@prisma-next/utils/result";
6
6
  import { relative, resolve } from "pathe";
7
7
  import { readFile, writeFile } from "node:fs/promises";
8
+ import { isStructuredError } from "@prisma-next/utils/structured-error";
8
9
  import { EOL } from "node:os";
9
10
  import { format } from "@prisma-next/psl-parser/format";
10
- import { isStructuredError } from "@prisma-next/utils/structured-error";
11
11
  //#region src/control-api/operations/format.ts
12
12
  function resolveNewline(formatterNewline, eol) {
13
13
  if (formatterNewline !== void 0) return formatterNewline;
@@ -100,4 +100,4 @@ function createFormatCommand() {
100
100
  //#endregion
101
101
  export { createFormatCommand as t };
102
102
 
103
- //# sourceMappingURL=format-cCyDfmRE.mjs.map
103
+ //# sourceMappingURL=format-DI5qVr22.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"format-cCyDfmRE.mjs","names":[],"sources":["../src/control-api/operations/format.ts","../src/commands/format.ts"],"sourcesContent":["import { readFile, writeFile } from 'node:fs/promises';\nimport { EOL } from 'node:os';\nimport { loadConfig } from '@prisma-next/config-loader';\nimport { type FormatOptions, format } from '@prisma-next/psl-parser/format';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { isStructuredError } from '@prisma-next/utils/structured-error';\nimport { CliStructuredError, errorRuntime, errorUnexpected } from '../../utils/cli-errors';\n\nexport interface FormatOperationOptions {\n readonly configPath?: string;\n readonly eol?: string;\n}\n\nexport interface FormatOperationResult {\n readonly formatted: boolean;\n readonly path?: string;\n}\n\nexport function resolveNewline(\n formatterNewline: 'LF' | 'CRLF' | undefined,\n eol: string,\n): 'LF' | 'CRLF' {\n if (formatterNewline !== undefined) {\n return formatterNewline;\n }\n return eol === '\\r\\n' ? 'CRLF' : 'LF';\n}\n\nexport async function executeFormat(\n options: FormatOperationOptions,\n): Promise<Result<FormatOperationResult, CliStructuredError>> {\n const eol = options.eol ?? EOL;\n\n let config: Awaited<ReturnType<typeof loadConfig>>;\n try {\n config = await loadConfig(options.configPath);\n } catch (error) {\n if (CliStructuredError.is(error)) {\n return notOk(error);\n }\n return notOk(errorUnexpected(error instanceof Error ? error.message : String(error)));\n }\n\n const source = config.contract?.source;\n if (source?.format !== 'psl') {\n return ok({ formatted: false });\n }\n\n const inputPath = source.inputs?.[0];\n if (inputPath === undefined) {\n return ok({ formatted: false });\n }\n\n let contents: string;\n try {\n contents = await readFile(inputPath, 'utf-8');\n } catch (error) {\n return notOk(\n errorRuntime('Failed to read contract source file', {\n why: error instanceof Error ? error.message : String(error),\n fix: `Check that ${inputPath} exists and is readable.`,\n }),\n );\n }\n\n const formatOptions: FormatOptions = {\n indent: config.formatter?.indent ?? 2,\n newline: resolveNewline(config.formatter?.newline, eol),\n };\n\n let formatted: string;\n try {\n formatted = format(contents, formatOptions);\n } catch (error) {\n if (isStructuredError(error) && error.code === 'PSL.PARSE_FAILED') {\n return notOk(\n errorRuntime('Cannot format PSL with parse errors', {\n why: error.message,\n fix: 'Fix the parse errors in your schema and try again.',\n meta: { diagnostics: error.meta?.['diagnostics'] },\n }),\n );\n }\n return notOk(errorUnexpected(error instanceof Error ? error.message : String(error)));\n }\n\n try {\n await writeFile(inputPath, formatted, 'utf-8');\n } catch (error) {\n return notOk(\n errorRuntime('Failed to write formatted contract source file', {\n why: error instanceof Error ? error.message : String(error),\n fix: `Check that ${inputPath} is writable.`,\n }),\n );\n }\n\n return ok({ formatted: true, path: inputPath });\n}\n","import { ifDefined } from '@prisma-next/utils/defined';\nimport { Command } from 'commander';\nimport { relative, resolve } from 'pathe';\nimport { executeFormat } from '../control-api/operations/format';\nimport {\n addGlobalOptions,\n setCommandDescriptions,\n setCommandExamples,\n} from '../utils/command-helpers';\nimport { formatStyledHeader } from '../utils/formatters/styled';\nimport type { CommonCommandOptions } from '../utils/global-flags';\nimport { parseGlobalFlagsOrExit } from '../utils/global-flags';\nimport { handleResult } from '../utils/result-handler';\nimport { createTerminalUI } from '../utils/terminal-ui';\n\ninterface FormatCommandOptions extends CommonCommandOptions {\n readonly config?: string;\n}\n\nexport function createFormatCommand(): Command {\n const command = new Command('format');\n setCommandDescriptions(\n command,\n 'Format your PSL contract source',\n 'Formats the Prisma schema (PSL) contract source declared in your config\\n' +\n '(contract.source.inputs[0]) in place. Only runs when contract.source.format\\n' +\n \"is 'psl'; a TypeScript or unset source is left untouched. Indent and newline are\\n\" +\n 'read from the optional formatter config section, defaulting to two spaces and the\\n' +\n 'system newline.',\n );\n setCommandExamples(command, [\n 'prisma-next format',\n 'prisma-next format --config ./custom-config.ts',\n ]);\n addGlobalOptions(command)\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .action(async (options: FormatCommandOptions) => {\n const flags = parseGlobalFlagsOrExit(options);\n const ui = createTerminalUI(flags);\n\n if (!flags.json && !flags.quiet) {\n const displayConfigPath = options.config\n ? relative(process.cwd(), resolve(options.config))\n : 'prisma-next.config.ts';\n ui.stderr(\n formatStyledHeader({\n command: 'format',\n description: 'Format your PSL contract source',\n details: [{ label: 'config', value: displayConfigPath }],\n flags,\n }),\n );\n }\n\n const result = await executeFormat({ ...ifDefined('configPath', options.config) });\n\n const exitCode = handleResult(result, flags, ui, (value) => {\n if (flags.json) {\n ui.output(JSON.stringify(value));\n return;\n }\n if (flags.quiet) {\n return;\n }\n if (value.formatted) {\n ui.success(`Formatted ${relative(process.cwd(), value.path ?? '')}`);\n } else {\n ui.info('Nothing to format (contract source is not PSL).');\n }\n });\n process.exit(exitCode);\n });\n\n return command;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"format-DI5qVr22.mjs","names":[],"sources":["../src/control-api/operations/format.ts","../src/commands/format.ts"],"sourcesContent":["import { readFile, writeFile } from 'node:fs/promises';\nimport { EOL } from 'node:os';\nimport { loadConfig } from '@prisma-next/config-loader';\nimport { type FormatOptions, format } from '@prisma-next/psl-parser/format';\nimport { notOk, ok, type Result } from '@prisma-next/utils/result';\nimport { isStructuredError } from '@prisma-next/utils/structured-error';\nimport { CliStructuredError, errorRuntime, errorUnexpected } from '../../utils/cli-errors';\n\nexport interface FormatOperationOptions {\n readonly configPath?: string;\n readonly eol?: string;\n}\n\nexport interface FormatOperationResult {\n readonly formatted: boolean;\n readonly path?: string;\n}\n\nexport function resolveNewline(\n formatterNewline: 'LF' | 'CRLF' | undefined,\n eol: string,\n): 'LF' | 'CRLF' {\n if (formatterNewline !== undefined) {\n return formatterNewline;\n }\n return eol === '\\r\\n' ? 'CRLF' : 'LF';\n}\n\nexport async function executeFormat(\n options: FormatOperationOptions,\n): Promise<Result<FormatOperationResult, CliStructuredError>> {\n const eol = options.eol ?? EOL;\n\n let config: Awaited<ReturnType<typeof loadConfig>>;\n try {\n config = await loadConfig(options.configPath);\n } catch (error) {\n if (CliStructuredError.is(error)) {\n return notOk(error);\n }\n return notOk(errorUnexpected(error instanceof Error ? error.message : String(error)));\n }\n\n const source = config.contract?.source;\n if (source?.format !== 'psl') {\n return ok({ formatted: false });\n }\n\n const inputPath = source.inputs?.[0];\n if (inputPath === undefined) {\n return ok({ formatted: false });\n }\n\n let contents: string;\n try {\n contents = await readFile(inputPath, 'utf-8');\n } catch (error) {\n return notOk(\n errorRuntime('Failed to read contract source file', {\n why: error instanceof Error ? error.message : String(error),\n fix: `Check that ${inputPath} exists and is readable.`,\n }),\n );\n }\n\n const formatOptions: FormatOptions = {\n indent: config.formatter?.indent ?? 2,\n newline: resolveNewline(config.formatter?.newline, eol),\n };\n\n let formatted: string;\n try {\n formatted = format(contents, formatOptions);\n } catch (error) {\n if (isStructuredError(error) && error.code === 'PSL.PARSE_FAILED') {\n return notOk(\n errorRuntime('Cannot format PSL with parse errors', {\n why: error.message,\n fix: 'Fix the parse errors in your schema and try again.',\n meta: { diagnostics: error.meta?.['diagnostics'] },\n }),\n );\n }\n return notOk(errorUnexpected(error instanceof Error ? error.message : String(error)));\n }\n\n try {\n await writeFile(inputPath, formatted, 'utf-8');\n } catch (error) {\n return notOk(\n errorRuntime('Failed to write formatted contract source file', {\n why: error instanceof Error ? error.message : String(error),\n fix: `Check that ${inputPath} is writable.`,\n }),\n );\n }\n\n return ok({ formatted: true, path: inputPath });\n}\n","import { ifDefined } from '@prisma-next/utils/defined';\nimport { Command } from 'commander';\nimport { relative, resolve } from 'pathe';\nimport { executeFormat } from '../control-api/operations/format';\nimport {\n addGlobalOptions,\n setCommandDescriptions,\n setCommandExamples,\n} from '../utils/command-helpers';\nimport { formatStyledHeader } from '../utils/formatters/styled';\nimport type { CommonCommandOptions } from '../utils/global-flags';\nimport { parseGlobalFlagsOrExit } from '../utils/global-flags';\nimport { handleResult } from '../utils/result-handler';\nimport { createTerminalUI } from '../utils/terminal-ui';\n\ninterface FormatCommandOptions extends CommonCommandOptions {\n readonly config?: string;\n}\n\nexport function createFormatCommand(): Command {\n const command = new Command('format');\n setCommandDescriptions(\n command,\n 'Format your PSL contract source',\n 'Formats the Prisma schema (PSL) contract source declared in your config\\n' +\n '(contract.source.inputs[0]) in place. Only runs when contract.source.format\\n' +\n \"is 'psl'; a TypeScript or unset source is left untouched. Indent and newline are\\n\" +\n 'read from the optional formatter config section, defaulting to two spaces and the\\n' +\n 'system newline.',\n );\n setCommandExamples(command, [\n 'prisma-next format',\n 'prisma-next format --config ./custom-config.ts',\n ]);\n addGlobalOptions(command)\n .option('--config <path>', 'Path to prisma-next.config.ts')\n .action(async (options: FormatCommandOptions) => {\n const flags = parseGlobalFlagsOrExit(options);\n const ui = createTerminalUI(flags);\n\n if (!flags.json && !flags.quiet) {\n const displayConfigPath = options.config\n ? relative(process.cwd(), resolve(options.config))\n : 'prisma-next.config.ts';\n ui.stderr(\n formatStyledHeader({\n command: 'format',\n description: 'Format your PSL contract source',\n details: [{ label: 'config', value: displayConfigPath }],\n flags,\n }),\n );\n }\n\n const result = await executeFormat({ ...ifDefined('configPath', options.config) });\n\n const exitCode = handleResult(result, flags, ui, (value) => {\n if (flags.json) {\n ui.output(JSON.stringify(value));\n return;\n }\n if (flags.quiet) {\n return;\n }\n if (value.formatted) {\n ui.success(`Formatted ${relative(process.cwd(), value.path ?? '')}`);\n } else {\n ui.info('Nothing to format (contract source is not PSL).');\n }\n });\n process.exit(exitCode);\n });\n\n return command;\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { R as errorConfigValidation } from "./command-helpers-CVn3U9Uz.mjs";
1
+ import { R as errorConfigValidation } from "./command-helpers-D-jBl0Qt.mjs";
2
2
  import "@prisma-next/framework-components/components";
3
3
  //#region src/utils/framework-components.ts
4
4
  /**
@@ -55,4 +55,4 @@ function assertFrameworkComponentsCompatible(expectedFamilyId, expectedTargetId,
55
55
  //#endregion
56
56
  export { assertFrameworkComponentsCompatible as t };
57
57
 
58
- //# sourceMappingURL=framework-components-DUN-TYDg.mjs.map
58
+ //# sourceMappingURL=framework-components-C4XACYNB.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"framework-components-DUN-TYDg.mjs","names":[],"sources":["../src/utils/framework-components.ts"],"sourcesContent":["import type { Contract } from '@prisma-next/contract/types';\nimport {\n checkContractComponentRequirements,\n type TargetBoundComponentDescriptor,\n} from '@prisma-next/framework-components/components';\nimport type { ControlStack } from '@prisma-next/framework-components/control';\nimport { errorConfigValidation, errorContractMissingExtensions } from './cli-errors';\n\n/**\n * Asserts that all framework components are compatible with the expected family and target.\n *\n * This function validates that each component in the framework components array:\n * - Has kind 'target', 'adapter', 'extension', or 'driver'\n * - Has familyId matching expectedFamilyId\n * - Has targetId matching expectedTargetId\n *\n * This validation happens at the CLI composition boundary, before passing components\n * to typed planner/runner instances. It fills the gap between runtime validation\n * (via `validateConfig()`) and compile-time type enforcement.\n *\n * @param expectedFamilyId - The expected family ID (e.g., 'sql')\n * @param expectedTargetId - The expected target ID (e.g., 'postgres')\n * @param frameworkComponents - Array of framework components to validate\n * @returns The same array typed as TargetBoundComponentDescriptor\n * @throws CliStructuredError if any component is incompatible\n *\n * @example\n * ```ts\n * const config = await loadConfig();\n * const frameworkComponents = [config.target, config.adapter, ...(config.extensions ?? [])];\n *\n * // Validate and type-narrow components before passing to planner\n * const typedComponents = assertFrameworkComponentsCompatible(\n * config.family.familyId,\n * config.target.targetId,\n * frameworkComponents\n * );\n *\n * const planner = target.migrations.createPlanner(familyInstance);\n * planner.plan({ contract, schema, policy, frameworkComponents: typedComponents });\n * ```\n */\nexport function assertFrameworkComponentsCompatible<\n TFamilyId extends string,\n TTargetId extends string,\n>(\n expectedFamilyId: TFamilyId,\n expectedTargetId: TTargetId,\n frameworkComponents: ReadonlyArray<unknown>,\n): ReadonlyArray<TargetBoundComponentDescriptor<TFamilyId, TTargetId>> {\n for (let i = 0; i < frameworkComponents.length; i++) {\n const component = frameworkComponents[i];\n\n // Check that component is an object\n if (typeof component !== 'object' || component === null) {\n throw errorConfigValidation('frameworkComponents[]', {\n why: `Framework component at index ${i} must be an object`,\n });\n }\n\n const record = component as Record<string, unknown>;\n\n // Check kind\n if (!Object.hasOwn(record, 'kind')) {\n throw errorConfigValidation('frameworkComponents[].kind', {\n why: `Framework component at index ${i} must have 'kind' property`,\n });\n }\n\n const kind = record['kind'];\n if (kind !== 'target' && kind !== 'adapter' && kind !== 'extension' && kind !== 'driver') {\n throw errorConfigValidation('frameworkComponents[].kind', {\n why: `Framework component at index ${i} has invalid kind '${String(kind)}' (must be 'target', 'adapter', 'extension', or 'driver')`,\n });\n }\n\n // Check familyId\n if (!Object.hasOwn(record, 'familyId')) {\n throw errorConfigValidation('frameworkComponents[].familyId', {\n why: `Framework component at index ${i} (kind: ${String(kind)}) must have 'familyId' property`,\n });\n }\n\n const familyId = record['familyId'];\n if (familyId !== expectedFamilyId) {\n throw errorConfigValidation('frameworkComponents[].familyId', {\n why: `Framework component at index ${i} (kind: ${String(kind)}) has familyId '${String(familyId)}' but expected '${expectedFamilyId}'`,\n });\n }\n\n // Check targetId\n if (!Object.hasOwn(record, 'targetId')) {\n throw errorConfigValidation('frameworkComponents[].targetId', {\n why: `Framework component at index ${i} (kind: ${String(kind)}) must have 'targetId' property`,\n });\n }\n\n const targetId = record['targetId'];\n if (targetId !== expectedTargetId) {\n throw errorConfigValidation('frameworkComponents[].targetId', {\n why: `Framework component at index ${i} (kind: ${String(kind)}) has targetId '${String(targetId)}' but expected '${expectedTargetId}'`,\n });\n }\n }\n\n // Type assertion is safe because we've validated all components above\n return frameworkComponents as ReadonlyArray<TargetBoundComponentDescriptor<TFamilyId, TTargetId>>;\n}\n\n/**\n * Validates that a contract is compatible with the configured target, adapter,\n * and extension packs. Throws on family/target mismatches or missing extension packs.\n *\n * This check ensures the emitted contract matches the CLI config before running\n * commands that depend on the contract (e.g., db verify, db sign).\n *\n * @param contract - The contract to validate (must include targetFamily, target, extensions).\n * @param stack - The control plane stack (target, adapter, driver, extensions).\n *\n * @throws {CliStructuredError} errorConfigValidation when contract.targetFamily or contract.target\n * doesn't match the configured family/target.\n * @throws {CliStructuredError} errorContractMissingExtensions when the contract requires\n * extension packs that are not provided in the config (includes all missing packs in error.meta).\n *\n * @example\n * ```ts\n * import { assertContractRequirementsSatisfied } from './framework-components';\n *\n * const config = await loadConfig();\n * const contract = await loadContractJson(config.contract.output);\n * const stack = createControlStack({ family: config.family, target: config.target, adapter: config.adapter, ... });\n *\n * // Throws if contract is incompatible with config\n * assertContractRequirementsSatisfied({ contract, stack });\n * ```\n */\nexport function assertContractRequirementsSatisfied<\n TFamilyId extends string,\n TTargetId extends string,\n>({\n contract,\n stack,\n}: {\n readonly contract: Pick<Contract, 'targetFamily' | 'target' | 'extensions'>;\n readonly stack: ControlStack<TFamilyId, TTargetId>;\n}): void {\n const providedComponentIds = new Set<string>([\n stack.target.id,\n ...(stack.adapter ? [stack.adapter.id] : []),\n ]);\n for (const extension of stack.extensions) {\n providedComponentIds.add(extension.id);\n }\n\n const result = checkContractComponentRequirements({\n contract,\n expectedTargetFamily: stack.target.familyId,\n expectedTargetId: stack.target.targetId,\n providedComponentIds,\n });\n\n if (result.familyMismatch) {\n throw errorConfigValidation('contract.targetFamily', {\n why: `Contract was emitted for family '${result.familyMismatch.actual}' but CLI config is wired to '${result.familyMismatch.expected}'.`,\n });\n }\n\n if (result.targetMismatch) {\n throw errorConfigValidation('contract.target', {\n why: `Contract target '${result.targetMismatch.actual}' does not match CLI target '${result.targetMismatch.expected}'.`,\n });\n }\n\n if (result.missingExtensionPackIds.length > 0) {\n throw errorContractMissingExtensions({\n missingExtensions: result.missingExtensionPackIds,\n providedComponentIds: [...providedComponentIds],\n });\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0CA,SAAgB,oCAId,kBACA,kBACA,qBACqE;CACrE,KAAK,IAAI,IAAI,GAAG,IAAI,oBAAoB,QAAQ,KAAK;EACnD,MAAM,YAAY,oBAAoB;EAGtC,IAAI,OAAO,cAAc,YAAY,cAAc,MACjD,MAAM,sBAAsB,yBAAyB,EACnD,KAAK,gCAAgC,EAAE,oBACzC,CAAC;EAGH,MAAM,SAAS;EAGf,IAAI,CAAC,OAAO,OAAO,QAAQ,MAAM,GAC/B,MAAM,sBAAsB,8BAA8B,EACxD,KAAK,gCAAgC,EAAE,4BACzC,CAAC;EAGH,MAAM,OAAO,OAAO;EACpB,IAAI,SAAS,YAAY,SAAS,aAAa,SAAS,eAAe,SAAS,UAC9E,MAAM,sBAAsB,8BAA8B,EACxD,KAAK,gCAAgC,EAAE,qBAAqB,OAAO,IAAI,EAAE,2DAC3E,CAAC;EAIH,IAAI,CAAC,OAAO,OAAO,QAAQ,UAAU,GACnC,MAAM,sBAAsB,kCAAkC,EAC5D,KAAK,gCAAgC,EAAE,UAAU,OAAO,IAAI,EAAE,iCAChE,CAAC;EAGH,MAAM,WAAW,OAAO;EACxB,IAAI,aAAa,kBACf,MAAM,sBAAsB,kCAAkC,EAC5D,KAAK,gCAAgC,EAAE,UAAU,OAAO,IAAI,EAAE,kBAAkB,OAAO,QAAQ,EAAE,kBAAkB,iBAAiB,GACtI,CAAC;EAIH,IAAI,CAAC,OAAO,OAAO,QAAQ,UAAU,GACnC,MAAM,sBAAsB,kCAAkC,EAC5D,KAAK,gCAAgC,EAAE,UAAU,OAAO,IAAI,EAAE,iCAChE,CAAC;EAGH,MAAM,WAAW,OAAO;EACxB,IAAI,aAAa,kBACf,MAAM,sBAAsB,kCAAkC,EAC5D,KAAK,gCAAgC,EAAE,UAAU,OAAO,IAAI,EAAE,kBAAkB,OAAO,QAAQ,EAAE,kBAAkB,iBAAiB,GACtI,CAAC;CAEL;CAGA,OAAO;AACT"}
1
+ {"version":3,"file":"framework-components-C4XACYNB.mjs","names":[],"sources":["../src/utils/framework-components.ts"],"sourcesContent":["import type { Contract } from '@prisma-next/contract/types';\nimport {\n checkContractComponentRequirements,\n type TargetBoundComponentDescriptor,\n} from '@prisma-next/framework-components/components';\nimport type { ControlStack } from '@prisma-next/framework-components/control';\nimport { errorConfigValidation, errorContractMissingExtensions } from './cli-errors';\n\n/**\n * Asserts that all framework components are compatible with the expected family and target.\n *\n * This function validates that each component in the framework components array:\n * - Has kind 'target', 'adapter', 'extension', or 'driver'\n * - Has familyId matching expectedFamilyId\n * - Has targetId matching expectedTargetId\n *\n * This validation happens at the CLI composition boundary, before passing components\n * to typed planner/runner instances. It fills the gap between runtime validation\n * (via `validateConfig()`) and compile-time type enforcement.\n *\n * @param expectedFamilyId - The expected family ID (e.g., 'sql')\n * @param expectedTargetId - The expected target ID (e.g., 'postgres')\n * @param frameworkComponents - Array of framework components to validate\n * @returns The same array typed as TargetBoundComponentDescriptor\n * @throws CliStructuredError if any component is incompatible\n *\n * @example\n * ```ts\n * const config = await loadConfig();\n * const frameworkComponents = [config.target, config.adapter, ...(config.extensions ?? [])];\n *\n * // Validate and type-narrow components before passing to planner\n * const typedComponents = assertFrameworkComponentsCompatible(\n * config.family.familyId,\n * config.target.targetId,\n * frameworkComponents\n * );\n *\n * const planner = target.migrations.createPlanner(familyInstance);\n * planner.plan({ contract, schema, policy, frameworkComponents: typedComponents });\n * ```\n */\nexport function assertFrameworkComponentsCompatible<\n TFamilyId extends string,\n TTargetId extends string,\n>(\n expectedFamilyId: TFamilyId,\n expectedTargetId: TTargetId,\n frameworkComponents: ReadonlyArray<unknown>,\n): ReadonlyArray<TargetBoundComponentDescriptor<TFamilyId, TTargetId>> {\n for (let i = 0; i < frameworkComponents.length; i++) {\n const component = frameworkComponents[i];\n\n // Check that component is an object\n if (typeof component !== 'object' || component === null) {\n throw errorConfigValidation('frameworkComponents[]', {\n why: `Framework component at index ${i} must be an object`,\n });\n }\n\n const record = component as Record<string, unknown>;\n\n // Check kind\n if (!Object.hasOwn(record, 'kind')) {\n throw errorConfigValidation('frameworkComponents[].kind', {\n why: `Framework component at index ${i} must have 'kind' property`,\n });\n }\n\n const kind = record['kind'];\n if (kind !== 'target' && kind !== 'adapter' && kind !== 'extension' && kind !== 'driver') {\n throw errorConfigValidation('frameworkComponents[].kind', {\n why: `Framework component at index ${i} has invalid kind '${String(kind)}' (must be 'target', 'adapter', 'extension', or 'driver')`,\n });\n }\n\n // Check familyId\n if (!Object.hasOwn(record, 'familyId')) {\n throw errorConfigValidation('frameworkComponents[].familyId', {\n why: `Framework component at index ${i} (kind: ${String(kind)}) must have 'familyId' property`,\n });\n }\n\n const familyId = record['familyId'];\n if (familyId !== expectedFamilyId) {\n throw errorConfigValidation('frameworkComponents[].familyId', {\n why: `Framework component at index ${i} (kind: ${String(kind)}) has familyId '${String(familyId)}' but expected '${expectedFamilyId}'`,\n });\n }\n\n // Check targetId\n if (!Object.hasOwn(record, 'targetId')) {\n throw errorConfigValidation('frameworkComponents[].targetId', {\n why: `Framework component at index ${i} (kind: ${String(kind)}) must have 'targetId' property`,\n });\n }\n\n const targetId = record['targetId'];\n if (targetId !== expectedTargetId) {\n throw errorConfigValidation('frameworkComponents[].targetId', {\n why: `Framework component at index ${i} (kind: ${String(kind)}) has targetId '${String(targetId)}' but expected '${expectedTargetId}'`,\n });\n }\n }\n\n // Type assertion is safe because we've validated all components above\n return frameworkComponents as ReadonlyArray<TargetBoundComponentDescriptor<TFamilyId, TTargetId>>;\n}\n\n/**\n * Validates that a contract is compatible with the configured target, adapter,\n * and extension packs. Throws on family/target mismatches or missing extension packs.\n *\n * This check ensures the emitted contract matches the CLI config before running\n * commands that depend on the contract (e.g., db verify, db sign).\n *\n * @param contract - The contract to validate (must include targetFamily, target, extensions).\n * @param stack - The control plane stack (target, adapter, driver, extensions).\n *\n * @throws {CliStructuredError} errorConfigValidation when contract.targetFamily or contract.target\n * doesn't match the configured family/target.\n * @throws {CliStructuredError} errorContractMissingExtensions when the contract requires\n * extension packs that are not provided in the config (includes all missing packs in error.meta).\n *\n * @example\n * ```ts\n * import { assertContractRequirementsSatisfied } from './framework-components';\n *\n * const config = await loadConfig();\n * const contract = await loadContractJson(config.contract.output);\n * const stack = createControlStack({ family: config.family, target: config.target, adapter: config.adapter, ... });\n *\n * // Throws if contract is incompatible with config\n * assertContractRequirementsSatisfied({ contract, stack });\n * ```\n */\nexport function assertContractRequirementsSatisfied<\n TFamilyId extends string,\n TTargetId extends string,\n>({\n contract,\n stack,\n}: {\n readonly contract: Pick<Contract, 'targetFamily' | 'target' | 'extensions'>;\n readonly stack: ControlStack<TFamilyId, TTargetId>;\n}): void {\n const providedComponentIds = new Set<string>([\n stack.target.id,\n ...(stack.adapter ? [stack.adapter.id] : []),\n ]);\n for (const extension of stack.extensions) {\n providedComponentIds.add(extension.id);\n }\n\n const result = checkContractComponentRequirements({\n contract,\n expectedTargetFamily: stack.target.familyId,\n expectedTargetId: stack.target.targetId,\n providedComponentIds,\n });\n\n if (result.familyMismatch) {\n throw errorConfigValidation('contract.targetFamily', {\n why: `Contract was emitted for family '${result.familyMismatch.actual}' but CLI config is wired to '${result.familyMismatch.expected}'.`,\n });\n }\n\n if (result.targetMismatch) {\n throw errorConfigValidation('contract.target', {\n why: `Contract target '${result.targetMismatch.actual}' does not match CLI target '${result.targetMismatch.expected}'.`,\n });\n }\n\n if (result.missingExtensionPackIds.length > 0) {\n throw errorContractMissingExtensions({\n missingExtensions: result.missingExtensionPackIds,\n providedComponentIds: [...providedComponentIds],\n });\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0CA,SAAgB,oCAId,kBACA,kBACA,qBACqE;CACrE,KAAK,IAAI,IAAI,GAAG,IAAI,oBAAoB,QAAQ,KAAK;EACnD,MAAM,YAAY,oBAAoB;EAGtC,IAAI,OAAO,cAAc,YAAY,cAAc,MACjD,MAAM,sBAAsB,yBAAyB,EACnD,KAAK,gCAAgC,EAAE,oBACzC,CAAC;EAGH,MAAM,SAAS;EAGf,IAAI,CAAC,OAAO,OAAO,QAAQ,MAAM,GAC/B,MAAM,sBAAsB,8BAA8B,EACxD,KAAK,gCAAgC,EAAE,4BACzC,CAAC;EAGH,MAAM,OAAO,OAAO;EACpB,IAAI,SAAS,YAAY,SAAS,aAAa,SAAS,eAAe,SAAS,UAC9E,MAAM,sBAAsB,8BAA8B,EACxD,KAAK,gCAAgC,EAAE,qBAAqB,OAAO,IAAI,EAAE,2DAC3E,CAAC;EAIH,IAAI,CAAC,OAAO,OAAO,QAAQ,UAAU,GACnC,MAAM,sBAAsB,kCAAkC,EAC5D,KAAK,gCAAgC,EAAE,UAAU,OAAO,IAAI,EAAE,iCAChE,CAAC;EAGH,MAAM,WAAW,OAAO;EACxB,IAAI,aAAa,kBACf,MAAM,sBAAsB,kCAAkC,EAC5D,KAAK,gCAAgC,EAAE,UAAU,OAAO,IAAI,EAAE,kBAAkB,OAAO,QAAQ,EAAE,kBAAkB,iBAAiB,GACtI,CAAC;EAIH,IAAI,CAAC,OAAO,OAAO,QAAQ,UAAU,GACnC,MAAM,sBAAsB,kCAAkC,EAC5D,KAAK,gCAAgC,EAAE,UAAU,OAAO,IAAI,EAAE,iCAChE,CAAC;EAGH,MAAM,WAAW,OAAO;EACxB,IAAI,aAAa,kBACf,MAAM,sBAAsB,kCAAkC,EAC5D,KAAK,gCAAgC,EAAE,UAAU,OAAO,IAAI,EAAE,kBAAkB,OAAO,QAAQ,EAAE,kBAAkB,iBAAiB,GACtI,CAAC;CAEL;CAGA,OAAO;AACT"}
@@ -1,11 +1,13 @@
1
- import { F as CliStructuredError, _ as createTerminalUI, b as formatErrorJson, x as formatErrorOutput } from "./command-helpers-CVn3U9Uz.mjs";
1
+ import { F as CliStructuredError$1, _ as createTerminalUI, b as formatErrorJson, x as formatErrorOutput } from "./command-helpers-D-jBl0Qt.mjs";
2
2
  import { a as starterSchema, c as version, i as schemaSample, n as dbFile, o as targetLabel, r as defaultSchemaPath, s as targetPackageName, t as configFile } from "./cli.mjs";
3
3
  import { i as renderInitOutro, n as buildNextSteps, r as formatInitJson, t as InitOutputSchema } from "./output-DWNYqZGc.mjs";
4
4
  import { createRequire } from "node:module";
5
+ import { CliStructuredError } from "@prisma-next/errors/control";
5
6
  import { basename, dirname, extname, isAbsolute, join, normalize } from "pathe";
6
7
  import { blindCast } from "@prisma-next/utils/casts";
7
8
  import * as clack from "@clack/prompts";
8
9
  import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
10
+ import { InternalError } from "@prisma-next/utils/internal-error";
9
11
  import { execFile } from "node:child_process";
10
12
  import { promisify } from "node:util";
11
13
  import { detect, getUserAgent } from "package-manager-detector/detect";
@@ -182,7 +184,7 @@ function stripQuotes(value) {
182
184
  * the user was never given the choice — `--force` is the contract.
183
185
  */
184
186
  function errorInitReinitNeedsForce() {
185
- return new CliStructuredError("CLI.INIT_REINIT_NEEDS_FORCE", "Project is already initialized", {
187
+ return new CliStructuredError$1("CLI.INIT_REINIT_NEEDS_FORCE", "Project is already initialized", {
186
188
  why: "A `prisma-next.config.ts` already exists in this directory. Re-running `init` would overwrite the scaffolded files; in non-interactive mode `init` will not do that without `--force`.",
187
189
  fix: "Pass `--force` to overwrite the existing scaffold, or run `init` interactively to confirm.",
188
190
  docsUrl: "https://prisma-next.dev/docs/cli/init"
@@ -207,7 +209,7 @@ function errorInitMissingFlags(options) {
207
209
  default: return `--${flag} <value>`;
208
210
  }
209
211
  }).join(" ");
210
- return new CliStructuredError("CLI.INIT_MISSING_FLAGS", "Missing required flags", {
212
+ return new CliStructuredError$1("CLI.INIT_MISSING_FLAGS", "Missing required flags", {
211
213
  why: `${options.why} Missing required flag(s): ${flagList}.`,
212
214
  fix: `Re-run with the missing flag(s) supplied, e.g. \`prisma-next init --yes ${fixList}\`. Use \`prisma-next init --help\` to see every flag.`,
213
215
  docsUrl: "https://prisma-next.dev/docs/cli/init",
@@ -219,7 +221,7 @@ function errorInitMissingFlags(options) {
219
221
  * allowed values in `meta` for machine-readable consumption.
220
222
  */
221
223
  function errorInitInvalidFlagValue(options) {
222
- return new CliStructuredError("CLI.INIT_INVALID_FLAG_VALUE", `Invalid value for --${options.flag}`, {
224
+ return new CliStructuredError$1("CLI.INIT_INVALID_FLAG_VALUE", `Invalid value for --${options.flag}`, {
223
225
  why: `\`--${options.flag} ${options.value}\` is not one of: ${options.allowed.join(", ")}.`,
224
226
  fix: `Use one of: ${options.allowed.map((v) => `--${options.flag} ${v}`).join(", ")}.`,
225
227
  docsUrl: "https://prisma-next.dev/docs/cli/init",
@@ -237,7 +239,7 @@ function errorInitInvalidFlagValue(options) {
237
239
  */
238
240
  function errorInitAuthoringSchemaPathMismatch(options) {
239
241
  const expectedAuthoring = options.expectedExtension === ".ts" ? "typescript" : "psl";
240
- return new CliStructuredError("CLI.INIT_AUTHORING_SCHEMA_PATH_MISMATCH", "Authoring and schema path do not match", {
242
+ return new CliStructuredError$1("CLI.INIT_AUTHORING_SCHEMA_PATH_MISMATCH", "Authoring and schema path do not match", {
241
243
  why: `\`--authoring ${options.authoring}\` requires a schema file ending in ${options.expectedExtension}, but \`--schema-path ${options.schemaPath}\` ends in ${options.actualExtension}.`,
242
244
  fix: `Use a matching pair, for example \`--authoring ${expectedAuthoring} --schema-path <path>${options.expectedExtension}\`, or change \`--authoring\` to match the path you supplied. You can also omit \`--schema-path\` to use the default for the chosen authoring.`,
243
245
  docsUrl: "https://prisma-next.dev/docs/cli/init",
@@ -257,7 +259,7 @@ function errorInitAuthoringSchemaPathMismatch(options) {
257
259
  * 3 (USER_ABORTED).
258
260
  */
259
261
  function errorInitUserAborted() {
260
- return new CliStructuredError("CLI.INIT_USER_ABORTED", "Init cancelled", {
262
+ return new CliStructuredError$1("CLI.INIT_USER_ABORTED", "Init cancelled", {
261
263
  why: "The interactive prompt was cancelled before all required inputs were supplied. No files were modified.",
262
264
  fix: "Re-run `prisma-next init` and complete the prompts, or pass the required inputs as flags (see `--help`) for a non-interactive run.",
263
265
  severity: "info"
@@ -272,7 +274,7 @@ function errorInitUserAborted() {
272
274
  * mode is supposed to prevent.
273
275
  */
274
276
  function errorInitStrictProbeWithoutProbe() {
275
- return new CliStructuredError("CLI.INIT_STRICT_PROBE_WITHOUT_PROBE", "`--strict-probe` requires `--probe-db`", {
277
+ return new CliStructuredError$1("CLI.INIT_STRICT_PROBE_WITHOUT_PROBE", "`--strict-probe` requires `--probe-db`", {
276
278
  why: "`--strict-probe` only changes how a *failed* probe is reported; without `--probe-db` no probe is attempted in the first place. (`init` is offline-by-default — it never opens a connection to your database without explicit consent.)",
277
279
  fix: "Add `--probe-db` to opt in to the probe, or drop `--strict-probe` if you do not need the version check.",
278
280
  docsUrl: "https://prisma-next.dev/docs/cli/init"
@@ -287,7 +289,7 @@ function errorInitStrictProbeWithoutProbe() {
287
289
  */
288
290
  function errorInitInstallFailed(options) {
289
291
  const trimmed = options.stderrLines.map((s) => s.trim()).filter(Boolean);
290
- return new CliStructuredError("CLI.INIT_INSTALL_FAILED", "Failed to install dependencies", {
292
+ return new CliStructuredError$1("CLI.INIT_INSTALL_FAILED", "Failed to install dependencies", {
291
293
  why: trimmed.length === 0 ? "The package manager exited with an error and no recoverable fallback applied." : `The package manager exited with: ${trimmed[0]}`,
292
294
  fix: `Install manually:\n ${options.addCommand}\n ${options.addDevCommand}\nThen run \`${options.emitCommand}\` to emit the contract.`,
293
295
  docsUrl: "https://prisma-next.dev/docs/cli/init",
@@ -309,7 +311,7 @@ function errorInitInstallFailed(options) {
309
311
  * and re-run.
310
312
  */
311
313
  function errorInitInvalidManifest(options) {
312
- return new CliStructuredError("CLI.INIT_INVALID_MANIFEST", `Failed to parse ${options.path}`, {
314
+ return new CliStructuredError$1("CLI.INIT_INVALID_MANIFEST", `Failed to parse ${options.path}`, {
313
315
  why: `\`${options.path}\` is not valid JSON: ${options.cause}`,
314
316
  fix: `Fix the JSON syntax in \`${options.path}\` (a missing comma or unbalanced brace is the most common cause), then re-run \`prisma-next init\`.`,
315
317
  docsUrl: "https://prisma-next.dev/docs/cli/init",
@@ -334,7 +336,7 @@ function errorInitInvalidManifest(options) {
334
336
  * re-run.
335
337
  */
336
338
  function errorInitInvalidTsconfig(options) {
337
- return new CliStructuredError("CLI.INIT_INVALID_TSCONFIG", `Failed to parse ${options.path}`, {
339
+ return new CliStructuredError$1("CLI.INIT_INVALID_TSCONFIG", `Failed to parse ${options.path}`, {
338
340
  why: `\`${options.path}\` is not valid JSON or JSONC: ${options.cause}`,
339
341
  fix: `Fix the syntax in \`${options.path}\` and re-run \`prisma-next init\`. \`init\` accepts JSONC (comments and trailing commas) but cannot recover from unbalanced braces or missing commas.`,
340
342
  docsUrl: "https://prisma-next.dev/docs/cli/init",
@@ -359,7 +361,7 @@ function errorInitInvalidTsconfig(options) {
359
361
  * carries `filesWritten` so a follow-up agent can resume manually.
360
362
  */
361
363
  function errorInitProbeFailed(options) {
362
- return new CliStructuredError("CLI.INIT_PROBE_FAILED", "Database probe failed", {
364
+ return new CliStructuredError$1("CLI.INIT_PROBE_FAILED", "Database probe failed", {
363
365
  why: `\`--probe-db\` could not complete and \`--strict-probe\` was set: ${options.cause}`,
364
366
  fix: "Confirm `DATABASE_URL` points at a reachable server, or drop `--strict-probe` to treat probe failures as warnings.",
365
367
  docsUrl: "https://prisma-next.dev/docs/cli/init",
@@ -376,7 +378,7 @@ function errorInitProbeFailed(options) {
376
378
  * `5 = EMIT_FAILED`.
377
379
  */
378
380
  function errorInitEmitFailed(options) {
379
- return new CliStructuredError("CLI.INIT_EMIT_FAILED", "Failed to emit contract", {
381
+ return new CliStructuredError$1("CLI.INIT_EMIT_FAILED", "Failed to emit contract", {
380
382
  why: `\`prisma-next contract emit\` failed: ${options.cause}`,
381
383
  fix: `Inspect your contract file, fix the underlying issue, then re-run \`${options.emitCommand}\`. Pass \`-v\` for the full error envelope.`,
382
384
  docsUrl: "https://prisma-next.dev/docs/cli/contract-emit",
@@ -398,7 +400,7 @@ function errorInitEmitFailed(options) {
398
400
  * semantics. Maps to exit code `6 = SKILL_INSTALL_FAILED`.
399
401
  */
400
402
  function errorInitSkillInstallFailed(options) {
401
- return new CliStructuredError("CLI.INIT_SKILL_INSTALL_FAILED", "Failed to install Prisma Next skills", {
403
+ return new CliStructuredError$1("CLI.INIT_SKILL_INSTALL_FAILED", "Failed to install Prisma Next skills", {
402
404
  why: `\`${options.skillInstallCommand}\` exited with an error: ${options.cause}`,
403
405
  fix: `Either:
404
406
  - Re-run \`prisma-next init --no-skill${options.filesWritten.length > 0 ? " --force" : ""}\` to skip the skill install for this run, or\n - Fix the underlying issue (network, npm registry, \`npx skills\` on PATH) and install manually:\n ${options.skillInstallCommand}`,
@@ -1008,7 +1010,7 @@ async function defaultProbePostgres(databaseUrl, baseDir, overrides) {
1008
1010
  */
1009
1011
  function parsePostgresVersion(versionString) {
1010
1012
  const match = versionString.match(/PostgreSQL\s+(\d+(?:\.\d+)?)/i);
1011
- if (match === null || match[1] === void 0) throw new Error(`Could not parse PostgreSQL version from \`${versionString}\``);
1013
+ if (match === null || match[1] === void 0) throw new CliStructuredError("CLI.INIT_PROBE_FAILED", `Could not parse PostgreSQL version from \`${versionString}\``);
1012
1014
  return match[1];
1013
1015
  }
1014
1016
  async function defaultProbeMongo(databaseUrl, baseDir, overrides) {
@@ -1017,7 +1019,7 @@ async function defaultProbeMongo(databaseUrl, baseDir, overrides) {
1017
1019
  try {
1018
1020
  const buildInfo = await client.db().admin().command({ buildInfo: 1 });
1019
1021
  const versionString = String(buildInfo.version ?? "");
1020
- if (versionString.length === 0) throw new Error("buildInfo did not include a `version` field");
1022
+ if (versionString.length === 0) throw new CliStructuredError("CLI.INIT_PROBE_FAILED", "buildInfo did not include a `version` field");
1021
1023
  return { serverVersion: versionString };
1022
1024
  } finally {
1023
1025
  await client.close().catch(() => void 0);
@@ -1378,7 +1380,7 @@ function renderTemplate(templateFile, variableNames, vars) {
1378
1380
  let result = readFileSync(join(import.meta.dirname, templateFile), "utf-8");
1379
1381
  for (const key of variableNames) {
1380
1382
  const value = vars[key];
1381
- if (value === void 0) throw new Error(`Template variable '${key}' is not defined`);
1383
+ if (value === void 0) throw new InternalError(`Template variable '${key}' is not defined`);
1382
1384
  result = result.replaceAll(`{{${key}}}`, value);
1383
1385
  }
1384
1386
  return result;
@@ -1648,7 +1650,7 @@ async function runInit(baseDir, runOptions) {
1648
1650
  canPrompt
1649
1651
  });
1650
1652
  } catch (error) {
1651
- if (CliStructuredError.is(error)) return emitError(ui, flags, error);
1653
+ if (CliStructuredError$1.is(error)) return emitError(ui, flags, error);
1652
1654
  throw error;
1653
1655
  }
1654
1656
  const pm = await detectPackageManager(baseDir);
@@ -1798,7 +1800,7 @@ async function runInit(baseDir, runOptions) {
1798
1800
  hasTypesNode: parsedPackageJson !== null ? hasDirectDep(parsedPackageJson, "@types/node") : false
1799
1801
  });
1800
1802
  } catch (error) {
1801
- if (CliStructuredError.is(error)) return emitError(ui, flags, error);
1803
+ if (CliStructuredError$1.is(error)) return emitError(ui, flags, error);
1802
1804
  throw error;
1803
1805
  }
1804
1806
  warnings.push(...install.warnings);
@@ -1812,7 +1814,7 @@ async function runInit(baseDir, runOptions) {
1812
1814
  });
1813
1815
  contractEmitted = true;
1814
1816
  } catch (error) {
1815
- if (CliStructuredError.is(error)) return emitError(ui, flags, error);
1817
+ if (CliStructuredError$1.is(error)) return emitError(ui, flags, error);
1816
1818
  throw error;
1817
1819
  }
1818
1820
  if (inputs.probeDb) {
@@ -1849,7 +1851,7 @@ async function runInit(baseDir, runOptions) {
1849
1851
  skillRegistered = true;
1850
1852
  } catch (error) {
1851
1853
  spinner.stop("Agent-skill install failed");
1852
- if (CliStructuredError.is(error)) return emitError(ui, flags, error);
1854
+ if (CliStructuredError$1.is(error)) return emitError(ui, flags, error);
1853
1855
  throw error;
1854
1856
  }
1855
1857
  }
@@ -1876,7 +1878,7 @@ async function runInit(baseDir, runOptions) {
1876
1878
  warnings
1877
1879
  };
1878
1880
  const validated = InitOutputSchema(output);
1879
- if (validated instanceof Error || validated.problems !== void 0) return emitError(ui, flags, new CliStructuredError("CLI.INIT_INVALID_OUTPUT_DOCUMENT", "Init produced an invalid output document", {
1881
+ if (validated instanceof Error || validated.problems !== void 0) return emitError(ui, flags, new CliStructuredError$1("CLI.INIT_INVALID_OUTPUT_DOCUMENT", "Init produced an invalid output document", {
1880
1882
  why: `The success document failed schema validation: ${String(validated)}`,
1881
1883
  fix: "This is a bug in prisma-next. Please report it with the full `-v` output.",
1882
1884
  docsUrl: "https://prisma-next.dev/docs/cli/init"
@@ -2148,7 +2150,7 @@ async function runEmit(ctx) {
2148
2150
  const spinner = ctx.ui.spinner();
2149
2151
  spinner.start("Emitting contract...");
2150
2152
  try {
2151
- const { executeContractEmit } = await import("./contract-emit-CfIbTnsR.mjs").then((n) => n.t);
2153
+ const { executeContractEmit } = await import("./contract-emit-hVdlaF2U.mjs").then((n) => n.t);
2152
2154
  await executeContractEmit({ configPath: join(ctx.baseDir, "prisma-next.config.ts") });
2153
2155
  spinner.stop("Contract emitted");
2154
2156
  } catch (err) {
@@ -2201,4 +2203,4 @@ function sanitisePackageName(raw) {
2201
2203
  //#endregion
2202
2204
  export { runInit };
2203
2205
 
2204
- //# sourceMappingURL=init-C9U3ffHH.mjs.map
2206
+ //# sourceMappingURL=init-ClrRkbwd.mjs.map