@prisma-next/core-control-plane 0.1.0-pr.57.9 → 0.1.0-pr.58.2
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 -26
- package/dist/exports/emission.js +13 -0
- package/dist/exports/emission.js.map +1 -1
- package/dist/exports/types.d.ts +8 -35
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -14,10 +14,9 @@ This package provides the core domain logic for control plane operations (contra
|
|
|
14
14
|
- **Domain Actions**:
|
|
15
15
|
- `verifyDatabase()`: Verifies database contract markers (accepts config object and ContractIR)
|
|
16
16
|
|
|
17
|
-
Note: Contract emission is implemented on
|
|
17
|
+
Note: Contract emission is implemented on family instances (e.g., `familyInstance.emitContract()`), not as a core domain action.
|
|
18
18
|
- **Error Factories**: Domain error factories (`CliStructuredError`, config errors, runtime errors)
|
|
19
19
|
- **Pack Manifest Types**: Type definitions for extension pack manifests
|
|
20
|
-
- **Migration SPI**: Generic migration planner/runner interfaces (`MigrationPlanner<TFamilyId, TTargetId>`, `MigrationRunner<TFamilyId, TTargetId>`, `TargetMigrationsCapability<TFamilyId, TTargetId, TFamilyInstance>`) that thread family/target IDs for compile-time component compatibility enforcement
|
|
21
20
|
|
|
22
21
|
## Dependencies
|
|
23
22
|
|
|
@@ -103,30 +102,6 @@ throw errorConfigFileNotFound('prisma-next.config.ts', {
|
|
|
103
102
|
});
|
|
104
103
|
```
|
|
105
104
|
|
|
106
|
-
## Migration SPI Design
|
|
107
|
-
|
|
108
|
-
The migration planner/runner interfaces are generic over `TFamilyId` and `TTargetId` to enable compile-time enforcement of component compatibility:
|
|
109
|
-
|
|
110
|
-
- **`MigrationPlanner<TFamilyId, TTargetId>`**: Generic planner interface that accepts `TargetBoundComponentDescriptor<TFamilyId, TTargetId>[]`
|
|
111
|
-
- **`MigrationRunner<TFamilyId, TTargetId>`**: Generic runner interface that accepts `TargetBoundComponentDescriptor<TFamilyId, TTargetId>[]`
|
|
112
|
-
- **`TargetMigrationsCapability<TFamilyId, TTargetId, TFamilyInstance>`**: Generic capability interface for targets that support migrations
|
|
113
|
-
|
|
114
|
-
The CLI performs runtime validation at the composition boundary using `assertFrameworkComponentsCompatible()` before calling typed planner/runner instances. This validates that all components have matching `familyId` and `targetId`, then returns a typed `TargetBoundComponentDescriptor` array that satisfies the planner/runner interface requirements.
|
|
115
|
-
|
|
116
|
-
```typescript
|
|
117
|
-
// CLI composition boundary - runtime assertion + type narrowing
|
|
118
|
-
const rawComponents = [config.target, config.adapter, ...(config.extensions ?? [])];
|
|
119
|
-
const frameworkComponents = assertFrameworkComponentsCompatible(
|
|
120
|
-
config.family.familyId,
|
|
121
|
-
config.target.targetId,
|
|
122
|
-
rawComponents,
|
|
123
|
-
);
|
|
124
|
-
|
|
125
|
-
// Now frameworkComponents is typed as TargetBoundComponentDescriptor<TFamilyId, TTargetId>[]
|
|
126
|
-
const planner = target.migrations.createPlanner(sqlFamilyInstance);
|
|
127
|
-
planner.plan({ contract, schema, policy, frameworkComponents });
|
|
128
|
-
```
|
|
129
|
-
|
|
130
105
|
## Package Location
|
|
131
106
|
|
|
132
107
|
This package is part of the **framework domain**, **core layer**, **migration plane**:
|
package/dist/exports/emission.js
CHANGED
|
@@ -232,6 +232,16 @@ function validateCoreStructure(ir) {
|
|
|
232
232
|
throw new Error("ContractIR must have sources");
|
|
233
233
|
}
|
|
234
234
|
}
|
|
235
|
+
function validateExtensions(ir, extensionIds) {
|
|
236
|
+
const extensions = ir.extensions;
|
|
237
|
+
for (const extensionId of extensionIds) {
|
|
238
|
+
if (!extensions[extensionId]) {
|
|
239
|
+
throw new Error(
|
|
240
|
+
`Extension "${extensionId}" must appear in contract.extensions.${extensionId}`
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
235
245
|
async function emit(ir, options, targetFamily) {
|
|
236
246
|
const { operationRegistry, codecTypeImports, operationTypeImports, extensionIds } = options;
|
|
237
247
|
validateCoreStructure(ir);
|
|
@@ -243,6 +253,9 @@ async function emit(ir, options, targetFamily) {
|
|
|
243
253
|
};
|
|
244
254
|
targetFamily.validateTypes(ir, ctx);
|
|
245
255
|
targetFamily.validateStructure(ir);
|
|
256
|
+
if (extensionIds) {
|
|
257
|
+
validateExtensions(ir, extensionIds);
|
|
258
|
+
}
|
|
246
259
|
const contractJson = {
|
|
247
260
|
schemaVersion: ir.schemaVersion,
|
|
248
261
|
targetFamily: ir.targetFamily,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/emission/canonicalization.ts","../../src/emission/emit.ts","../../src/emission/hashing.ts"],"sourcesContent":["import type { ContractIR } from '@prisma-next/contract/ir';\n\ntype NormalizedContract = {\n schemaVersion: string;\n targetFamily: string;\n target: string;\n coreHash?: string;\n profileHash?: string;\n models: Record<string, unknown>;\n relations: Record<string, unknown>;\n storage: Record<string, unknown>;\n extensions: Record<string, unknown>;\n capabilities: Record<string, Record<string, boolean>>;\n meta: Record<string, unknown>;\n sources: Record<string, unknown>;\n};\n\nconst TOP_LEVEL_ORDER = [\n 'schemaVersion',\n 'canonicalVersion',\n 'targetFamily',\n 'target',\n 'coreHash',\n 'profileHash',\n 'models',\n 'storage',\n 'capabilities',\n 'extensions',\n 'meta',\n 'sources',\n] as const;\n\nfunction isDefaultValue(value: unknown): boolean {\n if (value === false) return true;\n if (value === null) return false;\n if (Array.isArray(value) && value.length === 0) return true;\n if (typeof value === 'object' && value !== null) {\n const keys = Object.keys(value);\n return keys.length === 0;\n }\n return false;\n}\n\nfunction omitDefaults(obj: unknown, path: readonly string[]): unknown {\n if (obj === null || typeof obj !== 'object') {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => omitDefaults(item, path));\n }\n\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(obj)) {\n const currentPath = [...path, key];\n\n // Exclude metadata fields from canonicalization\n if (key === '_generated') {\n continue;\n }\n\n if (key === 'nullable' && value === false) {\n continue;\n }\n\n if (key === 'generated' && value === false) {\n continue;\n }\n\n if (isDefaultValue(value)) {\n const isRequiredModels = currentPath.length === 1 && currentPath[0] === 'models';\n const isRequiredTables =\n currentPath.length === 2 && currentPath[0] === 'storage' && currentPath[1] === 'tables';\n const isRequiredRelations = currentPath.length === 1 && currentPath[0] === 'relations';\n const isRequiredExtensions = currentPath.length === 1 && currentPath[0] === 'extensions';\n const isRequiredCapabilities = currentPath.length === 1 && currentPath[0] === 'capabilities';\n const isRequiredMeta = currentPath.length === 1 && currentPath[0] === 'meta';\n const isRequiredSources = currentPath.length === 1 && currentPath[0] === 'sources';\n const isExtensionNamespace = currentPath.length === 2 && currentPath[0] === 'extensions';\n const isModelRelations =\n currentPath.length === 3 && currentPath[0] === 'models' && currentPath[2] === 'relations';\n const isTableUniques =\n currentPath.length === 4 &&\n currentPath[0] === 'storage' &&\n currentPath[1] === 'tables' &&\n currentPath[3] === 'uniques';\n const isTableIndexes =\n currentPath.length === 4 &&\n currentPath[0] === 'storage' &&\n currentPath[1] === 'tables' &&\n currentPath[3] === 'indexes';\n const isTableForeignKeys =\n currentPath.length === 4 &&\n currentPath[0] === 'storage' &&\n currentPath[1] === 'tables' &&\n currentPath[3] === 'foreignKeys';\n\n if (\n !isRequiredModels &&\n !isRequiredTables &&\n !isRequiredRelations &&\n !isRequiredExtensions &&\n !isRequiredCapabilities &&\n !isRequiredMeta &&\n !isRequiredSources &&\n !isExtensionNamespace &&\n !isModelRelations &&\n !isTableUniques &&\n !isTableIndexes &&\n !isTableForeignKeys\n ) {\n continue;\n }\n }\n\n result[key] = omitDefaults(value, currentPath);\n }\n\n return result;\n}\n\nfunction sortObjectKeys(obj: unknown): unknown {\n if (obj === null || typeof obj !== 'object') {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => sortObjectKeys(item));\n }\n\n const sorted: Record<string, unknown> = {};\n const keys = Object.keys(obj).sort();\n for (const key of keys) {\n sorted[key] = sortObjectKeys((obj as Record<string, unknown>)[key]);\n }\n\n return sorted;\n}\n\ntype StorageObject = {\n tables?: Record<string, unknown>;\n [key: string]: unknown;\n};\n\ntype TableObject = {\n indexes?: unknown[];\n uniques?: unknown[];\n [key: string]: unknown;\n};\n\nfunction sortIndexesAndUniques(storage: unknown): unknown {\n if (!storage || typeof storage !== 'object') {\n return storage;\n }\n\n const storageObj = storage as StorageObject;\n if (!storageObj.tables || typeof storageObj.tables !== 'object') {\n return storage;\n }\n\n const tables = storageObj.tables;\n const result: StorageObject = { ...storageObj };\n\n result.tables = {};\n // Sort table names to ensure deterministic ordering\n const sortedTableNames = Object.keys(tables).sort();\n for (const tableName of sortedTableNames) {\n const table = tables[tableName];\n if (!table || typeof table !== 'object') {\n result.tables[tableName] = table;\n continue;\n }\n\n const tableObj = table as TableObject;\n const sortedTable: TableObject = { ...tableObj };\n\n if (Array.isArray(tableObj.indexes)) {\n sortedTable.indexes = [...tableObj.indexes].sort((a, b) => {\n const nameA = (a as { name?: string })?.name || '';\n const nameB = (b as { name?: string })?.name || '';\n return nameA.localeCompare(nameB);\n });\n }\n\n if (Array.isArray(tableObj.uniques)) {\n sortedTable.uniques = [...tableObj.uniques].sort((a, b) => {\n const nameA = (a as { name?: string })?.name || '';\n const nameB = (b as { name?: string })?.name || '';\n return nameA.localeCompare(nameB);\n });\n }\n\n result.tables[tableName] = sortedTable;\n }\n\n return result;\n}\n\nfunction orderTopLevel(obj: Record<string, unknown>): Record<string, unknown> {\n const ordered: Record<string, unknown> = {};\n const remaining = new Set(Object.keys(obj));\n\n for (const key of TOP_LEVEL_ORDER) {\n if (remaining.has(key)) {\n ordered[key] = obj[key];\n remaining.delete(key);\n }\n }\n\n for (const key of Array.from(remaining).sort()) {\n ordered[key] = obj[key];\n }\n\n return ordered;\n}\n\nexport function canonicalizeContract(\n ir: ContractIR & { coreHash?: string; profileHash?: string },\n): string {\n const normalized: NormalizedContract = {\n schemaVersion: ir.schemaVersion,\n targetFamily: ir.targetFamily,\n target: ir.target,\n models: ir.models,\n relations: ir.relations,\n storage: ir.storage,\n extensions: ir.extensions,\n capabilities: ir.capabilities,\n meta: ir.meta,\n sources: ir.sources,\n };\n\n if (ir.coreHash !== undefined) {\n normalized.coreHash = ir.coreHash;\n }\n\n if (ir.profileHash !== undefined) {\n normalized.profileHash = ir.profileHash;\n }\n\n const withDefaultsOmitted = omitDefaults(normalized, []) as NormalizedContract;\n const withSortedIndexes = sortIndexesAndUniques(withDefaultsOmitted.storage);\n const withSortedStorage = { ...withDefaultsOmitted, storage: withSortedIndexes };\n const withSortedKeys = sortObjectKeys(withSortedStorage) as Record<string, unknown>;\n const withOrderedTopLevel = orderTopLevel(withSortedKeys);\n\n return JSON.stringify(withOrderedTopLevel, null, 2);\n}\n","import type { ContractIR } from '@prisma-next/contract/ir';\nimport type { TargetFamilyHook, ValidationContext } from '@prisma-next/contract/types';\nimport { format } from 'prettier';\nimport { canonicalizeContract } from './canonicalization';\nimport { computeCoreHash, computeProfileHash } from './hashing';\nimport type { EmitOptions, EmitResult } from './types';\n\nfunction validateCoreStructure(ir: ContractIR): void {\n if (!ir.targetFamily) {\n throw new Error('ContractIR must have targetFamily');\n }\n if (!ir.target) {\n throw new Error('ContractIR must have target');\n }\n if (!ir.schemaVersion) {\n throw new Error('ContractIR must have schemaVersion');\n }\n if (!ir.models || typeof ir.models !== 'object') {\n throw new Error('ContractIR must have models');\n }\n if (!ir.storage || typeof ir.storage !== 'object') {\n throw new Error('ContractIR must have storage');\n }\n if (!ir.relations || typeof ir.relations !== 'object') {\n throw new Error('ContractIR must have relations');\n }\n if (!ir.extensions || typeof ir.extensions !== 'object') {\n throw new Error('ContractIR must have extensions');\n }\n if (!ir.capabilities || typeof ir.capabilities !== 'object') {\n throw new Error('ContractIR must have capabilities');\n }\n if (!ir.meta || typeof ir.meta !== 'object') {\n throw new Error('ContractIR must have meta');\n }\n if (!ir.sources || typeof ir.sources !== 'object') {\n throw new Error('ContractIR must have sources');\n }\n}\n\nexport async function emit(\n ir: ContractIR,\n options: EmitOptions,\n targetFamily: TargetFamilyHook,\n): Promise<EmitResult> {\n const { operationRegistry, codecTypeImports, operationTypeImports, extensionIds } = options;\n\n validateCoreStructure(ir);\n\n const ctx: ValidationContext = {\n ...(operationRegistry ? { operationRegistry } : {}),\n ...(codecTypeImports ? { codecTypeImports } : {}),\n ...(operationTypeImports ? { operationTypeImports } : {}),\n ...(extensionIds ? { extensionIds } : {}),\n };\n targetFamily.validateTypes(ir, ctx);\n\n targetFamily.validateStructure(ir);\n\n const contractJson = {\n schemaVersion: ir.schemaVersion,\n targetFamily: ir.targetFamily,\n target: ir.target,\n models: ir.models,\n relations: ir.relations,\n storage: ir.storage,\n extensions: ir.extensions,\n capabilities: ir.capabilities,\n meta: ir.meta,\n sources: ir.sources,\n } as const;\n\n const coreHash = computeCoreHash(contractJson);\n const profileHash = computeProfileHash(contractJson);\n\n const contractWithHashes: ContractIR & { coreHash?: string; profileHash?: string } = {\n ...ir,\n schemaVersion: contractJson.schemaVersion,\n coreHash,\n profileHash,\n };\n\n // Add _generated metadata to indicate this is a generated artifact\n // This ensures consistency between CLI emit and programmatic emit\n // Always add/update _generated with standard content for consistency\n const contractJsonObj = JSON.parse(canonicalizeContract(contractWithHashes)) as Record<\n string,\n unknown\n >;\n const contractJsonWithMeta = {\n ...contractJsonObj,\n _generated: {\n warning: '⚠️ GENERATED FILE - DO NOT EDIT',\n message: 'This file is automatically generated by \"prisma-next emit\".',\n regenerate: 'To regenerate, run: prisma-next emit',\n },\n };\n const contractJsonString = JSON.stringify(contractJsonWithMeta, null, 2);\n\n const contractDtsRaw = targetFamily.generateContractTypes(\n ir,\n codecTypeImports ?? [],\n operationTypeImports ?? [],\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 coreHash,\n profileHash,\n };\n}\n","import { createHash } from 'node:crypto';\nimport type { ContractIR } from '@prisma-next/contract/ir';\nimport { canonicalizeContract } from './canonicalization';\n\ntype ContractInput = {\n schemaVersion: string;\n targetFamily: string;\n target: string;\n models: Record<string, unknown>;\n relations: Record<string, unknown>;\n storage: Record<string, unknown>;\n extensions: Record<string, unknown>;\n sources: Record<string, unknown>;\n capabilities: Record<string, Record<string, boolean>>;\n meta: Record<string, unknown>;\n [key: string]: unknown;\n};\n\nfunction computeHash(content: string): string {\n const hash = createHash('sha256');\n hash.update(content);\n return `sha256:${hash.digest('hex')}`;\n}\n\nexport function computeCoreHash(contract: ContractInput): string {\n const coreContract: ContractIR = {\n schemaVersion: contract.schemaVersion,\n targetFamily: contract.targetFamily,\n target: contract.target,\n models: contract.models,\n relations: contract.relations,\n storage: contract.storage,\n extensions: contract.extensions,\n sources: contract.sources,\n capabilities: contract.capabilities,\n meta: contract.meta,\n };\n const canonical = canonicalizeContract(coreContract);\n return computeHash(canonical);\n}\n\nexport function computeProfileHash(contract: ContractInput): string {\n const profileContract: ContractIR = {\n schemaVersion: contract.schemaVersion,\n targetFamily: contract.targetFamily,\n target: contract.target,\n models: {},\n relations: {},\n storage: {},\n extensions: {},\n capabilities: contract.capabilities,\n meta: {},\n sources: {},\n };\n const canonical = canonicalizeContract(profileContract);\n return computeHash(canonical);\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/emission/canonicalization.ts","../../src/emission/emit.ts","../../src/emission/hashing.ts"],"sourcesContent":["import type { ContractIR } from '@prisma-next/contract/ir';\n\ntype NormalizedContract = {\n schemaVersion: string;\n targetFamily: string;\n target: string;\n coreHash?: string;\n profileHash?: string;\n models: Record<string, unknown>;\n relations: Record<string, unknown>;\n storage: Record<string, unknown>;\n extensions: Record<string, unknown>;\n capabilities: Record<string, Record<string, boolean>>;\n meta: Record<string, unknown>;\n sources: Record<string, unknown>;\n};\n\nconst TOP_LEVEL_ORDER = [\n 'schemaVersion',\n 'canonicalVersion',\n 'targetFamily',\n 'target',\n 'coreHash',\n 'profileHash',\n 'models',\n 'storage',\n 'capabilities',\n 'extensions',\n 'meta',\n 'sources',\n] as const;\n\nfunction isDefaultValue(value: unknown): boolean {\n if (value === false) return true;\n if (value === null) return false;\n if (Array.isArray(value) && value.length === 0) return true;\n if (typeof value === 'object' && value !== null) {\n const keys = Object.keys(value);\n return keys.length === 0;\n }\n return false;\n}\n\nfunction omitDefaults(obj: unknown, path: readonly string[]): unknown {\n if (obj === null || typeof obj !== 'object') {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => omitDefaults(item, path));\n }\n\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(obj)) {\n const currentPath = [...path, key];\n\n // Exclude metadata fields from canonicalization\n if (key === '_generated') {\n continue;\n }\n\n if (key === 'nullable' && value === false) {\n continue;\n }\n\n if (key === 'generated' && value === false) {\n continue;\n }\n\n if (isDefaultValue(value)) {\n const isRequiredModels = currentPath.length === 1 && currentPath[0] === 'models';\n const isRequiredTables =\n currentPath.length === 2 && currentPath[0] === 'storage' && currentPath[1] === 'tables';\n const isRequiredRelations = currentPath.length === 1 && currentPath[0] === 'relations';\n const isRequiredExtensions = currentPath.length === 1 && currentPath[0] === 'extensions';\n const isRequiredCapabilities = currentPath.length === 1 && currentPath[0] === 'capabilities';\n const isRequiredMeta = currentPath.length === 1 && currentPath[0] === 'meta';\n const isRequiredSources = currentPath.length === 1 && currentPath[0] === 'sources';\n const isExtensionNamespace = currentPath.length === 2 && currentPath[0] === 'extensions';\n const isModelRelations =\n currentPath.length === 3 && currentPath[0] === 'models' && currentPath[2] === 'relations';\n const isTableUniques =\n currentPath.length === 4 &&\n currentPath[0] === 'storage' &&\n currentPath[1] === 'tables' &&\n currentPath[3] === 'uniques';\n const isTableIndexes =\n currentPath.length === 4 &&\n currentPath[0] === 'storage' &&\n currentPath[1] === 'tables' &&\n currentPath[3] === 'indexes';\n const isTableForeignKeys =\n currentPath.length === 4 &&\n currentPath[0] === 'storage' &&\n currentPath[1] === 'tables' &&\n currentPath[3] === 'foreignKeys';\n\n if (\n !isRequiredModels &&\n !isRequiredTables &&\n !isRequiredRelations &&\n !isRequiredExtensions &&\n !isRequiredCapabilities &&\n !isRequiredMeta &&\n !isRequiredSources &&\n !isExtensionNamespace &&\n !isModelRelations &&\n !isTableUniques &&\n !isTableIndexes &&\n !isTableForeignKeys\n ) {\n continue;\n }\n }\n\n result[key] = omitDefaults(value, currentPath);\n }\n\n return result;\n}\n\nfunction sortObjectKeys(obj: unknown): unknown {\n if (obj === null || typeof obj !== 'object') {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => sortObjectKeys(item));\n }\n\n const sorted: Record<string, unknown> = {};\n const keys = Object.keys(obj).sort();\n for (const key of keys) {\n sorted[key] = sortObjectKeys((obj as Record<string, unknown>)[key]);\n }\n\n return sorted;\n}\n\ntype StorageObject = {\n tables?: Record<string, unknown>;\n [key: string]: unknown;\n};\n\ntype TableObject = {\n indexes?: unknown[];\n uniques?: unknown[];\n [key: string]: unknown;\n};\n\nfunction sortIndexesAndUniques(storage: unknown): unknown {\n if (!storage || typeof storage !== 'object') {\n return storage;\n }\n\n const storageObj = storage as StorageObject;\n if (!storageObj.tables || typeof storageObj.tables !== 'object') {\n return storage;\n }\n\n const tables = storageObj.tables;\n const result: StorageObject = { ...storageObj };\n\n result.tables = {};\n // Sort table names to ensure deterministic ordering\n const sortedTableNames = Object.keys(tables).sort();\n for (const tableName of sortedTableNames) {\n const table = tables[tableName];\n if (!table || typeof table !== 'object') {\n result.tables[tableName] = table;\n continue;\n }\n\n const tableObj = table as TableObject;\n const sortedTable: TableObject = { ...tableObj };\n\n if (Array.isArray(tableObj.indexes)) {\n sortedTable.indexes = [...tableObj.indexes].sort((a, b) => {\n const nameA = (a as { name?: string })?.name || '';\n const nameB = (b as { name?: string })?.name || '';\n return nameA.localeCompare(nameB);\n });\n }\n\n if (Array.isArray(tableObj.uniques)) {\n sortedTable.uniques = [...tableObj.uniques].sort((a, b) => {\n const nameA = (a as { name?: string })?.name || '';\n const nameB = (b as { name?: string })?.name || '';\n return nameA.localeCompare(nameB);\n });\n }\n\n result.tables[tableName] = sortedTable;\n }\n\n return result;\n}\n\nfunction orderTopLevel(obj: Record<string, unknown>): Record<string, unknown> {\n const ordered: Record<string, unknown> = {};\n const remaining = new Set(Object.keys(obj));\n\n for (const key of TOP_LEVEL_ORDER) {\n if (remaining.has(key)) {\n ordered[key] = obj[key];\n remaining.delete(key);\n }\n }\n\n for (const key of Array.from(remaining).sort()) {\n ordered[key] = obj[key];\n }\n\n return ordered;\n}\n\nexport function canonicalizeContract(\n ir: ContractIR & { coreHash?: string; profileHash?: string },\n): string {\n const normalized: NormalizedContract = {\n schemaVersion: ir.schemaVersion,\n targetFamily: ir.targetFamily,\n target: ir.target,\n models: ir.models,\n relations: ir.relations,\n storage: ir.storage,\n extensions: ir.extensions,\n capabilities: ir.capabilities,\n meta: ir.meta,\n sources: ir.sources,\n };\n\n if (ir.coreHash !== undefined) {\n normalized.coreHash = ir.coreHash;\n }\n\n if (ir.profileHash !== undefined) {\n normalized.profileHash = ir.profileHash;\n }\n\n const withDefaultsOmitted = omitDefaults(normalized, []) as NormalizedContract;\n const withSortedIndexes = sortIndexesAndUniques(withDefaultsOmitted.storage);\n const withSortedStorage = { ...withDefaultsOmitted, storage: withSortedIndexes };\n const withSortedKeys = sortObjectKeys(withSortedStorage) as Record<string, unknown>;\n const withOrderedTopLevel = orderTopLevel(withSortedKeys);\n\n return JSON.stringify(withOrderedTopLevel, null, 2);\n}\n","import type { ContractIR } from '@prisma-next/contract/ir';\nimport type { TargetFamilyHook, ValidationContext } from '@prisma-next/contract/types';\nimport { format } from 'prettier';\nimport { canonicalizeContract } from './canonicalization';\nimport { computeCoreHash, computeProfileHash } from './hashing';\nimport type { EmitOptions, EmitResult } from './types';\n\nfunction validateCoreStructure(ir: ContractIR): void {\n if (!ir.targetFamily) {\n throw new Error('ContractIR must have targetFamily');\n }\n if (!ir.target) {\n throw new Error('ContractIR must have target');\n }\n if (!ir.schemaVersion) {\n throw new Error('ContractIR must have schemaVersion');\n }\n if (!ir.models || typeof ir.models !== 'object') {\n throw new Error('ContractIR must have models');\n }\n if (!ir.storage || typeof ir.storage !== 'object') {\n throw new Error('ContractIR must have storage');\n }\n if (!ir.relations || typeof ir.relations !== 'object') {\n throw new Error('ContractIR must have relations');\n }\n if (!ir.extensions || typeof ir.extensions !== 'object') {\n throw new Error('ContractIR must have extensions');\n }\n if (!ir.capabilities || typeof ir.capabilities !== 'object') {\n throw new Error('ContractIR must have capabilities');\n }\n if (!ir.meta || typeof ir.meta !== 'object') {\n throw new Error('ContractIR must have meta');\n }\n if (!ir.sources || typeof ir.sources !== 'object') {\n throw new Error('ContractIR must have sources');\n }\n}\n\nfunction validateExtensions(ir: ContractIR, extensionIds: ReadonlyArray<string>): void {\n const extensions = ir.extensions as Record<string, unknown>;\n for (const extensionId of extensionIds) {\n if (!extensions[extensionId]) {\n throw new Error(\n `Extension \"${extensionId}\" must appear in contract.extensions.${extensionId}`,\n );\n }\n }\n}\n\nexport async function emit(\n ir: ContractIR,\n options: EmitOptions,\n targetFamily: TargetFamilyHook,\n): Promise<EmitResult> {\n const { operationRegistry, codecTypeImports, operationTypeImports, extensionIds } = options;\n\n validateCoreStructure(ir);\n\n const ctx: ValidationContext = {\n ...(operationRegistry ? { operationRegistry } : {}),\n ...(codecTypeImports ? { codecTypeImports } : {}),\n ...(operationTypeImports ? { operationTypeImports } : {}),\n ...(extensionIds ? { extensionIds } : {}),\n };\n targetFamily.validateTypes(ir, ctx);\n\n targetFamily.validateStructure(ir);\n\n if (extensionIds) {\n validateExtensions(ir, extensionIds);\n }\n\n const contractJson = {\n schemaVersion: ir.schemaVersion,\n targetFamily: ir.targetFamily,\n target: ir.target,\n models: ir.models,\n relations: ir.relations,\n storage: ir.storage,\n extensions: ir.extensions,\n capabilities: ir.capabilities,\n meta: ir.meta,\n sources: ir.sources,\n } as const;\n\n const coreHash = computeCoreHash(contractJson);\n const profileHash = computeProfileHash(contractJson);\n\n const contractWithHashes: ContractIR & { coreHash?: string; profileHash?: string } = {\n ...ir,\n schemaVersion: contractJson.schemaVersion,\n coreHash,\n profileHash,\n };\n\n // Add _generated metadata to indicate this is a generated artifact\n // This ensures consistency between CLI emit and programmatic emit\n // Always add/update _generated with standard content for consistency\n const contractJsonObj = JSON.parse(canonicalizeContract(contractWithHashes)) as Record<\n string,\n unknown\n >;\n const contractJsonWithMeta = {\n ...contractJsonObj,\n _generated: {\n warning: '⚠️ GENERATED FILE - DO NOT EDIT',\n message: 'This file is automatically generated by \"prisma-next emit\".',\n regenerate: 'To regenerate, run: prisma-next emit',\n },\n };\n const contractJsonString = JSON.stringify(contractJsonWithMeta, null, 2);\n\n const contractDtsRaw = targetFamily.generateContractTypes(\n ir,\n codecTypeImports ?? [],\n operationTypeImports ?? [],\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 coreHash,\n profileHash,\n };\n}\n","import { createHash } from 'node:crypto';\nimport type { ContractIR } from '@prisma-next/contract/ir';\nimport { canonicalizeContract } from './canonicalization';\n\ntype ContractInput = {\n schemaVersion: string;\n targetFamily: string;\n target: string;\n models: Record<string, unknown>;\n relations: Record<string, unknown>;\n storage: Record<string, unknown>;\n extensions: Record<string, unknown>;\n sources: Record<string, unknown>;\n capabilities: Record<string, Record<string, boolean>>;\n meta: Record<string, unknown>;\n [key: string]: unknown;\n};\n\nfunction computeHash(content: string): string {\n const hash = createHash('sha256');\n hash.update(content);\n return `sha256:${hash.digest('hex')}`;\n}\n\nexport function computeCoreHash(contract: ContractInput): string {\n const coreContract: ContractIR = {\n schemaVersion: contract.schemaVersion,\n targetFamily: contract.targetFamily,\n target: contract.target,\n models: contract.models,\n relations: contract.relations,\n storage: contract.storage,\n extensions: contract.extensions,\n sources: contract.sources,\n capabilities: contract.capabilities,\n meta: contract.meta,\n };\n const canonical = canonicalizeContract(coreContract);\n return computeHash(canonical);\n}\n\nexport function computeProfileHash(contract: ContractInput): string {\n const profileContract: ContractIR = {\n schemaVersion: contract.schemaVersion,\n targetFamily: contract.targetFamily,\n target: contract.target,\n models: {},\n relations: {},\n storage: {},\n extensions: {},\n capabilities: contract.capabilities,\n meta: {},\n sources: {},\n };\n const canonical = canonicalizeContract(profileContract);\n return computeHash(canonical);\n}\n"],"mappings":"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","names":[]}
|
package/dist/exports/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { FamilyInstance, DriverInstance, FamilyDescriptor, TargetInstance, TargetDescriptor, AdapterInstance, AdapterDescriptor, DriverDescriptor, ExtensionInstance, ExtensionDescriptor } from '@prisma-next/contract/framework-components';
|
|
2
2
|
import { ContractIR } from '@prisma-next/contract/ir';
|
|
3
3
|
import { TargetFamilyHook } from '@prisma-next/contract/types';
|
|
4
4
|
import { Result } from '@prisma-next/utils/result';
|
|
@@ -109,59 +109,39 @@ type MigrationRunnerResult = Result<MigrationRunnerSuccessValue, MigrationRunner
|
|
|
109
109
|
/**
|
|
110
110
|
* Migration planner interface for planning schema changes.
|
|
111
111
|
* This is the minimal interface that CLI commands use.
|
|
112
|
-
*
|
|
113
|
-
* @template TFamilyId - The family ID (e.g., 'sql', 'document')
|
|
114
|
-
* @template TTargetId - The target ID (e.g., 'postgres', 'mysql')
|
|
115
112
|
*/
|
|
116
|
-
interface MigrationPlanner
|
|
113
|
+
interface MigrationPlanner {
|
|
117
114
|
plan(options: {
|
|
118
115
|
readonly contract: unknown;
|
|
119
116
|
readonly schema: unknown;
|
|
120
117
|
readonly policy: MigrationOperationPolicy;
|
|
121
|
-
/**
|
|
122
|
-
* Active framework components participating in this composition.
|
|
123
|
-
* Families/targets can interpret this list to derive family-specific metadata.
|
|
124
|
-
* All components must have matching familyId and targetId.
|
|
125
|
-
*/
|
|
126
|
-
readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<TFamilyId, TTargetId>>;
|
|
127
118
|
}): MigrationPlannerResult;
|
|
128
119
|
}
|
|
129
120
|
/**
|
|
130
121
|
* Migration runner interface for executing migration plans.
|
|
131
122
|
* This is the minimal interface that CLI commands use.
|
|
132
|
-
*
|
|
133
|
-
* @template TFamilyId - The family ID (e.g., 'sql', 'document')
|
|
134
|
-
* @template TTargetId - The target ID (e.g., 'postgres', 'mysql')
|
|
135
123
|
*/
|
|
136
|
-
interface MigrationRunner
|
|
124
|
+
interface MigrationRunner {
|
|
137
125
|
execute(options: {
|
|
138
126
|
readonly plan: MigrationPlan;
|
|
139
|
-
readonly driver: ControlDriverInstance<
|
|
127
|
+
readonly driver: ControlDriverInstance<string, string>;
|
|
140
128
|
readonly destinationContract: unknown;
|
|
141
129
|
readonly policy: MigrationOperationPolicy;
|
|
142
130
|
readonly callbacks?: {
|
|
143
131
|
onOperationStart?(op: MigrationPlanOperation): void;
|
|
144
132
|
onOperationComplete?(op: MigrationPlanOperation): void;
|
|
145
133
|
};
|
|
146
|
-
/**
|
|
147
|
-
* Active framework components participating in this composition.
|
|
148
|
-
* Families/targets can interpret this list to derive family-specific metadata.
|
|
149
|
-
* All components must have matching familyId and targetId.
|
|
150
|
-
*/
|
|
151
|
-
readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<TFamilyId, TTargetId>>;
|
|
152
134
|
}): Promise<MigrationRunnerResult>;
|
|
153
135
|
}
|
|
154
136
|
/**
|
|
155
137
|
* Optional capability interface for targets that support migrations.
|
|
156
138
|
* Targets that implement migrations expose this via their descriptor.
|
|
157
139
|
*
|
|
158
|
-
* @template TFamilyId - The family ID (e.g., 'sql', 'document')
|
|
159
|
-
* @template TTargetId - The target ID (e.g., 'postgres', 'mysql')
|
|
160
140
|
* @template TFamilyInstance - The family instance type (e.g., SqlControlFamilyInstance)
|
|
161
141
|
*/
|
|
162
|
-
interface TargetMigrationsCapability<
|
|
163
|
-
createPlanner(family: TFamilyInstance): MigrationPlanner
|
|
164
|
-
createRunner(family: TFamilyInstance): MigrationRunner
|
|
142
|
+
interface TargetMigrationsCapability<TFamilyInstance extends ControlFamilyInstance<string> = ControlFamilyInstance<string>> {
|
|
143
|
+
createPlanner(family: TFamilyInstance): MigrationPlanner;
|
|
144
|
+
createRunner(family: TFamilyInstance): MigrationRunner;
|
|
165
145
|
}
|
|
166
146
|
|
|
167
147
|
/**
|
|
@@ -206,11 +186,6 @@ interface ControlFamilyInstance<TFamilyId extends string, TSchemaIR = unknown> e
|
|
|
206
186
|
readonly strict: boolean;
|
|
207
187
|
readonly contractPath: string;
|
|
208
188
|
readonly configPath?: string;
|
|
209
|
-
/**
|
|
210
|
-
* Active framework components participating in this composition.
|
|
211
|
-
* All components must have matching familyId and targetId.
|
|
212
|
-
*/
|
|
213
|
-
readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<TFamilyId, string>>;
|
|
214
189
|
}): Promise<VerifyDatabaseSchemaResult>;
|
|
215
190
|
/**
|
|
216
191
|
* Signs the database with the contract marker.
|
|
@@ -362,10 +337,8 @@ interface ControlTargetDescriptor<TFamilyId extends string, TTargetId extends st
|
|
|
362
337
|
/**
|
|
363
338
|
* Optional migrations capability.
|
|
364
339
|
* Targets that support migrations expose this property.
|
|
365
|
-
* The capability is parameterized by family and target IDs to ensure type-level
|
|
366
|
-
* compatibility of framework components.
|
|
367
340
|
*/
|
|
368
|
-
readonly migrations?: TargetMigrationsCapability<
|
|
341
|
+
readonly migrations?: TargetMigrationsCapability<TFamilyInstance>;
|
|
369
342
|
create(): TTargetInstance;
|
|
370
343
|
}
|
|
371
344
|
/**
|
package/package.json
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma-next/core-control-plane",
|
|
3
|
-
"version": "0.1.0-pr.
|
|
3
|
+
"version": "0.1.0-pr.58.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"description": "Control plane domain actions, config types, validation, and error factories for Prisma Next",
|
|
7
7
|
"dependencies": {
|
|
8
8
|
"arktype": "^2.1.26",
|
|
9
9
|
"prettier": "^3.3.3",
|
|
10
|
-
"@prisma-next/contract": "0.1.0-pr.
|
|
11
|
-
"@prisma-next/operations": "0.1.0-pr.
|
|
12
|
-
"@prisma-next/utils": "0.1.0-pr.
|
|
10
|
+
"@prisma-next/contract": "0.1.0-pr.58.2",
|
|
11
|
+
"@prisma-next/operations": "0.1.0-pr.58.2",
|
|
12
|
+
"@prisma-next/utils": "0.1.0-pr.58.2"
|
|
13
13
|
},
|
|
14
14
|
"devDependencies": {
|
|
15
15
|
"tsup": "^8.3.0",
|
|
16
16
|
"typescript": "^5.9.3",
|
|
17
|
-
"vitest": "^
|
|
17
|
+
"vitest": "^4.0.16",
|
|
18
18
|
"@prisma-next/test-utils": "0.0.1"
|
|
19
19
|
},
|
|
20
20
|
"files": [
|