@prisma-next/sql-runtime 0.3.0-dev.3 → 0.3.0-dev.31

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 (53) hide show
  1. package/README.md +1 -2
  2. package/dist/{accelerate-EEKAFGN3-SHR4XFVV.js → accelerate-EEKAFGN3-P6A6XJWJ.js} +28 -28
  3. package/dist/{accelerate-EEKAFGN3-SHR4XFVV.js.map → accelerate-EEKAFGN3-P6A6XJWJ.js.map} +1 -1
  4. package/dist/{chunk-C6I3V3DM.js → chunk-APA6GHYY.js} +84 -2
  5. package/dist/chunk-APA6GHYY.js.map +1 -0
  6. package/dist/{dist-LCVVJCGI.js → dist-AQ3LWXOX.js} +13 -13
  7. package/dist/{dist-LCVVJCGI.js.map → dist-AQ3LWXOX.js.map} +1 -1
  8. package/dist/index.js +1 -1
  9. package/dist/src/codecs/decoding.d.ts +4 -0
  10. package/dist/src/codecs/decoding.d.ts.map +1 -0
  11. package/dist/src/codecs/encoding.d.ts +5 -0
  12. package/dist/src/codecs/encoding.d.ts.map +1 -0
  13. package/dist/src/codecs/validation.d.ts +6 -0
  14. package/dist/src/codecs/validation.d.ts.map +1 -0
  15. package/dist/src/exports/index.d.ts +11 -0
  16. package/dist/src/exports/index.d.ts.map +1 -0
  17. package/dist/src/index.d.ts +2 -0
  18. package/dist/src/index.d.ts.map +1 -0
  19. package/dist/src/lower-sql-plan.d.ts +15 -0
  20. package/dist/src/lower-sql-plan.d.ts.map +1 -0
  21. package/dist/src/sql-context.d.ts +130 -0
  22. package/dist/src/sql-context.d.ts.map +1 -0
  23. package/dist/src/sql-family-adapter.d.ts +10 -0
  24. package/dist/src/sql-family-adapter.d.ts.map +1 -0
  25. package/dist/src/sql-marker.d.ts +22 -0
  26. package/dist/src/sql-marker.d.ts.map +1 -0
  27. package/dist/src/sql-runtime.d.ts +25 -0
  28. package/dist/src/sql-runtime.d.ts.map +1 -0
  29. package/dist/test/utils.d.ts +20 -24
  30. package/dist/test/utils.d.ts.map +1 -0
  31. package/dist/test/utils.js +26 -26
  32. package/dist/test/utils.js.map +1 -1
  33. package/package.json +25 -22
  34. package/src/codecs/decoding.ts +140 -0
  35. package/src/codecs/encoding.ts +76 -0
  36. package/src/codecs/validation.ts +67 -0
  37. package/src/exports/index.ts +40 -0
  38. package/src/index.ts +1 -0
  39. package/src/lower-sql-plan.ts +32 -0
  40. package/src/sql-context.ts +402 -0
  41. package/src/sql-family-adapter.ts +43 -0
  42. package/src/sql-marker.ts +105 -0
  43. package/src/sql-runtime.ts +166 -0
  44. package/test/async-iterable-result.test.ts +136 -0
  45. package/test/context.types.test-d.ts +70 -0
  46. package/test/parameterized-types.test.ts +553 -0
  47. package/test/sql-context.test.ts +217 -0
  48. package/test/sql-family-adapter.test.ts +86 -0
  49. package/test/sql-runtime.test.ts +155 -0
  50. package/test/utils.ts +266 -0
  51. package/dist/chunk-C6I3V3DM.js.map +0 -1
  52. package/dist/index.d.ts +0 -29
  53. package/dist/sql-runtime-DgEbg2OP.d.ts +0 -109
@@ -0,0 +1,217 @@
1
+ import type { SqlContract, SqlStorage } from '@prisma-next/sql-contract/types';
2
+ import type { SqlOperationSignature } from '@prisma-next/sql-operations';
3
+ import type { CodecRegistry, SelectAst } from '@prisma-next/sql-relational-core/ast';
4
+ import { codec, createCodecRegistry } from '@prisma-next/sql-relational-core/ast';
5
+ import { describe, expect, it } from 'vitest';
6
+ import {
7
+ createRuntimeContext,
8
+ type SqlRuntimeExtensionDescriptor,
9
+ type SqlRuntimeExtensionInstance,
10
+ } from '../src/sql-context';
11
+
12
+ // Minimal test contract
13
+ const testContract: SqlContract<SqlStorage> = {
14
+ schemaVersion: '1',
15
+ targetFamily: 'sql',
16
+ target: 'postgres',
17
+ coreHash: 'sha256:test',
18
+ models: {},
19
+ relations: {},
20
+ storage: { tables: {} },
21
+ extensionPacks: {},
22
+ capabilities: {},
23
+ meta: {},
24
+ sources: {},
25
+ mappings: {
26
+ codecTypes: {},
27
+ operationTypes: {},
28
+ },
29
+ };
30
+
31
+ // Stub adapter codecs
32
+ function createStubCodecs(): CodecRegistry {
33
+ const registry = createCodecRegistry();
34
+ registry.register(
35
+ codec({
36
+ typeId: 'pg/int4@1',
37
+ targetTypes: ['int4'],
38
+ encode: (v: number) => v,
39
+ decode: (w: number) => w,
40
+ }),
41
+ );
42
+ return registry;
43
+ }
44
+
45
+ // Create a test adapter descriptor
46
+ function createTestAdapterDescriptor() {
47
+ const codecs = createStubCodecs();
48
+ return {
49
+ kind: 'adapter' as const,
50
+ id: 'test-adapter',
51
+ version: '0.0.1',
52
+ familyId: 'sql' as const,
53
+ targetId: 'postgres' as const,
54
+ create() {
55
+ return {
56
+ familyId: 'sql' as const,
57
+ targetId: 'postgres' as const,
58
+ profile: {
59
+ id: 'test-profile',
60
+ target: 'postgres',
61
+ capabilities: {},
62
+ codecs() {
63
+ return codecs;
64
+ },
65
+ },
66
+ lower(ast: SelectAst) {
67
+ return {
68
+ profileId: 'test-profile',
69
+ body: Object.freeze({ sql: JSON.stringify(ast), params: [] }),
70
+ };
71
+ },
72
+ };
73
+ },
74
+ };
75
+ }
76
+
77
+ // Create a test target descriptor
78
+ function createTestTargetDescriptor() {
79
+ return {
80
+ kind: 'target' as const,
81
+ id: 'postgres',
82
+ version: '0.0.1',
83
+ familyId: 'sql' as const,
84
+ targetId: 'postgres' as const,
85
+ create() {
86
+ return { familyId: 'sql' as const, targetId: 'postgres' as const };
87
+ },
88
+ };
89
+ }
90
+
91
+ // Create a test extension descriptor
92
+ function createTestExtensionDescriptor(options?: {
93
+ hasCodecs?: boolean;
94
+ hasOperations?: boolean;
95
+ }): SqlRuntimeExtensionDescriptor<'postgres'> {
96
+ const { hasCodecs = false, hasOperations = false } = options ?? {};
97
+
98
+ // Build the codecs function if needed
99
+ const codecsFn = hasCodecs
100
+ ? () => {
101
+ const registry = createCodecRegistry();
102
+ registry.register(
103
+ codec({
104
+ typeId: 'test/ext@1',
105
+ targetTypes: ['ext'],
106
+ encode: (v: string) => v,
107
+ decode: (w: string) => w,
108
+ }),
109
+ );
110
+ return registry;
111
+ }
112
+ : undefined;
113
+
114
+ // Build the operations function if needed
115
+ const operationsFn = hasOperations
116
+ ? (): ReadonlyArray<SqlOperationSignature> => [
117
+ {
118
+ forTypeId: 'test/ext@1',
119
+ method: 'testOp',
120
+ args: [],
121
+ returns: { kind: 'builtin', type: 'number' },
122
+ lowering: { targetFamily: 'sql', strategy: 'function', template: 'test()' },
123
+ },
124
+ ]
125
+ : undefined;
126
+
127
+ return {
128
+ kind: 'extension' as const,
129
+ id: 'test-extension',
130
+ version: '0.0.1',
131
+ familyId: 'sql' as const,
132
+ targetId: 'postgres' as const,
133
+ create(): SqlRuntimeExtensionInstance<'postgres'> {
134
+ // Return object with optional methods only if they exist
135
+ const instance: SqlRuntimeExtensionInstance<'postgres'> = {
136
+ familyId: 'sql' as const,
137
+ targetId: 'postgres' as const,
138
+ };
139
+ if (codecsFn) {
140
+ (instance as { codecs?: () => CodecRegistry }).codecs = codecsFn;
141
+ }
142
+ if (operationsFn) {
143
+ (instance as { operations?: () => ReadonlyArray<SqlOperationSignature> }).operations =
144
+ operationsFn;
145
+ }
146
+ return instance;
147
+ },
148
+ };
149
+ }
150
+
151
+ describe('createRuntimeContext', () => {
152
+ it('creates context with adapter codecs', () => {
153
+ const context = createRuntimeContext({
154
+ contract: testContract,
155
+ target: createTestTargetDescriptor(),
156
+ adapter: createTestAdapterDescriptor(),
157
+ });
158
+
159
+ expect(context.contract).toBe(testContract);
160
+ expect(context.adapter).toBeDefined();
161
+ expect(context.codecs.has('pg/int4@1')).toBe(true);
162
+ expect(context.operations).toBeDefined();
163
+ });
164
+
165
+ it('creates context with empty extension packs', () => {
166
+ const context = createRuntimeContext({
167
+ contract: testContract,
168
+ target: createTestTargetDescriptor(),
169
+ adapter: createTestAdapterDescriptor(),
170
+ extensionPacks: [],
171
+ });
172
+
173
+ expect(context.codecs.has('pg/int4@1')).toBe(true);
174
+ // No extension codecs registered
175
+ expect(context.codecs.has('test/ext@1')).toBe(false);
176
+ });
177
+
178
+ it('registers extension codecs', () => {
179
+ const context = createRuntimeContext({
180
+ contract: testContract,
181
+ target: createTestTargetDescriptor(),
182
+ adapter: createTestAdapterDescriptor(),
183
+ extensionPacks: [createTestExtensionDescriptor({ hasCodecs: true })],
184
+ });
185
+
186
+ // Adapter codec
187
+ expect(context.codecs.has('pg/int4@1')).toBe(true);
188
+ // Extension codec
189
+ expect(context.codecs.has('test/ext@1')).toBe(true);
190
+ });
191
+
192
+ it('registers extension operations', () => {
193
+ const context = createRuntimeContext({
194
+ contract: testContract,
195
+ target: createTestTargetDescriptor(),
196
+ adapter: createTestAdapterDescriptor(),
197
+ extensionPacks: [createTestExtensionDescriptor({ hasOperations: true })],
198
+ });
199
+
200
+ const ops = context.operations.byType('test/ext@1');
201
+ expect(ops.length).toBe(1);
202
+ expect(ops[0]?.method).toBe('testOp');
203
+ });
204
+
205
+ it('handles extension without codecs or operations', () => {
206
+ const context = createRuntimeContext({
207
+ contract: testContract,
208
+ target: createTestTargetDescriptor(),
209
+ adapter: createTestAdapterDescriptor(),
210
+ extensionPacks: [createTestExtensionDescriptor({ hasCodecs: false, hasOperations: false })],
211
+ });
212
+
213
+ // Only adapter codec
214
+ expect(context.codecs.has('pg/int4@1')).toBe(true);
215
+ expect(context.codecs.has('test/ext@1')).toBe(false);
216
+ });
217
+ });
@@ -0,0 +1,86 @@
1
+ import type { ExecutionPlan } from '@prisma-next/contract/types';
2
+ import type { SqlContract, SqlStorage } from '@prisma-next/sql-contract/types';
3
+ import { describe, expect, it } from 'vitest';
4
+ import { SqlFamilyAdapter } from '../src/sql-family-adapter';
5
+
6
+ // Minimal test contract
7
+ const testContract: SqlContract<SqlStorage> = {
8
+ schemaVersion: '1',
9
+ targetFamily: 'sql',
10
+ target: 'postgres',
11
+ coreHash: 'sha256:test-hash',
12
+ models: {},
13
+ relations: {},
14
+ storage: { tables: {} },
15
+ extensionPacks: {},
16
+ capabilities: {},
17
+ meta: {},
18
+ sources: {},
19
+ mappings: {
20
+ codecTypes: {},
21
+ operationTypes: {},
22
+ },
23
+ };
24
+
25
+ describe('SqlFamilyAdapter', () => {
26
+ it('creates adapter with contract and marker reader', () => {
27
+ const adapter = new SqlFamilyAdapter(testContract);
28
+
29
+ expect(adapter.contract).toBe(testContract);
30
+ expect(adapter.markerReader).toBeDefined();
31
+ expect(adapter.markerReader.readMarkerStatement).toBeDefined();
32
+ });
33
+
34
+ it('validates plan with matching target and hash', () => {
35
+ const adapter = new SqlFamilyAdapter(testContract);
36
+ const plan: ExecutionPlan = {
37
+ meta: {
38
+ target: 'postgres',
39
+ coreHash: 'sha256:test-hash',
40
+ lane: 'sql',
41
+ paramDescriptors: [],
42
+ },
43
+ sql: 'SELECT 1',
44
+ params: [],
45
+ };
46
+
47
+ // Should not throw
48
+ expect(() => adapter.validatePlan(plan, testContract)).not.toThrow();
49
+ });
50
+
51
+ it('throws on plan target mismatch', () => {
52
+ const adapter = new SqlFamilyAdapter(testContract);
53
+ const plan: ExecutionPlan = {
54
+ meta: {
55
+ target: 'mysql', // Wrong target
56
+ coreHash: 'sha256:test-hash',
57
+ lane: 'sql',
58
+ paramDescriptors: [],
59
+ },
60
+ sql: 'SELECT 1',
61
+ params: [],
62
+ };
63
+
64
+ expect(() => adapter.validatePlan(plan, testContract)).toThrow(
65
+ 'Plan target does not match runtime target',
66
+ );
67
+ });
68
+
69
+ it('throws on plan coreHash mismatch', () => {
70
+ const adapter = new SqlFamilyAdapter(testContract);
71
+ const plan: ExecutionPlan = {
72
+ meta: {
73
+ target: 'postgres',
74
+ coreHash: 'sha256:different-hash', // Wrong hash
75
+ lane: 'sql',
76
+ paramDescriptors: [],
77
+ },
78
+ sql: 'SELECT 1',
79
+ params: [],
80
+ };
81
+
82
+ expect(() => adapter.validatePlan(plan, testContract)).toThrow(
83
+ 'Plan core hash does not match runtime contract',
84
+ );
85
+ });
86
+ });
@@ -0,0 +1,155 @@
1
+ import { createOperationRegistry } from '@prisma-next/operations';
2
+ import type { SqlContract, SqlStorage } from '@prisma-next/sql-contract/types';
3
+ import type {
4
+ CodecRegistry,
5
+ SelectAst,
6
+ SqlDriver,
7
+ SqlExecuteRequest,
8
+ } from '@prisma-next/sql-relational-core/ast';
9
+ import { codec, createCodecRegistry } from '@prisma-next/sql-relational-core/ast';
10
+ import { describe, expect, it, vi } from 'vitest';
11
+ import type { RuntimeContext } from '../src/sql-context';
12
+ import { createRuntime } from '../src/sql-runtime';
13
+
14
+ // Minimal test contract
15
+ const testContract: SqlContract<SqlStorage> = {
16
+ schemaVersion: '1',
17
+ targetFamily: 'sql',
18
+ target: 'postgres',
19
+ coreHash: 'sha256:test',
20
+ models: {},
21
+ relations: {},
22
+ storage: { tables: {} },
23
+ extensionPacks: {},
24
+ capabilities: {},
25
+ meta: {},
26
+ sources: {},
27
+ mappings: {
28
+ codecTypes: {},
29
+ operationTypes: {},
30
+ },
31
+ };
32
+
33
+ // Create a stub codec registry
34
+ function createStubCodecs(): CodecRegistry {
35
+ const registry = createCodecRegistry();
36
+ registry.register(
37
+ codec({
38
+ typeId: 'pg/int4@1',
39
+ targetTypes: ['int4'],
40
+ encode: (v: number) => v,
41
+ decode: (w: number) => w,
42
+ }),
43
+ );
44
+ return registry;
45
+ }
46
+
47
+ // Create a stub adapter
48
+ function createStubAdapter() {
49
+ const codecs = createStubCodecs();
50
+ return {
51
+ familyId: 'sql' as const,
52
+ targetId: 'postgres' as const,
53
+ profile: {
54
+ id: 'test-profile',
55
+ target: 'postgres',
56
+ capabilities: {},
57
+ codecs() {
58
+ return codecs;
59
+ },
60
+ },
61
+ lower(ast: SelectAst) {
62
+ return {
63
+ profileId: 'test-profile',
64
+ body: Object.freeze({ sql: JSON.stringify(ast), params: [] }),
65
+ };
66
+ },
67
+ };
68
+ }
69
+
70
+ // Create a mock driver that implements SqlDriver interface
71
+ function createMockDriver(): SqlDriver {
72
+ const execute = vi.fn().mockImplementation(async function* (_request: SqlExecuteRequest) {
73
+ yield { id: 1 };
74
+ });
75
+
76
+ return {
77
+ connect: vi.fn().mockResolvedValue(undefined),
78
+ execute,
79
+ query: vi.fn().mockResolvedValue({ rows: [], rowCount: 0 }),
80
+ close: vi.fn().mockResolvedValue(undefined),
81
+ };
82
+ }
83
+
84
+ // Create a test runtime context
85
+ function createTestContext(contract: SqlContract<SqlStorage>): RuntimeContext<typeof contract> {
86
+ const adapter = createStubAdapter();
87
+ return {
88
+ contract,
89
+ adapter,
90
+ codecs: adapter.profile.codecs(),
91
+ operations: createOperationRegistry(),
92
+ };
93
+ }
94
+
95
+ describe('createRuntime', () => {
96
+ it('creates runtime with valid options', () => {
97
+ const context = createTestContext(testContract);
98
+ const driver = createMockDriver();
99
+
100
+ const runtime = createRuntime({
101
+ context,
102
+ driver,
103
+ verify: { mode: 'onFirstUse', requireMarker: false },
104
+ });
105
+
106
+ expect(runtime).toBeDefined();
107
+ expect(runtime.execute).toBeDefined();
108
+ expect(runtime.telemetry).toBeDefined();
109
+ expect(runtime.operations).toBeDefined();
110
+ expect(runtime.close).toBeDefined();
111
+ });
112
+
113
+ it('returns operations registry', () => {
114
+ const context = createTestContext(testContract);
115
+ const driver = createMockDriver();
116
+
117
+ const runtime = createRuntime({
118
+ context,
119
+ driver,
120
+ verify: { mode: 'onFirstUse', requireMarker: false },
121
+ });
122
+
123
+ const ops = runtime.operations();
124
+ expect(ops).toBeDefined();
125
+ expect(ops.byType).toBeDefined();
126
+ });
127
+
128
+ it('returns null telemetry when no events', () => {
129
+ const context = createTestContext(testContract);
130
+ const driver = createMockDriver();
131
+
132
+ const runtime = createRuntime({
133
+ context,
134
+ driver,
135
+ verify: { mode: 'onFirstUse', requireMarker: false },
136
+ });
137
+
138
+ // Before any execution, telemetry should be null
139
+ expect(runtime.telemetry()).toBeNull();
140
+ });
141
+
142
+ it('closes runtime', async () => {
143
+ const context = createTestContext(testContract);
144
+ const driver = createMockDriver();
145
+
146
+ const runtime = createRuntime({
147
+ context,
148
+ driver,
149
+ verify: { mode: 'onFirstUse', requireMarker: false },
150
+ });
151
+
152
+ await runtime.close();
153
+ expect(driver.close).toHaveBeenCalled();
154
+ });
155
+ });