@prisma/client-engine-runtime 6.8.0-dev.10 → 6.8.0-dev.12
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/dist/QueryPlan.d.ts +47 -0
- package/dist/index.d.mts +49 -0
- package/dist/index.d.ts +49 -0
- package/dist/index.js +66 -0
- package/dist/index.mjs +66 -0
- package/dist/interpreter/validation.d.ts +2 -0
- package/package.json +3 -3
package/dist/QueryPlan.d.ts
CHANGED
|
@@ -141,4 +141,51 @@ export type QueryPlanNode = {
|
|
|
141
141
|
expr: QueryPlanNode;
|
|
142
142
|
structure: ResultNode;
|
|
143
143
|
};
|
|
144
|
+
} | {
|
|
145
|
+
type: 'validate';
|
|
146
|
+
args: {
|
|
147
|
+
expr: QueryPlanNode;
|
|
148
|
+
rules: DataRule[];
|
|
149
|
+
} & ValidationError;
|
|
150
|
+
};
|
|
151
|
+
export type DataRule = {
|
|
152
|
+
type: 'rowCountEq';
|
|
153
|
+
args: number;
|
|
154
|
+
} | {
|
|
155
|
+
type: 'rowCountNeq';
|
|
156
|
+
args: number;
|
|
157
|
+
};
|
|
158
|
+
export type ValidationError = {
|
|
159
|
+
error_identifier: 'RELATION_VIOLATION';
|
|
160
|
+
context: {
|
|
161
|
+
relation: string;
|
|
162
|
+
modelA: string;
|
|
163
|
+
modelB: string;
|
|
164
|
+
};
|
|
165
|
+
} | {
|
|
166
|
+
error_identifier: 'MISSING_RELATED_RECORD';
|
|
167
|
+
context: {
|
|
168
|
+
model: string;
|
|
169
|
+
relation: string;
|
|
170
|
+
relationType: string;
|
|
171
|
+
operation: string;
|
|
172
|
+
neededFor?: string;
|
|
173
|
+
};
|
|
174
|
+
} | {
|
|
175
|
+
error_identifier: 'MISSING_RECORD';
|
|
176
|
+
context: {
|
|
177
|
+
operation: string;
|
|
178
|
+
};
|
|
179
|
+
} | {
|
|
180
|
+
error_identifier: 'INCOMPLETE_CONNECT_INPUT';
|
|
181
|
+
context: {
|
|
182
|
+
expectedRows: number;
|
|
183
|
+
};
|
|
184
|
+
} | {
|
|
185
|
+
error_identifier: 'RECORDS_NOT_CONNECTED';
|
|
186
|
+
context: {
|
|
187
|
+
relation: string;
|
|
188
|
+
parent: string;
|
|
189
|
+
child: string;
|
|
190
|
+
};
|
|
144
191
|
};
|
package/dist/index.d.mts
CHANGED
|
@@ -7,6 +7,14 @@ import { SqlQueryable } from '@prisma/driver-adapter-utils';
|
|
|
7
7
|
import { SqlResultSet } from '@prisma/driver-adapter-utils';
|
|
8
8
|
import { Transaction } from '@prisma/driver-adapter-utils';
|
|
9
9
|
|
|
10
|
+
export declare type DataRule = {
|
|
11
|
+
type: 'rowCountEq';
|
|
12
|
+
args: number;
|
|
13
|
+
} | {
|
|
14
|
+
type: 'rowCountNeq';
|
|
15
|
+
args: number;
|
|
16
|
+
};
|
|
17
|
+
|
|
10
18
|
declare type ExtendedSpanOptions = SpanOptions & {
|
|
11
19
|
name: string;
|
|
12
20
|
};
|
|
@@ -194,6 +202,12 @@ export declare type QueryPlanNode = {
|
|
|
194
202
|
expr: QueryPlanNode;
|
|
195
203
|
structure: ResultNode;
|
|
196
204
|
};
|
|
205
|
+
} | {
|
|
206
|
+
type: 'validate';
|
|
207
|
+
args: {
|
|
208
|
+
expr: QueryPlanNode;
|
|
209
|
+
rules: DataRule[];
|
|
210
|
+
} & ValidationError;
|
|
197
211
|
};
|
|
198
212
|
|
|
199
213
|
export declare type ResultNode = {
|
|
@@ -266,6 +280,41 @@ export declare class UserFacingError extends Error {
|
|
|
266
280
|
};
|
|
267
281
|
}
|
|
268
282
|
|
|
283
|
+
export declare type ValidationError = {
|
|
284
|
+
error_identifier: 'RELATION_VIOLATION';
|
|
285
|
+
context: {
|
|
286
|
+
relation: string;
|
|
287
|
+
modelA: string;
|
|
288
|
+
modelB: string;
|
|
289
|
+
};
|
|
290
|
+
} | {
|
|
291
|
+
error_identifier: 'MISSING_RELATED_RECORD';
|
|
292
|
+
context: {
|
|
293
|
+
model: string;
|
|
294
|
+
relation: string;
|
|
295
|
+
relationType: string;
|
|
296
|
+
operation: string;
|
|
297
|
+
neededFor?: string;
|
|
298
|
+
};
|
|
299
|
+
} | {
|
|
300
|
+
error_identifier: 'MISSING_RECORD';
|
|
301
|
+
context: {
|
|
302
|
+
operation: string;
|
|
303
|
+
};
|
|
304
|
+
} | {
|
|
305
|
+
error_identifier: 'INCOMPLETE_CONNECT_INPUT';
|
|
306
|
+
context: {
|
|
307
|
+
expectedRows: number;
|
|
308
|
+
};
|
|
309
|
+
} | {
|
|
310
|
+
error_identifier: 'RECORDS_NOT_CONNECTED';
|
|
311
|
+
context: {
|
|
312
|
+
relation: string;
|
|
313
|
+
parent: string;
|
|
314
|
+
child: string;
|
|
315
|
+
};
|
|
316
|
+
};
|
|
317
|
+
|
|
269
318
|
/**
|
|
270
319
|
* The general type of values each node can evaluate to.
|
|
271
320
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -7,6 +7,14 @@ import { SqlQueryable } from '@prisma/driver-adapter-utils';
|
|
|
7
7
|
import { SqlResultSet } from '@prisma/driver-adapter-utils';
|
|
8
8
|
import { Transaction } from '@prisma/driver-adapter-utils';
|
|
9
9
|
|
|
10
|
+
export declare type DataRule = {
|
|
11
|
+
type: 'rowCountEq';
|
|
12
|
+
args: number;
|
|
13
|
+
} | {
|
|
14
|
+
type: 'rowCountNeq';
|
|
15
|
+
args: number;
|
|
16
|
+
};
|
|
17
|
+
|
|
10
18
|
declare type ExtendedSpanOptions = SpanOptions & {
|
|
11
19
|
name: string;
|
|
12
20
|
};
|
|
@@ -194,6 +202,12 @@ export declare type QueryPlanNode = {
|
|
|
194
202
|
expr: QueryPlanNode;
|
|
195
203
|
structure: ResultNode;
|
|
196
204
|
};
|
|
205
|
+
} | {
|
|
206
|
+
type: 'validate';
|
|
207
|
+
args: {
|
|
208
|
+
expr: QueryPlanNode;
|
|
209
|
+
rules: DataRule[];
|
|
210
|
+
} & ValidationError;
|
|
197
211
|
};
|
|
198
212
|
|
|
199
213
|
export declare type ResultNode = {
|
|
@@ -266,6 +280,41 @@ export declare class UserFacingError extends Error {
|
|
|
266
280
|
};
|
|
267
281
|
}
|
|
268
282
|
|
|
283
|
+
export declare type ValidationError = {
|
|
284
|
+
error_identifier: 'RELATION_VIOLATION';
|
|
285
|
+
context: {
|
|
286
|
+
relation: string;
|
|
287
|
+
modelA: string;
|
|
288
|
+
modelB: string;
|
|
289
|
+
};
|
|
290
|
+
} | {
|
|
291
|
+
error_identifier: 'MISSING_RELATED_RECORD';
|
|
292
|
+
context: {
|
|
293
|
+
model: string;
|
|
294
|
+
relation: string;
|
|
295
|
+
relationType: string;
|
|
296
|
+
operation: string;
|
|
297
|
+
neededFor?: string;
|
|
298
|
+
};
|
|
299
|
+
} | {
|
|
300
|
+
error_identifier: 'MISSING_RECORD';
|
|
301
|
+
context: {
|
|
302
|
+
operation: string;
|
|
303
|
+
};
|
|
304
|
+
} | {
|
|
305
|
+
error_identifier: 'INCOMPLETE_CONNECT_INPUT';
|
|
306
|
+
context: {
|
|
307
|
+
expectedRows: number;
|
|
308
|
+
};
|
|
309
|
+
} | {
|
|
310
|
+
error_identifier: 'RECORDS_NOT_CONNECTED';
|
|
311
|
+
context: {
|
|
312
|
+
relation: string;
|
|
313
|
+
parent: string;
|
|
314
|
+
child: string;
|
|
315
|
+
};
|
|
316
|
+
};
|
|
317
|
+
|
|
269
318
|
/**
|
|
270
319
|
* The general type of values each node can evaluate to.
|
|
271
320
|
*/
|
package/dist/index.js
CHANGED
|
@@ -581,6 +581,67 @@ function serializeSql(resultSet) {
|
|
|
581
581
|
);
|
|
582
582
|
}
|
|
583
583
|
|
|
584
|
+
// src/interpreter/validation.ts
|
|
585
|
+
function performValidation(data, rules, error) {
|
|
586
|
+
if (!rules.every((rule) => doesSatisfyRule(data, rule))) {
|
|
587
|
+
const message = renderMessage(data, error);
|
|
588
|
+
const code = getErrorCode2(error);
|
|
589
|
+
throw new UserFacingError(message, code, error.context);
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
function doesSatisfyRule(data, rule) {
|
|
593
|
+
switch (rule.type) {
|
|
594
|
+
case "rowCountEq":
|
|
595
|
+
if (Array.isArray(data)) {
|
|
596
|
+
return data.length === rule.args;
|
|
597
|
+
}
|
|
598
|
+
if (data === null) {
|
|
599
|
+
return rule.args === 0;
|
|
600
|
+
}
|
|
601
|
+
return rule.args === 1;
|
|
602
|
+
case "rowCountNeq":
|
|
603
|
+
if (Array.isArray(data)) {
|
|
604
|
+
return data.length !== rule.args;
|
|
605
|
+
}
|
|
606
|
+
if (data === null) {
|
|
607
|
+
return rule.args !== 0;
|
|
608
|
+
}
|
|
609
|
+
return rule.args !== 1;
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
function renderMessage(data, error) {
|
|
613
|
+
switch (error.error_identifier) {
|
|
614
|
+
case "RELATION_VIOLATION":
|
|
615
|
+
return `The change you are trying to make would violate the required relation '${error.context.relation}' between the \`${error.context.modelA}\` and \`${error.context.modelB}\` models.`;
|
|
616
|
+
case "MISSING_RECORD":
|
|
617
|
+
return `No record was found for ${error.context.operation}.`;
|
|
618
|
+
case "MISSING_RELATED_RECORD": {
|
|
619
|
+
const hint = error.context.neededFor ? ` (needed to ${error.context.neededFor})` : "";
|
|
620
|
+
return `An operation failed because it depends on one or more records that were required but not found. No '${error.context.model}' record${hint} was found for ${error.context.operation} on ${error.context.relationType} relation '${error.context.relation}'.`;
|
|
621
|
+
}
|
|
622
|
+
case "INCOMPLETE_CONNECT_INPUT":
|
|
623
|
+
return `An operation failed because it depends on one or more records that were required but not found. Expected ${error.context.expectedRows} records to be connected, found only ${Array.isArray(data) ? data.length : 0}.`;
|
|
624
|
+
case "RECORDS_NOT_CONNECTED":
|
|
625
|
+
return `The records for relation \`${error.context.relation}\` between the \`${error.context.parent}\` and \`${error.context.child}\` models are not connected.`;
|
|
626
|
+
default:
|
|
627
|
+
assertNever(error, `Unknown error identifier: ${error}`);
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
function getErrorCode2(error) {
|
|
631
|
+
switch (error.error_identifier) {
|
|
632
|
+
case "RELATION_VIOLATION":
|
|
633
|
+
return "P2014";
|
|
634
|
+
case "RECORDS_NOT_CONNECTED":
|
|
635
|
+
return "P2017";
|
|
636
|
+
case "MISSING_RECORD":
|
|
637
|
+
case "MISSING_RELATED_RECORD":
|
|
638
|
+
case "INCOMPLETE_CONNECT_INPUT":
|
|
639
|
+
return "P2025";
|
|
640
|
+
default:
|
|
641
|
+
assertNever(error, `Unknown error identifier: ${error}`);
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
|
|
584
645
|
// src/interpreter/QueryInterpreter.ts
|
|
585
646
|
var QueryInterpreter = class _QueryInterpreter {
|
|
586
647
|
#transactionManager;
|
|
@@ -718,6 +779,11 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
718
779
|
const data = await this.interpretNode(node.args.expr, queryable, scope, generators);
|
|
719
780
|
return applyDataMap(data, node.args.structure);
|
|
720
781
|
}
|
|
782
|
+
case "validate": {
|
|
783
|
+
const data = await this.interpretNode(node.args.expr, queryable, scope, generators);
|
|
784
|
+
performValidation(data, node.args.rules, node.args);
|
|
785
|
+
return data;
|
|
786
|
+
}
|
|
721
787
|
default:
|
|
722
788
|
assertNever(node, `Unexpected node type: ${node.type}`);
|
|
723
789
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -539,6 +539,67 @@ function serializeSql(resultSet) {
|
|
|
539
539
|
);
|
|
540
540
|
}
|
|
541
541
|
|
|
542
|
+
// src/interpreter/validation.ts
|
|
543
|
+
function performValidation(data, rules, error) {
|
|
544
|
+
if (!rules.every((rule) => doesSatisfyRule(data, rule))) {
|
|
545
|
+
const message = renderMessage(data, error);
|
|
546
|
+
const code = getErrorCode2(error);
|
|
547
|
+
throw new UserFacingError(message, code, error.context);
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
function doesSatisfyRule(data, rule) {
|
|
551
|
+
switch (rule.type) {
|
|
552
|
+
case "rowCountEq":
|
|
553
|
+
if (Array.isArray(data)) {
|
|
554
|
+
return data.length === rule.args;
|
|
555
|
+
}
|
|
556
|
+
if (data === null) {
|
|
557
|
+
return rule.args === 0;
|
|
558
|
+
}
|
|
559
|
+
return rule.args === 1;
|
|
560
|
+
case "rowCountNeq":
|
|
561
|
+
if (Array.isArray(data)) {
|
|
562
|
+
return data.length !== rule.args;
|
|
563
|
+
}
|
|
564
|
+
if (data === null) {
|
|
565
|
+
return rule.args !== 0;
|
|
566
|
+
}
|
|
567
|
+
return rule.args !== 1;
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
function renderMessage(data, error) {
|
|
571
|
+
switch (error.error_identifier) {
|
|
572
|
+
case "RELATION_VIOLATION":
|
|
573
|
+
return `The change you are trying to make would violate the required relation '${error.context.relation}' between the \`${error.context.modelA}\` and \`${error.context.modelB}\` models.`;
|
|
574
|
+
case "MISSING_RECORD":
|
|
575
|
+
return `No record was found for ${error.context.operation}.`;
|
|
576
|
+
case "MISSING_RELATED_RECORD": {
|
|
577
|
+
const hint = error.context.neededFor ? ` (needed to ${error.context.neededFor})` : "";
|
|
578
|
+
return `An operation failed because it depends on one or more records that were required but not found. No '${error.context.model}' record${hint} was found for ${error.context.operation} on ${error.context.relationType} relation '${error.context.relation}'.`;
|
|
579
|
+
}
|
|
580
|
+
case "INCOMPLETE_CONNECT_INPUT":
|
|
581
|
+
return `An operation failed because it depends on one or more records that were required but not found. Expected ${error.context.expectedRows} records to be connected, found only ${Array.isArray(data) ? data.length : 0}.`;
|
|
582
|
+
case "RECORDS_NOT_CONNECTED":
|
|
583
|
+
return `The records for relation \`${error.context.relation}\` between the \`${error.context.parent}\` and \`${error.context.child}\` models are not connected.`;
|
|
584
|
+
default:
|
|
585
|
+
assertNever(error, `Unknown error identifier: ${error}`);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
function getErrorCode2(error) {
|
|
589
|
+
switch (error.error_identifier) {
|
|
590
|
+
case "RELATION_VIOLATION":
|
|
591
|
+
return "P2014";
|
|
592
|
+
case "RECORDS_NOT_CONNECTED":
|
|
593
|
+
return "P2017";
|
|
594
|
+
case "MISSING_RECORD":
|
|
595
|
+
case "MISSING_RELATED_RECORD":
|
|
596
|
+
case "INCOMPLETE_CONNECT_INPUT":
|
|
597
|
+
return "P2025";
|
|
598
|
+
default:
|
|
599
|
+
assertNever(error, `Unknown error identifier: ${error}`);
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
|
|
542
603
|
// src/interpreter/QueryInterpreter.ts
|
|
543
604
|
var QueryInterpreter = class _QueryInterpreter {
|
|
544
605
|
#transactionManager;
|
|
@@ -676,6 +737,11 @@ var QueryInterpreter = class _QueryInterpreter {
|
|
|
676
737
|
const data = await this.interpretNode(node.args.expr, queryable, scope, generators);
|
|
677
738
|
return applyDataMap(data, node.args.structure);
|
|
678
739
|
}
|
|
740
|
+
case "validate": {
|
|
741
|
+
const data = await this.interpretNode(node.args.expr, queryable, scope, generators);
|
|
742
|
+
performValidation(data, node.args.rules, node.args);
|
|
743
|
+
return data;
|
|
744
|
+
}
|
|
679
745
|
default:
|
|
680
746
|
assertNever(node, `Unexpected node type: ${node.type}`);
|
|
681
747
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma/client-engine-runtime",
|
|
3
|
-
"version": "6.8.0-dev.
|
|
3
|
+
"version": "6.8.0-dev.12",
|
|
4
4
|
"description": "This package is intended for Prisma's internal use",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
"nanoid": "5.1.5",
|
|
31
31
|
"ulid": "3.0.0",
|
|
32
32
|
"uuid": "11.1.0",
|
|
33
|
-
"@prisma/debug": "6.8.0-dev.
|
|
34
|
-
"@prisma/driver-adapter-utils": "6.8.0-dev.
|
|
33
|
+
"@prisma/debug": "6.8.0-dev.12",
|
|
34
|
+
"@prisma/driver-adapter-utils": "6.8.0-dev.12"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@types/jest": "29.5.14",
|