@prisma-next/family-sql 0.3.0-dev.5 → 0.3.0-dev.52
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 +12 -6
- package/dist/assembly-BVS641kd.mjs +106 -0
- package/dist/assembly-BVS641kd.mjs.map +1 -0
- package/dist/control-adapter.d.mts +60 -0
- package/dist/control-adapter.d.mts.map +1 -0
- package/dist/control-adapter.mjs +1 -0
- package/dist/control-instance-CWKSpACr.d.mts +292 -0
- package/dist/control-instance-CWKSpACr.d.mts.map +1 -0
- package/dist/control.d.mts +64 -0
- package/dist/control.d.mts.map +1 -0
- package/dist/control.mjs +536 -0
- package/dist/control.mjs.map +1 -0
- package/dist/runtime.d.mts +27 -0
- package/dist/runtime.d.mts.map +1 -0
- package/dist/runtime.mjs +38 -0
- package/dist/runtime.mjs.map +1 -0
- package/dist/schema-verify.d.mts +48 -0
- package/dist/schema-verify.d.mts.map +1 -0
- package/dist/schema-verify.mjs +4 -0
- package/dist/test-utils.d.mts +2 -0
- package/dist/test-utils.mjs +3 -0
- package/dist/verify-BfMETJcM.mjs +108 -0
- package/dist/verify-BfMETJcM.mjs.map +1 -0
- package/dist/verify-sql-schema-CpAVEi8A.mjs +1058 -0
- package/dist/verify-sql-schema-CpAVEi8A.mjs.map +1 -0
- package/dist/verify-sql-schema-DhHnkpPa.d.mts +67 -0
- package/dist/verify-sql-schema-DhHnkpPa.d.mts.map +1 -0
- package/dist/verify.d.mts +31 -0
- package/dist/verify.d.mts.map +1 -0
- package/dist/verify.mjs +3 -0
- package/package.json +36 -47
- package/src/core/assembly.ts +158 -59
- package/src/core/control-adapter.ts +15 -0
- package/src/core/control-descriptor.ts +37 -0
- package/src/core/{instance.ts → control-instance.ts} +108 -241
- package/src/core/migrations/types.ts +62 -163
- package/src/core/runtime-descriptor.ts +19 -41
- package/src/core/runtime-instance.ts +11 -133
- package/src/core/schema-verify/verify-helpers.ts +187 -97
- package/src/core/schema-verify/verify-sql-schema.ts +910 -392
- package/src/core/verify.ts +4 -13
- package/src/exports/control.ts +9 -6
- package/src/exports/runtime.ts +2 -6
- package/src/exports/schema-verify.ts +10 -2
- package/src/exports/test-utils.ts +0 -1
- package/dist/chunk-6K3RPBDP.js +0 -580
- package/dist/chunk-6K3RPBDP.js.map +0 -1
- package/dist/chunk-BHEGVBY7.js +0 -772
- package/dist/chunk-BHEGVBY7.js.map +0 -1
- package/dist/chunk-SU7LN2UH.js +0 -96
- package/dist/chunk-SU7LN2UH.js.map +0 -1
- package/dist/core/assembly.d.ts +0 -25
- package/dist/core/assembly.d.ts.map +0 -1
- package/dist/core/control-adapter.d.ts +0 -42
- package/dist/core/control-adapter.d.ts.map +0 -1
- package/dist/core/descriptor.d.ts +0 -31
- package/dist/core/descriptor.d.ts.map +0 -1
- package/dist/core/instance.d.ts +0 -142
- package/dist/core/instance.d.ts.map +0 -1
- package/dist/core/migrations/plan-helpers.d.ts +0 -20
- package/dist/core/migrations/plan-helpers.d.ts.map +0 -1
- package/dist/core/migrations/policies.d.ts +0 -6
- package/dist/core/migrations/policies.d.ts.map +0 -1
- package/dist/core/migrations/types.d.ts +0 -280
- package/dist/core/migrations/types.d.ts.map +0 -1
- package/dist/core/runtime-descriptor.d.ts +0 -19
- package/dist/core/runtime-descriptor.d.ts.map +0 -1
- package/dist/core/runtime-instance.d.ts +0 -54
- package/dist/core/runtime-instance.d.ts.map +0 -1
- package/dist/core/schema-verify/verify-helpers.d.ts +0 -50
- package/dist/core/schema-verify/verify-helpers.d.ts.map +0 -1
- package/dist/core/schema-verify/verify-sql-schema.d.ts +0 -45
- package/dist/core/schema-verify/verify-sql-schema.d.ts.map +0 -1
- package/dist/core/verify.d.ts +0 -39
- package/dist/core/verify.d.ts.map +0 -1
- package/dist/exports/control-adapter.d.ts +0 -2
- package/dist/exports/control-adapter.d.ts.map +0 -1
- package/dist/exports/control-adapter.js +0 -1
- package/dist/exports/control-adapter.js.map +0 -1
- package/dist/exports/control.d.ts +0 -13
- package/dist/exports/control.d.ts.map +0 -1
- package/dist/exports/control.js +0 -149
- package/dist/exports/control.js.map +0 -1
- package/dist/exports/runtime.d.ts +0 -8
- package/dist/exports/runtime.d.ts.map +0 -1
- package/dist/exports/runtime.js +0 -64
- package/dist/exports/runtime.js.map +0 -1
- package/dist/exports/schema-verify.d.ts +0 -11
- package/dist/exports/schema-verify.d.ts.map +0 -1
- package/dist/exports/schema-verify.js +0 -11
- package/dist/exports/schema-verify.js.map +0 -1
- package/dist/exports/test-utils.d.ts +0 -7
- package/dist/exports/test-utils.d.ts.map +0 -1
- package/dist/exports/test-utils.js +0 -17
- package/dist/exports/test-utils.js.map +0 -1
- package/dist/exports/verify.d.ts +0 -2
- package/dist/exports/verify.d.ts.map +0 -1
- package/dist/exports/verify.js +0 -11
- package/dist/exports/verify.js.map +0 -1
- package/src/core/descriptor.ts +0 -37
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
TargetBoundComponentDescriptor,
|
|
3
|
+
TargetDescriptor,
|
|
4
|
+
} from '@prisma-next/contract/framework-components';
|
|
2
5
|
import type { ContractIR } from '@prisma-next/contract/ir';
|
|
3
|
-
import type { OperationManifest } from '@prisma-next/contract/pack-manifest-types';
|
|
4
6
|
import type { ContractMarkerRecord, TypesImportSpec } from '@prisma-next/contract/types';
|
|
5
7
|
import { emit } from '@prisma-next/core-control-plane/emission';
|
|
6
8
|
import type { CoreSchemaView, SchemaTreeNode } from '@prisma-next/core-control-plane/schema-view';
|
|
7
9
|
import type {
|
|
8
|
-
ControlAdapterDescriptor,
|
|
9
10
|
ControlDriverInstance,
|
|
10
|
-
ControlExtensionDescriptor,
|
|
11
11
|
ControlFamilyInstance,
|
|
12
|
-
ControlTargetDescriptor,
|
|
13
12
|
EmitContractResult,
|
|
14
13
|
OperationContext,
|
|
15
14
|
SignDatabaseResult,
|
|
@@ -18,9 +17,8 @@ import type {
|
|
|
18
17
|
} from '@prisma-next/core-control-plane/types';
|
|
19
18
|
import type { OperationRegistry } from '@prisma-next/operations';
|
|
20
19
|
import type { SqlContract, SqlStorage } from '@prisma-next/sql-contract/types';
|
|
20
|
+
import { validateContract } from '@prisma-next/sql-contract/validate';
|
|
21
21
|
import { sqlTargetFamilyHook } from '@prisma-next/sql-contract-emitter';
|
|
22
|
-
import { validateContract } from '@prisma-next/sql-contract-ts/contract';
|
|
23
|
-
import type { SqlOperationSignature } from '@prisma-next/sql-operations';
|
|
24
22
|
import {
|
|
25
23
|
ensureSchemaStatement,
|
|
26
24
|
ensureTableStatement,
|
|
@@ -33,60 +31,18 @@ import {
|
|
|
33
31
|
extractCodecTypeImports,
|
|
34
32
|
extractExtensionIds,
|
|
35
33
|
extractOperationTypeImports,
|
|
34
|
+
extractParameterizedRenderers,
|
|
35
|
+
extractParameterizedTypeImports,
|
|
36
|
+
type SqlControlDescriptorWithContributions,
|
|
36
37
|
} from './assembly';
|
|
37
38
|
import type { SqlControlAdapter } from './control-adapter';
|
|
38
|
-
import type {
|
|
39
|
+
import type {
|
|
40
|
+
SqlControlAdapterDescriptor,
|
|
41
|
+
SqlControlExtensionDescriptor,
|
|
42
|
+
} from './migrations/types';
|
|
39
43
|
import { verifySqlSchema } from './schema-verify/verify-sql-schema';
|
|
40
44
|
import { collectSupportedCodecTypeIds, readMarker } from './verify';
|
|
41
45
|
|
|
42
|
-
/**
|
|
43
|
-
* Converts an OperationManifest (descriptor declarative data) to a SqlOperationSignature.
|
|
44
|
-
* This is SQL-family-specific conversion logic used by instance creation and test utilities.
|
|
45
|
-
*/
|
|
46
|
-
export function convertOperationManifest(manifest: OperationManifest): SqlOperationSignature {
|
|
47
|
-
return {
|
|
48
|
-
forTypeId: manifest.for,
|
|
49
|
-
method: manifest.method,
|
|
50
|
-
args: manifest.args.map((arg: OperationManifest['args'][number]) => {
|
|
51
|
-
if (arg.kind === 'typeId') {
|
|
52
|
-
if (!arg.type) {
|
|
53
|
-
throw new Error('typeId arg must have type property');
|
|
54
|
-
}
|
|
55
|
-
return { kind: 'typeId' as const, type: arg.type };
|
|
56
|
-
}
|
|
57
|
-
if (arg.kind === 'param') {
|
|
58
|
-
return { kind: 'param' as const };
|
|
59
|
-
}
|
|
60
|
-
if (arg.kind === 'literal') {
|
|
61
|
-
return { kind: 'literal' as const };
|
|
62
|
-
}
|
|
63
|
-
throw new Error(`Invalid arg kind: ${(arg as { kind: unknown }).kind}`);
|
|
64
|
-
}),
|
|
65
|
-
returns: (() => {
|
|
66
|
-
if (manifest.returns.kind === 'typeId') {
|
|
67
|
-
return { kind: 'typeId' as const, type: manifest.returns.type };
|
|
68
|
-
}
|
|
69
|
-
if (manifest.returns.kind === 'builtin') {
|
|
70
|
-
return {
|
|
71
|
-
kind: 'builtin' as const,
|
|
72
|
-
type: manifest.returns.type as 'number' | 'boolean' | 'string',
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
throw new Error(`Invalid return kind: ${(manifest.returns as { kind: unknown }).kind}`);
|
|
76
|
-
})(),
|
|
77
|
-
lowering: {
|
|
78
|
-
targetFamily: 'sql',
|
|
79
|
-
strategy: manifest.lowering.strategy,
|
|
80
|
-
template: manifest.lowering.template,
|
|
81
|
-
},
|
|
82
|
-
...(manifest.capabilities ? { capabilities: manifest.capabilities } : {}),
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Extracts codec type IDs used in contract storage tables.
|
|
88
|
-
* Uses type guards to safely access SQL-specific structure without importing SQL types.
|
|
89
|
-
*/
|
|
90
46
|
function extractCodecTypeIdsFromContract(contract: unknown): readonly string[] {
|
|
91
47
|
const typeIds = new Set<string>();
|
|
92
48
|
|
|
@@ -128,14 +84,11 @@ function extractCodecTypeIdsFromContract(contract: unknown): readonly string[] {
|
|
|
128
84
|
return Array.from(typeIds).sort();
|
|
129
85
|
}
|
|
130
86
|
|
|
131
|
-
/**
|
|
132
|
-
* Creates a VerifyDatabaseResult object with common structure.
|
|
133
|
-
*/
|
|
134
87
|
function createVerifyResult(options: {
|
|
135
88
|
ok: boolean;
|
|
136
89
|
code?: string;
|
|
137
90
|
summary: string;
|
|
138
|
-
|
|
91
|
+
contractStorageHash: string;
|
|
139
92
|
contractProfileHash?: string;
|
|
140
93
|
marker?: ContractMarkerRecord;
|
|
141
94
|
expectedTargetId: string;
|
|
@@ -146,8 +99,8 @@ function createVerifyResult(options: {
|
|
|
146
99
|
contractPath: string;
|
|
147
100
|
totalTime: number;
|
|
148
101
|
}): VerifyDatabaseResult {
|
|
149
|
-
const contract: {
|
|
150
|
-
|
|
102
|
+
const contract: { storageHash: string; profileHash?: string } = {
|
|
103
|
+
storageHash: options.contractStorageHash,
|
|
151
104
|
};
|
|
152
105
|
if (options.contractProfileHash) {
|
|
153
106
|
contract.profileHash = options.contractProfileHash;
|
|
@@ -183,8 +136,8 @@ function createVerifyResult(options: {
|
|
|
183
136
|
}
|
|
184
137
|
|
|
185
138
|
if (options.marker) {
|
|
186
|
-
(result as { marker?: {
|
|
187
|
-
|
|
139
|
+
(result as { marker?: { storageHash: string; profileHash: string } }).marker = {
|
|
140
|
+
storageHash: options.marker.storageHash,
|
|
188
141
|
profileHash: options.marker.profileHash,
|
|
189
142
|
};
|
|
190
143
|
}
|
|
@@ -201,10 +154,6 @@ function createVerifyResult(options: {
|
|
|
201
154
|
return result;
|
|
202
155
|
}
|
|
203
156
|
|
|
204
|
-
/**
|
|
205
|
-
* Type metadata for SQL storage types.
|
|
206
|
-
* Maps contract storage type IDs to native database types.
|
|
207
|
-
*/
|
|
208
157
|
interface SqlTypeMetadata {
|
|
209
158
|
readonly typeId: string;
|
|
210
159
|
readonly familyId: 'sql';
|
|
@@ -212,15 +161,8 @@ interface SqlTypeMetadata {
|
|
|
212
161
|
readonly nativeType?: string;
|
|
213
162
|
}
|
|
214
163
|
|
|
215
|
-
/**
|
|
216
|
-
* Registry mapping type IDs to their metadata.
|
|
217
|
-
* Keyed by contract storage type ID (e.g., 'pg/int4@1').
|
|
218
|
-
*/
|
|
219
164
|
type SqlTypeMetadataRegistry = Map<string, SqlTypeMetadata>;
|
|
220
165
|
|
|
221
|
-
/**
|
|
222
|
-
* State fields for SQL family instance that hold assembly data.
|
|
223
|
-
*/
|
|
224
166
|
interface SqlFamilyInstanceState {
|
|
225
167
|
readonly operationRegistry: OperationRegistry;
|
|
226
168
|
readonly codecTypeImports: ReadonlyArray<TypesImportSpec>;
|
|
@@ -229,9 +171,6 @@ interface SqlFamilyInstanceState {
|
|
|
229
171
|
readonly typeMetadataRegistry: SqlTypeMetadataRegistry;
|
|
230
172
|
}
|
|
231
173
|
|
|
232
|
-
/**
|
|
233
|
-
* Options for schema verification.
|
|
234
|
-
*/
|
|
235
174
|
export interface SchemaVerifyOptions {
|
|
236
175
|
readonly driver: ControlDriverInstance<'sql', string>;
|
|
237
176
|
readonly contractIR: unknown;
|
|
@@ -244,23 +183,11 @@ export interface SchemaVerifyOptions {
|
|
|
244
183
|
readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<'sql', string>>;
|
|
245
184
|
}
|
|
246
185
|
|
|
247
|
-
/**
|
|
248
|
-
* SQL control family instance interface.
|
|
249
|
-
* Extends ControlFamilyInstance with SQL-specific domain actions.
|
|
250
|
-
*/
|
|
251
186
|
export interface SqlControlFamilyInstance
|
|
252
187
|
extends ControlFamilyInstance<'sql'>,
|
|
253
188
|
SqlFamilyInstanceState {
|
|
254
|
-
/**
|
|
255
|
-
* Validates a contract JSON and returns a validated ContractIR (without mappings).
|
|
256
|
-
* Mappings are runtime-only and should not be part of ContractIR.
|
|
257
|
-
*/
|
|
258
189
|
validateContractIR(contractJson: unknown): ContractIR;
|
|
259
190
|
|
|
260
|
-
/**
|
|
261
|
-
* Verifies the database marker against the contract.
|
|
262
|
-
* Compares target, coreHash, and profileHash.
|
|
263
|
-
*/
|
|
264
191
|
verify(options: {
|
|
265
192
|
readonly driver: ControlDriverInstance<'sql', string>;
|
|
266
193
|
readonly contractIR: unknown;
|
|
@@ -269,17 +196,8 @@ export interface SqlControlFamilyInstance
|
|
|
269
196
|
readonly configPath?: string;
|
|
270
197
|
}): Promise<VerifyDatabaseResult>;
|
|
271
198
|
|
|
272
|
-
/**
|
|
273
|
-
* Verifies the database schema against the contract.
|
|
274
|
-
* Compares contract requirements against live database schema.
|
|
275
|
-
*/
|
|
276
199
|
schemaVerify(options: SchemaVerifyOptions): Promise<VerifyDatabaseSchemaResult>;
|
|
277
200
|
|
|
278
|
-
/**
|
|
279
|
-
* Signs the database with the contract marker.
|
|
280
|
-
* Writes or updates the contract marker if schema verification passes.
|
|
281
|
-
* This operation is idempotent - if the marker already matches, no changes are made.
|
|
282
|
-
*/
|
|
283
201
|
sign(options: {
|
|
284
202
|
readonly driver: ControlDriverInstance<'sql', string>;
|
|
285
203
|
readonly contractIR: unknown;
|
|
@@ -287,75 +205,64 @@ export interface SqlControlFamilyInstance
|
|
|
287
205
|
readonly configPath?: string;
|
|
288
206
|
}): Promise<SignDatabaseResult>;
|
|
289
207
|
|
|
290
|
-
/**
|
|
291
|
-
* Introspects the database schema and returns a family-specific schema IR.
|
|
292
|
-
*
|
|
293
|
-
* This is a read-only operation that returns a snapshot of the live database schema.
|
|
294
|
-
* The method is family-owned and delegates to target/adapter-specific introspectors
|
|
295
|
-
* to perform the actual schema introspection.
|
|
296
|
-
*
|
|
297
|
-
* @param options - Introspection options
|
|
298
|
-
* @param options.driver - Control plane driver for database connection
|
|
299
|
-
* @param options.contractIR - Optional contract IR for contract-guided introspection.
|
|
300
|
-
* When provided, families may use it for filtering, optimization, or validation
|
|
301
|
-
* during introspection. The contract IR does not change the meaning of "what exists"
|
|
302
|
-
* in the database - it only guides how introspection is performed.
|
|
303
|
-
* @returns Promise resolving to the family-specific Schema IR (e.g., `SqlSchemaIR` for SQL).
|
|
304
|
-
* The IR represents the complete schema snapshot at the time of introspection.
|
|
305
|
-
*/
|
|
306
208
|
introspect(options: {
|
|
307
209
|
readonly driver: ControlDriverInstance<'sql', string>;
|
|
308
210
|
readonly contractIR?: unknown;
|
|
309
211
|
}): Promise<SqlSchemaIR>;
|
|
310
212
|
|
|
311
|
-
/**
|
|
312
|
-
* Projects a SQL Schema IR into a core schema view for CLI visualization.
|
|
313
|
-
* Converts SqlSchemaIR (tables, columns, indexes, extensions) into a tree structure.
|
|
314
|
-
*/
|
|
315
213
|
toSchemaView(schema: SqlSchemaIR): CoreSchemaView;
|
|
316
214
|
|
|
317
|
-
/**
|
|
318
|
-
* Emits contract JSON and DTS as strings.
|
|
319
|
-
* Uses the instance's preassembled state (operation registry, type imports, extension IDs).
|
|
320
|
-
* Handles stripping mappings and validation internally.
|
|
321
|
-
*/
|
|
322
215
|
emitContract(options: { readonly contractIR: ContractIR | unknown }): Promise<EmitContractResult>;
|
|
323
216
|
}
|
|
324
217
|
|
|
325
|
-
/**
|
|
326
|
-
* SQL family instance type.
|
|
327
|
-
* Maintains backward compatibility with FamilyInstance while implementing SqlControlFamilyInstance.
|
|
328
|
-
*/
|
|
329
218
|
export type SqlFamilyInstance = SqlControlFamilyInstance;
|
|
330
219
|
|
|
331
|
-
interface CreateSqlFamilyInstanceOptions<TTargetId extends string
|
|
332
|
-
readonly target:
|
|
333
|
-
|
|
334
|
-
|
|
220
|
+
interface CreateSqlFamilyInstanceOptions<TTargetId extends string> {
|
|
221
|
+
readonly target: TargetDescriptor<'sql', TTargetId> &
|
|
222
|
+
SqlControlDescriptorWithContributions &
|
|
223
|
+
DescriptorWithStorageTypes;
|
|
224
|
+
readonly adapter: SqlControlAdapterDescriptor<TTargetId> & DescriptorWithStorageTypes;
|
|
225
|
+
readonly extensionPacks: readonly (SqlControlExtensionDescriptor<TTargetId> &
|
|
226
|
+
DescriptorWithStorageTypes)[];
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function isSqlControlAdapter<TTargetId extends string>(
|
|
230
|
+
value: unknown,
|
|
231
|
+
): value is SqlControlAdapter<TTargetId> {
|
|
232
|
+
return (
|
|
233
|
+
typeof value === 'object' &&
|
|
234
|
+
value !== null &&
|
|
235
|
+
'introspect' in value &&
|
|
236
|
+
typeof (value as { introspect: unknown }).introspect === 'function'
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
interface DescriptorWithStorageTypes {
|
|
241
|
+
readonly targetId?: string | undefined;
|
|
242
|
+
readonly types?:
|
|
243
|
+
| {
|
|
244
|
+
readonly storage?:
|
|
245
|
+
| ReadonlyArray<{
|
|
246
|
+
readonly typeId: string;
|
|
247
|
+
readonly familyId: string;
|
|
248
|
+
readonly targetId: string;
|
|
249
|
+
readonly nativeType?: string | undefined;
|
|
250
|
+
}>
|
|
251
|
+
| undefined;
|
|
252
|
+
}
|
|
253
|
+
| undefined;
|
|
335
254
|
}
|
|
336
255
|
|
|
337
|
-
/**
|
|
338
|
-
* Builds a SQL type metadata registry from extension pack manifests.
|
|
339
|
-
* Collects type metadata from target, adapter, and extension pack manifests.
|
|
340
|
-
*
|
|
341
|
-
* @param options - Descriptors for target, adapter, and extensions
|
|
342
|
-
* @returns Registry mapping type IDs to their metadata, filtered by targetId
|
|
343
|
-
*/
|
|
344
256
|
function buildSqlTypeMetadataRegistry(options: {
|
|
345
|
-
readonly target:
|
|
346
|
-
readonly adapter:
|
|
347
|
-
readonly extensionPacks: readonly
|
|
257
|
+
readonly target: DescriptorWithStorageTypes;
|
|
258
|
+
readonly adapter: DescriptorWithStorageTypes & { readonly targetId: string };
|
|
259
|
+
readonly extensionPacks: readonly DescriptorWithStorageTypes[];
|
|
348
260
|
}): SqlTypeMetadataRegistry {
|
|
349
261
|
const { target, adapter, extensionPacks: extensions } = options;
|
|
350
262
|
const registry = new Map<string, SqlTypeMetadata>();
|
|
351
|
-
|
|
352
|
-
// Get targetId from adapter (they should match)
|
|
353
263
|
const targetId = adapter.targetId;
|
|
354
|
-
|
|
355
|
-
// Collect descriptors to iterate over
|
|
356
264
|
const descriptors = [target, adapter, ...extensions];
|
|
357
265
|
|
|
358
|
-
// Iterate over each descriptor's types
|
|
359
266
|
for (const descriptor of descriptors) {
|
|
360
267
|
const types = descriptor.types;
|
|
361
268
|
const storageTypes = types?.storage;
|
|
@@ -364,11 +271,8 @@ function buildSqlTypeMetadataRegistry(options: {
|
|
|
364
271
|
continue;
|
|
365
272
|
}
|
|
366
273
|
|
|
367
|
-
// Filter for SQL family and matching targetId
|
|
368
274
|
for (const storageType of storageTypes) {
|
|
369
275
|
if (storageType.familyId === 'sql' && storageType.targetId === targetId) {
|
|
370
|
-
// Use existing entry if present, otherwise create new one
|
|
371
|
-
// Later entries (extensions) can override earlier ones (adapter/target)
|
|
372
276
|
registry.set(storageType.typeId, {
|
|
373
277
|
typeId: storageType.typeId,
|
|
374
278
|
familyId: 'sql',
|
|
@@ -382,36 +286,27 @@ function buildSqlTypeMetadataRegistry(options: {
|
|
|
382
286
|
return registry;
|
|
383
287
|
}
|
|
384
288
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
*/
|
|
388
|
-
export function createSqlFamilyInstance<TTargetId extends string, TTargetDetails>(
|
|
389
|
-
options: CreateSqlFamilyInstanceOptions<TTargetId, TTargetDetails>,
|
|
289
|
+
export function createSqlFamilyInstance<TTargetId extends string>(
|
|
290
|
+
options: CreateSqlFamilyInstanceOptions<TTargetId>,
|
|
390
291
|
): SqlFamilyInstance {
|
|
391
292
|
const { target, adapter, extensionPacks: extensions = [] } = options;
|
|
392
293
|
|
|
393
|
-
|
|
394
|
-
// Assembly functions only use manifest and id, so we can pass Control*Descriptor types directly
|
|
395
|
-
const descriptors = [target, adapter, ...extensions];
|
|
294
|
+
const descriptors: SqlControlDescriptorWithContributions[] = [target, adapter, ...extensions];
|
|
396
295
|
|
|
397
|
-
|
|
398
|
-
const operationRegistry = assembleOperationRegistry(descriptors, convertOperationManifest);
|
|
296
|
+
const operationRegistry = assembleOperationRegistry(descriptors);
|
|
399
297
|
const codecTypeImports = extractCodecTypeImports(descriptors);
|
|
400
298
|
const operationTypeImports = extractOperationTypeImports(descriptors);
|
|
401
299
|
const extensionIds = extractExtensionIds(adapter, target, extensions);
|
|
300
|
+
const parameterizedRenderers = extractParameterizedRenderers(descriptors);
|
|
301
|
+
const parameterizedTypeImports = extractParameterizedTypeImports(descriptors);
|
|
402
302
|
|
|
403
|
-
// Build type metadata registry from manifests
|
|
404
303
|
const typeMetadataRegistry = buildSqlTypeMetadataRegistry({
|
|
405
304
|
target,
|
|
406
305
|
adapter,
|
|
407
306
|
extensionPacks: extensions,
|
|
408
307
|
});
|
|
409
308
|
|
|
410
|
-
/**
|
|
411
|
-
* Strips mappings from a contract (mappings are runtime-only).
|
|
412
|
-
*/
|
|
413
309
|
function stripMappings(contract: unknown): unknown {
|
|
414
|
-
// Type guard to check if contract has mappings
|
|
415
310
|
if (typeof contract === 'object' && contract !== null && 'mappings' in contract) {
|
|
416
311
|
const { mappings: _mappings, ...contractIR } = contract as {
|
|
417
312
|
mappings?: unknown;
|
|
@@ -422,6 +317,13 @@ export function createSqlFamilyInstance<TTargetId extends string, TTargetDetails
|
|
|
422
317
|
return contract;
|
|
423
318
|
}
|
|
424
319
|
|
|
320
|
+
function normalizeProviderContractIR(contract: unknown): ContractIR {
|
|
321
|
+
const contractWithoutMappings = stripMappings(contract);
|
|
322
|
+
const validated = validateContract<SqlContract<SqlStorage>>(contractWithoutMappings);
|
|
323
|
+
const { mappings: _mappings, ...contractIR } = validated;
|
|
324
|
+
return contractIR as ContractIR;
|
|
325
|
+
}
|
|
326
|
+
|
|
425
327
|
return {
|
|
426
328
|
familyId: 'sql',
|
|
427
329
|
operationRegistry,
|
|
@@ -431,12 +333,7 @@ export function createSqlFamilyInstance<TTargetId extends string, TTargetDetails
|
|
|
431
333
|
typeMetadataRegistry,
|
|
432
334
|
|
|
433
335
|
validateContractIR(contractJson: unknown): ContractIR {
|
|
434
|
-
|
|
435
|
-
const validated = validateContract<SqlContract<SqlStorage>>(contractJson);
|
|
436
|
-
// Strip mappings before returning ContractIR (mappings are runtime-only)
|
|
437
|
-
// The validated contract has all required ContractIR properties
|
|
438
|
-
const { mappings: _mappings, ...contractIR } = validated;
|
|
439
|
-
return contractIR as ContractIR;
|
|
336
|
+
return normalizeProviderContractIR(contractJson);
|
|
440
337
|
},
|
|
441
338
|
|
|
442
339
|
async verify(verifyOptions: {
|
|
@@ -449,40 +346,30 @@ export function createSqlFamilyInstance<TTargetId extends string, TTargetDetails
|
|
|
449
346
|
const { driver, contractIR, expectedTargetId, contractPath, configPath } = verifyOptions;
|
|
450
347
|
const startTime = Date.now();
|
|
451
348
|
|
|
452
|
-
// Type guard to ensure contract has required properties
|
|
453
349
|
if (
|
|
454
350
|
typeof contractIR !== 'object' ||
|
|
455
351
|
contractIR === null ||
|
|
456
|
-
!('
|
|
352
|
+
!('storageHash' in contractIR) ||
|
|
457
353
|
!('target' in contractIR) ||
|
|
458
|
-
typeof contractIR.
|
|
354
|
+
typeof contractIR.storageHash !== 'string' ||
|
|
459
355
|
typeof contractIR.target !== 'string'
|
|
460
356
|
) {
|
|
461
|
-
throw new Error('Contract is missing required fields:
|
|
357
|
+
throw new Error('Contract is missing required fields: storageHash or target');
|
|
462
358
|
}
|
|
463
359
|
|
|
464
|
-
|
|
465
|
-
const contractCoreHash = contractIR.coreHash;
|
|
360
|
+
const contractStorageHash = contractIR.storageHash;
|
|
466
361
|
const contractProfileHash =
|
|
467
362
|
'profileHash' in contractIR && typeof contractIR.profileHash === 'string'
|
|
468
363
|
? contractIR.profileHash
|
|
469
364
|
: undefined;
|
|
470
365
|
const contractTarget = contractIR.target;
|
|
471
366
|
|
|
472
|
-
// Read marker from database
|
|
473
367
|
const marker = await readMarker(driver);
|
|
474
368
|
|
|
475
|
-
// Compute codec coverage (optional)
|
|
476
369
|
let missingCodecs: readonly string[] | undefined;
|
|
477
370
|
let codecCoverageSkipped = false;
|
|
478
|
-
const supportedTypeIds = collectSupportedCodecTypeIds
|
|
479
|
-
adapter,
|
|
480
|
-
target,
|
|
481
|
-
...extensions,
|
|
482
|
-
]);
|
|
371
|
+
const supportedTypeIds = collectSupportedCodecTypeIds([adapter, target, ...extensions]);
|
|
483
372
|
if (supportedTypeIds.length === 0) {
|
|
484
|
-
// Helper is present but returns empty (MVP behavior)
|
|
485
|
-
// Coverage check is skipped - missingCodecs remains undefined
|
|
486
373
|
codecCoverageSkipped = true;
|
|
487
374
|
} else {
|
|
488
375
|
const supportedSet = new Set(supportedTypeIds);
|
|
@@ -493,14 +380,13 @@ export function createSqlFamilyInstance<TTargetId extends string, TTargetDetails
|
|
|
493
380
|
}
|
|
494
381
|
}
|
|
495
382
|
|
|
496
|
-
// Check marker presence
|
|
497
383
|
if (!marker) {
|
|
498
384
|
const totalTime = Date.now() - startTime;
|
|
499
385
|
return createVerifyResult({
|
|
500
386
|
ok: false,
|
|
501
387
|
code: 'PN-RTM-3001',
|
|
502
388
|
summary: 'Marker missing',
|
|
503
|
-
|
|
389
|
+
contractStorageHash,
|
|
504
390
|
expectedTargetId,
|
|
505
391
|
contractPath,
|
|
506
392
|
totalTime,
|
|
@@ -511,14 +397,13 @@ export function createSqlFamilyInstance<TTargetId extends string, TTargetDetails
|
|
|
511
397
|
});
|
|
512
398
|
}
|
|
513
399
|
|
|
514
|
-
// Compare target
|
|
515
400
|
if (contractTarget !== expectedTargetId) {
|
|
516
401
|
const totalTime = Date.now() - startTime;
|
|
517
402
|
return createVerifyResult({
|
|
518
403
|
ok: false,
|
|
519
404
|
code: 'PN-RTM-3003',
|
|
520
405
|
summary: 'Target mismatch',
|
|
521
|
-
|
|
406
|
+
contractStorageHash,
|
|
522
407
|
marker,
|
|
523
408
|
expectedTargetId,
|
|
524
409
|
actualTargetId: contractTarget,
|
|
@@ -531,14 +416,13 @@ export function createSqlFamilyInstance<TTargetId extends string, TTargetDetails
|
|
|
531
416
|
});
|
|
532
417
|
}
|
|
533
418
|
|
|
534
|
-
|
|
535
|
-
if (marker.coreHash !== contractCoreHash) {
|
|
419
|
+
if (marker.storageHash !== contractStorageHash) {
|
|
536
420
|
const totalTime = Date.now() - startTime;
|
|
537
421
|
return createVerifyResult({
|
|
538
422
|
ok: false,
|
|
539
423
|
code: 'PN-RTM-3002',
|
|
540
424
|
summary: 'Hash mismatch',
|
|
541
|
-
|
|
425
|
+
contractStorageHash,
|
|
542
426
|
marker,
|
|
543
427
|
expectedTargetId,
|
|
544
428
|
contractPath,
|
|
@@ -550,14 +434,13 @@ export function createSqlFamilyInstance<TTargetId extends string, TTargetDetails
|
|
|
550
434
|
});
|
|
551
435
|
}
|
|
552
436
|
|
|
553
|
-
// Compare profile hash if present
|
|
554
437
|
if (contractProfileHash && marker.profileHash !== contractProfileHash) {
|
|
555
438
|
const totalTime = Date.now() - startTime;
|
|
556
439
|
return createVerifyResult({
|
|
557
440
|
ok: false,
|
|
558
441
|
code: 'PN-RTM-3002',
|
|
559
442
|
summary: 'Hash mismatch',
|
|
560
|
-
|
|
443
|
+
contractStorageHash,
|
|
561
444
|
contractProfileHash,
|
|
562
445
|
marker,
|
|
563
446
|
expectedTargetId,
|
|
@@ -569,12 +452,11 @@ export function createSqlFamilyInstance<TTargetId extends string, TTargetDetails
|
|
|
569
452
|
});
|
|
570
453
|
}
|
|
571
454
|
|
|
572
|
-
// Success - all checks passed
|
|
573
455
|
const totalTime = Date.now() - startTime;
|
|
574
456
|
return createVerifyResult({
|
|
575
457
|
ok: true,
|
|
576
458
|
summary: 'Database matches contract',
|
|
577
|
-
|
|
459
|
+
contractStorageHash,
|
|
578
460
|
marker,
|
|
579
461
|
expectedTargetId,
|
|
580
462
|
contractPath,
|
|
@@ -589,14 +471,14 @@ export function createSqlFamilyInstance<TTargetId extends string, TTargetDetails
|
|
|
589
471
|
async schemaVerify(options: SchemaVerifyOptions): Promise<VerifyDatabaseSchemaResult> {
|
|
590
472
|
const { driver, contractIR, strict, context, frameworkComponents } = options;
|
|
591
473
|
|
|
592
|
-
// Validate contractIR as SqlContract<SqlStorage>
|
|
593
474
|
const contract = validateContract<SqlContract<SqlStorage>>(contractIR);
|
|
594
475
|
|
|
595
|
-
// Introspect live schema (DB I/O)
|
|
596
476
|
const controlAdapter = adapter.create();
|
|
477
|
+
if (!isSqlControlAdapter(controlAdapter)) {
|
|
478
|
+
throw new Error('Adapter does not implement SqlControlAdapter.introspect()');
|
|
479
|
+
}
|
|
597
480
|
const schemaIR = await controlAdapter.introspect(driver, contractIR);
|
|
598
481
|
|
|
599
|
-
// Pure verification (no I/O) - delegates to extracted pure function
|
|
600
482
|
return verifySqlSchema({
|
|
601
483
|
contract,
|
|
602
484
|
schema: schemaIR,
|
|
@@ -604,6 +486,9 @@ export function createSqlFamilyInstance<TTargetId extends string, TTargetDetails
|
|
|
604
486
|
...ifDefined('context', context),
|
|
605
487
|
typeMetadataRegistry,
|
|
606
488
|
frameworkComponents,
|
|
489
|
+
// Wire up target-specific normalizers if available
|
|
490
|
+
...ifDefined('normalizeDefault', controlAdapter.normalizeDefault),
|
|
491
|
+
...ifDefined('normalizeNativeType', controlAdapter.normalizeNativeType),
|
|
607
492
|
});
|
|
608
493
|
},
|
|
609
494
|
async sign(options: {
|
|
@@ -615,33 +500,27 @@ export function createSqlFamilyInstance<TTargetId extends string, TTargetDetails
|
|
|
615
500
|
const { driver, contractIR, contractPath, configPath } = options;
|
|
616
501
|
const startTime = Date.now();
|
|
617
502
|
|
|
618
|
-
// Validate contractIR as SqlContract<SqlStorage>
|
|
619
503
|
const contract = validateContract<SqlContract<SqlStorage>>(contractIR);
|
|
620
504
|
|
|
621
|
-
|
|
622
|
-
const contractCoreHash = contract.coreHash;
|
|
505
|
+
const contractStorageHash = contract.storageHash;
|
|
623
506
|
const contractProfileHash =
|
|
624
507
|
'profileHash' in contract && typeof contract.profileHash === 'string'
|
|
625
508
|
? contract.profileHash
|
|
626
|
-
:
|
|
509
|
+
: contractStorageHash;
|
|
627
510
|
const contractTarget = contract.target;
|
|
628
511
|
|
|
629
|
-
// Ensure marker schema and table exist
|
|
630
512
|
await driver.query(ensureSchemaStatement.sql, ensureSchemaStatement.params);
|
|
631
513
|
await driver.query(ensureTableStatement.sql, ensureTableStatement.params);
|
|
632
514
|
|
|
633
|
-
// Read existing marker
|
|
634
515
|
const existingMarker = await readMarker(driver);
|
|
635
516
|
|
|
636
|
-
// Determine if we need to write/update marker
|
|
637
517
|
let markerCreated = false;
|
|
638
518
|
let markerUpdated = false;
|
|
639
|
-
let previousHashes: {
|
|
519
|
+
let previousHashes: { storageHash?: string; profileHash?: string } | undefined;
|
|
640
520
|
|
|
641
521
|
if (!existingMarker) {
|
|
642
|
-
// No marker exists - insert new one
|
|
643
522
|
const write = writeContractMarker({
|
|
644
|
-
|
|
523
|
+
storageHash: contractStorageHash,
|
|
645
524
|
profileHash: contractProfileHash,
|
|
646
525
|
contractJson: contractIR,
|
|
647
526
|
canonicalVersion: 1,
|
|
@@ -649,22 +528,19 @@ export function createSqlFamilyInstance<TTargetId extends string, TTargetDetails
|
|
|
649
528
|
await driver.query(write.insert.sql, write.insert.params);
|
|
650
529
|
markerCreated = true;
|
|
651
530
|
} else {
|
|
652
|
-
|
|
653
|
-
const existingCoreHash = existingMarker.coreHash;
|
|
531
|
+
const existingStorageHash = existingMarker.storageHash;
|
|
654
532
|
const existingProfileHash = existingMarker.profileHash;
|
|
655
533
|
|
|
656
|
-
|
|
657
|
-
const coreHashMatches = existingCoreHash === contractCoreHash;
|
|
534
|
+
const storageHashMatches = existingStorageHash === contractStorageHash;
|
|
658
535
|
const profileHashMatches = existingProfileHash === contractProfileHash;
|
|
659
536
|
|
|
660
|
-
if (!
|
|
661
|
-
// Hashes differ - update marker and capture previous hashes for output
|
|
537
|
+
if (!storageHashMatches || !profileHashMatches) {
|
|
662
538
|
previousHashes = {
|
|
663
|
-
|
|
539
|
+
storageHash: existingStorageHash,
|
|
664
540
|
profileHash: existingProfileHash,
|
|
665
541
|
};
|
|
666
542
|
const write = writeContractMarker({
|
|
667
|
-
|
|
543
|
+
storageHash: contractStorageHash,
|
|
668
544
|
profileHash: contractProfileHash,
|
|
669
545
|
contractJson: contractIR,
|
|
670
546
|
canonicalVersion: existingMarker.canonicalVersion ?? 1,
|
|
@@ -672,15 +548,13 @@ export function createSqlFamilyInstance<TTargetId extends string, TTargetDetails
|
|
|
672
548
|
await driver.query(write.update.sql, write.update.params);
|
|
673
549
|
markerUpdated = true;
|
|
674
550
|
}
|
|
675
|
-
// If hashes match, no-op (idempotent) - previousHashes remains undefined
|
|
676
551
|
}
|
|
677
552
|
|
|
678
|
-
// Build summary message
|
|
679
553
|
let summary: string;
|
|
680
554
|
if (markerCreated) {
|
|
681
555
|
summary = 'Database signed (marker created)';
|
|
682
556
|
} else if (markerUpdated) {
|
|
683
|
-
summary = `Database signed (marker updated from ${previousHashes?.
|
|
557
|
+
summary = `Database signed (marker updated from ${previousHashes?.storageHash ?? 'unknown'})`;
|
|
684
558
|
} else {
|
|
685
559
|
summary = 'Database already signed with this contract';
|
|
686
560
|
}
|
|
@@ -691,7 +565,7 @@ export function createSqlFamilyInstance<TTargetId extends string, TTargetDetails
|
|
|
691
565
|
ok: true,
|
|
692
566
|
summary,
|
|
693
567
|
contract: {
|
|
694
|
-
|
|
568
|
+
storageHash: contractStorageHash,
|
|
695
569
|
profileHash: contractProfileHash,
|
|
696
570
|
},
|
|
697
571
|
target: {
|
|
@@ -724,24 +598,24 @@ export function createSqlFamilyInstance<TTargetId extends string, TTargetDetails
|
|
|
724
598
|
const { driver, contractIR } = options;
|
|
725
599
|
|
|
726
600
|
const controlAdapter = adapter.create();
|
|
601
|
+
if (!isSqlControlAdapter(controlAdapter)) {
|
|
602
|
+
throw new Error('Adapter does not implement SqlControlAdapter.introspect()');
|
|
603
|
+
}
|
|
727
604
|
return controlAdapter.introspect(driver, contractIR);
|
|
728
605
|
},
|
|
729
606
|
|
|
730
607
|
toSchemaView(schema: SqlSchemaIR): CoreSchemaView {
|
|
731
608
|
const rootLabel = 'contract';
|
|
732
609
|
|
|
733
|
-
// Build table nodes
|
|
734
610
|
const tableNodes: readonly SchemaTreeNode[] = Object.entries(schema.tables).map(
|
|
735
611
|
([tableName, table]: [string, SqlTableIR]) => {
|
|
736
612
|
const children: SchemaTreeNode[] = [];
|
|
737
613
|
|
|
738
|
-
// Add column nodes grouped under "columns"
|
|
739
614
|
const columnNodes: SchemaTreeNode[] = [];
|
|
740
615
|
for (const [columnName, column] of Object.entries(table.columns)) {
|
|
741
|
-
const nullableText = column.nullable ? '(nullable)' : '(not nullable)';
|
|
742
|
-
// Always display nativeType for introspection (database state)
|
|
743
616
|
const typeDisplay = column.nativeType;
|
|
744
|
-
const
|
|
617
|
+
const nullability = column.nullable ? 'nullable' : 'not nullable';
|
|
618
|
+
const label = `${columnName}: ${typeDisplay} (${nullability})`;
|
|
745
619
|
columnNodes.push({
|
|
746
620
|
kind: 'field',
|
|
747
621
|
id: `column-${tableName}-${columnName}`,
|
|
@@ -749,11 +623,11 @@ export function createSqlFamilyInstance<TTargetId extends string, TTargetDetails
|
|
|
749
623
|
meta: {
|
|
750
624
|
nativeType: column.nativeType,
|
|
751
625
|
nullable: column.nullable,
|
|
626
|
+
...ifDefined('default', column.default),
|
|
752
627
|
},
|
|
753
628
|
});
|
|
754
629
|
}
|
|
755
630
|
|
|
756
|
-
// Add "columns" grouping node if there are columns
|
|
757
631
|
if (columnNodes.length > 0) {
|
|
758
632
|
children.push({
|
|
759
633
|
kind: 'collection',
|
|
@@ -763,7 +637,6 @@ export function createSqlFamilyInstance<TTargetId extends string, TTargetDetails
|
|
|
763
637
|
});
|
|
764
638
|
}
|
|
765
639
|
|
|
766
|
-
// Add primary key node if present
|
|
767
640
|
if (table.primaryKey) {
|
|
768
641
|
const pkColumns = table.primaryKey.columns.join(', ');
|
|
769
642
|
children.push({
|
|
@@ -777,7 +650,6 @@ export function createSqlFamilyInstance<TTargetId extends string, TTargetDetails
|
|
|
777
650
|
});
|
|
778
651
|
}
|
|
779
652
|
|
|
780
|
-
// Add unique constraint nodes
|
|
781
653
|
for (const unique of table.uniques) {
|
|
782
654
|
const name = unique.name ?? `${tableName}_${unique.columns.join('_')}_unique`;
|
|
783
655
|
const label = `unique ${name}`;
|
|
@@ -792,7 +664,6 @@ export function createSqlFamilyInstance<TTargetId extends string, TTargetDetails
|
|
|
792
664
|
});
|
|
793
665
|
}
|
|
794
666
|
|
|
795
|
-
// Add index nodes
|
|
796
667
|
for (const index of table.indexes) {
|
|
797
668
|
const name = index.name ?? `${tableName}_${index.columns.join('_')}_idx`;
|
|
798
669
|
const label = index.unique ? `unique index ${name}` : `index ${name}`;
|
|
@@ -807,7 +678,6 @@ export function createSqlFamilyInstance<TTargetId extends string, TTargetDetails
|
|
|
807
678
|
});
|
|
808
679
|
}
|
|
809
680
|
|
|
810
|
-
// Build table meta
|
|
811
681
|
const tableMeta: Record<string, unknown> = {};
|
|
812
682
|
if (table.primaryKey) {
|
|
813
683
|
tableMeta['primaryKey'] = table.primaryKey.columns;
|
|
@@ -835,14 +705,12 @@ export function createSqlFamilyInstance<TTargetId extends string, TTargetDetails
|
|
|
835
705
|
},
|
|
836
706
|
);
|
|
837
707
|
|
|
838
|
-
// Add extension nodes (format: "extensionName extension is enabled")
|
|
839
708
|
const extensionNodes: readonly SchemaTreeNode[] = schema.extensions.map((extName) => ({
|
|
840
709
|
kind: 'extension',
|
|
841
710
|
id: `extension-${extName}`,
|
|
842
711
|
label: `${extName} extension is enabled`,
|
|
843
712
|
}));
|
|
844
713
|
|
|
845
|
-
// Combine all children
|
|
846
714
|
const rootChildren = [...tableNodes, ...extensionNodes];
|
|
847
715
|
|
|
848
716
|
const rootNode: SchemaTreeNode = {
|
|
@@ -858,20 +726,18 @@ export function createSqlFamilyInstance<TTargetId extends string, TTargetDetails
|
|
|
858
726
|
},
|
|
859
727
|
|
|
860
728
|
async emitContract({ contractIR }): Promise<EmitContractResult> {
|
|
861
|
-
|
|
862
|
-
const contractWithoutMappings = stripMappings(contractIR);
|
|
863
|
-
|
|
864
|
-
// Validate and normalize the contract
|
|
865
|
-
const validatedIR = this.validateContractIR(contractWithoutMappings);
|
|
729
|
+
const normalizedIR = normalizeProviderContractIR(contractIR);
|
|
866
730
|
|
|
867
731
|
const result = await emit(
|
|
868
|
-
|
|
732
|
+
normalizedIR,
|
|
869
733
|
{
|
|
870
734
|
outputDir: '',
|
|
871
735
|
operationRegistry,
|
|
872
736
|
codecTypeImports,
|
|
873
737
|
operationTypeImports,
|
|
874
738
|
extensionIds,
|
|
739
|
+
parameterizedRenderers,
|
|
740
|
+
parameterizedTypeImports,
|
|
875
741
|
},
|
|
876
742
|
sqlTargetFamilyHook,
|
|
877
743
|
);
|
|
@@ -879,7 +745,8 @@ export function createSqlFamilyInstance<TTargetId extends string, TTargetDetails
|
|
|
879
745
|
return {
|
|
880
746
|
contractJson: result.contractJson,
|
|
881
747
|
contractDts: result.contractDts,
|
|
882
|
-
|
|
748
|
+
storageHash: result.storageHash,
|
|
749
|
+
...(result.executionHash ? { executionHash: result.executionHash } : {}),
|
|
883
750
|
profileHash: result.profileHash,
|
|
884
751
|
};
|
|
885
752
|
},
|