@prisma-next/sql-runtime 0.3.0-dev.34 → 0.3.0-dev.36

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 (163) hide show
  1. package/README.md +115 -24
  2. package/dist/exports-C8hi0N-a.mjs +622 -0
  3. package/dist/exports-C8hi0N-a.mjs.map +1 -0
  4. package/dist/index-SlQIrV_t.d.mts +131 -0
  5. package/dist/index-SlQIrV_t.d.mts.map +1 -0
  6. package/dist/index.d.mts +2 -0
  7. package/dist/index.mjs +3 -0
  8. package/dist/test/utils.d.mts +82 -0
  9. package/dist/test/utils.d.mts.map +1 -0
  10. package/dist/test/utils.mjs +212 -0
  11. package/dist/test/utils.mjs.map +1 -0
  12. package/package.json +26 -20
  13. package/src/codecs/decoding.ts +84 -3
  14. package/src/codecs/encoding.ts +15 -2
  15. package/src/codecs/json-schema-validation.ts +61 -0
  16. package/src/exports/index.ts +9 -4
  17. package/src/lower-sql-plan.ts +8 -8
  18. package/src/sql-context.ts +286 -245
  19. package/src/sql-family-adapter.ts +9 -5
  20. package/src/sql-marker.ts +2 -2
  21. package/src/sql-runtime.ts +89 -23
  22. package/test/async-iterable-result.test.ts +42 -34
  23. package/test/context.types.test-d.ts +12 -14
  24. package/test/execution-stack.test.ts +166 -0
  25. package/test/json-schema-validation.test.ts +653 -0
  26. package/test/parameterized-types.test.ts +182 -196
  27. package/test/sql-context.test.ts +292 -117
  28. package/test/sql-family-adapter.test.ts +7 -6
  29. package/test/sql-runtime.test.ts +117 -31
  30. package/test/utils.ts +76 -50
  31. package/dist/accelerate-EEKAFGN3-P6A6XJWJ.js +0 -137863
  32. package/dist/accelerate-EEKAFGN3-P6A6XJWJ.js.map +0 -1
  33. package/dist/amcheck-24VY6X5V.js +0 -13
  34. package/dist/amcheck-24VY6X5V.js.map +0 -1
  35. package/dist/bloom-VS74NLHT.js +0 -13
  36. package/dist/bloom-VS74NLHT.js.map +0 -1
  37. package/dist/btree_gin-WBC4EAAI.js +0 -13
  38. package/dist/btree_gin-WBC4EAAI.js.map +0 -1
  39. package/dist/btree_gist-UNC6QD3M.js +0 -13
  40. package/dist/btree_gist-UNC6QD3M.js.map +0 -1
  41. package/dist/chunk-3KTOEDFX.js +0 -49
  42. package/dist/chunk-3KTOEDFX.js.map +0 -1
  43. package/dist/chunk-47DZBRQC.js +0 -1280
  44. package/dist/chunk-47DZBRQC.js.map +0 -1
  45. package/dist/chunk-52N6AFZM.js +0 -133
  46. package/dist/chunk-52N6AFZM.js.map +0 -1
  47. package/dist/chunk-7D4SUZUM.js +0 -38
  48. package/dist/chunk-7D4SUZUM.js.map +0 -1
  49. package/dist/chunk-APA6GHYY.js +0 -537
  50. package/dist/chunk-APA6GHYY.js.map +0 -1
  51. package/dist/chunk-ECWIHLAT.js +0 -37
  52. package/dist/chunk-ECWIHLAT.js.map +0 -1
  53. package/dist/chunk-EI626SDC.js +0 -105
  54. package/dist/chunk-EI626SDC.js.map +0 -1
  55. package/dist/chunk-UKKOYUGL.js +0 -578
  56. package/dist/chunk-UKKOYUGL.js.map +0 -1
  57. package/dist/chunk-XPLNMXQV.js +0 -1537
  58. package/dist/chunk-XPLNMXQV.js.map +0 -1
  59. package/dist/citext-T7MXGUY7.js +0 -13
  60. package/dist/citext-T7MXGUY7.js.map +0 -1
  61. package/dist/client-5FENX6AW.js +0 -299
  62. package/dist/client-5FENX6AW.js.map +0 -1
  63. package/dist/cube-TFDQBZCI.js +0 -13
  64. package/dist/cube-TFDQBZCI.js.map +0 -1
  65. package/dist/dict_int-AEUOPGWP.js +0 -13
  66. package/dist/dict_int-AEUOPGWP.js.map +0 -1
  67. package/dist/dict_xsyn-DAAYX3FL.js +0 -13
  68. package/dist/dict_xsyn-DAAYX3FL.js.map +0 -1
  69. package/dist/dist-AQ3LWXOX.js +0 -570
  70. package/dist/dist-AQ3LWXOX.js.map +0 -1
  71. package/dist/dist-LBVX6BJW.js +0 -189
  72. package/dist/dist-LBVX6BJW.js.map +0 -1
  73. package/dist/dist-WLKUVDN2.js +0 -5127
  74. package/dist/dist-WLKUVDN2.js.map +0 -1
  75. package/dist/earthdistance-KIGTF4LE.js +0 -13
  76. package/dist/earthdistance-KIGTF4LE.js.map +0 -1
  77. package/dist/file_fdw-5N55UP6I.js +0 -13
  78. package/dist/file_fdw-5N55UP6I.js.map +0 -1
  79. package/dist/fuzzystrmatch-KN3YWBFP.js +0 -13
  80. package/dist/fuzzystrmatch-KN3YWBFP.js.map +0 -1
  81. package/dist/hstore-YX726NKN.js +0 -13
  82. package/dist/hstore-YX726NKN.js.map +0 -1
  83. package/dist/http-exception-FZY2H4OF.js +0 -8
  84. package/dist/http-exception-FZY2H4OF.js.map +0 -1
  85. package/dist/index.js +0 -30
  86. package/dist/index.js.map +0 -1
  87. package/dist/intarray-NKVXNO2D.js +0 -13
  88. package/dist/intarray-NKVXNO2D.js.map +0 -1
  89. package/dist/isn-FTEMJGEV.js +0 -13
  90. package/dist/isn-FTEMJGEV.js.map +0 -1
  91. package/dist/lo-DB7L4NGI.js +0 -13
  92. package/dist/lo-DB7L4NGI.js.map +0 -1
  93. package/dist/logger-WQ7SHNDD.js +0 -68
  94. package/dist/logger-WQ7SHNDD.js.map +0 -1
  95. package/dist/ltree-Z32TZT6W.js +0 -13
  96. package/dist/ltree-Z32TZT6W.js.map +0 -1
  97. package/dist/nodefs-NM46ACH7.js +0 -31
  98. package/dist/nodefs-NM46ACH7.js.map +0 -1
  99. package/dist/opfs-ahp-NJO33LVZ.js +0 -332
  100. package/dist/opfs-ahp-NJO33LVZ.js.map +0 -1
  101. package/dist/pageinspect-YP3IZR4X.js +0 -13
  102. package/dist/pageinspect-YP3IZR4X.js.map +0 -1
  103. package/dist/pg_buffercache-7TD5J2FB.js +0 -13
  104. package/dist/pg_buffercache-7TD5J2FB.js.map +0 -1
  105. package/dist/pg_dump-SG4KYBUB.js +0 -2492
  106. package/dist/pg_dump-SG4KYBUB.js.map +0 -1
  107. package/dist/pg_freespacemap-DZDNCPZK.js +0 -13
  108. package/dist/pg_freespacemap-DZDNCPZK.js.map +0 -1
  109. package/dist/pg_surgery-J2MUEWEP.js +0 -13
  110. package/dist/pg_surgery-J2MUEWEP.js.map +0 -1
  111. package/dist/pg_trgm-7VNQOYS6.js +0 -13
  112. package/dist/pg_trgm-7VNQOYS6.js.map +0 -1
  113. package/dist/pg_visibility-TTSIPHFL.js +0 -13
  114. package/dist/pg_visibility-TTSIPHFL.js.map +0 -1
  115. package/dist/pg_walinspect-KPFHSHRJ.js +0 -13
  116. package/dist/pg_walinspect-KPFHSHRJ.js.map +0 -1
  117. package/dist/proxy-signals-GUDAMDHV.js +0 -39
  118. package/dist/proxy-signals-GUDAMDHV.js.map +0 -1
  119. package/dist/seg-IYVDLE4O.js +0 -13
  120. package/dist/seg-IYVDLE4O.js.map +0 -1
  121. package/dist/src/codecs/decoding.d.ts +0 -4
  122. package/dist/src/codecs/decoding.d.ts.map +0 -1
  123. package/dist/src/codecs/encoding.d.ts +0 -5
  124. package/dist/src/codecs/encoding.d.ts.map +0 -1
  125. package/dist/src/codecs/validation.d.ts +0 -6
  126. package/dist/src/codecs/validation.d.ts.map +0 -1
  127. package/dist/src/exports/index.d.ts +0 -11
  128. package/dist/src/exports/index.d.ts.map +0 -1
  129. package/dist/src/index.d.ts +0 -2
  130. package/dist/src/index.d.ts.map +0 -1
  131. package/dist/src/lower-sql-plan.d.ts +0 -15
  132. package/dist/src/lower-sql-plan.d.ts.map +0 -1
  133. package/dist/src/sql-context.d.ts +0 -130
  134. package/dist/src/sql-context.d.ts.map +0 -1
  135. package/dist/src/sql-family-adapter.d.ts +0 -10
  136. package/dist/src/sql-family-adapter.d.ts.map +0 -1
  137. package/dist/src/sql-marker.d.ts +0 -22
  138. package/dist/src/sql-marker.d.ts.map +0 -1
  139. package/dist/src/sql-runtime.d.ts +0 -25
  140. package/dist/src/sql-runtime.d.ts.map +0 -1
  141. package/dist/tablefunc-EF4RCS7S.js +0 -13
  142. package/dist/tablefunc-EF4RCS7S.js.map +0 -1
  143. package/dist/tcn-3VT5BQYW.js +0 -13
  144. package/dist/tcn-3VT5BQYW.js.map +0 -1
  145. package/dist/test/utils.d.ts +0 -60
  146. package/dist/test/utils.d.ts.map +0 -1
  147. package/dist/test/utils.js +0 -24635
  148. package/dist/test/utils.js.map +0 -1
  149. package/dist/tiny-CW6F4GX6.js +0 -10
  150. package/dist/tiny-CW6F4GX6.js.map +0 -1
  151. package/dist/tsm_system_rows-ES7KNUQH.js +0 -13
  152. package/dist/tsm_system_rows-ES7KNUQH.js.map +0 -1
  153. package/dist/tsm_system_time-76WEIMBG.js +0 -13
  154. package/dist/tsm_system_time-76WEIMBG.js.map +0 -1
  155. package/dist/unaccent-7RYF3R64.js +0 -13
  156. package/dist/unaccent-7RYF3R64.js.map +0 -1
  157. package/dist/utility-Q5A254LJ-J4HTKZPT.js +0 -347
  158. package/dist/utility-Q5A254LJ-J4HTKZPT.js.map +0 -1
  159. package/dist/uuid_ossp-4ETE4FPE.js +0 -13
  160. package/dist/uuid_ossp-4ETE4FPE.js.map +0 -1
  161. package/dist/vector-74GPNV7V.js +0 -13
  162. package/dist/vector-74GPNV7V.js.map +0 -1
  163. package/src/index.ts +0 -1
@@ -1,220 +1,197 @@
1
+ import { checkContractComponentRequirements } from '@prisma-next/contract/framework-components';
2
+ import type { ExecutionMutationDefaultValue } from '@prisma-next/contract/types';
3
+ import { createExecutionStack, type ExecutionStack } from '@prisma-next/core-execution-plane/stack';
1
4
  import type {
2
5
  RuntimeAdapterDescriptor,
3
6
  RuntimeAdapterInstance,
7
+ RuntimeDriverDescriptor,
8
+ RuntimeDriverInstance,
4
9
  RuntimeExtensionDescriptor,
5
10
  RuntimeExtensionInstance,
6
11
  RuntimeTargetDescriptor,
12
+ RuntimeTargetInstance,
7
13
  } from '@prisma-next/core-execution-plane/types';
14
+ import { generateId } from '@prisma-next/ids/runtime';
8
15
  import { createOperationRegistry } from '@prisma-next/operations';
16
+ import { runtimeError } from '@prisma-next/runtime-executor';
9
17
  import type { SqlContract, SqlStorage, StorageTypeInstance } from '@prisma-next/sql-contract/types';
10
18
  import type { SqlOperationSignature } from '@prisma-next/sql-operations';
11
19
  import type {
12
20
  Adapter,
21
+ CodecParamsDescriptor,
13
22
  CodecRegistry,
14
23
  LoweredStatement,
15
24
  QueryAst,
25
+ SqlDriver,
16
26
  } from '@prisma-next/sql-relational-core/ast';
17
27
  import { createCodecRegistry } from '@prisma-next/sql-relational-core/ast';
18
28
  import type {
19
- QueryLaneContext,
29
+ AppliedMutationDefault,
30
+ ExecutionContext,
31
+ JsonSchemaValidateFn,
32
+ JsonSchemaValidatorRegistry,
33
+ MutationDefaultsOptions,
20
34
  TypeHelperRegistry,
21
35
  } from '@prisma-next/sql-relational-core/query-lane-context';
22
- import type { Type } from 'arktype';
23
36
  import { type as arktype } from 'arktype';
24
37
 
25
- // ============================================================================
26
- // Runtime Parameterized Codec Descriptor Types
27
- // ============================================================================
28
-
29
38
  /**
30
39
  * Runtime parameterized codec descriptor.
31
40
  * Provides validation schema and optional init hook for codecs that support type parameters.
32
41
  * Used at runtime to validate typeParams and create type helpers.
42
+ *
43
+ * This is a type alias for `CodecParamsDescriptor` from the AST layer,
44
+ * which is the shared definition used by both adapter and runtime.
33
45
  */
34
- export interface RuntimeParameterizedCodecDescriptor<
46
+ export type RuntimeParameterizedCodecDescriptor<
35
47
  TParams = Record<string, unknown>,
36
48
  THelper = unknown,
37
- > {
38
- /** The codec ID this descriptor applies to (e.g., 'pg/vector@1') */
39
- readonly codecId: string;
40
-
41
- /**
42
- * Arktype schema for validating typeParams.
43
- * The schema is used to validate both storage.types entries and inline column typeParams.
44
- */
45
- readonly paramsSchema: Type<TParams>;
46
-
47
- /**
48
- * Optional init hook called during runtime context creation.
49
- * Receives validated params and returns a helper object to be stored in context.types.
50
- * If not provided, the validated params are stored directly.
51
- */
52
- readonly init?: (params: TParams) => THelper;
53
- }
54
-
55
- // ============================================================================
56
- // SQL Runtime Extension Types
57
- // ============================================================================
49
+ > = CodecParamsDescriptor<TParams, THelper>;
58
50
 
59
- /**
60
- * SQL runtime extension instance.
61
- * Extends the framework RuntimeExtensionInstance with SQL-specific hooks
62
- * for contributing codecs and operations to the runtime context.
63
- *
64
- * @template TTargetId - The target ID (e.g., 'postgres', 'mysql')
65
- */
66
- export interface SqlRuntimeExtensionInstance<TTargetId extends string>
67
- extends RuntimeExtensionInstance<'sql', TTargetId> {
68
- /** Returns codecs to register in the runtime context. */
69
- codecs?(): CodecRegistry;
70
- /** Returns operations to register in the runtime context. */
71
- operations?(): ReadonlyArray<SqlOperationSignature>;
72
- /**
73
- * Returns parameterized codec descriptors for type validation and helper creation.
74
- * Uses unknown for type parameters to allow any concrete descriptor types.
75
- */
51
+ export interface SqlStaticContributions {
52
+ readonly codecs: () => CodecRegistry;
53
+ readonly operationSignatures: () => ReadonlyArray<SqlOperationSignature>;
76
54
  // biome-ignore lint/suspicious/noExplicitAny: needed for covariance with concrete descriptor types
77
- parameterizedCodecs?(): ReadonlyArray<RuntimeParameterizedCodecDescriptor<any, any>>;
55
+ readonly parameterizedCodecs: () => ReadonlyArray<RuntimeParameterizedCodecDescriptor<any, any>>;
78
56
  }
79
57
 
80
- /**
81
- * SQL runtime extension descriptor.
82
- * Extends the framework RuntimeExtensionDescriptor with SQL-specific instance type.
83
- *
84
- * @template TTargetId - The target ID (e.g., 'postgres', 'mysql')
85
- */
86
- export interface SqlRuntimeExtensionDescriptor<TTargetId extends string>
87
- extends RuntimeExtensionDescriptor<'sql', TTargetId, SqlRuntimeExtensionInstance<TTargetId>> {
58
+ export interface SqlRuntimeTargetDescriptor<
59
+ TTargetId extends string = string,
60
+ TTargetInstance extends RuntimeTargetInstance<'sql', TTargetId> = RuntimeTargetInstance<
61
+ 'sql',
62
+ TTargetId
63
+ >,
64
+ > extends RuntimeTargetDescriptor<'sql', TTargetId, TTargetInstance>,
65
+ SqlStaticContributions {}
66
+
67
+ export interface SqlRuntimeAdapterDescriptor<
68
+ TTargetId extends string = string,
69
+ TAdapterInstance extends RuntimeAdapterInstance<
70
+ 'sql',
71
+ TTargetId
72
+ > = SqlRuntimeAdapterInstance<TTargetId>,
73
+ > extends RuntimeAdapterDescriptor<'sql', TTargetId, TAdapterInstance>,
74
+ SqlStaticContributions {}
75
+
76
+ export interface SqlRuntimeExtensionDescriptor<TTargetId extends string = string>
77
+ extends RuntimeExtensionDescriptor<'sql', TTargetId, SqlRuntimeExtensionInstance<TTargetId>>,
78
+ SqlStaticContributions {
88
79
  create(): SqlRuntimeExtensionInstance<TTargetId>;
89
80
  }
90
81
 
91
- // ============================================================================
92
- // SQL Runtime Adapter Instance
93
- // ============================================================================
82
+ export interface SqlExecutionStack<TTargetId extends string = string> {
83
+ readonly target: SqlRuntimeTargetDescriptor<TTargetId>;
84
+ readonly adapter: SqlRuntimeAdapterDescriptor<TTargetId>;
85
+ readonly extensionPacks: readonly SqlRuntimeExtensionDescriptor<TTargetId>[];
86
+ }
87
+
88
+ export type SqlExecutionStackWithDriver<TTargetId extends string = string> = Omit<
89
+ ExecutionStack<
90
+ 'sql',
91
+ TTargetId,
92
+ SqlRuntimeAdapterInstance<TTargetId>,
93
+ SqlRuntimeDriverInstance<TTargetId>,
94
+ SqlRuntimeExtensionInstance<TTargetId>
95
+ >,
96
+ 'target' | 'adapter' | 'driver' | 'extensionPacks'
97
+ > & {
98
+ readonly target: SqlRuntimeTargetDescriptor<TTargetId>;
99
+ readonly adapter: SqlRuntimeAdapterDescriptor<TTargetId, SqlRuntimeAdapterInstance<TTargetId>>;
100
+ readonly driver:
101
+ | RuntimeDriverDescriptor<'sql', TTargetId, unknown, SqlRuntimeDriverInstance<TTargetId>>
102
+ | undefined;
103
+ readonly extensionPacks: readonly SqlRuntimeExtensionDescriptor<TTargetId>[];
104
+ };
105
+
106
+ export interface SqlRuntimeExtensionInstance<TTargetId extends string>
107
+ extends RuntimeExtensionInstance<'sql', TTargetId> {}
94
108
 
95
- /**
96
- * SQL runtime adapter instance interface.
97
- * Combines RuntimeAdapterInstance identity with SQL Adapter behavior.
98
- * The instance IS an Adapter (via intersection), not HAS an adapter property.
99
- *
100
- * @template TTargetId - The target ID (e.g., 'postgres', 'mysql')
101
- */
102
109
  export type SqlRuntimeAdapterInstance<TTargetId extends string = string> = RuntimeAdapterInstance<
103
110
  'sql',
104
111
  TTargetId
105
112
  > &
106
113
  Adapter<QueryAst, SqlContract<SqlStorage>, LoweredStatement>;
107
114
 
108
- // ============================================================================
109
- // SQL Runtime Context
110
- // ============================================================================
111
-
112
- export type { TypeHelperRegistry };
113
-
114
- export interface RuntimeContext<TContract extends SqlContract<SqlStorage> = SqlContract<SqlStorage>>
115
- extends QueryLaneContext<TContract> {
116
- readonly adapter:
117
- | Adapter<QueryAst, TContract, LoweredStatement>
118
- | Adapter<QueryAst, SqlContract<SqlStorage>, LoweredStatement>;
119
-
120
- /**
121
- * Initialized type helpers from storage.types.
122
- * Each entry corresponds to a named type instance in the contract's storage.types.
123
- * The value is the result of calling the codec's init hook (if provided)
124
- * or the validated typeParams (if no init hook).
125
- */
126
- readonly types?: TypeHelperRegistry;
127
- }
128
-
129
115
  /**
130
- * Descriptor-first options for creating a SQL runtime context.
131
- * Takes the same framework composition as control-plane: target, adapter, extensionPacks.
132
- *
133
- * @template TContract - The SQL contract type
134
- * @template TTargetId - The target ID (e.g., 'postgres', 'mysql')
116
+ * NOTE: Binding type is intentionally erased to unknown at this shared runtime layer.
117
+ * Target clients (for example `postgres()`) validate and construct the concrete binding
118
+ * before calling `driver.connect(binding)`, which keeps runtime behavior safe today.
119
+ * A future follow-up can preserve TBinding through stack/context generics end-to-end.
135
120
  */
136
- export interface CreateRuntimeContextOptions<
137
- TContract extends SqlContract<SqlStorage> = SqlContract<SqlStorage>,
138
- TTargetId extends string = string,
139
- > {
140
- readonly contract: TContract;
141
- readonly target: RuntimeTargetDescriptor<'sql', TTargetId>;
142
- readonly adapter: RuntimeAdapterDescriptor<
143
- 'sql',
144
- TTargetId,
145
- SqlRuntimeAdapterInstance<TTargetId>
146
- >;
147
- readonly extensionPacks?: ReadonlyArray<SqlRuntimeExtensionDescriptor<TTargetId>>;
121
+ export type SqlRuntimeDriverInstance<TTargetId extends string = string> = RuntimeDriverInstance<
122
+ 'sql',
123
+ TTargetId
124
+ > &
125
+ SqlDriver<unknown>;
126
+
127
+ export function createSqlExecutionStack<TTargetId extends string>(options: {
128
+ readonly target: SqlRuntimeTargetDescriptor<TTargetId>;
129
+ readonly adapter: SqlRuntimeAdapterDescriptor<TTargetId>;
130
+ readonly driver?:
131
+ | RuntimeDriverDescriptor<'sql', TTargetId, unknown, SqlRuntimeDriverInstance<TTargetId>>
132
+ | undefined;
133
+ readonly extensionPacks?: readonly SqlRuntimeExtensionDescriptor<TTargetId>[] | undefined;
134
+ }): SqlExecutionStackWithDriver<TTargetId> {
135
+ return createExecutionStack({
136
+ target: options.target,
137
+ adapter: options.adapter,
138
+ driver: options.driver,
139
+ extensionPacks: options.extensionPacks,
140
+ });
148
141
  }
149
142
 
150
- // ============================================================================
151
- // Runtime Error Types and Helpers
152
- // ============================================================================
143
+ export type { ExecutionContext, JsonSchemaValidatorRegistry, TypeHelperRegistry };
153
144
 
154
- /**
155
- * Structured error thrown by the SQL runtime.
156
- *
157
- * Aligns with the repository's error envelope convention:
158
- * - `code`: Stable error code for programmatic handling (e.g., `RUNTIME.TYPE_PARAMS_INVALID`)
159
- * - `category`: Error source category (`RUNTIME`)
160
- * - `severity`: Error severity level (`error`)
161
- * - `details`: Optional structured details for debugging
162
- *
163
- * @example
164
- * ```typescript
165
- * try {
166
- * createRuntimeContext({ ... });
167
- * } catch (e) {
168
- * if ((e as RuntimeError).code === 'RUNTIME.TYPE_PARAMS_INVALID') {
169
- * console.error('Invalid type parameters:', (e as RuntimeError).details);
170
- * }
171
- * }
172
- * ```
173
- */
174
- export interface RuntimeError extends Error {
175
- /** Stable error code for programmatic handling (e.g., `RUNTIME.TYPE_PARAMS_INVALID`) */
176
- readonly code: string;
177
- /** Error source category */
178
- readonly category: 'RUNTIME';
179
- /** Error severity level */
180
- readonly severity: 'error';
181
- /** Optional structured details for debugging */
182
- readonly details?: Record<string, unknown>;
183
- }
145
+ export function assertExecutionStackContractRequirements(
146
+ contract: SqlContract<SqlStorage>,
147
+ stack: SqlExecutionStack,
148
+ ): void {
149
+ const providedComponentIds = new Set<string>([
150
+ stack.target.id,
151
+ stack.adapter.id,
152
+ ...stack.extensionPacks.map((pack) => pack.id),
153
+ ]);
184
154
 
185
- /**
186
- * Creates a RuntimeError for invalid type parameters.
187
- *
188
- * Error code: `RUNTIME.TYPE_PARAMS_INVALID`
189
- *
190
- * Thrown when:
191
- * - `storage.types` entries have typeParams that fail codec schema validation
192
- * - Column inline typeParams fail codec schema validation
193
- *
194
- * @internal
195
- */
196
- function runtimeTypeParamsInvalid(
197
- message: string,
198
- details?: Record<string, unknown>,
199
- ): RuntimeError {
200
- const error = new Error(message) as RuntimeError;
201
- Object.defineProperty(error, 'name', { value: 'RuntimeError', configurable: true });
202
- return Object.assign(error, {
203
- code: 'RUNTIME.TYPE_PARAMS_INVALID',
204
- category: 'RUNTIME' as const,
205
- severity: 'error' as const,
206
- details,
155
+ const result = checkContractComponentRequirements({
156
+ contract,
157
+ expectedTargetFamily: 'sql',
158
+ expectedTargetId: stack.target.targetId,
159
+ providedComponentIds,
207
160
  });
208
- }
209
161
 
210
- // ============================================================================
211
- // Parameterized Type Validation
212
- // ============================================================================
162
+ if (result.familyMismatch) {
163
+ throw runtimeError(
164
+ 'RUNTIME.CONTRACT_FAMILY_MISMATCH',
165
+ `Contract target family '${result.familyMismatch.actual}' does not match runtime family '${result.familyMismatch.expected}'.`,
166
+ {
167
+ actual: result.familyMismatch.actual,
168
+ expected: result.familyMismatch.expected,
169
+ },
170
+ );
171
+ }
172
+
173
+ if (result.targetMismatch) {
174
+ throw runtimeError(
175
+ 'RUNTIME.CONTRACT_TARGET_MISMATCH',
176
+ `Contract target '${result.targetMismatch.actual}' does not match runtime target descriptor '${result.targetMismatch.expected}'.`,
177
+ {
178
+ actual: result.targetMismatch.actual,
179
+ expected: result.targetMismatch.expected,
180
+ },
181
+ );
182
+ }
183
+
184
+ if (result.missingExtensionPackIds.length > 0) {
185
+ const packIds = result.missingExtensionPackIds;
186
+ const packList = packIds.map((id) => `'${id}'`).join(', ');
187
+ throw runtimeError(
188
+ 'RUNTIME.MISSING_EXTENSION_PACK',
189
+ `Contract requires extension pack(s) ${packList}, but runtime descriptors do not provide matching component(s).`,
190
+ { packIds },
191
+ );
192
+ }
193
+ }
213
194
 
214
- /**
215
- * Validates typeParams against the codec's paramsSchema.
216
- * @throws RuntimeError with code RUNTIME.TYPE_PARAMS_INVALID if validation fails
217
- */
218
195
  function validateTypeParams(
219
196
  typeParams: Record<string, unknown>,
220
197
  codecDescriptor: RuntimeParameterizedCodecDescriptor,
@@ -226,7 +203,8 @@ function validateTypeParams(
226
203
  const locationInfo = context.typeName
227
204
  ? `type '${context.typeName}'`
228
205
  : `column '${context.tableName}.${context.columnName}'`;
229
- throw runtimeTypeParamsInvalid(
206
+ throw runtimeError(
207
+ 'RUNTIME.TYPE_PARAMS_INVALID',
230
208
  `Invalid typeParams for ${locationInfo} (codecId: ${codecDescriptor.codecId}): ${messages}`,
231
209
  { ...context, codecId: codecDescriptor.codecId, typeParams },
232
210
  );
@@ -234,43 +212,27 @@ function validateTypeParams(
234
212
  return result as Record<string, unknown>;
235
213
  }
236
214
 
237
- /**
238
- * Collects parameterized codec descriptors from extension instances.
239
- * Returns a map of codecId → descriptor for quick lookup.
240
- */
241
215
  function collectParameterizedCodecDescriptors(
242
- extensionInstances: ReadonlyArray<SqlRuntimeExtensionInstance<string>>,
216
+ contributors: ReadonlyArray<SqlStaticContributions>,
243
217
  ): Map<string, RuntimeParameterizedCodecDescriptor> {
244
218
  const descriptors = new Map<string, RuntimeParameterizedCodecDescriptor>();
245
219
 
246
- for (const extInstance of extensionInstances) {
247
- const paramCodecs = extInstance.parameterizedCodecs?.();
248
- if (paramCodecs) {
249
- for (const descriptor of paramCodecs) {
250
- if (descriptors.has(descriptor.codecId)) {
251
- console.warn(
252
- `Duplicate parameterized codec descriptor for codecId '${descriptor.codecId}' - using later registration`,
253
- );
254
- }
255
- descriptors.set(descriptor.codecId, descriptor);
220
+ for (const contributor of contributors) {
221
+ for (const descriptor of contributor.parameterizedCodecs()) {
222
+ if (descriptors.has(descriptor.codecId)) {
223
+ throw runtimeError(
224
+ 'RUNTIME.DUPLICATE_PARAMETERIZED_CODEC',
225
+ `Duplicate parameterized codec descriptor for codecId '${descriptor.codecId}'.`,
226
+ { codecId: descriptor.codecId },
227
+ );
256
228
  }
229
+ descriptors.set(descriptor.codecId, descriptor);
257
230
  }
258
231
  }
259
232
 
260
233
  return descriptors;
261
234
  }
262
235
 
263
- /**
264
- * Initializes type helpers from storage.types using codec descriptors.
265
- *
266
- * For each named type instance in `storage.types`:
267
- * - If a codec descriptor exists with an `init` hook: calls the hook and stores the result
268
- * - Otherwise: stores the full type instance metadata directly (codecId, nativeType, typeParams)
269
- *
270
- * This matches the typing in `ExtractSchemaTypes<Contract>` which extracts
271
- * `Contract['storage']['types']` directly, ensuring runtime values match static types
272
- * when no init hook transforms the value.
273
- */
274
236
  function initializeTypeHelpers(
275
237
  storageTypes: Record<string, StorageTypeInstance> | undefined,
276
238
  codecDescriptors: Map<string, RuntimeParameterizedCodecDescriptor>,
@@ -285,20 +247,16 @@ function initializeTypeHelpers(
285
247
  const descriptor = codecDescriptors.get(typeInstance.codecId);
286
248
 
287
249
  if (descriptor) {
288
- // Validate typeParams against the codec's schema
289
250
  const validatedParams = validateTypeParams(typeInstance.typeParams, descriptor, {
290
251
  typeName,
291
252
  });
292
253
 
293
- // Call init hook if provided, otherwise store full type instance
294
254
  if (descriptor.init) {
295
255
  helpers[typeName] = descriptor.init(validatedParams);
296
256
  } else {
297
- // No init hook: expose full type instance metadata (matches contract typing)
298
257
  helpers[typeName] = typeInstance;
299
258
  }
300
259
  } else {
301
- // No descriptor found: expose full type instance (no validation possible)
302
260
  helpers[typeName] = typeInstance;
303
261
  }
304
262
  }
@@ -306,10 +264,6 @@ function initializeTypeHelpers(
306
264
  return helpers;
307
265
  }
308
266
 
309
- /**
310
- * Validates inline column typeParams across all tables.
311
- * @throws RuntimeError with code RUNTIME.TYPE_PARAMS_INVALID if validation fails
312
- */
313
267
  function validateColumnTypeParams(
314
268
  storage: SqlStorage,
315
269
  codecDescriptors: Map<string, RuntimeParameterizedCodecDescriptor>,
@@ -327,76 +281,163 @@ function validateColumnTypeParams(
327
281
  }
328
282
 
329
283
  /**
330
- * Creates a SQL runtime context from descriptor-first composition.
284
+ * Builds a registry of compiled JSON Schema validators by scanning the contract
285
+ * for columns whose codec descriptor provides an `init` hook returning `{ validate }`.
331
286
  *
332
- * The context includes:
333
- * - The validated contract
334
- * - The adapter instance (created from descriptor)
335
- * - Codec registry (populated from adapter + extension instances)
336
- * - Operation registry (populated from extension instances)
337
- * - Types registry (initialized helpers from storage.types)
338
- *
339
- * @param options - Descriptor-first composition options
340
- * @returns RuntimeContext with registries wired from all components
287
+ * Handles both:
288
+ * - Inline `typeParams.schema` on columns
289
+ * - `typeRef` `storage.types[ref]` with init hook results already in `types` registry
341
290
  */
342
- export function createRuntimeContext<
343
- TContract extends SqlContract<SqlStorage> = SqlContract<SqlStorage>,
344
- TTargetId extends string = string,
345
- >(options: CreateRuntimeContextOptions<TContract, TTargetId>): RuntimeContext<TContract> {
346
- const { contract, adapter: adapterDescriptor, extensionPacks } = options;
291
+ function buildJsonSchemaValidatorRegistry(
292
+ contract: SqlContract<SqlStorage>,
293
+ types: TypeHelperRegistry,
294
+ codecDescriptors: Map<string, RuntimeParameterizedCodecDescriptor>,
295
+ ): JsonSchemaValidatorRegistry | undefined {
296
+ const validators = new Map<string, JsonSchemaValidateFn>();
297
+
298
+ // Collect codec IDs that have init hooks (these produce { validate } helpers)
299
+ const codecIdsWithInit = new Set<string>();
300
+ for (const [codecId, descriptor] of codecDescriptors) {
301
+ if (descriptor.init) {
302
+ codecIdsWithInit.add(codecId);
303
+ }
304
+ }
347
305
 
348
- // Create adapter instance from descriptor
349
- // The adapter instance IS an Adapter (via intersection)
350
- const adapterInstance = adapterDescriptor.create();
306
+ if (codecIdsWithInit.size === 0) {
307
+ return undefined;
308
+ }
351
309
 
352
- // Create registries
353
- const codecRegistry = createCodecRegistry();
354
- const operationRegistry = createOperationRegistry();
310
+ for (const [tableName, table] of Object.entries(contract.storage.tables)) {
311
+ for (const [columnName, column] of Object.entries(table.columns)) {
312
+ if (!codecIdsWithInit.has(column.codecId)) continue;
313
+
314
+ const key = `${tableName}.${columnName}`;
315
+
316
+ // Case 1: column references a named type → validator already compiled via init hook
317
+ if (column.typeRef) {
318
+ const helper = types[column.typeRef] as { validate?: JsonSchemaValidateFn } | undefined;
319
+ if (helper?.validate) {
320
+ validators.set(key, helper.validate);
321
+ }
322
+ continue;
323
+ }
324
+
325
+ // Case 2: inline typeParams with schema → compile via init hook
326
+ if (column.typeParams) {
327
+ const descriptor = codecDescriptors.get(column.codecId);
328
+ if (descriptor?.init) {
329
+ const helper = descriptor.init(column.typeParams) as
330
+ | { validate?: JsonSchemaValidateFn }
331
+ | undefined;
332
+ if (helper?.validate) {
333
+ validators.set(key, helper.validate);
334
+ }
335
+ }
336
+ }
337
+ }
338
+ }
339
+
340
+ if (validators.size === 0) return undefined;
341
+ return {
342
+ get: (key: string) => validators.get(key),
343
+ size: validators.size,
344
+ };
345
+ }
355
346
 
356
- // Register adapter codecs (adapter instance has profile.codecs())
357
- const adapterCodecs = adapterInstance.profile.codecs();
358
- for (const codec of adapterCodecs.values()) {
359
- codecRegistry.register(codec);
347
+ function computeExecutionDefaultValue(spec: ExecutionMutationDefaultValue): unknown {
348
+ switch (spec.kind) {
349
+ case 'generator':
350
+ return generateId(spec.params ? { id: spec.id, params: spec.params } : { id: spec.id });
360
351
  }
352
+ }
361
353
 
362
- // Create extension instances and collect their contributions
363
- const extensionInstances: SqlRuntimeExtensionInstance<TTargetId>[] = [];
354
+ function applyMutationDefaults(
355
+ contract: SqlContract<SqlStorage>,
356
+ options: MutationDefaultsOptions,
357
+ ): ReadonlyArray<AppliedMutationDefault> {
358
+ const defaults = contract.execution?.mutations.defaults ?? [];
359
+ if (defaults.length === 0) {
360
+ return [];
361
+ }
364
362
 
365
- for (const extDescriptor of extensionPacks ?? []) {
366
- const extInstance = extDescriptor.create();
367
- extensionInstances.push(extInstance);
363
+ const applied: AppliedMutationDefault[] = [];
364
+ const appliedColumns = new Set<string>();
368
365
 
369
- const extCodecs = extInstance.codecs?.();
370
- if (extCodecs) {
371
- for (const codec of extCodecs.values()) {
372
- codecRegistry.register(codec);
373
- }
366
+ for (const mutationDefault of defaults) {
367
+ if (mutationDefault.ref.table !== options.table) {
368
+ continue;
374
369
  }
375
370
 
376
- const extOperations = extInstance.operations?.();
377
- if (extOperations) {
378
- for (const operation of extOperations) {
379
- operationRegistry.register(operation);
380
- }
371
+ const defaultSpec =
372
+ options.op === 'create' ? mutationDefault.onCreate : mutationDefault.onUpdate;
373
+ if (!defaultSpec) {
374
+ continue;
375
+ }
376
+
377
+ const columnName = mutationDefault.ref.column;
378
+ if (Object.hasOwn(options.values, columnName) || appliedColumns.has(columnName)) {
379
+ continue;
380
+ }
381
+
382
+ applied.push({
383
+ column: columnName,
384
+ value: computeExecutionDefaultValue(defaultSpec),
385
+ });
386
+ appliedColumns.add(columnName);
387
+ }
388
+
389
+ return applied;
390
+ }
391
+
392
+ export function createExecutionContext<
393
+ TContract extends SqlContract<SqlStorage> = SqlContract<SqlStorage>,
394
+ TTargetId extends string = string,
395
+ >(options: {
396
+ readonly contract: TContract;
397
+ readonly stack: SqlExecutionStack<TTargetId>;
398
+ }): ExecutionContext<TContract> {
399
+ const { contract, stack } = options;
400
+
401
+ assertExecutionStackContractRequirements(contract, stack);
402
+
403
+ const codecRegistry = createCodecRegistry();
404
+ const operationRegistry = createOperationRegistry();
405
+
406
+ const contributors: SqlStaticContributions[] = [
407
+ stack.target,
408
+ stack.adapter,
409
+ ...stack.extensionPacks,
410
+ ];
411
+
412
+ for (const contributor of contributors) {
413
+ for (const c of contributor.codecs().values()) {
414
+ codecRegistry.register(c);
415
+ }
416
+ for (const operation of contributor.operationSignatures()) {
417
+ operationRegistry.register(operation);
381
418
  }
382
419
  }
383
420
 
384
- // Collect parameterized codec descriptors from extensions
385
- const parameterizedCodecDescriptors = collectParameterizedCodecDescriptors(extensionInstances);
421
+ const parameterizedCodecDescriptors = collectParameterizedCodecDescriptors(contributors);
386
422
 
387
- // Validate column typeParams if any descriptors are registered
388
423
  if (parameterizedCodecDescriptors.size > 0) {
389
424
  validateColumnTypeParams(contract.storage, parameterizedCodecDescriptors);
390
425
  }
391
426
 
392
- // Initialize type helpers from storage.types
393
427
  const types = initializeTypeHelpers(contract.storage.types, parameterizedCodecDescriptors);
394
428
 
429
+ const jsonSchemaValidators = buildJsonSchemaValidatorRegistry(
430
+ contract,
431
+ types,
432
+ parameterizedCodecDescriptors,
433
+ );
434
+
395
435
  return {
396
436
  contract,
397
- adapter: adapterInstance,
398
437
  operations: operationRegistry,
399
438
  codecs: codecRegistry,
400
439
  types,
440
+ ...(jsonSchemaValidators ? { jsonSchemaValidators } : {}),
441
+ applyMutationDefaults: (options) => applyMutationDefaults(contract, options),
401
442
  };
402
443
  }