@prisma-next/core-control-plane 0.3.0-dev.131 → 0.3.0-dev.133

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.
@@ -9,7 +9,6 @@ type CanonicalContractInput = {
9
9
  target: string;
10
10
  roots?: Record<string, string>;
11
11
  models: Record<string, unknown>;
12
- relations?: Record<string, unknown>;
13
12
  storage: Record<string, unknown>;
14
13
  execution?: Record<string, unknown>;
15
14
  extensionPacks: Record<string, unknown>;
@@ -1 +1 @@
1
- {"version":3,"file":"emission.d.mts","names":[],"sources":["../src/emission/canonicalization.ts","../src/emission/types.ts","../src/emission/emit.ts","../src/emission/hashing.ts"],"sourcesContent":[],"mappings":";;;;;KAqBY,sBAAA;;;;UAIF;EAJE,MAAA,EAKF,MALE,CAAA,MAAA,EAAA,OAAsB,CAAA;EAIxB,SAAA,CAAA,EAEI,MAFJ,CAAA,MAAA,EAAA,OAAA,CAAA;EACA,OAAA,EAEC,MAFD,CAAA,MAAA,EAAA,OAAA,CAAA;EACI,SAAA,CAAA,EAEA,MAFA,CAAA,MAAA,EAAA,OAAA,CAAA;EACH,cAAA,EAEO,MAFP,CAAA,MAAA,EAAA,OAAA,CAAA;EACG,YAAA,EAEE,MAFF,CAAA,MAAA,EAEiB,MAFjB,CAAA,MAAA,EAAA,OAAA,CAAA,CAAA;EACI,IAAA,EAEV,MAFU,CAAA,MAAA,EAAA,OAAA,CAAA;EACa,WAAA,CAAA,EAAA,MAAA;EAAf,aAAA,CAAA,EAAA,MAAA;EACR,WAAA,CAAA,EAAA,MAAA;CAAM;AA2PE,iBAAA,oBAAA,CAAyB,EAAA,EAAA,sBAAsB,CAAA,EAAA,MAAA;;;UCxR9C,WAAA;;+BAEc;EDgBnB,SAAA,gBAAsB,CAAA,ECfJ,aDeI,CCfU,eDeV,CAAA;EAIxB,SAAA,oBAAA,CAAA,EClBwB,aDkBxB,CClBsC,eDkBtC,CAAA;EACA,SAAA,YAAA,CAAA,EClBgB,aDkBhB,CAAA,MAAA,CAAA;EACI;;;;EAIiB,SAAA,sBAAA,CAAA,EClBK,GDkBL,CAAA,MAAA,EClBiB,eDkBjB,CAAA;EAAf;;;AA4PhB;sCCzQsC,cAAc;;;AAfpD;;EAG4C,SAAA,yBAAA,CAAA,EAiBL,aAjBK,CAiBS,eAjBT,CAAA;;AACI,UAmB/B,UAAA,CAnB+B;EAAd,SAAA,YAAA,EAAA,MAAA;EACR,SAAA,WAAA,EAAA,MAAA;EAKsB,SAAA,WAAA,EAAA,MAAA;EAAZ,SAAA,aAAA,CAAA,EAAA,MAAA;EAKgB,SAAA,WAAA,EAAA,MAAA;;;;iBC8H9B,IAAA,KAChB,qBACK,2BACK,mBACb,QAAQ;;;iBCzIK,kBAAA,WAA6B;iBAgB7B,kBAAA,WAA6B;iBAgB7B,oBAAA,WAA+B"}
1
+ {"version":3,"file":"emission.d.mts","names":[],"sources":["../src/emission/canonicalization.ts","../src/emission/types.ts","../src/emission/emit.ts","../src/emission/hashing.ts"],"sourcesContent":[],"mappings":";;;;;KAoBY,sBAAA;;;;UAIF;EAJE,MAAA,EAKF,MALE,CAAA,MAAA,EAAA,OAAsB,CAAA;EAIxB,OAAA,EAEC,MAFD,CAAA,MAAA,EAAA,OAAA,CAAA;EACA,SAAA,CAAA,EAEI,MAFJ,CAAA,MAAA,EAAA,OAAA,CAAA;EACC,cAAA,EAEO,MAFP,CAAA,MAAA,EAAA,OAAA,CAAA;EACG,YAAA,EAEE,MAFF,CAAA,MAAA,EAEiB,MAFjB,CAAA,MAAA,EAAA,OAAA,CAAA,CAAA;EACI,IAAA,EAEV,MAFU,CAAA,MAAA,EAAA,OAAA,CAAA;EACa,WAAA,CAAA,EAAA,MAAA;EAAf,aAAA,CAAA,EAAA,MAAA;EACR,WAAA,CAAA,EAAA,MAAA;CAAM;AAwPE,iBAAA,oBAAA,CAAyB,EAAA,EAAA,sBAAsB,CAAA,EAAA,MAAA;;;UCnR9C,WAAA;;+BAEc;EDenB,SAAA,gBAAsB,CAAA,ECdJ,aDcI,CCdU,eDcV,CAAA;EAIxB,SAAA,oBAAA,CAAA,ECjBwB,aDiBxB,CCjBsC,eDiBtC,CAAA;EACA,SAAA,YAAA,CAAA,ECjBgB,aDiBhB,CAAA,MAAA,CAAA;EACC;;;;EAGK,SAAA,sBAAA,CAAA,EChBoB,GDgBpB,CAAA,MAAA,EChBgC,eDgBhC,CAAA;EACR;;AAwPR;;sCCpQsC,cAAc;;AAfpD;;;EAG8B,SAAA,yBAAA,CAAA,EAiBS,aAjBT,CAiBuB,eAjBvB,CAAA;;AACI,UAmBjB,UAAA,CAnBiB;EACR,SAAA,YAAA,EAAA,MAAA;EAKsB,SAAA,WAAA,EAAA,MAAA;EAAZ,SAAA,WAAA,EAAA,MAAA;EAKgB,SAAA,aAAA,CAAA,EAAA,MAAA;EAAd,SAAA,WAAA,EAAA,MAAA;;;;iBCgFhB,IAAA,KAChB,qBACK,2BACK,mBACb,QAAQ;;;iBC3FK,kBAAA,WAA6B;iBAe7B,kBAAA,WAA6B;iBAe7B,oBAAA,WAA+B"}
package/dist/emission.mjs CHANGED
@@ -16,7 +16,6 @@ const TOP_LEVEL_ORDER = [
16
16
  "profileHash",
17
17
  "roots",
18
18
  "models",
19
- "relations",
20
19
  "storage",
21
20
  "execution",
22
21
  "capabilities",
@@ -47,7 +46,6 @@ function omitDefaults(obj, path) {
47
46
  const isRequiredTables = isArrayEqual(currentPath, ["storage", "tables"]);
48
47
  const isRequiredCollections = isArrayEqual(currentPath, ["storage", "collections"]);
49
48
  const isCollectionEntry = currentPath.length === 3 && isArrayEqual([currentPath[0], currentPath[1]], ["storage", "collections"]);
50
- const isRequiredRelations = isArrayEqual(currentPath, ["relations"]);
51
49
  const isRequiredRoots = isArrayEqual(currentPath, ["roots"]);
52
50
  const isRequiredExtensionPacks = isArrayEqual(currentPath, ["extensionPacks"]);
53
51
  const isRequiredCapabilities = isArrayEqual(currentPath, ["capabilities"]);
@@ -87,7 +85,7 @@ function omitDefaults(obj, path) {
87
85
  "foreignKeys"
88
86
  ]);
89
87
  const isFkBooleanField = currentPath.length === 5 && currentPath[0] === "storage" && currentPath[1] === "tables" && currentPath[3] === "foreignKeys" && (key === "constraint" || key === "index");
90
- if (!isRequiredModels && !isRequiredTables && !isRequiredCollections && !isCollectionEntry && !isRequiredRelations && !isRequiredRoots && !isRequiredExtensionPacks && !isRequiredCapabilities && !isRequiredMeta && !isRequiredExecutionDefaults && !isExtensionNamespace && !isModelRelations && !isTableUniques && !isTableIndexes && !isTableForeignKeys && !isFkBooleanField) continue;
88
+ if (!isRequiredModels && !isRequiredTables && !isRequiredCollections && !isCollectionEntry && !isRequiredRoots && !isRequiredExtensionPacks && !isRequiredCapabilities && !isRequiredMeta && !isRequiredExecutionDefaults && !isExtensionNamespace && !isModelRelations && !isTableUniques && !isTableIndexes && !isTableForeignKeys && !isFkBooleanField) continue;
91
89
  }
92
90
  result[key] = omitDefaults(value, currentPath);
93
91
  }
@@ -149,7 +147,6 @@ function canonicalizeContract(ir) {
149
147
  target: ir.target,
150
148
  ...ifDefined("roots", ir.roots),
151
149
  models: ir.models,
152
- ...ifDefined("relations", ir.relations),
153
150
  storage: ir.storage,
154
151
  ...ifDefined("execution", ir.execution),
155
152
  extensionPacks: ir.extensionPacks,
@@ -180,7 +177,6 @@ function computeStorageHash(contract) {
180
177
  target: contract.target,
181
178
  storage: contract.storage,
182
179
  models: {},
183
- relations: {},
184
180
  extensionPacks: {},
185
181
  capabilities: {},
186
182
  meta: {}
@@ -192,7 +188,6 @@ function computeProfileHash(contract) {
192
188
  targetFamily: contract.targetFamily,
193
189
  target: contract.target,
194
190
  models: {},
195
- relations: {},
196
191
  storage: {},
197
192
  extensionPacks: {},
198
193
  capabilities: contract.capabilities,
@@ -205,7 +200,6 @@ function computeExecutionHash(contract) {
205
200
  targetFamily: contract.targetFamily,
206
201
  target: contract.target,
207
202
  models: {},
208
- relations: {},
209
203
  storage: {},
210
204
  extensionPacks: {},
211
205
  capabilities: {},
@@ -225,44 +219,15 @@ function stripStrategyFromRelations(relations) {
225
219
  }
226
220
  return result;
227
221
  }
228
- function toDomainModel(models) {
222
+ function stripRelationStrategies(models) {
229
223
  const result = {};
230
224
  for (const [modelName, modelUnknown] of Object.entries(models)) {
231
225
  const model = modelUnknown;
232
226
  const relations = model["relations"];
233
227
  const cleanedRelations = stripStrategyFromRelations(relations);
234
- const fields = model["fields"];
235
- if (!fields) {
236
- result[modelName] = {
237
- ...model,
238
- ...cleanedRelations !== void 0 ? { relations: cleanedRelations } : {}
239
- };
240
- continue;
241
- }
242
- if (!Object.values(fields).some((f) => f["codecId"] !== void 0)) {
243
- result[modelName] = {
244
- ...model,
245
- ...cleanedRelations !== void 0 ? { relations: cleanedRelations } : {}
246
- };
247
- continue;
248
- }
249
- const storage = model["storage"] ?? {};
250
- const mergedStorageFields = { ...storage["fields"] ?? {} };
251
- const cleanedFields = {};
252
- for (const [fieldName, field] of Object.entries(fields)) {
253
- const { column, ...domainOnly } = field;
254
- if (domainOnly["nullable"] === void 0) domainOnly["nullable"] = false;
255
- cleanedFields[fieldName] = domainOnly;
256
- if (column !== void 0 && !mergedStorageFields[fieldName]) mergedStorageFields[fieldName] = { column };
257
- }
258
228
  result[modelName] = {
259
229
  ...model,
260
- fields: cleanedFields,
261
- ...cleanedRelations !== void 0 ? { relations: cleanedRelations } : {},
262
- storage: {
263
- ...storage,
264
- fields: mergedStorageFields
265
- }
230
+ ...cleanedRelations !== void 0 ? { relations: cleanedRelations } : {}
266
231
  };
267
232
  }
268
233
  return result;
@@ -274,7 +239,6 @@ const CanonicalContractSchema = type({
274
239
  targetFamily: "string",
275
240
  target: "string",
276
241
  models: type({ "[string]": "unknown" }),
277
- "relations?": type({ "[string]": "unknown" }),
278
242
  "roots?": "Record<string, string>",
279
243
  storage: type({ "[string]": "unknown" }),
280
244
  "execution?": type({ "[string]": "unknown" }),
@@ -297,7 +261,6 @@ function validateCoreStructure(ir) {
297
261
  if (!ir.schemaVersion) throw new Error("ContractIR must have schemaVersion");
298
262
  if (!ir.models || typeof ir.models !== "object") throw new Error("ContractIR must have models");
299
263
  if (!ir.storage || typeof ir.storage !== "object") throw new Error("ContractIR must have storage");
300
- if (ir.relations !== void 0 && typeof ir.relations !== "object") throw new Error("ContractIR relations must be an object when provided");
301
264
  if (!ir.extensionPacks || typeof ir.extensionPacks !== "object") throw new Error("ContractIR must have extensionPacks");
302
265
  if (!ir.capabilities || typeof ir.capabilities !== "object") throw new Error("ContractIR must have capabilities");
303
266
  if (!ir.meta || typeof ir.meta !== "object") throw new Error("ContractIR must have meta");
@@ -318,8 +281,7 @@ async function emit(ir, options, targetFamily) {
318
281
  targetFamily: ir.targetFamily,
319
282
  target: ir.target,
320
283
  ...ifDefined("roots", ir.roots),
321
- models: toDomainModel(ir.models),
322
- ...ifDefined("relations", ir.relations),
284
+ models: stripRelationStrategies(ir.models),
323
285
  storage: ir.storage,
324
286
  ...ifDefined("execution", ir.execution),
325
287
  extensionPacks: ir.extensionPacks,
@@ -1 +1 @@
1
- {"version":3,"file":"emission.mjs","names":["result: Record<string, unknown>","sorted: Record<string, unknown>","result: StorageObject","sortedTable: TableObject","ordered: Record<string, unknown>","normalized: NormalizedContract","result: Record<string, Record<string, unknown>>","result: Record<string, unknown>","mergedStorageFields: Record<string, Record<string, unknown>>","cleanedFields: Record<string, Record<string, unknown>>","ctx: ValidationContext"],"sources":["../src/emission/canonicalization.ts","../src/emission/hashing.ts","../src/emission/emit.ts"],"sourcesContent":["import { bigintJsonReplacer } from '@prisma-next/contract/types';\nimport { isArrayEqual } from '@prisma-next/utils/array-equal';\nimport { ifDefined } from '@prisma-next/utils/defined';\n\ntype NormalizedContract = {\n schemaVersion: string;\n targetFamily: string;\n target: string;\n storageHash?: string;\n executionHash?: string;\n profileHash?: string;\n roots?: Record<string, string>;\n models: Record<string, unknown>;\n relations?: Record<string, unknown>;\n storage: Record<string, unknown>;\n execution?: Record<string, unknown>;\n extensionPacks: Record<string, unknown>;\n capabilities: Record<string, Record<string, boolean>>;\n meta: Record<string, unknown>;\n};\n\nexport type CanonicalContractInput = {\n schemaVersion: string;\n targetFamily: string;\n target: string;\n roots?: Record<string, string>;\n models: Record<string, unknown>;\n relations?: Record<string, unknown>;\n storage: Record<string, unknown>;\n execution?: Record<string, unknown>;\n extensionPacks: Record<string, unknown>;\n capabilities: Record<string, Record<string, boolean>>;\n meta: Record<string, unknown>;\n storageHash?: string;\n executionHash?: string;\n profileHash?: string;\n};\n\nconst TOP_LEVEL_ORDER = [\n 'schemaVersion',\n 'canonicalVersion',\n 'targetFamily',\n 'target',\n 'storageHash',\n 'executionHash',\n 'profileHash',\n 'roots',\n 'models',\n 'relations',\n 'storage',\n 'execution',\n 'capabilities',\n 'extensionPacks',\n 'meta',\n] as const;\n\nfunction isDefaultValue(value: unknown): boolean {\n if (value === false) return true;\n if (value === null) return false;\n if (value instanceof Date) return false;\n if (Array.isArray(value) && value.length === 0) return true;\n if (typeof value === 'object' && value !== null) {\n const keys = Object.keys(value);\n return keys.length === 0;\n }\n return false;\n}\n\nfunction omitDefaults(obj: unknown, path: readonly string[]): unknown {\n if (obj === null || typeof obj !== 'object') {\n return obj;\n }\n\n if (obj instanceof Date) {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => omitDefaults(item, path));\n }\n\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(obj)) {\n const currentPath = [...path, key];\n\n // Exclude metadata fields from canonicalization\n if (key === '_generated') {\n continue;\n }\n\n if (key === 'nullable' && value === false) {\n continue;\n }\n\n if (key === 'generated' && value === false) {\n continue;\n }\n\n // Strip 'noAction' referential actions (the database default) for hash stability.\n // A contract with explicit `onDelete: 'noAction'` is semantically identical to\n // one that omits `onDelete` entirely, so they should produce the same hash.\n if ((key === 'onDelete' || key === 'onUpdate') && value === 'noAction') {\n continue;\n }\n\n if (isDefaultValue(value)) {\n const isRequiredModels = isArrayEqual(currentPath, ['models']);\n const isRequiredTables = isArrayEqual(currentPath, ['storage', 'tables']);\n const isRequiredCollections = isArrayEqual(currentPath, ['storage', 'collections']);\n const isCollectionEntry =\n currentPath.length === 3 &&\n isArrayEqual([currentPath[0], currentPath[1]], ['storage', 'collections']);\n const isRequiredRelations = isArrayEqual(currentPath, ['relations']);\n const isRequiredRoots = isArrayEqual(currentPath, ['roots']);\n const isRequiredExtensionPacks = isArrayEqual(currentPath, ['extensionPacks']);\n const isRequiredCapabilities = isArrayEqual(currentPath, ['capabilities']);\n const isRequiredMeta = isArrayEqual(currentPath, ['meta']);\n const isRequiredExecutionDefaults = isArrayEqual(currentPath, [\n 'execution',\n 'mutations',\n 'defaults',\n ]);\n const isExtensionNamespace = currentPath.length === 2 && currentPath[0] === 'extensionPacks';\n const isModelRelations =\n currentPath.length === 3 &&\n isArrayEqual([currentPath[0], currentPath[2]], ['models', 'relations']);\n const isTableUniques =\n currentPath.length === 4 &&\n isArrayEqual(\n [currentPath[0], currentPath[1], currentPath[3]],\n ['storage', 'tables', 'uniques'],\n );\n const isTableIndexes =\n currentPath.length === 4 &&\n isArrayEqual(\n [currentPath[0], currentPath[1], currentPath[3]],\n ['storage', 'tables', 'indexes'],\n );\n const isTableForeignKeys =\n currentPath.length === 4 &&\n isArrayEqual(\n [currentPath[0], currentPath[1], currentPath[3]],\n ['storage', 'tables', 'foreignKeys'],\n );\n\n // Preserve per-FK `constraint` and `index` booleans (even when `false`)\n // so that hash distinguishes `false` from absent.\n // Path: ['storage', 'tables', <tableName>, 'foreignKeys', 'constraint' | 'index']\n const isFkBooleanField =\n currentPath.length === 5 &&\n currentPath[0] === 'storage' &&\n currentPath[1] === 'tables' &&\n currentPath[3] === 'foreignKeys' &&\n (key === 'constraint' || key === 'index');\n\n if (\n !isRequiredModels &&\n !isRequiredTables &&\n !isRequiredCollections &&\n !isCollectionEntry &&\n !isRequiredRelations &&\n !isRequiredRoots &&\n !isRequiredExtensionPacks &&\n !isRequiredCapabilities &&\n !isRequiredMeta &&\n !isRequiredExecutionDefaults &&\n !isExtensionNamespace &&\n !isModelRelations &&\n !isTableUniques &&\n !isTableIndexes &&\n !isTableForeignKeys &&\n !isFkBooleanField\n ) {\n continue;\n }\n }\n\n result[key] = omitDefaults(value, currentPath);\n }\n\n return result;\n}\n\nfunction sortObjectKeys(obj: unknown): unknown {\n if (obj === null || typeof obj !== 'object') {\n return obj;\n }\n\n if (obj instanceof Date) {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => sortObjectKeys(item));\n }\n\n const sorted: Record<string, unknown> = {};\n const keys = Object.keys(obj).sort();\n for (const key of keys) {\n sorted[key] = sortObjectKeys((obj as Record<string, unknown>)[key]);\n }\n\n return sorted;\n}\n\ntype StorageObject = {\n tables?: Record<string, unknown>;\n [key: string]: unknown;\n};\n\ntype TableObject = {\n indexes?: unknown[];\n uniques?: unknown[];\n [key: string]: unknown;\n};\n\nfunction sortIndexesAndUniques(storage: unknown): unknown {\n if (!storage || typeof storage !== 'object') {\n return storage;\n }\n\n const storageObj = storage as StorageObject;\n if (!storageObj.tables || typeof storageObj.tables !== 'object') {\n return storage;\n }\n\n const tables = storageObj.tables;\n const result: StorageObject = { ...storageObj };\n\n result.tables = {};\n // Sort table names to ensure deterministic ordering\n const sortedTableNames = Object.keys(tables).sort();\n for (const tableName of sortedTableNames) {\n const table = tables[tableName];\n if (!table || typeof table !== 'object') {\n result.tables[tableName] = table;\n continue;\n }\n\n const tableObj = table as TableObject;\n const sortedTable: TableObject = { ...tableObj };\n\n if (Array.isArray(tableObj.indexes)) {\n sortedTable.indexes = [...tableObj.indexes].sort((a, b) => {\n const nameA = (a as { name?: string })?.name || '';\n const nameB = (b as { name?: string })?.name || '';\n return nameA.localeCompare(nameB);\n });\n }\n\n if (Array.isArray(tableObj.uniques)) {\n sortedTable.uniques = [...tableObj.uniques].sort((a, b) => {\n const nameA = (a as { name?: string })?.name || '';\n const nameB = (b as { name?: string })?.name || '';\n return nameA.localeCompare(nameB);\n });\n }\n\n result.tables[tableName] = sortedTable;\n }\n\n return result;\n}\n\nfunction orderTopLevel(obj: Record<string, unknown>): Record<string, unknown> {\n const ordered: Record<string, unknown> = {};\n const remaining = new Set(Object.keys(obj));\n\n for (const key of TOP_LEVEL_ORDER) {\n if (remaining.has(key)) {\n ordered[key] = obj[key];\n remaining.delete(key);\n }\n }\n\n for (const key of Array.from(remaining).sort()) {\n ordered[key] = obj[key];\n }\n\n return ordered;\n}\n\nexport function canonicalizeContract(ir: CanonicalContractInput): string {\n const normalized: NormalizedContract = {\n schemaVersion: ir.schemaVersion,\n targetFamily: ir.targetFamily,\n target: ir.target,\n ...ifDefined('roots', ir.roots),\n models: ir.models,\n ...ifDefined('relations', ir.relations),\n storage: ir.storage,\n ...ifDefined('execution', ir.execution),\n extensionPacks: ir.extensionPacks,\n capabilities: ir.capabilities,\n meta: ir.meta,\n };\n Object.assign(\n normalized,\n ifDefined('storageHash', ir.storageHash),\n ifDefined('executionHash', ir.executionHash),\n ifDefined('profileHash', ir.profileHash),\n );\n\n const withDefaultsOmitted = omitDefaults(normalized, []) as NormalizedContract;\n const withSortedIndexes = sortIndexesAndUniques(withDefaultsOmitted.storage);\n const withSortedStorage = { ...withDefaultsOmitted, storage: withSortedIndexes };\n const withSortedKeys = sortObjectKeys(withSortedStorage) as Record<string, unknown>;\n const withOrderedTopLevel = orderTopLevel(withSortedKeys);\n\n return JSON.stringify(withOrderedTopLevel, bigintJsonReplacer, 2);\n}\n","import { createHash } from 'node:crypto';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport type { CanonicalContractInput } from './canonicalization';\nimport { canonicalizeContract } from './canonicalization';\n\nfunction computeHash(content: string): string {\n const hash = createHash('sha256');\n hash.update(content);\n return `sha256:${hash.digest('hex')}`;\n}\n\nexport function computeStorageHash(contract: CanonicalContractInput): string {\n const storageContract = {\n schemaVersion: contract.schemaVersion,\n targetFamily: contract.targetFamily,\n target: contract.target,\n storage: contract.storage,\n models: {},\n relations: {},\n extensionPacks: {},\n capabilities: {},\n meta: {},\n };\n const canonical = canonicalizeContract(storageContract);\n return computeHash(canonical);\n}\n\nexport function computeProfileHash(contract: CanonicalContractInput): string {\n const profileContract = {\n schemaVersion: contract.schemaVersion,\n targetFamily: contract.targetFamily,\n target: contract.target,\n models: {},\n relations: {},\n storage: {},\n extensionPacks: {},\n capabilities: contract.capabilities,\n meta: {},\n };\n const canonical = canonicalizeContract(profileContract);\n return computeHash(canonical);\n}\n\nexport function computeExecutionHash(contract: CanonicalContractInput): string {\n const executionContract = {\n schemaVersion: contract.schemaVersion,\n targetFamily: contract.targetFamily,\n target: contract.target,\n models: {},\n relations: {},\n storage: {},\n extensionPacks: {},\n capabilities: {},\n meta: {},\n ...ifDefined('execution', contract.execution),\n };\n const canonical = canonicalizeContract(executionContract);\n return computeHash(canonical);\n}\n","import type { ContractIR } from '@prisma-next/contract/ir';\nimport type { TargetFamilyHook, ValidationContext } from '@prisma-next/contract/types';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { type } from 'arktype';\nimport { format } from 'prettier';\nimport { canonicalizeContract } from './canonicalization';\nimport { computeExecutionHash, computeProfileHash, computeStorageHash } from './hashing';\nimport type { EmitOptions, EmitResult } from './types';\n\nfunction stripStrategyFromRelations(\n relations: Record<string, Record<string, unknown>> | undefined,\n): Record<string, Record<string, unknown>> | undefined {\n if (!relations) return undefined;\n const result: Record<string, Record<string, unknown>> = {};\n for (const [relName, rel] of Object.entries(relations)) {\n const { strategy: _, ...rest } = rel;\n result[relName] = rest;\n }\n return result;\n}\n\nfunction toDomainModel(models: Record<string, unknown>): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [modelName, modelUnknown] of Object.entries(models)) {\n const model = modelUnknown as Record<string, unknown>;\n const relations = model['relations'] as Record<string, Record<string, unknown>> | undefined;\n const cleanedRelations = stripStrategyFromRelations(relations);\n\n const fields = model['fields'] as Record<string, Record<string, unknown>> | undefined;\n if (!fields) {\n result[modelName] = {\n ...model,\n ...(cleanedRelations !== undefined ? { relations: cleanedRelations } : {}),\n };\n continue;\n }\n\n const hasEnrichedFields = Object.values(fields).some((f) => f['codecId'] !== undefined);\n if (!hasEnrichedFields) {\n result[modelName] = {\n ...model,\n ...(cleanedRelations !== undefined ? { relations: cleanedRelations } : {}),\n };\n continue;\n }\n\n const storage = (model['storage'] ?? {}) as Record<string, unknown>;\n const existingStorageFields = (storage['fields'] ?? {}) as Record<\n string,\n Record<string, unknown>\n >;\n const mergedStorageFields: Record<string, Record<string, unknown>> = {\n ...existingStorageFields,\n };\n\n const cleanedFields: Record<string, Record<string, unknown>> = {};\n for (const [fieldName, field] of Object.entries(fields)) {\n const { column, ...domainOnly } = field;\n if (domainOnly['nullable'] === undefined) {\n domainOnly['nullable'] = false;\n }\n cleanedFields[fieldName] = domainOnly;\n\n if (column !== undefined && !mergedStorageFields[fieldName]) {\n mergedStorageFields[fieldName] = { column };\n }\n }\n\n result[modelName] = {\n ...model,\n fields: cleanedFields,\n ...(cleanedRelations !== undefined ? { relations: cleanedRelations } : {}),\n storage: { ...storage, fields: mergedStorageFields },\n };\n }\n return result;\n}\n\nconst CanonicalMetaSchema = type({\n '[string]': 'unknown',\n});\n\nconst CanonicalContractSchema = type({\n '+': 'reject',\n schemaVersion: 'string',\n targetFamily: 'string',\n target: 'string',\n models: type({ '[string]': 'unknown' }),\n 'relations?': type({ '[string]': 'unknown' }),\n 'roots?': 'Record<string, string>',\n storage: type({ '[string]': 'unknown' }),\n 'execution?': type({ '[string]': 'unknown' }),\n extensionPacks: type({ '[string]': 'unknown' }),\n capabilities: type({\n '[string]': type({\n '[string]': 'boolean',\n }),\n }),\n meta: CanonicalMetaSchema,\n});\n\nfunction assertCanonicalArtifactShape(value: unknown): void {\n const result = CanonicalContractSchema(value);\n if (result instanceof type.errors) {\n const issues = result\n .map((error) => {\n const path = error.path?.toString() ?? '<root>';\n return `${path}: ${error.message}`;\n })\n .join('; ');\n throw new Error(`ContractIR canonical artifact validation failed: ${issues}`);\n }\n}\n\nfunction validateCoreStructure(ir: ContractIR): void {\n if (!ir.targetFamily) {\n throw new Error('ContractIR must have targetFamily');\n }\n if (!ir.target) {\n throw new Error('ContractIR must have target');\n }\n if (!ir.schemaVersion) {\n throw new Error('ContractIR must have schemaVersion');\n }\n if (!ir.models || typeof ir.models !== 'object') {\n throw new Error('ContractIR must have models');\n }\n if (!ir.storage || typeof ir.storage !== 'object') {\n throw new Error('ContractIR must have storage');\n }\n if (ir.relations !== undefined && typeof ir.relations !== 'object') {\n throw new Error('ContractIR relations must be an object when provided');\n }\n if (!ir.extensionPacks || typeof ir.extensionPacks !== 'object') {\n throw new Error('ContractIR must have extensionPacks');\n }\n if (!ir.capabilities || typeof ir.capabilities !== 'object') {\n throw new Error('ContractIR must have capabilities');\n }\n if (!ir.meta || typeof ir.meta !== 'object') {\n throw new Error('ContractIR must have meta');\n }\n}\n\nexport async function emit(\n ir: ContractIR,\n options: EmitOptions,\n targetFamily: TargetFamilyHook,\n): Promise<EmitResult> {\n const {\n operationRegistry,\n codecTypeImports,\n operationTypeImports,\n extensionIds,\n parameterizedRenderers,\n parameterizedTypeImports,\n queryOperationTypeImports,\n } = options;\n\n validateCoreStructure(ir);\n\n const ctx: ValidationContext = {\n ...ifDefined('operationRegistry', operationRegistry),\n ...ifDefined('codecTypeImports', codecTypeImports),\n ...ifDefined('operationTypeImports', operationTypeImports),\n ...ifDefined('extensionIds', extensionIds),\n };\n targetFamily.validateTypes(ir, ctx);\n\n targetFamily.validateStructure(ir);\n\n const canonicalContract = {\n schemaVersion: ir.schemaVersion,\n targetFamily: ir.targetFamily,\n target: ir.target,\n ...ifDefined('roots', ir.roots),\n models: toDomainModel(ir.models as Record<string, unknown>),\n ...ifDefined('relations', ir.relations),\n storage: ir.storage,\n ...ifDefined('execution', ir.execution),\n extensionPacks: ir.extensionPacks,\n capabilities: ir.capabilities,\n meta: ir.meta,\n };\n assertCanonicalArtifactShape(canonicalContract);\n\n const storageHash = computeStorageHash(canonicalContract);\n const executionHash = canonicalContract.execution\n ? computeExecutionHash(canonicalContract)\n : undefined;\n const profileHash = computeProfileHash(canonicalContract);\n\n const contractWithHashes = {\n ...canonicalContract,\n storageHash,\n ...ifDefined('executionHash', executionHash),\n profileHash,\n };\n\n // Add _generated metadata to indicate this is a generated artifact\n // This ensures consistency between CLI emit and programmatic emit\n // Always add/update _generated with standard content for consistency\n const contractJsonObj = JSON.parse(canonicalizeContract(contractWithHashes)) as Record<\n string,\n unknown\n >;\n const contractJsonWithMeta = {\n ...contractJsonObj,\n _generated: {\n warning: '⚠️ GENERATED FILE - DO NOT EDIT',\n message: 'This file is automatically generated by \"prisma-next contract emit\".',\n regenerate: 'To regenerate, run: prisma-next contract emit',\n },\n };\n const contractJsonString = JSON.stringify(contractJsonWithMeta, null, 2);\n\n const generateOptions =\n parameterizedRenderers || parameterizedTypeImports || queryOperationTypeImports\n ? {\n ...ifDefined('parameterizedRenderers', parameterizedRenderers),\n ...ifDefined('parameterizedTypeImports', parameterizedTypeImports),\n ...ifDefined('queryOperationTypeImports', queryOperationTypeImports),\n }\n : undefined;\n\n const contractTypeHashes = {\n storageHash,\n ...ifDefined('executionHash', executionHash),\n profileHash,\n };\n const contractDtsRaw = targetFamily.generateContractTypes(\n ir,\n codecTypeImports ?? [],\n operationTypeImports ?? [],\n contractTypeHashes,\n generateOptions,\n );\n const contractDts = await format(contractDtsRaw, {\n parser: 'typescript',\n singleQuote: true,\n semi: true,\n printWidth: 100,\n });\n\n return {\n contractJson: contractJsonString,\n contractDts,\n storageHash,\n ...ifDefined('executionHash', executionHash),\n profileHash,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"emission.mjs","names":["result: Record<string, unknown>","sorted: Record<string, unknown>","result: StorageObject","sortedTable: TableObject","ordered: Record<string, unknown>","normalized: NormalizedContract","result: Record<string, Record<string, unknown>>","result: Record<string, unknown>","ctx: ValidationContext"],"sources":["../src/emission/canonicalization.ts","../src/emission/hashing.ts","../src/emission/emit.ts"],"sourcesContent":["import { bigintJsonReplacer } from '@prisma-next/contract/types';\nimport { isArrayEqual } from '@prisma-next/utils/array-equal';\nimport { ifDefined } from '@prisma-next/utils/defined';\n\ntype NormalizedContract = {\n schemaVersion: string;\n targetFamily: string;\n target: string;\n storageHash?: string;\n executionHash?: string;\n profileHash?: string;\n roots?: Record<string, string>;\n models: Record<string, unknown>;\n storage: Record<string, unknown>;\n execution?: Record<string, unknown>;\n extensionPacks: Record<string, unknown>;\n capabilities: Record<string, Record<string, boolean>>;\n meta: Record<string, unknown>;\n};\n\nexport type CanonicalContractInput = {\n schemaVersion: string;\n targetFamily: string;\n target: string;\n roots?: Record<string, string>;\n models: Record<string, unknown>;\n storage: Record<string, unknown>;\n execution?: Record<string, unknown>;\n extensionPacks: Record<string, unknown>;\n capabilities: Record<string, Record<string, boolean>>;\n meta: Record<string, unknown>;\n storageHash?: string;\n executionHash?: string;\n profileHash?: string;\n};\n\nconst TOP_LEVEL_ORDER = [\n 'schemaVersion',\n 'canonicalVersion',\n 'targetFamily',\n 'target',\n 'storageHash',\n 'executionHash',\n 'profileHash',\n 'roots',\n 'models',\n 'storage',\n 'execution',\n 'capabilities',\n 'extensionPacks',\n 'meta',\n] as const;\n\nfunction isDefaultValue(value: unknown): boolean {\n if (value === false) return true;\n if (value === null) return false;\n if (value instanceof Date) return false;\n if (Array.isArray(value) && value.length === 0) return true;\n if (typeof value === 'object' && value !== null) {\n const keys = Object.keys(value);\n return keys.length === 0;\n }\n return false;\n}\n\nfunction omitDefaults(obj: unknown, path: readonly string[]): unknown {\n if (obj === null || typeof obj !== 'object') {\n return obj;\n }\n\n if (obj instanceof Date) {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => omitDefaults(item, path));\n }\n\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(obj)) {\n const currentPath = [...path, key];\n\n // Exclude metadata fields from canonicalization\n if (key === '_generated') {\n continue;\n }\n\n if (key === 'nullable' && value === false) {\n continue;\n }\n\n if (key === 'generated' && value === false) {\n continue;\n }\n\n // Strip 'noAction' referential actions (the database default) for hash stability.\n // A contract with explicit `onDelete: 'noAction'` is semantically identical to\n // one that omits `onDelete` entirely, so they should produce the same hash.\n if ((key === 'onDelete' || key === 'onUpdate') && value === 'noAction') {\n continue;\n }\n\n if (isDefaultValue(value)) {\n const isRequiredModels = isArrayEqual(currentPath, ['models']);\n const isRequiredTables = isArrayEqual(currentPath, ['storage', 'tables']);\n const isRequiredCollections = isArrayEqual(currentPath, ['storage', 'collections']);\n const isCollectionEntry =\n currentPath.length === 3 &&\n isArrayEqual([currentPath[0], currentPath[1]], ['storage', 'collections']);\n const isRequiredRoots = isArrayEqual(currentPath, ['roots']);\n const isRequiredExtensionPacks = isArrayEqual(currentPath, ['extensionPacks']);\n const isRequiredCapabilities = isArrayEqual(currentPath, ['capabilities']);\n const isRequiredMeta = isArrayEqual(currentPath, ['meta']);\n const isRequiredExecutionDefaults = isArrayEqual(currentPath, [\n 'execution',\n 'mutations',\n 'defaults',\n ]);\n const isExtensionNamespace = currentPath.length === 2 && currentPath[0] === 'extensionPacks';\n const isModelRelations =\n currentPath.length === 3 &&\n isArrayEqual([currentPath[0], currentPath[2]], ['models', 'relations']);\n const isTableUniques =\n currentPath.length === 4 &&\n isArrayEqual(\n [currentPath[0], currentPath[1], currentPath[3]],\n ['storage', 'tables', 'uniques'],\n );\n const isTableIndexes =\n currentPath.length === 4 &&\n isArrayEqual(\n [currentPath[0], currentPath[1], currentPath[3]],\n ['storage', 'tables', 'indexes'],\n );\n const isTableForeignKeys =\n currentPath.length === 4 &&\n isArrayEqual(\n [currentPath[0], currentPath[1], currentPath[3]],\n ['storage', 'tables', 'foreignKeys'],\n );\n\n // Preserve per-FK `constraint` and `index` booleans (even when `false`)\n // so that hash distinguishes `false` from absent.\n // Path: ['storage', 'tables', <tableName>, 'foreignKeys', 'constraint' | 'index']\n const isFkBooleanField =\n currentPath.length === 5 &&\n currentPath[0] === 'storage' &&\n currentPath[1] === 'tables' &&\n currentPath[3] === 'foreignKeys' &&\n (key === 'constraint' || key === 'index');\n\n if (\n !isRequiredModels &&\n !isRequiredTables &&\n !isRequiredCollections &&\n !isCollectionEntry &&\n !isRequiredRoots &&\n !isRequiredExtensionPacks &&\n !isRequiredCapabilities &&\n !isRequiredMeta &&\n !isRequiredExecutionDefaults &&\n !isExtensionNamespace &&\n !isModelRelations &&\n !isTableUniques &&\n !isTableIndexes &&\n !isTableForeignKeys &&\n !isFkBooleanField\n ) {\n continue;\n }\n }\n\n result[key] = omitDefaults(value, currentPath);\n }\n\n return result;\n}\n\nfunction sortObjectKeys(obj: unknown): unknown {\n if (obj === null || typeof obj !== 'object') {\n return obj;\n }\n\n if (obj instanceof Date) {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => sortObjectKeys(item));\n }\n\n const sorted: Record<string, unknown> = {};\n const keys = Object.keys(obj).sort();\n for (const key of keys) {\n sorted[key] = sortObjectKeys((obj as Record<string, unknown>)[key]);\n }\n\n return sorted;\n}\n\ntype StorageObject = {\n tables?: Record<string, unknown>;\n [key: string]: unknown;\n};\n\ntype TableObject = {\n indexes?: unknown[];\n uniques?: unknown[];\n [key: string]: unknown;\n};\n\nfunction sortIndexesAndUniques(storage: unknown): unknown {\n if (!storage || typeof storage !== 'object') {\n return storage;\n }\n\n const storageObj = storage as StorageObject;\n if (!storageObj.tables || typeof storageObj.tables !== 'object') {\n return storage;\n }\n\n const tables = storageObj.tables;\n const result: StorageObject = { ...storageObj };\n\n result.tables = {};\n // Sort table names to ensure deterministic ordering\n const sortedTableNames = Object.keys(tables).sort();\n for (const tableName of sortedTableNames) {\n const table = tables[tableName];\n if (!table || typeof table !== 'object') {\n result.tables[tableName] = table;\n continue;\n }\n\n const tableObj = table as TableObject;\n const sortedTable: TableObject = { ...tableObj };\n\n if (Array.isArray(tableObj.indexes)) {\n sortedTable.indexes = [...tableObj.indexes].sort((a, b) => {\n const nameA = (a as { name?: string })?.name || '';\n const nameB = (b as { name?: string })?.name || '';\n return nameA.localeCompare(nameB);\n });\n }\n\n if (Array.isArray(tableObj.uniques)) {\n sortedTable.uniques = [...tableObj.uniques].sort((a, b) => {\n const nameA = (a as { name?: string })?.name || '';\n const nameB = (b as { name?: string })?.name || '';\n return nameA.localeCompare(nameB);\n });\n }\n\n result.tables[tableName] = sortedTable;\n }\n\n return result;\n}\n\nfunction orderTopLevel(obj: Record<string, unknown>): Record<string, unknown> {\n const ordered: Record<string, unknown> = {};\n const remaining = new Set(Object.keys(obj));\n\n for (const key of TOP_LEVEL_ORDER) {\n if (remaining.has(key)) {\n ordered[key] = obj[key];\n remaining.delete(key);\n }\n }\n\n for (const key of Array.from(remaining).sort()) {\n ordered[key] = obj[key];\n }\n\n return ordered;\n}\n\nexport function canonicalizeContract(ir: CanonicalContractInput): string {\n const normalized: NormalizedContract = {\n schemaVersion: ir.schemaVersion,\n targetFamily: ir.targetFamily,\n target: ir.target,\n ...ifDefined('roots', ir.roots),\n models: ir.models,\n storage: ir.storage,\n ...ifDefined('execution', ir.execution),\n extensionPacks: ir.extensionPacks,\n capabilities: ir.capabilities,\n meta: ir.meta,\n };\n Object.assign(\n normalized,\n ifDefined('storageHash', ir.storageHash),\n ifDefined('executionHash', ir.executionHash),\n ifDefined('profileHash', ir.profileHash),\n );\n\n const withDefaultsOmitted = omitDefaults(normalized, []) as NormalizedContract;\n const withSortedIndexes = sortIndexesAndUniques(withDefaultsOmitted.storage);\n const withSortedStorage = { ...withDefaultsOmitted, storage: withSortedIndexes };\n const withSortedKeys = sortObjectKeys(withSortedStorage) as Record<string, unknown>;\n const withOrderedTopLevel = orderTopLevel(withSortedKeys);\n\n return JSON.stringify(withOrderedTopLevel, bigintJsonReplacer, 2);\n}\n","import { createHash } from 'node:crypto';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport type { CanonicalContractInput } from './canonicalization';\nimport { canonicalizeContract } from './canonicalization';\n\nfunction computeHash(content: string): string {\n const hash = createHash('sha256');\n hash.update(content);\n return `sha256:${hash.digest('hex')}`;\n}\n\nexport function computeStorageHash(contract: CanonicalContractInput): string {\n const storageContract = {\n schemaVersion: contract.schemaVersion,\n targetFamily: contract.targetFamily,\n target: contract.target,\n storage: contract.storage,\n models: {},\n extensionPacks: {},\n capabilities: {},\n meta: {},\n };\n const canonical = canonicalizeContract(storageContract);\n return computeHash(canonical);\n}\n\nexport function computeProfileHash(contract: CanonicalContractInput): string {\n const profileContract = {\n schemaVersion: contract.schemaVersion,\n targetFamily: contract.targetFamily,\n target: contract.target,\n models: {},\n storage: {},\n extensionPacks: {},\n capabilities: contract.capabilities,\n meta: {},\n };\n const canonical = canonicalizeContract(profileContract);\n return computeHash(canonical);\n}\n\nexport function computeExecutionHash(contract: CanonicalContractInput): string {\n const executionContract = {\n schemaVersion: contract.schemaVersion,\n targetFamily: contract.targetFamily,\n target: contract.target,\n models: {},\n storage: {},\n extensionPacks: {},\n capabilities: {},\n meta: {},\n ...ifDefined('execution', contract.execution),\n };\n const canonical = canonicalizeContract(executionContract);\n return computeHash(canonical);\n}\n","import type { ContractIR } from '@prisma-next/contract/ir';\nimport type { TargetFamilyHook, ValidationContext } from '@prisma-next/contract/types';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { type } from 'arktype';\nimport { format } from 'prettier';\nimport { canonicalizeContract } from './canonicalization';\nimport { computeExecutionHash, computeProfileHash, computeStorageHash } from './hashing';\nimport type { EmitOptions, EmitResult } from './types';\n\nfunction stripStrategyFromRelations(\n relations: Record<string, Record<string, unknown>> | undefined,\n): Record<string, Record<string, unknown>> | undefined {\n if (!relations) return undefined;\n const result: Record<string, Record<string, unknown>> = {};\n for (const [relName, rel] of Object.entries(relations)) {\n const { strategy: _, ...rest } = rel;\n result[relName] = rest;\n }\n return result;\n}\n\nfunction stripRelationStrategies(models: Record<string, unknown>): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [modelName, modelUnknown] of Object.entries(models)) {\n const model = modelUnknown as Record<string, unknown>;\n const relations = model['relations'] as Record<string, Record<string, unknown>> | undefined;\n const cleanedRelations = stripStrategyFromRelations(relations);\n\n result[modelName] = {\n ...model,\n ...(cleanedRelations !== undefined ? { relations: cleanedRelations } : {}),\n };\n }\n return result;\n}\n\nconst CanonicalMetaSchema = type({\n '[string]': 'unknown',\n});\n\nconst CanonicalContractSchema = type({\n '+': 'reject',\n schemaVersion: 'string',\n targetFamily: 'string',\n target: 'string',\n models: type({ '[string]': 'unknown' }),\n 'roots?': 'Record<string, string>',\n storage: type({ '[string]': 'unknown' }),\n 'execution?': type({ '[string]': 'unknown' }),\n extensionPacks: type({ '[string]': 'unknown' }),\n capabilities: type({\n '[string]': type({\n '[string]': 'boolean',\n }),\n }),\n meta: CanonicalMetaSchema,\n});\n\nfunction assertCanonicalArtifactShape(value: unknown): void {\n const result = CanonicalContractSchema(value);\n if (result instanceof type.errors) {\n const issues = result\n .map((error) => {\n const path = error.path?.toString() ?? '<root>';\n return `${path}: ${error.message}`;\n })\n .join('; ');\n throw new Error(`ContractIR canonical artifact validation failed: ${issues}`);\n }\n}\n\nfunction validateCoreStructure(ir: ContractIR): void {\n if (!ir.targetFamily) {\n throw new Error('ContractIR must have targetFamily');\n }\n if (!ir.target) {\n throw new Error('ContractIR must have target');\n }\n if (!ir.schemaVersion) {\n throw new Error('ContractIR must have schemaVersion');\n }\n if (!ir.models || typeof ir.models !== 'object') {\n throw new Error('ContractIR must have models');\n }\n if (!ir.storage || typeof ir.storage !== 'object') {\n throw new Error('ContractIR must have storage');\n }\n if (!ir.extensionPacks || typeof ir.extensionPacks !== 'object') {\n throw new Error('ContractIR must have extensionPacks');\n }\n if (!ir.capabilities || typeof ir.capabilities !== 'object') {\n throw new Error('ContractIR must have capabilities');\n }\n if (!ir.meta || typeof ir.meta !== 'object') {\n throw new Error('ContractIR must have meta');\n }\n}\n\nexport async function emit(\n ir: ContractIR,\n options: EmitOptions,\n targetFamily: TargetFamilyHook,\n): Promise<EmitResult> {\n const {\n operationRegistry,\n codecTypeImports,\n operationTypeImports,\n extensionIds,\n parameterizedRenderers,\n parameterizedTypeImports,\n queryOperationTypeImports,\n } = options;\n\n validateCoreStructure(ir);\n\n const ctx: ValidationContext = {\n ...ifDefined('operationRegistry', operationRegistry),\n ...ifDefined('codecTypeImports', codecTypeImports),\n ...ifDefined('operationTypeImports', operationTypeImports),\n ...ifDefined('extensionIds', extensionIds),\n };\n targetFamily.validateTypes(ir, ctx);\n\n targetFamily.validateStructure(ir);\n\n const canonicalContract = {\n schemaVersion: ir.schemaVersion,\n targetFamily: ir.targetFamily,\n target: ir.target,\n ...ifDefined('roots', ir.roots),\n models: stripRelationStrategies(ir.models as Record<string, unknown>),\n storage: ir.storage,\n ...ifDefined('execution', ir.execution),\n extensionPacks: ir.extensionPacks,\n capabilities: ir.capabilities,\n meta: ir.meta,\n };\n assertCanonicalArtifactShape(canonicalContract);\n\n const storageHash = computeStorageHash(canonicalContract);\n const executionHash = canonicalContract.execution\n ? computeExecutionHash(canonicalContract)\n : undefined;\n const profileHash = computeProfileHash(canonicalContract);\n\n const contractWithHashes = {\n ...canonicalContract,\n storageHash,\n ...ifDefined('executionHash', executionHash),\n profileHash,\n };\n\n // Add _generated metadata to indicate this is a generated artifact\n // This ensures consistency between CLI emit and programmatic emit\n // Always add/update _generated with standard content for consistency\n const contractJsonObj = JSON.parse(canonicalizeContract(contractWithHashes)) as Record<\n string,\n unknown\n >;\n const contractJsonWithMeta = {\n ...contractJsonObj,\n _generated: {\n warning: '⚠️ GENERATED FILE - DO NOT EDIT',\n message: 'This file is automatically generated by \"prisma-next contract emit\".',\n regenerate: 'To regenerate, run: prisma-next contract emit',\n },\n };\n const contractJsonString = JSON.stringify(contractJsonWithMeta, null, 2);\n\n const generateOptions =\n parameterizedRenderers || parameterizedTypeImports || queryOperationTypeImports\n ? {\n ...ifDefined('parameterizedRenderers', parameterizedRenderers),\n ...ifDefined('parameterizedTypeImports', parameterizedTypeImports),\n ...ifDefined('queryOperationTypeImports', queryOperationTypeImports),\n }\n : undefined;\n\n const contractTypeHashes = {\n storageHash,\n ...ifDefined('executionHash', executionHash),\n profileHash,\n };\n const contractDtsRaw = targetFamily.generateContractTypes(\n ir,\n codecTypeImports ?? [],\n operationTypeImports ?? [],\n contractTypeHashes,\n generateOptions,\n );\n const contractDts = await format(contractDtsRaw, {\n parser: 'typescript',\n singleQuote: true,\n semi: true,\n printWidth: 100,\n });\n\n return {\n contractJson: contractJsonString,\n contractDts,\n storageHash,\n ...ifDefined('executionHash', executionHash),\n profileHash,\n };\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,23 +1,23 @@
1
1
  {
2
2
  "name": "@prisma-next/core-control-plane",
3
- "version": "0.3.0-dev.131",
3
+ "version": "0.3.0-dev.133",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "description": "Control-plane migration/emission primitives and structured error utilities",
7
7
  "dependencies": {
8
8
  "arktype": "^2.1.26",
9
9
  "prettier": "^3.3.3",
10
- "@prisma-next/operations": "0.3.0-dev.131",
11
- "@prisma-next/contract": "0.3.0-dev.131",
12
- "@prisma-next/utils": "0.3.0-dev.131"
10
+ "@prisma-next/contract": "0.3.0-dev.133",
11
+ "@prisma-next/operations": "0.3.0-dev.133",
12
+ "@prisma-next/utils": "0.3.0-dev.133"
13
13
  },
14
14
  "devDependencies": {
15
15
  "tsdown": "0.18.4",
16
16
  "typescript": "5.9.3",
17
17
  "vitest": "4.0.17",
18
18
  "@prisma-next/test-utils": "0.0.1",
19
- "@prisma-next/tsconfig": "0.0.0",
20
- "@prisma-next/tsdown": "0.0.0"
19
+ "@prisma-next/tsdown": "0.0.0",
20
+ "@prisma-next/tsconfig": "0.0.0"
21
21
  },
22
22
  "files": [
23
23
  "dist",
@@ -11,7 +11,6 @@ type NormalizedContract = {
11
11
  profileHash?: string;
12
12
  roots?: Record<string, string>;
13
13
  models: Record<string, unknown>;
14
- relations?: Record<string, unknown>;
15
14
  storage: Record<string, unknown>;
16
15
  execution?: Record<string, unknown>;
17
16
  extensionPacks: Record<string, unknown>;
@@ -25,7 +24,6 @@ export type CanonicalContractInput = {
25
24
  target: string;
26
25
  roots?: Record<string, string>;
27
26
  models: Record<string, unknown>;
28
- relations?: Record<string, unknown>;
29
27
  storage: Record<string, unknown>;
30
28
  execution?: Record<string, unknown>;
31
29
  extensionPacks: Record<string, unknown>;
@@ -46,7 +44,6 @@ const TOP_LEVEL_ORDER = [
46
44
  'profileHash',
47
45
  'roots',
48
46
  'models',
49
- 'relations',
50
47
  'storage',
51
48
  'execution',
52
49
  'capabilities',
@@ -111,7 +108,6 @@ function omitDefaults(obj: unknown, path: readonly string[]): unknown {
111
108
  const isCollectionEntry =
112
109
  currentPath.length === 3 &&
113
110
  isArrayEqual([currentPath[0], currentPath[1]], ['storage', 'collections']);
114
- const isRequiredRelations = isArrayEqual(currentPath, ['relations']);
115
111
  const isRequiredRoots = isArrayEqual(currentPath, ['roots']);
116
112
  const isRequiredExtensionPacks = isArrayEqual(currentPath, ['extensionPacks']);
117
113
  const isRequiredCapabilities = isArrayEqual(currentPath, ['capabilities']);
@@ -159,7 +155,6 @@ function omitDefaults(obj: unknown, path: readonly string[]): unknown {
159
155
  !isRequiredTables &&
160
156
  !isRequiredCollections &&
161
157
  !isCollectionEntry &&
162
- !isRequiredRelations &&
163
158
  !isRequiredRoots &&
164
159
  !isRequiredExtensionPacks &&
165
160
  !isRequiredCapabilities &&
@@ -288,7 +283,6 @@ export function canonicalizeContract(ir: CanonicalContractInput): string {
288
283
  target: ir.target,
289
284
  ...ifDefined('roots', ir.roots),
290
285
  models: ir.models,
291
- ...ifDefined('relations', ir.relations),
292
286
  storage: ir.storage,
293
287
  ...ifDefined('execution', ir.execution),
294
288
  extensionPacks: ir.extensionPacks,
@@ -19,58 +19,16 @@ function stripStrategyFromRelations(
19
19
  return result;
20
20
  }
21
21
 
22
- function toDomainModel(models: Record<string, unknown>): Record<string, unknown> {
22
+ function stripRelationStrategies(models: Record<string, unknown>): Record<string, unknown> {
23
23
  const result: Record<string, unknown> = {};
24
24
  for (const [modelName, modelUnknown] of Object.entries(models)) {
25
25
  const model = modelUnknown as Record<string, unknown>;
26
26
  const relations = model['relations'] as Record<string, Record<string, unknown>> | undefined;
27
27
  const cleanedRelations = stripStrategyFromRelations(relations);
28
28
 
29
- const fields = model['fields'] as Record<string, Record<string, unknown>> | undefined;
30
- if (!fields) {
31
- result[modelName] = {
32
- ...model,
33
- ...(cleanedRelations !== undefined ? { relations: cleanedRelations } : {}),
34
- };
35
- continue;
36
- }
37
-
38
- const hasEnrichedFields = Object.values(fields).some((f) => f['codecId'] !== undefined);
39
- if (!hasEnrichedFields) {
40
- result[modelName] = {
41
- ...model,
42
- ...(cleanedRelations !== undefined ? { relations: cleanedRelations } : {}),
43
- };
44
- continue;
45
- }
46
-
47
- const storage = (model['storage'] ?? {}) as Record<string, unknown>;
48
- const existingStorageFields = (storage['fields'] ?? {}) as Record<
49
- string,
50
- Record<string, unknown>
51
- >;
52
- const mergedStorageFields: Record<string, Record<string, unknown>> = {
53
- ...existingStorageFields,
54
- };
55
-
56
- const cleanedFields: Record<string, Record<string, unknown>> = {};
57
- for (const [fieldName, field] of Object.entries(fields)) {
58
- const { column, ...domainOnly } = field;
59
- if (domainOnly['nullable'] === undefined) {
60
- domainOnly['nullable'] = false;
61
- }
62
- cleanedFields[fieldName] = domainOnly;
63
-
64
- if (column !== undefined && !mergedStorageFields[fieldName]) {
65
- mergedStorageFields[fieldName] = { column };
66
- }
67
- }
68
-
69
29
  result[modelName] = {
70
30
  ...model,
71
- fields: cleanedFields,
72
31
  ...(cleanedRelations !== undefined ? { relations: cleanedRelations } : {}),
73
- storage: { ...storage, fields: mergedStorageFields },
74
32
  };
75
33
  }
76
34
  return result;
@@ -86,7 +44,6 @@ const CanonicalContractSchema = type({
86
44
  targetFamily: 'string',
87
45
  target: 'string',
88
46
  models: type({ '[string]': 'unknown' }),
89
- 'relations?': type({ '[string]': 'unknown' }),
90
47
  'roots?': 'Record<string, string>',
91
48
  storage: type({ '[string]': 'unknown' }),
92
49
  'execution?': type({ '[string]': 'unknown' }),
@@ -128,9 +85,6 @@ function validateCoreStructure(ir: ContractIR): void {
128
85
  if (!ir.storage || typeof ir.storage !== 'object') {
129
86
  throw new Error('ContractIR must have storage');
130
87
  }
131
- if (ir.relations !== undefined && typeof ir.relations !== 'object') {
132
- throw new Error('ContractIR relations must be an object when provided');
133
- }
134
88
  if (!ir.extensionPacks || typeof ir.extensionPacks !== 'object') {
135
89
  throw new Error('ContractIR must have extensionPacks');
136
90
  }
@@ -174,8 +128,7 @@ export async function emit(
174
128
  targetFamily: ir.targetFamily,
175
129
  target: ir.target,
176
130
  ...ifDefined('roots', ir.roots),
177
- models: toDomainModel(ir.models as Record<string, unknown>),
178
- ...ifDefined('relations', ir.relations),
131
+ models: stripRelationStrategies(ir.models as Record<string, unknown>),
179
132
  storage: ir.storage,
180
133
  ...ifDefined('execution', ir.execution),
181
134
  extensionPacks: ir.extensionPacks,
@@ -16,7 +16,6 @@ export function computeStorageHash(contract: CanonicalContractInput): string {
16
16
  target: contract.target,
17
17
  storage: contract.storage,
18
18
  models: {},
19
- relations: {},
20
19
  extensionPacks: {},
21
20
  capabilities: {},
22
21
  meta: {},
@@ -31,7 +30,6 @@ export function computeProfileHash(contract: CanonicalContractInput): string {
31
30
  targetFamily: contract.targetFamily,
32
31
  target: contract.target,
33
32
  models: {},
34
- relations: {},
35
33
  storage: {},
36
34
  extensionPacks: {},
37
35
  capabilities: contract.capabilities,
@@ -47,7 +45,6 @@ export function computeExecutionHash(contract: CanonicalContractInput): string {
47
45
  targetFamily: contract.targetFamily,
48
46
  target: contract.target,
49
47
  models: {},
50
- relations: {},
51
48
  storage: {},
52
49
  extensionPacks: {},
53
50
  capabilities: {},