@prisma-next/emitter 0.4.0-dev.9 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/exports/index.d.mts +12 -3
- package/dist/exports/index.d.mts.map +1 -1
- package/dist/exports/index.mjs +14 -2
- package/dist/exports/index.mjs.map +1 -1
- package/package.json +6 -6
- package/src/artifact-paths.ts +17 -0
- package/src/emit-types.ts +4 -0
- package/src/emit.ts +7 -1
- package/src/exports/index.ts +2 -0
- package/test/emitter.test.ts +51 -16
package/dist/exports/index.d.mts
CHANGED
|
@@ -3,8 +3,14 @@ import { Contract } from "@prisma-next/contract/types";
|
|
|
3
3
|
import { CodecLookup } from "@prisma-next/framework-components/codec";
|
|
4
4
|
import { EmissionSpi, GenerateContractTypesOptions, TypesImportSpec } from "@prisma-next/framework-components/emission";
|
|
5
5
|
|
|
6
|
+
//#region src/artifact-paths.d.ts
|
|
7
|
+
interface EmittedArtifactPaths {
|
|
8
|
+
readonly jsonPath: string;
|
|
9
|
+
readonly dtsPath: string;
|
|
10
|
+
}
|
|
11
|
+
declare function getEmittedArtifactPaths(outputJsonPath: string): EmittedArtifactPaths;
|
|
12
|
+
//#endregion
|
|
6
13
|
//#region src/emit-types.d.ts
|
|
7
|
-
|
|
8
14
|
/**
|
|
9
15
|
* The subset of ControlStack that emit() reads.
|
|
10
16
|
* All fields are optional so tests can pass minimal objects.
|
|
@@ -17,6 +23,9 @@ interface EmitStackInput {
|
|
|
17
23
|
readonly extensionIds?: ReadonlyArray<string>;
|
|
18
24
|
readonly codecLookup?: CodecLookup;
|
|
19
25
|
}
|
|
26
|
+
interface EmitOptions {
|
|
27
|
+
readonly outputJsonPath?: string;
|
|
28
|
+
}
|
|
20
29
|
interface EmitResult {
|
|
21
30
|
readonly contractJson: string;
|
|
22
31
|
readonly contractDts: string;
|
|
@@ -26,7 +35,7 @@ interface EmitResult {
|
|
|
26
35
|
}
|
|
27
36
|
//#endregion
|
|
28
37
|
//#region src/emit.d.ts
|
|
29
|
-
declare function emit(contract: Contract, stack: EmitStackInput, targetFamily: EmissionSpi): Promise<EmitResult>;
|
|
38
|
+
declare function emit(contract: Contract, stack: EmitStackInput, targetFamily: EmissionSpi, options?: EmitOptions): Promise<EmitResult>;
|
|
30
39
|
//#endregion
|
|
31
40
|
//#region src/generate-contract-dts.d.ts
|
|
32
41
|
declare function generateContractDts(contract: Contract, emitter: EmissionSpi, codecTypeImports: ReadonlyArray<TypesImportSpec>, operationTypeImports: ReadonlyArray<TypesImportSpec>, hashes: {
|
|
@@ -35,5 +44,5 @@ declare function generateContractDts(contract: Contract, emitter: EmissionSpi, c
|
|
|
35
44
|
readonly profileHash: string;
|
|
36
45
|
}, options?: GenerateContractTypesOptions, codecLookup?: CodecLookup): string;
|
|
37
46
|
//#endregion
|
|
38
|
-
export { type EmitResult, type EmitStackInput, deduplicateImports, emit, generateCodecTypeIntersection, generateContractDts, generateFieldOutputTypesMap, generateHashTypeAliases, generateImportLines, generateModelRelationsType, generateRootsType, serializeObjectKey, serializeValue };
|
|
47
|
+
export { type EmitResult, type EmitStackInput, type EmittedArtifactPaths, deduplicateImports, emit, generateCodecTypeIntersection, generateContractDts, generateFieldOutputTypesMap, generateHashTypeAliases, generateImportLines, generateModelRelationsType, generateRootsType, getEmittedArtifactPaths, serializeObjectKey, serializeValue };
|
|
39
48
|
//# sourceMappingURL=index.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/emit-types.ts","../../src/emit.ts","../../src/generate-contract-dts.ts"],"sourcesContent":[],"mappings":"
|
|
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"],"sourcesContent":[],"mappings":";;;;;;UAEiB,oBAAA;;;;iBAKD,uBAAA,0BAAiD;;;;;;;AALjE;AAKgB,UCCC,cAAA,CDDsB;8BCET,cAAc;kCACV,cAAc;uCACT,cAAc;EAHpC,SAAA,YAAc,CAAA,EAIL,aAJK,CAAA,MAAA,CAAA;EACa,SAAA,WAAA,CAAA,EAInB,WAJmB;;AACI,UAM/B,WAAA,CAN+B;EAAd,SAAA,cAAA,CAAA,EAAA,MAAA;;AACK,UAStB,UAAA,CATsB;EACb,SAAA,YAAA,EAAA,MAAA;EACD,SAAA,WAAA,EAAA,MAAA;EAAW,SAAA,WAAA,EAAA,MAAA;EAGnB,SAAA,aAAW,CAAA,EAAA,MAAA;EAIX,SAAA,WAAU,EAAA,MAAA;;;;iBCTL,IAAA,WACV,iBACH,8BACO,uBACJ,cACT,QAAQ;;;iBCKK,mBAAA,WACJ,mBACD,+BACS,cAAc,wCACV,cAAc;;;EHvBrB,SAAA,WAAA,EAAA,MAAoB;AAKrC,CAAA,EAAA,OAAuC,CAAvB,EGwBJ,4BHxB2B,EAA0B,WAAoB,CAApB,EGyBjD,WHzBqE,CAAA,EAAA,MAAA"}
|
package/dist/exports/index.mjs
CHANGED
|
@@ -3,6 +3,17 @@ import { canonicalizeContractToObject } from "@prisma-next/contract/hashing";
|
|
|
3
3
|
import { ifDefined } from "@prisma-next/utils/defined";
|
|
4
4
|
import { format } from "prettier";
|
|
5
5
|
|
|
6
|
+
//#region src/artifact-paths.ts
|
|
7
|
+
const JSON_EXTENSION = ".json";
|
|
8
|
+
function getEmittedArtifactPaths(outputJsonPath) {
|
|
9
|
+
if (!outputJsonPath.endsWith(JSON_EXTENSION)) throw new Error("Contract output path must end with .json");
|
|
10
|
+
return {
|
|
11
|
+
jsonPath: outputJsonPath,
|
|
12
|
+
dtsPath: `${outputJsonPath.slice(0, -5)}.d.ts`
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
//#endregion
|
|
6
17
|
//#region src/generate-contract-dts.ts
|
|
7
18
|
function generateContractDts(contract, emitter, codecTypeImports, operationTypeImports, hashes, options, codecLookup) {
|
|
8
19
|
const allImports = [...codecTypeImports, ...operationTypeImports];
|
|
@@ -67,7 +78,8 @@ ${contractWrapper}
|
|
|
67
78
|
//#endregion
|
|
68
79
|
//#region src/emit.ts
|
|
69
80
|
const SCHEMA_VERSION = "1";
|
|
70
|
-
async function emit(contract, stack, targetFamily) {
|
|
81
|
+
async function emit(contract, stack, targetFamily, options) {
|
|
82
|
+
if (options?.outputJsonPath !== void 0) getEmittedArtifactPaths(options.outputJsonPath);
|
|
71
83
|
const { codecTypeImports, operationTypeImports, queryOperationTypeImports } = stack;
|
|
72
84
|
const { storageHash } = contract.storage;
|
|
73
85
|
const executionHash = contract.execution?.executionHash;
|
|
@@ -102,5 +114,5 @@ async function emit(contract, stack, targetFamily) {
|
|
|
102
114
|
}
|
|
103
115
|
|
|
104
116
|
//#endregion
|
|
105
|
-
export { deduplicateImports, emit, generateCodecTypeIntersection, generateContractDts, generateFieldOutputTypesMap, generateHashTypeAliases, generateImportLines, generateModelRelationsType, generateRootsType, serializeObjectKey, serializeValue };
|
|
117
|
+
export { deduplicateImports, emit, generateCodecTypeIntersection, generateContractDts, generateFieldOutputTypesMap, generateHashTypeAliases, generateImportLines, generateModelRelationsType, generateRootsType, getEmittedArtifactPaths, serializeObjectKey, serializeValue };
|
|
106
118
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["allImports: TypesImportSpec[]"],"sources":["../../src/generate-contract-dts.ts","../../src/emit.ts"],"sourcesContent":["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 operationTypeImports: 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, ...operationTypeImports];\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 const operationTypes = generateCodecTypeIntersection(operationTypeImports, 'OperationTypes');\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 fieldTypesMaps = generateBothFieldTypesMaps(\n contract.models as Record<string, ContractModel> | undefined,\n codecLookup,\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};\nexport type OperationTypes = ${operationTypes};\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 type { 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): Promise<EmitResult> {\n const { codecTypeImports, operationTypeImports, 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 operationTypeImports ?? [],\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":";;;;;;
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["allImports: TypesImportSpec[]"],"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 operationTypeImports: 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, ...operationTypeImports];\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 const operationTypes = generateCodecTypeIntersection(operationTypeImports, 'OperationTypes');\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 fieldTypesMaps = generateBothFieldTypesMaps(\n contract.models as Record<string, ContractModel> | undefined,\n codecLookup,\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};\nexport type OperationTypes = ${operationTypes};\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, operationTypeImports, 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 operationTypeImports ?? [],\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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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma-next/emitter",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"files": [
|
|
@@ -11,18 +11,18 @@
|
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"arktype": "^2.0.0",
|
|
13
13
|
"prettier": "^3.3.3",
|
|
14
|
-
"@prisma-next/
|
|
15
|
-
"@prisma-next/
|
|
16
|
-
"@prisma-next/
|
|
17
|
-
"@prisma-next/
|
|
14
|
+
"@prisma-next/contract": "0.4.1",
|
|
15
|
+
"@prisma-next/framework-components": "0.4.1",
|
|
16
|
+
"@prisma-next/operations": "0.4.1",
|
|
17
|
+
"@prisma-next/utils": "0.4.1"
|
|
18
18
|
},
|
|
19
19
|
"devDependencies": {
|
|
20
20
|
"@types/node": "24.10.4",
|
|
21
21
|
"tsdown": "0.18.4",
|
|
22
22
|
"typescript": "5.9.3",
|
|
23
23
|
"vitest": "4.0.17",
|
|
24
|
-
"@prisma-next/test-utils": "0.0.1",
|
|
25
24
|
"@prisma-next/tsconfig": "0.0.0",
|
|
25
|
+
"@prisma-next/test-utils": "0.0.1",
|
|
26
26
|
"@prisma-next/tsdown": "0.0.0"
|
|
27
27
|
},
|
|
28
28
|
"exports": {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const JSON_EXTENSION = '.json';
|
|
2
|
+
|
|
3
|
+
export interface EmittedArtifactPaths {
|
|
4
|
+
readonly jsonPath: string;
|
|
5
|
+
readonly dtsPath: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function getEmittedArtifactPaths(outputJsonPath: string): EmittedArtifactPaths {
|
|
9
|
+
if (!outputJsonPath.endsWith(JSON_EXTENSION)) {
|
|
10
|
+
throw new Error('Contract output path must end with .json');
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return {
|
|
14
|
+
jsonPath: outputJsonPath,
|
|
15
|
+
dtsPath: `${outputJsonPath.slice(0, -JSON_EXTENSION.length)}.d.ts`,
|
|
16
|
+
};
|
|
17
|
+
}
|
package/src/emit-types.ts
CHANGED
|
@@ -14,6 +14,10 @@ export interface EmitStackInput {
|
|
|
14
14
|
readonly codecLookup?: CodecLookup;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
export interface EmitOptions {
|
|
18
|
+
readonly outputJsonPath?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
17
21
|
export interface EmitResult {
|
|
18
22
|
readonly contractJson: string;
|
|
19
23
|
readonly contractDts: string;
|
package/src/emit.ts
CHANGED
|
@@ -3,7 +3,8 @@ import type { Contract } from '@prisma-next/contract/types';
|
|
|
3
3
|
import type { EmissionSpi } from '@prisma-next/framework-components/emission';
|
|
4
4
|
import { ifDefined } from '@prisma-next/utils/defined';
|
|
5
5
|
import { format } from 'prettier';
|
|
6
|
-
import
|
|
6
|
+
import { getEmittedArtifactPaths } from './artifact-paths';
|
|
7
|
+
import type { EmitOptions, EmitResult, EmitStackInput } from './emit-types';
|
|
7
8
|
import { generateContractDts } from './generate-contract-dts';
|
|
8
9
|
|
|
9
10
|
const SCHEMA_VERSION = '1';
|
|
@@ -12,7 +13,12 @@ export async function emit(
|
|
|
12
13
|
contract: Contract,
|
|
13
14
|
stack: EmitStackInput,
|
|
14
15
|
targetFamily: EmissionSpi,
|
|
16
|
+
options?: EmitOptions,
|
|
15
17
|
): Promise<EmitResult> {
|
|
18
|
+
if (options?.outputJsonPath !== undefined) {
|
|
19
|
+
getEmittedArtifactPaths(options.outputJsonPath);
|
|
20
|
+
}
|
|
21
|
+
|
|
16
22
|
const { codecTypeImports, operationTypeImports, queryOperationTypeImports } = stack;
|
|
17
23
|
|
|
18
24
|
const { storageHash } = contract.storage;
|
package/src/exports/index.ts
CHANGED
package/test/emitter.test.ts
CHANGED
|
@@ -2,13 +2,44 @@ import type { TypesImportSpec } from '@prisma-next/framework-components/emission
|
|
|
2
2
|
import { timeouts } from '@prisma-next/test-utils';
|
|
3
3
|
import { describe, expect, it } from 'vitest';
|
|
4
4
|
import type { EmitStackInput } from '../src/exports';
|
|
5
|
-
import { emit } from '../src/exports';
|
|
5
|
+
import { emit, getEmittedArtifactPaths } from '../src/exports';
|
|
6
6
|
import { createMockSpi } from './mock-spi';
|
|
7
7
|
import { createTestContract } from './utils';
|
|
8
8
|
|
|
9
9
|
const mockSqlHook = createMockSpi();
|
|
10
10
|
|
|
11
11
|
describe('emitter', () => {
|
|
12
|
+
it('derives colocated artifact paths from contract.json output', () => {
|
|
13
|
+
expect(getEmittedArtifactPaths('/abs/contract.json')).toEqual({
|
|
14
|
+
jsonPath: '/abs/contract.json',
|
|
15
|
+
dtsPath: '/abs/contract.d.ts',
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('rejects non-json output paths when deriving artifact paths', () => {
|
|
20
|
+
expect(() => getEmittedArtifactPaths('/abs/contract.ts')).toThrow(
|
|
21
|
+
'Contract output path must end with .json',
|
|
22
|
+
);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it(
|
|
26
|
+
'rejects non-json output paths when emit receives an output path',
|
|
27
|
+
async () => {
|
|
28
|
+
const ir = createTestContract();
|
|
29
|
+
const options: EmitStackInput = {
|
|
30
|
+
codecTypeImports: [],
|
|
31
|
+
operationTypeImports: [],
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
await expect(
|
|
35
|
+
emit(ir, options, mockSqlHook, {
|
|
36
|
+
outputJsonPath: '/abs/contract.ts',
|
|
37
|
+
}),
|
|
38
|
+
).rejects.toThrow('Contract output path must end with .json');
|
|
39
|
+
},
|
|
40
|
+
timeouts.typeScriptCompilation,
|
|
41
|
+
);
|
|
42
|
+
|
|
12
43
|
it(
|
|
13
44
|
'emits contract.json and contract.d.ts',
|
|
14
45
|
async () => {
|
|
@@ -182,23 +213,27 @@ describe('emitter', () => {
|
|
|
182
213
|
expect(result.contractDts).toBeDefined();
|
|
183
214
|
});
|
|
184
215
|
|
|
185
|
-
it(
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
216
|
+
it(
|
|
217
|
+
'omits sources from emitted contract artifact',
|
|
218
|
+
async () => {
|
|
219
|
+
const ir = createTestContract({
|
|
220
|
+
sources: {
|
|
221
|
+
schema: { sourceId: 'schema.prisma' },
|
|
222
|
+
},
|
|
223
|
+
});
|
|
191
224
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
225
|
+
const options: EmitStackInput = {
|
|
226
|
+
codecTypeImports: [],
|
|
227
|
+
operationTypeImports: [],
|
|
228
|
+
extensionIds: [],
|
|
229
|
+
};
|
|
197
230
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
231
|
+
const result = await emit(ir, options, mockSqlHook);
|
|
232
|
+
const contractJson = JSON.parse(result.contractJson) as Record<string, unknown>;
|
|
233
|
+
expect(contractJson).not.toHaveProperty('sources');
|
|
234
|
+
},
|
|
235
|
+
timeouts.typeScriptCompilation,
|
|
236
|
+
);
|
|
202
237
|
|
|
203
238
|
it('accepts meta keys when family validation allows them', async () => {
|
|
204
239
|
const ir = createTestContract({
|