prisma-guard 1.19.0 → 1.21.0
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 +218 -20
- package/dist/generator/index.js +1 -1
- package/dist/generator/index.js.map +1 -1
- package/dist/runtime/index.cjs +637 -156
- package/dist/runtime/index.cjs.map +1 -1
- package/dist/runtime/index.d.cts +3 -3
- package/dist/runtime/index.d.ts +3 -3
- package/dist/runtime/index.js +637 -156
- package/dist/runtime/index.js.map +1 -1
- package/package.json +1 -1
package/dist/runtime/index.cjs
CHANGED
|
@@ -57,11 +57,92 @@ var CallerError = class extends Error {
|
|
|
57
57
|
this.name = "CallerError";
|
|
58
58
|
}
|
|
59
59
|
};
|
|
60
|
+
function formatIssue(issue) {
|
|
61
|
+
const path = issue.path.length > 0 ? `${issue.path.join(".")}: ` : "";
|
|
62
|
+
const code = issue.code;
|
|
63
|
+
if (code === "invalid_union") {
|
|
64
|
+
const unionErrors = issue.unionErrors;
|
|
65
|
+
if (unionErrors && unionErrors.length > 0) {
|
|
66
|
+
const branches = unionErrors.map((ue, i) => {
|
|
67
|
+
const nested = ue.issues.map(formatIssue).join(", ");
|
|
68
|
+
return `branch ${i + 1}: [${nested}]`;
|
|
69
|
+
}).join(" | ");
|
|
70
|
+
return `${path}No matching variant (${branches})`;
|
|
71
|
+
}
|
|
72
|
+
return `${path}No matching variant`;
|
|
73
|
+
}
|
|
74
|
+
if (issue.code === "unrecognized_keys") {
|
|
75
|
+
const keys = issue.keys;
|
|
76
|
+
if (keys && keys.length > 0) {
|
|
77
|
+
return `${path}Unrecognized key(s): ${keys.join(", ")}`;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (issue.code === "invalid_type") {
|
|
81
|
+
const expected = issue.expected;
|
|
82
|
+
const received = issue.received;
|
|
83
|
+
if (expected && received) {
|
|
84
|
+
return `${path}Expected ${expected}, received ${received}`;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if (code === "invalid_enum_value") {
|
|
88
|
+
const options = issue.options;
|
|
89
|
+
if (options) {
|
|
90
|
+
return `${path}Invalid value. Expected one of: ${options.join(", ")}`;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if (code === "too_small") {
|
|
94
|
+
const minimum = issue.minimum;
|
|
95
|
+
const type = issue.type;
|
|
96
|
+
if (type === "string" && minimum !== void 0) {
|
|
97
|
+
return `${path}String must contain at least ${minimum} character(s)`;
|
|
98
|
+
}
|
|
99
|
+
if (type === "array" && minimum !== void 0) {
|
|
100
|
+
return `${path}Array must contain at least ${minimum} element(s)`;
|
|
101
|
+
}
|
|
102
|
+
if (type === "number" && minimum !== void 0) {
|
|
103
|
+
return `${path}Number must be >= ${minimum}`;
|
|
104
|
+
}
|
|
105
|
+
return `${path}${issue.message}`;
|
|
106
|
+
}
|
|
107
|
+
if (code === "too_big") {
|
|
108
|
+
const maximum = issue.maximum;
|
|
109
|
+
const type = issue.type;
|
|
110
|
+
if (type === "string" && maximum !== void 0) {
|
|
111
|
+
return `${path}String must contain at most ${maximum} character(s)`;
|
|
112
|
+
}
|
|
113
|
+
if (type === "array" && maximum !== void 0) {
|
|
114
|
+
return `${path}Array must contain at most ${maximum} element(s)`;
|
|
115
|
+
}
|
|
116
|
+
if (type === "number" && maximum !== void 0) {
|
|
117
|
+
return `${path}Number must be <= ${maximum}`;
|
|
118
|
+
}
|
|
119
|
+
return `${path}${issue.message}`;
|
|
120
|
+
}
|
|
121
|
+
if (code === "invalid_format") {
|
|
122
|
+
const format = issue.format;
|
|
123
|
+
if (format) {
|
|
124
|
+
return `${path}Invalid ${format} format`;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
if (code === "invalid_value") {
|
|
128
|
+
const values = issue.values;
|
|
129
|
+
if (values) {
|
|
130
|
+
return `${path}Invalid value. Expected one of: ${values.join(", ")}`;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return `${path}${issue.message}`;
|
|
134
|
+
}
|
|
60
135
|
function formatZodError(err) {
|
|
61
|
-
return err.issues.map((
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
136
|
+
return err.issues.map(formatIssue).join("; ");
|
|
137
|
+
}
|
|
138
|
+
function wrapParseError(err, context) {
|
|
139
|
+
if (err instanceof ShapeError) {
|
|
140
|
+
throw new ShapeError(`${context}: ${err.message}`, { cause: err });
|
|
141
|
+
}
|
|
142
|
+
if (err && typeof err === "object" && "issues" in err) {
|
|
143
|
+
throw new ShapeError(`${context}: ${formatZodError(err)}`, { cause: err });
|
|
144
|
+
}
|
|
145
|
+
throw err;
|
|
65
146
|
}
|
|
66
147
|
|
|
67
148
|
// src/shared/scalar-base.ts
|
|
@@ -207,15 +288,19 @@ function coerceToArray(value) {
|
|
|
207
288
|
return value;
|
|
208
289
|
const keys = Object.keys(value);
|
|
209
290
|
if (keys.length === 0)
|
|
210
|
-
return
|
|
291
|
+
return value;
|
|
211
292
|
const allNumeric = keys.every((k) => /^\d+$/.test(k));
|
|
212
293
|
if (!allNumeric)
|
|
213
294
|
return value;
|
|
214
|
-
const
|
|
295
|
+
const indices = keys.map(Number).sort((a, b) => a - b);
|
|
296
|
+
for (let i = 0; i < indices.length; i++) {
|
|
297
|
+
if (indices[i] !== i)
|
|
298
|
+
return value;
|
|
299
|
+
}
|
|
215
300
|
const obj = value;
|
|
216
|
-
const result =
|
|
217
|
-
for (
|
|
218
|
-
result
|
|
301
|
+
const result = new Array(indices.length);
|
|
302
|
+
for (let i = 0; i < indices.length; i++) {
|
|
303
|
+
result[i] = obj[String(i)];
|
|
219
304
|
}
|
|
220
305
|
return result;
|
|
221
306
|
}
|
|
@@ -233,7 +318,8 @@ var SCALAR_OPERATORS = {
|
|
|
233
318
|
"gt",
|
|
234
319
|
"gte",
|
|
235
320
|
"lt",
|
|
236
|
-
"lte"
|
|
321
|
+
"lte",
|
|
322
|
+
"search"
|
|
237
323
|
]),
|
|
238
324
|
Int: /* @__PURE__ */ new Set(["equals", "not", "gt", "gte", "lt", "lte", "in", "notIn"]),
|
|
239
325
|
Float: /* @__PURE__ */ new Set(["equals", "not", "gt", "gte", "lt", "lte", "in", "notIn"]),
|
|
@@ -335,7 +421,7 @@ function createScalarListOperatorSchema(fieldMeta, operator, enumMap, scalarBase
|
|
|
335
421
|
}
|
|
336
422
|
function createJsonOperatorSchema(fieldMeta, operator) {
|
|
337
423
|
const jsonValue = import_zod2.z.unknown();
|
|
338
|
-
if (operator === "equals"
|
|
424
|
+
if (operator === "equals") {
|
|
339
425
|
return !fieldMeta.isRequired ? import_zod2.z.union([jsonValue, import_zod2.z.null()]) : jsonValue;
|
|
340
426
|
}
|
|
341
427
|
if (operator === "path") {
|
|
@@ -351,6 +437,29 @@ function createJsonOperatorSchema(fieldMeta, operator) {
|
|
|
351
437
|
`Operator "${operator}" not supported for Json fields`
|
|
352
438
|
);
|
|
353
439
|
}
|
|
440
|
+
function buildNotFilterSchema(fieldMeta, scalarSchema, enumMap, scalarBase) {
|
|
441
|
+
const allOps = getSupportedOperators(fieldMeta);
|
|
442
|
+
const nestedOps = allOps.filter((o) => o !== "not");
|
|
443
|
+
if (nestedOps.length === 0)
|
|
444
|
+
return scalarSchema;
|
|
445
|
+
const nestedSchemas = {};
|
|
446
|
+
for (const op of nestedOps) {
|
|
447
|
+
nestedSchemas[op] = createOperatorSchema(
|
|
448
|
+
fieldMeta,
|
|
449
|
+
op,
|
|
450
|
+
enumMap,
|
|
451
|
+
scalarBase
|
|
452
|
+
).optional();
|
|
453
|
+
}
|
|
454
|
+
const nestedKeys = Object.keys(nestedSchemas);
|
|
455
|
+
const nestedObj = import_zod2.z.object(nestedSchemas).strict().refine(
|
|
456
|
+
(v) => nestedKeys.some(
|
|
457
|
+
(k) => v[k] !== void 0
|
|
458
|
+
),
|
|
459
|
+
{ message: "not filter must specify at least one operator" }
|
|
460
|
+
);
|
|
461
|
+
return import_zod2.z.union([scalarSchema, nestedObj]);
|
|
462
|
+
}
|
|
354
463
|
function createOperatorSchema(fieldMeta, operator, enumMap, scalarBase) {
|
|
355
464
|
if (fieldMeta.isList) {
|
|
356
465
|
return createScalarListOperatorSchema(
|
|
@@ -371,9 +480,13 @@ function createOperatorSchema(fieldMeta, operator, enumMap, scalarBase) {
|
|
|
371
480
|
);
|
|
372
481
|
}
|
|
373
482
|
const enumSchema = import_zod2.z.enum(values);
|
|
374
|
-
if (operator === "equals"
|
|
483
|
+
if (operator === "equals") {
|
|
375
484
|
return !fieldMeta.isRequired ? import_zod2.z.union([enumSchema, import_zod2.z.null()]) : enumSchema;
|
|
376
485
|
}
|
|
486
|
+
if (operator === "not") {
|
|
487
|
+
const scalarSchema = !fieldMeta.isRequired ? import_zod2.z.union([enumSchema, import_zod2.z.null()]) : enumSchema;
|
|
488
|
+
return buildNotFilterSchema(fieldMeta, scalarSchema, enumMap, scalarBase);
|
|
489
|
+
}
|
|
377
490
|
const itemSchema = !fieldMeta.isRequired ? import_zod2.z.union([enumSchema, import_zod2.z.null()]) : enumSchema;
|
|
378
491
|
return import_zod2.z.preprocess(coerceToArray, import_zod2.z.array(itemSchema));
|
|
379
492
|
}
|
|
@@ -384,6 +497,11 @@ function createOperatorSchema(fieldMeta, operator, enumMap, scalarBase) {
|
|
|
384
497
|
`Operator "${operator}" not supported for type "Json"`
|
|
385
498
|
);
|
|
386
499
|
}
|
|
500
|
+
if (operator === "not") {
|
|
501
|
+
const jsonValue = import_zod2.z.unknown();
|
|
502
|
+
const scalarSchema = !fieldMeta.isRequired ? import_zod2.z.union([jsonValue, import_zod2.z.null()]) : jsonValue;
|
|
503
|
+
return buildNotFilterSchema(fieldMeta, scalarSchema, enumMap, scalarBase);
|
|
504
|
+
}
|
|
387
505
|
return createJsonOperatorSchema(fieldMeta, operator);
|
|
388
506
|
}
|
|
389
507
|
const supportedOps = SCALAR_OPERATORS[fieldMeta.type];
|
|
@@ -406,9 +524,13 @@ function createOperatorSchema(fieldMeta, operator, enumMap, scalarBase) {
|
|
|
406
524
|
}
|
|
407
525
|
const scalar = factory();
|
|
408
526
|
const coerced = wrapWithInputCoercion(fieldMeta.type, false, scalar);
|
|
409
|
-
if (operator === "equals"
|
|
527
|
+
if (operator === "equals") {
|
|
410
528
|
return !fieldMeta.isRequired ? import_zod2.z.union([coerced, import_zod2.z.null()]) : coerced;
|
|
411
529
|
}
|
|
530
|
+
if (operator === "not") {
|
|
531
|
+
const scalarSchema = !fieldMeta.isRequired ? import_zod2.z.union([coerced, import_zod2.z.null()]) : coerced;
|
|
532
|
+
return buildNotFilterSchema(fieldMeta, scalarSchema, enumMap, scalarBase);
|
|
533
|
+
}
|
|
412
534
|
if (operator === "in" || operator === "notIn") {
|
|
413
535
|
const itemSchema = !fieldMeta.isRequired ? import_zod2.z.union([coerced, import_zod2.z.null()]) : coerced;
|
|
414
536
|
return import_zod2.z.preprocess(coerceToArray, import_zod2.z.array(itemSchema));
|
|
@@ -817,6 +939,8 @@ function deepClone(value) {
|
|
|
817
939
|
return new Date(value.getTime());
|
|
818
940
|
if (value instanceof Uint8Array)
|
|
819
941
|
return value.slice();
|
|
942
|
+
if (value instanceof RegExp)
|
|
943
|
+
return new RegExp(value.source, value.flags);
|
|
820
944
|
if (Array.isArray(value))
|
|
821
945
|
return value.map(deepClone);
|
|
822
946
|
const proto = Object.getPrototypeOf(value);
|
|
@@ -834,7 +958,10 @@ function deepClone(value) {
|
|
|
834
958
|
}
|
|
835
959
|
|
|
836
960
|
// src/runtime/query-builder-forced.ts
|
|
837
|
-
var EMPTY_WHERE_FORCED = {
|
|
961
|
+
var EMPTY_WHERE_FORCED = {
|
|
962
|
+
conditions: {},
|
|
963
|
+
relations: {}
|
|
964
|
+
};
|
|
838
965
|
function hasWhereForced(f) {
|
|
839
966
|
return Object.keys(f.conditions).length > 0 || Object.keys(f.relations).length > 0;
|
|
840
967
|
}
|
|
@@ -894,7 +1021,7 @@ function mergeUniqueWhereForced(where, forced) {
|
|
|
894
1021
|
}
|
|
895
1022
|
return result;
|
|
896
1023
|
}
|
|
897
|
-
function applyBuiltShape(built, body, isUniqueMethod) {
|
|
1024
|
+
function applyBuiltShape(built, body, isUniqueMethod, modelName) {
|
|
898
1025
|
let parseable = body;
|
|
899
1026
|
const hasWhereInSchema = "where" in built.zodSchema.shape;
|
|
900
1027
|
if (isPlainObject(body)) {
|
|
@@ -920,7 +1047,20 @@ function applyBuiltShape(built, body, isUniqueMethod) {
|
|
|
920
1047
|
}
|
|
921
1048
|
}
|
|
922
1049
|
}
|
|
923
|
-
|
|
1050
|
+
let validated;
|
|
1051
|
+
try {
|
|
1052
|
+
validated = built.zodSchema.parse(parseable);
|
|
1053
|
+
} catch (err) {
|
|
1054
|
+
if (err instanceof ShapeError)
|
|
1055
|
+
throw err;
|
|
1056
|
+
if (err && typeof err === "object" && "issues" in err) {
|
|
1057
|
+
const context = modelName ? `Invalid query on model "${modelName}"` : "Invalid query";
|
|
1058
|
+
throw new ShapeError(`${context}: ${formatZodError(err)}`, {
|
|
1059
|
+
cause: err
|
|
1060
|
+
});
|
|
1061
|
+
}
|
|
1062
|
+
throw err;
|
|
1063
|
+
}
|
|
924
1064
|
if (hasWhereForced(built.forcedWhere)) {
|
|
925
1065
|
validated.where = isUniqueMethod ? mergeUniqueWhereForced(
|
|
926
1066
|
validated.where,
|
|
@@ -1295,7 +1435,8 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
|
|
|
1295
1435
|
model,
|
|
1296
1436
|
fieldSchemas,
|
|
1297
1437
|
relationForced,
|
|
1298
|
-
currentDepth
|
|
1438
|
+
currentDepth,
|
|
1439
|
+
scalarConditions
|
|
1299
1440
|
);
|
|
1300
1441
|
continue;
|
|
1301
1442
|
}
|
|
@@ -1377,7 +1518,7 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
|
|
|
1377
1518
|
}
|
|
1378
1519
|
}
|
|
1379
1520
|
}
|
|
1380
|
-
function processRelationFilter(key, value, fieldMeta, model, fieldSchemas, parentRelations, depth) {
|
|
1521
|
+
function processRelationFilter(key, value, fieldMeta, model, fieldSchemas, parentRelations, depth, parentConditions) {
|
|
1381
1522
|
if (!isPlainObject(value)) {
|
|
1382
1523
|
throw new ShapeError(
|
|
1383
1524
|
`Relation filter for "${key}" must be an object with operators (some, every, none, is, isNot)`
|
|
@@ -1392,6 +1533,7 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
|
|
|
1392
1533
|
const opSchemas = {};
|
|
1393
1534
|
const opForced = {};
|
|
1394
1535
|
let hasClientOps = false;
|
|
1536
|
+
let hasForcedNull = false;
|
|
1395
1537
|
for (const [op, opValue] of Object.entries(value)) {
|
|
1396
1538
|
if (!allowedOps.has(op)) {
|
|
1397
1539
|
const allowed = [...allowedOps].join(", ");
|
|
@@ -1399,9 +1541,24 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
|
|
|
1399
1541
|
`Operator "${op}" not supported for ${fieldMeta.isList ? "to-many" : "to-one"} relation "${key}". Allowed: ${allowed}`
|
|
1400
1542
|
);
|
|
1401
1543
|
}
|
|
1544
|
+
if (opValue === null) {
|
|
1545
|
+
if (!TO_ONE_RELATION_OPS.has(op)) {
|
|
1546
|
+
throw new ShapeError(
|
|
1547
|
+
`Null value for operator "${op}" is only valid on to-one relation operators (is, isNot), not on "${key}"`
|
|
1548
|
+
);
|
|
1549
|
+
}
|
|
1550
|
+
const existing = parentConditions[key];
|
|
1551
|
+
if (existing && isPlainObject(existing)) {
|
|
1552
|
+
existing[op] = null;
|
|
1553
|
+
} else {
|
|
1554
|
+
parentConditions[key] = { [op]: null };
|
|
1555
|
+
}
|
|
1556
|
+
hasForcedNull = true;
|
|
1557
|
+
continue;
|
|
1558
|
+
}
|
|
1402
1559
|
if (!isPlainObject(opValue)) {
|
|
1403
1560
|
throw new ShapeError(
|
|
1404
|
-
`Relation filter operator "${op}" on "${key}" must be an object defining nested where fields`
|
|
1561
|
+
`Relation filter operator "${op}" on "${key}" must be an object defining nested where fields, or null for to-one existence checks`
|
|
1405
1562
|
);
|
|
1406
1563
|
}
|
|
1407
1564
|
const nested = buildWhereSchema(fieldMeta.type, opValue, depth + 1);
|
|
@@ -1427,7 +1584,7 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
|
|
|
1427
1584
|
opForced[op] = nested.forced;
|
|
1428
1585
|
}
|
|
1429
1586
|
}
|
|
1430
|
-
if (!hasClientOps && Object.keys(opForced).length === 0) {
|
|
1587
|
+
if (!hasClientOps && Object.keys(opForced).length === 0 && !hasForcedNull) {
|
|
1431
1588
|
throw new ShapeError(
|
|
1432
1589
|
`Relation filter for "${key}" on model "${model}" produced no conditions. Define at least one nested field in the operator shape.`
|
|
1433
1590
|
);
|
|
@@ -1435,7 +1592,7 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
|
|
|
1435
1592
|
if (hasClientOps) {
|
|
1436
1593
|
const clientOpKeys = Object.keys(opSchemas);
|
|
1437
1594
|
const opObjSchema = import_zod4.z.object(opSchemas).strict();
|
|
1438
|
-
if (Object.keys(opForced).length === 0) {
|
|
1595
|
+
if (Object.keys(opForced).length === 0 && !hasForcedNull) {
|
|
1439
1596
|
fieldSchemas[key] = opObjSchema.refine(
|
|
1440
1597
|
(v) => clientOpKeys.some(
|
|
1441
1598
|
(k) => v[k] !== void 0
|
|
@@ -1451,13 +1608,6 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
|
|
|
1451
1608
|
}
|
|
1452
1609
|
}
|
|
1453
1610
|
function processScalarField(fieldName, operators, model, fieldMeta, fieldSchemas, scalarConditions) {
|
|
1454
|
-
if (operators === true) {
|
|
1455
|
-
const supportedOps = getSupportedOperators(fieldMeta);
|
|
1456
|
-
const expanded = {};
|
|
1457
|
-
for (const op of supportedOps)
|
|
1458
|
-
expanded[op] = true;
|
|
1459
|
-
operators = expanded;
|
|
1460
|
-
}
|
|
1461
1611
|
if (!isPlainObject(operators)) {
|
|
1462
1612
|
throw new ShapeError(
|
|
1463
1613
|
`Where config for scalar field "${fieldName}" on model "${model}" must be an object of operators`
|
|
@@ -1570,7 +1720,82 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
|
|
|
1570
1720
|
scalarConditions[fieldName] = fieldForced;
|
|
1571
1721
|
}
|
|
1572
1722
|
}
|
|
1573
|
-
|
|
1723
|
+
function buildUniqueWhereSchema(model, whereConfig) {
|
|
1724
|
+
const modelFields = typeMap[model];
|
|
1725
|
+
if (!modelFields)
|
|
1726
|
+
throw new ShapeError(`Unknown model: ${model}`);
|
|
1727
|
+
const fieldSchemas = {};
|
|
1728
|
+
const forced = {};
|
|
1729
|
+
const forcedOnlyKeys = /* @__PURE__ */ new Set();
|
|
1730
|
+
for (const [key, value] of Object.entries(whereConfig)) {
|
|
1731
|
+
if (COMBINATOR_KEYS.has(key)) {
|
|
1732
|
+
throw new ShapeError(
|
|
1733
|
+
`Combinator "${key}" is not supported in unique where for model "${model}"`
|
|
1734
|
+
);
|
|
1735
|
+
}
|
|
1736
|
+
const fieldMeta = modelFields[key];
|
|
1737
|
+
if (!fieldMeta)
|
|
1738
|
+
throw new ShapeError(`Unknown field "${key}" on model "${model}"`);
|
|
1739
|
+
if (fieldMeta.isRelation)
|
|
1740
|
+
throw new ShapeError(
|
|
1741
|
+
`Relation field "${key}" cannot be used in unique where for model "${model}"`
|
|
1742
|
+
);
|
|
1743
|
+
const base = createBaseType(fieldMeta, enumMap, scalarBase);
|
|
1744
|
+
let directSchema;
|
|
1745
|
+
if (!fieldMeta.isEnum && !fieldMeta.isRelation && !fieldMeta.isUnsupported) {
|
|
1746
|
+
directSchema = wrapWithInputCoercion(
|
|
1747
|
+
fieldMeta.type,
|
|
1748
|
+
fieldMeta.isList,
|
|
1749
|
+
base
|
|
1750
|
+
);
|
|
1751
|
+
} else {
|
|
1752
|
+
directSchema = base;
|
|
1753
|
+
}
|
|
1754
|
+
const equalsWrapper = import_zod4.z.object({ equals: directSchema }).strict().transform((v) => v.equals);
|
|
1755
|
+
if (value === true) {
|
|
1756
|
+
fieldSchemas[key] = import_zod4.z.union([directSchema, equalsWrapper]);
|
|
1757
|
+
continue;
|
|
1758
|
+
}
|
|
1759
|
+
if (isPlainObject(value)) {
|
|
1760
|
+
const keys = Object.keys(value);
|
|
1761
|
+
if (keys.length === 1 && keys[0] === "equals") {
|
|
1762
|
+
const equalsVal = value.equals;
|
|
1763
|
+
if (equalsVal === true) {
|
|
1764
|
+
fieldSchemas[key] = import_zod4.z.union([directSchema, equalsWrapper]);
|
|
1765
|
+
} else {
|
|
1766
|
+
const actual2 = isForcedValue(equalsVal) ? equalsVal.value : equalsVal;
|
|
1767
|
+
try {
|
|
1768
|
+
forced[key] = directSchema.parse(actual2);
|
|
1769
|
+
} catch (err) {
|
|
1770
|
+
throw new ShapeError(
|
|
1771
|
+
`Invalid forced value for unique where "${model}.${key}": ${err.message}`
|
|
1772
|
+
);
|
|
1773
|
+
}
|
|
1774
|
+
forcedOnlyKeys.add(key);
|
|
1775
|
+
}
|
|
1776
|
+
continue;
|
|
1777
|
+
}
|
|
1778
|
+
throw new ShapeError(
|
|
1779
|
+
`Unique where field "${key}" on model "${model}" only accepts true or { equals: true/value }. Got operators: ${keys.join(", ")}`
|
|
1780
|
+
);
|
|
1781
|
+
}
|
|
1782
|
+
const actual = isForcedValue(value) ? value.value : value;
|
|
1783
|
+
try {
|
|
1784
|
+
forced[key] = directSchema.parse(actual);
|
|
1785
|
+
} catch (err) {
|
|
1786
|
+
throw new ShapeError(
|
|
1787
|
+
`Invalid forced value for unique where "${model}.${key}": ${err.message}`
|
|
1788
|
+
);
|
|
1789
|
+
}
|
|
1790
|
+
forcedOnlyKeys.add(key);
|
|
1791
|
+
}
|
|
1792
|
+
return {
|
|
1793
|
+
schema: Object.keys(fieldSchemas).length > 0 ? import_zod4.z.object(fieldSchemas).strict() : null,
|
|
1794
|
+
forced,
|
|
1795
|
+
forcedOnlyKeys
|
|
1796
|
+
};
|
|
1797
|
+
}
|
|
1798
|
+
return { buildWhereSchema, buildUniqueWhereSchema };
|
|
1574
1799
|
}
|
|
1575
1800
|
|
|
1576
1801
|
// src/runtime/query-builder-args.ts
|
|
@@ -1669,25 +1894,26 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
1669
1894
|
return import_zod5.z.union([singleSchema, import_zod5.z.preprocess(coerceToArray, import_zod5.z.array(singleSchema).min(1))]).optional();
|
|
1670
1895
|
}
|
|
1671
1896
|
function buildTakeSchema(config) {
|
|
1672
|
-
|
|
1673
|
-
|
|
1897
|
+
const normalized = typeof config === "number" ? { max: config, default: config } : config;
|
|
1898
|
+
if (!Number.isFinite(normalized.max) || !Number.isInteger(normalized.max)) {
|
|
1899
|
+
throw new ShapeError(`take max must be a finite integer, got ${normalized.max}`);
|
|
1674
1900
|
}
|
|
1675
|
-
if (
|
|
1676
|
-
throw new ShapeError(`take max must be at least 1, got ${
|
|
1901
|
+
if (normalized.max < 1) {
|
|
1902
|
+
throw new ShapeError(`take max must be at least 1, got ${normalized.max}`);
|
|
1677
1903
|
}
|
|
1678
|
-
if (
|
|
1679
|
-
if (!Number.isFinite(
|
|
1680
|
-
throw new ShapeError(`take default must be a finite integer, got ${
|
|
1904
|
+
if (normalized.default !== void 0) {
|
|
1905
|
+
if (!Number.isFinite(normalized.default) || !Number.isInteger(normalized.default)) {
|
|
1906
|
+
throw new ShapeError(`take default must be a finite integer, got ${normalized.default}`);
|
|
1681
1907
|
}
|
|
1682
|
-
if (
|
|
1683
|
-
throw new ShapeError(`take default must be at least 1, got ${
|
|
1908
|
+
if (normalized.default < 1) {
|
|
1909
|
+
throw new ShapeError(`take default must be at least 1, got ${normalized.default}`);
|
|
1684
1910
|
}
|
|
1685
|
-
if (
|
|
1911
|
+
if (normalized.default > normalized.max) {
|
|
1686
1912
|
throw new ShapeError("take default cannot exceed max");
|
|
1687
1913
|
}
|
|
1688
|
-
return import_zod5.z.number().int().min(1).max(
|
|
1914
|
+
return import_zod5.z.number().int().min(1).max(normalized.max).default(normalized.default);
|
|
1689
1915
|
}
|
|
1690
|
-
return import_zod5.z.number().int().min(1).max(
|
|
1916
|
+
return import_zod5.z.number().int().min(1).max(normalized.max).optional();
|
|
1691
1917
|
}
|
|
1692
1918
|
function buildCursorSchema(model, cursorConfig) {
|
|
1693
1919
|
const modelFields = typeMap[model];
|
|
@@ -1794,10 +2020,21 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
1794
2020
|
).optional();
|
|
1795
2021
|
}
|
|
1796
2022
|
const havingFieldKeys = Object.keys(fieldSchemas);
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
2023
|
+
const havingSchema = import_zod5.z.lazy(() => {
|
|
2024
|
+
const allSchemas = { ...fieldSchemas };
|
|
2025
|
+
allSchemas["AND"] = import_zod5.z.preprocess(coerceToArray, import_zod5.z.array(havingSchema).min(1)).optional();
|
|
2026
|
+
allSchemas["OR"] = import_zod5.z.preprocess(coerceToArray, import_zod5.z.array(havingSchema).min(1)).optional();
|
|
2027
|
+
allSchemas["NOT"] = import_zod5.z.union([
|
|
2028
|
+
havingSchema,
|
|
2029
|
+
import_zod5.z.preprocess(coerceToArray, import_zod5.z.array(havingSchema).min(1))
|
|
2030
|
+
]).optional();
|
|
2031
|
+
const allKeys = [...havingFieldKeys, "AND", "OR", "NOT"];
|
|
2032
|
+
return import_zod5.z.object(allSchemas).strict().refine(
|
|
2033
|
+
(v) => allKeys.some((k) => v[k] !== void 0),
|
|
2034
|
+
{ message: "having must specify at least one field or combinator" }
|
|
2035
|
+
);
|
|
2036
|
+
});
|
|
2037
|
+
return havingSchema.optional();
|
|
1801
2038
|
}
|
|
1802
2039
|
function buildAggregateFieldSchema(model, opName, fieldConfig) {
|
|
1803
2040
|
const modelFields = typeMap[model];
|
|
@@ -2569,6 +2806,17 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
2569
2806
|
return null;
|
|
2570
2807
|
return { key: matched, shape: shapes[matched] };
|
|
2571
2808
|
}
|
|
2809
|
+
function resolveDefaultShape(config, model, method, normalizedBody, opts, builtCache, isUnique) {
|
|
2810
|
+
const shapeOrFn = config["default"];
|
|
2811
|
+
let built;
|
|
2812
|
+
if (typeof shapeOrFn === "function") {
|
|
2813
|
+
const resolved = resolveAndValidateShape(shapeOrFn, opts?.ctx);
|
|
2814
|
+
built = buildShapeZodSchema(model, method, resolved);
|
|
2815
|
+
} else {
|
|
2816
|
+
built = builtCache.get("default");
|
|
2817
|
+
}
|
|
2818
|
+
return applyBuiltShape(built, normalizedBody, isUnique);
|
|
2819
|
+
}
|
|
2572
2820
|
function buildQuerySchema(model, method, config) {
|
|
2573
2821
|
const isSingle = typeof config === "function" || isShapeConfig(config);
|
|
2574
2822
|
const builtCache = /* @__PURE__ */ new Map();
|
|
@@ -2620,23 +2868,39 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
2620
2868
|
"Pass caller via opts.caller, not in the request body."
|
|
2621
2869
|
);
|
|
2622
2870
|
}
|
|
2871
|
+
const namedConfig = config;
|
|
2623
2872
|
const caller = opts?.caller;
|
|
2624
2873
|
if (typeof caller !== "string") {
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2874
|
+
if ("default" in namedConfig) {
|
|
2875
|
+
return resolveDefaultShape(
|
|
2876
|
+
namedConfig,
|
|
2877
|
+
model,
|
|
2878
|
+
method,
|
|
2879
|
+
normalizedBody,
|
|
2880
|
+
opts,
|
|
2881
|
+
builtCache,
|
|
2882
|
+
isUnique
|
|
2883
|
+
);
|
|
2884
|
+
}
|
|
2885
|
+
const allowed = Object.keys(namedConfig);
|
|
2628
2886
|
throw new CallerError(
|
|
2629
2887
|
`Missing caller. This query uses named shape routing with keys: ${allowed.map((k) => `"${k}"`).join(", ")}. Provide caller via opts.caller.`
|
|
2630
2888
|
);
|
|
2631
2889
|
}
|
|
2632
|
-
const matched = matchCaller(
|
|
2633
|
-
config,
|
|
2634
|
-
caller
|
|
2635
|
-
);
|
|
2890
|
+
const matched = matchCaller(namedConfig, caller);
|
|
2636
2891
|
if (!matched) {
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2892
|
+
if ("default" in namedConfig) {
|
|
2893
|
+
return resolveDefaultShape(
|
|
2894
|
+
namedConfig,
|
|
2895
|
+
model,
|
|
2896
|
+
method,
|
|
2897
|
+
normalizedBody,
|
|
2898
|
+
opts,
|
|
2899
|
+
builtCache,
|
|
2900
|
+
isUnique
|
|
2901
|
+
);
|
|
2902
|
+
}
|
|
2903
|
+
const allowed = Object.keys(namedConfig);
|
|
2640
2904
|
throw new CallerError(
|
|
2641
2905
|
`Unknown caller: "${caller}". Allowed: ${allowed.map((k) => `"${k}"`).join(", ")}`
|
|
2642
2906
|
);
|
|
@@ -2656,6 +2920,7 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
2656
2920
|
buildQuerySchema,
|
|
2657
2921
|
buildShapeZodSchema,
|
|
2658
2922
|
buildWhereSchema: whereBuilder.buildWhereSchema,
|
|
2923
|
+
buildUniqueWhereSchema: whereBuilder.buildUniqueWhereSchema,
|
|
2659
2924
|
buildIncludeSchema: projectionBuilder.buildIncludeSchema,
|
|
2660
2925
|
buildSelectSchema: projectionBuilder.buildSelectSchema
|
|
2661
2926
|
};
|
|
@@ -2668,23 +2933,10 @@ var READ_OPS = /* @__PURE__ */ new Set([
|
|
|
2668
2933
|
"findFirstOrThrow",
|
|
2669
2934
|
"count"
|
|
2670
2935
|
]);
|
|
2671
|
-
var AGGREGATE_OPS = /* @__PURE__ */ new Set([
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
]);
|
|
2675
|
-
var FIND_UNIQUE_OPS = /* @__PURE__ */ new Set([
|
|
2676
|
-
"findUnique",
|
|
2677
|
-
"findUniqueOrThrow"
|
|
2678
|
-
]);
|
|
2679
|
-
var CREATE_OPS = /* @__PURE__ */ new Set([
|
|
2680
|
-
"create",
|
|
2681
|
-
"createMany",
|
|
2682
|
-
"createManyAndReturn"
|
|
2683
|
-
]);
|
|
2684
|
-
var UNIQUE_MUTATION_OPS = /* @__PURE__ */ new Set([
|
|
2685
|
-
"update",
|
|
2686
|
-
"delete"
|
|
2687
|
-
]);
|
|
2936
|
+
var AGGREGATE_OPS = /* @__PURE__ */ new Set(["aggregate", "groupBy"]);
|
|
2937
|
+
var FIND_UNIQUE_OPS = /* @__PURE__ */ new Set(["findUnique", "findUniqueOrThrow"]);
|
|
2938
|
+
var CREATE_OPS = /* @__PURE__ */ new Set(["create", "createMany", "createManyAndReturn"]);
|
|
2939
|
+
var UNIQUE_MUTATION_OPS = /* @__PURE__ */ new Set(["update", "delete"]);
|
|
2688
2940
|
var MULTI_MUTATION_OPS = /* @__PURE__ */ new Set([
|
|
2689
2941
|
"updateMany",
|
|
2690
2942
|
"updateManyAndReturn",
|
|
@@ -2813,7 +3065,9 @@ function createScopeExtension(scopeMap, contextFn, guardConfig, logger) {
|
|
|
2813
3065
|
for (const s of presentScopes) {
|
|
2814
3066
|
validateScopeValue(s.root, ctx[s.root]);
|
|
2815
3067
|
}
|
|
2816
|
-
const presentConditions = presentScopes.map((s) => ({
|
|
3068
|
+
const presentConditions = presentScopes.map((s) => ({
|
|
3069
|
+
[s.fk]: ctx[s.root]
|
|
3070
|
+
}));
|
|
2817
3071
|
const missingRoots = scopes.filter((s) => ctx[s.root] == null).map((s) => s.root);
|
|
2818
3072
|
const isMutation = CREATE_OPS.has(operation) || UNIQUE_MUTATION_OPS.has(operation) || MULTI_MUTATION_OPS.has(operation) || operation === "upsert";
|
|
2819
3073
|
if (missingRoots.length > 0) {
|
|
@@ -2843,14 +3097,32 @@ function createScopeExtension(scopeMap, contextFn, guardConfig, logger) {
|
|
|
2843
3097
|
throw new ShapeError(`upsert expects create to be an object`);
|
|
2844
3098
|
}
|
|
2845
3099
|
nextArgs.create = { ...args.create };
|
|
2846
|
-
enforceDataScope(
|
|
3100
|
+
enforceDataScope(
|
|
3101
|
+
nextArgs.create,
|
|
3102
|
+
scopes,
|
|
3103
|
+
overrides,
|
|
3104
|
+
log,
|
|
3105
|
+
model,
|
|
3106
|
+
operation,
|
|
3107
|
+
onScopeRelationWrite,
|
|
3108
|
+
"create"
|
|
3109
|
+
);
|
|
2847
3110
|
}
|
|
2848
3111
|
if (args.update !== void 0 && args.update !== null) {
|
|
2849
3112
|
if (typeof args.update !== "object" || Array.isArray(args.update)) {
|
|
2850
3113
|
throw new ShapeError(`upsert expects update to be an object`);
|
|
2851
3114
|
}
|
|
2852
3115
|
nextArgs.update = { ...args.update };
|
|
2853
|
-
enforceDataScope(
|
|
3116
|
+
enforceDataScope(
|
|
3117
|
+
nextArgs.update,
|
|
3118
|
+
scopes,
|
|
3119
|
+
overrides,
|
|
3120
|
+
log,
|
|
3121
|
+
model,
|
|
3122
|
+
operation,
|
|
3123
|
+
onScopeRelationWrite,
|
|
3124
|
+
"mutate"
|
|
3125
|
+
);
|
|
2854
3126
|
}
|
|
2855
3127
|
return query(nextArgs);
|
|
2856
3128
|
}
|
|
@@ -2860,7 +3132,15 @@ function createScopeExtension(scopeMap, contextFn, guardConfig, logger) {
|
|
|
2860
3132
|
`Scoped model "${model}" does not allow ${operation} via scope extension (findUniqueMode is "reject"). Use findFirst with explicit where conditions instead.`
|
|
2861
3133
|
);
|
|
2862
3134
|
}
|
|
2863
|
-
return handleFindUnique(
|
|
3135
|
+
return handleFindUnique(
|
|
3136
|
+
args,
|
|
3137
|
+
query,
|
|
3138
|
+
conditions,
|
|
3139
|
+
scopes,
|
|
3140
|
+
operation,
|
|
3141
|
+
log,
|
|
3142
|
+
model
|
|
3143
|
+
);
|
|
2864
3144
|
}
|
|
2865
3145
|
if (READ_OPS.has(operation)) {
|
|
2866
3146
|
nextArgs.where = buildAndConditions(args.where, conditions);
|
|
@@ -2888,7 +3168,16 @@ function createScopeExtension(scopeMap, contextFn, guardConfig, logger) {
|
|
|
2888
3168
|
}
|
|
2889
3169
|
nextArgs.data = args.data.map((d) => {
|
|
2890
3170
|
const item = { ...d };
|
|
2891
|
-
enforceDataScope(
|
|
3171
|
+
enforceDataScope(
|
|
3172
|
+
item,
|
|
3173
|
+
scopes,
|
|
3174
|
+
overrides,
|
|
3175
|
+
log,
|
|
3176
|
+
model,
|
|
3177
|
+
operation,
|
|
3178
|
+
onScopeRelationWrite,
|
|
3179
|
+
"create"
|
|
3180
|
+
);
|
|
2892
3181
|
return item;
|
|
2893
3182
|
});
|
|
2894
3183
|
} else {
|
|
@@ -2896,7 +3185,16 @@ function createScopeExtension(scopeMap, contextFn, guardConfig, logger) {
|
|
|
2896
3185
|
throw new ShapeError(`${operation} expects data to be an object`);
|
|
2897
3186
|
}
|
|
2898
3187
|
nextArgs.data = { ...args.data };
|
|
2899
|
-
enforceDataScope(
|
|
3188
|
+
enforceDataScope(
|
|
3189
|
+
nextArgs.data,
|
|
3190
|
+
scopes,
|
|
3191
|
+
overrides,
|
|
3192
|
+
log,
|
|
3193
|
+
model,
|
|
3194
|
+
operation,
|
|
3195
|
+
onScopeRelationWrite,
|
|
3196
|
+
"create"
|
|
3197
|
+
);
|
|
2900
3198
|
}
|
|
2901
3199
|
return query(nextArgs);
|
|
2902
3200
|
}
|
|
@@ -2907,7 +3205,16 @@ function createScopeExtension(scopeMap, contextFn, guardConfig, logger) {
|
|
|
2907
3205
|
throw new ShapeError(`${operation} expects data to be an object`);
|
|
2908
3206
|
}
|
|
2909
3207
|
nextArgs.data = { ...args.data };
|
|
2910
|
-
enforceDataScope(
|
|
3208
|
+
enforceDataScope(
|
|
3209
|
+
nextArgs.data,
|
|
3210
|
+
scopes,
|
|
3211
|
+
overrides,
|
|
3212
|
+
log,
|
|
3213
|
+
model,
|
|
3214
|
+
operation,
|
|
3215
|
+
onScopeRelationWrite,
|
|
3216
|
+
"mutate"
|
|
3217
|
+
);
|
|
2911
3218
|
}
|
|
2912
3219
|
return query(nextArgs);
|
|
2913
3220
|
}
|
|
@@ -2918,7 +3225,16 @@ function createScopeExtension(scopeMap, contextFn, guardConfig, logger) {
|
|
|
2918
3225
|
throw new ShapeError(`${operation} expects data to be an object`);
|
|
2919
3226
|
}
|
|
2920
3227
|
nextArgs.data = { ...args.data };
|
|
2921
|
-
enforceDataScope(
|
|
3228
|
+
enforceDataScope(
|
|
3229
|
+
nextArgs.data,
|
|
3230
|
+
scopes,
|
|
3231
|
+
overrides,
|
|
3232
|
+
log,
|
|
3233
|
+
model,
|
|
3234
|
+
operation,
|
|
3235
|
+
onScopeRelationWrite,
|
|
3236
|
+
"mutate"
|
|
3237
|
+
);
|
|
2922
3238
|
}
|
|
2923
3239
|
return query(nextArgs);
|
|
2924
3240
|
}
|
|
@@ -2929,7 +3245,7 @@ function createScopeExtension(scopeMap, contextFn, guardConfig, logger) {
|
|
|
2929
3245
|
}
|
|
2930
3246
|
};
|
|
2931
3247
|
}
|
|
2932
|
-
async function handleFindUnique(args, query, conditions, scopes, operation, log) {
|
|
3248
|
+
async function handleFindUnique(args, query, conditions, scopes, operation, log, model) {
|
|
2933
3249
|
const nextArgs = { ...args };
|
|
2934
3250
|
const injectedFks = [];
|
|
2935
3251
|
const originalSelect = args?.select;
|
|
@@ -2947,7 +3263,9 @@ async function handleFindUnique(args, query, conditions, scopes, operation, log)
|
|
|
2947
3263
|
if (result === null)
|
|
2948
3264
|
return result;
|
|
2949
3265
|
if (typeof result !== "object" || result === null) {
|
|
2950
|
-
throw new ShapeError(
|
|
3266
|
+
throw new ShapeError(
|
|
3267
|
+
`${operation} on model "${model}" returned a non-object, non-null result`
|
|
3268
|
+
);
|
|
2951
3269
|
}
|
|
2952
3270
|
const resultObj = result;
|
|
2953
3271
|
let verifyObj = resultObj;
|
|
@@ -2956,22 +3274,29 @@ async function handleFindUnique(args, query, conditions, scopes, operation, log)
|
|
|
2956
3274
|
const where = args?.where;
|
|
2957
3275
|
if (!where || typeof where !== "object" || Array.isArray(where)) {
|
|
2958
3276
|
throw new PolicyError(
|
|
2959
|
-
`prisma-guard: Cannot verify scope \u2014 missing FK fields (${missingFks.join(", ")}) and
|
|
3277
|
+
`prisma-guard: Cannot verify scope on model "${model}" for ${operation} \u2014 missing FK fields (${missingFks.join(", ")}) in result and args.where is not a valid object. Ensure the where clause is a plain object so the verification query can re-fetch FK values.`
|
|
2960
3278
|
);
|
|
2961
3279
|
}
|
|
2962
3280
|
let verifyResult;
|
|
2963
3281
|
try {
|
|
2964
3282
|
verifyResult = await query({ where, select: buildFkSelect(fks) });
|
|
2965
3283
|
} catch (err) {
|
|
3284
|
+
log.warn(
|
|
3285
|
+
`prisma-guard: Scope verification re-query failed for ${operation} on model "${model}": ${err?.message ?? String(err)}`
|
|
3286
|
+
);
|
|
2966
3287
|
throw new PolicyError(
|
|
2967
|
-
`prisma-guard: Scope verification query failed for
|
|
3288
|
+
`prisma-guard: Scope verification re-query failed for ${operation} on model "${model}". The re-query to fetch FK fields (${fks.join(", ")}) returned a database error. Check server logs for the underlying cause.`
|
|
2968
3289
|
);
|
|
2969
3290
|
}
|
|
2970
3291
|
if (verifyResult === null) {
|
|
2971
|
-
throw new PolicyError(
|
|
3292
|
+
throw new PolicyError(
|
|
3293
|
+
`prisma-guard: Scope verification re-query on model "${model}" returned null for an existing ${operation} result. The record may have been deleted between the original query and verification.`
|
|
3294
|
+
);
|
|
2972
3295
|
}
|
|
2973
3296
|
if (typeof verifyResult !== "object" || verifyResult === null) {
|
|
2974
|
-
throw new PolicyError(
|
|
3297
|
+
throw new PolicyError(
|
|
3298
|
+
`prisma-guard: Scope verification re-query on model "${model}" returned a non-object result.`
|
|
3299
|
+
);
|
|
2975
3300
|
}
|
|
2976
3301
|
verifyObj = verifyResult;
|
|
2977
3302
|
}
|
|
@@ -2979,12 +3304,14 @@ async function handleFindUnique(args, query, conditions, scopes, operation, log)
|
|
|
2979
3304
|
const [fk, value] = Object.entries(condition)[0];
|
|
2980
3305
|
if (!(fk in verifyObj)) {
|
|
2981
3306
|
throw new PolicyError(
|
|
2982
|
-
`prisma-guard: Cannot verify scope on "${
|
|
3307
|
+
`prisma-guard: Cannot verify scope on model "${model}" \u2014 FK field "${fk}" not present in verification result. Ensure "${fk}" is selectable on model "${model}" (not excluded by select or field-level access).`
|
|
2983
3308
|
);
|
|
2984
3309
|
}
|
|
2985
3310
|
if (!looseEqual(verifyObj[fk], value, log, fk)) {
|
|
2986
3311
|
if (operation === "findUniqueOrThrow") {
|
|
2987
|
-
throw new PolicyError(
|
|
3312
|
+
throw new PolicyError(
|
|
3313
|
+
`Record on model "${model}" not accessible in current scope`
|
|
3314
|
+
);
|
|
2988
3315
|
}
|
|
2989
3316
|
return null;
|
|
2990
3317
|
}
|
|
@@ -3689,11 +4016,22 @@ function buildDataSchema(model, dataConfig, mode, typeMap, schemaBuilder, zodDef
|
|
|
3689
4016
|
forced
|
|
3690
4017
|
};
|
|
3691
4018
|
}
|
|
3692
|
-
function validateAndMergeData(bodyData, cached, method) {
|
|
4019
|
+
function validateAndMergeData(bodyData, cached, method, modelName) {
|
|
3693
4020
|
if (bodyData === void 0 || bodyData === null) {
|
|
3694
4021
|
throw new ShapeError(`${method} requires "data" in request body`);
|
|
3695
4022
|
}
|
|
3696
|
-
|
|
4023
|
+
let validated;
|
|
4024
|
+
try {
|
|
4025
|
+
validated = cached.schema.parse(bodyData);
|
|
4026
|
+
} catch (err) {
|
|
4027
|
+
if (err instanceof ShapeError)
|
|
4028
|
+
throw err;
|
|
4029
|
+
if (err && typeof err === "object" && "issues" in err) {
|
|
4030
|
+
const context = modelName ? `Invalid data for ${method} on model "${modelName}"` : `Invalid data for ${method}`;
|
|
4031
|
+
throw new ShapeError(`${context}: ${formatZodError(err)}`, { cause: err });
|
|
4032
|
+
}
|
|
4033
|
+
throw err;
|
|
4034
|
+
}
|
|
3697
4035
|
return { ...validated, ...deepClone(cached.forced) };
|
|
3698
4036
|
}
|
|
3699
4037
|
function hasDataRefines(dataConfig) {
|
|
@@ -3763,14 +4101,26 @@ function resolveShape(input, body, contextFn, caller) {
|
|
|
3763
4101
|
);
|
|
3764
4102
|
}
|
|
3765
4103
|
if (typeof caller !== "string") {
|
|
4104
|
+
if ("default" in namedMap) {
|
|
4105
|
+
const shapeOrFn2 = namedMap["default"];
|
|
4106
|
+
const wasDynamic2 = typeof shapeOrFn2 === "function";
|
|
4107
|
+
const shape2 = wasDynamic2 ? resolveDynamicShape(shapeOrFn2, contextFn) : shapeOrFn2;
|
|
4108
|
+
return { shape: shape2, body: parsed, matchedKey: "default", wasDynamic: wasDynamic2 };
|
|
4109
|
+
}
|
|
3766
4110
|
const patterns2 = Object.keys(namedMap);
|
|
3767
4111
|
throw new CallerError(
|
|
3768
|
-
`Missing caller. This guard uses named shape routing with keys: ${patterns2.map((k) => `"${k}"`).join(", ")}. Provide caller as second argument to .guard() or set "caller" in the context function.`
|
|
4112
|
+
`Missing caller. This guard uses named shape routing with keys: ${patterns2.map((k) => `"${k}"`).join(", ")}. Provide caller as second argument to .guard() or set "caller" in the context function, or add a "default" variant.`
|
|
3769
4113
|
);
|
|
3770
4114
|
}
|
|
3771
4115
|
const patterns = Object.keys(namedMap);
|
|
3772
4116
|
const matched = matchCallerPattern(patterns, caller);
|
|
3773
4117
|
if (!matched) {
|
|
4118
|
+
if ("default" in namedMap) {
|
|
4119
|
+
const shapeOrFn2 = namedMap["default"];
|
|
4120
|
+
const wasDynamic2 = typeof shapeOrFn2 === "function";
|
|
4121
|
+
const shape2 = wasDynamic2 ? resolveDynamicShape(shapeOrFn2, contextFn) : shapeOrFn2;
|
|
4122
|
+
return { shape: shape2, body: parsed, matchedKey: "default", wasDynamic: wasDynamic2 };
|
|
4123
|
+
}
|
|
3774
4124
|
throw new CallerError(
|
|
3775
4125
|
`Unknown caller: "${caller}". Allowed: ${patterns.map((k) => `"${k}"`).join(", ")}`
|
|
3776
4126
|
);
|
|
@@ -3801,17 +4151,6 @@ var PROJECTION_MUTATION_METHODS = /* @__PURE__ */ new Set([
|
|
|
3801
4151
|
"updateManyAndReturn"
|
|
3802
4152
|
]);
|
|
3803
4153
|
var BATCH_CREATE_METHODS = /* @__PURE__ */ new Set(["createMany", "createManyAndReturn"]);
|
|
3804
|
-
function normalizeUniqueWhere(where) {
|
|
3805
|
-
const result = {};
|
|
3806
|
-
for (const [key, value] of Object.entries(where)) {
|
|
3807
|
-
if (key !== "AND" && key !== "OR" && key !== "NOT" && isPlainObject(value) && "equals" in value && Object.keys(value).length === 1) {
|
|
3808
|
-
result[key] = value.equals;
|
|
3809
|
-
} else {
|
|
3810
|
-
result[key] = value;
|
|
3811
|
-
}
|
|
3812
|
-
}
|
|
3813
|
-
return result;
|
|
3814
|
-
}
|
|
3815
4154
|
function buildDefaultSelectInput(config) {
|
|
3816
4155
|
const result = {};
|
|
3817
4156
|
for (const [key, value] of Object.entries(config)) {
|
|
@@ -4031,6 +4370,36 @@ function createModelGuardExtension(config) {
|
|
|
4031
4370
|
return;
|
|
4032
4371
|
validateUniqueEquality(modelName, shape.where, method, uniqueMap, typeMap);
|
|
4033
4372
|
}
|
|
4373
|
+
function validateUniqueWhereShapeConfig(modelName, where, method) {
|
|
4374
|
+
const constraints = uniqueMap[modelName];
|
|
4375
|
+
if (!constraints || constraints.length === 0)
|
|
4376
|
+
return;
|
|
4377
|
+
const equalityFields = /* @__PURE__ */ new Set();
|
|
4378
|
+
for (const [key, value] of Object.entries(where)) {
|
|
4379
|
+
if (key === "AND" || key === "OR" || key === "NOT")
|
|
4380
|
+
continue;
|
|
4381
|
+
if (value === true) {
|
|
4382
|
+
equalityFields.add(key);
|
|
4383
|
+
continue;
|
|
4384
|
+
}
|
|
4385
|
+
if (isPlainObject(value) && "equals" in value) {
|
|
4386
|
+
equalityFields.add(key);
|
|
4387
|
+
continue;
|
|
4388
|
+
}
|
|
4389
|
+
if (value !== null && value !== void 0) {
|
|
4390
|
+
equalityFields.add(key);
|
|
4391
|
+
}
|
|
4392
|
+
}
|
|
4393
|
+
const valid = constraints.some(
|
|
4394
|
+
(constraint) => constraint.every((field) => equalityFields.has(field))
|
|
4395
|
+
);
|
|
4396
|
+
if (!valid) {
|
|
4397
|
+
const constraintDesc = constraints.map((c) => `(${c.join(", ")})`).join(" | ");
|
|
4398
|
+
throw new ShapeError(
|
|
4399
|
+
`${method} on model "${modelName}" requires where to cover a unique constraint with equality operators only: ${constraintDesc}`
|
|
4400
|
+
);
|
|
4401
|
+
}
|
|
4402
|
+
}
|
|
4034
4403
|
function createGuardedMethods(modelName, modelDelegate, input, explicitCaller) {
|
|
4035
4404
|
function callDelegate(method, args) {
|
|
4036
4405
|
if (typeof modelDelegate[method] !== "function") {
|
|
@@ -4053,6 +4422,7 @@ function createModelGuardExtension(config) {
|
|
|
4053
4422
|
const dataSchemaCache = /* @__PURE__ */ new Map();
|
|
4054
4423
|
const whereBuiltCache = /* @__PURE__ */ new Map();
|
|
4055
4424
|
const projectionCache = /* @__PURE__ */ new Map();
|
|
4425
|
+
const uniqueWhereCache = /* @__PURE__ */ new Map();
|
|
4056
4426
|
function getReadShape(method, queryShape, matchedKey, wasDynamic) {
|
|
4057
4427
|
if (!wasDynamic) {
|
|
4058
4428
|
const cacheKey = `${method}\0${matchedKey}`;
|
|
@@ -4110,6 +4480,21 @@ function createModelGuardExtension(config) {
|
|
|
4110
4480
|
}
|
|
4111
4481
|
return queryBuilder.buildWhereSchema(modelName, whereConfig);
|
|
4112
4482
|
}
|
|
4483
|
+
function getUniqueWhereBuilt(whereConfig, matchedKey, wasDynamic) {
|
|
4484
|
+
if (!wasDynamic) {
|
|
4485
|
+
const cacheKey = `unique\0${matchedKey}`;
|
|
4486
|
+
const cached = uniqueWhereCache.get(cacheKey);
|
|
4487
|
+
if (cached)
|
|
4488
|
+
return cached;
|
|
4489
|
+
const built = queryBuilder.buildUniqueWhereSchema(
|
|
4490
|
+
modelName,
|
|
4491
|
+
whereConfig
|
|
4492
|
+
);
|
|
4493
|
+
uniqueWhereCache.set(cacheKey, built);
|
|
4494
|
+
return built;
|
|
4495
|
+
}
|
|
4496
|
+
return queryBuilder.buildUniqueWhereSchema(modelName, whereConfig);
|
|
4497
|
+
}
|
|
4113
4498
|
function buildProjectionSchema(shape) {
|
|
4114
4499
|
const schemaFields = {};
|
|
4115
4500
|
let forcedIncludeTree = {};
|
|
@@ -4189,7 +4574,15 @@ function createModelGuardExtension(config) {
|
|
|
4189
4574
|
} else {
|
|
4190
4575
|
projectionBody = buildDefaultProjectionBody(shape);
|
|
4191
4576
|
}
|
|
4192
|
-
|
|
4577
|
+
let validated;
|
|
4578
|
+
try {
|
|
4579
|
+
validated = projection.zodSchema.parse(projectionBody);
|
|
4580
|
+
} catch (err) {
|
|
4581
|
+
wrapParseError(
|
|
4582
|
+
err,
|
|
4583
|
+
`Invalid select/include projection on model "${modelName}" for ${method}`
|
|
4584
|
+
);
|
|
4585
|
+
}
|
|
4193
4586
|
if (Object.keys(projection.forcedIncludeTree).length > 0) {
|
|
4194
4587
|
applyForcedTree(validated, "include", projection.forcedIncludeTree);
|
|
4195
4588
|
}
|
|
@@ -4226,7 +4619,11 @@ function createModelGuardExtension(config) {
|
|
|
4226
4619
|
}
|
|
4227
4620
|
sanitizedWhere = w;
|
|
4228
4621
|
}
|
|
4229
|
-
|
|
4622
|
+
try {
|
|
4623
|
+
validatedWhere = built.schema.parse(sanitizedWhere);
|
|
4624
|
+
} catch (err) {
|
|
4625
|
+
wrapParseError(err, `Invalid "where" clause on model "${modelName}"`);
|
|
4626
|
+
}
|
|
4230
4627
|
} else if (bodyWhere !== void 0) {
|
|
4231
4628
|
if (bodyWhere === null || !isPlainObject(bodyWhere) || Object.keys(bodyWhere).length > 0) {
|
|
4232
4629
|
let hasOnlyForcedKeys = false;
|
|
@@ -4256,7 +4653,68 @@ function createModelGuardExtension(config) {
|
|
|
4256
4653
|
wasDynamic
|
|
4257
4654
|
);
|
|
4258
4655
|
if (Object.keys(where).length === 0) {
|
|
4259
|
-
|
|
4656
|
+
const expectedFields = shape.where ? Object.keys(shape.where).join(", ") : "none defined";
|
|
4657
|
+
throw new ShapeError(
|
|
4658
|
+
`${method} on model "${modelName}" requires a where condition. Expected fields: ${expectedFields}`
|
|
4659
|
+
);
|
|
4660
|
+
}
|
|
4661
|
+
return where;
|
|
4662
|
+
}
|
|
4663
|
+
function buildUniqueWhereFromShape(shape, bodyWhere, matchedKey, wasDynamic) {
|
|
4664
|
+
if (!shape.where)
|
|
4665
|
+
return {};
|
|
4666
|
+
const built = getUniqueWhereBuilt(shape.where, matchedKey, wasDynamic);
|
|
4667
|
+
let result = {};
|
|
4668
|
+
if (built.schema) {
|
|
4669
|
+
if (bodyWhere !== void 0 && bodyWhere !== null) {
|
|
4670
|
+
if (!isPlainObject(bodyWhere)) {
|
|
4671
|
+
throw new ShapeError(
|
|
4672
|
+
`Invalid "where" on model "${modelName}": unique where must be a plain object`
|
|
4673
|
+
);
|
|
4674
|
+
}
|
|
4675
|
+
const sanitized = { ...bodyWhere };
|
|
4676
|
+
for (const key of built.forcedOnlyKeys) {
|
|
4677
|
+
delete sanitized[key];
|
|
4678
|
+
}
|
|
4679
|
+
try {
|
|
4680
|
+
result = built.schema.parse(sanitized);
|
|
4681
|
+
} catch (err) {
|
|
4682
|
+
const allowedFields = Object.keys(shape.where).join(", ");
|
|
4683
|
+
wrapParseError(
|
|
4684
|
+
err,
|
|
4685
|
+
`Invalid unique "where" on model "${modelName}". Allowed fields: ${allowedFields}`
|
|
4686
|
+
);
|
|
4687
|
+
}
|
|
4688
|
+
}
|
|
4689
|
+
} else if (bodyWhere !== void 0 && bodyWhere !== null) {
|
|
4690
|
+
if (isPlainObject(bodyWhere)) {
|
|
4691
|
+
const hasOnlyForcedKeys = built.forcedOnlyKeys.size > 0 && Object.keys(bodyWhere).every((k) => built.forcedOnlyKeys.has(k));
|
|
4692
|
+
if (!hasOnlyForcedKeys && Object.keys(bodyWhere).length > 0) {
|
|
4693
|
+
throw new ShapeError(
|
|
4694
|
+
`Unique where on model "${modelName}" contains only forced values. Client where input is not accepted.`
|
|
4695
|
+
);
|
|
4696
|
+
}
|
|
4697
|
+
}
|
|
4698
|
+
}
|
|
4699
|
+
for (const [key, value] of Object.entries(built.forced)) {
|
|
4700
|
+
result[key] = value;
|
|
4701
|
+
}
|
|
4702
|
+
return result;
|
|
4703
|
+
}
|
|
4704
|
+
function requireUniqueWhere(shape, bodyWhere, method, matchedKey, wasDynamic) {
|
|
4705
|
+
const where = buildUniqueWhereFromShape(
|
|
4706
|
+
shape,
|
|
4707
|
+
bodyWhere,
|
|
4708
|
+
matchedKey,
|
|
4709
|
+
wasDynamic
|
|
4710
|
+
);
|
|
4711
|
+
if (Object.keys(where).length === 0) {
|
|
4712
|
+
const constraints = uniqueMap[modelName];
|
|
4713
|
+
const constraintDesc = constraints ? constraints.map((c) => `(${c.join(", ")})`).join(" | ") : "unknown";
|
|
4714
|
+
const expectedFields = shape.where ? Object.keys(shape.where).join(", ") : "none defined";
|
|
4715
|
+
throw new ShapeError(
|
|
4716
|
+
`${method} on model "${modelName}" requires a unique where condition. Unique constraints: ${constraintDesc}. Shape allows: ${expectedFields}`
|
|
4717
|
+
);
|
|
4260
4718
|
}
|
|
4261
4719
|
return where;
|
|
4262
4720
|
}
|
|
@@ -4299,7 +4757,7 @@ function createModelGuardExtension(config) {
|
|
|
4299
4757
|
);
|
|
4300
4758
|
const isUnique = UNIQUE_READ_METHODS.has(method);
|
|
4301
4759
|
const effectiveBody = buildEffectiveReadBody(resolved);
|
|
4302
|
-
const args = applyBuiltShape(built, effectiveBody, isUnique);
|
|
4760
|
+
const args = applyBuiltShape(built, effectiveBody, isUnique, modelName);
|
|
4303
4761
|
if (isUnique && args.where) {
|
|
4304
4762
|
validateResolvedUniqueWhere(
|
|
4305
4763
|
modelName,
|
|
@@ -4355,7 +4813,8 @@ function createModelGuardExtension(config) {
|
|
|
4355
4813
|
const data = validateAndMergeData(
|
|
4356
4814
|
resolved.body.data,
|
|
4357
4815
|
dataSchema,
|
|
4358
|
-
method
|
|
4816
|
+
method,
|
|
4817
|
+
modelName
|
|
4359
4818
|
);
|
|
4360
4819
|
args = { data };
|
|
4361
4820
|
} else {
|
|
@@ -4364,7 +4823,7 @@ function createModelGuardExtension(config) {
|
|
|
4364
4823
|
if (resolved.body.data.length === 0)
|
|
4365
4824
|
throw new ShapeError(`${method} received empty data array`);
|
|
4366
4825
|
const data = resolved.body.data.map(
|
|
4367
|
-
(item) => validateAndMergeData(item, dataSchema, method)
|
|
4826
|
+
(item) => validateAndMergeData(item, dataSchema, method, modelName)
|
|
4368
4827
|
);
|
|
4369
4828
|
args = { data };
|
|
4370
4829
|
}
|
|
@@ -4409,7 +4868,6 @@ function createModelGuardExtension(config) {
|
|
|
4409
4868
|
`Guard shape requires "where" for ${method} to prevent unconstrained bulk mutations`
|
|
4410
4869
|
);
|
|
4411
4870
|
}
|
|
4412
|
-
maybeValidateUniqueWhere(modelName, resolved.shape, method);
|
|
4413
4871
|
const dataSchema = getDataSchema(
|
|
4414
4872
|
"update",
|
|
4415
4873
|
resolved.shape.data,
|
|
@@ -4419,30 +4877,40 @@ function createModelGuardExtension(config) {
|
|
|
4419
4877
|
const data = validateAndMergeData(
|
|
4420
4878
|
resolved.body.data,
|
|
4421
4879
|
dataSchema,
|
|
4422
|
-
method
|
|
4423
|
-
);
|
|
4424
|
-
let where = isUniqueWhere ? requireWhere(
|
|
4425
|
-
resolved.shape,
|
|
4426
|
-
resolved.body.where,
|
|
4427
4880
|
method,
|
|
4428
|
-
|
|
4429
|
-
resolved.matchedKey,
|
|
4430
|
-
resolved.wasDynamic
|
|
4431
|
-
) : buildWhereFromShape(
|
|
4432
|
-
resolved.shape,
|
|
4433
|
-
resolved.body.where,
|
|
4434
|
-
false,
|
|
4435
|
-
resolved.matchedKey,
|
|
4436
|
-
resolved.wasDynamic
|
|
4881
|
+
modelName
|
|
4437
4882
|
);
|
|
4438
|
-
|
|
4439
|
-
throw new ShapeError(
|
|
4440
|
-
`${method} requires at least one where condition`
|
|
4441
|
-
);
|
|
4442
|
-
}
|
|
4883
|
+
let where;
|
|
4443
4884
|
if (isUniqueWhere) {
|
|
4885
|
+
if (resolved.shape.where) {
|
|
4886
|
+
validateUniqueWhereShapeConfig(
|
|
4887
|
+
modelName,
|
|
4888
|
+
resolved.shape.where,
|
|
4889
|
+
method
|
|
4890
|
+
);
|
|
4891
|
+
}
|
|
4892
|
+
where = requireUniqueWhere(
|
|
4893
|
+
resolved.shape,
|
|
4894
|
+
resolved.body.where,
|
|
4895
|
+
method,
|
|
4896
|
+
resolved.matchedKey,
|
|
4897
|
+
resolved.wasDynamic
|
|
4898
|
+
);
|
|
4444
4899
|
validateResolvedUniqueWhere(modelName, where, method, uniqueMap);
|
|
4445
|
-
|
|
4900
|
+
} else {
|
|
4901
|
+
maybeValidateUniqueWhere(modelName, resolved.shape, method);
|
|
4902
|
+
where = buildWhereFromShape(
|
|
4903
|
+
resolved.shape,
|
|
4904
|
+
resolved.body.where,
|
|
4905
|
+
false,
|
|
4906
|
+
resolved.matchedKey,
|
|
4907
|
+
resolved.wasDynamic
|
|
4908
|
+
);
|
|
4909
|
+
if (isBulk && Object.keys(where).length === 0) {
|
|
4910
|
+
throw new ShapeError(
|
|
4911
|
+
`${method} requires at least one where condition`
|
|
4912
|
+
);
|
|
4913
|
+
}
|
|
4446
4914
|
}
|
|
4447
4915
|
const args = { data, where };
|
|
4448
4916
|
if (supportsProjection) {
|
|
@@ -4480,29 +4948,37 @@ function createModelGuardExtension(config) {
|
|
|
4480
4948
|
`Guard shape requires "where" for ${method} to prevent unconstrained bulk mutations`
|
|
4481
4949
|
);
|
|
4482
4950
|
}
|
|
4483
|
-
|
|
4484
|
-
let where = isUniqueWhere ? requireWhere(
|
|
4485
|
-
resolved.shape,
|
|
4486
|
-
resolved.body.where,
|
|
4487
|
-
method,
|
|
4488
|
-
true,
|
|
4489
|
-
resolved.matchedKey,
|
|
4490
|
-
resolved.wasDynamic
|
|
4491
|
-
) : buildWhereFromShape(
|
|
4492
|
-
resolved.shape,
|
|
4493
|
-
resolved.body.where,
|
|
4494
|
-
false,
|
|
4495
|
-
resolved.matchedKey,
|
|
4496
|
-
resolved.wasDynamic
|
|
4497
|
-
);
|
|
4498
|
-
if (isBulk && Object.keys(where).length === 0) {
|
|
4499
|
-
throw new ShapeError(
|
|
4500
|
-
`${method} requires at least one where condition`
|
|
4501
|
-
);
|
|
4502
|
-
}
|
|
4951
|
+
let where;
|
|
4503
4952
|
if (isUniqueWhere) {
|
|
4953
|
+
if (resolved.shape.where) {
|
|
4954
|
+
validateUniqueWhereShapeConfig(
|
|
4955
|
+
modelName,
|
|
4956
|
+
resolved.shape.where,
|
|
4957
|
+
method
|
|
4958
|
+
);
|
|
4959
|
+
}
|
|
4960
|
+
where = requireUniqueWhere(
|
|
4961
|
+
resolved.shape,
|
|
4962
|
+
resolved.body.where,
|
|
4963
|
+
method,
|
|
4964
|
+
resolved.matchedKey,
|
|
4965
|
+
resolved.wasDynamic
|
|
4966
|
+
);
|
|
4504
4967
|
validateResolvedUniqueWhere(modelName, where, method, uniqueMap);
|
|
4505
|
-
|
|
4968
|
+
} else {
|
|
4969
|
+
maybeValidateUniqueWhere(modelName, resolved.shape, method);
|
|
4970
|
+
where = buildWhereFromShape(
|
|
4971
|
+
resolved.shape,
|
|
4972
|
+
resolved.body.where,
|
|
4973
|
+
false,
|
|
4974
|
+
resolved.matchedKey,
|
|
4975
|
+
resolved.wasDynamic
|
|
4976
|
+
);
|
|
4977
|
+
if (isBulk && Object.keys(where).length === 0) {
|
|
4978
|
+
throw new ShapeError(
|
|
4979
|
+
`${method} requires at least one where condition`
|
|
4980
|
+
);
|
|
4981
|
+
}
|
|
4506
4982
|
}
|
|
4507
4983
|
const args = { where };
|
|
4508
4984
|
if (supportsProjection) {
|
|
@@ -4546,7 +5022,11 @@ function createModelGuardExtension(config) {
|
|
|
4546
5022
|
ALLOWED_BODY_KEYS_UPSERT,
|
|
4547
5023
|
"upsert"
|
|
4548
5024
|
);
|
|
4549
|
-
|
|
5025
|
+
validateUniqueWhereShapeConfig(
|
|
5026
|
+
modelName,
|
|
5027
|
+
resolved.shape.where,
|
|
5028
|
+
"upsert"
|
|
5029
|
+
);
|
|
4550
5030
|
const fks = modelScopeFks.get(modelName) ?? /* @__PURE__ */ new Set();
|
|
4551
5031
|
validateCreateCompleteness(
|
|
4552
5032
|
modelName,
|
|
@@ -4564,7 +5044,8 @@ function createModelGuardExtension(config) {
|
|
|
4564
5044
|
const createData = validateAndMergeData(
|
|
4565
5045
|
resolved.body.create,
|
|
4566
5046
|
createDataSchema,
|
|
4567
|
-
"upsert (create)"
|
|
5047
|
+
"upsert (create)",
|
|
5048
|
+
modelName
|
|
4568
5049
|
);
|
|
4569
5050
|
const updateDataSchema = getDataSchema(
|
|
4570
5051
|
"update",
|
|
@@ -4575,19 +5056,19 @@ function createModelGuardExtension(config) {
|
|
|
4575
5056
|
const updateData = validateAndMergeData(
|
|
4576
5057
|
resolved.body.update,
|
|
4577
5058
|
updateDataSchema,
|
|
4578
|
-
"upsert (update)"
|
|
5059
|
+
"upsert (update)",
|
|
5060
|
+
modelName
|
|
4579
5061
|
);
|
|
4580
|
-
const where =
|
|
5062
|
+
const where = requireUniqueWhere(
|
|
4581
5063
|
resolved.shape,
|
|
4582
5064
|
resolved.body.where,
|
|
4583
5065
|
"upsert",
|
|
4584
|
-
true,
|
|
4585
5066
|
resolved.matchedKey,
|
|
4586
5067
|
resolved.wasDynamic
|
|
4587
5068
|
);
|
|
4588
5069
|
validateResolvedUniqueWhere(modelName, where, "upsert", uniqueMap);
|
|
4589
5070
|
const args = {
|
|
4590
|
-
where
|
|
5071
|
+
where,
|
|
4591
5072
|
create: createData,
|
|
4592
5073
|
update: updateData
|
|
4593
5074
|
};
|