@prisma-next/sql-runtime 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 (169) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +141 -24
  3. package/dist/exports-BKjZvwMh.mjs +971 -0
  4. package/dist/exports-BKjZvwMh.mjs.map +1 -0
  5. package/dist/index-eHiENgIB.d.mts +182 -0
  6. package/dist/index-eHiENgIB.d.mts.map +1 -0
  7. package/dist/index.d.mts +2 -0
  8. package/dist/index.mjs +3 -0
  9. package/dist/test/utils.d.mts +82 -0
  10. package/dist/test/utils.d.mts.map +1 -0
  11. package/dist/test/utils.mjs +221 -0
  12. package/dist/test/utils.mjs.map +1 -0
  13. package/package.json +29 -22
  14. package/src/codecs/decoding.ts +84 -3
  15. package/src/codecs/encoding.ts +5 -15
  16. package/src/codecs/json-schema-validation.ts +61 -0
  17. package/src/exports/index.ts +19 -7
  18. package/src/lower-sql-plan.ts +8 -8
  19. package/src/plugins/budgets.ts +375 -0
  20. package/src/plugins/lints.ts +211 -0
  21. package/src/sql-context.ts +448 -98
  22. package/src/sql-family-adapter.ts +9 -5
  23. package/src/sql-marker.ts +2 -2
  24. package/src/sql-runtime.ts +126 -30
  25. package/test/async-iterable-result.test.ts +43 -35
  26. package/test/budgets.test.ts +481 -0
  27. package/test/context.types.test-d.ts +68 -0
  28. package/test/execution-stack.test.ts +166 -0
  29. package/test/json-schema-validation.test.ts +575 -0
  30. package/test/lints.test.ts +161 -0
  31. package/test/mutation-default-generators.test.ts +256 -0
  32. package/test/parameterized-types.test.ts +536 -0
  33. package/test/sql-context.test.ts +293 -121
  34. package/test/sql-family-adapter.test.ts +8 -10
  35. package/test/sql-runtime.test.ts +219 -34
  36. package/test/utils.ts +90 -51
  37. package/dist/accelerate-EEKAFGN3-P6A6XJWJ.js +0 -137863
  38. package/dist/accelerate-EEKAFGN3-P6A6XJWJ.js.map +0 -1
  39. package/dist/amcheck-24VY6X5V.js +0 -13
  40. package/dist/amcheck-24VY6X5V.js.map +0 -1
  41. package/dist/bloom-VS74NLHT.js +0 -13
  42. package/dist/bloom-VS74NLHT.js.map +0 -1
  43. package/dist/btree_gin-WBC4EAAI.js +0 -13
  44. package/dist/btree_gin-WBC4EAAI.js.map +0 -1
  45. package/dist/btree_gist-UNC6QD3M.js +0 -13
  46. package/dist/btree_gist-UNC6QD3M.js.map +0 -1
  47. package/dist/chunk-3KTOEDFX.js +0 -49
  48. package/dist/chunk-3KTOEDFX.js.map +0 -1
  49. package/dist/chunk-47DZBRQC.js +0 -1280
  50. package/dist/chunk-47DZBRQC.js.map +0 -1
  51. package/dist/chunk-52N6AFZM.js +0 -133
  52. package/dist/chunk-52N6AFZM.js.map +0 -1
  53. package/dist/chunk-7D4SUZUM.js +0 -38
  54. package/dist/chunk-7D4SUZUM.js.map +0 -1
  55. package/dist/chunk-C6I3V3DM.js +0 -455
  56. package/dist/chunk-C6I3V3DM.js.map +0 -1
  57. package/dist/chunk-ECWIHLAT.js +0 -37
  58. package/dist/chunk-ECWIHLAT.js.map +0 -1
  59. package/dist/chunk-EI626SDC.js +0 -105
  60. package/dist/chunk-EI626SDC.js.map +0 -1
  61. package/dist/chunk-UKKOYUGL.js +0 -578
  62. package/dist/chunk-UKKOYUGL.js.map +0 -1
  63. package/dist/chunk-XPLNMXQV.js +0 -1537
  64. package/dist/chunk-XPLNMXQV.js.map +0 -1
  65. package/dist/citext-T7MXGUY7.js +0 -13
  66. package/dist/citext-T7MXGUY7.js.map +0 -1
  67. package/dist/client-5FENX6AW.js +0 -299
  68. package/dist/client-5FENX6AW.js.map +0 -1
  69. package/dist/cube-TFDQBZCI.js +0 -13
  70. package/dist/cube-TFDQBZCI.js.map +0 -1
  71. package/dist/dict_int-AEUOPGWP.js +0 -13
  72. package/dist/dict_int-AEUOPGWP.js.map +0 -1
  73. package/dist/dict_xsyn-DAAYX3FL.js +0 -13
  74. package/dist/dict_xsyn-DAAYX3FL.js.map +0 -1
  75. package/dist/dist-AQ3LWXOX.js +0 -570
  76. package/dist/dist-AQ3LWXOX.js.map +0 -1
  77. package/dist/dist-LBVX6BJW.js +0 -189
  78. package/dist/dist-LBVX6BJW.js.map +0 -1
  79. package/dist/dist-WLKUVDN2.js +0 -5127
  80. package/dist/dist-WLKUVDN2.js.map +0 -1
  81. package/dist/earthdistance-KIGTF4LE.js +0 -13
  82. package/dist/earthdistance-KIGTF4LE.js.map +0 -1
  83. package/dist/file_fdw-5N55UP6I.js +0 -13
  84. package/dist/file_fdw-5N55UP6I.js.map +0 -1
  85. package/dist/fuzzystrmatch-KN3YWBFP.js +0 -13
  86. package/dist/fuzzystrmatch-KN3YWBFP.js.map +0 -1
  87. package/dist/hstore-YX726NKN.js +0 -13
  88. package/dist/hstore-YX726NKN.js.map +0 -1
  89. package/dist/http-exception-FZY2H4OF.js +0 -8
  90. package/dist/http-exception-FZY2H4OF.js.map +0 -1
  91. package/dist/index.js +0 -30
  92. package/dist/index.js.map +0 -1
  93. package/dist/intarray-NKVXNO2D.js +0 -13
  94. package/dist/intarray-NKVXNO2D.js.map +0 -1
  95. package/dist/isn-FTEMJGEV.js +0 -13
  96. package/dist/isn-FTEMJGEV.js.map +0 -1
  97. package/dist/lo-DB7L4NGI.js +0 -13
  98. package/dist/lo-DB7L4NGI.js.map +0 -1
  99. package/dist/logger-WQ7SHNDD.js +0 -68
  100. package/dist/logger-WQ7SHNDD.js.map +0 -1
  101. package/dist/ltree-Z32TZT6W.js +0 -13
  102. package/dist/ltree-Z32TZT6W.js.map +0 -1
  103. package/dist/nodefs-NM46ACH7.js +0 -31
  104. package/dist/nodefs-NM46ACH7.js.map +0 -1
  105. package/dist/opfs-ahp-NJO33LVZ.js +0 -332
  106. package/dist/opfs-ahp-NJO33LVZ.js.map +0 -1
  107. package/dist/pageinspect-YP3IZR4X.js +0 -13
  108. package/dist/pageinspect-YP3IZR4X.js.map +0 -1
  109. package/dist/pg_buffercache-7TD5J2FB.js +0 -13
  110. package/dist/pg_buffercache-7TD5J2FB.js.map +0 -1
  111. package/dist/pg_dump-SG4KYBUB.js +0 -2492
  112. package/dist/pg_dump-SG4KYBUB.js.map +0 -1
  113. package/dist/pg_freespacemap-DZDNCPZK.js +0 -13
  114. package/dist/pg_freespacemap-DZDNCPZK.js.map +0 -1
  115. package/dist/pg_surgery-J2MUEWEP.js +0 -13
  116. package/dist/pg_surgery-J2MUEWEP.js.map +0 -1
  117. package/dist/pg_trgm-7VNQOYS6.js +0 -13
  118. package/dist/pg_trgm-7VNQOYS6.js.map +0 -1
  119. package/dist/pg_visibility-TTSIPHFL.js +0 -13
  120. package/dist/pg_visibility-TTSIPHFL.js.map +0 -1
  121. package/dist/pg_walinspect-KPFHSHRJ.js +0 -13
  122. package/dist/pg_walinspect-KPFHSHRJ.js.map +0 -1
  123. package/dist/proxy-signals-GUDAMDHV.js +0 -39
  124. package/dist/proxy-signals-GUDAMDHV.js.map +0 -1
  125. package/dist/seg-IYVDLE4O.js +0 -13
  126. package/dist/seg-IYVDLE4O.js.map +0 -1
  127. package/dist/src/codecs/decoding.d.ts +0 -4
  128. package/dist/src/codecs/decoding.d.ts.map +0 -1
  129. package/dist/src/codecs/encoding.d.ts +0 -5
  130. package/dist/src/codecs/encoding.d.ts.map +0 -1
  131. package/dist/src/codecs/validation.d.ts +0 -6
  132. package/dist/src/codecs/validation.d.ts.map +0 -1
  133. package/dist/src/exports/index.d.ts +0 -11
  134. package/dist/src/exports/index.d.ts.map +0 -1
  135. package/dist/src/index.d.ts +0 -2
  136. package/dist/src/index.d.ts.map +0 -1
  137. package/dist/src/lower-sql-plan.d.ts +0 -15
  138. package/dist/src/lower-sql-plan.d.ts.map +0 -1
  139. package/dist/src/sql-context.d.ts +0 -65
  140. package/dist/src/sql-context.d.ts.map +0 -1
  141. package/dist/src/sql-family-adapter.d.ts +0 -10
  142. package/dist/src/sql-family-adapter.d.ts.map +0 -1
  143. package/dist/src/sql-marker.d.ts +0 -22
  144. package/dist/src/sql-marker.d.ts.map +0 -1
  145. package/dist/src/sql-runtime.d.ts +0 -25
  146. package/dist/src/sql-runtime.d.ts.map +0 -1
  147. package/dist/tablefunc-EF4RCS7S.js +0 -13
  148. package/dist/tablefunc-EF4RCS7S.js.map +0 -1
  149. package/dist/tcn-3VT5BQYW.js +0 -13
  150. package/dist/tcn-3VT5BQYW.js.map +0 -1
  151. package/dist/test/utils.d.ts +0 -59
  152. package/dist/test/utils.d.ts.map +0 -1
  153. package/dist/test/utils.js +0 -24634
  154. package/dist/test/utils.js.map +0 -1
  155. package/dist/tiny-CW6F4GX6.js +0 -10
  156. package/dist/tiny-CW6F4GX6.js.map +0 -1
  157. package/dist/tsm_system_rows-ES7KNUQH.js +0 -13
  158. package/dist/tsm_system_rows-ES7KNUQH.js.map +0 -1
  159. package/dist/tsm_system_time-76WEIMBG.js +0 -13
  160. package/dist/tsm_system_time-76WEIMBG.js.map +0 -1
  161. package/dist/unaccent-7RYF3R64.js +0 -13
  162. package/dist/unaccent-7RYF3R64.js.map +0 -1
  163. package/dist/utility-Q5A254LJ-J4HTKZPT.js +0 -347
  164. package/dist/utility-Q5A254LJ-J4HTKZPT.js.map +0 -1
  165. package/dist/uuid_ossp-4ETE4FPE.js +0 -13
  166. package/dist/uuid_ossp-4ETE4FPE.js.map +0 -1
  167. package/dist/vector-74GPNV7V.js +0 -13
  168. package/dist/vector-74GPNV7V.js.map +0 -1
  169. package/src/index.ts +0 -1
@@ -1,4 +1,10 @@
1
- import { createOperationRegistry } from '@prisma-next/operations';
1
+ import { coreHash, type ExecutionPlan } from '@prisma-next/contract/types';
2
+ import type { ExecutionStackInstance } from '@prisma-next/core-execution-plane/stack';
3
+ import { instantiateExecutionStack } from '@prisma-next/core-execution-plane/stack';
4
+ import type {
5
+ RuntimeDriverInstance,
6
+ RuntimeExtensionInstance,
7
+ } from '@prisma-next/core-execution-plane/types';
2
8
  import type { SqlContract, SqlStorage } from '@prisma-next/sql-contract/types';
3
9
  import type {
4
10
  CodecRegistry,
@@ -8,15 +14,19 @@ import type {
8
14
  } from '@prisma-next/sql-relational-core/ast';
9
15
  import { codec, createCodecRegistry } from '@prisma-next/sql-relational-core/ast';
10
16
  import { describe, expect, it, vi } from 'vitest';
11
- import type { RuntimeContext } from '../src/sql-context';
17
+ import type {
18
+ SqlRuntimeAdapterDescriptor,
19
+ SqlRuntimeAdapterInstance,
20
+ SqlRuntimeTargetDescriptor,
21
+ } from '../src/sql-context';
22
+ import { createExecutionContext, createSqlExecutionStack } from '../src/sql-context';
12
23
  import { createRuntime } from '../src/sql-runtime';
13
24
 
14
- // Minimal test contract
15
25
  const testContract: SqlContract<SqlStorage> = {
16
26
  schemaVersion: '1',
17
27
  targetFamily: 'sql',
18
28
  target: 'postgres',
19
- coreHash: 'sha256:test',
29
+ storageHash: coreHash('sha256:test'),
20
30
  models: {},
21
31
  relations: {},
22
32
  storage: { tables: {} },
@@ -24,13 +34,17 @@ const testContract: SqlContract<SqlStorage> = {
24
34
  capabilities: {},
25
35
  meta: {},
26
36
  sources: {},
27
- mappings: {
28
- codecTypes: {},
29
- operationTypes: {},
30
- },
37
+ mappings: {},
31
38
  };
32
39
 
33
- // Create a stub codec registry
40
+ interface DriverExecuteSpies {
41
+ rootExecute: ReturnType<typeof vi.fn>;
42
+ connectionExecute: ReturnType<typeof vi.fn>;
43
+ transactionExecute: ReturnType<typeof vi.fn>;
44
+ }
45
+
46
+ type MockSqlDriver = SqlDriver & { __spies: DriverExecuteSpies };
47
+
34
48
  function createStubCodecs(): CodecRegistry {
35
49
  const registry = createCodecRegistry();
36
50
  registry.register(
@@ -44,7 +58,6 @@ function createStubCodecs(): CodecRegistry {
44
58
  return registry;
45
59
  }
46
60
 
47
- // Create a stub adapter
48
61
  function createStubAdapter() {
49
62
  const codecs = createStubCodecs();
50
63
  return {
@@ -67,37 +80,141 @@ function createStubAdapter() {
67
80
  };
68
81
  }
69
82
 
70
- // Create a mock driver that implements SqlDriver interface
71
- function createMockDriver(): SqlDriver {
72
- const execute = vi.fn().mockImplementation(async function* (_request: SqlExecuteRequest) {
83
+ function createMockDriver(): MockSqlDriver {
84
+ const rootExecute = vi.fn().mockImplementation(async function* (_request: SqlExecuteRequest) {
73
85
  yield { id: 1 };
74
86
  });
87
+ const connectionExecute = vi.fn().mockImplementation(async function* (
88
+ _request: SqlExecuteRequest,
89
+ ) {
90
+ yield { id: 2 };
91
+ });
92
+ const transactionExecute = vi.fn().mockImplementation(async function* (
93
+ _request: SqlExecuteRequest,
94
+ ) {
95
+ yield { id: 3 };
96
+ });
75
97
 
76
- return {
77
- connect: vi.fn().mockResolvedValue(undefined),
78
- execute,
79
- query: vi.fn().mockResolvedValue({ rows: [], rowCount: 0 }),
98
+ const query = vi.fn().mockResolvedValue({ rows: [], rowCount: 0 });
99
+
100
+ const transaction = {
101
+ execute: transactionExecute,
102
+ query,
103
+ commit: vi.fn().mockResolvedValue(undefined),
104
+ rollback: vi.fn().mockResolvedValue(undefined),
105
+ };
106
+
107
+ const connection = {
108
+ execute: connectionExecute,
109
+ query,
110
+ release: vi.fn().mockResolvedValue(undefined),
111
+ beginTransaction: vi.fn().mockResolvedValue(transaction),
112
+ };
113
+
114
+ const driver: SqlDriver = {
115
+ execute: rootExecute,
116
+ query,
117
+ connect: vi.fn().mockImplementation(async (_binding?: undefined) => undefined),
118
+ acquireConnection: vi.fn().mockResolvedValue(connection),
80
119
  close: vi.fn().mockResolvedValue(undefined),
81
120
  };
121
+
122
+ return Object.assign(driver, {
123
+ __spies: {
124
+ rootExecute,
125
+ connectionExecute,
126
+ transactionExecute,
127
+ },
128
+ });
82
129
  }
83
130
 
84
- // Create a test runtime context
85
- function createTestContext(contract: SqlContract<SqlStorage>): RuntimeContext<typeof contract> {
131
+ function createTestTargetDescriptor(): SqlRuntimeTargetDescriptor<'postgres'> {
132
+ return {
133
+ kind: 'target',
134
+ id: 'postgres',
135
+ version: '0.0.1',
136
+ familyId: 'sql' as const,
137
+ targetId: 'postgres' as const,
138
+ codecs: () => createCodecRegistry(),
139
+ operationSignatures: () => [],
140
+ parameterizedCodecs: () => [],
141
+ create() {
142
+ return { familyId: 'sql' as const, targetId: 'postgres' as const };
143
+ },
144
+ };
145
+ }
146
+
147
+ function createTestAdapterDescriptor(
148
+ adapter: ReturnType<typeof createStubAdapter>,
149
+ ): SqlRuntimeAdapterDescriptor<'postgres'> {
150
+ const codecRegistry = adapter.profile.codecs();
151
+ return {
152
+ kind: 'adapter',
153
+ id: 'test-adapter',
154
+ version: '0.0.1',
155
+ familyId: 'sql' as const,
156
+ targetId: 'postgres' as const,
157
+ codecs: () => codecRegistry,
158
+ operationSignatures: () => [],
159
+ parameterizedCodecs: () => [],
160
+ create() {
161
+ return Object.assign(
162
+ { familyId: 'sql' as const, targetId: 'postgres' as const },
163
+ adapter,
164
+ ) as SqlRuntimeAdapterInstance<'postgres'>;
165
+ },
166
+ };
167
+ }
168
+
169
+ function createTestSetup() {
86
170
  const adapter = createStubAdapter();
171
+ const driver = createMockDriver();
172
+
173
+ const targetDescriptor = createTestTargetDescriptor();
174
+ const adapterDescriptor = createTestAdapterDescriptor(adapter);
175
+
176
+ const stack = createSqlExecutionStack({
177
+ target: targetDescriptor,
178
+ adapter: adapterDescriptor,
179
+ extensionPacks: [],
180
+ });
181
+ type SqlTestStackInstance = ExecutionStackInstance<
182
+ 'sql',
183
+ 'postgres',
184
+ SqlRuntimeAdapterInstance<'postgres'>,
185
+ RuntimeDriverInstance<'sql', 'postgres'>,
186
+ RuntimeExtensionInstance<'sql', 'postgres'>
187
+ >;
188
+ const stackInstance = instantiateExecutionStack(stack) as SqlTestStackInstance;
189
+
190
+ const context = createExecutionContext({
191
+ contract: testContract,
192
+ stack: { target: targetDescriptor, adapter: adapterDescriptor, extensionPacks: [] },
193
+ });
194
+
195
+ return { stackInstance, context, driver };
196
+ }
197
+
198
+ function createRawExecutionPlan<Row = Record<string, unknown>>(): ExecutionPlan<Row> {
87
199
  return {
88
- contract,
89
- adapter,
90
- codecs: adapter.profile.codecs(),
91
- operations: createOperationRegistry(),
200
+ sql: 'select 1',
201
+ params: [],
202
+ meta: {
203
+ target: testContract.target,
204
+ targetFamily: testContract.targetFamily,
205
+ storageHash: testContract.storageHash,
206
+ lane: 'raw',
207
+ paramDescriptors: [],
208
+ },
92
209
  };
93
210
  }
94
211
 
95
212
  describe('createRuntime', () => {
96
- it('creates runtime with valid options', () => {
97
- const context = createTestContext(testContract);
98
- const driver = createMockDriver();
213
+ it('creates runtime with context and driver', () => {
214
+ const { stackInstance, context, driver } = createTestSetup();
99
215
 
100
216
  const runtime = createRuntime({
217
+ stackInstance,
101
218
  context,
102
219
  driver,
103
220
  verify: { mode: 'onFirstUse', requireMarker: false },
@@ -111,10 +228,10 @@ describe('createRuntime', () => {
111
228
  });
112
229
 
113
230
  it('returns operations registry', () => {
114
- const context = createTestContext(testContract);
115
- const driver = createMockDriver();
231
+ const { stackInstance, context, driver } = createTestSetup();
116
232
 
117
233
  const runtime = createRuntime({
234
+ stackInstance,
118
235
  context,
119
236
  driver,
120
237
  verify: { mode: 'onFirstUse', requireMarker: false },
@@ -126,24 +243,23 @@ describe('createRuntime', () => {
126
243
  });
127
244
 
128
245
  it('returns null telemetry when no events', () => {
129
- const context = createTestContext(testContract);
130
- const driver = createMockDriver();
246
+ const { stackInstance, context, driver } = createTestSetup();
131
247
 
132
248
  const runtime = createRuntime({
249
+ stackInstance,
133
250
  context,
134
251
  driver,
135
252
  verify: { mode: 'onFirstUse', requireMarker: false },
136
253
  });
137
254
 
138
- // Before any execution, telemetry should be null
139
255
  expect(runtime.telemetry()).toBeNull();
140
256
  });
141
257
 
142
- it('closes runtime', async () => {
143
- const context = createTestContext(testContract);
144
- const driver = createMockDriver();
258
+ it('closes runtime and driver', async () => {
259
+ const { stackInstance, context, driver } = createTestSetup();
145
260
 
146
261
  const runtime = createRuntime({
262
+ stackInstance,
147
263
  context,
148
264
  driver,
149
265
  verify: { mode: 'onFirstUse', requireMarker: false },
@@ -152,4 +268,73 @@ describe('createRuntime', () => {
152
268
  await runtime.close();
153
269
  expect(driver.close).toHaveBeenCalled();
154
270
  });
271
+
272
+ it('validates codec registry at startup when verify mode is startup', () => {
273
+ const { stackInstance, context, driver } = createTestSetup();
274
+
275
+ const runtime = createRuntime({
276
+ stackInstance,
277
+ context,
278
+ driver,
279
+ verify: { mode: 'startup', requireMarker: false },
280
+ });
281
+
282
+ expect(runtime).toBeDefined();
283
+ });
284
+
285
+ it('uses acquired connection queryable for connection.execute', async () => {
286
+ const { stackInstance, context, driver } = createTestSetup();
287
+ const runtime = createRuntime({
288
+ stackInstance,
289
+ context,
290
+ driver,
291
+ verify: { mode: 'onFirstUse', requireMarker: false },
292
+ });
293
+
294
+ const connection = await runtime.connection();
295
+ await connection.execute(createRawExecutionPlan()).toArray();
296
+
297
+ expect(driver.__spies.connectionExecute).toHaveBeenCalledTimes(1);
298
+ expect(driver.__spies.transactionExecute).not.toHaveBeenCalled();
299
+ expect(driver.__spies.rootExecute).not.toHaveBeenCalled();
300
+
301
+ await connection.release();
302
+ });
303
+
304
+ it('uses transaction queryable for transaction.execute', async () => {
305
+ const { stackInstance, context, driver } = createTestSetup();
306
+ const runtime = createRuntime({
307
+ stackInstance,
308
+ context,
309
+ driver,
310
+ verify: { mode: 'onFirstUse', requireMarker: false },
311
+ });
312
+
313
+ const connection = await runtime.connection();
314
+ const transaction = await connection.transaction();
315
+ await transaction.execute(createRawExecutionPlan()).toArray();
316
+
317
+ expect(driver.__spies.transactionExecute).toHaveBeenCalledTimes(1);
318
+ expect(driver.__spies.connectionExecute).not.toHaveBeenCalled();
319
+ expect(driver.__spies.rootExecute).not.toHaveBeenCalled();
320
+
321
+ await transaction.rollback();
322
+ await connection.release();
323
+ });
324
+
325
+ it('keeps root execute on driver queryable for runtime.execute', async () => {
326
+ const { stackInstance, context, driver } = createTestSetup();
327
+ const runtime = createRuntime({
328
+ stackInstance,
329
+ context,
330
+ driver,
331
+ verify: { mode: 'onFirstUse', requireMarker: false },
332
+ });
333
+
334
+ await runtime.execute(createRawExecutionPlan()).toArray();
335
+
336
+ expect(driver.__spies.rootExecute).toHaveBeenCalledTimes(1);
337
+ expect(driver.__spies.connectionExecute).not.toHaveBeenCalled();
338
+ expect(driver.__spies.transactionExecute).not.toHaveBeenCalled();
339
+ });
155
340
  });
package/test/utils.ts CHANGED
@@ -1,4 +1,9 @@
1
1
  import type { ExecutionPlan, ResultType } from '@prisma-next/contract/types';
2
+ import { coreHash, profileHash } from '@prisma-next/contract/types';
3
+ import { instantiateExecutionStack } from '@prisma-next/core-execution-plane/stack';
4
+ import type { RuntimeDriverDescriptor } from '@prisma-next/core-execution-plane/types';
5
+ import { builtinGeneratorIds } from '@prisma-next/ids';
6
+ import { generateId } from '@prisma-next/ids/runtime';
2
7
  import type { SqlContract, SqlStorage } from '@prisma-next/sql-contract/types';
3
8
  import type { Adapter, LoweredStatement, SelectAst } from '@prisma-next/sql-relational-core/ast';
4
9
  import { codec, createCodecRegistry } from '@prisma-next/sql-relational-core/ast';
@@ -7,18 +12,29 @@ import { collectAsync, drainAsyncIterable } from '@prisma-next/test-utils';
7
12
  import type { Client } from 'pg';
8
13
  import type { SqlStatement } from '../src/exports';
9
14
  import {
15
+ createExecutionContext,
10
16
  type createRuntime,
11
- createRuntimeContext,
17
+ createSqlExecutionStack,
12
18
  ensureSchemaStatement,
13
19
  ensureTableStatement,
14
20
  writeContractMarker,
15
21
  } from '../src/exports';
16
22
  import type {
17
- RuntimeContext,
23
+ ExecutionContext,
24
+ SqlRuntimeAdapterDescriptor,
18
25
  SqlRuntimeAdapterInstance,
26
+ SqlRuntimeDriverInstance,
19
27
  SqlRuntimeExtensionDescriptor,
28
+ SqlRuntimeTargetDescriptor,
20
29
  } from '../src/sql-context';
21
30
 
31
+ function createTestMutationDefaultGenerators() {
32
+ return builtinGeneratorIds.map((id) => ({
33
+ id,
34
+ generate: (params?: Record<string, unknown>) => generateId(params ? { id, params } : { id }),
35
+ }));
36
+ }
37
+
22
38
  /**
23
39
  * Executes a plan and collects all results into an array.
24
40
  * This helper DRYs up the common pattern of executing plans in tests.
@@ -71,8 +87,8 @@ export async function setupTestDatabase(
71
87
  await executeStatement(client, ensureSchemaStatement);
72
88
  await executeStatement(client, ensureTableStatement);
73
89
  const write = writeContractMarker({
74
- coreHash: contract.coreHash,
75
- profileHash: contract.profileHash ?? contract.coreHash,
90
+ storageHash: contract.storageHash,
91
+ profileHash: contract.profileHash ?? contract.storageHash,
76
92
  contractJson: contract,
77
93
  canonicalVersion: 1,
78
94
  });
@@ -88,8 +104,8 @@ export async function writeTestContractMarker(
88
104
  contract: SqlContract<SqlStorage>,
89
105
  ): Promise<void> {
90
106
  const write = writeContractMarker({
91
- coreHash: contract.coreHash,
92
- profileHash: contract.profileHash ?? contract.coreHash,
107
+ storageHash: contract.storageHash,
108
+ profileHash: contract.profileHash ?? contract.storageHash,
93
109
  contractJson: contract,
94
110
  canonicalVersion: 1,
95
111
  });
@@ -98,56 +114,42 @@ export async function writeTestContractMarker(
98
114
 
99
115
  /**
100
116
  * Creates a test adapter descriptor from a raw adapter.
101
- * This wraps the adapter in a descriptor for descriptor-first context creation in tests.
102
- * The adapter instance IS an Adapter (via intersection), with identity properties added.
117
+ * Wraps the adapter in an SqlRuntimeAdapterDescriptor with static contributions
118
+ * derived from the adapter's codec registry.
103
119
  */
104
- function createTestAdapterDescriptor(
120
+ export function createTestAdapterDescriptor(
105
121
  adapter: Adapter<SelectAst, SqlContract<SqlStorage>, LoweredStatement>,
106
- ): {
107
- readonly kind: 'adapter';
108
- readonly id: string;
109
- readonly version: string;
110
- readonly familyId: 'sql';
111
- readonly targetId: 'postgres';
112
- create(): SqlRuntimeAdapterInstance<'postgres'>;
113
- } {
122
+ ): SqlRuntimeAdapterDescriptor<'postgres'> {
123
+ const codecRegistry = adapter.profile.codecs();
114
124
  return {
115
125
  kind: 'adapter' as const,
116
126
  id: 'test-adapter',
117
127
  version: '0.0.1',
118
128
  familyId: 'sql' as const,
119
129
  targetId: 'postgres' as const,
130
+ codecs: () => codecRegistry,
131
+ operationSignatures: () => [],
132
+ parameterizedCodecs: () => [],
133
+ mutationDefaultGenerators: createTestMutationDefaultGenerators,
120
134
  create(): SqlRuntimeAdapterInstance<'postgres'> {
121
- // Return an object that combines identity properties with the adapter's methods
122
- return Object.assign(
123
- {
124
- familyId: 'sql' as const,
125
- targetId: 'postgres' as const,
126
- },
127
- adapter,
128
- );
135
+ return Object.assign({ familyId: 'sql' as const, targetId: 'postgres' as const }, adapter);
129
136
  },
130
137
  };
131
138
  }
132
139
 
133
140
  /**
134
- * Creates a test target descriptor.
135
- * This is a minimal descriptor for descriptor-first context creation in tests.
141
+ * Creates a test target descriptor with empty static contributions.
136
142
  */
137
- function createTestTargetDescriptor(): {
138
- readonly kind: 'target';
139
- readonly id: string;
140
- readonly version: string;
141
- readonly familyId: 'sql';
142
- readonly targetId: 'postgres';
143
- create(): { readonly familyId: 'sql'; readonly targetId: 'postgres' };
144
- } {
143
+ export function createTestTargetDescriptor(): SqlRuntimeTargetDescriptor<'postgres'> {
145
144
  return {
146
145
  kind: 'target' as const,
147
146
  id: 'postgres',
148
147
  version: '0.0.1',
149
148
  familyId: 'sql' as const,
150
149
  targetId: 'postgres' as const,
150
+ codecs: () => createCodecRegistry(),
151
+ operationSignatures: () => [],
152
+ parameterizedCodecs: () => [],
151
153
  create() {
152
154
  return { familyId: 'sql' as const, targetId: 'postgres' as const };
153
155
  },
@@ -155,7 +157,7 @@ function createTestTargetDescriptor(): {
155
157
  }
156
158
 
157
159
  /**
158
- * Creates a runtime context with standard test configuration.
160
+ * Creates an ExecutionContext for testing.
159
161
  * This helper DRYs up the common pattern of context creation in tests.
160
162
  *
161
163
  * Accepts a raw adapter and optional extension descriptors, wrapping the
@@ -167,13 +169,34 @@ export function createTestContext<TContract extends SqlContract<SqlStorage>>(
167
169
  options?: {
168
170
  extensionPacks?: ReadonlyArray<SqlRuntimeExtensionDescriptor<'postgres'>>;
169
171
  },
170
- ): RuntimeContext<TContract> {
171
- return createRuntimeContext<TContract, 'postgres'>({
172
+ ): ExecutionContext<TContract> {
173
+ return createExecutionContext({
172
174
  contract,
175
+ stack: {
176
+ target: createTestTargetDescriptor(),
177
+ adapter: createTestAdapterDescriptor(adapter),
178
+ extensionPacks: options?.extensionPacks ?? [],
179
+ },
180
+ });
181
+ }
182
+
183
+ export function createTestStackInstance(options?: {
184
+ extensionPacks?: ReadonlyArray<SqlRuntimeExtensionDescriptor<'postgres'>>;
185
+ driver?: RuntimeDriverDescriptor<
186
+ 'sql',
187
+ 'postgres',
188
+ unknown,
189
+ SqlRuntimeDriverInstance<'postgres'>
190
+ >;
191
+ }) {
192
+ const stack = createSqlExecutionStack({
173
193
  target: createTestTargetDescriptor(),
174
- adapter: createTestAdapterDescriptor(adapter),
194
+ adapter: createTestAdapterDescriptor(createStubAdapter()),
195
+ driver: options?.driver,
175
196
  extensionPacks: options?.extensionPacks ?? [],
176
197
  });
198
+
199
+ return instantiateExecutionStack(stack);
177
200
  }
178
201
 
179
202
  /**
@@ -212,8 +235,7 @@ export function createStubAdapter(): Adapter<SelectAst, SqlContract<SqlStorage>,
212
235
  typeId: 'pg/timestamptz@1',
213
236
  targetTypes: ['timestamptz'],
214
237
  encode: (value: string | Date) => (value instanceof Date ? value.toISOString() : value),
215
- decode: (wire: string | Date) =>
216
- typeof wire === 'string' ? wire : wire instanceof Date ? wire.toISOString() : String(wire),
238
+ decode: (wire: string | Date) => (wire instanceof Date ? wire : new Date(wire)),
217
239
  }),
218
240
  );
219
241
 
@@ -238,18 +260,35 @@ export function createStubAdapter(): Adapter<SelectAst, SqlContract<SqlStorage>,
238
260
 
239
261
  /**
240
262
  * Creates a valid test contract without using validateContract.
241
- * Ensures mappings are present and returns the contract with proper typing.
263
+ * Ensures all required fields are present (mappings, capabilities, extensionPacks, meta, sources)
264
+ * and returns the contract with proper typing.
242
265
  * This helper allows tests to create contracts without depending on sql-query.
243
266
  */
244
- export function createTestContract<T extends SqlContract<SqlStorage>>(contract: T): T {
245
- // Ensure mappings are present
246
- if (!contract.mappings) {
247
- return {
248
- ...contract,
249
- mappings: { codecTypes: {}, operationTypes: {} },
250
- } as T;
251
- }
252
- return contract;
267
+ export function createTestContract(
268
+ contract: Partial<Omit<SqlContract<SqlStorage>, 'storageHash' | 'profileHash'>> & {
269
+ storageHash?: string;
270
+ profileHash?: string;
271
+ },
272
+ ): SqlContract<SqlStorage> {
273
+ const { execution, ...rest } = contract;
274
+
275
+ return {
276
+ ...rest,
277
+ schemaVersion: rest.schemaVersion ?? '1',
278
+ target: rest.target ?? 'postgres',
279
+ targetFamily: rest.targetFamily ?? 'sql',
280
+ storage: rest.storage ?? { tables: {} },
281
+ models: rest.models ?? {},
282
+ relations: rest.relations ?? {},
283
+ mappings: rest.mappings ?? {},
284
+ capabilities: rest.capabilities ?? {},
285
+ extensionPacks: rest.extensionPacks ?? {},
286
+ meta: rest.meta ?? {},
287
+ sources: rest.sources ?? {},
288
+ ...(execution ? { execution } : {}),
289
+ storageHash: coreHash(rest.storageHash ?? 'sha256:testcore'),
290
+ profileHash: profileHash(rest.profileHash ?? 'sha256:testprofile'),
291
+ } satisfies SqlContract<SqlStorage>;
253
292
  }
254
293
 
255
294
  // Re-export generic utilities from test-utils