@prisma-next/emitter 0.5.0-dev.9 → 0.5.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/README.md +1 -2
- package/dist/domain-type-generation.d.mts +11 -5
- package/dist/domain-type-generation.d.mts.map +1 -1
- package/dist/domain-type-generation.mjs +13 -16
- package/dist/domain-type-generation.mjs.map +1 -1
- package/dist/exports/index.d.mts +1 -2
- package/dist/exports/index.d.mts.map +1 -1
- package/dist/exports/index.mjs +11 -11
- package/dist/exports/index.mjs.map +1 -1
- package/dist/test/utils.d.mts.map +1 -1
- package/dist/test/utils.mjs +1 -2
- package/dist/test/utils.mjs.map +1 -1
- package/dist/type-expression-safety.d.mts.map +1 -1
- package/dist/type-expression-safety.mjs +7 -2
- package/dist/type-expression-safety.mjs.map +1 -0
- package/package.json +10 -9
- package/src/domain-type-generation.ts +31 -10
- package/src/emit-types.ts +0 -1
- package/src/emit.ts +1 -2
- package/src/generate-contract-dts.ts +10 -4
- package/dist/type-expression-safety-7_1tfJXA.mjs +0 -8
- package/dist/type-expression-safety-7_1tfJXA.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -25,7 +25,7 @@ Provide a deterministic, verifiable representation of the application's data con
|
|
|
25
25
|
- **Validate**: Core structure validation (family-specific validation is the caller's responsibility)
|
|
26
26
|
- **Canonicalize**: Compute `storageHash` (schema meaning), `executionHash` (execution defaults), and `profileHash` (capabilities/pins) from canonical JSON
|
|
27
27
|
- **Emit**: Generate `contract.json` and `contract.d.ts` with family-specific type generation
|
|
28
|
-
- **Descriptor-Agnostic**: The emitter is completely agnostic to how descriptors are produced. It receives pre-assembled `OperationRegistry`, `codecTypeImports`,
|
|
28
|
+
- **Descriptor-Agnostic**: The emitter is completely agnostic to how descriptors are produced. It receives pre-assembled `OperationRegistry`, `codecTypeImports`, and `extensionIds` from the CLI or family helpers—no pack manifest parsing happens inside the emitter.
|
|
29
29
|
|
|
30
30
|
**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.
|
|
31
31
|
|
|
@@ -162,7 +162,6 @@ const result = await emit(contract, {
|
|
|
162
162
|
outputDir: './dist',
|
|
163
163
|
operationRegistry: createOperationRegistry(), // Pre-assembled from packs
|
|
164
164
|
codecTypeImports: [], // Extracted from packs (codec types)
|
|
165
|
-
operationTypeImports: [], // Extracted from packs (operation types)
|
|
166
165
|
extensionIds: ['postgres', 'pg'], // Extracted from packs
|
|
167
166
|
}, sqlEmission);
|
|
168
167
|
|
|
@@ -23,16 +23,22 @@ type ResolvedFieldType = {
|
|
|
23
23
|
readonly input: string;
|
|
24
24
|
readonly output: string;
|
|
25
25
|
};
|
|
26
|
-
|
|
26
|
+
/**
|
|
27
|
+
* Per-family resolver for typeParams that don't live inline on the framework-domain `ContractField`. SQL columns authored via a named `storage.types` entry carry their `typeRef` on the storage column (family-specific) rather than on the framework's domain field; the per-family emitter walks `storage.types[ref].typeParams` here so the framework emit path can render the parameterized output type.
|
|
28
|
+
*
|
|
29
|
+
* Returns `undefined` when the field has no resolvable typeParams (i.e. the column isn't parameterized, isn't a `typeRef`, or the family doesn't support named storage types).
|
|
30
|
+
*/
|
|
31
|
+
type FieldTypeParamsResolver = (modelName: string, fieldName: string) => Record<string, unknown> | undefined;
|
|
32
|
+
declare function resolveFieldType(field: ContractField, codecLookup?: CodecLookup, resolvedTypeParams?: Record<string, unknown>): ResolvedFieldType;
|
|
27
33
|
declare function generateFieldResolvedType(field: ContractField, codecLookup?: CodecLookup, side?: 'input' | 'output'): string;
|
|
28
|
-
declare function generateBothFieldTypesMaps(models: Record<string, ContractModel> | undefined, codecLookup?: CodecLookup): ResolvedFieldType;
|
|
29
|
-
declare function generateFieldOutputTypesMap(models: Record<string, ContractModel> | undefined, codecLookup?: CodecLookup): string;
|
|
30
|
-
declare function generateFieldInputTypesMap(models: Record<string, ContractModel> | undefined, codecLookup?: CodecLookup): string;
|
|
34
|
+
declare function generateBothFieldTypesMaps(models: Record<string, ContractModel> | undefined, codecLookup?: CodecLookup, resolveFieldTypeParams?: FieldTypeParamsResolver): ResolvedFieldType;
|
|
35
|
+
declare function generateFieldOutputTypesMap(models: Record<string, ContractModel> | undefined, codecLookup?: CodecLookup, resolveFieldTypeParams?: FieldTypeParamsResolver): string;
|
|
36
|
+
declare function generateFieldInputTypesMap(models: Record<string, ContractModel> | undefined, codecLookup?: CodecLookup, resolveFieldTypeParams?: FieldTypeParamsResolver): string;
|
|
31
37
|
declare function generateValueObjectType(_voName: string, vo: ContractValueObject, _valueObjects: Record<string, ContractValueObject>, side?: 'input' | 'output', codecLookup?: CodecLookup): string;
|
|
32
38
|
declare function resolveValueObjectType(_voName: string, vo: ContractValueObject, _valueObjects: Record<string, ContractValueObject>, codecLookup?: CodecLookup): ResolvedFieldType;
|
|
33
39
|
declare function generateContractFieldDescriptor(fieldName: string, field: ContractField): string;
|
|
34
40
|
declare function generateValueObjectsDescriptorType(valueObjects: Record<string, ContractValueObject> | undefined): string;
|
|
35
41
|
declare function generateValueObjectTypeAliases(valueObjects: Record<string, ContractValueObject> | undefined, codecLookup?: CodecLookup): string;
|
|
36
42
|
//#endregion
|
|
37
|
-
export { ResolvedFieldType, deduplicateImports, generateBothFieldTypesMaps, generateCodecTypeIntersection, generateContractFieldDescriptor, generateFieldInputTypesMap, generateFieldOutputTypesMap, generateFieldResolvedType, generateHashTypeAliases, generateImportLines, generateModelFieldEntry, generateModelFieldsType, generateModelRelationsType, generateModelsType, generateRootsType, generateValueObjectType, generateValueObjectTypeAliases, generateValueObjectsDescriptorType, resolveFieldType, resolveValueObjectType, serializeExecutionType, serializeObjectKey, serializeValue };
|
|
43
|
+
export { FieldTypeParamsResolver, ResolvedFieldType, deduplicateImports, generateBothFieldTypesMaps, generateCodecTypeIntersection, generateContractFieldDescriptor, generateFieldInputTypesMap, generateFieldOutputTypesMap, generateFieldResolvedType, generateHashTypeAliases, generateImportLines, generateModelFieldEntry, generateModelFieldsType, generateModelRelationsType, generateModelsType, generateRootsType, generateValueObjectType, generateValueObjectTypeAliases, generateValueObjectsDescriptorType, resolveFieldType, resolveValueObjectType, serializeExecutionType, serializeObjectKey, serializeValue };
|
|
38
44
|
//# sourceMappingURL=domain-type-generation.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"domain-type-generation.d.mts","names":[],"sources":["../src/domain-type-generation.ts"],"
|
|
1
|
+
{"version":3,"file":"domain-type-generation.d.mts","names":[],"sources":["../src/domain-type-generation.ts"],"mappings":";;;;;iBASgB,cAAA,CAAe,KAAA;AAAA,iBA+Bf,kBAAA,CAAmB,GAAA;AAAA,iBAOnB,iBAAA,CAAkB,KAAA,EAAO,MAAA;AAAA,iBAgBzB,uBAAA,CAAwB,SAAA,UAAmB,KAAA,EAAO,aAAA;AAAA,iBAgBlD,uBAAA,CAAwB,MAAA,EAAQ,MAAA,SAAe,aAAA;AAAA,iBAQ/C,0BAAA,CAA2B,SAAA,EAAW,MAAA;AAAA,iBAsCtC,kBAAA,CACd,MAAA,EAAQ,MAAA,SAAe,aAAA,GACvB,oBAAA,GAAuB,SAAA,UAAmB,KAAA,EAAO,aAAA;AAAA,iBAqCnC,kBAAA,CAAmB,OAAA,EAAS,eAAA,KAAoB,eAAA;AAAA,iBAahD,mBAAA,CAAoB,OAAA,EAAS,eAAA;AAAA,iBAO7B,6BAAA,CACd,OAAA,EAAS,aAAA,CAAc,eAAA,GACvB,KAAA;AAAA,iBAMc,sBAAA,CAAuB,SAAA,EAAW,MAAA;AAAA,iBASlC,uBAAA,CAAwB,MAAA;EAAA,SAC7B,WAAA;EAAA,SACA,aAAA;EAAA,SACA,WAAA;AAAA;AAAA,KAaC,iBAAA;EAAA,SAA+B,KAAA;EAAA,SAAwB,MAAA;AAAA;;;;;;KAevD,uBAAA,IACV,SAAA,UACA,SAAA,aACG,MAAA;AAAA,iBAEW,gBAAA,CACd,KAAA,EAAO,aAAA,EACP,WAAA,GAAc,WAAA,EACd,kBAAA,GAAqB,MAAA,oBACpB,iBAAA;AAAA,iBAkDa,yBAAA,CACd,KAAA,EAAO,aAAA,EACP,WAAA,GAAc,WAAA,EACd,IAAA;AAAA,iBAKc,0BAAA,CACd,MAAA,EAAQ,MAAA,SAAe,aAAA,eACvB,WAAA,GAAc,WAAA,EACd,sBAAA,GAAyB,uBAAA,GACxB,iBAAA;AAAA,iBA2Ca,2BAAA,CACd,MAAA,EAAQ,MAAA,SAAe,aAAA,eACvB,WAAA,GAAc,WAAA,EACd,sBAAA,GAAyB,uBAAA;AAAA,iBAKX,0BAAA,CACd,MAAA,EAAQ,MAAA,SAAe,aAAA,eACvB,WAAA,GAAc,WAAA,EACd,sBAAA,GAAyB,uBAAA;AAAA,iBAKX,uBAAA,CACd,OAAA,UACA,EAAA,EAAI,mBAAA,EACJ,aAAA,EAAe,MAAA,SAAe,mBAAA,GAC9B,IAAA,uBACA,WAAA,GAAc,WAAA;AAAA,iBAKA,sBAAA,CACd,OAAA,UACA,EAAA,EAAI,mBAAA,EACJ,aAAA,EAAe,MAAA,SAAe,mBAAA,GAC9B,WAAA,GAAc,WAAA,GACb,iBAAA;AAAA,iBAgBa,+BAAA,CAAgC,SAAA,UAAmB,KAAA,EAAO,aAAA;AAAA,iBAoB1D,kCAAA,CACd,YAAA,EAAc,MAAA,SAAe,mBAAA;AAAA,iBAoBf,8BAAA,CACd,YAAA,EAAc,MAAA,SAAe,mBAAA,eAC7B,WAAA,GAAc,WAAA"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { isSafeTypeExpression } from "./type-expression-safety.mjs";
|
|
3
2
|
//#region src/domain-type-generation.ts
|
|
4
3
|
function serializeValue(value) {
|
|
5
4
|
if (value === null) return "null";
|
|
@@ -124,17 +123,15 @@ function applyModifiers(base, field) {
|
|
|
124
123
|
if (field.nullable) result = `${result} | null`;
|
|
125
124
|
return result;
|
|
126
125
|
}
|
|
127
|
-
function resolveFieldType(field, codecLookup) {
|
|
126
|
+
function resolveFieldType(field, codecLookup, resolvedTypeParams) {
|
|
128
127
|
const { type } = field;
|
|
129
128
|
switch (type.kind) {
|
|
130
129
|
case "scalar": {
|
|
131
130
|
let outputResolved;
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
if (rendered && isSafeTypeExpression(rendered)) outputResolved = rendered;
|
|
137
|
-
}
|
|
131
|
+
const effectiveTypeParams = (type.typeParams && Object.keys(type.typeParams).length > 0 ? type.typeParams : void 0) ?? resolvedTypeParams;
|
|
132
|
+
if (codecLookup && effectiveTypeParams && Object.keys(effectiveTypeParams).length > 0) {
|
|
133
|
+
const rendered = codecLookup.renderOutputTypeFor(type.codecId, effectiveTypeParams);
|
|
134
|
+
if (rendered && isSafeTypeExpression(rendered)) outputResolved = rendered;
|
|
138
135
|
}
|
|
139
136
|
const codecAccessor = `CodecTypes[${serializeValue(type.codecId)}]`;
|
|
140
137
|
return {
|
|
@@ -163,7 +160,7 @@ function resolveFieldType(field, codecLookup) {
|
|
|
163
160
|
function generateFieldResolvedType(field, codecLookup, side = "output") {
|
|
164
161
|
return resolveFieldType(field, codecLookup)[side];
|
|
165
162
|
}
|
|
166
|
-
function generateBothFieldTypesMaps(models, codecLookup) {
|
|
163
|
+
function generateBothFieldTypesMaps(models, codecLookup, resolveFieldTypeParams) {
|
|
167
164
|
if (!models || Object.keys(models).length === 0) return {
|
|
168
165
|
output: "Record<string, never>",
|
|
169
166
|
input: "Record<string, never>"
|
|
@@ -175,7 +172,7 @@ function generateBothFieldTypesMaps(models, codecLookup) {
|
|
|
175
172
|
const outputFieldEntries = [];
|
|
176
173
|
const inputFieldEntries = [];
|
|
177
174
|
for (const [fieldName, field] of Object.entries(model.fields)) {
|
|
178
|
-
const resolved = resolveFieldType(field, codecLookup);
|
|
175
|
+
const resolved = resolveFieldType(field, codecLookup, (field.type.kind === "scalar" && field.type.typeParams && Object.keys(field.type.typeParams).length > 0 ? field.type.typeParams : void 0) ?? resolveFieldTypeParams?.(modelName, fieldName));
|
|
179
176
|
const key = `readonly ${serializeObjectKey(fieldName)}`;
|
|
180
177
|
outputFieldEntries.push(`${key}: ${resolved.output}`);
|
|
181
178
|
inputFieldEntries.push(`${key}: ${resolved.input}`);
|
|
@@ -191,11 +188,11 @@ function generateBothFieldTypesMaps(models, codecLookup) {
|
|
|
191
188
|
input: `{ ${inputModelEntries.join("; ")} }`
|
|
192
189
|
};
|
|
193
190
|
}
|
|
194
|
-
function generateFieldOutputTypesMap(models, codecLookup) {
|
|
195
|
-
return generateBothFieldTypesMaps(models, codecLookup).output;
|
|
191
|
+
function generateFieldOutputTypesMap(models, codecLookup, resolveFieldTypeParams) {
|
|
192
|
+
return generateBothFieldTypesMaps(models, codecLookup, resolveFieldTypeParams).output;
|
|
196
193
|
}
|
|
197
|
-
function generateFieldInputTypesMap(models, codecLookup) {
|
|
198
|
-
return generateBothFieldTypesMaps(models, codecLookup).input;
|
|
194
|
+
function generateFieldInputTypesMap(models, codecLookup, resolveFieldTypeParams) {
|
|
195
|
+
return generateBothFieldTypesMaps(models, codecLookup, resolveFieldTypeParams).input;
|
|
199
196
|
}
|
|
200
197
|
function generateValueObjectType(_voName, vo, _valueObjects, side = "output", codecLookup) {
|
|
201
198
|
return resolveValueObjectType(_voName, vo, _valueObjects, codecLookup)[side];
|
|
@@ -249,7 +246,7 @@ function generateValueObjectTypeAliases(valueObjects, codecLookup) {
|
|
|
249
246
|
}
|
|
250
247
|
return aliases.join("\n");
|
|
251
248
|
}
|
|
252
|
-
|
|
253
249
|
//#endregion
|
|
254
250
|
export { deduplicateImports, generateBothFieldTypesMaps, generateCodecTypeIntersection, generateContractFieldDescriptor, generateFieldInputTypesMap, generateFieldOutputTypesMap, generateFieldResolvedType, generateHashTypeAliases, generateImportLines, generateModelFieldEntry, generateModelFieldsType, generateModelRelationsType, generateModelsType, generateRootsType, generateValueObjectType, generateValueObjectTypeAliases, generateValueObjectsDescriptorType, resolveFieldType, resolveValueObjectType, serializeExecutionType, serializeObjectKey, serializeValue };
|
|
251
|
+
|
|
255
252
|
//# sourceMappingURL=domain-type-generation.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"domain-type-generation.mjs","names":["entries: string[]","fieldEntries: string[]","relationEntries: string[]","parts: string[]","modelTypes: string[]","modelParts: string[]","result: TypesImportSpec[]","outputResolved: string | undefined","outputModelEntries: string[]","inputModelEntries: string[]","outputFieldEntries: string[]","inputFieldEntries: string[]","outputEntries: string[]","inputEntries: string[]","mods: string[]","voEntries: string[]","aliases: string[]"],"sources":["../src/domain-type-generation.ts"],"sourcesContent":["import type {\n ContractField,\n ContractModel,\n ContractValueObject,\n} from '@prisma-next/contract/types';\nimport type { CodecLookup } from '@prisma-next/framework-components/codec';\nimport type { TypesImportSpec } from '@prisma-next/framework-components/emission';\nimport { isSafeTypeExpression } from './type-expression-safety';\n\nexport function serializeValue(value: unknown): string {\n if (value === null) {\n return 'null';\n }\n if (value === undefined) {\n return 'undefined';\n }\n if (typeof value === 'string') {\n const escaped = value.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\");\n return `'${escaped}'`;\n }\n if (typeof value === 'number' || typeof value === 'boolean') {\n return String(value);\n }\n if (typeof value === 'bigint') {\n return `${value}n`;\n }\n if (Array.isArray(value)) {\n const items = value.map((v) => serializeValue(v)).join(', ');\n return `readonly [${items}]`;\n }\n if (typeof value === 'object') {\n const entries: string[] = [];\n for (const [k, v] of Object.entries(value)) {\n entries.push(`readonly ${serializeObjectKey(k)}: ${serializeValue(v)}`);\n }\n return `{ ${entries.join('; ')} }`;\n }\n return 'unknown';\n}\n\nexport function serializeObjectKey(key: string): string {\n if (/^[$A-Z_a-z][$\\w]*$/.test(key)) {\n return key;\n }\n return serializeValue(key);\n}\n\nexport function generateRootsType(roots: Record<string, string> | undefined): string {\n if (!roots || Object.keys(roots).length === 0) {\n return 'Record<string, string>';\n }\n const entries = Object.entries(roots)\n .map(([key, value]) => `readonly ${serializeObjectKey(key)}: ${serializeValue(value)}`)\n .join('; ');\n return `{ ${entries} }`;\n}\n\nfunction contractFieldModifierSuffix(field: ContractField): string {\n const many = field.many === true ? '; readonly many: true' : '';\n const dict = field.dict === true ? '; readonly dict: true' : '';\n return many + dict;\n}\n\nexport function generateModelFieldEntry(fieldName: string, field: ContractField): string {\n const mods = contractFieldModifierSuffix(field);\n const { nullable, type } = field;\n if (type.kind === 'scalar') {\n const typeParamsSpec =\n type.typeParams && Object.keys(type.typeParams).length > 0\n ? `; readonly typeParams: ${serializeValue(type.typeParams)}`\n : '';\n return `readonly ${serializeObjectKey(fieldName)}: { readonly nullable: ${nullable}; readonly type: { readonly kind: 'scalar'; readonly codecId: ${serializeValue(type.codecId)}${typeParamsSpec} }${mods} }`;\n }\n if (type.kind === 'valueObject') {\n return `readonly ${serializeObjectKey(fieldName)}: { readonly nullable: ${nullable}; readonly type: { readonly kind: 'valueObject'; readonly name: ${serializeValue(type.name)} }${mods} }`;\n }\n return `readonly ${serializeObjectKey(fieldName)}: { readonly nullable: ${nullable}; readonly type: ${serializeValue(type)}${mods} }`;\n}\n\nexport function generateModelFieldsType(fields: Record<string, ContractField>): string {\n const fieldEntries: string[] = [];\n for (const [fieldName, field] of Object.entries(fields)) {\n fieldEntries.push(generateModelFieldEntry(fieldName, field));\n }\n return fieldEntries.length > 0 ? `{ ${fieldEntries.join('; ')} }` : 'Record<string, never>';\n}\n\nexport function generateModelRelationsType(relations: Record<string, unknown>): string {\n const relationEntries: string[] = [];\n\n for (const [relName, rel] of Object.entries(relations)) {\n if (typeof rel !== 'object' || rel === null) continue;\n const relObj = rel as Record<string, unknown>;\n const parts: string[] = [];\n\n if (relObj['to']) parts.push(`readonly to: ${serializeValue(relObj['to'])}`);\n if (relObj['cardinality'])\n parts.push(`readonly cardinality: ${serializeValue(relObj['cardinality'])}`);\n\n const on = relObj['on'] as { localFields?: string[]; targetFields?: string[] } | undefined;\n if (on && (!on.localFields || !on.targetFields)) {\n throw new Error(\n `Relation \"${relName}\" has an \"on\" block but is missing localFields or targetFields`,\n );\n }\n if (on?.localFields && on.targetFields) {\n const localFields = on.localFields.map((f) => serializeValue(f)).join(', ');\n const targetFields = on.targetFields.map((f) => serializeValue(f)).join(', ');\n parts.push(\n `readonly on: { readonly localFields: readonly [${localFields}]; readonly targetFields: readonly [${targetFields}] }`,\n );\n }\n\n if (parts.length > 0) {\n relationEntries.push(`readonly ${relName}: { ${parts.join('; ')} }`);\n }\n }\n\n if (relationEntries.length === 0) {\n return 'Record<string, never>';\n }\n\n return `{ ${relationEntries.join('; ')} }`;\n}\n\nexport function generateModelsType(\n models: Record<string, ContractModel>,\n generateModelStorage: (modelName: string, model: ContractModel) => string,\n): string {\n if (!models || Object.keys(models).length === 0) {\n return 'Record<string, never>';\n }\n\n const modelTypes: string[] = [];\n for (const [modelName, model] of Object.entries(models).sort(([a], [b]) => a.localeCompare(b))) {\n const fieldsType = generateModelFieldsType(model.fields);\n const relationsType = generateModelRelationsType(model.relations);\n const storageType = generateModelStorage(modelName, model);\n\n const modelParts: string[] = [\n `readonly fields: ${fieldsType}`,\n `readonly relations: ${relationsType}`,\n `readonly storage: ${storageType}`,\n ];\n\n if (model.owner) {\n modelParts.push(`readonly owner: ${serializeValue(model.owner)}`);\n }\n if (model.discriminator) {\n modelParts.push(`readonly discriminator: ${serializeValue(model.discriminator)}`);\n }\n if (model.variants) {\n modelParts.push(`readonly variants: ${serializeValue(model.variants)}`);\n }\n if (model.base) {\n modelParts.push(`readonly base: ${serializeValue(model.base)}`);\n }\n\n modelTypes.push(`readonly ${modelName}: { ${modelParts.join('; ')} }`);\n }\n\n return `{ ${modelTypes.join('; ')} }`;\n}\n\nexport function deduplicateImports(imports: TypesImportSpec[]): TypesImportSpec[] {\n const seenKeys = new Set<string>();\n const result: TypesImportSpec[] = [];\n for (const imp of imports) {\n const key = `${imp.package}::${imp.named}`;\n if (!seenKeys.has(key)) {\n seenKeys.add(key);\n result.push(imp);\n }\n }\n return result;\n}\n\nexport function generateImportLines(imports: TypesImportSpec[]): string[] {\n return imports.map((imp) => {\n const importClause = imp.named === imp.alias ? imp.named : `${imp.named} as ${imp.alias}`;\n return `import type { ${importClause} } from '${imp.package}';`;\n });\n}\n\nexport function generateCodecTypeIntersection(\n imports: ReadonlyArray<TypesImportSpec>,\n named: string,\n): string {\n const aliases = imports.filter((imp) => imp.named === named).map((imp) => imp.alias);\n return aliases.join(' & ') || 'Record<string, never>';\n}\n\nexport function serializeExecutionType(execution: Record<string, unknown>): string {\n const parts: string[] = ['readonly executionHash: ExecutionHash'];\n for (const [key, value] of Object.entries(execution)) {\n if (key === 'executionHash') continue;\n parts.push(`readonly ${serializeObjectKey(key)}: ${serializeValue(value)}`);\n }\n return `{ ${parts.join('; ')} }`;\n}\n\nexport function generateHashTypeAliases(hashes: {\n readonly storageHash: string;\n readonly executionHash?: string;\n readonly profileHash: string;\n}): string {\n const executionHashType = hashes.executionHash\n ? `ExecutionHashBase<'${hashes.executionHash}'>`\n : 'ExecutionHashBase<string>';\n\n return [\n `export type StorageHash = StorageHashBase<'${hashes.storageHash}'>;`,\n `export type ExecutionHash = ${executionHashType};`,\n `export type ProfileHash = ProfileHashBase<'${hashes.profileHash}'>;`,\n ].join('\\n');\n}\n\nexport type ResolvedFieldType = { readonly input: string; readonly output: string };\n\nfunction applyModifiers(base: string, field: ContractField): string {\n let result = base;\n if (field.many === true) result = `ReadonlyArray<${result}>`;\n if (field.dict === true) result = `Readonly<Record<string, ${result}>>`;\n if (field.nullable) result = `${result} | null`;\n return result;\n}\n\nexport function resolveFieldType(\n field: ContractField,\n codecLookup?: CodecLookup,\n): ResolvedFieldType {\n const { type } = field;\n\n switch (type.kind) {\n case 'scalar': {\n let outputResolved: string | undefined;\n if (codecLookup && type.typeParams && Object.keys(type.typeParams).length > 0) {\n const codec = codecLookup.get(type.codecId);\n if (codec?.renderOutputType) {\n const rendered = codec.renderOutputType(type.typeParams);\n if (rendered && isSafeTypeExpression(rendered)) {\n outputResolved = rendered;\n }\n }\n }\n const codecAccessor = `CodecTypes[${serializeValue(type.codecId)}]`;\n return {\n output: applyModifiers(outputResolved ?? `${codecAccessor}['output']`, field),\n input: applyModifiers(`${codecAccessor}['input']`, field),\n };\n }\n case 'valueObject':\n return {\n output: applyModifiers(`${type.name}Output`, field),\n input: applyModifiers(`${type.name}Input`, field),\n };\n case 'union': {\n const outputMembers = type.members.map((m) =>\n m.kind === 'scalar'\n ? `CodecTypes[${serializeValue(m.codecId)}]['output']`\n : `${m.name}Output`,\n );\n const inputMembers = type.members.map((m) =>\n m.kind === 'scalar'\n ? `CodecTypes[${serializeValue(m.codecId)}]['input']`\n : `${m.name}Input`,\n );\n return {\n output: applyModifiers(outputMembers.join(' | '), field),\n input: applyModifiers(inputMembers.join(' | '), field),\n };\n }\n default:\n return {\n output: applyModifiers('unknown', field),\n input: applyModifiers('unknown', field),\n };\n }\n}\n\nexport function generateFieldResolvedType(\n field: ContractField,\n codecLookup?: CodecLookup,\n side: 'input' | 'output' = 'output',\n): string {\n return resolveFieldType(field, codecLookup)[side];\n}\n\nexport function generateBothFieldTypesMaps(\n models: Record<string, ContractModel> | undefined,\n codecLookup?: CodecLookup,\n): ResolvedFieldType {\n if (!models || Object.keys(models).length === 0) {\n return { output: 'Record<string, never>', input: 'Record<string, never>' };\n }\n\n const outputModelEntries: string[] = [];\n const inputModelEntries: string[] = [];\n for (const [modelName, model] of Object.entries(models).sort(([a], [b]) => a.localeCompare(b))) {\n if (!model) continue;\n const outputFieldEntries: string[] = [];\n const inputFieldEntries: string[] = [];\n for (const [fieldName, field] of Object.entries(model.fields)) {\n const resolved = resolveFieldType(field, codecLookup);\n const key = `readonly ${serializeObjectKey(fieldName)}`;\n outputFieldEntries.push(`${key}: ${resolved.output}`);\n inputFieldEntries.push(`${key}: ${resolved.input}`);\n }\n const outputFields =\n outputFieldEntries.length > 0\n ? `{ ${outputFieldEntries.join('; ')} }`\n : 'Record<string, never>';\n const inputFields =\n inputFieldEntries.length > 0\n ? `{ ${inputFieldEntries.join('; ')} }`\n : 'Record<string, never>';\n const modelKey = `readonly ${serializeObjectKey(modelName)}`;\n outputModelEntries.push(`${modelKey}: ${outputFields}`);\n inputModelEntries.push(`${modelKey}: ${inputFields}`);\n }\n\n return {\n output: `{ ${outputModelEntries.join('; ')} }`,\n input: `{ ${inputModelEntries.join('; ')} }`,\n };\n}\n\nexport function generateFieldOutputTypesMap(\n models: Record<string, ContractModel> | undefined,\n codecLookup?: CodecLookup,\n): string {\n return generateBothFieldTypesMaps(models, codecLookup).output;\n}\n\nexport function generateFieldInputTypesMap(\n models: Record<string, ContractModel> | undefined,\n codecLookup?: CodecLookup,\n): string {\n return generateBothFieldTypesMaps(models, codecLookup).input;\n}\n\nexport function generateValueObjectType(\n _voName: string,\n vo: ContractValueObject,\n _valueObjects: Record<string, ContractValueObject>,\n side: 'input' | 'output' = 'output',\n codecLookup?: CodecLookup,\n): string {\n return resolveValueObjectType(_voName, vo, _valueObjects, codecLookup)[side];\n}\n\nexport function resolveValueObjectType(\n _voName: string,\n vo: ContractValueObject,\n _valueObjects: Record<string, ContractValueObject>,\n codecLookup?: CodecLookup,\n): ResolvedFieldType {\n const outputEntries: string[] = [];\n const inputEntries: string[] = [];\n for (const [fieldName, field] of Object.entries(vo.fields)) {\n const resolved = resolveFieldType(field, codecLookup);\n const key = `readonly ${serializeObjectKey(fieldName)}`;\n outputEntries.push(`${key}: ${resolved.output}`);\n inputEntries.push(`${key}: ${resolved.input}`);\n }\n const empty = 'Record<string, never>';\n return {\n output: outputEntries.length > 0 ? `{ ${outputEntries.join('; ')} }` : empty,\n input: inputEntries.length > 0 ? `{ ${inputEntries.join('; ')} }` : empty,\n };\n}\n\nexport function generateContractFieldDescriptor(fieldName: string, field: ContractField): string {\n const mods: string[] = [];\n if (field.many === true) mods.push('; readonly many: true');\n if (field.dict === true) mods.push('; readonly dict: true');\n const modStr = mods.join('');\n\n const { type } = field;\n if (type.kind === 'scalar') {\n const typeParamsSpec =\n type.typeParams && Object.keys(type.typeParams).length > 0\n ? `; readonly typeParams: ${serializeValue(type.typeParams)}`\n : '';\n return `readonly ${serializeObjectKey(fieldName)}: { readonly nullable: ${field.nullable}; readonly type: { readonly kind: 'scalar'; readonly codecId: ${serializeValue(type.codecId)}${typeParamsSpec} }${modStr} }`;\n }\n if (type.kind === 'valueObject') {\n return `readonly ${serializeObjectKey(fieldName)}: { readonly nullable: ${field.nullable}; readonly type: { readonly kind: 'valueObject'; readonly name: ${serializeValue(type.name)} }${modStr} }`;\n }\n return `readonly ${serializeObjectKey(fieldName)}: { readonly nullable: ${field.nullable}; readonly type: ${serializeValue(type)}${modStr} }`;\n}\n\nexport function generateValueObjectsDescriptorType(\n valueObjects: Record<string, ContractValueObject> | undefined,\n): string {\n if (!valueObjects || Object.keys(valueObjects).length === 0) {\n return 'Record<string, never>';\n }\n\n const voEntries: string[] = [];\n for (const [voName, vo] of Object.entries(valueObjects)) {\n const fieldEntries: string[] = [];\n for (const [fieldName, field] of Object.entries(vo.fields)) {\n fieldEntries.push(generateContractFieldDescriptor(fieldName, field));\n }\n const fieldsType =\n fieldEntries.length > 0 ? `{ ${fieldEntries.join('; ')} }` : 'Record<string, never>';\n voEntries.push(`readonly ${serializeObjectKey(voName)}: { readonly fields: ${fieldsType} }`);\n }\n\n return `{ ${voEntries.join('; ')} }`;\n}\n\nexport function generateValueObjectTypeAliases(\n valueObjects: Record<string, ContractValueObject> | undefined,\n codecLookup?: CodecLookup,\n): string {\n if (!valueObjects || Object.keys(valueObjects).length === 0) {\n return '';\n }\n\n const aliases: string[] = [];\n for (const [voName, vo] of Object.entries(valueObjects)) {\n const resolved = resolveValueObjectType(voName, vo, valueObjects, codecLookup);\n aliases.push(`export type ${voName}Output = ${resolved.output};`);\n aliases.push(`export type ${voName}Input = ${resolved.input};`);\n }\n return aliases.join('\\n');\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"domain-type-generation.mjs","names":[],"sources":["../src/domain-type-generation.ts"],"sourcesContent":["import type {\n ContractField,\n ContractModel,\n ContractValueObject,\n} from '@prisma-next/contract/types';\nimport type { CodecLookup } from '@prisma-next/framework-components/codec';\nimport type { TypesImportSpec } from '@prisma-next/framework-components/emission';\nimport { isSafeTypeExpression } from './type-expression-safety';\n\nexport function serializeValue(value: unknown): string {\n if (value === null) {\n return 'null';\n }\n if (value === undefined) {\n return 'undefined';\n }\n if (typeof value === 'string') {\n const escaped = value.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\");\n return `'${escaped}'`;\n }\n if (typeof value === 'number' || typeof value === 'boolean') {\n return String(value);\n }\n if (typeof value === 'bigint') {\n return `${value}n`;\n }\n if (Array.isArray(value)) {\n const items = value.map((v) => serializeValue(v)).join(', ');\n return `readonly [${items}]`;\n }\n if (typeof value === 'object') {\n const entries: string[] = [];\n for (const [k, v] of Object.entries(value)) {\n entries.push(`readonly ${serializeObjectKey(k)}: ${serializeValue(v)}`);\n }\n return `{ ${entries.join('; ')} }`;\n }\n return 'unknown';\n}\n\nexport function serializeObjectKey(key: string): string {\n if (/^[$A-Z_a-z][$\\w]*$/.test(key)) {\n return key;\n }\n return serializeValue(key);\n}\n\nexport function generateRootsType(roots: Record<string, string> | undefined): string {\n if (!roots || Object.keys(roots).length === 0) {\n return 'Record<string, string>';\n }\n const entries = Object.entries(roots)\n .map(([key, value]) => `readonly ${serializeObjectKey(key)}: ${serializeValue(value)}`)\n .join('; ');\n return `{ ${entries} }`;\n}\n\nfunction contractFieldModifierSuffix(field: ContractField): string {\n const many = field.many === true ? '; readonly many: true' : '';\n const dict = field.dict === true ? '; readonly dict: true' : '';\n return many + dict;\n}\n\nexport function generateModelFieldEntry(fieldName: string, field: ContractField): string {\n const mods = contractFieldModifierSuffix(field);\n const { nullable, type } = field;\n if (type.kind === 'scalar') {\n const typeParamsSpec =\n type.typeParams && Object.keys(type.typeParams).length > 0\n ? `; readonly typeParams: ${serializeValue(type.typeParams)}`\n : '';\n return `readonly ${serializeObjectKey(fieldName)}: { readonly nullable: ${nullable}; readonly type: { readonly kind: 'scalar'; readonly codecId: ${serializeValue(type.codecId)}${typeParamsSpec} }${mods} }`;\n }\n if (type.kind === 'valueObject') {\n return `readonly ${serializeObjectKey(fieldName)}: { readonly nullable: ${nullable}; readonly type: { readonly kind: 'valueObject'; readonly name: ${serializeValue(type.name)} }${mods} }`;\n }\n return `readonly ${serializeObjectKey(fieldName)}: { readonly nullable: ${nullable}; readonly type: ${serializeValue(type)}${mods} }`;\n}\n\nexport function generateModelFieldsType(fields: Record<string, ContractField>): string {\n const fieldEntries: string[] = [];\n for (const [fieldName, field] of Object.entries(fields)) {\n fieldEntries.push(generateModelFieldEntry(fieldName, field));\n }\n return fieldEntries.length > 0 ? `{ ${fieldEntries.join('; ')} }` : 'Record<string, never>';\n}\n\nexport function generateModelRelationsType(relations: Record<string, unknown>): string {\n const relationEntries: string[] = [];\n\n for (const [relName, rel] of Object.entries(relations)) {\n if (typeof rel !== 'object' || rel === null) continue;\n const relObj = rel as Record<string, unknown>;\n const parts: string[] = [];\n\n if (relObj['to']) parts.push(`readonly to: ${serializeValue(relObj['to'])}`);\n if (relObj['cardinality'])\n parts.push(`readonly cardinality: ${serializeValue(relObj['cardinality'])}`);\n\n const on = relObj['on'] as { localFields?: string[]; targetFields?: string[] } | undefined;\n if (on && (!on.localFields || !on.targetFields)) {\n throw new Error(\n `Relation \"${relName}\" has an \"on\" block but is missing localFields or targetFields`,\n );\n }\n if (on?.localFields && on.targetFields) {\n const localFields = on.localFields.map((f) => serializeValue(f)).join(', ');\n const targetFields = on.targetFields.map((f) => serializeValue(f)).join(', ');\n parts.push(\n `readonly on: { readonly localFields: readonly [${localFields}]; readonly targetFields: readonly [${targetFields}] }`,\n );\n }\n\n if (parts.length > 0) {\n relationEntries.push(`readonly ${relName}: { ${parts.join('; ')} }`);\n }\n }\n\n if (relationEntries.length === 0) {\n return 'Record<string, never>';\n }\n\n return `{ ${relationEntries.join('; ')} }`;\n}\n\nexport function generateModelsType(\n models: Record<string, ContractModel>,\n generateModelStorage: (modelName: string, model: ContractModel) => string,\n): string {\n if (!models || Object.keys(models).length === 0) {\n return 'Record<string, never>';\n }\n\n const modelTypes: string[] = [];\n for (const [modelName, model] of Object.entries(models).sort(([a], [b]) => a.localeCompare(b))) {\n const fieldsType = generateModelFieldsType(model.fields);\n const relationsType = generateModelRelationsType(model.relations);\n const storageType = generateModelStorage(modelName, model);\n\n const modelParts: string[] = [\n `readonly fields: ${fieldsType}`,\n `readonly relations: ${relationsType}`,\n `readonly storage: ${storageType}`,\n ];\n\n if (model.owner) {\n modelParts.push(`readonly owner: ${serializeValue(model.owner)}`);\n }\n if (model.discriminator) {\n modelParts.push(`readonly discriminator: ${serializeValue(model.discriminator)}`);\n }\n if (model.variants) {\n modelParts.push(`readonly variants: ${serializeValue(model.variants)}`);\n }\n if (model.base) {\n modelParts.push(`readonly base: ${serializeValue(model.base)}`);\n }\n\n modelTypes.push(`readonly ${modelName}: { ${modelParts.join('; ')} }`);\n }\n\n return `{ ${modelTypes.join('; ')} }`;\n}\n\nexport function deduplicateImports(imports: TypesImportSpec[]): TypesImportSpec[] {\n const seenKeys = new Set<string>();\n const result: TypesImportSpec[] = [];\n for (const imp of imports) {\n const key = `${imp.package}::${imp.named}`;\n if (!seenKeys.has(key)) {\n seenKeys.add(key);\n result.push(imp);\n }\n }\n return result;\n}\n\nexport function generateImportLines(imports: TypesImportSpec[]): string[] {\n return imports.map((imp) => {\n const importClause = imp.named === imp.alias ? imp.named : `${imp.named} as ${imp.alias}`;\n return `import type { ${importClause} } from '${imp.package}';`;\n });\n}\n\nexport function generateCodecTypeIntersection(\n imports: ReadonlyArray<TypesImportSpec>,\n named: string,\n): string {\n const aliases = imports.filter((imp) => imp.named === named).map((imp) => imp.alias);\n return aliases.join(' & ') || 'Record<string, never>';\n}\n\nexport function serializeExecutionType(execution: Record<string, unknown>): string {\n const parts: string[] = ['readonly executionHash: ExecutionHash'];\n for (const [key, value] of Object.entries(execution)) {\n if (key === 'executionHash') continue;\n parts.push(`readonly ${serializeObjectKey(key)}: ${serializeValue(value)}`);\n }\n return `{ ${parts.join('; ')} }`;\n}\n\nexport function generateHashTypeAliases(hashes: {\n readonly storageHash: string;\n readonly executionHash?: string;\n readonly profileHash: string;\n}): string {\n const executionHashType = hashes.executionHash\n ? `ExecutionHashBase<'${hashes.executionHash}'>`\n : 'ExecutionHashBase<string>';\n\n return [\n `export type StorageHash = StorageHashBase<'${hashes.storageHash}'>;`,\n `export type ExecutionHash = ${executionHashType};`,\n `export type ProfileHash = ProfileHashBase<'${hashes.profileHash}'>;`,\n ].join('\\n');\n}\n\nexport type ResolvedFieldType = { readonly input: string; readonly output: string };\n\nfunction applyModifiers(base: string, field: ContractField): string {\n let result = base;\n if (field.many === true) result = `ReadonlyArray<${result}>`;\n if (field.dict === true) result = `Readonly<Record<string, ${result}>>`;\n if (field.nullable) result = `${result} | null`;\n return result;\n}\n\n/**\n * Per-family resolver for typeParams that don't live inline on the framework-domain `ContractField`. SQL columns authored via a named `storage.types` entry carry their `typeRef` on the storage column (family-specific) rather than on the framework's domain field; the per-family emitter walks `storage.types[ref].typeParams` here so the framework emit path can render the parameterized output type.\n *\n * Returns `undefined` when the field has no resolvable typeParams (i.e. the column isn't parameterized, isn't a `typeRef`, or the family doesn't support named storage types).\n */\nexport type FieldTypeParamsResolver = (\n modelName: string,\n fieldName: string,\n) => Record<string, unknown> | undefined;\n\nexport function resolveFieldType(\n field: ContractField,\n codecLookup?: CodecLookup,\n resolvedTypeParams?: Record<string, unknown>,\n): ResolvedFieldType {\n const { type } = field;\n\n switch (type.kind) {\n case 'scalar': {\n let outputResolved: string | undefined;\n const inlineTypeParams =\n type.typeParams && Object.keys(type.typeParams).length > 0 ? type.typeParams : undefined;\n const effectiveTypeParams = inlineTypeParams ?? resolvedTypeParams;\n if (codecLookup && effectiveTypeParams && Object.keys(effectiveTypeParams).length > 0) {\n const rendered = codecLookup.renderOutputTypeFor(type.codecId, effectiveTypeParams);\n if (rendered && isSafeTypeExpression(rendered)) {\n outputResolved = rendered;\n }\n }\n const codecAccessor = `CodecTypes[${serializeValue(type.codecId)}]`;\n return {\n output: applyModifiers(outputResolved ?? `${codecAccessor}['output']`, field),\n input: applyModifiers(`${codecAccessor}['input']`, field),\n };\n }\n case 'valueObject':\n return {\n output: applyModifiers(`${type.name}Output`, field),\n input: applyModifiers(`${type.name}Input`, field),\n };\n case 'union': {\n const outputMembers = type.members.map((m) =>\n m.kind === 'scalar'\n ? `CodecTypes[${serializeValue(m.codecId)}]['output']`\n : `${m.name}Output`,\n );\n const inputMembers = type.members.map((m) =>\n m.kind === 'scalar'\n ? `CodecTypes[${serializeValue(m.codecId)}]['input']`\n : `${m.name}Input`,\n );\n return {\n output: applyModifiers(outputMembers.join(' | '), field),\n input: applyModifiers(inputMembers.join(' | '), field),\n };\n }\n default:\n return {\n output: applyModifiers('unknown', field),\n input: applyModifiers('unknown', field),\n };\n }\n}\n\nexport function generateFieldResolvedType(\n field: ContractField,\n codecLookup?: CodecLookup,\n side: 'input' | 'output' = 'output',\n): string {\n return resolveFieldType(field, codecLookup)[side];\n}\n\nexport function generateBothFieldTypesMaps(\n models: Record<string, ContractModel> | undefined,\n codecLookup?: CodecLookup,\n resolveFieldTypeParams?: FieldTypeParamsResolver,\n): ResolvedFieldType {\n if (!models || Object.keys(models).length === 0) {\n return { output: 'Record<string, never>', input: 'Record<string, never>' };\n }\n\n const outputModelEntries: string[] = [];\n const inputModelEntries: string[] = [];\n for (const [modelName, model] of Object.entries(models).sort(([a], [b]) => a.localeCompare(b))) {\n if (!model) continue;\n const outputFieldEntries: string[] = [];\n const inputFieldEntries: string[] = [];\n for (const [fieldName, field] of Object.entries(model.fields)) {\n const inlineTypeParams =\n field.type.kind === 'scalar' &&\n field.type.typeParams &&\n Object.keys(field.type.typeParams).length > 0\n ? field.type.typeParams\n : undefined;\n const resolvedTypeParams = inlineTypeParams ?? resolveFieldTypeParams?.(modelName, fieldName);\n const resolved = resolveFieldType(field, codecLookup, resolvedTypeParams);\n const key = `readonly ${serializeObjectKey(fieldName)}`;\n outputFieldEntries.push(`${key}: ${resolved.output}`);\n inputFieldEntries.push(`${key}: ${resolved.input}`);\n }\n const outputFields =\n outputFieldEntries.length > 0\n ? `{ ${outputFieldEntries.join('; ')} }`\n : 'Record<string, never>';\n const inputFields =\n inputFieldEntries.length > 0\n ? `{ ${inputFieldEntries.join('; ')} }`\n : 'Record<string, never>';\n const modelKey = `readonly ${serializeObjectKey(modelName)}`;\n outputModelEntries.push(`${modelKey}: ${outputFields}`);\n inputModelEntries.push(`${modelKey}: ${inputFields}`);\n }\n\n return {\n output: `{ ${outputModelEntries.join('; ')} }`,\n input: `{ ${inputModelEntries.join('; ')} }`,\n };\n}\n\nexport function generateFieldOutputTypesMap(\n models: Record<string, ContractModel> | undefined,\n codecLookup?: CodecLookup,\n resolveFieldTypeParams?: FieldTypeParamsResolver,\n): string {\n return generateBothFieldTypesMaps(models, codecLookup, resolveFieldTypeParams).output;\n}\n\nexport function generateFieldInputTypesMap(\n models: Record<string, ContractModel> | undefined,\n codecLookup?: CodecLookup,\n resolveFieldTypeParams?: FieldTypeParamsResolver,\n): string {\n return generateBothFieldTypesMaps(models, codecLookup, resolveFieldTypeParams).input;\n}\n\nexport function generateValueObjectType(\n _voName: string,\n vo: ContractValueObject,\n _valueObjects: Record<string, ContractValueObject>,\n side: 'input' | 'output' = 'output',\n codecLookup?: CodecLookup,\n): string {\n return resolveValueObjectType(_voName, vo, _valueObjects, codecLookup)[side];\n}\n\nexport function resolveValueObjectType(\n _voName: string,\n vo: ContractValueObject,\n _valueObjects: Record<string, ContractValueObject>,\n codecLookup?: CodecLookup,\n): ResolvedFieldType {\n const outputEntries: string[] = [];\n const inputEntries: string[] = [];\n for (const [fieldName, field] of Object.entries(vo.fields)) {\n const resolved = resolveFieldType(field, codecLookup);\n const key = `readonly ${serializeObjectKey(fieldName)}`;\n outputEntries.push(`${key}: ${resolved.output}`);\n inputEntries.push(`${key}: ${resolved.input}`);\n }\n const empty = 'Record<string, never>';\n return {\n output: outputEntries.length > 0 ? `{ ${outputEntries.join('; ')} }` : empty,\n input: inputEntries.length > 0 ? `{ ${inputEntries.join('; ')} }` : empty,\n };\n}\n\nexport function generateContractFieldDescriptor(fieldName: string, field: ContractField): string {\n const mods: string[] = [];\n if (field.many === true) mods.push('; readonly many: true');\n if (field.dict === true) mods.push('; readonly dict: true');\n const modStr = mods.join('');\n\n const { type } = field;\n if (type.kind === 'scalar') {\n const typeParamsSpec =\n type.typeParams && Object.keys(type.typeParams).length > 0\n ? `; readonly typeParams: ${serializeValue(type.typeParams)}`\n : '';\n return `readonly ${serializeObjectKey(fieldName)}: { readonly nullable: ${field.nullable}; readonly type: { readonly kind: 'scalar'; readonly codecId: ${serializeValue(type.codecId)}${typeParamsSpec} }${modStr} }`;\n }\n if (type.kind === 'valueObject') {\n return `readonly ${serializeObjectKey(fieldName)}: { readonly nullable: ${field.nullable}; readonly type: { readonly kind: 'valueObject'; readonly name: ${serializeValue(type.name)} }${modStr} }`;\n }\n return `readonly ${serializeObjectKey(fieldName)}: { readonly nullable: ${field.nullable}; readonly type: ${serializeValue(type)}${modStr} }`;\n}\n\nexport function generateValueObjectsDescriptorType(\n valueObjects: Record<string, ContractValueObject> | undefined,\n): string {\n if (!valueObjects || Object.keys(valueObjects).length === 0) {\n return 'Record<string, never>';\n }\n\n const voEntries: string[] = [];\n for (const [voName, vo] of Object.entries(valueObjects)) {\n const fieldEntries: string[] = [];\n for (const [fieldName, field] of Object.entries(vo.fields)) {\n fieldEntries.push(generateContractFieldDescriptor(fieldName, field));\n }\n const fieldsType =\n fieldEntries.length > 0 ? `{ ${fieldEntries.join('; ')} }` : 'Record<string, never>';\n voEntries.push(`readonly ${serializeObjectKey(voName)}: { readonly fields: ${fieldsType} }`);\n }\n\n return `{ ${voEntries.join('; ')} }`;\n}\n\nexport function generateValueObjectTypeAliases(\n valueObjects: Record<string, ContractValueObject> | undefined,\n codecLookup?: CodecLookup,\n): string {\n if (!valueObjects || Object.keys(valueObjects).length === 0) {\n return '';\n }\n\n const aliases: string[] = [];\n for (const [voName, vo] of Object.entries(valueObjects)) {\n const resolved = resolveValueObjectType(voName, vo, valueObjects, codecLookup);\n aliases.push(`export type ${voName}Output = ${resolved.output};`);\n aliases.push(`export type ${voName}Input = ${resolved.input};`);\n }\n return aliases.join('\\n');\n}\n"],"mappings":";;AASA,SAAgB,eAAe,OAAwB;CACrD,IAAI,UAAU,MACZ,OAAO;CAET,IAAI,UAAU,KAAA,GACZ,OAAO;CAET,IAAI,OAAO,UAAU,UAEnB,OAAO,IADS,MAAM,QAAQ,OAAO,OAAO,CAAC,QAAQ,MAAM,MACzC,CAAC;CAErB,IAAI,OAAO,UAAU,YAAY,OAAO,UAAU,WAChD,OAAO,OAAO,MAAM;CAEtB,IAAI,OAAO,UAAU,UACnB,OAAO,GAAG,MAAM;CAElB,IAAI,MAAM,QAAQ,MAAM,EAEtB,OAAO,aADO,MAAM,KAAK,MAAM,eAAe,EAAE,CAAC,CAAC,KAAK,KAC9B,CAAC;CAE5B,IAAI,OAAO,UAAU,UAAU;EAC7B,MAAM,UAAoB,EAAE;EAC5B,KAAK,MAAM,CAAC,GAAG,MAAM,OAAO,QAAQ,MAAM,EACxC,QAAQ,KAAK,YAAY,mBAAmB,EAAE,CAAC,IAAI,eAAe,EAAE,GAAG;EAEzE,OAAO,KAAK,QAAQ,KAAK,KAAK,CAAC;;CAEjC,OAAO;;AAGT,SAAgB,mBAAmB,KAAqB;CACtD,IAAI,qBAAqB,KAAK,IAAI,EAChC,OAAO;CAET,OAAO,eAAe,IAAI;;AAG5B,SAAgB,kBAAkB,OAAmD;CACnF,IAAI,CAAC,SAAS,OAAO,KAAK,MAAM,CAAC,WAAW,GAC1C,OAAO;CAKT,OAAO,KAHS,OAAO,QAAQ,MAAM,CAClC,KAAK,CAAC,KAAK,WAAW,YAAY,mBAAmB,IAAI,CAAC,IAAI,eAAe,MAAM,GAAG,CACtF,KAAK,KACW,CAAC;;AAGtB,SAAS,4BAA4B,OAA8B;CAGjE,QAFa,MAAM,SAAS,OAAO,0BAA0B,OAChD,MAAM,SAAS,OAAO,0BAA0B;;AAI/D,SAAgB,wBAAwB,WAAmB,OAA8B;CACvF,MAAM,OAAO,4BAA4B,MAAM;CAC/C,MAAM,EAAE,UAAU,SAAS;CAC3B,IAAI,KAAK,SAAS,UAAU;EAC1B,MAAM,iBACJ,KAAK,cAAc,OAAO,KAAK,KAAK,WAAW,CAAC,SAAS,IACrD,0BAA0B,eAAe,KAAK,WAAW,KACzD;EACN,OAAO,YAAY,mBAAmB,UAAU,CAAC,yBAAyB,SAAS,gEAAgE,eAAe,KAAK,QAAQ,GAAG,eAAe,IAAI,KAAK;;CAE5M,IAAI,KAAK,SAAS,eAChB,OAAO,YAAY,mBAAmB,UAAU,CAAC,yBAAyB,SAAS,kEAAkE,eAAe,KAAK,KAAK,CAAC,IAAI,KAAK;CAE1L,OAAO,YAAY,mBAAmB,UAAU,CAAC,yBAAyB,SAAS,mBAAmB,eAAe,KAAK,GAAG,KAAK;;AAGpI,SAAgB,wBAAwB,QAA+C;CACrF,MAAM,eAAyB,EAAE;CACjC,KAAK,MAAM,CAAC,WAAW,UAAU,OAAO,QAAQ,OAAO,EACrD,aAAa,KAAK,wBAAwB,WAAW,MAAM,CAAC;CAE9D,OAAO,aAAa,SAAS,IAAI,KAAK,aAAa,KAAK,KAAK,CAAC,MAAM;;AAGtE,SAAgB,2BAA2B,WAA4C;CACrF,MAAM,kBAA4B,EAAE;CAEpC,KAAK,MAAM,CAAC,SAAS,QAAQ,OAAO,QAAQ,UAAU,EAAE;EACtD,IAAI,OAAO,QAAQ,YAAY,QAAQ,MAAM;EAC7C,MAAM,SAAS;EACf,MAAM,QAAkB,EAAE;EAE1B,IAAI,OAAO,OAAO,MAAM,KAAK,gBAAgB,eAAe,OAAO,MAAM,GAAG;EAC5E,IAAI,OAAO,gBACT,MAAM,KAAK,yBAAyB,eAAe,OAAO,eAAe,GAAG;EAE9E,MAAM,KAAK,OAAO;EAClB,IAAI,OAAO,CAAC,GAAG,eAAe,CAAC,GAAG,eAChC,MAAM,IAAI,MACR,aAAa,QAAQ,gEACtB;EAEH,IAAI,IAAI,eAAe,GAAG,cAAc;GACtC,MAAM,cAAc,GAAG,YAAY,KAAK,MAAM,eAAe,EAAE,CAAC,CAAC,KAAK,KAAK;GAC3E,MAAM,eAAe,GAAG,aAAa,KAAK,MAAM,eAAe,EAAE,CAAC,CAAC,KAAK,KAAK;GAC7E,MAAM,KACJ,kDAAkD,YAAY,sCAAsC,aAAa,KAClH;;EAGH,IAAI,MAAM,SAAS,GACjB,gBAAgB,KAAK,YAAY,QAAQ,MAAM,MAAM,KAAK,KAAK,CAAC,IAAI;;CAIxE,IAAI,gBAAgB,WAAW,GAC7B,OAAO;CAGT,OAAO,KAAK,gBAAgB,KAAK,KAAK,CAAC;;AAGzC,SAAgB,mBACd,QACA,sBACQ;CACR,IAAI,CAAC,UAAU,OAAO,KAAK,OAAO,CAAC,WAAW,GAC5C,OAAO;CAGT,MAAM,aAAuB,EAAE;CAC/B,KAAK,MAAM,CAAC,WAAW,UAAU,OAAO,QAAQ,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,EAAE,CAAC,EAAE;EAC9F,MAAM,aAAa,wBAAwB,MAAM,OAAO;EACxD,MAAM,gBAAgB,2BAA2B,MAAM,UAAU;EACjE,MAAM,cAAc,qBAAqB,WAAW,MAAM;EAE1D,MAAM,aAAuB;GAC3B,oBAAoB;GACpB,uBAAuB;GACvB,qBAAqB;GACtB;EAED,IAAI,MAAM,OACR,WAAW,KAAK,mBAAmB,eAAe,MAAM,MAAM,GAAG;EAEnE,IAAI,MAAM,eACR,WAAW,KAAK,2BAA2B,eAAe,MAAM,cAAc,GAAG;EAEnF,IAAI,MAAM,UACR,WAAW,KAAK,sBAAsB,eAAe,MAAM,SAAS,GAAG;EAEzE,IAAI,MAAM,MACR,WAAW,KAAK,kBAAkB,eAAe,MAAM,KAAK,GAAG;EAGjE,WAAW,KAAK,YAAY,UAAU,MAAM,WAAW,KAAK,KAAK,CAAC,IAAI;;CAGxE,OAAO,KAAK,WAAW,KAAK,KAAK,CAAC;;AAGpC,SAAgB,mBAAmB,SAA+C;CAChF,MAAM,2BAAW,IAAI,KAAa;CAClC,MAAM,SAA4B,EAAE;CACpC,KAAK,MAAM,OAAO,SAAS;EACzB,MAAM,MAAM,GAAG,IAAI,QAAQ,IAAI,IAAI;EACnC,IAAI,CAAC,SAAS,IAAI,IAAI,EAAE;GACtB,SAAS,IAAI,IAAI;GACjB,OAAO,KAAK,IAAI;;;CAGpB,OAAO;;AAGT,SAAgB,oBAAoB,SAAsC;CACxE,OAAO,QAAQ,KAAK,QAAQ;EAE1B,OAAO,iBADc,IAAI,UAAU,IAAI,QAAQ,IAAI,QAAQ,GAAG,IAAI,MAAM,MAAM,IAAI,QAC7C,WAAW,IAAI,QAAQ;GAC5D;;AAGJ,SAAgB,8BACd,SACA,OACQ;CAER,OADgB,QAAQ,QAAQ,QAAQ,IAAI,UAAU,MAAM,CAAC,KAAK,QAAQ,IAAI,MAChE,CAAC,KAAK,MAAM,IAAI;;AAGhC,SAAgB,uBAAuB,WAA4C;CACjF,MAAM,QAAkB,CAAC,wCAAwC;CACjE,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,UAAU,EAAE;EACpD,IAAI,QAAQ,iBAAiB;EAC7B,MAAM,KAAK,YAAY,mBAAmB,IAAI,CAAC,IAAI,eAAe,MAAM,GAAG;;CAE7E,OAAO,KAAK,MAAM,KAAK,KAAK,CAAC;;AAG/B,SAAgB,wBAAwB,QAI7B;CACT,MAAM,oBAAoB,OAAO,gBAC7B,sBAAsB,OAAO,cAAc,MAC3C;CAEJ,OAAO;EACL,8CAA8C,OAAO,YAAY;EACjE,+BAA+B,kBAAkB;EACjD,8CAA8C,OAAO,YAAY;EAClE,CAAC,KAAK,KAAK;;AAKd,SAAS,eAAe,MAAc,OAA8B;CAClE,IAAI,SAAS;CACb,IAAI,MAAM,SAAS,MAAM,SAAS,iBAAiB,OAAO;CAC1D,IAAI,MAAM,SAAS,MAAM,SAAS,2BAA2B,OAAO;CACpE,IAAI,MAAM,UAAU,SAAS,GAAG,OAAO;CACvC,OAAO;;AAaT,SAAgB,iBACd,OACA,aACA,oBACmB;CACnB,MAAM,EAAE,SAAS;CAEjB,QAAQ,KAAK,MAAb;EACE,KAAK,UAAU;GACb,IAAI;GAGJ,MAAM,uBADJ,KAAK,cAAc,OAAO,KAAK,KAAK,WAAW,CAAC,SAAS,IAAI,KAAK,aAAa,KAAA,MACjC;GAChD,IAAI,eAAe,uBAAuB,OAAO,KAAK,oBAAoB,CAAC,SAAS,GAAG;IACrF,MAAM,WAAW,YAAY,oBAAoB,KAAK,SAAS,oBAAoB;IACnF,IAAI,YAAY,qBAAqB,SAAS,EAC5C,iBAAiB;;GAGrB,MAAM,gBAAgB,cAAc,eAAe,KAAK,QAAQ,CAAC;GACjE,OAAO;IACL,QAAQ,eAAe,kBAAkB,GAAG,cAAc,aAAa,MAAM;IAC7E,OAAO,eAAe,GAAG,cAAc,YAAY,MAAM;IAC1D;;EAEH,KAAK,eACH,OAAO;GACL,QAAQ,eAAe,GAAG,KAAK,KAAK,SAAS,MAAM;GACnD,OAAO,eAAe,GAAG,KAAK,KAAK,QAAQ,MAAM;GAClD;EACH,KAAK,SAAS;GACZ,MAAM,gBAAgB,KAAK,QAAQ,KAAK,MACtC,EAAE,SAAS,WACP,cAAc,eAAe,EAAE,QAAQ,CAAC,eACxC,GAAG,EAAE,KAAK,QACf;GACD,MAAM,eAAe,KAAK,QAAQ,KAAK,MACrC,EAAE,SAAS,WACP,cAAc,eAAe,EAAE,QAAQ,CAAC,cACxC,GAAG,EAAE,KAAK,OACf;GACD,OAAO;IACL,QAAQ,eAAe,cAAc,KAAK,MAAM,EAAE,MAAM;IACxD,OAAO,eAAe,aAAa,KAAK,MAAM,EAAE,MAAM;IACvD;;EAEH,SACE,OAAO;GACL,QAAQ,eAAe,WAAW,MAAM;GACxC,OAAO,eAAe,WAAW,MAAM;GACxC;;;AAIP,SAAgB,0BACd,OACA,aACA,OAA2B,UACnB;CACR,OAAO,iBAAiB,OAAO,YAAY,CAAC;;AAG9C,SAAgB,2BACd,QACA,aACA,wBACmB;CACnB,IAAI,CAAC,UAAU,OAAO,KAAK,OAAO,CAAC,WAAW,GAC5C,OAAO;EAAE,QAAQ;EAAyB,OAAO;EAAyB;CAG5E,MAAM,qBAA+B,EAAE;CACvC,MAAM,oBAA8B,EAAE;CACtC,KAAK,MAAM,CAAC,WAAW,UAAU,OAAO,QAAQ,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,EAAE,CAAC,EAAE;EAC9F,IAAI,CAAC,OAAO;EACZ,MAAM,qBAA+B,EAAE;EACvC,MAAM,oBAA8B,EAAE;EACtC,KAAK,MAAM,CAAC,WAAW,UAAU,OAAO,QAAQ,MAAM,OAAO,EAAE;GAQ7D,MAAM,WAAW,iBAAiB,OAAO,cANvC,MAAM,KAAK,SAAS,YACpB,MAAM,KAAK,cACX,OAAO,KAAK,MAAM,KAAK,WAAW,CAAC,SAAS,IACxC,MAAM,KAAK,aACX,KAAA,MACyC,yBAAyB,WAAW,UAAU,CACpB;GACzE,MAAM,MAAM,YAAY,mBAAmB,UAAU;GACrD,mBAAmB,KAAK,GAAG,IAAI,IAAI,SAAS,SAAS;GACrD,kBAAkB,KAAK,GAAG,IAAI,IAAI,SAAS,QAAQ;;EAErD,MAAM,eACJ,mBAAmB,SAAS,IACxB,KAAK,mBAAmB,KAAK,KAAK,CAAC,MACnC;EACN,MAAM,cACJ,kBAAkB,SAAS,IACvB,KAAK,kBAAkB,KAAK,KAAK,CAAC,MAClC;EACN,MAAM,WAAW,YAAY,mBAAmB,UAAU;EAC1D,mBAAmB,KAAK,GAAG,SAAS,IAAI,eAAe;EACvD,kBAAkB,KAAK,GAAG,SAAS,IAAI,cAAc;;CAGvD,OAAO;EACL,QAAQ,KAAK,mBAAmB,KAAK,KAAK,CAAC;EAC3C,OAAO,KAAK,kBAAkB,KAAK,KAAK,CAAC;EAC1C;;AAGH,SAAgB,4BACd,QACA,aACA,wBACQ;CACR,OAAO,2BAA2B,QAAQ,aAAa,uBAAuB,CAAC;;AAGjF,SAAgB,2BACd,QACA,aACA,wBACQ;CACR,OAAO,2BAA2B,QAAQ,aAAa,uBAAuB,CAAC;;AAGjF,SAAgB,wBACd,SACA,IACA,eACA,OAA2B,UAC3B,aACQ;CACR,OAAO,uBAAuB,SAAS,IAAI,eAAe,YAAY,CAAC;;AAGzE,SAAgB,uBACd,SACA,IACA,eACA,aACmB;CACnB,MAAM,gBAA0B,EAAE;CAClC,MAAM,eAAyB,EAAE;CACjC,KAAK,MAAM,CAAC,WAAW,UAAU,OAAO,QAAQ,GAAG,OAAO,EAAE;EAC1D,MAAM,WAAW,iBAAiB,OAAO,YAAY;EACrD,MAAM,MAAM,YAAY,mBAAmB,UAAU;EACrD,cAAc,KAAK,GAAG,IAAI,IAAI,SAAS,SAAS;EAChD,aAAa,KAAK,GAAG,IAAI,IAAI,SAAS,QAAQ;;CAEhD,MAAM,QAAQ;CACd,OAAO;EACL,QAAQ,cAAc,SAAS,IAAI,KAAK,cAAc,KAAK,KAAK,CAAC,MAAM;EACvE,OAAO,aAAa,SAAS,IAAI,KAAK,aAAa,KAAK,KAAK,CAAC,MAAM;EACrE;;AAGH,SAAgB,gCAAgC,WAAmB,OAA8B;CAC/F,MAAM,OAAiB,EAAE;CACzB,IAAI,MAAM,SAAS,MAAM,KAAK,KAAK,wBAAwB;CAC3D,IAAI,MAAM,SAAS,MAAM,KAAK,KAAK,wBAAwB;CAC3D,MAAM,SAAS,KAAK,KAAK,GAAG;CAE5B,MAAM,EAAE,SAAS;CACjB,IAAI,KAAK,SAAS,UAAU;EAC1B,MAAM,iBACJ,KAAK,cAAc,OAAO,KAAK,KAAK,WAAW,CAAC,SAAS,IACrD,0BAA0B,eAAe,KAAK,WAAW,KACzD;EACN,OAAO,YAAY,mBAAmB,UAAU,CAAC,yBAAyB,MAAM,SAAS,gEAAgE,eAAe,KAAK,QAAQ,GAAG,eAAe,IAAI,OAAO;;CAEpN,IAAI,KAAK,SAAS,eAChB,OAAO,YAAY,mBAAmB,UAAU,CAAC,yBAAyB,MAAM,SAAS,kEAAkE,eAAe,KAAK,KAAK,CAAC,IAAI,OAAO;CAElM,OAAO,YAAY,mBAAmB,UAAU,CAAC,yBAAyB,MAAM,SAAS,mBAAmB,eAAe,KAAK,GAAG,OAAO;;AAG5I,SAAgB,mCACd,cACQ;CACR,IAAI,CAAC,gBAAgB,OAAO,KAAK,aAAa,CAAC,WAAW,GACxD,OAAO;CAGT,MAAM,YAAsB,EAAE;CAC9B,KAAK,MAAM,CAAC,QAAQ,OAAO,OAAO,QAAQ,aAAa,EAAE;EACvD,MAAM,eAAyB,EAAE;EACjC,KAAK,MAAM,CAAC,WAAW,UAAU,OAAO,QAAQ,GAAG,OAAO,EACxD,aAAa,KAAK,gCAAgC,WAAW,MAAM,CAAC;EAEtE,MAAM,aACJ,aAAa,SAAS,IAAI,KAAK,aAAa,KAAK,KAAK,CAAC,MAAM;EAC/D,UAAU,KAAK,YAAY,mBAAmB,OAAO,CAAC,uBAAuB,WAAW,IAAI;;CAG9F,OAAO,KAAK,UAAU,KAAK,KAAK,CAAC;;AAGnC,SAAgB,+BACd,cACA,aACQ;CACR,IAAI,CAAC,gBAAgB,OAAO,KAAK,aAAa,CAAC,WAAW,GACxD,OAAO;CAGT,MAAM,UAAoB,EAAE;CAC5B,KAAK,MAAM,CAAC,QAAQ,OAAO,OAAO,QAAQ,aAAa,EAAE;EACvD,MAAM,WAAW,uBAAuB,QAAQ,IAAI,cAAc,YAAY;EAC9E,QAAQ,KAAK,eAAe,OAAO,WAAW,SAAS,OAAO,GAAG;EACjE,QAAQ,KAAK,eAAe,OAAO,UAAU,SAAS,MAAM,GAAG;;CAEjE,OAAO,QAAQ,KAAK,KAAK"}
|
package/dist/exports/index.d.mts
CHANGED
|
@@ -18,7 +18,6 @@ declare function getEmittedArtifactPaths(outputJsonPath: string): EmittedArtifac
|
|
|
18
18
|
*/
|
|
19
19
|
interface EmitStackInput {
|
|
20
20
|
readonly codecTypeImports?: ReadonlyArray<TypesImportSpec>;
|
|
21
|
-
readonly operationTypeImports?: ReadonlyArray<TypesImportSpec>;
|
|
22
21
|
readonly queryOperationTypeImports?: ReadonlyArray<TypesImportSpec>;
|
|
23
22
|
readonly extensionIds?: ReadonlyArray<string>;
|
|
24
23
|
readonly codecLookup?: CodecLookup;
|
|
@@ -38,7 +37,7 @@ interface EmitResult {
|
|
|
38
37
|
declare function emit(contract: Contract, stack: EmitStackInput, targetFamily: EmissionSpi, options?: EmitOptions): Promise<EmitResult>;
|
|
39
38
|
//#endregion
|
|
40
39
|
//#region src/generate-contract-dts.d.ts
|
|
41
|
-
declare function generateContractDts(contract: Contract, emitter: EmissionSpi, codecTypeImports: ReadonlyArray<TypesImportSpec>,
|
|
40
|
+
declare function generateContractDts(contract: Contract, emitter: EmissionSpi, codecTypeImports: ReadonlyArray<TypesImportSpec>, hashes: {
|
|
42
41
|
readonly storageHash: string;
|
|
43
42
|
readonly executionHash?: string;
|
|
44
43
|
readonly profileHash: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/artifact-paths.ts","../../src/emit-types.ts","../../src/emit.ts","../../src/generate-contract-dts.ts"],"
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/artifact-paths.ts","../../src/emit-types.ts","../../src/emit.ts","../../src/generate-contract-dts.ts"],"mappings":";;;;;;UAEiB,oBAAA;EAAA,SACN,QAAA;EAAA,SACA,OAAA;AAAA;AAAA,iBAGK,uBAAA,CAAwB,cAAA,WAAyB,oBAAA;;;;;;;AALjE;UCMiB,cAAA;EAAA,SACN,gBAAA,GAAmB,aAAA,CAAc,eAAA;EAAA,SACjC,yBAAA,GAA4B,aAAA,CAAc,eAAA;EAAA,SAC1C,YAAA,GAAe,aAAA;EAAA,SACf,WAAA,GAAc,WAAA;AAAA;AAAA,UAGR,WAAA;EAAA,SACN,cAAA;AAAA;AAAA,UAGM,UAAA;EAAA,SACN,YAAA;EAAA,SACA,WAAA;EAAA,SACA,WAAA;EAAA,SACA,aAAA;EAAA,SACA,WAAA;AAAA;;;iBCbW,IAAA,CACpB,QAAA,EAAU,QAAA,EACV,KAAA,EAAO,cAAA,EACP,YAAA,EAAc,WAAA,EACd,OAAA,GAAU,WAAA,GACT,OAAA,CAAQ,UAAA;;;iBCKK,mBAAA,CACd,QAAA,EAAU,QAAA,EACV,OAAA,EAAS,WAAA,EACT,gBAAA,EAAkB,aAAA,CAAc,eAAA,GAChC,MAAA;EAAA,SACW,WAAA;EAAA,SACA,aAAA;EAAA,SACA,WAAA;AAAA,GAEX,OAAA,GAAU,4BAAA,EACV,WAAA,GAAc,WAAA"}
|
package/dist/exports/index.mjs
CHANGED
|
@@ -2,7 +2,6 @@ import { deduplicateImports, generateBothFieldTypesMaps, generateCodecTypeInters
|
|
|
2
2
|
import { canonicalizeContractToObject } from "@prisma-next/contract/hashing";
|
|
3
3
|
import { ifDefined } from "@prisma-next/utils/defined";
|
|
4
4
|
import { format } from "prettier";
|
|
5
|
-
|
|
6
5
|
//#region src/artifact-paths.ts
|
|
7
6
|
const JSON_EXTENSION = ".json";
|
|
8
7
|
function getEmittedArtifactPaths(outputJsonPath) {
|
|
@@ -12,17 +11,15 @@ function getEmittedArtifactPaths(outputJsonPath) {
|
|
|
12
11
|
dtsPath: `${outputJsonPath.slice(0, -5)}.d.ts`
|
|
13
12
|
};
|
|
14
13
|
}
|
|
15
|
-
|
|
16
14
|
//#endregion
|
|
17
15
|
//#region src/generate-contract-dts.ts
|
|
18
|
-
function generateContractDts(contract, emitter, codecTypeImports,
|
|
19
|
-
const allImports = [...codecTypeImports
|
|
16
|
+
function generateContractDts(contract, emitter, codecTypeImports, hashes, options, codecLookup) {
|
|
17
|
+
const allImports = [...codecTypeImports];
|
|
20
18
|
if (options?.queryOperationTypeImports) allImports.push(...options.queryOperationTypeImports);
|
|
21
19
|
const importLines = generateImportLines(deduplicateImports(allImports));
|
|
22
20
|
const familyImportLines = emitter.getFamilyImports();
|
|
23
21
|
const hashAliases = generateHashTypeAliases(hashes);
|
|
24
22
|
const codecTypes = generateCodecTypeIntersection(codecTypeImports, "CodecTypes");
|
|
25
|
-
const operationTypes = generateCodecTypeIntersection(operationTypeImports, "OperationTypes");
|
|
26
23
|
const familyTypeAliases = emitter.getFamilyTypeAliases(options);
|
|
27
24
|
const typeMapsExpr = emitter.getTypeMapsExpression();
|
|
28
25
|
const storageType = emitter.generateStorageType(contract, "StorageHash");
|
|
@@ -32,7 +29,12 @@ function generateContractDts(contract, emitter, codecTypeImports, operationTypeI
|
|
|
32
29
|
const valueObjectTypeAliases = generateValueObjectTypeAliases(valueObjects, codecLookup);
|
|
33
30
|
const valueObjectsDescriptor = generateValueObjectsDescriptorType(valueObjects);
|
|
34
31
|
const executionClause = contract.execution !== void 0 ? `\n readonly execution: ${serializeExecutionType(contract.execution)};` : "";
|
|
35
|
-
const
|
|
32
|
+
const resolveFieldTypeParams = emitter.resolveFieldTypeParams ? (modelName, fieldName) => {
|
|
33
|
+
const model = contract.models?.[modelName];
|
|
34
|
+
if (!model) return void 0;
|
|
35
|
+
return emitter.resolveFieldTypeParams?.(modelName, fieldName, model, contract);
|
|
36
|
+
} : void 0;
|
|
37
|
+
const fieldTypesMaps = generateBothFieldTypesMaps(contract.models, codecLookup, resolveFieldTypeParams);
|
|
36
38
|
const contractWrapper = emitter.getContractWrapper("ContractBase", "TypeMaps");
|
|
37
39
|
return `// ⚠️ GENERATED FILE - DO NOT EDIT
|
|
38
40
|
// This file is automatically generated by 'prisma-next contract emit'.
|
|
@@ -50,7 +52,6 @@ import type {
|
|
|
50
52
|
${hashAliases}
|
|
51
53
|
|
|
52
54
|
export type CodecTypes = ${codecTypes};
|
|
53
|
-
export type OperationTypes = ${operationTypes};
|
|
54
55
|
${familyTypeAliases}
|
|
55
56
|
${valueObjectTypeAliases}
|
|
56
57
|
export type FieldOutputTypes = ${fieldTypesMaps.output};
|
|
@@ -74,13 +75,12 @@ ${modelsType}
|
|
|
74
75
|
${contractWrapper}
|
|
75
76
|
`;
|
|
76
77
|
}
|
|
77
|
-
|
|
78
78
|
//#endregion
|
|
79
79
|
//#region src/emit.ts
|
|
80
80
|
const SCHEMA_VERSION = "1";
|
|
81
81
|
async function emit(contract, stack, targetFamily, options) {
|
|
82
82
|
if (options?.outputJsonPath !== void 0) getEmittedArtifactPaths(options.outputJsonPath);
|
|
83
|
-
const { codecTypeImports,
|
|
83
|
+
const { codecTypeImports, queryOperationTypeImports } = stack;
|
|
84
84
|
const { storageHash } = contract.storage;
|
|
85
85
|
const executionHash = contract.execution?.executionHash;
|
|
86
86
|
const { profileHash } = contract;
|
|
@@ -101,7 +101,7 @@ async function emit(contract, stack, targetFamily, options) {
|
|
|
101
101
|
};
|
|
102
102
|
return {
|
|
103
103
|
contractJson: contractJsonString,
|
|
104
|
-
contractDts: await format(generateContractDts(contract, targetFamily, codecTypeImports ?? [],
|
|
104
|
+
contractDts: await format(generateContractDts(contract, targetFamily, codecTypeImports ?? [], contractTypeHashes, generateOptions, stack.codecLookup), {
|
|
105
105
|
parser: "typescript",
|
|
106
106
|
singleQuote: true,
|
|
107
107
|
semi: true,
|
|
@@ -112,7 +112,7 @@ async function emit(contract, stack, targetFamily, options) {
|
|
|
112
112
|
profileHash
|
|
113
113
|
};
|
|
114
114
|
}
|
|
115
|
-
|
|
116
115
|
//#endregion
|
|
117
116
|
export { deduplicateImports, emit, generateCodecTypeIntersection, generateContractDts, generateFieldOutputTypesMap, generateHashTypeAliases, generateImportLines, generateModelRelationsType, generateRootsType, getEmittedArtifactPaths, serializeObjectKey, serializeValue };
|
|
117
|
+
|
|
118
118
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/artifact-paths.ts","../../src/generate-contract-dts.ts","../../src/emit.ts"],"sourcesContent":["const JSON_EXTENSION = '.json';\n\nexport interface EmittedArtifactPaths {\n readonly jsonPath: string;\n readonly dtsPath: string;\n}\n\nexport function getEmittedArtifactPaths(outputJsonPath: string): EmittedArtifactPaths {\n if (!outputJsonPath.endsWith(JSON_EXTENSION)) {\n throw new Error('Contract output path must end with .json');\n }\n\n return {\n jsonPath: outputJsonPath,\n dtsPath: `${outputJsonPath.slice(0, -JSON_EXTENSION.length)}.d.ts`,\n };\n}\n","import type { Contract, ContractModel, ContractValueObject } from '@prisma-next/contract/types';\nimport type { CodecLookup } from '@prisma-next/framework-components/codec';\nimport type {\n EmissionSpi,\n GenerateContractTypesOptions,\n TypesImportSpec,\n} from '@prisma-next/framework-components/emission';\nimport {\n deduplicateImports,\n generateBothFieldTypesMaps,\n generateCodecTypeIntersection,\n generateHashTypeAliases,\n generateImportLines,\n generateModelsType,\n generateRootsType,\n generateValueObjectsDescriptorType,\n generateValueObjectTypeAliases,\n serializeExecutionType,\n serializeValue,\n} from './domain-type-generation';\n\nexport function generateContractDts(\n contract: Contract,\n emitter: EmissionSpi,\n codecTypeImports: ReadonlyArray<TypesImportSpec>,\n hashes: {\n readonly storageHash: string;\n readonly executionHash?: string;\n readonly profileHash: string;\n },\n options?: GenerateContractTypesOptions,\n codecLookup?: CodecLookup,\n): string {\n const allImports: TypesImportSpec[] = [...codecTypeImports];\n if (options?.queryOperationTypeImports) {\n allImports.push(...options.queryOperationTypeImports);\n }\n const uniqueImports = deduplicateImports(allImports);\n const importLines = generateImportLines(uniqueImports);\n\n const familyImportLines = emitter.getFamilyImports();\n\n const hashAliases = generateHashTypeAliases(hashes);\n\n const codecTypes = generateCodecTypeIntersection(codecTypeImports, 'CodecTypes');\n\n const familyTypeAliases = emitter.getFamilyTypeAliases(options);\n\n const typeMapsExpr = emitter.getTypeMapsExpression();\n\n const storageType = emitter.generateStorageType(contract, 'StorageHash');\n\n const modelsType = generateModelsType(\n contract.models as Record<string, ContractModel>,\n (name, model) => emitter.generateModelStorageType(name, model),\n );\n\n const rootsType = generateRootsType(contract.roots);\n\n const valueObjects = contract.valueObjects as Record<string, ContractValueObject> | undefined;\n const valueObjectTypeAliases = generateValueObjectTypeAliases(valueObjects, codecLookup);\n const valueObjectsDescriptor = generateValueObjectsDescriptorType(valueObjects);\n\n const executionClause =\n contract.execution !== undefined\n ? `\\n readonly execution: ${serializeExecutionType(contract.execution)};`\n : '';\n\n const resolveFieldTypeParams = emitter.resolveFieldTypeParams\n ? (modelName: string, fieldName: string) => {\n const model = (contract.models as Record<string, ContractModel> | undefined)?.[modelName];\n if (!model) return undefined;\n return emitter.resolveFieldTypeParams?.(modelName, fieldName, model, contract);\n }\n : undefined;\n\n const fieldTypesMaps = generateBothFieldTypesMaps(\n contract.models as Record<string, ContractModel> | undefined,\n codecLookup,\n resolveFieldTypeParams,\n );\n\n const contractWrapper = emitter.getContractWrapper('ContractBase', 'TypeMaps');\n\n return `// ⚠️ GENERATED FILE - DO NOT EDIT\n// This file is automatically generated by 'prisma-next contract emit'.\n// To regenerate, run: prisma-next contract emit\n${importLines.join('\\n')}\n\n${familyImportLines.join('\\n')}\nimport type {\n Contract as ContractType,\n ExecutionHashBase,\n ProfileHashBase,\n StorageHashBase,\n} from '@prisma-next/contract/types';\n\n${hashAliases}\n\nexport type CodecTypes = ${codecTypes};\n${familyTypeAliases}\n${valueObjectTypeAliases}\nexport type FieldOutputTypes = ${fieldTypesMaps.output};\nexport type FieldInputTypes = ${fieldTypesMaps.input};\nexport type TypeMaps = ${typeMapsExpr};\n\ntype ContractBase = ContractType<\n${storageType},\n${modelsType}\n> & {\n readonly target: ${serializeValue(contract.target)};\n readonly targetFamily: ${serializeValue(contract.targetFamily)};\n readonly roots: ${rootsType};\n readonly capabilities: ${serializeValue(contract.capabilities)};\n readonly extensionPacks: ${serializeValue(contract.extensionPacks)};${executionClause}\n readonly meta: ${serializeValue(contract.meta)};\n ${valueObjects ? `readonly valueObjects: ${valueObjectsDescriptor};` : ''}\n readonly profileHash: ProfileHash;\n};\n\n${contractWrapper}\n`;\n}\n","import { canonicalizeContractToObject } from '@prisma-next/contract/hashing';\nimport type { Contract } from '@prisma-next/contract/types';\nimport type { EmissionSpi } from '@prisma-next/framework-components/emission';\nimport { ifDefined } from '@prisma-next/utils/defined';\nimport { format } from 'prettier';\nimport { getEmittedArtifactPaths } from './artifact-paths';\nimport type { EmitOptions, EmitResult, EmitStackInput } from './emit-types';\nimport { generateContractDts } from './generate-contract-dts';\n\nconst SCHEMA_VERSION = '1';\n\nexport async function emit(\n contract: Contract,\n stack: EmitStackInput,\n targetFamily: EmissionSpi,\n options?: EmitOptions,\n): Promise<EmitResult> {\n if (options?.outputJsonPath !== undefined) {\n getEmittedArtifactPaths(options.outputJsonPath);\n }\n\n const { codecTypeImports, queryOperationTypeImports } = stack;\n\n const { storageHash } = contract.storage;\n const executionHash = contract.execution?.executionHash;\n const { profileHash } = contract;\n\n const canonicalized = canonicalizeContractToObject(contract, {\n schemaVersion: SCHEMA_VERSION,\n });\n const contractJsonString = JSON.stringify(\n {\n ...canonicalized,\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 null,\n 2,\n );\n\n const generateOptions = queryOperationTypeImports ? { queryOperationTypeImports } : undefined;\n\n const contractTypeHashes = {\n storageHash,\n ...ifDefined('executionHash', executionHash),\n profileHash,\n };\n const contractDtsRaw = generateContractDts(\n contract,\n targetFamily,\n codecTypeImports ?? [],\n contractTypeHashes,\n generateOptions,\n stack.codecLookup,\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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.mts","names":[],"sources":["../../test/utils.ts"],"
|
|
1
|
+
{"version":3,"file":"utils.d.mts","names":[],"sources":["../../test/utils.ts"],"mappings":";;;KAGK,qBAAA;EACH,MAAA;EACA,YAAA;EACA,KAAA,GAAQ,MAAA;EACR,MAAA,GAAS,MAAA;EACT,OAAA,GAAU,MAAA;EACV,YAAA,GAAe,MAAA,SAAe,MAAA;EAC9B,cAAA,GAAiB,MAAA;EACjB,SAAA,GAAY,MAAA;EACZ,IAAA,GAAO,MAAA;EACP,WAAA;EACA,aAAA;EACA,OAAA,GAAU,MAAA;AAAA;AAAA,iBAGI,kBAAA,CAAmB,SAAA,GAAW,qBAAA,GAA6B,QAAA"}
|
package/dist/test/utils.mjs
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { createContract } from "@prisma-next/contract/testing";
|
|
2
|
-
|
|
3
2
|
//#region test/utils.ts
|
|
4
3
|
function createTestContract(overrides = {}) {
|
|
5
4
|
const { storageHash: _sh, schemaVersion: _sv, sources: _src, storage, ...rest } = overrides;
|
|
@@ -12,7 +11,7 @@ function createTestContract(overrides = {}) {
|
|
|
12
11
|
...cleanStorage ? { storage: cleanStorage } : {}
|
|
13
12
|
});
|
|
14
13
|
}
|
|
15
|
-
|
|
16
14
|
//#endregion
|
|
17
15
|
export { createTestContract };
|
|
16
|
+
|
|
18
17
|
//# sourceMappingURL=utils.mjs.map
|
package/dist/test/utils.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.mjs","names":[],"sources":["../../test/utils.ts"],"sourcesContent":["import { createContract } from '@prisma-next/contract/testing';\nimport type { Contract } from '@prisma-next/contract/types';\n\ntype TestContractOverrides = {\n target?: string;\n targetFamily?: string;\n roots?: Record<string, string>;\n models?: Record<string, unknown>;\n storage?: Record<string, unknown>;\n capabilities?: Record<string, Record<string, boolean>>;\n extensionPacks?: Record<string, unknown>;\n execution?: Record<string, unknown>;\n meta?: Record<string, unknown>;\n storageHash?: string;\n schemaVersion?: string;\n sources?: Record<string, unknown>;\n};\n\nexport function createTestContract(overrides: TestContractOverrides = {}): Contract {\n const { storageHash: _sh, schemaVersion: _sv, sources: _src, storage, ...rest } = overrides;\n const cleanStorage = storage\n ? (() => {\n const { storageHash: _innerSh, ...storageRest } = storage as Record<string, unknown>;\n return storageRest;\n })()\n : undefined;\n return createContract({\n ...rest,\n ...(cleanStorage ? { storage: cleanStorage } : {}),\n } as Parameters<typeof createContract>[0]);\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"utils.mjs","names":[],"sources":["../../test/utils.ts"],"sourcesContent":["import { createContract } from '@prisma-next/contract/testing';\nimport type { Contract } from '@prisma-next/contract/types';\n\ntype TestContractOverrides = {\n target?: string;\n targetFamily?: string;\n roots?: Record<string, string>;\n models?: Record<string, unknown>;\n storage?: Record<string, unknown>;\n capabilities?: Record<string, Record<string, boolean>>;\n extensionPacks?: Record<string, unknown>;\n execution?: Record<string, unknown>;\n meta?: Record<string, unknown>;\n storageHash?: string;\n schemaVersion?: string;\n sources?: Record<string, unknown>;\n};\n\nexport function createTestContract(overrides: TestContractOverrides = {}): Contract {\n const { storageHash: _sh, schemaVersion: _sv, sources: _src, storage, ...rest } = overrides;\n const cleanStorage = storage\n ? (() => {\n const { storageHash: _innerSh, ...storageRest } = storage as Record<string, unknown>;\n return storageRest;\n })()\n : undefined;\n return createContract({\n ...rest,\n ...(cleanStorage ? { storage: cleanStorage } : {}),\n } as Parameters<typeof createContract>[0]);\n}\n"],"mappings":";;AAkBA,SAAgB,mBAAmB,YAAmC,EAAE,EAAY;CAClF,MAAM,EAAE,aAAa,KAAK,eAAe,KAAK,SAAS,MAAM,SAAS,GAAG,SAAS;CAClF,MAAM,eAAe,iBACV;EACL,MAAM,EAAE,aAAa,UAAU,GAAG,gBAAgB;EAClD,OAAO;KACL,GACJ,KAAA;CACJ,OAAO,eAAe;EACpB,GAAG;EACH,GAAI,eAAe,EAAE,SAAS,cAAc,GAAG,EAAE;EAClD,CAAyC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"type-expression-safety.d.mts","names":[],"sources":["../src/type-expression-safety.ts"],"
|
|
1
|
+
{"version":3,"file":"type-expression-safety.d.mts","names":[],"sources":["../src/type-expression-safety.ts"],"mappings":";iBAAgB,oBAAA,CAAqB,IAAA"}
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
//#region src/type-expression-safety.ts
|
|
2
|
+
function isSafeTypeExpression(expr) {
|
|
3
|
+
return !/import\s*\(|require\s*\(|declare\s|export\s|eval\s*\(/.test(expr);
|
|
4
|
+
}
|
|
5
|
+
//#endregion
|
|
6
|
+
export { isSafeTypeExpression };
|
|
2
7
|
|
|
3
|
-
|
|
8
|
+
//# sourceMappingURL=type-expression-safety.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"type-expression-safety.mjs","names":[],"sources":["../src/type-expression-safety.ts"],"sourcesContent":["export function isSafeTypeExpression(expr: string): boolean {\n return !/import\\s*\\(|require\\s*\\(|declare\\s|export\\s|eval\\s*\\(/.test(expr);\n}\n"],"mappings":";AAAA,SAAgB,qBAAqB,MAAuB;CAC1D,OAAO,CAAC,wDAAwD,KAAK,KAAK"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma-next/emitter",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.1",
|
|
4
|
+
"license": "Apache-2.0",
|
|
4
5
|
"type": "module",
|
|
5
6
|
"sideEffects": false,
|
|
6
7
|
"files": [
|
|
@@ -8,18 +9,18 @@
|
|
|
8
9
|
"src"
|
|
9
10
|
],
|
|
10
11
|
"dependencies": {
|
|
11
|
-
"arktype": "^2.
|
|
12
|
-
"prettier": "^3.
|
|
13
|
-
"@prisma-next/
|
|
14
|
-
"@prisma-next/
|
|
15
|
-
"@prisma-next/
|
|
16
|
-
"@prisma-next/
|
|
12
|
+
"arktype": "^2.1.29",
|
|
13
|
+
"prettier": "^3.8.3",
|
|
14
|
+
"@prisma-next/contract": "0.5.1",
|
|
15
|
+
"@prisma-next/framework-components": "0.5.1",
|
|
16
|
+
"@prisma-next/utils": "0.5.1",
|
|
17
|
+
"@prisma-next/operations": "0.5.1"
|
|
17
18
|
},
|
|
18
19
|
"devDependencies": {
|
|
19
20
|
"@types/node": "24.10.4",
|
|
20
|
-
"tsdown": "0.
|
|
21
|
+
"tsdown": "0.22.0",
|
|
21
22
|
"typescript": "5.9.3",
|
|
22
|
-
"vitest": "4.
|
|
23
|
+
"vitest": "4.1.5",
|
|
23
24
|
"@prisma-next/test-utils": "0.0.1",
|
|
24
25
|
"@prisma-next/tsconfig": "0.0.0",
|
|
25
26
|
"@prisma-next/tsdown": "0.0.0"
|
|
@@ -225,22 +225,33 @@ function applyModifiers(base: string, field: ContractField): string {
|
|
|
225
225
|
return result;
|
|
226
226
|
}
|
|
227
227
|
|
|
228
|
+
/**
|
|
229
|
+
* Per-family resolver for typeParams that don't live inline on the framework-domain `ContractField`. SQL columns authored via a named `storage.types` entry carry their `typeRef` on the storage column (family-specific) rather than on the framework's domain field; the per-family emitter walks `storage.types[ref].typeParams` here so the framework emit path can render the parameterized output type.
|
|
230
|
+
*
|
|
231
|
+
* Returns `undefined` when the field has no resolvable typeParams (i.e. the column isn't parameterized, isn't a `typeRef`, or the family doesn't support named storage types).
|
|
232
|
+
*/
|
|
233
|
+
export type FieldTypeParamsResolver = (
|
|
234
|
+
modelName: string,
|
|
235
|
+
fieldName: string,
|
|
236
|
+
) => Record<string, unknown> | undefined;
|
|
237
|
+
|
|
228
238
|
export function resolveFieldType(
|
|
229
239
|
field: ContractField,
|
|
230
240
|
codecLookup?: CodecLookup,
|
|
241
|
+
resolvedTypeParams?: Record<string, unknown>,
|
|
231
242
|
): ResolvedFieldType {
|
|
232
243
|
const { type } = field;
|
|
233
244
|
|
|
234
245
|
switch (type.kind) {
|
|
235
246
|
case 'scalar': {
|
|
236
247
|
let outputResolved: string | undefined;
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
248
|
+
const inlineTypeParams =
|
|
249
|
+
type.typeParams && Object.keys(type.typeParams).length > 0 ? type.typeParams : undefined;
|
|
250
|
+
const effectiveTypeParams = inlineTypeParams ?? resolvedTypeParams;
|
|
251
|
+
if (codecLookup && effectiveTypeParams && Object.keys(effectiveTypeParams).length > 0) {
|
|
252
|
+
const rendered = codecLookup.renderOutputTypeFor(type.codecId, effectiveTypeParams);
|
|
253
|
+
if (rendered && isSafeTypeExpression(rendered)) {
|
|
254
|
+
outputResolved = rendered;
|
|
244
255
|
}
|
|
245
256
|
}
|
|
246
257
|
const codecAccessor = `CodecTypes[${serializeValue(type.codecId)}]`;
|
|
@@ -289,6 +300,7 @@ export function generateFieldResolvedType(
|
|
|
289
300
|
export function generateBothFieldTypesMaps(
|
|
290
301
|
models: Record<string, ContractModel> | undefined,
|
|
291
302
|
codecLookup?: CodecLookup,
|
|
303
|
+
resolveFieldTypeParams?: FieldTypeParamsResolver,
|
|
292
304
|
): ResolvedFieldType {
|
|
293
305
|
if (!models || Object.keys(models).length === 0) {
|
|
294
306
|
return { output: 'Record<string, never>', input: 'Record<string, never>' };
|
|
@@ -301,7 +313,14 @@ export function generateBothFieldTypesMaps(
|
|
|
301
313
|
const outputFieldEntries: string[] = [];
|
|
302
314
|
const inputFieldEntries: string[] = [];
|
|
303
315
|
for (const [fieldName, field] of Object.entries(model.fields)) {
|
|
304
|
-
const
|
|
316
|
+
const inlineTypeParams =
|
|
317
|
+
field.type.kind === 'scalar' &&
|
|
318
|
+
field.type.typeParams &&
|
|
319
|
+
Object.keys(field.type.typeParams).length > 0
|
|
320
|
+
? field.type.typeParams
|
|
321
|
+
: undefined;
|
|
322
|
+
const resolvedTypeParams = inlineTypeParams ?? resolveFieldTypeParams?.(modelName, fieldName);
|
|
323
|
+
const resolved = resolveFieldType(field, codecLookup, resolvedTypeParams);
|
|
305
324
|
const key = `readonly ${serializeObjectKey(fieldName)}`;
|
|
306
325
|
outputFieldEntries.push(`${key}: ${resolved.output}`);
|
|
307
326
|
inputFieldEntries.push(`${key}: ${resolved.input}`);
|
|
@@ -328,15 +347,17 @@ export function generateBothFieldTypesMaps(
|
|
|
328
347
|
export function generateFieldOutputTypesMap(
|
|
329
348
|
models: Record<string, ContractModel> | undefined,
|
|
330
349
|
codecLookup?: CodecLookup,
|
|
350
|
+
resolveFieldTypeParams?: FieldTypeParamsResolver,
|
|
331
351
|
): string {
|
|
332
|
-
return generateBothFieldTypesMaps(models, codecLookup).output;
|
|
352
|
+
return generateBothFieldTypesMaps(models, codecLookup, resolveFieldTypeParams).output;
|
|
333
353
|
}
|
|
334
354
|
|
|
335
355
|
export function generateFieldInputTypesMap(
|
|
336
356
|
models: Record<string, ContractModel> | undefined,
|
|
337
357
|
codecLookup?: CodecLookup,
|
|
358
|
+
resolveFieldTypeParams?: FieldTypeParamsResolver,
|
|
338
359
|
): string {
|
|
339
|
-
return generateBothFieldTypesMaps(models, codecLookup).input;
|
|
360
|
+
return generateBothFieldTypesMaps(models, codecLookup, resolveFieldTypeParams).input;
|
|
340
361
|
}
|
|
341
362
|
|
|
342
363
|
export function generateValueObjectType(
|
package/src/emit-types.ts
CHANGED
|
@@ -8,7 +8,6 @@ import type { TypesImportSpec } from '@prisma-next/framework-components/emission
|
|
|
8
8
|
*/
|
|
9
9
|
export interface EmitStackInput {
|
|
10
10
|
readonly codecTypeImports?: ReadonlyArray<TypesImportSpec>;
|
|
11
|
-
readonly operationTypeImports?: ReadonlyArray<TypesImportSpec>;
|
|
12
11
|
readonly queryOperationTypeImports?: ReadonlyArray<TypesImportSpec>;
|
|
13
12
|
readonly extensionIds?: ReadonlyArray<string>;
|
|
14
13
|
readonly codecLookup?: CodecLookup;
|
package/src/emit.ts
CHANGED
|
@@ -19,7 +19,7 @@ export async function emit(
|
|
|
19
19
|
getEmittedArtifactPaths(options.outputJsonPath);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
const { codecTypeImports,
|
|
22
|
+
const { codecTypeImports, queryOperationTypeImports } = stack;
|
|
23
23
|
|
|
24
24
|
const { storageHash } = contract.storage;
|
|
25
25
|
const executionHash = contract.execution?.executionHash;
|
|
@@ -52,7 +52,6 @@ export async function emit(
|
|
|
52
52
|
contract,
|
|
53
53
|
targetFamily,
|
|
54
54
|
codecTypeImports ?? [],
|
|
55
|
-
operationTypeImports ?? [],
|
|
56
55
|
contractTypeHashes,
|
|
57
56
|
generateOptions,
|
|
58
57
|
stack.codecLookup,
|
|
@@ -23,7 +23,6 @@ export function generateContractDts(
|
|
|
23
23
|
contract: Contract,
|
|
24
24
|
emitter: EmissionSpi,
|
|
25
25
|
codecTypeImports: ReadonlyArray<TypesImportSpec>,
|
|
26
|
-
operationTypeImports: ReadonlyArray<TypesImportSpec>,
|
|
27
26
|
hashes: {
|
|
28
27
|
readonly storageHash: string;
|
|
29
28
|
readonly executionHash?: string;
|
|
@@ -32,7 +31,7 @@ export function generateContractDts(
|
|
|
32
31
|
options?: GenerateContractTypesOptions,
|
|
33
32
|
codecLookup?: CodecLookup,
|
|
34
33
|
): string {
|
|
35
|
-
const allImports: TypesImportSpec[] = [...codecTypeImports
|
|
34
|
+
const allImports: TypesImportSpec[] = [...codecTypeImports];
|
|
36
35
|
if (options?.queryOperationTypeImports) {
|
|
37
36
|
allImports.push(...options.queryOperationTypeImports);
|
|
38
37
|
}
|
|
@@ -44,7 +43,6 @@ export function generateContractDts(
|
|
|
44
43
|
const hashAliases = generateHashTypeAliases(hashes);
|
|
45
44
|
|
|
46
45
|
const codecTypes = generateCodecTypeIntersection(codecTypeImports, 'CodecTypes');
|
|
47
|
-
const operationTypes = generateCodecTypeIntersection(operationTypeImports, 'OperationTypes');
|
|
48
46
|
|
|
49
47
|
const familyTypeAliases = emitter.getFamilyTypeAliases(options);
|
|
50
48
|
|
|
@@ -68,9 +66,18 @@ export function generateContractDts(
|
|
|
68
66
|
? `\n readonly execution: ${serializeExecutionType(contract.execution)};`
|
|
69
67
|
: '';
|
|
70
68
|
|
|
69
|
+
const resolveFieldTypeParams = emitter.resolveFieldTypeParams
|
|
70
|
+
? (modelName: string, fieldName: string) => {
|
|
71
|
+
const model = (contract.models as Record<string, ContractModel> | undefined)?.[modelName];
|
|
72
|
+
if (!model) return undefined;
|
|
73
|
+
return emitter.resolveFieldTypeParams?.(modelName, fieldName, model, contract);
|
|
74
|
+
}
|
|
75
|
+
: undefined;
|
|
76
|
+
|
|
71
77
|
const fieldTypesMaps = generateBothFieldTypesMaps(
|
|
72
78
|
contract.models as Record<string, ContractModel> | undefined,
|
|
73
79
|
codecLookup,
|
|
80
|
+
resolveFieldTypeParams,
|
|
74
81
|
);
|
|
75
82
|
|
|
76
83
|
const contractWrapper = emitter.getContractWrapper('ContractBase', 'TypeMaps');
|
|
@@ -91,7 +98,6 @@ import type {
|
|
|
91
98
|
${hashAliases}
|
|
92
99
|
|
|
93
100
|
export type CodecTypes = ${codecTypes};
|
|
94
|
-
export type OperationTypes = ${operationTypes};
|
|
95
101
|
${familyTypeAliases}
|
|
96
102
|
${valueObjectTypeAliases}
|
|
97
103
|
export type FieldOutputTypes = ${fieldTypesMaps.output};
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
//#region src/type-expression-safety.ts
|
|
2
|
-
function isSafeTypeExpression(expr) {
|
|
3
|
-
return !/import\s*\(|require\s*\(|declare\s|export\s|eval\s*\(/.test(expr);
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
//#endregion
|
|
7
|
-
export { isSafeTypeExpression as t };
|
|
8
|
-
//# sourceMappingURL=type-expression-safety-7_1tfJXA.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"type-expression-safety-7_1tfJXA.mjs","names":[],"sources":["../src/type-expression-safety.ts"],"sourcesContent":["export function isSafeTypeExpression(expr: string): boolean {\n return !/import\\s*\\(|require\\s*\\(|declare\\s|export\\s|eval\\s*\\(/.test(expr);\n}\n"],"mappings":";AAAA,SAAgB,qBAAqB,MAAuB;AAC1D,QAAO,CAAC,wDAAwD,KAAK,KAAK"}
|