@prisma-next/family-sql 0.3.0-dev.12 → 0.3.0-dev.122

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.
Files changed (101) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +34 -7
  3. package/dist/assembly-Dzumaba1.mjs +159 -0
  4. package/dist/assembly-Dzumaba1.mjs.map +1 -0
  5. package/dist/control-adapter.d.mts +60 -0
  6. package/dist/control-adapter.d.mts.map +1 -0
  7. package/dist/control-adapter.mjs +1 -0
  8. package/dist/control-instance-BKuHINR7.d.mts +411 -0
  9. package/dist/control-instance-BKuHINR7.d.mts.map +1 -0
  10. package/dist/control.d.mts +128 -0
  11. package/dist/control.d.mts.map +1 -0
  12. package/dist/control.mjs +683 -0
  13. package/dist/control.mjs.map +1 -0
  14. package/dist/runtime.d.mts +27 -0
  15. package/dist/runtime.d.mts.map +1 -0
  16. package/dist/runtime.mjs +38 -0
  17. package/dist/runtime.mjs.map +1 -0
  18. package/dist/schema-verify.d.mts +48 -0
  19. package/dist/schema-verify.d.mts.map +1 -0
  20. package/dist/schema-verify.mjs +4 -0
  21. package/dist/test-utils.d.mts +2 -0
  22. package/dist/test-utils.mjs +3 -0
  23. package/dist/verify-BfMETJcM.mjs +108 -0
  24. package/dist/verify-BfMETJcM.mjs.map +1 -0
  25. package/dist/verify-sql-schema-C3Pit9o4.mjs +1085 -0
  26. package/dist/verify-sql-schema-C3Pit9o4.mjs.map +1 -0
  27. package/dist/verify-sql-schema-DhHnkpPa.d.mts +67 -0
  28. package/dist/verify-sql-schema-DhHnkpPa.d.mts.map +1 -0
  29. package/dist/verify.d.mts +31 -0
  30. package/dist/verify.d.mts.map +1 -0
  31. package/dist/verify.mjs +3 -0
  32. package/package.json +35 -46
  33. package/src/core/assembly.ts +265 -59
  34. package/src/core/control-adapter.ts +15 -0
  35. package/src/core/{descriptor.ts → control-descriptor.ts} +15 -11
  36. package/src/core/{instance.ts → control-instance.ts} +106 -248
  37. package/src/core/migrations/contract-to-schema-ir.ts +265 -0
  38. package/src/core/migrations/types.ts +193 -168
  39. package/src/core/runtime-descriptor.ts +19 -41
  40. package/src/core/runtime-instance.ts +11 -133
  41. package/src/core/schema-verify/verify-helpers.ts +201 -105
  42. package/src/core/schema-verify/verify-sql-schema.ts +918 -413
  43. package/src/core/verify.ts +4 -13
  44. package/src/exports/control.ts +29 -6
  45. package/src/exports/runtime.ts +2 -6
  46. package/src/exports/schema-verify.ts +10 -2
  47. package/src/exports/test-utils.ts +1 -1
  48. package/dist/chunk-BHEGVBY7.js +0 -772
  49. package/dist/chunk-BHEGVBY7.js.map +0 -1
  50. package/dist/chunk-SQ2VWYDV.js +0 -589
  51. package/dist/chunk-SQ2VWYDV.js.map +0 -1
  52. package/dist/chunk-SU7LN2UH.js +0 -96
  53. package/dist/chunk-SU7LN2UH.js.map +0 -1
  54. package/dist/core/assembly.d.ts +0 -25
  55. package/dist/core/assembly.d.ts.map +0 -1
  56. package/dist/core/control-adapter.d.ts +0 -42
  57. package/dist/core/control-adapter.d.ts.map +0 -1
  58. package/dist/core/descriptor.d.ts +0 -24
  59. package/dist/core/descriptor.d.ts.map +0 -1
  60. package/dist/core/instance.d.ts +0 -140
  61. package/dist/core/instance.d.ts.map +0 -1
  62. package/dist/core/migrations/plan-helpers.d.ts +0 -20
  63. package/dist/core/migrations/plan-helpers.d.ts.map +0 -1
  64. package/dist/core/migrations/policies.d.ts +0 -6
  65. package/dist/core/migrations/policies.d.ts.map +0 -1
  66. package/dist/core/migrations/types.d.ts +0 -280
  67. package/dist/core/migrations/types.d.ts.map +0 -1
  68. package/dist/core/runtime-descriptor.d.ts +0 -19
  69. package/dist/core/runtime-descriptor.d.ts.map +0 -1
  70. package/dist/core/runtime-instance.d.ts +0 -54
  71. package/dist/core/runtime-instance.d.ts.map +0 -1
  72. package/dist/core/schema-verify/verify-helpers.d.ts +0 -50
  73. package/dist/core/schema-verify/verify-helpers.d.ts.map +0 -1
  74. package/dist/core/schema-verify/verify-sql-schema.d.ts +0 -45
  75. package/dist/core/schema-verify/verify-sql-schema.d.ts.map +0 -1
  76. package/dist/core/verify.d.ts +0 -39
  77. package/dist/core/verify.d.ts.map +0 -1
  78. package/dist/exports/control-adapter.d.ts +0 -2
  79. package/dist/exports/control-adapter.d.ts.map +0 -1
  80. package/dist/exports/control-adapter.js +0 -1
  81. package/dist/exports/control-adapter.js.map +0 -1
  82. package/dist/exports/control.d.ts +0 -13
  83. package/dist/exports/control.d.ts.map +0 -1
  84. package/dist/exports/control.js +0 -149
  85. package/dist/exports/control.js.map +0 -1
  86. package/dist/exports/runtime.d.ts +0 -8
  87. package/dist/exports/runtime.d.ts.map +0 -1
  88. package/dist/exports/runtime.js +0 -64
  89. package/dist/exports/runtime.js.map +0 -1
  90. package/dist/exports/schema-verify.d.ts +0 -11
  91. package/dist/exports/schema-verify.d.ts.map +0 -1
  92. package/dist/exports/schema-verify.js +0 -11
  93. package/dist/exports/schema-verify.js.map +0 -1
  94. package/dist/exports/test-utils.d.ts +0 -7
  95. package/dist/exports/test-utils.d.ts.map +0 -1
  96. package/dist/exports/test-utils.js +0 -17
  97. package/dist/exports/test-utils.js.map +0 -1
  98. package/dist/exports/verify.d.ts +0 -2
  99. package/dist/exports/verify.d.ts.map +0 -1
  100. package/dist/exports/verify.js +0 -11
  101. package/dist/exports/verify.js.map +0 -1
@@ -1,32 +1,74 @@
1
- import type { OperationManifest } from '@prisma-next/contract/pack-manifest-types';
2
- import type { TypesImportSpec } from '@prisma-next/contract/types';
3
1
  import type {
4
- ControlAdapterDescriptor,
5
- ControlExtensionDescriptor,
6
- ControlTargetDescriptor,
7
- } from '@prisma-next/core-control-plane/types';
8
- import type { OperationRegistry, OperationSignature } from '@prisma-next/operations';
2
+ NormalizedTypeRenderer,
3
+ TargetBoundComponentDescriptor,
4
+ TypeRenderer,
5
+ } from '@prisma-next/contract/framework-components';
6
+ import { normalizeRenderer } from '@prisma-next/contract/framework-components';
7
+ import type { TypesImportSpec } from '@prisma-next/contract/types';
8
+ import type { OperationRegistry } from '@prisma-next/operations';
9
9
  import { createOperationRegistry } from '@prisma-next/operations';
10
+ import type {
11
+ CodecControlHooks,
12
+ ControlMutationDefaultFunctionEntry,
13
+ ControlMutationDefaultGeneratorDescriptor,
14
+ PslScalarTypeDescriptor,
15
+ SqlControlStaticContributions,
16
+ } from './migrations/types';
17
+
18
+ function addUniqueId(ids: string[], seen: Set<string>, id: string): void {
19
+ if (!seen.has(id)) {
20
+ ids.push(id);
21
+ seen.add(id);
22
+ }
23
+ }
24
+
25
+ function assertUniqueCodecOwner(options: {
26
+ readonly codecId: string;
27
+ readonly owners: Map<string, string>;
28
+ readonly descriptorId: string;
29
+ readonly entityLabel: string;
30
+ readonly entityOwnershipLabel: string;
31
+ }): void {
32
+ const existingOwner = options.owners.get(options.codecId);
33
+ if (existingOwner !== undefined) {
34
+ throw new Error(
35
+ `Duplicate ${options.entityLabel} for codecId "${options.codecId}". ` +
36
+ `Descriptor "${options.descriptorId}" conflicts with "${existingOwner}". ` +
37
+ `Each codecId can only have one ${options.entityOwnershipLabel}.`,
38
+ );
39
+ }
40
+ }
41
+
42
+ export interface SqlControlDescriptorWithContributions extends SqlControlStaticContributions {
43
+ readonly id: string;
44
+ readonly types?: {
45
+ readonly codecTypes?: {
46
+ readonly import?: TypesImportSpec;
47
+ readonly parameterized?: Record<string, TypeRenderer>;
48
+ readonly typeImports?: ReadonlyArray<TypesImportSpec>;
49
+ };
50
+ readonly operationTypes?: { readonly import: TypesImportSpec };
51
+ };
52
+ }
53
+
54
+ export interface AssembledControlMutationDefaultContributions {
55
+ readonly defaultFunctionRegistry: ReadonlyMap<string, ControlMutationDefaultFunctionEntry>;
56
+ readonly generatorDescriptors: readonly ControlMutationDefaultGeneratorDescriptor[];
57
+ }
58
+
59
+ export interface AssembledPslInterpretationContributions
60
+ extends AssembledControlMutationDefaultContributions {
61
+ readonly scalarTypeDescriptors: ReadonlyMap<string, PslScalarTypeDescriptor>;
62
+ }
10
63
 
11
- /**
12
- * Assembles an operation registry from descriptors (adapter, target, extensions).
13
- * Loops over descriptors, extracts operations, converts them using the provided
14
- * conversion function, and registers them in a new registry.
15
- */
16
64
  export function assembleOperationRegistry(
17
- descriptors: ReadonlyArray<
18
- | ControlTargetDescriptor<'sql', string>
19
- | ControlAdapterDescriptor<'sql', string>
20
- | ControlExtensionDescriptor<'sql', string>
21
- >,
22
- convertOperationManifest: (manifest: OperationManifest) => OperationSignature,
65
+ descriptors: ReadonlyArray<SqlControlDescriptorWithContributions>,
23
66
  ): OperationRegistry {
24
67
  const registry = createOperationRegistry();
25
68
 
26
69
  for (const descriptor of descriptors) {
27
- const operations = descriptor.operations ?? [];
28
- for (const operationManifest of operations as ReadonlyArray<OperationManifest>) {
29
- const signature = convertOperationManifest(operationManifest);
70
+ const signatures = descriptor.operationSignatures();
71
+ for (const signature of signatures) {
30
72
  registry.register(signature);
31
73
  }
32
74
  }
@@ -34,15 +76,21 @@ export function assembleOperationRegistry(
34
76
  return registry;
35
77
  }
36
78
 
37
- /**
38
- * Extracts codec type imports from descriptors for contract.d.ts generation.
39
- */
79
+ interface DescriptorWithTypes {
80
+ readonly id: string;
81
+ readonly types?: {
82
+ readonly codecTypes?: {
83
+ readonly import?: TypesImportSpec;
84
+ readonly parameterized?: Record<string, TypeRenderer>;
85
+ readonly typeImports?: ReadonlyArray<TypesImportSpec>;
86
+ };
87
+ readonly operationTypes?: { readonly import: TypesImportSpec };
88
+ readonly queryOperationTypes?: { readonly import: TypesImportSpec };
89
+ };
90
+ }
91
+
40
92
  export function extractCodecTypeImports(
41
- descriptors: ReadonlyArray<
42
- | ControlTargetDescriptor<'sql', string>
43
- | ControlAdapterDescriptor<'sql', string>
44
- | ControlExtensionDescriptor<'sql', string>
45
- >,
93
+ descriptors: ReadonlyArray<DescriptorWithTypes>,
46
94
  ): ReadonlyArray<TypesImportSpec> {
47
95
  const imports: TypesImportSpec[] = [];
48
96
 
@@ -52,20 +100,16 @@ export function extractCodecTypeImports(
52
100
  if (codecTypes?.import) {
53
101
  imports.push(codecTypes.import);
54
102
  }
103
+ if (codecTypes?.typeImports) {
104
+ imports.push(...codecTypes.typeImports);
105
+ }
55
106
  }
56
107
 
57
108
  return imports;
58
109
  }
59
110
 
60
- /**
61
- * Extracts operation type imports from descriptors for contract.d.ts generation.
62
- */
63
111
  export function extractOperationTypeImports(
64
- descriptors: ReadonlyArray<
65
- | ControlTargetDescriptor<'sql', string>
66
- | ControlAdapterDescriptor<'sql', string>
67
- | ControlExtensionDescriptor<'sql', string>
68
- >,
112
+ descriptors: ReadonlyArray<DescriptorWithTypes>,
69
113
  ): ReadonlyArray<TypesImportSpec> {
70
114
  const imports: TypesImportSpec[] = [];
71
115
 
@@ -80,38 +124,200 @@ export function extractOperationTypeImports(
80
124
  return imports;
81
125
  }
82
126
 
83
- /**
84
- * Extracts extension IDs from descriptors in deterministic order:
85
- * [adapter.id, target.id, ...extensions.map(e => e.id)]
86
- * Deduplicates while preserving stable order.
87
- */
127
+ export function extractQueryOperationTypeImports(
128
+ descriptors: ReadonlyArray<DescriptorWithTypes>,
129
+ ): ReadonlyArray<TypesImportSpec> {
130
+ const imports: TypesImportSpec[] = [];
131
+
132
+ for (const descriptor of descriptors) {
133
+ const types = descriptor.types;
134
+ const queryOperationTypes = types?.queryOperationTypes;
135
+ if (queryOperationTypes?.import) {
136
+ imports.push(queryOperationTypes.import);
137
+ }
138
+ }
139
+
140
+ return imports;
141
+ }
142
+
88
143
  export function extractExtensionIds(
89
- adapter: ControlAdapterDescriptor<'sql', string>,
90
- target: ControlTargetDescriptor<'sql', string>,
91
- extensions: ReadonlyArray<ControlExtensionDescriptor<'sql', string>>,
144
+ adapter: { readonly id: string },
145
+ target: { readonly id: string },
146
+ extensions: ReadonlyArray<{ readonly id: string }>,
92
147
  ): ReadonlyArray<string> {
93
148
  const ids: string[] = [];
94
149
  const seen = new Set<string>();
95
150
 
96
- // Add adapter first
97
- if (!seen.has(adapter.id)) {
98
- ids.push(adapter.id);
99
- seen.add(adapter.id);
151
+ addUniqueId(ids, seen, adapter.id);
152
+ addUniqueId(ids, seen, target.id);
153
+
154
+ for (const ext of extensions) {
155
+ addUniqueId(ids, seen, ext.id);
100
156
  }
101
157
 
102
- // Add target second
103
- if (!seen.has(target.id)) {
104
- ids.push(target.id);
105
- seen.add(target.id);
158
+ return ids;
159
+ }
160
+
161
+ export function extractParameterizedRenderers(
162
+ descriptors: ReadonlyArray<DescriptorWithTypes>,
163
+ ): Map<string, NormalizedTypeRenderer> {
164
+ const renderers = new Map<string, NormalizedTypeRenderer>();
165
+ const owners = new Map<string, string>();
166
+
167
+ for (const descriptor of descriptors) {
168
+ const codecTypes = descriptor.types?.codecTypes;
169
+ if (!codecTypes?.parameterized) continue;
170
+
171
+ const parameterized: Record<string, TypeRenderer> = codecTypes.parameterized;
172
+ for (const [codecId, renderer] of Object.entries(parameterized)) {
173
+ assertUniqueCodecOwner({
174
+ codecId,
175
+ owners,
176
+ descriptorId: descriptor.id,
177
+ entityLabel: 'parameterized renderer',
178
+ entityOwnershipLabel: 'renderer',
179
+ });
180
+ renderers.set(codecId, normalizeRenderer(codecId, renderer));
181
+ owners.set(codecId, descriptor.id);
182
+ }
106
183
  }
107
184
 
108
- // Add extensions in order
109
- for (const ext of extensions) {
110
- if (!seen.has(ext.id)) {
111
- ids.push(ext.id);
112
- seen.add(ext.id);
185
+ return renderers;
186
+ }
187
+
188
+ type CodecControlHooksMap = Record<string, CodecControlHooks>;
189
+
190
+ function hasCodecControlHooks(descriptor: unknown): descriptor is {
191
+ readonly id: string;
192
+ readonly types: {
193
+ readonly codecTypes: {
194
+ readonly controlPlaneHooks: CodecControlHooksMap;
195
+ };
196
+ };
197
+ } {
198
+ if (typeof descriptor !== 'object' || descriptor === null) {
199
+ return false;
200
+ }
201
+ const d = descriptor as { types?: { codecTypes?: { controlPlaneHooks?: unknown } } };
202
+ const hooks = d.types?.codecTypes?.controlPlaneHooks;
203
+ return hooks !== null && hooks !== undefined && typeof hooks === 'object';
204
+ }
205
+
206
+ export function extractCodecControlHooks(
207
+ descriptors: ReadonlyArray<TargetBoundComponentDescriptor<'sql', string>>,
208
+ ): Map<string, CodecControlHooks> {
209
+ const hooks = new Map<string, CodecControlHooks>();
210
+ const owners = new Map<string, string>();
211
+
212
+ for (const descriptor of descriptors) {
213
+ if (typeof descriptor !== 'object' || descriptor === null) {
214
+ continue;
215
+ }
216
+ if (!hasCodecControlHooks(descriptor)) {
217
+ continue;
218
+ }
219
+ const controlPlaneHooks = descriptor.types.codecTypes.controlPlaneHooks;
220
+ for (const [codecId, hook] of Object.entries(controlPlaneHooks)) {
221
+ assertUniqueCodecOwner({
222
+ codecId,
223
+ owners,
224
+ descriptorId: descriptor.id,
225
+ entityLabel: 'control hooks',
226
+ entityOwnershipLabel: 'owner',
227
+ });
228
+ hooks.set(codecId, hook);
229
+ owners.set(codecId, descriptor.id);
113
230
  }
114
231
  }
115
232
 
116
- return ids;
233
+ return hooks;
234
+ }
235
+
236
+ export function extractParameterizedTypeImports(
237
+ descriptors: ReadonlyArray<DescriptorWithTypes>,
238
+ ): ReadonlyArray<TypesImportSpec> {
239
+ const imports: TypesImportSpec[] = [];
240
+
241
+ for (const descriptor of descriptors) {
242
+ const typeImports = descriptor.types?.codecTypes?.typeImports;
243
+ if (typeImports) {
244
+ imports.push(...typeImports);
245
+ }
246
+ }
247
+
248
+ return imports;
249
+ }
250
+
251
+ export function assembleControlMutationDefaultContributions(
252
+ descriptors: ReadonlyArray<SqlControlDescriptorWithContributions>,
253
+ ): AssembledControlMutationDefaultContributions {
254
+ const defaultFunctionRegistry = new Map<string, ControlMutationDefaultFunctionEntry>();
255
+ const functionOwners = new Map<string, string>();
256
+ const generatorMap = new Map<string, ControlMutationDefaultGeneratorDescriptor>();
257
+ const generatorOwners = new Map<string, string>();
258
+
259
+ for (const descriptor of descriptors) {
260
+ const contributions = descriptor.controlMutationDefaults?.();
261
+ if (!contributions) {
262
+ continue;
263
+ }
264
+
265
+ for (const generatorDescriptor of contributions.generatorDescriptors) {
266
+ const owner = generatorOwners.get(generatorDescriptor.id);
267
+ if (owner) {
268
+ throw new Error(
269
+ `Duplicate mutation default generator id "${generatorDescriptor.id}". Descriptor "${descriptor.id}" conflicts with "${owner}".`,
270
+ );
271
+ }
272
+ generatorMap.set(generatorDescriptor.id, generatorDescriptor);
273
+ generatorOwners.set(generatorDescriptor.id, descriptor.id);
274
+ }
275
+
276
+ for (const [functionName, handler] of contributions.defaultFunctionRegistry) {
277
+ const owner = functionOwners.get(functionName);
278
+ if (owner) {
279
+ throw new Error(
280
+ `Duplicate mutation default function "${functionName}". Descriptor "${descriptor.id}" conflicts with "${owner}".`,
281
+ );
282
+ }
283
+ defaultFunctionRegistry.set(functionName, handler);
284
+ functionOwners.set(functionName, descriptor.id);
285
+ }
286
+ }
287
+
288
+ return {
289
+ defaultFunctionRegistry,
290
+ generatorDescriptors: Array.from(generatorMap.values()),
291
+ };
292
+ }
293
+
294
+ export function assemblePslInterpretationContributions(
295
+ descriptors: ReadonlyArray<SqlControlDescriptorWithContributions>,
296
+ ): AssembledPslInterpretationContributions {
297
+ const mutationDefaults = assembleControlMutationDefaultContributions(descriptors);
298
+ const scalarTypeDescriptors = new Map<string, PslScalarTypeDescriptor>();
299
+ const scalarOwners = new Map<string, string>();
300
+
301
+ for (const descriptor of descriptors) {
302
+ const pslTypeContributions = descriptor.pslTypeDescriptors?.();
303
+ if (!pslTypeContributions) {
304
+ continue;
305
+ }
306
+
307
+ for (const [typeName, scalarDescriptor] of pslTypeContributions.scalarTypeDescriptors) {
308
+ const owner = scalarOwners.get(typeName);
309
+ if (owner) {
310
+ throw new Error(
311
+ `Duplicate PSL scalar type descriptor "${typeName}". Descriptor "${descriptor.id}" conflicts with "${owner}".`,
312
+ );
313
+ }
314
+ scalarTypeDescriptors.set(typeName, scalarDescriptor);
315
+ scalarOwners.set(typeName, descriptor.id);
316
+ }
317
+ }
318
+
319
+ return {
320
+ ...mutationDefaults,
321
+ scalarTypeDescriptors,
322
+ };
117
323
  }
@@ -3,6 +3,7 @@ import type {
3
3
  ControlDriverInstance,
4
4
  } from '@prisma-next/core-control-plane/types';
5
5
  import type { SqlSchemaIR } from '@prisma-next/sql-schema-ir/types';
6
+ import type { DefaultNormalizer, NativeTypeNormalizer } from './schema-verify/verify-sql-schema';
6
7
 
7
8
  /**
8
9
  * SQL control adapter interface for control-plane operations.
@@ -36,6 +37,20 @@ export interface SqlControlAdapter<TTarget extends string = string>
36
37
  contractIR?: unknown,
37
38
  schema?: string,
38
39
  ): Promise<SqlSchemaIR>;
40
+
41
+ /**
42
+ * Optional target-specific normalizer for raw database default expressions.
43
+ * When provided, schema defaults (raw strings) are normalized before comparison
44
+ * with contract defaults (ColumnDefault objects) during schema verification.
45
+ */
46
+ readonly normalizeDefault?: DefaultNormalizer;
47
+
48
+ /**
49
+ * Optional target-specific normalizer for schema native type names.
50
+ * When provided, schema native types (from introspection) are normalized
51
+ * before comparison with contract native types during schema verification.
52
+ */
53
+ readonly normalizeNativeType?: NativeTypeNormalizer;
39
54
  }
40
55
 
41
56
  /**
@@ -1,14 +1,16 @@
1
+ import type { TargetDescriptor } from '@prisma-next/contract/framework-components';
1
2
  import type {
2
3
  ControlFamilyDescriptor,
3
4
  ControlPlaneStack,
4
5
  } from '@prisma-next/core-control-plane/types';
5
6
  import { sqlTargetFamilyHook } from '@prisma-next/sql-contract-emitter';
6
- import { createSqlFamilyInstance, type SqlControlFamilyInstance } from './instance';
7
+ import type { SqlControlDescriptorWithContributions } from './assembly';
8
+ import { createSqlFamilyInstance, type SqlControlFamilyInstance } from './control-instance';
9
+ import type {
10
+ SqlControlAdapterDescriptor,
11
+ SqlControlExtensionDescriptor,
12
+ } from './migrations/types';
7
13
 
8
- /**
9
- * SQL family descriptor implementation.
10
- * Provides the SQL family hook and factory method.
11
- */
12
14
  export class SqlFamilyDescriptor
13
15
  implements ControlFamilyDescriptor<'sql', SqlControlFamilyInstance>
14
16
  {
@@ -21,13 +23,15 @@ export class SqlFamilyDescriptor
21
23
  create<TTargetId extends string>(
22
24
  stack: ControlPlaneStack<'sql', TTargetId>,
23
25
  ): SqlControlFamilyInstance {
24
- // Note: driver is not passed here because SqlFamilyInstance operations
25
- // (validate, emit, etc.) don't require DB connectivity. Commands that
26
- // need the driver (verify, introspect) get it directly from the stack.
26
+ const target = stack.target as unknown as TargetDescriptor<'sql', TTargetId> &
27
+ SqlControlDescriptorWithContributions;
28
+ const adapter = stack.adapter as unknown as SqlControlAdapterDescriptor<TTargetId>;
29
+ const extensionPacks =
30
+ stack.extensionPacks as unknown as readonly SqlControlExtensionDescriptor<TTargetId>[];
27
31
  return createSqlFamilyInstance({
28
- target: stack.target,
29
- adapter: stack.adapter,
30
- extensionPacks: stack.extensionPacks,
32
+ target,
33
+ adapter,
34
+ extensionPacks,
31
35
  });
32
36
  }
33
37
  }