@prisma-next/sql-runtime 0.3.0-dev.34 → 0.3.0-dev.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +115 -24
- package/dist/exports-C8hi0N-a.mjs +622 -0
- package/dist/exports-C8hi0N-a.mjs.map +1 -0
- package/dist/index-SlQIrV_t.d.mts +131 -0
- package/dist/index-SlQIrV_t.d.mts.map +1 -0
- package/dist/index.d.mts +2 -0
- package/dist/index.mjs +3 -0
- package/dist/test/utils.d.mts +82 -0
- package/dist/test/utils.d.mts.map +1 -0
- package/dist/test/utils.mjs +212 -0
- package/dist/test/utils.mjs.map +1 -0
- package/package.json +26 -20
- package/src/codecs/decoding.ts +84 -3
- package/src/codecs/encoding.ts +15 -2
- package/src/codecs/json-schema-validation.ts +61 -0
- package/src/exports/index.ts +9 -4
- package/src/lower-sql-plan.ts +8 -8
- package/src/sql-context.ts +286 -245
- package/src/sql-family-adapter.ts +9 -5
- package/src/sql-marker.ts +2 -2
- package/src/sql-runtime.ts +89 -23
- package/test/async-iterable-result.test.ts +42 -34
- package/test/context.types.test-d.ts +12 -14
- package/test/execution-stack.test.ts +166 -0
- package/test/json-schema-validation.test.ts +653 -0
- package/test/parameterized-types.test.ts +182 -196
- package/test/sql-context.test.ts +292 -117
- package/test/sql-family-adapter.test.ts +7 -6
- package/test/sql-runtime.test.ts +117 -31
- package/test/utils.ts +76 -50
- package/dist/accelerate-EEKAFGN3-P6A6XJWJ.js +0 -137863
- package/dist/accelerate-EEKAFGN3-P6A6XJWJ.js.map +0 -1
- package/dist/amcheck-24VY6X5V.js +0 -13
- package/dist/amcheck-24VY6X5V.js.map +0 -1
- package/dist/bloom-VS74NLHT.js +0 -13
- package/dist/bloom-VS74NLHT.js.map +0 -1
- package/dist/btree_gin-WBC4EAAI.js +0 -13
- package/dist/btree_gin-WBC4EAAI.js.map +0 -1
- package/dist/btree_gist-UNC6QD3M.js +0 -13
- package/dist/btree_gist-UNC6QD3M.js.map +0 -1
- package/dist/chunk-3KTOEDFX.js +0 -49
- package/dist/chunk-3KTOEDFX.js.map +0 -1
- package/dist/chunk-47DZBRQC.js +0 -1280
- package/dist/chunk-47DZBRQC.js.map +0 -1
- package/dist/chunk-52N6AFZM.js +0 -133
- package/dist/chunk-52N6AFZM.js.map +0 -1
- package/dist/chunk-7D4SUZUM.js +0 -38
- package/dist/chunk-7D4SUZUM.js.map +0 -1
- package/dist/chunk-APA6GHYY.js +0 -537
- package/dist/chunk-APA6GHYY.js.map +0 -1
- package/dist/chunk-ECWIHLAT.js +0 -37
- package/dist/chunk-ECWIHLAT.js.map +0 -1
- package/dist/chunk-EI626SDC.js +0 -105
- package/dist/chunk-EI626SDC.js.map +0 -1
- package/dist/chunk-UKKOYUGL.js +0 -578
- package/dist/chunk-UKKOYUGL.js.map +0 -1
- package/dist/chunk-XPLNMXQV.js +0 -1537
- package/dist/chunk-XPLNMXQV.js.map +0 -1
- package/dist/citext-T7MXGUY7.js +0 -13
- package/dist/citext-T7MXGUY7.js.map +0 -1
- package/dist/client-5FENX6AW.js +0 -299
- package/dist/client-5FENX6AW.js.map +0 -1
- package/dist/cube-TFDQBZCI.js +0 -13
- package/dist/cube-TFDQBZCI.js.map +0 -1
- package/dist/dict_int-AEUOPGWP.js +0 -13
- package/dist/dict_int-AEUOPGWP.js.map +0 -1
- package/dist/dict_xsyn-DAAYX3FL.js +0 -13
- package/dist/dict_xsyn-DAAYX3FL.js.map +0 -1
- package/dist/dist-AQ3LWXOX.js +0 -570
- package/dist/dist-AQ3LWXOX.js.map +0 -1
- package/dist/dist-LBVX6BJW.js +0 -189
- package/dist/dist-LBVX6BJW.js.map +0 -1
- package/dist/dist-WLKUVDN2.js +0 -5127
- package/dist/dist-WLKUVDN2.js.map +0 -1
- package/dist/earthdistance-KIGTF4LE.js +0 -13
- package/dist/earthdistance-KIGTF4LE.js.map +0 -1
- package/dist/file_fdw-5N55UP6I.js +0 -13
- package/dist/file_fdw-5N55UP6I.js.map +0 -1
- package/dist/fuzzystrmatch-KN3YWBFP.js +0 -13
- package/dist/fuzzystrmatch-KN3YWBFP.js.map +0 -1
- package/dist/hstore-YX726NKN.js +0 -13
- package/dist/hstore-YX726NKN.js.map +0 -1
- package/dist/http-exception-FZY2H4OF.js +0 -8
- package/dist/http-exception-FZY2H4OF.js.map +0 -1
- package/dist/index.js +0 -30
- package/dist/index.js.map +0 -1
- package/dist/intarray-NKVXNO2D.js +0 -13
- package/dist/intarray-NKVXNO2D.js.map +0 -1
- package/dist/isn-FTEMJGEV.js +0 -13
- package/dist/isn-FTEMJGEV.js.map +0 -1
- package/dist/lo-DB7L4NGI.js +0 -13
- package/dist/lo-DB7L4NGI.js.map +0 -1
- package/dist/logger-WQ7SHNDD.js +0 -68
- package/dist/logger-WQ7SHNDD.js.map +0 -1
- package/dist/ltree-Z32TZT6W.js +0 -13
- package/dist/ltree-Z32TZT6W.js.map +0 -1
- package/dist/nodefs-NM46ACH7.js +0 -31
- package/dist/nodefs-NM46ACH7.js.map +0 -1
- package/dist/opfs-ahp-NJO33LVZ.js +0 -332
- package/dist/opfs-ahp-NJO33LVZ.js.map +0 -1
- package/dist/pageinspect-YP3IZR4X.js +0 -13
- package/dist/pageinspect-YP3IZR4X.js.map +0 -1
- package/dist/pg_buffercache-7TD5J2FB.js +0 -13
- package/dist/pg_buffercache-7TD5J2FB.js.map +0 -1
- package/dist/pg_dump-SG4KYBUB.js +0 -2492
- package/dist/pg_dump-SG4KYBUB.js.map +0 -1
- package/dist/pg_freespacemap-DZDNCPZK.js +0 -13
- package/dist/pg_freespacemap-DZDNCPZK.js.map +0 -1
- package/dist/pg_surgery-J2MUEWEP.js +0 -13
- package/dist/pg_surgery-J2MUEWEP.js.map +0 -1
- package/dist/pg_trgm-7VNQOYS6.js +0 -13
- package/dist/pg_trgm-7VNQOYS6.js.map +0 -1
- package/dist/pg_visibility-TTSIPHFL.js +0 -13
- package/dist/pg_visibility-TTSIPHFL.js.map +0 -1
- package/dist/pg_walinspect-KPFHSHRJ.js +0 -13
- package/dist/pg_walinspect-KPFHSHRJ.js.map +0 -1
- package/dist/proxy-signals-GUDAMDHV.js +0 -39
- package/dist/proxy-signals-GUDAMDHV.js.map +0 -1
- package/dist/seg-IYVDLE4O.js +0 -13
- package/dist/seg-IYVDLE4O.js.map +0 -1
- package/dist/src/codecs/decoding.d.ts +0 -4
- package/dist/src/codecs/decoding.d.ts.map +0 -1
- package/dist/src/codecs/encoding.d.ts +0 -5
- package/dist/src/codecs/encoding.d.ts.map +0 -1
- package/dist/src/codecs/validation.d.ts +0 -6
- package/dist/src/codecs/validation.d.ts.map +0 -1
- package/dist/src/exports/index.d.ts +0 -11
- package/dist/src/exports/index.d.ts.map +0 -1
- package/dist/src/index.d.ts +0 -2
- package/dist/src/index.d.ts.map +0 -1
- package/dist/src/lower-sql-plan.d.ts +0 -15
- package/dist/src/lower-sql-plan.d.ts.map +0 -1
- package/dist/src/sql-context.d.ts +0 -130
- package/dist/src/sql-context.d.ts.map +0 -1
- package/dist/src/sql-family-adapter.d.ts +0 -10
- package/dist/src/sql-family-adapter.d.ts.map +0 -1
- package/dist/src/sql-marker.d.ts +0 -22
- package/dist/src/sql-marker.d.ts.map +0 -1
- package/dist/src/sql-runtime.d.ts +0 -25
- package/dist/src/sql-runtime.d.ts.map +0 -1
- package/dist/tablefunc-EF4RCS7S.js +0 -13
- package/dist/tablefunc-EF4RCS7S.js.map +0 -1
- package/dist/tcn-3VT5BQYW.js +0 -13
- package/dist/tcn-3VT5BQYW.js.map +0 -1
- package/dist/test/utils.d.ts +0 -60
- package/dist/test/utils.d.ts.map +0 -1
- package/dist/test/utils.js +0 -24635
- package/dist/test/utils.js.map +0 -1
- package/dist/tiny-CW6F4GX6.js +0 -10
- package/dist/tiny-CW6F4GX6.js.map +0 -1
- package/dist/tsm_system_rows-ES7KNUQH.js +0 -13
- package/dist/tsm_system_rows-ES7KNUQH.js.map +0 -1
- package/dist/tsm_system_time-76WEIMBG.js +0 -13
- package/dist/tsm_system_time-76WEIMBG.js.map +0 -1
- package/dist/unaccent-7RYF3R64.js +0 -13
- package/dist/unaccent-7RYF3R64.js.map +0 -1
- package/dist/utility-Q5A254LJ-J4HTKZPT.js +0 -347
- package/dist/utility-Q5A254LJ-J4HTKZPT.js.map +0 -1
- package/dist/uuid_ossp-4ETE4FPE.js +0 -13
- package/dist/uuid_ossp-4ETE4FPE.js.map +0 -1
- package/dist/vector-74GPNV7V.js +0 -13
- package/dist/vector-74GPNV7V.js.map +0 -1
- 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.
|
|
37
|
-
throw runtimeError(
|
|
38
|
-
|
|
39
|
-
|
|
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
|
|
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.
|
|
60
|
+
input.storageHash,
|
|
61
61
|
input.profileHash,
|
|
62
62
|
input.contractJson ?? null,
|
|
63
63
|
input.canonicalVersion ?? null,
|
package/src/sql-runtime.ts
CHANGED
|
@@ -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 {
|
|
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
|
|
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
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
|
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.
|
|
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
|
|
91
|
-
...(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.
|
|
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(
|
|
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:
|
|
218
|
+
export function createRuntime<TContract extends SqlContract<SqlStorage>, TTargetId extends string>(
|
|
219
|
+
options: CreateRuntimeOptions<TContract, TTargetId>,
|
|
164
220
|
): Runtime {
|
|
165
|
-
|
|
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 {
|
|
5
|
-
import {
|
|
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
|
|
18
|
-
): Promise<{ rows: ReadonlyArray<
|
|
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
|
|
33
|
-
|
|
38
|
+
async acquireConnection(): Promise<never> {
|
|
39
|
+
throw new Error('Not implemented in mock');
|
|
34
40
|
}
|
|
35
41
|
|
|
36
|
-
async
|
|
37
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
130
|
-
|
|
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 {
|
|
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('
|
|
37
|
-
//
|
|
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<
|
|
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('
|
|
48
|
-
// Verify the contract type is preserved in
|
|
49
|
-
expectTypeOf<
|
|
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 =
|
|
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('
|
|
66
|
-
// Verify
|
|
67
|
-
type DefaultContext =
|
|
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
|
|
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
|
+
});
|