@prisma-next/sql-runtime 0.3.0-dev.4 → 0.3.0-dev.40

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 (144) hide show
  1. package/README.md +116 -26
  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 +35 -26
  13. package/src/codecs/decoding.ts +221 -0
  14. package/src/codecs/encoding.ts +89 -0
  15. package/src/codecs/json-schema-validation.ts +61 -0
  16. package/src/codecs/validation.ts +67 -0
  17. package/src/exports/index.ts +45 -0
  18. package/src/lower-sql-plan.ts +32 -0
  19. package/src/sql-context.ts +443 -0
  20. package/src/sql-family-adapter.ts +47 -0
  21. package/src/sql-marker.ts +105 -0
  22. package/src/sql-runtime.ts +232 -0
  23. package/test/async-iterable-result.test.ts +144 -0
  24. package/test/context.types.test-d.ts +68 -0
  25. package/test/execution-stack.test.ts +166 -0
  26. package/test/json-schema-validation.test.ts +653 -0
  27. package/test/parameterized-types.test.ts +539 -0
  28. package/test/sql-context.test.ts +392 -0
  29. package/test/sql-family-adapter.test.ts +87 -0
  30. package/test/sql-runtime.test.ts +241 -0
  31. package/test/utils.ts +292 -0
  32. package/dist/accelerate-EEKAFGN3-P6A6XJWJ.js +0 -137863
  33. package/dist/accelerate-EEKAFGN3-P6A6XJWJ.js.map +0 -1
  34. package/dist/amcheck-24VY6X5V.js +0 -13
  35. package/dist/amcheck-24VY6X5V.js.map +0 -1
  36. package/dist/bloom-VS74NLHT.js +0 -13
  37. package/dist/bloom-VS74NLHT.js.map +0 -1
  38. package/dist/btree_gin-WBC4EAAI.js +0 -13
  39. package/dist/btree_gin-WBC4EAAI.js.map +0 -1
  40. package/dist/btree_gist-UNC6QD3M.js +0 -13
  41. package/dist/btree_gist-UNC6QD3M.js.map +0 -1
  42. package/dist/chunk-3KTOEDFX.js +0 -49
  43. package/dist/chunk-3KTOEDFX.js.map +0 -1
  44. package/dist/chunk-47DZBRQC.js +0 -1280
  45. package/dist/chunk-47DZBRQC.js.map +0 -1
  46. package/dist/chunk-52N6AFZM.js +0 -133
  47. package/dist/chunk-52N6AFZM.js.map +0 -1
  48. package/dist/chunk-7D4SUZUM.js +0 -38
  49. package/dist/chunk-7D4SUZUM.js.map +0 -1
  50. package/dist/chunk-C6I3V3DM.js +0 -455
  51. package/dist/chunk-C6I3V3DM.js.map +0 -1
  52. package/dist/chunk-ECWIHLAT.js +0 -37
  53. package/dist/chunk-ECWIHLAT.js.map +0 -1
  54. package/dist/chunk-EI626SDC.js +0 -105
  55. package/dist/chunk-EI626SDC.js.map +0 -1
  56. package/dist/chunk-UKKOYUGL.js +0 -578
  57. package/dist/chunk-UKKOYUGL.js.map +0 -1
  58. package/dist/chunk-XPLNMXQV.js +0 -1537
  59. package/dist/chunk-XPLNMXQV.js.map +0 -1
  60. package/dist/citext-T7MXGUY7.js +0 -13
  61. package/dist/citext-T7MXGUY7.js.map +0 -1
  62. package/dist/client-5FENX6AW.js +0 -299
  63. package/dist/client-5FENX6AW.js.map +0 -1
  64. package/dist/cube-TFDQBZCI.js +0 -13
  65. package/dist/cube-TFDQBZCI.js.map +0 -1
  66. package/dist/dict_int-AEUOPGWP.js +0 -13
  67. package/dist/dict_int-AEUOPGWP.js.map +0 -1
  68. package/dist/dict_xsyn-DAAYX3FL.js +0 -13
  69. package/dist/dict_xsyn-DAAYX3FL.js.map +0 -1
  70. package/dist/dist-AQ3LWXOX.js +0 -570
  71. package/dist/dist-AQ3LWXOX.js.map +0 -1
  72. package/dist/dist-LBVX6BJW.js +0 -189
  73. package/dist/dist-LBVX6BJW.js.map +0 -1
  74. package/dist/dist-WLKUVDN2.js +0 -5127
  75. package/dist/dist-WLKUVDN2.js.map +0 -1
  76. package/dist/earthdistance-KIGTF4LE.js +0 -13
  77. package/dist/earthdistance-KIGTF4LE.js.map +0 -1
  78. package/dist/file_fdw-5N55UP6I.js +0 -13
  79. package/dist/file_fdw-5N55UP6I.js.map +0 -1
  80. package/dist/fuzzystrmatch-KN3YWBFP.js +0 -13
  81. package/dist/fuzzystrmatch-KN3YWBFP.js.map +0 -1
  82. package/dist/hstore-YX726NKN.js +0 -13
  83. package/dist/hstore-YX726NKN.js.map +0 -1
  84. package/dist/http-exception-FZY2H4OF.js +0 -8
  85. package/dist/http-exception-FZY2H4OF.js.map +0 -1
  86. package/dist/index.d.ts +0 -29
  87. package/dist/index.js +0 -30
  88. package/dist/index.js.map +0 -1
  89. package/dist/intarray-NKVXNO2D.js +0 -13
  90. package/dist/intarray-NKVXNO2D.js.map +0 -1
  91. package/dist/isn-FTEMJGEV.js +0 -13
  92. package/dist/isn-FTEMJGEV.js.map +0 -1
  93. package/dist/lo-DB7L4NGI.js +0 -13
  94. package/dist/lo-DB7L4NGI.js.map +0 -1
  95. package/dist/logger-WQ7SHNDD.js +0 -68
  96. package/dist/logger-WQ7SHNDD.js.map +0 -1
  97. package/dist/ltree-Z32TZT6W.js +0 -13
  98. package/dist/ltree-Z32TZT6W.js.map +0 -1
  99. package/dist/nodefs-NM46ACH7.js +0 -31
  100. package/dist/nodefs-NM46ACH7.js.map +0 -1
  101. package/dist/opfs-ahp-NJO33LVZ.js +0 -332
  102. package/dist/opfs-ahp-NJO33LVZ.js.map +0 -1
  103. package/dist/pageinspect-YP3IZR4X.js +0 -13
  104. package/dist/pageinspect-YP3IZR4X.js.map +0 -1
  105. package/dist/pg_buffercache-7TD5J2FB.js +0 -13
  106. package/dist/pg_buffercache-7TD5J2FB.js.map +0 -1
  107. package/dist/pg_dump-SG4KYBUB.js +0 -2492
  108. package/dist/pg_dump-SG4KYBUB.js.map +0 -1
  109. package/dist/pg_freespacemap-DZDNCPZK.js +0 -13
  110. package/dist/pg_freespacemap-DZDNCPZK.js.map +0 -1
  111. package/dist/pg_surgery-J2MUEWEP.js +0 -13
  112. package/dist/pg_surgery-J2MUEWEP.js.map +0 -1
  113. package/dist/pg_trgm-7VNQOYS6.js +0 -13
  114. package/dist/pg_trgm-7VNQOYS6.js.map +0 -1
  115. package/dist/pg_visibility-TTSIPHFL.js +0 -13
  116. package/dist/pg_visibility-TTSIPHFL.js.map +0 -1
  117. package/dist/pg_walinspect-KPFHSHRJ.js +0 -13
  118. package/dist/pg_walinspect-KPFHSHRJ.js.map +0 -1
  119. package/dist/proxy-signals-GUDAMDHV.js +0 -39
  120. package/dist/proxy-signals-GUDAMDHV.js.map +0 -1
  121. package/dist/seg-IYVDLE4O.js +0 -13
  122. package/dist/seg-IYVDLE4O.js.map +0 -1
  123. package/dist/sql-runtime-DgEbg2OP.d.ts +0 -109
  124. package/dist/tablefunc-EF4RCS7S.js +0 -13
  125. package/dist/tablefunc-EF4RCS7S.js.map +0 -1
  126. package/dist/tcn-3VT5BQYW.js +0 -13
  127. package/dist/tcn-3VT5BQYW.js.map +0 -1
  128. package/dist/test/utils.d.ts +0 -64
  129. package/dist/test/utils.js +0 -24634
  130. package/dist/test/utils.js.map +0 -1
  131. package/dist/tiny-CW6F4GX6.js +0 -10
  132. package/dist/tiny-CW6F4GX6.js.map +0 -1
  133. package/dist/tsm_system_rows-ES7KNUQH.js +0 -13
  134. package/dist/tsm_system_rows-ES7KNUQH.js.map +0 -1
  135. package/dist/tsm_system_time-76WEIMBG.js +0 -13
  136. package/dist/tsm_system_time-76WEIMBG.js.map +0 -1
  137. package/dist/unaccent-7RYF3R64.js +0 -13
  138. package/dist/unaccent-7RYF3R64.js.map +0 -1
  139. package/dist/utility-Q5A254LJ-J4HTKZPT.js +0 -347
  140. package/dist/utility-Q5A254LJ-J4HTKZPT.js.map +0 -1
  141. package/dist/uuid_ossp-4ETE4FPE.js +0 -13
  142. package/dist/uuid_ossp-4ETE4FPE.js.map +0 -1
  143. package/dist/vector-74GPNV7V.js +0 -13
  144. package/dist/vector-74GPNV7V.js.map +0 -1
@@ -0,0 +1,232 @@
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';
4
+ import type { OperationRegistry } from '@prisma-next/operations';
5
+ import type {
6
+ Log,
7
+ Plugin,
8
+ RuntimeCore,
9
+ RuntimeCoreOptions,
10
+ RuntimeTelemetryEvent,
11
+ RuntimeVerifyOptions,
12
+ TelemetryOutcome,
13
+ } from '@prisma-next/runtime-executor';
14
+ import { AsyncIterableResult, createRuntimeCore } from '@prisma-next/runtime-executor';
15
+ import type { SqlContract, SqlStorage } from '@prisma-next/sql-contract/types';
16
+ import type {
17
+ Adapter,
18
+ CodecRegistry,
19
+ LoweredStatement,
20
+ QueryAst,
21
+ SelectAst,
22
+ SqlDriver,
23
+ } from '@prisma-next/sql-relational-core/ast';
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';
27
+ import { decodeRow } from './codecs/decoding';
28
+ import { encodeParams } from './codecs/encoding';
29
+ import { validateCodecRegistryCompleteness } from './codecs/validation';
30
+ import { lowerSqlPlan } from './lower-sql-plan';
31
+ import type {
32
+ ExecutionContext,
33
+ SqlRuntimeAdapterInstance,
34
+ SqlRuntimeExtensionInstance,
35
+ } from './sql-context';
36
+ import { SqlFamilyAdapter } from './sql-family-adapter';
37
+
38
+ export interface RuntimeOptions<
39
+ TContract extends SqlContract<SqlStorage> = SqlContract<SqlStorage>,
40
+ > {
41
+ readonly context: ExecutionContext<TContract>;
42
+ readonly adapter: Adapter<QueryAst, SqlContract<SqlStorage>, LoweredStatement>;
43
+ readonly driver: SqlDriver<unknown>;
44
+ readonly verify: RuntimeVerifyOptions;
45
+ readonly plugins?: readonly Plugin<
46
+ TContract,
47
+ Adapter<SelectAst, SqlContract<SqlStorage>, LoweredStatement>,
48
+ SqlDriver<unknown>
49
+ >[];
50
+ readonly mode?: 'strict' | 'permissive';
51
+ readonly log?: Log;
52
+ }
53
+
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>;
79
+ telemetry(): RuntimeTelemetryEvent | null;
80
+ close(): Promise<void>;
81
+ operations(): OperationRegistry;
82
+ }
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
+
100
+ export type { RuntimeTelemetryEvent, RuntimeVerifyOptions, TelemetryOutcome };
101
+
102
+ class SqlRuntimeImpl<TContract extends SqlContract<SqlStorage> = SqlContract<SqlStorage>>
103
+ implements Runtime
104
+ {
105
+ private readonly core: RuntimeCore<
106
+ TContract,
107
+ Adapter<SelectAst, SqlContract<SqlStorage>, LoweredStatement>,
108
+ SqlDriver<unknown>
109
+ >;
110
+ private readonly contract: TContract;
111
+ private readonly adapter: Adapter<QueryAst, SqlContract<SqlStorage>, LoweredStatement>;
112
+ private readonly codecRegistry: CodecRegistry;
113
+ private readonly jsonSchemaValidators: JsonSchemaValidatorRegistry | undefined;
114
+ private codecRegistryValidated: boolean;
115
+
116
+ constructor(options: RuntimeOptions<TContract>) {
117
+ const { context, adapter, driver, verify, plugins, mode, log } = options;
118
+ this.contract = context.contract;
119
+ this.adapter = adapter;
120
+ this.codecRegistry = context.codecs;
121
+ this.jsonSchemaValidators = context.jsonSchemaValidators;
122
+ this.codecRegistryValidated = false;
123
+
124
+ const familyAdapter = new SqlFamilyAdapter(context.contract);
125
+
126
+ const coreOptions: RuntimeCoreOptions<
127
+ TContract,
128
+ Adapter<SelectAst, SqlContract<SqlStorage>, LoweredStatement>,
129
+ SqlDriver<unknown>
130
+ > = {
131
+ familyAdapter,
132
+ driver,
133
+ verify,
134
+ plugins: plugins as readonly Plugin<
135
+ TContract,
136
+ Adapter<SelectAst, SqlContract<SqlStorage>, LoweredStatement>,
137
+ SqlDriver<unknown>
138
+ >[],
139
+ ...ifDefined('mode', mode),
140
+ ...ifDefined('log', log),
141
+ operationRegistry: context.operations,
142
+ };
143
+
144
+ this.core = createRuntimeCore(coreOptions);
145
+
146
+ if (verify.mode === 'startup') {
147
+ validateCodecRegistryCompleteness(this.codecRegistry, context.contract);
148
+ this.codecRegistryValidated = true;
149
+ }
150
+ }
151
+
152
+ private ensureCodecRegistryValidated(contract: SqlContract<SqlStorage>): void {
153
+ if (!this.codecRegistryValidated) {
154
+ validateCodecRegistryCompleteness(this.codecRegistry, contract);
155
+ this.codecRegistryValidated = true;
156
+ }
157
+ }
158
+
159
+ execute<Row = Record<string, unknown>>(
160
+ plan: ExecutionPlan<Row> | SqlQueryPlan<Row>,
161
+ ): AsyncIterableResult<Row> {
162
+ this.ensureCodecRegistryValidated(this.contract);
163
+
164
+ const isSqlQueryPlan = (p: ExecutionPlan<Row> | SqlQueryPlan<Row>): p is SqlQueryPlan<Row> => {
165
+ return 'ast' in p && !('sql' in p);
166
+ };
167
+
168
+ const executablePlan: ExecutionPlan<Row> = isSqlQueryPlan(plan)
169
+ ? lowerSqlPlan(this.adapter, this.contract, plan)
170
+ : plan;
171
+
172
+ const iterator = async function* (
173
+ self: SqlRuntimeImpl<TContract>,
174
+ ): AsyncGenerator<Row, void, unknown> {
175
+ const encodedParams = encodeParams(
176
+ executablePlan,
177
+ self.codecRegistry,
178
+ self.jsonSchemaValidators,
179
+ );
180
+ const planWithEncodedParams: ExecutionPlan<Row> = {
181
+ ...executablePlan,
182
+ params: encodedParams,
183
+ };
184
+
185
+ const coreIterator = self.core.execute(planWithEncodedParams);
186
+
187
+ for await (const rawRow of coreIterator) {
188
+ const decodedRow = decodeRow(
189
+ rawRow as Record<string, unknown>,
190
+ executablePlan,
191
+ self.codecRegistry,
192
+ self.jsonSchemaValidators,
193
+ );
194
+ yield decodedRow as Row;
195
+ }
196
+ };
197
+
198
+ return new AsyncIterableResult(iterator(this));
199
+ }
200
+
201
+ connection(): Promise<RuntimeConnection> {
202
+ return this.core.connection();
203
+ }
204
+
205
+ telemetry(): RuntimeTelemetryEvent | null {
206
+ return this.core.telemetry();
207
+ }
208
+
209
+ operations(): OperationRegistry {
210
+ return this.core.operations();
211
+ }
212
+
213
+ close(): Promise<void> {
214
+ return this.core.close();
215
+ }
216
+ }
217
+
218
+ export function createRuntime<TContract extends SqlContract<SqlStorage>, TTargetId extends string>(
219
+ options: CreateRuntimeOptions<TContract, TTargetId>,
220
+ ): Runtime {
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
+ });
232
+ }
@@ -0,0 +1,144 @@
1
+ import type { ExecutionPlan } from '@prisma-next/contract/types';
2
+ import { instantiateExecutionStack } from '@prisma-next/core-execution-plane/stack';
3
+ import type { AsyncIterableResult } from '@prisma-next/runtime-executor';
4
+ import { describe, expect, it } from 'vitest';
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';
14
+
15
+ class MockDriver {
16
+ private rows: ReadonlyArray<Record<string, unknown>> = [];
17
+
18
+ setRows(rows: ReadonlyArray<Record<string, unknown>>): void {
19
+ this.rows = rows;
20
+ }
21
+
22
+ async query<Row = Record<string, unknown>>(
23
+ _sql: string,
24
+ _params?: readonly unknown[],
25
+ ): Promise<{ rows: ReadonlyArray<Row> }> {
26
+ return { rows: [] };
27
+ }
28
+
29
+ async *execute<Row = Record<string, unknown>>(_options: {
30
+ sql: string;
31
+ params: readonly unknown[];
32
+ }): AsyncIterable<Row> {
33
+ for (const row of this.rows) {
34
+ yield row as Row;
35
+ }
36
+ }
37
+
38
+ async acquireConnection(): Promise<never> {
39
+ throw new Error('Not implemented in mock');
40
+ }
41
+
42
+ async connect(): Promise<void> {}
43
+
44
+ async close(): Promise<void> {}
45
+ }
46
+
47
+ const fixtureContract = createTestContract({
48
+ schemaVersion: '1',
49
+ targetFamily: 'sql',
50
+ target: 'postgres',
51
+ storageHash: 'test-hash',
52
+ profileHash: 'test-profile-hash',
53
+ storage: {
54
+ tables: {
55
+ user: {
56
+ columns: {
57
+ id: { nativeType: 'int4', codecId: 'pg/int4@1', nullable: false },
58
+ email: { nativeType: 'text', codecId: 'pg/text@1', nullable: false },
59
+ },
60
+ uniques: [],
61
+ indexes: [],
62
+ foreignKeys: [],
63
+ },
64
+ },
65
+ },
66
+ models: {},
67
+ relations: {},
68
+ mappings: { codecTypes: {}, operationTypes: {} },
69
+ });
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
+
88
+ describe('SqlRuntime AsyncIterableResult integration', () => {
89
+ it('returns AsyncIterableResult from execute', async () => {
90
+ const driver = new MockDriver();
91
+ driver.setRows([
92
+ { id: 1, email: 'test1@example.com' },
93
+ { id: 2, email: 'test2@example.com' },
94
+ ]);
95
+ const runtime = createTestRuntime(driver);
96
+
97
+ const plan: ExecutionPlan<{ id: number; email: string }> = {
98
+ sql: 'SELECT id, email FROM "user" ORDER BY id',
99
+ params: [],
100
+ meta: {
101
+ target: 'postgres',
102
+ targetFamily: 'sql',
103
+ storageHash: 'test-hash',
104
+ lane: 'sql',
105
+ paramDescriptors: [],
106
+ },
107
+ };
108
+
109
+ const result = runtime.execute(plan);
110
+
111
+ expect(result).toBeInstanceOf(Object);
112
+ expect(typeof result.toArray).toBe('function');
113
+ expect(typeof result[Symbol.asyncIterator]).toBe('function');
114
+
115
+ await runtime.close();
116
+ });
117
+
118
+ it('preserves type information', async () => {
119
+ const driver = new MockDriver();
120
+ driver.setRows([{ id: 1, email: 'test@example.com' }]);
121
+ const runtime = createTestRuntime(driver);
122
+
123
+ const plan: ExecutionPlan<{ id: number; email: string }> = {
124
+ sql: 'SELECT id, email FROM "user" LIMIT 1',
125
+ params: [],
126
+ meta: {
127
+ target: 'postgres',
128
+ targetFamily: 'sql',
129
+ storageHash: 'test-hash',
130
+ lane: 'sql',
131
+ paramDescriptors: [],
132
+ },
133
+ };
134
+
135
+ const result: AsyncIterableResult<{ id: number; email: string }> = runtime.execute(plan);
136
+ const rows = await result.toArray();
137
+
138
+ expect(rows.length).toBe(1);
139
+ expect(typeof rows[0]!.id).toBe('number');
140
+ expect(typeof rows[0]!.email).toBe('string');
141
+
142
+ await runtime.close();
143
+ });
144
+ });
@@ -0,0 +1,68 @@
1
+ import type { SqlContract, SqlMappings, SqlStorage } from '@prisma-next/sql-contract/types';
2
+ import { expectTypeOf, test } from 'vitest';
3
+ import type { ExecutionContext, TypeHelperRegistry } from '../src/sql-context';
4
+
5
+ // Contract type with storage.types using literal types (matching emission output)
6
+ type TestContract = SqlContract<
7
+ {
8
+ readonly tables: {
9
+ readonly document: {
10
+ readonly columns: {
11
+ readonly id: {
12
+ readonly nativeType: 'int4';
13
+ readonly codecId: 'pg/int4@1';
14
+ nullable: false;
15
+ };
16
+ };
17
+ readonly primaryKey: { readonly columns: readonly ['id'] };
18
+ readonly uniques: readonly [];
19
+ readonly indexes: readonly [];
20
+ readonly foreignKeys: readonly [];
21
+ };
22
+ };
23
+ readonly types: {
24
+ readonly Vector1536: {
25
+ readonly codecId: 'pg/vector@1';
26
+ readonly nativeType: 'vector';
27
+ readonly typeParams: { readonly length: 1536 };
28
+ };
29
+ };
30
+ },
31
+ Record<string, never>,
32
+ Record<string, never>,
33
+ SqlMappings
34
+ >;
35
+
36
+ test('ExecutionContext.types is TypeHelperRegistry', () => {
37
+ // ExecutionContext.types is intentionally loose (Record<string, unknown>)
38
+ // The strong typing comes from schema(context).types via ExtractSchemaTypes
39
+ expectTypeOf<ExecutionContext<TestContract>['types']>().toEqualTypeOf<TypeHelperRegistry>();
40
+
41
+ // TypeHelperRegistry allows any values - the actual type depends on init hooks
42
+ expectTypeOf<TypeHelperRegistry>().toEqualTypeOf<Record<string, unknown>>();
43
+ });
44
+
45
+ test('ExecutionContext preserves contract type parameter', () => {
46
+ // Verify the contract type is preserved in ExecutionContext
47
+ expectTypeOf<ExecutionContext<TestContract>['contract']>().toEqualTypeOf<TestContract>();
48
+
49
+ // Verify we can access storage.types through the context's contract
50
+ type ContractStorageTypes = ExecutionContext<TestContract>['contract']['storage']['types'];
51
+ expectTypeOf<ContractStorageTypes>().toExtend<
52
+ | {
53
+ readonly Vector1536: {
54
+ readonly codecId: 'pg/vector@1';
55
+ readonly nativeType: 'vector';
56
+ readonly typeParams: { readonly length: 1536 };
57
+ };
58
+ }
59
+ | undefined
60
+ >();
61
+ });
62
+
63
+ test('ExecutionContext accepts generic SqlContract', () => {
64
+ // Verify ExecutionContext defaults work
65
+ type DefaultContext = ExecutionContext;
66
+ expectTypeOf<DefaultContext['contract']>().toExtend<SqlContract<SqlStorage>>();
67
+ expectTypeOf<DefaultContext['types']>().toEqualTypeOf<TypeHelperRegistry>();
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
+ });