@prisma-next/emitter 0.3.0-pr.93.5 → 0.3.0-pr.94.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +3 -0
- package/dist/index.mjs +3 -0
- package/dist/test/utils.d.mts +19 -0
- package/dist/test/utils.d.mts.map +1 -0
- package/dist/test/utils.mjs +59 -0
- package/dist/test/utils.mjs.map +1 -0
- package/package.json +18 -16
- package/dist/exports/index.d.ts +0 -4
- package/dist/exports/index.d.ts.map +0 -1
- package/dist/exports/index.js +0 -6
- package/dist/exports/index.js.map +0 -1
- package/dist/target-family.d.ts +0 -2
- package/dist/target-family.d.ts.map +0 -1
- package/dist/test/utils.js +0 -78
- package/dist/test/utils.js.map +0 -1
- package/test/canonicalization.test.ts +0 -210
- package/test/emitter.integration.test.ts +0 -274
- package/test/emitter.roundtrip.test.ts +0 -370
- package/test/emitter.test.ts +0 -650
- package/test/factories.test.ts +0 -274
- package/test/hashing.test.ts +0 -59
- package/test/tsconfig.json +0 -4
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { EmitOptions, EmitResult, emit } from "@prisma-next/core-control-plane/emission";
|
|
2
|
+
import { TargetFamilyHook, TypesImportSpec, ValidationContext } from "@prisma-next/contract/types";
|
|
3
|
+
export { type EmitOptions, type EmitResult, type TargetFamilyHook, type TypesImportSpec, type ValidationContext, emit };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ContractIR } from "@prisma-next/contract/ir";
|
|
2
|
+
|
|
3
|
+
//#region test/utils.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Factory function for creating ContractIR objects in tests.
|
|
7
|
+
* Provides sensible defaults and allows overriding specific fields.
|
|
8
|
+
* Uses the emitter factories internally for consistency.
|
|
9
|
+
*
|
|
10
|
+
* If a field is explicitly set to `undefined` in overrides, it will be omitted
|
|
11
|
+
* from the result (useful for testing validation of missing fields).
|
|
12
|
+
*/
|
|
13
|
+
declare function createContractIR(overrides?: Partial<ContractIR> & {
|
|
14
|
+
coreHash?: string;
|
|
15
|
+
profileHash?: string;
|
|
16
|
+
}): ContractIR;
|
|
17
|
+
//#endregion
|
|
18
|
+
export { createContractIR };
|
|
19
|
+
//# sourceMappingURL=utils.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.mts","names":[],"sources":["../../test/utils.ts"],"sourcesContent":[],"mappings":";;;;;;AAUA;;;;;;iBAAgB,gBAAA,aACH,QAAQ;;;IAClB"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { irHeader, irMeta } from "@prisma-next/contract/ir";
|
|
2
|
+
|
|
3
|
+
//#region test/utils.ts
|
|
4
|
+
/**
|
|
5
|
+
* Factory function for creating ContractIR objects in tests.
|
|
6
|
+
* Provides sensible defaults and allows overriding specific fields.
|
|
7
|
+
* Uses the emitter factories internally for consistency.
|
|
8
|
+
*
|
|
9
|
+
* If a field is explicitly set to `undefined` in overrides, it will be omitted
|
|
10
|
+
* from the result (useful for testing validation of missing fields).
|
|
11
|
+
*/
|
|
12
|
+
function createContractIR(overrides = {}) {
|
|
13
|
+
const hasTarget = "target" in overrides;
|
|
14
|
+
const hasTargetFamily = "targetFamily" in overrides;
|
|
15
|
+
const hasCoreHash = "coreHash" in overrides;
|
|
16
|
+
const hasSchemaVersion = "schemaVersion" in overrides;
|
|
17
|
+
const hasModels = "models" in overrides;
|
|
18
|
+
const hasRelations = "relations" in overrides;
|
|
19
|
+
const hasStorage = "storage" in overrides;
|
|
20
|
+
const hasCapabilities = "capabilities" in overrides;
|
|
21
|
+
const hasExtensionPacks = "extensionPacks" in overrides;
|
|
22
|
+
const hasMeta = "meta" in overrides;
|
|
23
|
+
const hasSources = "sources" in overrides;
|
|
24
|
+
const headerOpts = {};
|
|
25
|
+
if (hasTarget && overrides.target !== void 0) headerOpts.target = overrides.target;
|
|
26
|
+
else if (!hasTarget) headerOpts.target = "postgres";
|
|
27
|
+
if (hasTargetFamily && overrides.targetFamily !== void 0) headerOpts.targetFamily = overrides.targetFamily;
|
|
28
|
+
else if (!hasTargetFamily) headerOpts.targetFamily = "sql";
|
|
29
|
+
if (hasCoreHash && overrides.coreHash !== void 0) headerOpts.coreHash = overrides.coreHash;
|
|
30
|
+
else if (!hasCoreHash) headerOpts.coreHash = "sha256:test";
|
|
31
|
+
if (overrides.profileHash !== void 0) headerOpts.profileHash = overrides.profileHash;
|
|
32
|
+
const header = irHeader(headerOpts);
|
|
33
|
+
const metaOpts = {};
|
|
34
|
+
if (hasCapabilities && overrides.capabilities !== void 0) metaOpts.capabilities = overrides.capabilities;
|
|
35
|
+
else if (!hasCapabilities) metaOpts.capabilities = {};
|
|
36
|
+
if (hasExtensionPacks && overrides.extensionPacks !== void 0) metaOpts.extensionPacks = overrides.extensionPacks;
|
|
37
|
+
else if (!hasExtensionPacks) metaOpts.extensionPacks = {};
|
|
38
|
+
if (hasMeta && overrides.meta !== void 0) metaOpts.meta = overrides.meta;
|
|
39
|
+
else if (!hasMeta) metaOpts.meta = {};
|
|
40
|
+
if (hasSources && overrides.sources !== void 0) metaOpts.sources = overrides.sources;
|
|
41
|
+
else if (!hasSources) metaOpts.sources = {};
|
|
42
|
+
const meta = irMeta(Object.keys(metaOpts).length > 0 ? metaOpts : void 0);
|
|
43
|
+
return {
|
|
44
|
+
schemaVersion: hasSchemaVersion && overrides.schemaVersion !== void 0 ? overrides.schemaVersion : hasSchemaVersion && overrides.schemaVersion === void 0 ? void 0 : header.schemaVersion,
|
|
45
|
+
target: header.target,
|
|
46
|
+
targetFamily: header.targetFamily,
|
|
47
|
+
capabilities: hasCapabilities && overrides.capabilities === void 0 ? void 0 : !hasCapabilities || overrides.capabilities !== void 0 ? meta.capabilities : {},
|
|
48
|
+
extensionPacks: hasExtensionPacks && overrides.extensionPacks === void 0 ? void 0 : !hasExtensionPacks || overrides.extensionPacks !== void 0 ? meta.extensionPacks : {},
|
|
49
|
+
meta: hasMeta && overrides.meta === void 0 ? void 0 : !hasMeta || overrides.meta !== void 0 ? meta.meta : {},
|
|
50
|
+
sources: hasSources && overrides.sources === void 0 ? void 0 : !hasSources || overrides.sources !== void 0 ? meta.sources : {},
|
|
51
|
+
storage: hasStorage && overrides.storage === void 0 ? void 0 : hasStorage && overrides.storage !== void 0 ? overrides.storage : !hasStorage ? { tables: {} } : {},
|
|
52
|
+
models: hasModels && overrides.models === void 0 ? void 0 : hasModels && overrides.models !== void 0 ? overrides.models : !hasModels ? {} : {},
|
|
53
|
+
relations: hasRelations && overrides.relations === void 0 ? void 0 : hasRelations && overrides.relations !== void 0 ? overrides.relations : !hasRelations ? {} : {}
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
//#endregion
|
|
58
|
+
export { createContractIR };
|
|
59
|
+
//# sourceMappingURL=utils.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.mjs","names":["headerOpts: {\n target?: string;\n targetFamily?: string;\n coreHash?: string;\n profileHash?: string;\n }","metaOpts: {\n capabilities?: Record<string, Record<string, boolean>>;\n extensionPacks?: Record<string, unknown>;\n meta?: Record<string, unknown>;\n sources?: Record<string, unknown>;\n }"],"sources":["../../test/utils.ts"],"sourcesContent":["import { type ContractIR, irHeader, irMeta } from '@prisma-next/contract/ir';\n\n/**\n * Factory function for creating ContractIR objects in tests.\n * Provides sensible defaults and allows overriding specific fields.\n * Uses the emitter factories internally for consistency.\n *\n * If a field is explicitly set to `undefined` in overrides, it will be omitted\n * from the result (useful for testing validation of missing fields).\n */\nexport function createContractIR(\n overrides: Partial<ContractIR> & { coreHash?: string; profileHash?: string } = {},\n): ContractIR {\n // Check if fields are explicitly undefined (not just missing)\n const hasTarget = 'target' in overrides;\n const hasTargetFamily = 'targetFamily' in overrides;\n const hasCoreHash = 'coreHash' in overrides;\n const hasSchemaVersion = 'schemaVersion' in overrides;\n const hasModels = 'models' in overrides;\n const hasRelations = 'relations' in overrides;\n const hasStorage = 'storage' in overrides;\n const hasCapabilities = 'capabilities' in overrides;\n const hasExtensionPacks = 'extensionPacks' in overrides;\n const hasMeta = 'meta' in overrides;\n const hasSources = 'sources' in overrides;\n\n // Build header, omitting fields that are explicitly undefined\n const headerOpts: {\n target?: string;\n targetFamily?: string;\n coreHash?: string;\n profileHash?: string;\n } = {};\n\n if (hasTarget && overrides.target !== undefined) {\n headerOpts.target = overrides.target;\n } else if (!hasTarget) {\n headerOpts.target = 'postgres';\n }\n\n if (hasTargetFamily && overrides.targetFamily !== undefined) {\n headerOpts.targetFamily = overrides.targetFamily;\n } else if (!hasTargetFamily) {\n headerOpts.targetFamily = 'sql';\n }\n\n if (hasCoreHash && overrides.coreHash !== undefined) {\n headerOpts.coreHash = overrides.coreHash;\n } else if (!hasCoreHash) {\n headerOpts.coreHash = 'sha256:test';\n }\n\n // profileHash is not part of ContractIR, but we can accept it for header creation\n if (overrides.profileHash !== undefined) {\n headerOpts.profileHash = overrides.profileHash;\n }\n\n const header = irHeader(\n headerOpts as {\n target: string;\n targetFamily: string;\n coreHash: string;\n profileHash?: string;\n },\n );\n\n // Build meta, handling explicitly undefined fields\n // If a field is explicitly undefined, we'll omit it from the result later\n const metaOpts: {\n capabilities?: Record<string, Record<string, boolean>>;\n extensionPacks?: Record<string, unknown>;\n meta?: Record<string, unknown>;\n sources?: Record<string, unknown>;\n } = {};\n\n if (hasCapabilities && overrides.capabilities !== undefined) {\n metaOpts.capabilities = overrides.capabilities;\n } else if (!hasCapabilities) {\n metaOpts.capabilities = {};\n }\n\n if (hasExtensionPacks && overrides.extensionPacks !== undefined) {\n metaOpts.extensionPacks = overrides.extensionPacks;\n } else if (!hasExtensionPacks) {\n metaOpts.extensionPacks = {};\n }\n\n if (hasMeta && overrides.meta !== undefined) {\n metaOpts.meta = overrides.meta;\n } else if (!hasMeta) {\n metaOpts.meta = {};\n }\n\n if (hasSources && overrides.sources !== undefined) {\n metaOpts.sources = overrides.sources;\n } else if (!hasSources) {\n metaOpts.sources = {};\n }\n\n const meta = irMeta(Object.keys(metaOpts).length > 0 ? metaOpts : undefined);\n\n // Build result by constructing the object directly (ContractIR doesn't include coreHash/profileHash)\n // When fields are explicitly undefined, include them as undefined (tests use type assertions to bypass TS)\n const result = {\n schemaVersion:\n hasSchemaVersion && overrides.schemaVersion !== undefined\n ? overrides.schemaVersion\n : hasSchemaVersion && overrides.schemaVersion === undefined\n ? (undefined as unknown as string)\n : header.schemaVersion,\n target: header.target,\n targetFamily: header.targetFamily,\n // Only include meta fields if they're not explicitly undefined\n capabilities:\n hasCapabilities && overrides.capabilities === undefined\n ? (undefined as unknown as Record<string, Record<string, boolean>>)\n : !hasCapabilities || overrides.capabilities !== undefined\n ? meta.capabilities\n : ({} as Record<string, Record<string, boolean>>),\n extensionPacks:\n hasExtensionPacks && overrides.extensionPacks === undefined\n ? (undefined as unknown as Record<string, unknown>)\n : !hasExtensionPacks || overrides.extensionPacks !== undefined\n ? meta.extensionPacks\n : ({} as Record<string, unknown>),\n meta:\n hasMeta && overrides.meta === undefined\n ? (undefined as unknown as Record<string, unknown>)\n : !hasMeta || overrides.meta !== undefined\n ? meta.meta\n : ({} as Record<string, unknown>),\n sources:\n hasSources && overrides.sources === undefined\n ? (undefined as unknown as Record<string, unknown>)\n : !hasSources || overrides.sources !== undefined\n ? meta.sources\n : ({} as Record<string, unknown>),\n // Only include family sections if they're not explicitly undefined\n storage:\n hasStorage && overrides.storage === undefined\n ? (undefined as unknown as Record<string, unknown>)\n : hasStorage && overrides.storage !== undefined\n ? (overrides.storage as Record<string, unknown>)\n : !hasStorage\n ? ({ tables: {} } as Record<string, unknown>)\n : ({} as Record<string, unknown>),\n models:\n hasModels && overrides.models === undefined\n ? (undefined as unknown as Record<string, unknown>)\n : hasModels && overrides.models !== undefined\n ? (overrides.models as Record<string, unknown>)\n : !hasModels\n ? {}\n : ({} as Record<string, unknown>),\n relations:\n hasRelations && overrides.relations === undefined\n ? (undefined as unknown as Record<string, unknown>)\n : hasRelations && overrides.relations !== undefined\n ? (overrides.relations as Record<string, unknown>)\n : !hasRelations\n ? {}\n : ({} as Record<string, unknown>),\n } as ContractIR;\n\n return result;\n}\n"],"mappings":";;;;;;;;;;;AAUA,SAAgB,iBACd,YAA+E,EAAE,EACrE;CAEZ,MAAM,YAAY,YAAY;CAC9B,MAAM,kBAAkB,kBAAkB;CAC1C,MAAM,cAAc,cAAc;CAClC,MAAM,mBAAmB,mBAAmB;CAC5C,MAAM,YAAY,YAAY;CAC9B,MAAM,eAAe,eAAe;CACpC,MAAM,aAAa,aAAa;CAChC,MAAM,kBAAkB,kBAAkB;CAC1C,MAAM,oBAAoB,oBAAoB;CAC9C,MAAM,UAAU,UAAU;CAC1B,MAAM,aAAa,aAAa;CAGhC,MAAMA,aAKF,EAAE;AAEN,KAAI,aAAa,UAAU,WAAW,OACpC,YAAW,SAAS,UAAU;UACrB,CAAC,UACV,YAAW,SAAS;AAGtB,KAAI,mBAAmB,UAAU,iBAAiB,OAChD,YAAW,eAAe,UAAU;UAC3B,CAAC,gBACV,YAAW,eAAe;AAG5B,KAAI,eAAe,UAAU,aAAa,OACxC,YAAW,WAAW,UAAU;UACvB,CAAC,YACV,YAAW,WAAW;AAIxB,KAAI,UAAU,gBAAgB,OAC5B,YAAW,cAAc,UAAU;CAGrC,MAAM,SAAS,SACb,WAMD;CAID,MAAMC,WAKF,EAAE;AAEN,KAAI,mBAAmB,UAAU,iBAAiB,OAChD,UAAS,eAAe,UAAU;UACzB,CAAC,gBACV,UAAS,eAAe,EAAE;AAG5B,KAAI,qBAAqB,UAAU,mBAAmB,OACpD,UAAS,iBAAiB,UAAU;UAC3B,CAAC,kBACV,UAAS,iBAAiB,EAAE;AAG9B,KAAI,WAAW,UAAU,SAAS,OAChC,UAAS,OAAO,UAAU;UACjB,CAAC,QACV,UAAS,OAAO,EAAE;AAGpB,KAAI,cAAc,UAAU,YAAY,OACtC,UAAS,UAAU,UAAU;UACpB,CAAC,WACV,UAAS,UAAU,EAAE;CAGvB,MAAM,OAAO,OAAO,OAAO,KAAK,SAAS,CAAC,SAAS,IAAI,WAAW,OAAU;AAiE5E,QA7De;EACb,eACE,oBAAoB,UAAU,kBAAkB,SAC5C,UAAU,gBACV,oBAAoB,UAAU,kBAAkB,SAC7C,SACD,OAAO;EACf,QAAQ,OAAO;EACf,cAAc,OAAO;EAErB,cACE,mBAAmB,UAAU,iBAAiB,SACzC,SACD,CAAC,mBAAmB,UAAU,iBAAiB,SAC7C,KAAK,eACJ,EAAE;EACX,gBACE,qBAAqB,UAAU,mBAAmB,SAC7C,SACD,CAAC,qBAAqB,UAAU,mBAAmB,SACjD,KAAK,iBACJ,EAAE;EACX,MACE,WAAW,UAAU,SAAS,SACzB,SACD,CAAC,WAAW,UAAU,SAAS,SAC7B,KAAK,OACJ,EAAE;EACX,SACE,cAAc,UAAU,YAAY,SAC/B,SACD,CAAC,cAAc,UAAU,YAAY,SACnC,KAAK,UACJ,EAAE;EAEX,SACE,cAAc,UAAU,YAAY,SAC/B,SACD,cAAc,UAAU,YAAY,SACjC,UAAU,UACX,CAAC,aACE,EAAE,QAAQ,EAAE,EAAE,GACd,EAAE;EACb,QACE,aAAa,UAAU,WAAW,SAC7B,SACD,aAAa,UAAU,WAAW,SAC/B,UAAU,SACX,CAAC,YACC,EAAE,GACD,EAAE;EACb,WACE,gBAAgB,UAAU,cAAc,SACnC,SACD,gBAAgB,UAAU,cAAc,SACrC,UAAU,YACX,CAAC,eACC,EAAE,GACD,EAAE;EACd"}
|
package/package.json
CHANGED
|
@@ -1,39 +1,41 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma-next/emitter",
|
|
3
|
-
"version": "0.3.0-pr.
|
|
3
|
+
"version": "0.3.0-pr.94.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
|
+
"engines": {
|
|
7
|
+
"node": ">=20"
|
|
8
|
+
},
|
|
6
9
|
"files": [
|
|
7
10
|
"dist",
|
|
8
11
|
"src",
|
|
9
|
-
"test"
|
|
12
|
+
"test/utils.ts"
|
|
10
13
|
],
|
|
11
14
|
"dependencies": {
|
|
12
15
|
"arktype": "^2.0.0",
|
|
13
|
-
"@prisma-next/contract": "0.3.0-pr.
|
|
14
|
-
"@prisma-next/core-control-plane": "0.3.0-pr.
|
|
16
|
+
"@prisma-next/contract": "0.3.0-pr.94.1",
|
|
17
|
+
"@prisma-next/core-control-plane": "0.3.0-pr.94.1"
|
|
15
18
|
},
|
|
16
19
|
"devDependencies": {
|
|
17
20
|
"@types/node": "24.10.4",
|
|
18
|
-
"
|
|
21
|
+
"tsdown": "0.18.4",
|
|
19
22
|
"typescript": "5.9.3",
|
|
20
23
|
"vitest": "4.0.16",
|
|
21
|
-
"@prisma-next/operations": "0.3.0-pr.
|
|
24
|
+
"@prisma-next/operations": "0.3.0-pr.94.1",
|
|
22
25
|
"@prisma-next/test-utils": "0.0.1",
|
|
23
|
-
"@prisma-next/tsconfig": "0.0.0"
|
|
26
|
+
"@prisma-next/tsconfig": "0.0.0",
|
|
27
|
+
"@prisma-next/tsdown": "0.0.0"
|
|
24
28
|
},
|
|
25
29
|
"exports": {
|
|
26
|
-
".":
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
},
|
|
30
|
-
"./test/utils": {
|
|
31
|
-
"types": "./dist/test/utils.d.ts",
|
|
32
|
-
"import": "./dist/test/utils.js"
|
|
33
|
-
}
|
|
30
|
+
".": "./dist/index.mjs",
|
|
31
|
+
"./test/utils": "./dist/test/utils.mjs",
|
|
32
|
+
"./package.json": "./package.json"
|
|
34
33
|
},
|
|
34
|
+
"main": "./dist/index.mjs",
|
|
35
|
+
"module": "./dist/index.mjs",
|
|
36
|
+
"types": "./dist/index.d.mts",
|
|
35
37
|
"scripts": {
|
|
36
|
-
"build": "
|
|
38
|
+
"build": "tsdown",
|
|
37
39
|
"test": "vitest run",
|
|
38
40
|
"test:coverage": "vitest run --coverage",
|
|
39
41
|
"typecheck": "tsc --noEmit",
|
package/dist/exports/index.d.ts
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
export type { TargetFamilyHook, TypesImportSpec, ValidationContext, } from '@prisma-next/contract/types';
|
|
2
|
-
export type { EmitOptions, EmitResult } from '@prisma-next/core-control-plane/emission';
|
|
3
|
-
export { emit } from '@prisma-next/core-control-plane/emission';
|
|
4
|
-
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/exports/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,gBAAgB,EAChB,eAAe,EACf,iBAAiB,GAClB,MAAM,6BAA6B,CAAC;AACrC,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,0CAA0C,CAAC;AAExF,OAAO,EAAE,IAAI,EAAE,MAAM,0CAA0C,CAAC"}
|
package/dist/exports/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/exports/index.ts"],"sourcesContent":["// Re-export types from @prisma-next/contract for backward compatibility\nexport type {\n TargetFamilyHook,\n TypesImportSpec,\n ValidationContext,\n} from '@prisma-next/contract/types';\nexport type { EmitOptions, EmitResult } from '@prisma-next/core-control-plane/emission';\n// Re-export emit function and types from core-control-plane\nexport { emit } from '@prisma-next/core-control-plane/emission';\n"],"mappings":";AAQA,SAAS,YAAY;","names":[]}
|
package/dist/target-family.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"target-family.d.ts","sourceRoot":"","sources":["../src/target-family.ts"],"names":[],"mappings":"AAEA,YAAY,EACV,gBAAgB,EAChB,eAAe,EACf,iBAAiB,GAClB,MAAM,6BAA6B,CAAC"}
|
package/dist/test/utils.js
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
// test/utils.ts
|
|
2
|
-
import { irHeader, irMeta } from "@prisma-next/contract/ir";
|
|
3
|
-
function createContractIR(overrides = {}) {
|
|
4
|
-
const hasTarget = "target" in overrides;
|
|
5
|
-
const hasTargetFamily = "targetFamily" in overrides;
|
|
6
|
-
const hasCoreHash = "coreHash" in overrides;
|
|
7
|
-
const hasSchemaVersion = "schemaVersion" in overrides;
|
|
8
|
-
const hasModels = "models" in overrides;
|
|
9
|
-
const hasRelations = "relations" in overrides;
|
|
10
|
-
const hasStorage = "storage" in overrides;
|
|
11
|
-
const hasCapabilities = "capabilities" in overrides;
|
|
12
|
-
const hasExtensionPacks = "extensionPacks" in overrides;
|
|
13
|
-
const hasMeta = "meta" in overrides;
|
|
14
|
-
const hasSources = "sources" in overrides;
|
|
15
|
-
const headerOpts = {};
|
|
16
|
-
if (hasTarget && overrides.target !== void 0) {
|
|
17
|
-
headerOpts.target = overrides.target;
|
|
18
|
-
} else if (!hasTarget) {
|
|
19
|
-
headerOpts.target = "postgres";
|
|
20
|
-
}
|
|
21
|
-
if (hasTargetFamily && overrides.targetFamily !== void 0) {
|
|
22
|
-
headerOpts.targetFamily = overrides.targetFamily;
|
|
23
|
-
} else if (!hasTargetFamily) {
|
|
24
|
-
headerOpts.targetFamily = "sql";
|
|
25
|
-
}
|
|
26
|
-
if (hasCoreHash && overrides.coreHash !== void 0) {
|
|
27
|
-
headerOpts.coreHash = overrides.coreHash;
|
|
28
|
-
} else if (!hasCoreHash) {
|
|
29
|
-
headerOpts.coreHash = "sha256:test";
|
|
30
|
-
}
|
|
31
|
-
if (overrides.profileHash !== void 0) {
|
|
32
|
-
headerOpts.profileHash = overrides.profileHash;
|
|
33
|
-
}
|
|
34
|
-
const header = irHeader(
|
|
35
|
-
headerOpts
|
|
36
|
-
);
|
|
37
|
-
const metaOpts = {};
|
|
38
|
-
if (hasCapabilities && overrides.capabilities !== void 0) {
|
|
39
|
-
metaOpts.capabilities = overrides.capabilities;
|
|
40
|
-
} else if (!hasCapabilities) {
|
|
41
|
-
metaOpts.capabilities = {};
|
|
42
|
-
}
|
|
43
|
-
if (hasExtensionPacks && overrides.extensionPacks !== void 0) {
|
|
44
|
-
metaOpts.extensionPacks = overrides.extensionPacks;
|
|
45
|
-
} else if (!hasExtensionPacks) {
|
|
46
|
-
metaOpts.extensionPacks = {};
|
|
47
|
-
}
|
|
48
|
-
if (hasMeta && overrides.meta !== void 0) {
|
|
49
|
-
metaOpts.meta = overrides.meta;
|
|
50
|
-
} else if (!hasMeta) {
|
|
51
|
-
metaOpts.meta = {};
|
|
52
|
-
}
|
|
53
|
-
if (hasSources && overrides.sources !== void 0) {
|
|
54
|
-
metaOpts.sources = overrides.sources;
|
|
55
|
-
} else if (!hasSources) {
|
|
56
|
-
metaOpts.sources = {};
|
|
57
|
-
}
|
|
58
|
-
const meta = irMeta(Object.keys(metaOpts).length > 0 ? metaOpts : void 0);
|
|
59
|
-
const result = {
|
|
60
|
-
schemaVersion: hasSchemaVersion && overrides.schemaVersion !== void 0 ? overrides.schemaVersion : hasSchemaVersion && overrides.schemaVersion === void 0 ? void 0 : header.schemaVersion,
|
|
61
|
-
target: header.target,
|
|
62
|
-
targetFamily: header.targetFamily,
|
|
63
|
-
// Only include meta fields if they're not explicitly undefined
|
|
64
|
-
capabilities: hasCapabilities && overrides.capabilities === void 0 ? void 0 : !hasCapabilities || overrides.capabilities !== void 0 ? meta.capabilities : {},
|
|
65
|
-
extensionPacks: hasExtensionPacks && overrides.extensionPacks === void 0 ? void 0 : !hasExtensionPacks || overrides.extensionPacks !== void 0 ? meta.extensionPacks : {},
|
|
66
|
-
meta: hasMeta && overrides.meta === void 0 ? void 0 : !hasMeta || overrides.meta !== void 0 ? meta.meta : {},
|
|
67
|
-
sources: hasSources && overrides.sources === void 0 ? void 0 : !hasSources || overrides.sources !== void 0 ? meta.sources : {},
|
|
68
|
-
// Only include family sections if they're not explicitly undefined
|
|
69
|
-
storage: hasStorage && overrides.storage === void 0 ? void 0 : hasStorage && overrides.storage !== void 0 ? overrides.storage : !hasStorage ? { tables: {} } : {},
|
|
70
|
-
models: hasModels && overrides.models === void 0 ? void 0 : hasModels && overrides.models !== void 0 ? overrides.models : !hasModels ? {} : {},
|
|
71
|
-
relations: hasRelations && overrides.relations === void 0 ? void 0 : hasRelations && overrides.relations !== void 0 ? overrides.relations : !hasRelations ? {} : {}
|
|
72
|
-
};
|
|
73
|
-
return result;
|
|
74
|
-
}
|
|
75
|
-
export {
|
|
76
|
-
createContractIR
|
|
77
|
-
};
|
|
78
|
-
//# sourceMappingURL=utils.js.map
|
package/dist/test/utils.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../test/utils.ts"],"sourcesContent":["import { type ContractIR, irHeader, irMeta } from '@prisma-next/contract/ir';\n\n/**\n * Factory function for creating ContractIR objects in tests.\n * Provides sensible defaults and allows overriding specific fields.\n * Uses the emitter factories internally for consistency.\n *\n * If a field is explicitly set to `undefined` in overrides, it will be omitted\n * from the result (useful for testing validation of missing fields).\n */\nexport function createContractIR(\n overrides: Partial<ContractIR> & { coreHash?: string; profileHash?: string } = {},\n): ContractIR {\n // Check if fields are explicitly undefined (not just missing)\n const hasTarget = 'target' in overrides;\n const hasTargetFamily = 'targetFamily' in overrides;\n const hasCoreHash = 'coreHash' in overrides;\n const hasSchemaVersion = 'schemaVersion' in overrides;\n const hasModels = 'models' in overrides;\n const hasRelations = 'relations' in overrides;\n const hasStorage = 'storage' in overrides;\n const hasCapabilities = 'capabilities' in overrides;\n const hasExtensionPacks = 'extensionPacks' in overrides;\n const hasMeta = 'meta' in overrides;\n const hasSources = 'sources' in overrides;\n\n // Build header, omitting fields that are explicitly undefined\n const headerOpts: {\n target?: string;\n targetFamily?: string;\n coreHash?: string;\n profileHash?: string;\n } = {};\n\n if (hasTarget && overrides.target !== undefined) {\n headerOpts.target = overrides.target;\n } else if (!hasTarget) {\n headerOpts.target = 'postgres';\n }\n\n if (hasTargetFamily && overrides.targetFamily !== undefined) {\n headerOpts.targetFamily = overrides.targetFamily;\n } else if (!hasTargetFamily) {\n headerOpts.targetFamily = 'sql';\n }\n\n if (hasCoreHash && overrides.coreHash !== undefined) {\n headerOpts.coreHash = overrides.coreHash;\n } else if (!hasCoreHash) {\n headerOpts.coreHash = 'sha256:test';\n }\n\n // profileHash is not part of ContractIR, but we can accept it for header creation\n if (overrides.profileHash !== undefined) {\n headerOpts.profileHash = overrides.profileHash;\n }\n\n const header = irHeader(\n headerOpts as {\n target: string;\n targetFamily: string;\n coreHash: string;\n profileHash?: string;\n },\n );\n\n // Build meta, handling explicitly undefined fields\n // If a field is explicitly undefined, we'll omit it from the result later\n const metaOpts: {\n capabilities?: Record<string, Record<string, boolean>>;\n extensionPacks?: Record<string, unknown>;\n meta?: Record<string, unknown>;\n sources?: Record<string, unknown>;\n } = {};\n\n if (hasCapabilities && overrides.capabilities !== undefined) {\n metaOpts.capabilities = overrides.capabilities;\n } else if (!hasCapabilities) {\n metaOpts.capabilities = {};\n }\n\n if (hasExtensionPacks && overrides.extensionPacks !== undefined) {\n metaOpts.extensionPacks = overrides.extensionPacks;\n } else if (!hasExtensionPacks) {\n metaOpts.extensionPacks = {};\n }\n\n if (hasMeta && overrides.meta !== undefined) {\n metaOpts.meta = overrides.meta;\n } else if (!hasMeta) {\n metaOpts.meta = {};\n }\n\n if (hasSources && overrides.sources !== undefined) {\n metaOpts.sources = overrides.sources;\n } else if (!hasSources) {\n metaOpts.sources = {};\n }\n\n const meta = irMeta(Object.keys(metaOpts).length > 0 ? metaOpts : undefined);\n\n // Build result by constructing the object directly (ContractIR doesn't include coreHash/profileHash)\n // When fields are explicitly undefined, include them as undefined (tests use type assertions to bypass TS)\n const result = {\n schemaVersion:\n hasSchemaVersion && overrides.schemaVersion !== undefined\n ? overrides.schemaVersion\n : hasSchemaVersion && overrides.schemaVersion === undefined\n ? (undefined as unknown as string)\n : header.schemaVersion,\n target: header.target,\n targetFamily: header.targetFamily,\n // Only include meta fields if they're not explicitly undefined\n capabilities:\n hasCapabilities && overrides.capabilities === undefined\n ? (undefined as unknown as Record<string, Record<string, boolean>>)\n : !hasCapabilities || overrides.capabilities !== undefined\n ? meta.capabilities\n : ({} as Record<string, Record<string, boolean>>),\n extensionPacks:\n hasExtensionPacks && overrides.extensionPacks === undefined\n ? (undefined as unknown as Record<string, unknown>)\n : !hasExtensionPacks || overrides.extensionPacks !== undefined\n ? meta.extensionPacks\n : ({} as Record<string, unknown>),\n meta:\n hasMeta && overrides.meta === undefined\n ? (undefined as unknown as Record<string, unknown>)\n : !hasMeta || overrides.meta !== undefined\n ? meta.meta\n : ({} as Record<string, unknown>),\n sources:\n hasSources && overrides.sources === undefined\n ? (undefined as unknown as Record<string, unknown>)\n : !hasSources || overrides.sources !== undefined\n ? meta.sources\n : ({} as Record<string, unknown>),\n // Only include family sections if they're not explicitly undefined\n storage:\n hasStorage && overrides.storage === undefined\n ? (undefined as unknown as Record<string, unknown>)\n : hasStorage && overrides.storage !== undefined\n ? (overrides.storage as Record<string, unknown>)\n : !hasStorage\n ? ({ tables: {} } as Record<string, unknown>)\n : ({} as Record<string, unknown>),\n models:\n hasModels && overrides.models === undefined\n ? (undefined as unknown as Record<string, unknown>)\n : hasModels && overrides.models !== undefined\n ? (overrides.models as Record<string, unknown>)\n : !hasModels\n ? {}\n : ({} as Record<string, unknown>),\n relations:\n hasRelations && overrides.relations === undefined\n ? (undefined as unknown as Record<string, unknown>)\n : hasRelations && overrides.relations !== undefined\n ? (overrides.relations as Record<string, unknown>)\n : !hasRelations\n ? {}\n : ({} as Record<string, unknown>),\n } as ContractIR;\n\n return result;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,210 +0,0 @@
|
|
|
1
|
-
import { canonicalizeContract } from '@prisma-next/core-control-plane/emission';
|
|
2
|
-
import { describe, expect, it } from 'vitest';
|
|
3
|
-
import { createContractIR } from './utils';
|
|
4
|
-
|
|
5
|
-
describe('canonicalization', () => {
|
|
6
|
-
it('orders top-level sections correctly', () => {
|
|
7
|
-
const ir = createContractIR({
|
|
8
|
-
capabilities: { postgres: { jsonAgg: true } },
|
|
9
|
-
meta: { source: 'test' },
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
const result = canonicalizeContract(ir);
|
|
13
|
-
const parsed = JSON.parse(result) as Record<string, unknown>;
|
|
14
|
-
|
|
15
|
-
const keys = Object.keys(parsed);
|
|
16
|
-
const schemaVersionIndex = keys.indexOf('schemaVersion');
|
|
17
|
-
const targetFamilyIndex = keys.indexOf('targetFamily');
|
|
18
|
-
const targetIndex = keys.indexOf('target');
|
|
19
|
-
const modelsIndex = keys.indexOf('models');
|
|
20
|
-
const storageIndex = keys.indexOf('storage');
|
|
21
|
-
const capabilitiesIndex = keys.indexOf('capabilities');
|
|
22
|
-
const metaIndex = keys.indexOf('meta');
|
|
23
|
-
|
|
24
|
-
expect(schemaVersionIndex).toBeLessThan(targetFamilyIndex);
|
|
25
|
-
expect(targetFamilyIndex).toBeLessThan(targetIndex);
|
|
26
|
-
expect(targetIndex).toBeLessThan(modelsIndex);
|
|
27
|
-
expect(modelsIndex).toBeLessThan(storageIndex);
|
|
28
|
-
expect(storageIndex).toBeLessThan(capabilitiesIndex);
|
|
29
|
-
expect(capabilitiesIndex).toBeLessThan(metaIndex);
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
it('omits nullable false from columns', () => {
|
|
33
|
-
const ir = createContractIR({
|
|
34
|
-
storage: {
|
|
35
|
-
tables: {
|
|
36
|
-
user: {
|
|
37
|
-
columns: {
|
|
38
|
-
id: { codecId: 'pg/int4@1', nativeType: 'int4', nullable: false },
|
|
39
|
-
email: { codecId: 'pg/text@1', nativeType: 'text', nullable: true },
|
|
40
|
-
},
|
|
41
|
-
},
|
|
42
|
-
},
|
|
43
|
-
},
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
const result = canonicalizeContract(ir);
|
|
47
|
-
const parsed = JSON.parse(result) as Record<string, unknown>;
|
|
48
|
-
const storage = parsed['storage'] as Record<string, unknown>;
|
|
49
|
-
const tables = storage['tables'] as Record<string, unknown>;
|
|
50
|
-
const user = tables['user'] as Record<string, unknown>;
|
|
51
|
-
const columns = user['columns'] as Record<string, unknown>;
|
|
52
|
-
const id = columns['id'] as Record<string, unknown>;
|
|
53
|
-
const email = columns['email'] as Record<string, unknown>;
|
|
54
|
-
expect(id['nullable']).toBeUndefined();
|
|
55
|
-
expect(email['nullable']).toBe(true);
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
it('omits empty arrays and objects except required ones', () => {
|
|
59
|
-
const ir = createContractIR();
|
|
60
|
-
|
|
61
|
-
const result = canonicalizeContract(ir);
|
|
62
|
-
const parsed = JSON.parse(result);
|
|
63
|
-
expect(parsed).toMatchObject({
|
|
64
|
-
models: expect.anything(),
|
|
65
|
-
storage: {
|
|
66
|
-
tables: expect.anything(),
|
|
67
|
-
},
|
|
68
|
-
});
|
|
69
|
-
// Required top-level fields (capabilities, extensionPacks, meta, relations, sources) are preserved even when empty
|
|
70
|
-
// because they are required by ContractIR and needed for round-trip tests
|
|
71
|
-
expect(parsed).toMatchObject({
|
|
72
|
-
capabilities: expect.anything(),
|
|
73
|
-
extensionPacks: expect.anything(),
|
|
74
|
-
meta: expect.anything(),
|
|
75
|
-
relations: expect.anything(),
|
|
76
|
-
sources: expect.anything(),
|
|
77
|
-
});
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
it('preserves semantic array order for column lists', () => {
|
|
81
|
-
const ir = createContractIR({
|
|
82
|
-
storage: {
|
|
83
|
-
tables: {
|
|
84
|
-
user: {
|
|
85
|
-
columns: {
|
|
86
|
-
first: { codecId: 'pg/text@1', nativeType: 'text', nullable: false },
|
|
87
|
-
second: { codecId: 'pg/text@1', nativeType: 'text', nullable: false },
|
|
88
|
-
},
|
|
89
|
-
primaryKey: {
|
|
90
|
-
columns: ['second', 'first'],
|
|
91
|
-
},
|
|
92
|
-
},
|
|
93
|
-
},
|
|
94
|
-
},
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
const result1 = canonicalizeContract(ir);
|
|
98
|
-
|
|
99
|
-
const ir2 = createContractIR({
|
|
100
|
-
storage: {
|
|
101
|
-
tables: {
|
|
102
|
-
user: {
|
|
103
|
-
columns: {
|
|
104
|
-
first: { codecId: 'pg/text@1', nativeType: 'text', nullable: false },
|
|
105
|
-
second: { codecId: 'pg/text@1', nativeType: 'text', nullable: false },
|
|
106
|
-
},
|
|
107
|
-
primaryKey: {
|
|
108
|
-
columns: ['first', 'second'],
|
|
109
|
-
},
|
|
110
|
-
},
|
|
111
|
-
},
|
|
112
|
-
},
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
const result2 = canonicalizeContract(ir2);
|
|
116
|
-
|
|
117
|
-
expect(result1).not.toBe(result2);
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
it('sorts non-semantic arrays by canonical name', () => {
|
|
121
|
-
const ir = createContractIR({
|
|
122
|
-
storage: {
|
|
123
|
-
tables: {
|
|
124
|
-
user: {
|
|
125
|
-
columns: {
|
|
126
|
-
id: { codecId: 'pg/int4@1', nativeType: 'int4', nullable: false },
|
|
127
|
-
},
|
|
128
|
-
indexes: [
|
|
129
|
-
{ columns: ['id'], name: 'user_email_idx' },
|
|
130
|
-
{ columns: ['id'], name: 'user_name_idx' },
|
|
131
|
-
],
|
|
132
|
-
},
|
|
133
|
-
},
|
|
134
|
-
},
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
const result = canonicalizeContract(ir);
|
|
138
|
-
const parsed = JSON.parse(result) as Record<string, unknown>;
|
|
139
|
-
const storage = parsed['storage'] as Record<string, unknown>;
|
|
140
|
-
const tables = storage['tables'] as Record<string, unknown>;
|
|
141
|
-
const user = tables['user'] as Record<string, unknown>;
|
|
142
|
-
const indexes = user['indexes'] as Array<{ name: string }>;
|
|
143
|
-
const indexNames = indexes.map((idx) => idx.name);
|
|
144
|
-
expect(indexNames).toEqual(['user_email_idx', 'user_name_idx']);
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
it('sorts nested object keys lexicographically', () => {
|
|
148
|
-
const ir = createContractIR({
|
|
149
|
-
storage: {
|
|
150
|
-
tables: {
|
|
151
|
-
user: {
|
|
152
|
-
columns: {
|
|
153
|
-
z_field: { codecId: 'pg/text@1', nativeType: 'text', nullable: false },
|
|
154
|
-
a_field: { codecId: 'pg/text@1', nativeType: 'text', nullable: false },
|
|
155
|
-
m_field: { codecId: 'pg/text@1', nativeType: 'text', nullable: false },
|
|
156
|
-
},
|
|
157
|
-
},
|
|
158
|
-
},
|
|
159
|
-
},
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
const result = canonicalizeContract(ir);
|
|
163
|
-
const parsed = JSON.parse(result) as Record<string, unknown>;
|
|
164
|
-
const storage = parsed['storage'] as Record<string, unknown>;
|
|
165
|
-
const tables = storage['tables'] as Record<string, unknown>;
|
|
166
|
-
const user = tables['user'] as Record<string, unknown>;
|
|
167
|
-
const columns = user['columns'] as Record<string, unknown>;
|
|
168
|
-
const columnKeys = Object.keys(columns);
|
|
169
|
-
expect(columnKeys).toEqual(['a_field', 'm_field', 'z_field']);
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
it('sorts extension namespaces lexicographically', () => {
|
|
173
|
-
const ir = createContractIR({
|
|
174
|
-
extensionPacks: {
|
|
175
|
-
pgvector: { version: '0.0.1' },
|
|
176
|
-
postgres: { version: '0.0.1' },
|
|
177
|
-
another: { version: '0.0.1' },
|
|
178
|
-
},
|
|
179
|
-
});
|
|
180
|
-
|
|
181
|
-
const result = canonicalizeContract(ir);
|
|
182
|
-
const parsed = JSON.parse(result) as Record<string, unknown>;
|
|
183
|
-
const extensionPacks = parsed['extensionPacks'] as Record<string, unknown>;
|
|
184
|
-
const extensionKeys = Object.keys(extensionPacks);
|
|
185
|
-
expect(extensionKeys).toEqual(['another', 'pgvector', 'postgres']);
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
it('omits generated false', () => {
|
|
189
|
-
const ir = createContractIR({
|
|
190
|
-
storage: {
|
|
191
|
-
tables: {
|
|
192
|
-
user: {
|
|
193
|
-
columns: {
|
|
194
|
-
id: { codecId: 'pg/int4@1', nativeType: 'int4', nullable: false, generated: false },
|
|
195
|
-
},
|
|
196
|
-
},
|
|
197
|
-
},
|
|
198
|
-
},
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
const result = canonicalizeContract(ir);
|
|
202
|
-
const parsed = JSON.parse(result) as Record<string, unknown>;
|
|
203
|
-
const storage = parsed['storage'] as Record<string, unknown>;
|
|
204
|
-
const tables = storage['tables'] as Record<string, unknown>;
|
|
205
|
-
const user = tables['user'] as Record<string, unknown>;
|
|
206
|
-
const columns = user['columns'] as Record<string, unknown>;
|
|
207
|
-
const id = columns['id'] as Record<string, unknown>;
|
|
208
|
-
expect(id['generated']).toBeUndefined();
|
|
209
|
-
});
|
|
210
|
-
});
|