@prisma-next/emitter 0.1.0-dev.3 → 0.1.0-dev.30
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/README.md +3 -4
- package/dist/test/utils.d.ts +16 -0
- package/dist/test/utils.js +78 -0
- package/dist/test/utils.js.map +1 -0
- package/package.json +13 -6
package/README.md
CHANGED
|
@@ -21,7 +21,7 @@ Provide a deterministic, verifiable representation of the application's data con
|
|
|
21
21
|
- **Validate**: Core structure validation plus family-specific type and structure validation via hooks
|
|
22
22
|
- **Canonicalize**: Compute `coreHash` (schema meaning) and `profileHash` (capabilities/pins) from canonical JSON
|
|
23
23
|
- **Emit**: Generate `contract.json` and `contract.d.ts` with family-specific type generation
|
|
24
|
-
- **
|
|
24
|
+
- **Descriptor-Agnostic**: The emitter is completely agnostic to how descriptors are produced. It receives pre-assembled `OperationRegistry`, `codecTypeImports`, `operationTypeImports`, and `extensionIds` from the CLI or family helpers—no pack manifest parsing happens inside the emitter.
|
|
25
25
|
|
|
26
26
|
**Note**: The emitter does NOT normalize contracts. Normalization must happen in the contract builder when the contract is created. The emitter assumes contracts are already normalized (all required fields present, including `schemaVersion`, `models`, `relations`, `storage`, `extensions`, `capabilities`, `meta`, and `sources`). All fields can be empty objects/arrays, but they must be present.
|
|
27
27
|
|
|
@@ -98,7 +98,7 @@ flowchart TD
|
|
|
98
98
|
- Excludes `_generated` metadata field from canonicalization to ensure determinism
|
|
99
99
|
- Sorts object keys, omits default values, and orders top-level fields consistently
|
|
100
100
|
|
|
101
|
-
**Note**: Extension pack
|
|
101
|
+
**Note**: Extension pack descriptor wiring happens in the CLI/family layer. The emitter only sees the resulting registry/type import arrays and extension IDs. Operation manifest types (`OperationManifest`) live in `@prisma-next/contract/types`.
|
|
102
102
|
|
|
103
103
|
**Note**: `TargetFamilyHook`, `ValidationContext`, and `TypesImportSpec` types are defined in `@prisma-next/contract/types` (shared plane) to allow both migration-plane (emitter) and shared-plane (control-plane) packages to import them without violating dependency rules. These types are re-exported from this package for backward compatibility.
|
|
104
104
|
|
|
@@ -112,7 +112,7 @@ This package is part of the **framework domain**, **tooling layer**, **migration
|
|
|
112
112
|
- **Domain**: framework (target-agnostic)
|
|
113
113
|
- **Layer**: tooling
|
|
114
114
|
- **Plane**: migration
|
|
115
|
-
- **Path**: `packages/framework/tooling/emitter`
|
|
115
|
+
- **Path**: `packages/1-framework/3-tooling/emitter`
|
|
116
116
|
|
|
117
117
|
## Related Subsystems
|
|
118
118
|
|
|
@@ -187,5 +187,4 @@ This ensures all required fields are present with sensible defaults. See `.curso
|
|
|
187
187
|
## Exports
|
|
188
188
|
|
|
189
189
|
- `.`: Main emitter API (`emit`, types)
|
|
190
|
-
- **Note**: Pack loading functions (`loadExtensionPacks`, `loadExtensionPackManifest`) are CLI-only and not exported from the emitter. Import them from `@prisma-next/cli` or use the CLI's `pack-loading.ts` module directly.
|
|
191
190
|
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ContractIR } from '@prisma-next/contract/ir';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Factory function for creating ContractIR objects in tests.
|
|
5
|
+
* Provides sensible defaults and allows overriding specific fields.
|
|
6
|
+
* Uses the emitter factories internally for consistency.
|
|
7
|
+
*
|
|
8
|
+
* If a field is explicitly set to `undefined` in overrides, it will be omitted
|
|
9
|
+
* from the result (useful for testing validation of missing fields).
|
|
10
|
+
*/
|
|
11
|
+
declare function createContractIR(overrides?: Partial<ContractIR> & {
|
|
12
|
+
coreHash?: string;
|
|
13
|
+
profileHash?: string;
|
|
14
|
+
}): ContractIR;
|
|
15
|
+
|
|
16
|
+
export { createContractIR };
|
|
@@ -0,0 +1,78 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma-next/emitter",
|
|
3
|
-
"version": "0.1.0-dev.
|
|
3
|
+
"version": "0.1.0-dev.30",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"files": [
|
|
@@ -8,21 +8,26 @@
|
|
|
8
8
|
],
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"arktype": "^2.0.0",
|
|
11
|
-
"@prisma-next/contract": "0.1.0-dev.
|
|
12
|
-
"@prisma-next/core-control-plane": "0.1.0-dev.
|
|
11
|
+
"@prisma-next/contract": "0.1.0-dev.30",
|
|
12
|
+
"@prisma-next/core-control-plane": "0.1.0-dev.30"
|
|
13
13
|
},
|
|
14
14
|
"devDependencies": {
|
|
15
|
-
"@types/node": "
|
|
15
|
+
"@types/node": "24.10.4",
|
|
16
|
+
"@vitest/coverage-v8": "^4.0.0",
|
|
16
17
|
"tsup": "^8.3.0",
|
|
17
18
|
"typescript": "^5.9.3",
|
|
18
|
-
"vitest": "^
|
|
19
|
-
"@prisma-next/operations": "0.1.0-dev.
|
|
19
|
+
"vitest": "^4.0.16",
|
|
20
|
+
"@prisma-next/operations": "0.1.0-dev.30",
|
|
20
21
|
"@prisma-next/test-utils": "0.0.1"
|
|
21
22
|
},
|
|
22
23
|
"exports": {
|
|
23
24
|
".": {
|
|
24
25
|
"types": "./dist/exports/index.d.ts",
|
|
25
26
|
"import": "./dist/exports/index.js"
|
|
27
|
+
},
|
|
28
|
+
"./test/utils": {
|
|
29
|
+
"types": "./dist/test/utils.d.ts",
|
|
30
|
+
"import": "./dist/test/utils.js"
|
|
26
31
|
}
|
|
27
32
|
},
|
|
28
33
|
"scripts": {
|
|
@@ -31,6 +36,8 @@
|
|
|
31
36
|
"test:coverage": "vitest run --coverage",
|
|
32
37
|
"typecheck": "tsc --project tsconfig.json --noEmit",
|
|
33
38
|
"lint": "biome check . --config-path ../../../../biome.json --error-on-warnings",
|
|
39
|
+
"lint:fix": "biome check --write . --config-path ../../../../biome.json",
|
|
40
|
+
"lint:fix:unsafe": "biome check --write --unsafe . --config-path ../../../../biome.json",
|
|
34
41
|
"clean": "node ../../../../scripts/clean.mjs"
|
|
35
42
|
}
|
|
36
43
|
}
|