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

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
@@ -33,11 +33,15 @@ export class SqlFamilyAdapter<TContract extends SqlContract<SqlStorage>>
33
33
  });
34
34
  }
35
35
 
36
- if (plan.meta.coreHash !== contract.coreHash) {
37
- throw runtimeError('PLAN.HASH_MISMATCH', 'Plan core hash does not match runtime contract', {
38
- planCoreHash: plan.meta.coreHash,
39
- runtimeCoreHash: contract.coreHash,
40
- });
36
+ if (plan.meta.storageHash !== contract.storageHash) {
37
+ throw runtimeError(
38
+ 'PLAN.HASH_MISMATCH',
39
+ 'Plan storage hash does not match runtime contract',
40
+ {
41
+ planStorageHash: plan.meta.storageHash,
42
+ runtimeStorageHash: contract.storageHash,
43
+ },
44
+ );
41
45
  }
42
46
  }
43
47
  }
package/src/sql-marker.ts CHANGED
@@ -6,7 +6,7 @@ export interface SqlStatement {
6
6
  }
7
7
 
8
8
  export interface WriteMarkerInput {
9
- readonly coreHash: string;
9
+ readonly storageHash: string;
10
10
  readonly profileHash: string;
11
11
  readonly contractJson?: unknown;
12
12
  readonly canonicalVersion?: number;
@@ -57,7 +57,7 @@ export interface WriteContractMarkerStatements {
57
57
  export function writeContractMarker(input: WriteMarkerInput): WriteContractMarkerStatements {
58
58
  const baseParams: readonly unknown[] = [
59
59
  1,
60
- input.coreHash,
60
+ input.storageHash,
61
61
  input.profileHash,
62
62
  input.contractJson ?? null,
63
63
  input.canonicalVersion ?? null,
@@ -1,4 +1,6 @@
1
1
  import type { ExecutionPlan } from '@prisma-next/contract/types';
2
+ import type { ExecutionStackInstance } from '@prisma-next/core-execution-plane/stack';
3
+ import type { RuntimeDriverInstance } from '@prisma-next/core-execution-plane/types';
2
4
  import type { OperationRegistry } from '@prisma-next/operations';
3
5
  import type {
4
6
  Log,
@@ -15,41 +17,86 @@ import type {
15
17
  Adapter,
16
18
  CodecRegistry,
17
19
  LoweredStatement,
20
+ QueryAst,
18
21
  SelectAst,
19
22
  SqlDriver,
20
23
  } from '@prisma-next/sql-relational-core/ast';
21
24
  import type { SqlQueryPlan } from '@prisma-next/sql-relational-core/plan';
25
+ import type { JsonSchemaValidatorRegistry } from '@prisma-next/sql-relational-core/query-lane-context';
26
+ import { ifDefined } from '@prisma-next/utils/defined';
22
27
  import { decodeRow } from './codecs/decoding';
23
28
  import { encodeParams } from './codecs/encoding';
24
29
  import { validateCodecRegistryCompleteness } from './codecs/validation';
25
30
  import { lowerSqlPlan } from './lower-sql-plan';
26
- import type { RuntimeContext } from './sql-context';
31
+ import type {
32
+ ExecutionContext,
33
+ SqlRuntimeAdapterInstance,
34
+ SqlRuntimeExtensionInstance,
35
+ } from './sql-context';
27
36
  import { SqlFamilyAdapter } from './sql-family-adapter';
28
37
 
29
38
  export interface RuntimeOptions<
30
39
  TContract extends SqlContract<SqlStorage> = SqlContract<SqlStorage>,
31
40
  > {
32
- readonly driver: SqlDriver;
41
+ readonly context: ExecutionContext<TContract>;
42
+ readonly adapter: Adapter<QueryAst, SqlContract<SqlStorage>, LoweredStatement>;
43
+ readonly driver: SqlDriver<unknown>;
33
44
  readonly verify: RuntimeVerifyOptions;
34
- readonly context: RuntimeContext<TContract>;
35
45
  readonly plugins?: readonly Plugin<
36
46
  TContract,
37
47
  Adapter<SelectAst, SqlContract<SqlStorage>, LoweredStatement>,
38
- SqlDriver
48
+ SqlDriver<unknown>
39
49
  >[];
40
50
  readonly mode?: 'strict' | 'permissive';
41
51
  readonly log?: Log;
42
52
  }
43
53
 
44
- export interface Runtime {
45
- execute<Row = Record<string, unknown>>(
46
- plan: ExecutionPlan<Row> | SqlQueryPlan<Row>,
47
- ): AsyncIterableResult<Row>;
54
+ export interface CreateRuntimeOptions<
55
+ TContract extends SqlContract<SqlStorage> = SqlContract<SqlStorage>,
56
+ TTargetId extends string = string,
57
+ > {
58
+ readonly stackInstance: ExecutionStackInstance<
59
+ 'sql',
60
+ TTargetId,
61
+ SqlRuntimeAdapterInstance<TTargetId>,
62
+ RuntimeDriverInstance<'sql', TTargetId>,
63
+ SqlRuntimeExtensionInstance<TTargetId>
64
+ >;
65
+ readonly context: ExecutionContext<TContract>;
66
+ readonly driver: SqlDriver<unknown>;
67
+ readonly verify: RuntimeVerifyOptions;
68
+ readonly plugins?: readonly Plugin<
69
+ TContract,
70
+ Adapter<SelectAst, SqlContract<SqlStorage>, LoweredStatement>,
71
+ SqlDriver<unknown>
72
+ >[];
73
+ readonly mode?: 'strict' | 'permissive';
74
+ readonly log?: Log;
75
+ }
76
+
77
+ export interface Runtime extends RuntimeQueryable {
78
+ connection(): Promise<RuntimeConnection>;
48
79
  telemetry(): RuntimeTelemetryEvent | null;
49
80
  close(): Promise<void>;
50
81
  operations(): OperationRegistry;
51
82
  }
52
83
 
84
+ export interface RuntimeConnection extends RuntimeQueryable {
85
+ transaction(): Promise<RuntimeTransaction>;
86
+ release(): Promise<void>;
87
+ }
88
+
89
+ export interface RuntimeTransaction extends RuntimeQueryable {
90
+ commit(): Promise<void>;
91
+ rollback(): Promise<void>;
92
+ }
93
+
94
+ export interface RuntimeQueryable {
95
+ execute<Row = Record<string, unknown>>(
96
+ plan: ExecutionPlan<Row> | SqlQueryPlan<Row>,
97
+ ): AsyncIterableResult<Row>;
98
+ }
99
+
53
100
  export type { RuntimeTelemetryEvent, RuntimeVerifyOptions, TelemetryOutcome };
54
101
 
55
102
  class SqlRuntimeImpl<TContract extends SqlContract<SqlStorage> = SqlContract<SqlStorage>>
@@ -58,18 +105,20 @@ class SqlRuntimeImpl<TContract extends SqlContract<SqlStorage> = SqlContract<Sql
58
105
  private readonly core: RuntimeCore<
59
106
  TContract,
60
107
  Adapter<SelectAst, SqlContract<SqlStorage>, LoweredStatement>,
61
- SqlDriver
108
+ SqlDriver<unknown>
62
109
  >;
63
110
  private readonly contract: TContract;
64
- private readonly context: RuntimeContext<TContract>;
111
+ private readonly adapter: Adapter<QueryAst, SqlContract<SqlStorage>, LoweredStatement>;
65
112
  private readonly codecRegistry: CodecRegistry;
113
+ private readonly jsonSchemaValidators: JsonSchemaValidatorRegistry | undefined;
66
114
  private codecRegistryValidated: boolean;
67
115
 
68
116
  constructor(options: RuntimeOptions<TContract>) {
69
- const { context, driver, verify, plugins, mode, log } = options;
117
+ const { context, adapter, driver, verify, plugins, mode, log } = options;
70
118
  this.contract = context.contract;
71
- this.context = context;
119
+ this.adapter = adapter;
72
120
  this.codecRegistry = context.codecs;
121
+ this.jsonSchemaValidators = context.jsonSchemaValidators;
73
122
  this.codecRegistryValidated = false;
74
123
 
75
124
  const familyAdapter = new SqlFamilyAdapter(context.contract);
@@ -77,7 +126,7 @@ class SqlRuntimeImpl<TContract extends SqlContract<SqlStorage> = SqlContract<Sql
77
126
  const coreOptions: RuntimeCoreOptions<
78
127
  TContract,
79
128
  Adapter<SelectAst, SqlContract<SqlStorage>, LoweredStatement>,
80
- SqlDriver
129
+ SqlDriver<unknown>
81
130
  > = {
82
131
  familyAdapter,
83
132
  driver,
@@ -85,10 +134,10 @@ class SqlRuntimeImpl<TContract extends SqlContract<SqlStorage> = SqlContract<Sql
85
134
  plugins: plugins as readonly Plugin<
86
135
  TContract,
87
136
  Adapter<SelectAst, SqlContract<SqlStorage>, LoweredStatement>,
88
- SqlDriver
137
+ SqlDriver<unknown>
89
138
  >[],
90
- ...(mode !== undefined ? { mode } : {}),
91
- ...(log !== undefined ? { log } : {}),
139
+ ...ifDefined('mode', mode),
140
+ ...ifDefined('log', log),
92
141
  operationRegistry: context.operations,
93
142
  };
94
143
 
@@ -112,20 +161,22 @@ class SqlRuntimeImpl<TContract extends SqlContract<SqlStorage> = SqlContract<Sql
112
161
  ): AsyncIterableResult<Row> {
113
162
  this.ensureCodecRegistryValidated(this.contract);
114
163
 
115
- // Check if plan is SqlQueryPlan (has ast but no sql)
116
164
  const isSqlQueryPlan = (p: ExecutionPlan<Row> | SqlQueryPlan<Row>): p is SqlQueryPlan<Row> => {
117
165
  return 'ast' in p && !('sql' in p);
118
166
  };
119
167
 
120
- // Lower SqlQueryPlan to Plan if needed
121
168
  const executablePlan: ExecutionPlan<Row> = isSqlQueryPlan(plan)
122
- ? lowerSqlPlan(this.context, plan)
169
+ ? lowerSqlPlan(this.adapter, this.contract, plan)
123
170
  : plan;
124
171
 
125
172
  const iterator = async function* (
126
173
  self: SqlRuntimeImpl<TContract>,
127
174
  ): AsyncGenerator<Row, void, unknown> {
128
- const encodedParams = encodeParams(executablePlan, self.codecRegistry);
175
+ const encodedParams = encodeParams(
176
+ executablePlan,
177
+ self.codecRegistry,
178
+ self.jsonSchemaValidators,
179
+ );
129
180
  const planWithEncodedParams: ExecutionPlan<Row> = {
130
181
  ...executablePlan,
131
182
  params: encodedParams,
@@ -138,6 +189,7 @@ class SqlRuntimeImpl<TContract extends SqlContract<SqlStorage> = SqlContract<Sql
138
189
  rawRow as Record<string, unknown>,
139
190
  executablePlan,
140
191
  self.codecRegistry,
192
+ self.jsonSchemaValidators,
141
193
  );
142
194
  yield decodedRow as Row;
143
195
  }
@@ -146,6 +198,10 @@ class SqlRuntimeImpl<TContract extends SqlContract<SqlStorage> = SqlContract<Sql
146
198
  return new AsyncIterableResult(iterator(this));
147
199
  }
148
200
 
201
+ connection(): Promise<RuntimeConnection> {
202
+ return this.core.connection();
203
+ }
204
+
149
205
  telemetry(): RuntimeTelemetryEvent | null {
150
206
  return this.core.telemetry();
151
207
  }
@@ -159,8 +215,18 @@ class SqlRuntimeImpl<TContract extends SqlContract<SqlStorage> = SqlContract<Sql
159
215
  }
160
216
  }
161
217
 
162
- export function createRuntime<TContract extends SqlContract<SqlStorage>>(
163
- options: RuntimeOptions<TContract>,
218
+ export function createRuntime<TContract extends SqlContract<SqlStorage>, TTargetId extends string>(
219
+ options: CreateRuntimeOptions<TContract, TTargetId>,
164
220
  ): Runtime {
165
- return new SqlRuntimeImpl(options);
221
+ const { stackInstance, context, driver, verify, plugins, mode, log } = options;
222
+
223
+ return new SqlRuntimeImpl({
224
+ context,
225
+ adapter: stackInstance.adapter,
226
+ driver,
227
+ verify,
228
+ ...ifDefined('plugins', plugins),
229
+ ...ifDefined('mode', mode),
230
+ ...ifDefined('log', log),
231
+ });
166
232
  }
@@ -1,10 +1,17 @@
1
1
  import type { ExecutionPlan } from '@prisma-next/contract/types';
2
+ import { instantiateExecutionStack } from '@prisma-next/core-execution-plane/stack';
2
3
  import type { AsyncIterableResult } from '@prisma-next/runtime-executor';
3
4
  import { describe, expect, it } from 'vitest';
4
- import { createRuntime } from '../src/exports';
5
- import { createStubAdapter, createTestContext, createTestContract } from './utils';
5
+ import type { Runtime } from '../src/exports';
6
+ import { createRuntime, createSqlExecutionStack } from '../src/exports';
7
+ import {
8
+ createStubAdapter,
9
+ createTestAdapterDescriptor,
10
+ createTestContext,
11
+ createTestContract,
12
+ createTestTargetDescriptor,
13
+ } from './utils';
6
14
 
7
- // Mock driver that implements SqlDriver interface
8
15
  class MockDriver {
9
16
  private rows: ReadonlyArray<Record<string, unknown>> = [];
10
17
 
@@ -12,11 +19,10 @@ class MockDriver {
12
19
  this.rows = rows;
13
20
  }
14
21
 
15
- async query(
22
+ async query<Row = Record<string, unknown>>(
16
23
  _sql: string,
17
- _params: readonly unknown[],
18
- ): Promise<{ rows: ReadonlyArray<unknown> }> {
19
- // Return empty marker result for contract verification
24
+ _params?: readonly unknown[],
25
+ ): Promise<{ rows: ReadonlyArray<Row> }> {
20
26
  return { rows: [] };
21
27
  }
22
28
 
@@ -29,20 +35,20 @@ class MockDriver {
29
35
  }
30
36
  }
31
37
 
32
- async connect(): Promise<void> {
33
- // No-op
38
+ async acquireConnection(): Promise<never> {
39
+ throw new Error('Not implemented in mock');
34
40
  }
35
41
 
36
- async close(): Promise<void> {
37
- // No-op
38
- }
42
+ async connect(): Promise<void> {}
43
+
44
+ async close(): Promise<void> {}
39
45
  }
40
46
 
41
47
  const fixtureContract = createTestContract({
42
48
  schemaVersion: '1',
43
49
  targetFamily: 'sql',
44
50
  target: 'postgres',
45
- coreHash: 'test-hash',
51
+ storageHash: 'test-hash',
46
52
  profileHash: 'test-profile-hash',
47
53
  storage: {
48
54
  tables: {
@@ -62,20 +68,31 @@ const fixtureContract = createTestContract({
62
68
  mappings: { codecTypes: {}, operationTypes: {} },
63
69
  });
64
70
 
71
+ function createTestRuntime(mockDriver: MockDriver): Runtime {
72
+ const adapter = createStubAdapter();
73
+ const stack = createSqlExecutionStack({
74
+ target: createTestTargetDescriptor(),
75
+ adapter: createTestAdapterDescriptor(adapter),
76
+ extensionPacks: [],
77
+ });
78
+ const stackInstance = instantiateExecutionStack(stack);
79
+ const context = createTestContext(fixtureContract, adapter);
80
+ return createRuntime({
81
+ stackInstance,
82
+ context,
83
+ driver: mockDriver,
84
+ verify: { mode: 'onFirstUse', requireMarker: false },
85
+ });
86
+ }
87
+
65
88
  describe('SqlRuntime AsyncIterableResult integration', () => {
66
89
  it('returns AsyncIterableResult from execute', async () => {
67
- const adapter = createStubAdapter();
68
90
  const driver = new MockDriver();
69
91
  driver.setRows([
70
92
  { id: 1, email: 'test1@example.com' },
71
93
  { id: 2, email: 'test2@example.com' },
72
94
  ]);
73
- const context = createTestContext(fixtureContract, adapter);
74
- const runtime = createRuntime({
75
- driver: driver as unknown as Parameters<typeof createRuntime>[0]['driver'],
76
- context,
77
- verify: { mode: 'onFirstUse', requireMarker: false },
78
- });
95
+ const runtime = createTestRuntime(driver);
79
96
 
80
97
  const plan: ExecutionPlan<{ id: number; email: string }> = {
81
98
  sql: 'SELECT id, email FROM "user" ORDER BY id',
@@ -83,7 +100,7 @@ describe('SqlRuntime AsyncIterableResult integration', () => {
83
100
  meta: {
84
101
  target: 'postgres',
85
102
  targetFamily: 'sql',
86
- coreHash: 'test-hash',
103
+ storageHash: 'test-hash',
87
104
  lane: 'sql',
88
105
  paramDescriptors: [],
89
106
  },
@@ -91,7 +108,6 @@ describe('SqlRuntime AsyncIterableResult integration', () => {
91
108
 
92
109
  const result = runtime.execute(plan);
93
110
 
94
- // Verify it's an AsyncIterableResult
95
111
  expect(result).toBeInstanceOf(Object);
96
112
  expect(typeof result.toArray).toBe('function');
97
113
  expect(typeof result[Symbol.asyncIterator]).toBe('function');
@@ -100,15 +116,9 @@ describe('SqlRuntime AsyncIterableResult integration', () => {
100
116
  });
101
117
 
102
118
  it('preserves type information', async () => {
103
- const adapter = createStubAdapter();
104
119
  const driver = new MockDriver();
105
120
  driver.setRows([{ id: 1, email: 'test@example.com' }]);
106
- const context = createTestContext(fixtureContract, adapter);
107
- const runtime = createRuntime({
108
- driver: driver as unknown as Parameters<typeof createRuntime>[0]['driver'],
109
- context,
110
- verify: { mode: 'onFirstUse', requireMarker: false },
111
- });
121
+ const runtime = createTestRuntime(driver);
112
122
 
113
123
  const plan: ExecutionPlan<{ id: number; email: string }> = {
114
124
  sql: 'SELECT id, email FROM "user" LIMIT 1',
@@ -116,7 +126,7 @@ describe('SqlRuntime AsyncIterableResult integration', () => {
116
126
  meta: {
117
127
  target: 'postgres',
118
128
  targetFamily: 'sql',
119
- coreHash: 'test-hash',
129
+ storageHash: 'test-hash',
120
130
  lane: 'sql',
121
131
  paramDescriptors: [],
122
132
  },
@@ -126,10 +136,8 @@ describe('SqlRuntime AsyncIterableResult integration', () => {
126
136
  const rows = await result.toArray();
127
137
 
128
138
  expect(rows.length).toBe(1);
129
- if (rows[0]) {
130
- expect(typeof rows[0].id).toBe('number');
131
- expect(typeof rows[0].email).toBe('string');
132
- }
139
+ expect(typeof rows[0]!.id).toBe('number');
140
+ expect(typeof rows[0]!.email).toBe('string');
133
141
 
134
142
  await runtime.close();
135
143
  });
@@ -1,6 +1,6 @@
1
1
  import type { SqlContract, SqlMappings, SqlStorage } from '@prisma-next/sql-contract/types';
2
2
  import { expectTypeOf, test } from 'vitest';
3
- import type { RuntimeContext, TypeHelperRegistry } from '../src/sql-context';
3
+ import type { ExecutionContext, TypeHelperRegistry } from '../src/sql-context';
4
4
 
5
5
  // Contract type with storage.types using literal types (matching emission output)
6
6
  type TestContract = SqlContract<
@@ -33,23 +33,21 @@ type TestContract = SqlContract<
33
33
  SqlMappings
34
34
  >;
35
35
 
36
- test('RuntimeContext.types is TypeHelperRegistry', () => {
37
- // RuntimeContext.types is intentionally loose (Record<string, unknown>)
36
+ test('ExecutionContext.types is TypeHelperRegistry', () => {
37
+ // ExecutionContext.types is intentionally loose (Record<string, unknown>)
38
38
  // The strong typing comes from schema(context).types via ExtractSchemaTypes
39
- expectTypeOf<RuntimeContext<TestContract>['types']>().toEqualTypeOf<
40
- TypeHelperRegistry | undefined
41
- >();
39
+ expectTypeOf<ExecutionContext<TestContract>['types']>().toEqualTypeOf<TypeHelperRegistry>();
42
40
 
43
41
  // TypeHelperRegistry allows any values - the actual type depends on init hooks
44
42
  expectTypeOf<TypeHelperRegistry>().toEqualTypeOf<Record<string, unknown>>();
45
43
  });
46
44
 
47
- test('RuntimeContext preserves contract type parameter', () => {
48
- // Verify the contract type is preserved in RuntimeContext
49
- expectTypeOf<RuntimeContext<TestContract>['contract']>().toEqualTypeOf<TestContract>();
45
+ test('ExecutionContext preserves contract type parameter', () => {
46
+ // Verify the contract type is preserved in ExecutionContext
47
+ expectTypeOf<ExecutionContext<TestContract>['contract']>().toEqualTypeOf<TestContract>();
50
48
 
51
49
  // Verify we can access storage.types through the context's contract
52
- type ContractStorageTypes = RuntimeContext<TestContract>['contract']['storage']['types'];
50
+ type ContractStorageTypes = ExecutionContext<TestContract>['contract']['storage']['types'];
53
51
  expectTypeOf<ContractStorageTypes>().toExtend<
54
52
  | {
55
53
  readonly Vector1536: {
@@ -62,9 +60,9 @@ test('RuntimeContext preserves contract type parameter', () => {
62
60
  >();
63
61
  });
64
62
 
65
- test('RuntimeContext accepts generic SqlContract', () => {
66
- // Verify RuntimeContext defaults work
67
- type DefaultContext = RuntimeContext;
63
+ test('ExecutionContext accepts generic SqlContract', () => {
64
+ // Verify ExecutionContext defaults work
65
+ type DefaultContext = ExecutionContext;
68
66
  expectTypeOf<DefaultContext['contract']>().toExtend<SqlContract<SqlStorage>>();
69
- expectTypeOf<DefaultContext['types']>().toEqualTypeOf<TypeHelperRegistry | undefined>();
67
+ expectTypeOf<DefaultContext['types']>().toEqualTypeOf<TypeHelperRegistry>();
70
68
  });
@@ -0,0 +1,166 @@
1
+ import { createExecutionStack } from '@prisma-next/core-execution-plane/stack';
2
+ import { codec, createCodecRegistry } from '@prisma-next/sql-relational-core/ast';
3
+ import { describe, expect, it } from 'vitest';
4
+ import { createExecutionContext, createSqlExecutionStack } from '../src/exports';
5
+ import type {
6
+ ExecutionContext,
7
+ SqlRuntimeAdapterDescriptor,
8
+ SqlRuntimeExtensionDescriptor,
9
+ SqlRuntimeTargetDescriptor,
10
+ } from '../src/sql-context';
11
+ import { createTestContract } from './utils';
12
+
13
+ function createStubAdapterDescriptor(): SqlRuntimeAdapterDescriptor<'postgres'> {
14
+ const registry = createCodecRegistry();
15
+ registry.register(
16
+ codec({
17
+ typeId: 'pg/text@1',
18
+ targetTypes: ['text'],
19
+ encode: (value: string) => value,
20
+ decode: (wire: string) => wire,
21
+ }),
22
+ );
23
+
24
+ return {
25
+ kind: 'adapter',
26
+ id: 'test-adapter',
27
+ version: '0.0.1',
28
+ familyId: 'sql' as const,
29
+ targetId: 'postgres' as const,
30
+ codecs: () => registry,
31
+ operationSignatures: () => [],
32
+ parameterizedCodecs: () => [],
33
+ create() {
34
+ return Object.assign(
35
+ { familyId: 'sql' as const, targetId: 'postgres' as const },
36
+ {
37
+ profile: {
38
+ id: 'test-profile',
39
+ target: 'postgres',
40
+ capabilities: {},
41
+ codecs: () => registry,
42
+ },
43
+ lower() {
44
+ return {
45
+ profileId: 'test-profile',
46
+ body: Object.freeze({ sql: '', params: [] }),
47
+ };
48
+ },
49
+ },
50
+ );
51
+ },
52
+ };
53
+ }
54
+
55
+ function createStubTargetDescriptor(): SqlRuntimeTargetDescriptor<'postgres'> {
56
+ return {
57
+ kind: 'target',
58
+ id: 'postgres',
59
+ version: '0.0.1',
60
+ familyId: 'sql' as const,
61
+ targetId: 'postgres' as const,
62
+ codecs: () => createCodecRegistry(),
63
+ operationSignatures: () => [],
64
+ parameterizedCodecs: () => [],
65
+ create() {
66
+ return { familyId: 'sql' as const, targetId: 'postgres' as const };
67
+ },
68
+ };
69
+ }
70
+
71
+ function createStubExtensionDescriptor(): SqlRuntimeExtensionDescriptor<'postgres'> {
72
+ const registry = createCodecRegistry();
73
+ registry.register(
74
+ codec({
75
+ typeId: 'pg/uuid@1',
76
+ targetTypes: ['uuid'],
77
+ encode: (value: string) => value,
78
+ decode: (wire: string) => wire,
79
+ }),
80
+ );
81
+
82
+ const operations = [
83
+ {
84
+ forTypeId: 'pg/text@1',
85
+ method: 'example',
86
+ args: [],
87
+ returns: { kind: 'builtin' as const, type: 'string' as const },
88
+ lowering: {
89
+ targetFamily: 'sql' as const,
90
+ strategy: 'function' as const,
91
+ template: 'example({args})',
92
+ },
93
+ },
94
+ ];
95
+
96
+ return {
97
+ kind: 'extension',
98
+ id: 'test-extension',
99
+ version: '0.0.1',
100
+ familyId: 'sql' as const,
101
+ targetId: 'postgres' as const,
102
+ codecs: () => registry,
103
+ operationSignatures: () => operations,
104
+ parameterizedCodecs: () => [],
105
+ create() {
106
+ return {
107
+ familyId: 'sql' as const,
108
+ targetId: 'postgres' as const,
109
+ };
110
+ },
111
+ };
112
+ }
113
+
114
+ describe('createExecutionStack', () => {
115
+ it('defaults driver to undefined and extensions to empty', () => {
116
+ const stack = createExecutionStack({
117
+ target: createStubTargetDescriptor(),
118
+ adapter: createStubAdapterDescriptor(),
119
+ });
120
+
121
+ expect(stack.driver).toBeUndefined();
122
+ expect(stack.extensionPacks).toEqual([]);
123
+ });
124
+
125
+ it('creates an execution context from descriptors-only stack', () => {
126
+ const contract = createTestContract({
127
+ storage: { tables: {} },
128
+ });
129
+
130
+ const context = createExecutionContext({
131
+ contract,
132
+ stack: {
133
+ target: createStubTargetDescriptor(),
134
+ adapter: createStubAdapterDescriptor(),
135
+ extensionPacks: [createStubExtensionDescriptor()],
136
+ },
137
+ }) as ExecutionContext<typeof contract>;
138
+
139
+ expect(context.contract).toBe(contract);
140
+ expect(context.codecs.get('pg/text@1')).toBeDefined();
141
+ expect(context.codecs.get('pg/uuid@1')).toBeDefined();
142
+ expect(context.operations.byType('pg/text@1')).toHaveLength(1);
143
+ expect(context.types).toEqual({});
144
+ });
145
+ });
146
+
147
+ describe('createSqlExecutionStack', () => {
148
+ it('preserves descriptor references and defaults extensions', () => {
149
+ const target = createStubTargetDescriptor();
150
+ const adapter = createStubAdapterDescriptor();
151
+ const stack = createSqlExecutionStack({ target, adapter });
152
+
153
+ expect(stack.target).toBe(target);
154
+ expect(stack.adapter).toBe(adapter);
155
+ expect(stack.extensionPacks).toEqual([]);
156
+ });
157
+
158
+ it('keeps extension packs intact', () => {
159
+ const target = createStubTargetDescriptor();
160
+ const adapter = createStubAdapterDescriptor();
161
+ const extension = createStubExtensionDescriptor();
162
+ const stack = createSqlExecutionStack({ target, adapter, extensionPacks: [extension] });
163
+
164
+ expect(stack.extensionPacks).toEqual([extension]);
165
+ });
166
+ });