@prisma-next/sql-runtime 0.3.0-dev.34 → 0.3.0-dev.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
package/package.json
CHANGED
|
@@ -1,27 +1,30 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma-next/sql-runtime",
|
|
3
|
-
"version": "0.3.0-dev.
|
|
3
|
+
"version": "0.3.0-dev.37",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"description": "SQL runtime implementation for Prisma Next",
|
|
7
7
|
"dependencies": {
|
|
8
8
|
"arktype": "^2.1.26",
|
|
9
|
-
"@prisma-next/
|
|
10
|
-
"@prisma-next/core-execution-plane": "0.3.0-dev.
|
|
11
|
-
"@prisma-next/
|
|
12
|
-
"@prisma-next/
|
|
13
|
-
"@prisma-next/
|
|
14
|
-
"@prisma-next/
|
|
15
|
-
"@prisma-next/sql-
|
|
9
|
+
"@prisma-next/utils": "0.3.0-dev.37",
|
|
10
|
+
"@prisma-next/core-execution-plane": "0.3.0-dev.37",
|
|
11
|
+
"@prisma-next/ids": "0.3.0-dev.37",
|
|
12
|
+
"@prisma-next/contract": "0.3.0-dev.37",
|
|
13
|
+
"@prisma-next/operations": "0.3.0-dev.37",
|
|
14
|
+
"@prisma-next/runtime-executor": "0.3.0-dev.37",
|
|
15
|
+
"@prisma-next/sql-operations": "0.3.0-dev.37",
|
|
16
|
+
"@prisma-next/sql-relational-core": "0.3.0-dev.37",
|
|
17
|
+
"@prisma-next/sql-contract": "0.3.0-dev.37"
|
|
16
18
|
},
|
|
17
19
|
"devDependencies": {
|
|
18
20
|
"@types/pg": "8.16.0",
|
|
19
21
|
"pg": "8.16.3",
|
|
20
|
-
"
|
|
22
|
+
"tsdown": "0.18.4",
|
|
21
23
|
"typescript": "5.9.3",
|
|
22
|
-
"vitest": "4.0.
|
|
24
|
+
"vitest": "4.0.17",
|
|
23
25
|
"@prisma-next/test-utils": "0.0.1",
|
|
24
|
-
"@prisma-next/tsconfig": "0.0.0"
|
|
26
|
+
"@prisma-next/tsconfig": "0.0.0",
|
|
27
|
+
"@prisma-next/tsdown": "0.0.0"
|
|
25
28
|
},
|
|
26
29
|
"files": [
|
|
27
30
|
"dist",
|
|
@@ -29,17 +32,20 @@
|
|
|
29
32
|
"test"
|
|
30
33
|
],
|
|
31
34
|
"exports": {
|
|
32
|
-
".":
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
35
|
+
".": "./dist/index.mjs",
|
|
36
|
+
"./test/utils": "./dist/test/utils.mjs",
|
|
37
|
+
"./package.json": "./package.json"
|
|
38
|
+
},
|
|
39
|
+
"main": "./dist/index.mjs",
|
|
40
|
+
"module": "./dist/index.mjs",
|
|
41
|
+
"types": "./dist/index.d.mts",
|
|
42
|
+
"repository": {
|
|
43
|
+
"type": "git",
|
|
44
|
+
"url": "https://github.com/prisma/prisma-next.git",
|
|
45
|
+
"directory": "packages/2-sql/5-runtime"
|
|
40
46
|
},
|
|
41
47
|
"scripts": {
|
|
42
|
-
"build": "
|
|
48
|
+
"build": "tsdown",
|
|
43
49
|
"test": "vitest run --passWithNoTests",
|
|
44
50
|
"test:coverage": "vitest run --coverage --passWithNoTests",
|
|
45
51
|
"typecheck": "tsc --project tsconfig.json --noEmit",
|
package/src/codecs/decoding.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { ExecutionPlan } from '@prisma-next/contract/types';
|
|
2
2
|
import type { Codec, CodecRegistry } from '@prisma-next/sql-relational-core/ast';
|
|
3
|
+
import type { JsonSchemaValidatorRegistry } from '@prisma-next/sql-relational-core/query-lane-context';
|
|
4
|
+
import { validateJsonValue } from './json-schema-validation';
|
|
3
5
|
|
|
4
6
|
function resolveRowCodec(
|
|
5
7
|
alias: string,
|
|
@@ -27,15 +29,69 @@ function resolveRowCodec(
|
|
|
27
29
|
return null;
|
|
28
30
|
}
|
|
29
31
|
|
|
32
|
+
type ColumnRefIndex = Map<string, { table: string; column: string }>;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Builds a lookup index from column name → { table, column } ref.
|
|
36
|
+
* Called once per decodeRow invocation to avoid O(aliases × refs) linear scans.
|
|
37
|
+
*/
|
|
38
|
+
function buildColumnRefIndex(plan: ExecutionPlan): ColumnRefIndex | null {
|
|
39
|
+
const columns = plan.meta.refs?.columns;
|
|
40
|
+
if (!columns) return null;
|
|
41
|
+
|
|
42
|
+
const index: ColumnRefIndex = new Map();
|
|
43
|
+
for (const ref of columns) {
|
|
44
|
+
index.set(ref.column, ref);
|
|
45
|
+
}
|
|
46
|
+
return index;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function parseProjectionRef(value: string): { table: string; column: string } | null {
|
|
50
|
+
if (value.startsWith('include:') || value.startsWith('operation:')) {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const separatorIndex = value.indexOf('.');
|
|
55
|
+
if (separatorIndex <= 0 || separatorIndex === value.length - 1) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
table: value.slice(0, separatorIndex),
|
|
61
|
+
column: value.slice(separatorIndex + 1),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function resolveColumnRefForAlias(
|
|
66
|
+
alias: string,
|
|
67
|
+
projection: ExecutionPlan['meta']['projection'],
|
|
68
|
+
fallbackColumnRefIndex: ColumnRefIndex | null,
|
|
69
|
+
): { table: string; column: string } | undefined {
|
|
70
|
+
if (projection && !Array.isArray(projection)) {
|
|
71
|
+
const mappedRef = (projection as Record<string, string>)[alias];
|
|
72
|
+
if (typeof mappedRef !== 'string') {
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
return parseProjectionRef(mappedRef) ?? undefined;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return fallbackColumnRefIndex?.get(alias);
|
|
79
|
+
}
|
|
80
|
+
|
|
30
81
|
export function decodeRow(
|
|
31
82
|
row: Record<string, unknown>,
|
|
32
83
|
plan: ExecutionPlan,
|
|
33
84
|
registry: CodecRegistry,
|
|
85
|
+
jsonValidators?: JsonSchemaValidatorRegistry,
|
|
34
86
|
): Record<string, unknown> {
|
|
35
87
|
const decoded: Record<string, unknown> = {};
|
|
88
|
+
const projection = plan.meta.projection;
|
|
89
|
+
|
|
90
|
+
// Fallback for plans that do not provide projection alias -> table.column mapping.
|
|
91
|
+
const fallbackColumnRefIndex =
|
|
92
|
+
jsonValidators && (!projection || Array.isArray(projection)) ? buildColumnRefIndex(plan) : null;
|
|
36
93
|
|
|
37
94
|
let aliases: readonly string[];
|
|
38
|
-
const projection = plan.meta.projection;
|
|
39
95
|
if (projection && !Array.isArray(projection)) {
|
|
40
96
|
aliases = Object.keys(projection);
|
|
41
97
|
} else if (projection && Array.isArray(projection)) {
|
|
@@ -47,7 +103,6 @@ export function decodeRow(
|
|
|
47
103
|
for (const alias of aliases) {
|
|
48
104
|
const wireValue = row[alias];
|
|
49
105
|
|
|
50
|
-
const projection = plan.meta.projection;
|
|
51
106
|
const projectionValue =
|
|
52
107
|
projection && typeof projection === 'object' && !Array.isArray(projection)
|
|
53
108
|
? (projection as Record<string, string>)[alias]
|
|
@@ -111,8 +166,34 @@ export function decodeRow(
|
|
|
111
166
|
}
|
|
112
167
|
|
|
113
168
|
try {
|
|
114
|
-
|
|
169
|
+
const decodedValue = codec.decode(wireValue);
|
|
170
|
+
|
|
171
|
+
// Validate decoded JSON value against schema
|
|
172
|
+
if (jsonValidators) {
|
|
173
|
+
const ref = resolveColumnRefForAlias(alias, projection, fallbackColumnRefIndex);
|
|
174
|
+
if (ref) {
|
|
175
|
+
validateJsonValue(
|
|
176
|
+
jsonValidators,
|
|
177
|
+
ref.table,
|
|
178
|
+
ref.column,
|
|
179
|
+
decodedValue,
|
|
180
|
+
'decode',
|
|
181
|
+
codec.id,
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
decoded[alias] = decodedValue;
|
|
115
187
|
} catch (error) {
|
|
188
|
+
// Re-throw JSON schema validation errors as-is
|
|
189
|
+
if (
|
|
190
|
+
error instanceof Error &&
|
|
191
|
+
'code' in error &&
|
|
192
|
+
(error as Error & { code: string }).code === 'RUNTIME.JSON_SCHEMA_VALIDATION_FAILED'
|
|
193
|
+
) {
|
|
194
|
+
throw error;
|
|
195
|
+
}
|
|
196
|
+
|
|
116
197
|
const decodeError = new Error(
|
|
117
198
|
`Failed to decode row alias '${alias}' with codec '${codec.id}': ${error instanceof Error ? error.message : String(error)}`,
|
|
118
199
|
) as Error & {
|
package/src/codecs/encoding.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { ExecutionPlan, ParamDescriptor } from '@prisma-next/contract/types';
|
|
2
2
|
import type { Codec, CodecRegistry } from '@prisma-next/sql-relational-core/ast';
|
|
3
|
+
import type { JsonSchemaValidatorRegistry } from '@prisma-next/sql-relational-core/query-lane-context';
|
|
4
|
+
import { validateJsonValue } from './json-schema-validation';
|
|
3
5
|
|
|
4
6
|
function resolveParamCodec(
|
|
5
7
|
paramDescriptor: ParamDescriptor,
|
|
@@ -31,11 +33,18 @@ export function encodeParam(
|
|
|
31
33
|
paramDescriptor: ParamDescriptor,
|
|
32
34
|
plan: ExecutionPlan,
|
|
33
35
|
registry: CodecRegistry,
|
|
36
|
+
jsonValidators?: JsonSchemaValidatorRegistry,
|
|
34
37
|
): unknown {
|
|
35
38
|
if (value === null || value === undefined) {
|
|
36
39
|
return null;
|
|
37
40
|
}
|
|
38
41
|
|
|
42
|
+
// Validate JSON value against schema before encoding
|
|
43
|
+
if (jsonValidators && paramDescriptor.refs) {
|
|
44
|
+
const { table, column } = paramDescriptor.refs;
|
|
45
|
+
validateJsonValue(jsonValidators, table, column, value, 'encode', paramDescriptor.codecId);
|
|
46
|
+
}
|
|
47
|
+
|
|
39
48
|
const codec = resolveParamCodec(paramDescriptor, plan, registry);
|
|
40
49
|
if (!codec) {
|
|
41
50
|
return value;
|
|
@@ -54,7 +63,11 @@ export function encodeParam(
|
|
|
54
63
|
return value;
|
|
55
64
|
}
|
|
56
65
|
|
|
57
|
-
export function encodeParams(
|
|
66
|
+
export function encodeParams(
|
|
67
|
+
plan: ExecutionPlan,
|
|
68
|
+
registry: CodecRegistry,
|
|
69
|
+
jsonValidators?: JsonSchemaValidatorRegistry,
|
|
70
|
+
): readonly unknown[] {
|
|
58
71
|
if (plan.params.length === 0) {
|
|
59
72
|
return plan.params;
|
|
60
73
|
}
|
|
@@ -66,7 +79,7 @@ export function encodeParams(plan: ExecutionPlan, registry: CodecRegistry): read
|
|
|
66
79
|
const paramDescriptor = plan.meta.paramDescriptors[i];
|
|
67
80
|
|
|
68
81
|
if (paramDescriptor) {
|
|
69
|
-
encoded.push(encodeParam(paramValue, paramDescriptor, plan, registry));
|
|
82
|
+
encoded.push(encodeParam(paramValue, paramDescriptor, plan, registry, jsonValidators));
|
|
70
83
|
} else {
|
|
71
84
|
encoded.push(paramValue);
|
|
72
85
|
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { runtimeError } from '@prisma-next/runtime-executor';
|
|
2
|
+
import type {
|
|
3
|
+
JsonSchemaValidationError,
|
|
4
|
+
JsonSchemaValidatorRegistry,
|
|
5
|
+
} from '@prisma-next/sql-relational-core/query-lane-context';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Validates a JSON value against its column's JSON Schema, if a validator exists.
|
|
9
|
+
*
|
|
10
|
+
* Throws `RUNTIME.JSON_SCHEMA_VALIDATION_FAILED` on validation failure.
|
|
11
|
+
* No-ops if no validator is registered for the column.
|
|
12
|
+
*/
|
|
13
|
+
export function validateJsonValue(
|
|
14
|
+
registry: JsonSchemaValidatorRegistry,
|
|
15
|
+
table: string,
|
|
16
|
+
column: string,
|
|
17
|
+
value: unknown,
|
|
18
|
+
direction: 'encode' | 'decode',
|
|
19
|
+
codecId?: string,
|
|
20
|
+
): void {
|
|
21
|
+
const key = `${table}.${column}`;
|
|
22
|
+
const validate = registry.get(key);
|
|
23
|
+
if (!validate) return;
|
|
24
|
+
|
|
25
|
+
const result = validate(value);
|
|
26
|
+
if (result.valid) return;
|
|
27
|
+
|
|
28
|
+
throw createJsonSchemaValidationError(table, column, direction, result.errors, codecId);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function createJsonSchemaValidationError(
|
|
32
|
+
table: string,
|
|
33
|
+
column: string,
|
|
34
|
+
direction: 'encode' | 'decode',
|
|
35
|
+
errors: ReadonlyArray<JsonSchemaValidationError>,
|
|
36
|
+
codecId?: string,
|
|
37
|
+
): Error {
|
|
38
|
+
const summary = formatErrorSummary(errors);
|
|
39
|
+
return runtimeError(
|
|
40
|
+
'RUNTIME.JSON_SCHEMA_VALIDATION_FAILED',
|
|
41
|
+
`JSON schema validation failed for column '${table}.${column}' (${direction}): ${summary}`,
|
|
42
|
+
{
|
|
43
|
+
table,
|
|
44
|
+
column,
|
|
45
|
+
codecId,
|
|
46
|
+
direction,
|
|
47
|
+
errors: [...errors],
|
|
48
|
+
},
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function formatErrorSummary(errors: ReadonlyArray<JsonSchemaValidationError>): string {
|
|
53
|
+
if (errors.length === 0) return 'unknown validation error';
|
|
54
|
+
if (errors.length === 1) {
|
|
55
|
+
const err = errors[0] as JsonSchemaValidationError;
|
|
56
|
+
return err.path === '/' ? err.message : `${err.path}: ${err.message}`;
|
|
57
|
+
}
|
|
58
|
+
return errors
|
|
59
|
+
.map((err) => (err.path === '/' ? err.message : `${err.path}: ${err.message}`))
|
|
60
|
+
.join('; ');
|
|
61
|
+
}
|
package/src/exports/index.ts
CHANGED
|
@@ -14,15 +14,20 @@ export {
|
|
|
14
14
|
} from '../codecs/validation';
|
|
15
15
|
export { lowerSqlPlan } from '../lower-sql-plan';
|
|
16
16
|
export type {
|
|
17
|
-
|
|
18
|
-
RuntimeContext,
|
|
17
|
+
ExecutionContext,
|
|
19
18
|
RuntimeParameterizedCodecDescriptor,
|
|
19
|
+
SqlExecutionStack,
|
|
20
|
+
SqlExecutionStackWithDriver,
|
|
21
|
+
SqlRuntimeAdapterDescriptor,
|
|
20
22
|
SqlRuntimeAdapterInstance,
|
|
23
|
+
SqlRuntimeDriverInstance,
|
|
21
24
|
SqlRuntimeExtensionDescriptor,
|
|
22
25
|
SqlRuntimeExtensionInstance,
|
|
26
|
+
SqlRuntimeTargetDescriptor,
|
|
27
|
+
SqlStaticContributions,
|
|
23
28
|
TypeHelperRegistry,
|
|
24
29
|
} from '../sql-context';
|
|
25
|
-
export {
|
|
30
|
+
export { createExecutionContext, createSqlExecutionStack } from '../sql-context';
|
|
26
31
|
export type { SqlStatement } from '../sql-marker';
|
|
27
32
|
export {
|
|
28
33
|
ensureSchemaStatement,
|
|
@@ -31,8 +36,8 @@ export {
|
|
|
31
36
|
writeContractMarker,
|
|
32
37
|
} from '../sql-marker';
|
|
33
38
|
export type {
|
|
39
|
+
CreateRuntimeOptions,
|
|
34
40
|
Runtime,
|
|
35
|
-
RuntimeOptions,
|
|
36
41
|
RuntimeTelemetryEvent,
|
|
37
42
|
RuntimeVerifyOptions,
|
|
38
43
|
TelemetryOutcome,
|
package/src/lower-sql-plan.ts
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import type { ExecutionPlan } from '@prisma-next/contract/types';
|
|
2
|
+
import type { SqlContract, SqlStorage } from '@prisma-next/sql-contract/types';
|
|
3
|
+
import type { Adapter, LoweredStatement, QueryAst } from '@prisma-next/sql-relational-core/ast';
|
|
2
4
|
import type { SqlQueryPlan } from '@prisma-next/sql-relational-core/plan';
|
|
3
|
-
import type { RuntimeContext } from './sql-context';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Lowers a SQL query plan to an executable Plan by calling the adapter's lower method.
|
|
7
8
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* @param context - Runtime context containing the adapter
|
|
9
|
+
* @param adapter - Adapter to lower AST to SQL
|
|
10
|
+
* @param contract - Contract for lowering context
|
|
12
11
|
* @param queryPlan - SQL query plan from a lane (contains AST, params, meta, but no SQL)
|
|
13
12
|
* @returns Fully executable Plan with SQL string
|
|
14
13
|
*/
|
|
15
14
|
export function lowerSqlPlan<Row>(
|
|
16
|
-
|
|
15
|
+
adapter: Adapter<QueryAst, SqlContract<SqlStorage>, LoweredStatement>,
|
|
16
|
+
contract: SqlContract<SqlStorage>,
|
|
17
17
|
queryPlan: SqlQueryPlan<Row>,
|
|
18
18
|
): ExecutionPlan<Row> {
|
|
19
|
-
const lowered =
|
|
20
|
-
contract
|
|
19
|
+
const lowered = adapter.lower(queryPlan.ast, {
|
|
20
|
+
contract,
|
|
21
21
|
params: queryPlan.params,
|
|
22
22
|
});
|
|
23
23
|
|