prisma-guard 1.28.1 → 1.30.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 +75 -1
- package/dist/generator/index.js +42 -33
- package/dist/generator/index.js.map +1 -1
- package/dist/runtime/index.cjs +293 -199
- package/dist/runtime/index.cjs.map +1 -1
- package/dist/runtime/index.d.cts +11 -2
- package/dist/runtime/index.d.ts +11 -2
- package/dist/runtime/index.js +293 -199
- package/dist/runtime/index.js.map +1 -1
- package/package.json +1 -1
package/dist/runtime/index.cjs
CHANGED
|
@@ -243,7 +243,7 @@ function createScalarBase(strictDecimal) {
|
|
|
243
243
|
return {
|
|
244
244
|
String: () => import_zod.z.string(),
|
|
245
245
|
Int: () => import_zod.z.number().int(),
|
|
246
|
-
Float: () => import_zod.z.number(),
|
|
246
|
+
Float: () => import_zod.z.number().finite(),
|
|
247
247
|
Decimal: createDecimalFactory(strictDecimal),
|
|
248
248
|
BigInt: () => import_zod.z.union([
|
|
249
249
|
import_zod.z.bigint(),
|
|
@@ -307,6 +307,9 @@ function isPlainObject(v) {
|
|
|
307
307
|
const proto = Object.getPrototypeOf(v);
|
|
308
308
|
return proto === Object.prototype || proto === null;
|
|
309
309
|
}
|
|
310
|
+
function isObjectLike(v) {
|
|
311
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
312
|
+
}
|
|
310
313
|
function schemaProducesValueForUndefined(schema) {
|
|
311
314
|
const result = schema.safeParse(void 0);
|
|
312
315
|
return result.success && result.data !== void 0;
|
|
@@ -384,6 +387,19 @@ function requireConfigTrue(config, context) {
|
|
|
384
387
|
}
|
|
385
388
|
}
|
|
386
389
|
}
|
|
390
|
+
function requirePlainObjectConfig(value, message) {
|
|
391
|
+
if (!isPlainObject(value)) {
|
|
392
|
+
throw new ShapeError(message);
|
|
393
|
+
}
|
|
394
|
+
return value;
|
|
395
|
+
}
|
|
396
|
+
function assertAllowedKeys(value, allowed, makeError) {
|
|
397
|
+
for (const key of Object.keys(value)) {
|
|
398
|
+
if (!allowed.has(key)) {
|
|
399
|
+
throw new ShapeError(makeError(key));
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
387
403
|
|
|
388
404
|
// src/runtime/zod-type-map.ts
|
|
389
405
|
var SCALAR_OPERATORS = {
|
|
@@ -447,24 +463,12 @@ var JSON_ARRAY_OPERATORS = /* @__PURE__ */ new Set([
|
|
|
447
463
|
"array_starts_with",
|
|
448
464
|
"array_ends_with"
|
|
449
465
|
]);
|
|
450
|
-
function getSupportedOperators(
|
|
451
|
-
|
|
452
|
-
let list;
|
|
453
|
-
let enumField;
|
|
454
|
-
if (typeof input === "string") {
|
|
455
|
-
fieldType = input;
|
|
456
|
-
list = isList;
|
|
457
|
-
enumField = isEnum;
|
|
458
|
-
} else {
|
|
459
|
-
fieldType = input.type;
|
|
460
|
-
list = input.isList;
|
|
461
|
-
enumField = input.isEnum === true;
|
|
462
|
-
}
|
|
463
|
-
if (list)
|
|
466
|
+
function getSupportedOperators(fieldMeta) {
|
|
467
|
+
if (fieldMeta.isList)
|
|
464
468
|
return [...SCALAR_LIST_OPERATORS];
|
|
465
|
-
if (
|
|
469
|
+
if (fieldMeta.isEnum === true)
|
|
466
470
|
return [...ENUM_OPERATORS];
|
|
467
|
-
const ops = SCALAR_OPERATORS[
|
|
471
|
+
const ops = SCALAR_OPERATORS[fieldMeta.type];
|
|
468
472
|
if (!ops)
|
|
469
473
|
return [];
|
|
470
474
|
return [...ops];
|
|
@@ -1029,6 +1033,7 @@ function validateContext(ctx) {
|
|
|
1029
1033
|
|
|
1030
1034
|
// src/runtime/query-builder-where.ts
|
|
1031
1035
|
var import_zod5 = require("zod");
|
|
1036
|
+
var import_node_util = require("util");
|
|
1032
1037
|
|
|
1033
1038
|
// src/shared/deep-clone.ts
|
|
1034
1039
|
function deepClone(value) {
|
|
@@ -1309,15 +1314,10 @@ function applyBuiltShape(built, body, isUniqueMethod, modelName) {
|
|
|
1309
1314
|
try {
|
|
1310
1315
|
validated = built.zodSchema.parse(parseable);
|
|
1311
1316
|
} catch (err) {
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
throw new ShapeError(`${context}: ${formatZodError(err)}`, {
|
|
1317
|
-
cause: err
|
|
1318
|
-
});
|
|
1319
|
-
}
|
|
1320
|
-
throw err;
|
|
1317
|
+
wrapParseError(
|
|
1318
|
+
err,
|
|
1319
|
+
modelName ? `Invalid query on model "${modelName}"` : "Invalid query"
|
|
1320
|
+
);
|
|
1321
1321
|
}
|
|
1322
1322
|
if (hasWhereForced(built.forcedWhere)) {
|
|
1323
1323
|
validated.where = isUniqueMethod ? mergeUniqueWhereForced(
|
|
@@ -1634,37 +1634,8 @@ var JSON_STRING_MODE_OPS = /* @__PURE__ */ new Set([
|
|
|
1634
1634
|
]);
|
|
1635
1635
|
var NEGATIVE_RELATION_OPS = /* @__PURE__ */ new Set(["none", "isNot"]);
|
|
1636
1636
|
var MAX_WHERE_DEPTH = 10;
|
|
1637
|
-
function
|
|
1638
|
-
|
|
1639
|
-
return `${value}n`;
|
|
1640
|
-
if (typeof value === "undefined")
|
|
1641
|
-
return "undefined";
|
|
1642
|
-
if (typeof value === "function")
|
|
1643
|
-
return "[function]";
|
|
1644
|
-
if (typeof value === "symbol")
|
|
1645
|
-
return value.toString();
|
|
1646
|
-
const seen = /* @__PURE__ */ new WeakSet();
|
|
1647
|
-
try {
|
|
1648
|
-
const json = JSON.stringify(value, (_key, current) => {
|
|
1649
|
-
if (typeof current === "bigint")
|
|
1650
|
-
return `${current}n`;
|
|
1651
|
-
if (typeof current === "undefined")
|
|
1652
|
-
return "[undefined]";
|
|
1653
|
-
if (typeof current === "function")
|
|
1654
|
-
return "[function]";
|
|
1655
|
-
if (typeof current === "symbol")
|
|
1656
|
-
return current.toString();
|
|
1657
|
-
if (current && typeof current === "object") {
|
|
1658
|
-
if (seen.has(current))
|
|
1659
|
-
return "[Circular]";
|
|
1660
|
-
seen.add(current);
|
|
1661
|
-
}
|
|
1662
|
-
return current;
|
|
1663
|
-
});
|
|
1664
|
-
return json === void 0 ? String(value) : json;
|
|
1665
|
-
} catch {
|
|
1666
|
-
return String(value);
|
|
1667
|
-
}
|
|
1637
|
+
function formatValue(value) {
|
|
1638
|
+
return (0, import_node_util.inspect)(value, { depth: 3, breakLength: Infinity });
|
|
1668
1639
|
}
|
|
1669
1640
|
function mergeScalarConditions(target, source) {
|
|
1670
1641
|
for (const [field, ops] of Object.entries(source)) {
|
|
@@ -1685,7 +1656,7 @@ function mergeScalarConditions(target, source) {
|
|
|
1685
1656
|
const existingVal = existing[op];
|
|
1686
1657
|
if (!deepEqual(existingVal, val)) {
|
|
1687
1658
|
throw new ShapeError(
|
|
1688
|
-
`Conflicting forced where values for "${field}.${op}": shape defines both ${
|
|
1659
|
+
`Conflicting forced where values for "${field}.${op}": shape defines both ${formatValue(existingVal)} and ${formatValue(val)}`
|
|
1689
1660
|
);
|
|
1690
1661
|
}
|
|
1691
1662
|
}
|
|
@@ -2523,10 +2494,7 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
2523
2494
|
`${fieldMeta.type} field "${fieldName}" cannot be used in having`
|
|
2524
2495
|
);
|
|
2525
2496
|
}
|
|
2526
|
-
const allowedOps = getSupportedOperators(
|
|
2527
|
-
fieldMeta.type,
|
|
2528
|
-
fieldMeta.isList
|
|
2529
|
-
);
|
|
2497
|
+
const allowedOps = getSupportedOperators(fieldMeta);
|
|
2530
2498
|
const opSchemas = {};
|
|
2531
2499
|
for (const op of allowedOps) {
|
|
2532
2500
|
opSchemas[op] = createOperatorSchema(
|
|
@@ -2703,20 +2671,27 @@ function buildDefaultProjectionBody(shape) {
|
|
|
2703
2671
|
|
|
2704
2672
|
// src/runtime/query-builder-projection.ts
|
|
2705
2673
|
var KNOWN_NESTED_KEYS = {
|
|
2706
|
-
include: /* @__PURE__ */ new Set([
|
|
2707
|
-
|
|
2674
|
+
include: /* @__PURE__ */ new Set([
|
|
2675
|
+
"where",
|
|
2676
|
+
"include",
|
|
2677
|
+
"select",
|
|
2678
|
+
"orderBy",
|
|
2679
|
+
"cursor",
|
|
2680
|
+
"take",
|
|
2681
|
+
"skip"
|
|
2682
|
+
]),
|
|
2683
|
+
select: /* @__PURE__ */ new Set([
|
|
2684
|
+
"select",
|
|
2685
|
+
"include",
|
|
2686
|
+
"where",
|
|
2687
|
+
"orderBy",
|
|
2688
|
+
"cursor",
|
|
2689
|
+
"take",
|
|
2690
|
+
"skip"
|
|
2691
|
+
])
|
|
2708
2692
|
};
|
|
2709
2693
|
var KNOWN_COUNT_SELECT_ENTRY_KEYS = /* @__PURE__ */ new Set(["where"]);
|
|
2710
2694
|
var MAX_PROJECTION_DEPTH = 10;
|
|
2711
|
-
function validateNestedKeys(keys, allowed, context) {
|
|
2712
|
-
for (const key of keys) {
|
|
2713
|
-
if (!allowed.has(key)) {
|
|
2714
|
-
throw new ShapeError(
|
|
2715
|
-
`Unknown key "${key}" in ${context}. Allowed: ${[...allowed].join(", ")}`
|
|
2716
|
-
);
|
|
2717
|
-
}
|
|
2718
|
-
}
|
|
2719
|
-
}
|
|
2720
2695
|
function hasDefinedKeys(v) {
|
|
2721
2696
|
return Object.values(v).some((value) => value !== void 0);
|
|
2722
2697
|
}
|
|
@@ -2729,6 +2704,20 @@ function wrapRelationSchema(nestedObj, skeleton) {
|
|
|
2729
2704
|
collapsed
|
|
2730
2705
|
);
|
|
2731
2706
|
}
|
|
2707
|
+
function buildRelationWhere(relatedType, whereConfig, context, buildWhereSchema) {
|
|
2708
|
+
if (Object.keys(whereConfig).length === 0) {
|
|
2709
|
+
throw new ShapeError(
|
|
2710
|
+
`Empty "where" in ${context}. Define at least one field.`
|
|
2711
|
+
);
|
|
2712
|
+
}
|
|
2713
|
+
const { schema, forced } = buildWhereSchema(relatedType, whereConfig);
|
|
2714
|
+
if (!schema && !hasWhereForced(forced)) {
|
|
2715
|
+
throw new ShapeError(
|
|
2716
|
+
`"where" in ${context} produced no schema and no forced conditions. Define at least one field.`
|
|
2717
|
+
);
|
|
2718
|
+
}
|
|
2719
|
+
return { schema, forced };
|
|
2720
|
+
}
|
|
2732
2721
|
function createProjectionBuilder(typeMap, _enumMap, deps) {
|
|
2733
2722
|
function buildIncludeCountSchema(model, config) {
|
|
2734
2723
|
const modelFields = typeMap[model];
|
|
@@ -2742,13 +2731,11 @@ function createProjectionBuilder(typeMap, _enumMap, deps) {
|
|
|
2742
2731
|
`Invalid _count config on model "${model}". Expected true or { select: { ... } }`
|
|
2743
2732
|
);
|
|
2744
2733
|
}
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
}
|
|
2751
|
-
}
|
|
2734
|
+
assertAllowedKeys(
|
|
2735
|
+
config,
|
|
2736
|
+
/* @__PURE__ */ new Set(["select"]),
|
|
2737
|
+
(key) => `Unknown key "${key}" in _count config on model "${model}". Only "select" is allowed.`
|
|
2738
|
+
);
|
|
2752
2739
|
if (!isPlainObject(config.select)) {
|
|
2753
2740
|
throw new ShapeError(
|
|
2754
2741
|
`Invalid _count.select on model "${model}". Expected a plain object with relation field keys.`
|
|
@@ -2765,11 +2752,17 @@ function createProjectionBuilder(typeMap, _enumMap, deps) {
|
|
|
2765
2752
|
for (const [fieldName, fieldConfig] of Object.entries(selectObj)) {
|
|
2766
2753
|
const fieldMeta = modelFields[fieldName];
|
|
2767
2754
|
if (!fieldMeta)
|
|
2768
|
-
throw new ShapeError(
|
|
2755
|
+
throw new ShapeError(
|
|
2756
|
+
`Unknown field "${fieldName}" on model "${model}" in _count.select`
|
|
2757
|
+
);
|
|
2769
2758
|
if (!fieldMeta.isRelation)
|
|
2770
|
-
throw new ShapeError(
|
|
2759
|
+
throw new ShapeError(
|
|
2760
|
+
`Field "${fieldName}" is not a relation on model "${model}" in _count.select`
|
|
2761
|
+
);
|
|
2771
2762
|
if (!fieldMeta.isList)
|
|
2772
|
-
throw new ShapeError(
|
|
2763
|
+
throw new ShapeError(
|
|
2764
|
+
`Field "${fieldName}" is a to-one relation on model "${model}" in _count.select. Only to-many relations support _count.`
|
|
2765
|
+
);
|
|
2773
2766
|
if (fieldConfig === true) {
|
|
2774
2767
|
countSelectFields[fieldName] = import_zod7.z.literal(true).optional();
|
|
2775
2768
|
continue;
|
|
@@ -2784,16 +2777,18 @@ function createProjectionBuilder(typeMap, _enumMap, deps) {
|
|
|
2784
2777
|
`Empty config for _count.select.${fieldName} on model "${model}". Use true or { where: { ... } }.`
|
|
2785
2778
|
);
|
|
2786
2779
|
}
|
|
2787
|
-
|
|
2788
|
-
|
|
2780
|
+
assertAllowedKeys(
|
|
2781
|
+
fieldConfig,
|
|
2789
2782
|
KNOWN_COUNT_SELECT_ENTRY_KEYS,
|
|
2790
|
-
`_count.select.${fieldName} on model "${model}"`
|
|
2783
|
+
(key) => `Unknown key "${key}" in _count.select.${fieldName} on model "${model}". Allowed: ${[...KNOWN_COUNT_SELECT_ENTRY_KEYS].join(", ")}`
|
|
2791
2784
|
);
|
|
2792
2785
|
if (fieldConfig.where) {
|
|
2793
2786
|
const relatedType = fieldMeta.type;
|
|
2794
|
-
const { schema: whereSchema, forced } =
|
|
2787
|
+
const { schema: whereSchema, forced } = buildRelationWhere(
|
|
2795
2788
|
relatedType,
|
|
2796
|
-
fieldConfig.where
|
|
2789
|
+
fieldConfig.where,
|
|
2790
|
+
`_count.select.${fieldName} on model "${model}"`,
|
|
2791
|
+
deps.buildWhereSchema
|
|
2797
2792
|
);
|
|
2798
2793
|
const nestedSchemas = {};
|
|
2799
2794
|
if (whereSchema)
|
|
@@ -2816,13 +2811,15 @@ function createProjectionBuilder(typeMap, _enumMap, deps) {
|
|
|
2816
2811
|
forcedCountWhere
|
|
2817
2812
|
};
|
|
2818
2813
|
}
|
|
2819
|
-
function buildNestedRelSchemas(relatedType, config, depth) {
|
|
2814
|
+
function buildNestedRelSchemas(relatedType, config, depth, context) {
|
|
2820
2815
|
const nestedSchemas = {};
|
|
2821
2816
|
const relForced = {};
|
|
2822
2817
|
if (config.where) {
|
|
2823
|
-
const { schema: whereSchema, forced } =
|
|
2818
|
+
const { schema: whereSchema, forced } = buildRelationWhere(
|
|
2824
2819
|
relatedType,
|
|
2825
|
-
config.where
|
|
2820
|
+
config.where,
|
|
2821
|
+
context,
|
|
2822
|
+
deps.buildWhereSchema
|
|
2826
2823
|
);
|
|
2827
2824
|
if (whereSchema)
|
|
2828
2825
|
nestedSchemas["where"] = whereSchema;
|
|
@@ -2830,7 +2827,12 @@ function createProjectionBuilder(typeMap, _enumMap, deps) {
|
|
|
2830
2827
|
relForced.where = forced;
|
|
2831
2828
|
}
|
|
2832
2829
|
if (config.include) {
|
|
2833
|
-
const nested = buildProjectionSchema(
|
|
2830
|
+
const nested = buildProjectionSchema(
|
|
2831
|
+
"include",
|
|
2832
|
+
relatedType,
|
|
2833
|
+
config.include,
|
|
2834
|
+
depth + 1
|
|
2835
|
+
);
|
|
2834
2836
|
nestedSchemas["include"] = nested.schema;
|
|
2835
2837
|
if (Object.keys(nested.forcedTree).length > 0)
|
|
2836
2838
|
relForced.include = nested.forcedTree;
|
|
@@ -2840,7 +2842,12 @@ function createProjectionBuilder(typeMap, _enumMap, deps) {
|
|
|
2840
2842
|
}
|
|
2841
2843
|
}
|
|
2842
2844
|
if (config.select) {
|
|
2843
|
-
const nested = buildProjectionSchema(
|
|
2845
|
+
const nested = buildProjectionSchema(
|
|
2846
|
+
"select",
|
|
2847
|
+
relatedType,
|
|
2848
|
+
config.select,
|
|
2849
|
+
depth + 1
|
|
2850
|
+
);
|
|
2844
2851
|
nestedSchemas["select"] = nested.schema;
|
|
2845
2852
|
if (Object.keys(nested.forcedTree).length > 0)
|
|
2846
2853
|
relForced.select = nested.forcedTree;
|
|
@@ -2850,15 +2857,26 @@ function createProjectionBuilder(typeMap, _enumMap, deps) {
|
|
|
2850
2857
|
}
|
|
2851
2858
|
}
|
|
2852
2859
|
if (config.orderBy) {
|
|
2853
|
-
nestedSchemas["orderBy"] = deps.buildOrderBySchema(
|
|
2860
|
+
nestedSchemas["orderBy"] = deps.buildOrderBySchema(
|
|
2861
|
+
relatedType,
|
|
2862
|
+
config.orderBy
|
|
2863
|
+
);
|
|
2854
2864
|
}
|
|
2855
2865
|
if (config.cursor) {
|
|
2856
|
-
nestedSchemas["cursor"] = deps.buildCursorSchema(
|
|
2866
|
+
nestedSchemas["cursor"] = deps.buildCursorSchema(
|
|
2867
|
+
relatedType,
|
|
2868
|
+
config.cursor
|
|
2869
|
+
);
|
|
2857
2870
|
}
|
|
2858
|
-
if (config.take) {
|
|
2871
|
+
if ("take" in config && config.take !== void 0) {
|
|
2859
2872
|
nestedSchemas["take"] = deps.buildTakeSchema(config.take);
|
|
2860
2873
|
}
|
|
2861
|
-
if (config.skip) {
|
|
2874
|
+
if ("skip" in config && config.skip !== void 0) {
|
|
2875
|
+
if (config.skip !== true) {
|
|
2876
|
+
throw new ShapeError(
|
|
2877
|
+
`Nested "skip" in ${context} must be true`
|
|
2878
|
+
);
|
|
2879
|
+
}
|
|
2862
2880
|
nestedSchemas["skip"] = import_zod7.z.number().int().min(0).optional();
|
|
2863
2881
|
}
|
|
2864
2882
|
return { nestedSchemas, relForced };
|
|
@@ -2884,28 +2902,43 @@ function createProjectionBuilder(typeMap, _enumMap, deps) {
|
|
|
2884
2902
|
let topLevelForcedCountWhere = {};
|
|
2885
2903
|
for (const [fieldName, config] of Object.entries(projectionConfig)) {
|
|
2886
2904
|
if (fieldName === "_count") {
|
|
2887
|
-
const countResult = buildIncludeCountSchema(
|
|
2905
|
+
const countResult = buildIncludeCountSchema(
|
|
2906
|
+
model,
|
|
2907
|
+
config
|
|
2908
|
+
);
|
|
2888
2909
|
fieldSchemas["_count"] = countResult.schema;
|
|
2889
2910
|
topLevelForcedCountWhere = countResult.forcedCountWhere;
|
|
2890
2911
|
continue;
|
|
2891
2912
|
}
|
|
2892
2913
|
const fieldMeta = modelFields[fieldName];
|
|
2893
2914
|
if (!fieldMeta)
|
|
2894
|
-
throw new ShapeError(
|
|
2915
|
+
throw new ShapeError(
|
|
2916
|
+
`Unknown field "${fieldName}" on model "${model}"`
|
|
2917
|
+
);
|
|
2895
2918
|
if (mode === "include" && !fieldMeta.isRelation) {
|
|
2896
|
-
throw new ShapeError(
|
|
2919
|
+
throw new ShapeError(
|
|
2920
|
+
`Field "${fieldName}" is not a relation on model "${model}"`
|
|
2921
|
+
);
|
|
2897
2922
|
}
|
|
2898
2923
|
if (config === true) {
|
|
2899
2924
|
fieldSchemas[fieldName] = import_zod7.z.literal(true).optional();
|
|
2900
2925
|
continue;
|
|
2901
2926
|
}
|
|
2902
2927
|
if (mode === "select" && !fieldMeta.isRelation) {
|
|
2903
|
-
throw new ShapeError(
|
|
2928
|
+
throw new ShapeError(
|
|
2929
|
+
`Nested select args only valid for relations, not scalar "${fieldName}" on model "${model}"`
|
|
2930
|
+
);
|
|
2904
2931
|
}
|
|
2905
2932
|
const contextLabel = `nested ${mode} for "${fieldName}" on model "${model}"`;
|
|
2906
|
-
|
|
2933
|
+
assertAllowedKeys(
|
|
2934
|
+
config,
|
|
2935
|
+
allowedNestedKeys,
|
|
2936
|
+
(key) => `Unknown key "${key}" in ${contextLabel}. Allowed: ${[...allowedNestedKeys].join(", ")}`
|
|
2937
|
+
);
|
|
2907
2938
|
if (config.select && config.include) {
|
|
2908
|
-
throw new ShapeError(
|
|
2939
|
+
throw new ShapeError(
|
|
2940
|
+
`Nested ${mode} for "${fieldName}" cannot define both "select" and "include".`
|
|
2941
|
+
);
|
|
2909
2942
|
}
|
|
2910
2943
|
if (!fieldMeta.isList) {
|
|
2911
2944
|
if (config.where || config.orderBy || config.cursor || config.take || config.skip) {
|
|
@@ -2914,7 +2947,12 @@ function createProjectionBuilder(typeMap, _enumMap, deps) {
|
|
|
2914
2947
|
);
|
|
2915
2948
|
}
|
|
2916
2949
|
}
|
|
2917
|
-
const { nestedSchemas, relForced } = buildNestedRelSchemas(
|
|
2950
|
+
const { nestedSchemas, relForced } = buildNestedRelSchemas(
|
|
2951
|
+
fieldMeta.type,
|
|
2952
|
+
config,
|
|
2953
|
+
currentDepth,
|
|
2954
|
+
contextLabel
|
|
2955
|
+
);
|
|
2918
2956
|
const nestedObj = import_zod7.z.object(nestedSchemas).strict();
|
|
2919
2957
|
fieldSchemas[fieldName] = wrapRelationSchema(
|
|
2920
2958
|
nestedObj,
|
|
@@ -2939,7 +2977,12 @@ function createProjectionBuilder(typeMap, _enumMap, deps) {
|
|
|
2939
2977
|
function buildSelectSchema(model, selectConfig, depth) {
|
|
2940
2978
|
return buildProjectionSchema("select", model, selectConfig, depth);
|
|
2941
2979
|
}
|
|
2942
|
-
return {
|
|
2980
|
+
return {
|
|
2981
|
+
buildIncludeSchema,
|
|
2982
|
+
buildSelectSchema,
|
|
2983
|
+
buildIncludeCountSchema,
|
|
2984
|
+
buildProjectionSchema
|
|
2985
|
+
};
|
|
2943
2986
|
}
|
|
2944
2987
|
|
|
2945
2988
|
// src/shared/operation-shape-keys.ts
|
|
@@ -2955,10 +2998,10 @@ var OPERATION_SHAPE_KEYS = {
|
|
|
2955
2998
|
groupBy: ["where", "orderBy", "by", "having", "take", "skip", "_count", "_avg", "_sum", "_min", "_max"],
|
|
2956
2999
|
create: ["data", "include", "select"],
|
|
2957
3000
|
createMany: ["data", "skipDuplicates"],
|
|
2958
|
-
createManyAndReturn: ["data", "select", "skipDuplicates"],
|
|
3001
|
+
createManyAndReturn: ["data", "select", "include", "skipDuplicates"],
|
|
2959
3002
|
update: ["where", "data", "include", "select"],
|
|
2960
3003
|
updateMany: ["where", "data"],
|
|
2961
|
-
updateManyAndReturn: ["where", "data", "select"],
|
|
3004
|
+
updateManyAndReturn: ["where", "data", "select", "include"],
|
|
2962
3005
|
upsert: ["where", "create", "update", "include", "select"],
|
|
2963
3006
|
delete: ["where", "include", "select"],
|
|
2964
3007
|
deleteMany: ["where"]
|
|
@@ -3272,7 +3315,17 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
3272
3315
|
let forcedIncludeCountWhere = {};
|
|
3273
3316
|
let forcedSelectCountWhere = {};
|
|
3274
3317
|
if (shape.where) {
|
|
3318
|
+
if (Object.keys(shape.where).length === 0) {
|
|
3319
|
+
throw new ShapeError(
|
|
3320
|
+
`Empty "where" in shape for model "${model}" method "${method}". Define at least one field.`
|
|
3321
|
+
);
|
|
3322
|
+
}
|
|
3275
3323
|
const builtWhere = UNIQUE_WHERE_METHODS.has(method) ? whereBuilder.buildUniqueWhereSchema(model, shape.where) : whereBuilder.buildWhereSchema(model, shape.where);
|
|
3324
|
+
if (!builtWhere.schema && !hasWhereForced(builtWhere.forced)) {
|
|
3325
|
+
throw new ShapeError(
|
|
3326
|
+
`"where" in shape for model "${model}" method "${method}" produced no schema and no forced conditions.`
|
|
3327
|
+
);
|
|
3328
|
+
}
|
|
3276
3329
|
if (builtWhere.schema) {
|
|
3277
3330
|
schemaFields.where = builtWhere.schema;
|
|
3278
3331
|
}
|
|
@@ -4074,27 +4127,19 @@ function validateRelationOpKeys(actual, opKey, model, field, opLabel) {
|
|
|
4074
4127
|
const allowed = RELATION_OP_ALLOWED_KEYS[opKey];
|
|
4075
4128
|
if (!allowed)
|
|
4076
4129
|
return;
|
|
4077
|
-
|
|
4078
|
-
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
}
|
|
4083
|
-
}
|
|
4130
|
+
assertAllowedKeys(
|
|
4131
|
+
actual,
|
|
4132
|
+
allowed,
|
|
4133
|
+
(key) => `Unknown key "${key}" in ${opLabel} config on "${model}.${field}". Allowed: ${[...allowed].join(", ")}`
|
|
4134
|
+
);
|
|
4084
4135
|
}
|
|
4085
4136
|
function validateAllowedKeys(value, allowed, method, kind) {
|
|
4086
|
-
|
|
4087
|
-
if (
|
|
4088
|
-
|
|
4089
|
-
throw new ShapeError(
|
|
4090
|
-
`Unexpected key "${key}" in ${method} body. Allowed keys: ${[...allowed].join(", ")}`
|
|
4091
|
-
);
|
|
4092
|
-
}
|
|
4093
|
-
throw new ShapeError(
|
|
4094
|
-
`Shape key "${key}" not valid for ${method}. Allowed: ${[...allowed].join(", ")}`
|
|
4095
|
-
);
|
|
4137
|
+
assertAllowedKeys(value, allowed, (key) => {
|
|
4138
|
+
if (kind === "body") {
|
|
4139
|
+
return `Unexpected key "${key}" in ${method} body. Allowed keys: ${[...allowed].join(", ")}`;
|
|
4096
4140
|
}
|
|
4097
|
-
|
|
4141
|
+
return `Shape key "${key}" not valid for ${method}. Allowed: ${[...allowed].join(", ")}`;
|
|
4142
|
+
});
|
|
4098
4143
|
}
|
|
4099
4144
|
function validateCreateCompleteness(modelName, dataConfig, typeMap, scopeFks, zodDefaults) {
|
|
4100
4145
|
const modelFields = typeMap[modelName];
|
|
@@ -4181,18 +4226,10 @@ function buildNestedDataSchema(model, config, mode, typeMap, schemaBuilder) {
|
|
|
4181
4226
|
}
|
|
4182
4227
|
return import_zod10.z.object(fieldSchemas).strict();
|
|
4183
4228
|
}
|
|
4184
|
-
function requirePlainObjectConfig(value, message) {
|
|
4185
|
-
if (!isPlainObject(value))
|
|
4186
|
-
throw new ShapeError(message);
|
|
4187
|
-
return value;
|
|
4188
|
-
}
|
|
4189
4229
|
function requireNestedObject(cfg, key, message) {
|
|
4190
|
-
|
|
4191
|
-
if (!v || !isPlainObject(v))
|
|
4192
|
-
throw new ShapeError(message);
|
|
4193
|
-
return v;
|
|
4230
|
+
return requirePlainObjectConfig(cfg[key], message);
|
|
4194
4231
|
}
|
|
4195
|
-
function
|
|
4232
|
+
function buildRelatedUniqueSelector(ctx, cfg, context) {
|
|
4196
4233
|
return buildUniqueSelectorSchema(
|
|
4197
4234
|
ctx.model,
|
|
4198
4235
|
ctx.fieldName,
|
|
@@ -4205,7 +4242,7 @@ function buildUniqueSelector(ctx, cfg, context) {
|
|
|
4205
4242
|
context
|
|
4206
4243
|
);
|
|
4207
4244
|
}
|
|
4208
|
-
function
|
|
4245
|
+
function buildRelatedNestedData(ctx, cfg, mode) {
|
|
4209
4246
|
return buildNestedDataSchema(
|
|
4210
4247
|
ctx.relatedModelName,
|
|
4211
4248
|
cfg,
|
|
@@ -4219,7 +4256,7 @@ var handleConnect = (ctx) => {
|
|
|
4219
4256
|
ctx.config,
|
|
4220
4257
|
`connect config on "${ctx.model}.${ctx.fieldName}" must be an object of unique selectors`
|
|
4221
4258
|
);
|
|
4222
|
-
const schema =
|
|
4259
|
+
const schema = buildRelatedUniqueSelector(ctx, cfg, "connect");
|
|
4223
4260
|
return wrapRelationOp(ctx.isList, schema);
|
|
4224
4261
|
};
|
|
4225
4262
|
var handleConnectOrCreate = (ctx) => {
|
|
@@ -4238,8 +4275,8 @@ var handleConnectOrCreate = (ctx) => {
|
|
|
4238
4275
|
"create",
|
|
4239
4276
|
`connectOrCreate on "${ctx.model}.${ctx.fieldName}" requires "create" object`
|
|
4240
4277
|
);
|
|
4241
|
-
const whereSchema =
|
|
4242
|
-
const createSchema =
|
|
4278
|
+
const whereSchema = buildRelatedUniqueSelector(ctx, where, "connectOrCreate.where");
|
|
4279
|
+
const createSchema = buildRelatedNestedData(ctx, create, "create");
|
|
4243
4280
|
const cocSchema = import_zod10.z.object({ where: whereSchema, create: createSchema }).strict();
|
|
4244
4281
|
return wrapRelationOp(ctx.isList, cocSchema);
|
|
4245
4282
|
};
|
|
@@ -4248,7 +4285,7 @@ var handleCreate = (ctx) => {
|
|
|
4248
4285
|
ctx.config,
|
|
4249
4286
|
`create config on "${ctx.model}.${ctx.fieldName}" must be an object of field names`
|
|
4250
4287
|
);
|
|
4251
|
-
const createSchema =
|
|
4288
|
+
const createSchema = buildRelatedNestedData(ctx, cfg, "create");
|
|
4252
4289
|
return wrapRelationOp(ctx.isList, createSchema);
|
|
4253
4290
|
};
|
|
4254
4291
|
var handleCreateMany = (ctx) => {
|
|
@@ -4267,7 +4304,7 @@ var handleCreateMany = (ctx) => {
|
|
|
4267
4304
|
"data",
|
|
4268
4305
|
`createMany on "${ctx.model}.${ctx.fieldName}" requires "data" object`
|
|
4269
4306
|
);
|
|
4270
|
-
const dataSchema =
|
|
4307
|
+
const dataSchema = buildRelatedNestedData(ctx, data, "create");
|
|
4271
4308
|
const cmSchemaFields = {
|
|
4272
4309
|
data: import_zod10.z.preprocess(coerceToArray, import_zod10.z.array(dataSchema))
|
|
4273
4310
|
};
|
|
@@ -4290,7 +4327,7 @@ var handleDisconnect = (ctx) => {
|
|
|
4290
4327
|
`disconnect config on "${ctx.model}.${ctx.fieldName}" must be true (to-one) or an object of unique selectors`
|
|
4291
4328
|
);
|
|
4292
4329
|
}
|
|
4293
|
-
const schema =
|
|
4330
|
+
const schema = buildRelatedUniqueSelector(ctx, ctx.config, "disconnect");
|
|
4294
4331
|
if (ctx.isList)
|
|
4295
4332
|
return wrapRelationOp(true, schema);
|
|
4296
4333
|
return import_zod10.z.union([import_zod10.z.literal(true), schema]).optional();
|
|
@@ -4309,7 +4346,7 @@ var handleDelete = (ctx) => {
|
|
|
4309
4346
|
`delete config on "${ctx.model}.${ctx.fieldName}" must be true (to-one) or an object of unique selectors`
|
|
4310
4347
|
);
|
|
4311
4348
|
}
|
|
4312
|
-
const schema =
|
|
4349
|
+
const schema = buildRelatedUniqueSelector(ctx, ctx.config, "delete");
|
|
4313
4350
|
if (ctx.isList)
|
|
4314
4351
|
return wrapRelationOp(true, schema);
|
|
4315
4352
|
return import_zod10.z.union([import_zod10.z.literal(true), schema]).optional();
|
|
@@ -4324,7 +4361,7 @@ var handleSet = (ctx) => {
|
|
|
4324
4361
|
ctx.config,
|
|
4325
4362
|
`set config on "${ctx.model}.${ctx.fieldName}" must be an object of unique selectors`
|
|
4326
4363
|
);
|
|
4327
|
-
const schema =
|
|
4364
|
+
const schema = buildRelatedUniqueSelector(ctx, cfg, "set");
|
|
4328
4365
|
return wrapRelationOp(true, schema);
|
|
4329
4366
|
};
|
|
4330
4367
|
var handleUpdate = (ctx) => {
|
|
@@ -4344,12 +4381,12 @@ var handleUpdate = (ctx) => {
|
|
|
4344
4381
|
"data",
|
|
4345
4382
|
`update on to-many "${ctx.model}.${ctx.fieldName}" requires "data" object`
|
|
4346
4383
|
);
|
|
4347
|
-
const whereSchema =
|
|
4348
|
-
const dataSchema2 =
|
|
4384
|
+
const whereSchema = buildRelatedUniqueSelector(ctx, where, "update.where");
|
|
4385
|
+
const dataSchema2 = buildRelatedNestedData(ctx, data, "update");
|
|
4349
4386
|
const updateSchema = import_zod10.z.object({ where: whereSchema, data: dataSchema2 }).strict();
|
|
4350
4387
|
return wrapRelationOp(true, updateSchema);
|
|
4351
4388
|
}
|
|
4352
|
-
const dataSchema =
|
|
4389
|
+
const dataSchema = buildRelatedNestedData(ctx, cfg, "update");
|
|
4353
4390
|
return dataSchema.optional();
|
|
4354
4391
|
};
|
|
4355
4392
|
var handleUpsert = (ctx) => {
|
|
@@ -4374,15 +4411,15 @@ var handleUpsert = (ctx) => {
|
|
|
4374
4411
|
"update",
|
|
4375
4412
|
`upsert on "${ctx.model}.${ctx.fieldName}" requires "update" object`
|
|
4376
4413
|
);
|
|
4377
|
-
const createSchema =
|
|
4378
|
-
const updateSchema =
|
|
4414
|
+
const createSchema = buildRelatedNestedData(ctx, create, "create");
|
|
4415
|
+
const updateSchema = buildRelatedNestedData(ctx, update, "update");
|
|
4379
4416
|
if (ctx.isList) {
|
|
4380
4417
|
const where = requireNestedObject(
|
|
4381
4418
|
cfg,
|
|
4382
4419
|
"where",
|
|
4383
4420
|
`upsert on to-many "${ctx.model}.${ctx.fieldName}" requires "where" object`
|
|
4384
4421
|
);
|
|
4385
|
-
const whereSchema =
|
|
4422
|
+
const whereSchema = buildRelatedUniqueSelector(ctx, where, "upsert.where");
|
|
4386
4423
|
const upsertSchema2 = import_zod10.z.object({ where: whereSchema, create: createSchema, update: updateSchema }).strict();
|
|
4387
4424
|
return wrapRelationOp(true, upsertSchema2);
|
|
4388
4425
|
}
|
|
@@ -4393,7 +4430,7 @@ var handleUpsert = (ctx) => {
|
|
|
4393
4430
|
`upsert on to-one "${ctx.model}.${ctx.fieldName}" has invalid "where": must be a plain object of unique selectors`
|
|
4394
4431
|
);
|
|
4395
4432
|
}
|
|
4396
|
-
const whereSchema =
|
|
4433
|
+
const whereSchema = buildRelatedUniqueSelector(ctx, cfg.where, "upsert.where");
|
|
4397
4434
|
const upsertSchema2 = import_zod10.z.object({ where: whereSchema, create: createSchema, update: updateSchema }).strict();
|
|
4398
4435
|
return upsertSchema2.optional();
|
|
4399
4436
|
}
|
|
@@ -4437,7 +4474,7 @@ var handleUpdateMany = (ctx) => {
|
|
|
4437
4474
|
ctx.typeMap,
|
|
4438
4475
|
ctx.schemaBuilder
|
|
4439
4476
|
);
|
|
4440
|
-
const dataSchema =
|
|
4477
|
+
const dataSchema = buildRelatedNestedData(ctx, data, "update");
|
|
4441
4478
|
const umSchema = import_zod10.z.object({ where: whereSchema, data: dataSchema }).strict();
|
|
4442
4479
|
return wrapRelationOp(true, umSchema);
|
|
4443
4480
|
};
|
|
@@ -4484,17 +4521,21 @@ function buildRelationWriteSchema(model, fieldName, relatedModelName, isList, co
|
|
|
4484
4521
|
throw new ShapeError(
|
|
4485
4522
|
`Unknown related model "${relatedModelName}" for field "${model}.${fieldName}"`
|
|
4486
4523
|
);
|
|
4487
|
-
|
|
4488
|
-
|
|
4489
|
-
|
|
4490
|
-
|
|
4491
|
-
|
|
4492
|
-
|
|
4524
|
+
assertAllowedKeys(
|
|
4525
|
+
config,
|
|
4526
|
+
KNOWN_RELATION_WRITE_OPS,
|
|
4527
|
+
(key) => `Unknown relation write operation "${key}" on "${model}.${fieldName}". Allowed: ${[...KNOWN_RELATION_WRITE_OPS].join(", ")}`
|
|
4528
|
+
);
|
|
4529
|
+
const definedEntries = Object.entries(config).filter(
|
|
4530
|
+
([, opConfig]) => opConfig !== void 0
|
|
4531
|
+
);
|
|
4532
|
+
if (definedEntries.length === 0) {
|
|
4533
|
+
throw new ShapeError(
|
|
4534
|
+
`Empty relation write config on "${model}.${fieldName}". Define at least one operation: ${[...KNOWN_RELATION_WRITE_OPS].join(", ")}`
|
|
4535
|
+
);
|
|
4493
4536
|
}
|
|
4494
4537
|
const opSchemas = {};
|
|
4495
|
-
for (const [op, opConfig] of
|
|
4496
|
-
if (opConfig === void 0)
|
|
4497
|
-
continue;
|
|
4538
|
+
for (const [op, opConfig] of definedEntries) {
|
|
4498
4539
|
const handler = RELATION_OP_HANDLERS[op];
|
|
4499
4540
|
opSchemas[op] = handler({
|
|
4500
4541
|
model,
|
|
@@ -4511,7 +4552,7 @@ function buildRelationWriteSchema(model, fieldName, relatedModelName, isList, co
|
|
|
4511
4552
|
}
|
|
4512
4553
|
return import_zod10.z.object(opSchemas).strict();
|
|
4513
4554
|
}
|
|
4514
|
-
function buildDataSchema(model, dataConfig, mode, typeMap, uniqueMap, enumMap, scalarBase, schemaBuilder, zodDefaults) {
|
|
4555
|
+
function buildDataSchema(model, dataConfig, mode, typeMap, uniqueMap, enumMap, scalarBase, schemaBuilder, zodDefaults, allowRelationWrites) {
|
|
4515
4556
|
const modelFields = typeMap[model];
|
|
4516
4557
|
if (!modelFields)
|
|
4517
4558
|
throw new ShapeError(`Unknown model: ${model}`);
|
|
@@ -4541,6 +4582,11 @@ function buildDataSchema(model, dataConfig, mode, typeMap, uniqueMap, enumMap, s
|
|
|
4541
4582
|
continue;
|
|
4542
4583
|
}
|
|
4543
4584
|
if (fieldMeta.isRelation) {
|
|
4585
|
+
if (!allowRelationWrites) {
|
|
4586
|
+
throw new ShapeError(
|
|
4587
|
+
`Field "${fieldName}" on model "${model}" is a relation. Relation writes are not supported for this method.`
|
|
4588
|
+
);
|
|
4589
|
+
}
|
|
4544
4590
|
if (!isPlainObject(value)) {
|
|
4545
4591
|
throw new ShapeError(
|
|
4546
4592
|
`Relation field "${fieldName}" on model "${model}" requires a relation write config object`
|
|
@@ -4654,13 +4700,8 @@ function validateAndMergeData(bodyData, cached, method, modelName) {
|
|
|
4654
4700
|
try {
|
|
4655
4701
|
validated = cached.schema.parse(bodyData);
|
|
4656
4702
|
} catch (err) {
|
|
4657
|
-
|
|
4658
|
-
|
|
4659
|
-
if (err && typeof err === "object" && "issues" in err) {
|
|
4660
|
-
const context = modelName ? `Invalid data for ${method} on model "${modelName}"` : `Invalid data for ${method}`;
|
|
4661
|
-
throw new ShapeError(`${context}: ${formatZodError(err)}`, { cause: err });
|
|
4662
|
-
}
|
|
4663
|
-
throw err;
|
|
4703
|
+
const context = modelName ? `Invalid data for ${method} on model "${modelName}"` : `Invalid data for ${method}`;
|
|
4704
|
+
wrapParseError(err, context);
|
|
4664
4705
|
}
|
|
4665
4706
|
return { ...validated, ...deepClone(cached.forced) };
|
|
4666
4707
|
}
|
|
@@ -4815,6 +4856,8 @@ var PROJECTION_MUTATION_METHODS = /* @__PURE__ */ new Set([
|
|
|
4815
4856
|
"updateManyAndReturn"
|
|
4816
4857
|
]);
|
|
4817
4858
|
var BATCH_CREATE_METHODS = /* @__PURE__ */ new Set(["createMany", "createManyAndReturn"]);
|
|
4859
|
+
var RELATION_WRITE_CREATE_METHODS = /* @__PURE__ */ new Set(["create"]);
|
|
4860
|
+
var RELATION_WRITE_UPDATE_METHODS = /* @__PURE__ */ new Set(["update"]);
|
|
4818
4861
|
var MAX_PROJECTION_WALK_DEPTH = 10;
|
|
4819
4862
|
function walkForClientContent(obj, predicate, depth) {
|
|
4820
4863
|
if (depth > MAX_PROJECTION_WALK_DEPTH)
|
|
@@ -4840,12 +4883,23 @@ function walkForClientContent(obj, predicate, depth) {
|
|
|
4840
4883
|
const nested = value;
|
|
4841
4884
|
if (nested.orderBy || nested.cursor || nested.take || nested.skip)
|
|
4842
4885
|
return true;
|
|
4843
|
-
if (nested.where && isPlainObject(nested.where) && hasClientControlledValues(
|
|
4886
|
+
if (nested.where && isPlainObject(nested.where) && hasClientControlledValues(
|
|
4887
|
+
nested.where,
|
|
4888
|
+
depth + 1
|
|
4889
|
+
)) {
|
|
4844
4890
|
return true;
|
|
4845
4891
|
}
|
|
4846
|
-
if (nested.include && walkForClientContent(
|
|
4892
|
+
if (nested.include && walkForClientContent(
|
|
4893
|
+
nested.include,
|
|
4894
|
+
predicate,
|
|
4895
|
+
depth + 1
|
|
4896
|
+
))
|
|
4847
4897
|
return true;
|
|
4848
|
-
if (nested.select && walkForClientContent(
|
|
4898
|
+
if (nested.select && walkForClientContent(
|
|
4899
|
+
nested.select,
|
|
4900
|
+
predicate,
|
|
4901
|
+
depth + 1
|
|
4902
|
+
))
|
|
4849
4903
|
return true;
|
|
4850
4904
|
}
|
|
4851
4905
|
return false;
|
|
@@ -4867,11 +4921,19 @@ function hasClientControlledValues(obj, depth = 0) {
|
|
|
4867
4921
|
function hasNestedClientControlledArgs(shape) {
|
|
4868
4922
|
const predicate = () => false;
|
|
4869
4923
|
if (shape.include) {
|
|
4870
|
-
if (walkForClientContent(
|
|
4924
|
+
if (walkForClientContent(
|
|
4925
|
+
shape.include,
|
|
4926
|
+
predicate,
|
|
4927
|
+
0
|
|
4928
|
+
))
|
|
4871
4929
|
return true;
|
|
4872
4930
|
}
|
|
4873
4931
|
if (shape.select) {
|
|
4874
|
-
if (walkForClientContent(
|
|
4932
|
+
if (walkForClientContent(
|
|
4933
|
+
shape.select,
|
|
4934
|
+
predicate,
|
|
4935
|
+
0
|
|
4936
|
+
))
|
|
4875
4937
|
return true;
|
|
4876
4938
|
}
|
|
4877
4939
|
return false;
|
|
@@ -4965,11 +5027,11 @@ function createModelGuardExtension(config) {
|
|
|
4965
5027
|
)
|
|
4966
5028
|
);
|
|
4967
5029
|
}
|
|
4968
|
-
function getDataSchema(mode, dataConfig, matchedKey, wasDynamic) {
|
|
5030
|
+
function getDataSchema(mode, dataConfig, matchedKey, wasDynamic, allowRelationWrites) {
|
|
4969
5031
|
const skipCache = wasDynamic || hasDataRefines(dataConfig);
|
|
4970
5032
|
return memoize(
|
|
4971
5033
|
dataSchemaCache,
|
|
4972
|
-
`${mode}\0${matchedKey}`,
|
|
5034
|
+
`${mode}\0${matchedKey}\0${allowRelationWrites ? "r" : "n"}`,
|
|
4973
5035
|
skipCache,
|
|
4974
5036
|
() => buildDataSchema(
|
|
4975
5037
|
modelName,
|
|
@@ -4980,7 +5042,8 @@ function createModelGuardExtension(config) {
|
|
|
4980
5042
|
enumMap,
|
|
4981
5043
|
scalarBase,
|
|
4982
5044
|
schemaBuilder,
|
|
4983
|
-
zodDefaults
|
|
5045
|
+
zodDefaults,
|
|
5046
|
+
allowRelationWrites
|
|
4984
5047
|
)
|
|
4985
5048
|
);
|
|
4986
5049
|
}
|
|
@@ -5168,15 +5231,13 @@ function createModelGuardExtension(config) {
|
|
|
5168
5231
|
let result = {};
|
|
5169
5232
|
if (built.schema) {
|
|
5170
5233
|
if (bodyWhere !== void 0 && bodyWhere !== null) {
|
|
5171
|
-
if (!
|
|
5234
|
+
if (!isObjectLike(bodyWhere)) {
|
|
5172
5235
|
throw new ShapeError(
|
|
5173
|
-
`Invalid "where" on model "${modelName}": unique where must be
|
|
5236
|
+
`Invalid "where" on model "${modelName}": unique where must be an object`
|
|
5174
5237
|
);
|
|
5175
5238
|
}
|
|
5176
|
-
const
|
|
5177
|
-
|
|
5178
|
-
built.forced
|
|
5179
|
-
) : { ...bodyWhere };
|
|
5239
|
+
const bodyWhereObj = { ...bodyWhere };
|
|
5240
|
+
const sanitized = hasWhereForced(built.forced) ? stripUniqueWhereForcedInput(bodyWhereObj, built.forced) : bodyWhereObj;
|
|
5180
5241
|
try {
|
|
5181
5242
|
result = built.schema.parse(sanitized);
|
|
5182
5243
|
} catch (err) {
|
|
@@ -5188,11 +5249,9 @@ function createModelGuardExtension(config) {
|
|
|
5188
5249
|
}
|
|
5189
5250
|
}
|
|
5190
5251
|
} else if (bodyWhere !== void 0 && bodyWhere !== null) {
|
|
5191
|
-
if (
|
|
5192
|
-
const
|
|
5193
|
-
|
|
5194
|
-
built.forced
|
|
5195
|
-
) : { ...bodyWhere };
|
|
5252
|
+
if (isObjectLike(bodyWhere)) {
|
|
5253
|
+
const bodyWhereObj = { ...bodyWhere };
|
|
5254
|
+
const sanitized = hasWhereForced(built.forced) ? stripUniqueWhereForcedInput(bodyWhereObj, built.forced) : bodyWhereObj;
|
|
5196
5255
|
if (Object.keys(sanitized).length > 0) {
|
|
5197
5256
|
throw new ShapeError(
|
|
5198
5257
|
`Unique where on model "${modelName}" contains only forced values. Client where input is not accepted.`
|
|
@@ -5200,7 +5259,7 @@ function createModelGuardExtension(config) {
|
|
|
5200
5259
|
}
|
|
5201
5260
|
} else {
|
|
5202
5261
|
throw new ShapeError(
|
|
5203
|
-
`Invalid "where" on model "${modelName}": unique where must be
|
|
5262
|
+
`Invalid "where" on model "${modelName}": unique where must be an object`
|
|
5204
5263
|
);
|
|
5205
5264
|
}
|
|
5206
5265
|
}
|
|
@@ -5238,6 +5297,39 @@ function createModelGuardExtension(config) {
|
|
|
5238
5297
|
const defaultProjection = buildDefaultProjectionBody(resolved.shape);
|
|
5239
5298
|
return { ...resolved.body, ...defaultProjection };
|
|
5240
5299
|
}
|
|
5300
|
+
function makeResolveMethod() {
|
|
5301
|
+
const WRITE_KEYS = ["data", "create", "update"];
|
|
5302
|
+
const hasOwn = (obj, key) => Object.prototype.hasOwnProperty.call(obj, key);
|
|
5303
|
+
return (body) => {
|
|
5304
|
+
const caller = resolveCaller();
|
|
5305
|
+
const resolved = resolveShape(input, body, contextFn, caller);
|
|
5306
|
+
for (const key of WRITE_KEYS) {
|
|
5307
|
+
if (hasOwn(resolved.shape, key)) {
|
|
5308
|
+
throw new ShapeError(
|
|
5309
|
+
`.resolve() is a read-only planning helper. Guard shape contains write key "${key}". Use the corresponding write method instead.`
|
|
5310
|
+
);
|
|
5311
|
+
}
|
|
5312
|
+
}
|
|
5313
|
+
for (const key of WRITE_KEYS) {
|
|
5314
|
+
if (hasOwn(resolved.body, key)) {
|
|
5315
|
+
throw new ShapeError(
|
|
5316
|
+
`.resolve() is a read-only planning helper. Request body contains write key "${key}".`
|
|
5317
|
+
);
|
|
5318
|
+
}
|
|
5319
|
+
}
|
|
5320
|
+
const effectiveReadBody = buildEffectiveReadBody({
|
|
5321
|
+
shape: resolved.shape,
|
|
5322
|
+
body: resolved.body
|
|
5323
|
+
});
|
|
5324
|
+
return {
|
|
5325
|
+
shape: resolved.shape,
|
|
5326
|
+
body: resolved.body,
|
|
5327
|
+
effectiveReadBody,
|
|
5328
|
+
matchedKey: resolved.matchedKey,
|
|
5329
|
+
wasDynamic: resolved.wasDynamic
|
|
5330
|
+
};
|
|
5331
|
+
};
|
|
5332
|
+
}
|
|
5241
5333
|
function makeReadMethod(method) {
|
|
5242
5334
|
return (body) => {
|
|
5243
5335
|
const caller = resolveCaller();
|
|
@@ -5271,6 +5363,7 @@ function createModelGuardExtension(config) {
|
|
|
5271
5363
|
const supportsProjection = PROJECTION_MUTATION_METHODS.has(method);
|
|
5272
5364
|
const allowedBodyKeys = getAllowedBodyKeys(method, supportsProjection);
|
|
5273
5365
|
const allowedShapeKeys = getAllowedShapeKeys(method, supportsProjection);
|
|
5366
|
+
const allowRelationWrites = RELATION_WRITE_CREATE_METHODS.has(method);
|
|
5274
5367
|
return (body) => {
|
|
5275
5368
|
const caller = resolveCaller();
|
|
5276
5369
|
const resolved = resolveShape(input, body, contextFn, caller);
|
|
@@ -5296,7 +5389,8 @@ function createModelGuardExtension(config) {
|
|
|
5296
5389
|
"create",
|
|
5297
5390
|
resolved.shape.data,
|
|
5298
5391
|
resolved.matchedKey,
|
|
5299
|
-
resolved.wasDynamic
|
|
5392
|
+
resolved.wasDynamic,
|
|
5393
|
+
allowRelationWrites
|
|
5300
5394
|
);
|
|
5301
5395
|
let args;
|
|
5302
5396
|
if (method === "create") {
|
|
@@ -5344,6 +5438,7 @@ function createModelGuardExtension(config) {
|
|
|
5344
5438
|
const supportsProjection = PROJECTION_MUTATION_METHODS.has(method);
|
|
5345
5439
|
const allowedBodyKeys = getAllowedBodyKeys(method, supportsProjection);
|
|
5346
5440
|
const allowedShapeKeys = getAllowedShapeKeys(method, supportsProjection);
|
|
5441
|
+
const allowRelationWrites = RELATION_WRITE_UPDATE_METHODS.has(method);
|
|
5347
5442
|
return (body) => {
|
|
5348
5443
|
const caller = resolveCaller();
|
|
5349
5444
|
const resolved = resolveShape(input, body, contextFn, caller);
|
|
@@ -5366,7 +5461,8 @@ function createModelGuardExtension(config) {
|
|
|
5366
5461
|
"update",
|
|
5367
5462
|
resolved.shape.data,
|
|
5368
5463
|
resolved.matchedKey,
|
|
5369
|
-
resolved.wasDynamic
|
|
5464
|
+
resolved.wasDynamic,
|
|
5465
|
+
allowRelationWrites
|
|
5370
5466
|
);
|
|
5371
5467
|
const data = validateAndMergeData(
|
|
5372
5468
|
resolved.body.data,
|
|
@@ -5516,12 +5612,7 @@ function createModelGuardExtension(config) {
|
|
|
5516
5612
|
"upsert",
|
|
5517
5613
|
"shape"
|
|
5518
5614
|
);
|
|
5519
|
-
validateAllowedKeys(
|
|
5520
|
-
resolved.body,
|
|
5521
|
-
allowedBodyKeys,
|
|
5522
|
-
"upsert",
|
|
5523
|
-
"body"
|
|
5524
|
-
);
|
|
5615
|
+
validateAllowedKeys(resolved.body, allowedBodyKeys, "upsert", "body");
|
|
5525
5616
|
validateUniqueWhereShapeConfig(
|
|
5526
5617
|
modelName,
|
|
5527
5618
|
resolved.shape.where,
|
|
@@ -5539,7 +5630,8 @@ function createModelGuardExtension(config) {
|
|
|
5539
5630
|
"create",
|
|
5540
5631
|
resolved.shape.create,
|
|
5541
5632
|
`upsert:create\0${resolved.matchedKey}`,
|
|
5542
|
-
resolved.wasDynamic
|
|
5633
|
+
resolved.wasDynamic,
|
|
5634
|
+
true
|
|
5543
5635
|
);
|
|
5544
5636
|
const createData = validateAndMergeData(
|
|
5545
5637
|
resolved.body.create,
|
|
@@ -5551,7 +5643,8 @@ function createModelGuardExtension(config) {
|
|
|
5551
5643
|
"update",
|
|
5552
5644
|
resolved.shape.update,
|
|
5553
5645
|
`upsert:update\0${resolved.matchedKey}`,
|
|
5554
|
-
resolved.wasDynamic
|
|
5646
|
+
resolved.wasDynamic,
|
|
5647
|
+
true
|
|
5555
5648
|
);
|
|
5556
5649
|
const updateData = validateAndMergeData(
|
|
5557
5650
|
resolved.body.update,
|
|
@@ -5584,6 +5677,7 @@ function createModelGuardExtension(config) {
|
|
|
5584
5677
|
};
|
|
5585
5678
|
}
|
|
5586
5679
|
return {
|
|
5680
|
+
resolve: makeResolveMethod(),
|
|
5587
5681
|
findMany: makeReadMethod("findMany"),
|
|
5588
5682
|
findFirst: makeReadMethod("findFirst"),
|
|
5589
5683
|
findFirstOrThrow: makeReadMethod("findFirstOrThrow"),
|