prisma-guard 1.11.0 → 1.13.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/dist/runtime/index.cjs +554 -17
- package/dist/runtime/index.cjs.map +1 -1
- package/dist/runtime/index.js +554 -17
- package/dist/runtime/index.js.map +1 -1
- package/package.json +1 -1
package/dist/runtime/index.js
CHANGED
|
@@ -2813,21 +2813,80 @@ import { z as z9 } from "zod";
|
|
|
2813
2813
|
// src/runtime/model-guard-data.ts
|
|
2814
2814
|
import { z as z8 } from "zod";
|
|
2815
2815
|
var ALLOWED_BODY_KEYS_CREATE = /* @__PURE__ */ new Set(["data"]);
|
|
2816
|
-
var ALLOWED_BODY_KEYS_CREATE_PROJECTION = /* @__PURE__ */ new Set([
|
|
2817
|
-
|
|
2818
|
-
|
|
2816
|
+
var ALLOWED_BODY_KEYS_CREATE_PROJECTION = /* @__PURE__ */ new Set([
|
|
2817
|
+
"data",
|
|
2818
|
+
"select",
|
|
2819
|
+
"include"
|
|
2820
|
+
]);
|
|
2821
|
+
var ALLOWED_BODY_KEYS_CREATE_MANY = /* @__PURE__ */ new Set([
|
|
2822
|
+
"data",
|
|
2823
|
+
"skipDuplicates"
|
|
2824
|
+
]);
|
|
2825
|
+
var ALLOWED_BODY_KEYS_CREATE_MANY_PROJECTION = /* @__PURE__ */ new Set([
|
|
2826
|
+
"data",
|
|
2827
|
+
"select",
|
|
2828
|
+
"include",
|
|
2829
|
+
"skipDuplicates"
|
|
2830
|
+
]);
|
|
2819
2831
|
var ALLOWED_BODY_KEYS_UPDATE = /* @__PURE__ */ new Set(["data", "where"]);
|
|
2820
|
-
var ALLOWED_BODY_KEYS_UPDATE_PROJECTION = /* @__PURE__ */ new Set([
|
|
2832
|
+
var ALLOWED_BODY_KEYS_UPDATE_PROJECTION = /* @__PURE__ */ new Set([
|
|
2833
|
+
"data",
|
|
2834
|
+
"where",
|
|
2835
|
+
"select",
|
|
2836
|
+
"include"
|
|
2837
|
+
]);
|
|
2821
2838
|
var ALLOWED_BODY_KEYS_DELETE = /* @__PURE__ */ new Set(["where"]);
|
|
2822
|
-
var ALLOWED_BODY_KEYS_DELETE_PROJECTION = /* @__PURE__ */ new Set([
|
|
2823
|
-
|
|
2839
|
+
var ALLOWED_BODY_KEYS_DELETE_PROJECTION = /* @__PURE__ */ new Set([
|
|
2840
|
+
"where",
|
|
2841
|
+
"select",
|
|
2842
|
+
"include"
|
|
2843
|
+
]);
|
|
2844
|
+
var ALLOWED_BODY_KEYS_UPSERT = /* @__PURE__ */ new Set([
|
|
2845
|
+
"where",
|
|
2846
|
+
"create",
|
|
2847
|
+
"update",
|
|
2848
|
+
"select",
|
|
2849
|
+
"include"
|
|
2850
|
+
]);
|
|
2824
2851
|
var VALID_SHAPE_KEYS_CREATE = /* @__PURE__ */ new Set(["data"]);
|
|
2825
|
-
var VALID_SHAPE_KEYS_CREATE_PROJECTION = /* @__PURE__ */ new Set([
|
|
2852
|
+
var VALID_SHAPE_KEYS_CREATE_PROJECTION = /* @__PURE__ */ new Set([
|
|
2853
|
+
"data",
|
|
2854
|
+
"select",
|
|
2855
|
+
"include"
|
|
2856
|
+
]);
|
|
2826
2857
|
var VALID_SHAPE_KEYS_UPDATE = /* @__PURE__ */ new Set(["data", "where"]);
|
|
2827
|
-
var VALID_SHAPE_KEYS_UPDATE_PROJECTION = /* @__PURE__ */ new Set([
|
|
2858
|
+
var VALID_SHAPE_KEYS_UPDATE_PROJECTION = /* @__PURE__ */ new Set([
|
|
2859
|
+
"data",
|
|
2860
|
+
"where",
|
|
2861
|
+
"select",
|
|
2862
|
+
"include"
|
|
2863
|
+
]);
|
|
2828
2864
|
var VALID_SHAPE_KEYS_DELETE = /* @__PURE__ */ new Set(["where"]);
|
|
2829
|
-
var VALID_SHAPE_KEYS_DELETE_PROJECTION = /* @__PURE__ */ new Set([
|
|
2830
|
-
|
|
2865
|
+
var VALID_SHAPE_KEYS_DELETE_PROJECTION = /* @__PURE__ */ new Set([
|
|
2866
|
+
"where",
|
|
2867
|
+
"select",
|
|
2868
|
+
"include"
|
|
2869
|
+
]);
|
|
2870
|
+
var VALID_SHAPE_KEYS_UPSERT = /* @__PURE__ */ new Set([
|
|
2871
|
+
"where",
|
|
2872
|
+
"create",
|
|
2873
|
+
"update",
|
|
2874
|
+
"select",
|
|
2875
|
+
"include"
|
|
2876
|
+
]);
|
|
2877
|
+
var KNOWN_RELATION_WRITE_OPS = /* @__PURE__ */ new Set([
|
|
2878
|
+
"connect",
|
|
2879
|
+
"connectOrCreate",
|
|
2880
|
+
"create",
|
|
2881
|
+
"createMany",
|
|
2882
|
+
"disconnect",
|
|
2883
|
+
"delete",
|
|
2884
|
+
"set",
|
|
2885
|
+
"update",
|
|
2886
|
+
"updateMany",
|
|
2887
|
+
"upsert",
|
|
2888
|
+
"deleteMany"
|
|
2889
|
+
]);
|
|
2831
2890
|
function validateMutationBodyKeys(body, allowed, method) {
|
|
2832
2891
|
for (const key of Object.keys(body)) {
|
|
2833
2892
|
if (!allowed.has(key)) {
|
|
@@ -2872,6 +2931,456 @@ function validateCreateCompleteness(modelName, dataConfig, typeMap, scopeFks, zo
|
|
|
2872
2931
|
);
|
|
2873
2932
|
}
|
|
2874
2933
|
}
|
|
2934
|
+
function buildWhereFieldsSchema(model, config, typeMap, schemaBuilder) {
|
|
2935
|
+
const modelFields = typeMap[model];
|
|
2936
|
+
if (!modelFields)
|
|
2937
|
+
throw new ShapeError(`Unknown model: ${model}`);
|
|
2938
|
+
const fieldSchemas = {};
|
|
2939
|
+
const fieldKeys = [];
|
|
2940
|
+
for (const [fieldName, value] of Object.entries(config)) {
|
|
2941
|
+
if (value !== true)
|
|
2942
|
+
throw new ShapeError(
|
|
2943
|
+
`Field "${fieldName}" in connect/where config must be true`
|
|
2944
|
+
);
|
|
2945
|
+
const meta = modelFields[fieldName];
|
|
2946
|
+
if (!meta)
|
|
2947
|
+
throw new ShapeError(`Unknown field "${fieldName}" on model "${model}"`);
|
|
2948
|
+
if (meta.isRelation)
|
|
2949
|
+
throw new ShapeError(
|
|
2950
|
+
`Relation field "${fieldName}" cannot be used in connect/where`
|
|
2951
|
+
);
|
|
2952
|
+
fieldSchemas[fieldName] = schemaBuilder.buildFieldSchema(model, fieldName).optional();
|
|
2953
|
+
fieldKeys.push(fieldName);
|
|
2954
|
+
}
|
|
2955
|
+
return z8.object(fieldSchemas).strict().refine(
|
|
2956
|
+
(v) => fieldKeys.some((k) => v[k] !== void 0),
|
|
2957
|
+
{ message: `At least one field required in connect/where` }
|
|
2958
|
+
);
|
|
2959
|
+
}
|
|
2960
|
+
function buildNestedDataSchema(model, config, typeMap, schemaBuilder) {
|
|
2961
|
+
const modelFields = typeMap[model];
|
|
2962
|
+
if (!modelFields)
|
|
2963
|
+
throw new ShapeError(`Unknown model: ${model}`);
|
|
2964
|
+
const fieldSchemas = {};
|
|
2965
|
+
for (const [fieldName, value] of Object.entries(config)) {
|
|
2966
|
+
if (value !== true)
|
|
2967
|
+
throw new ShapeError(
|
|
2968
|
+
`Field "${fieldName}" in nested data config must be true`
|
|
2969
|
+
);
|
|
2970
|
+
const meta = modelFields[fieldName];
|
|
2971
|
+
if (!meta)
|
|
2972
|
+
throw new ShapeError(`Unknown field "${fieldName}" on model "${model}"`);
|
|
2973
|
+
if (meta.isRelation)
|
|
2974
|
+
throw new ShapeError(
|
|
2975
|
+
`Nested relation writes inside nested data are not supported ("${model}.${fieldName}")`
|
|
2976
|
+
);
|
|
2977
|
+
if (meta.isUpdatedAt)
|
|
2978
|
+
throw new ShapeError(
|
|
2979
|
+
`updatedAt field "${fieldName}" cannot be used in nested data`
|
|
2980
|
+
);
|
|
2981
|
+
let fieldSchema = schemaBuilder.buildFieldSchema(model, fieldName);
|
|
2982
|
+
if (!meta.isRequired) {
|
|
2983
|
+
fieldSchema = fieldSchema.nullable().optional();
|
|
2984
|
+
} else if (meta.hasDefault) {
|
|
2985
|
+
fieldSchema = fieldSchema.optional();
|
|
2986
|
+
}
|
|
2987
|
+
fieldSchemas[fieldName] = fieldSchema;
|
|
2988
|
+
}
|
|
2989
|
+
return z8.object(fieldSchemas).strict();
|
|
2990
|
+
}
|
|
2991
|
+
function buildRelationWriteSchema(model, fieldName, relatedModelName, isList, config, typeMap, schemaBuilder) {
|
|
2992
|
+
const relatedFields = typeMap[relatedModelName];
|
|
2993
|
+
if (!relatedFields)
|
|
2994
|
+
throw new ShapeError(
|
|
2995
|
+
`Unknown related model "${relatedModelName}" for field "${model}.${fieldName}"`
|
|
2996
|
+
);
|
|
2997
|
+
for (const key of Object.keys(config)) {
|
|
2998
|
+
if (!KNOWN_RELATION_WRITE_OPS.has(key)) {
|
|
2999
|
+
throw new ShapeError(
|
|
3000
|
+
`Unknown relation write operation "${key}" on "${model}.${fieldName}". Allowed: ${[...KNOWN_RELATION_WRITE_OPS].join(", ")}`
|
|
3001
|
+
);
|
|
3002
|
+
}
|
|
3003
|
+
}
|
|
3004
|
+
const opSchemas = {};
|
|
3005
|
+
if (config.connect !== void 0) {
|
|
3006
|
+
if (!isPlainObject(config.connect)) {
|
|
3007
|
+
throw new ShapeError(
|
|
3008
|
+
`connect config on "${model}.${fieldName}" must be an object of field names`
|
|
3009
|
+
);
|
|
3010
|
+
}
|
|
3011
|
+
const connectSchema = buildWhereFieldsSchema(
|
|
3012
|
+
relatedModelName,
|
|
3013
|
+
config.connect,
|
|
3014
|
+
typeMap,
|
|
3015
|
+
schemaBuilder
|
|
3016
|
+
);
|
|
3017
|
+
opSchemas["connect"] = isList ? z8.union([
|
|
3018
|
+
connectSchema,
|
|
3019
|
+
z8.preprocess(coerceToArray, z8.array(connectSchema))
|
|
3020
|
+
]).optional() : connectSchema.optional();
|
|
3021
|
+
}
|
|
3022
|
+
if (config.connectOrCreate !== void 0) {
|
|
3023
|
+
if (!isPlainObject(config.connectOrCreate)) {
|
|
3024
|
+
throw new ShapeError(
|
|
3025
|
+
`connectOrCreate config on "${model}.${fieldName}" must be an object with "where" and "create"`
|
|
3026
|
+
);
|
|
3027
|
+
}
|
|
3028
|
+
const coc = config.connectOrCreate;
|
|
3029
|
+
if (!coc.where || !isPlainObject(coc.where)) {
|
|
3030
|
+
throw new ShapeError(
|
|
3031
|
+
`connectOrCreate on "${model}.${fieldName}" requires "where" object`
|
|
3032
|
+
);
|
|
3033
|
+
}
|
|
3034
|
+
if (!coc.create || !isPlainObject(coc.create)) {
|
|
3035
|
+
throw new ShapeError(
|
|
3036
|
+
`connectOrCreate on "${model}.${fieldName}" requires "create" object`
|
|
3037
|
+
);
|
|
3038
|
+
}
|
|
3039
|
+
const whereSchema = buildWhereFieldsSchema(
|
|
3040
|
+
relatedModelName,
|
|
3041
|
+
coc.where,
|
|
3042
|
+
typeMap,
|
|
3043
|
+
schemaBuilder
|
|
3044
|
+
);
|
|
3045
|
+
const createSchema = buildNestedDataSchema(
|
|
3046
|
+
relatedModelName,
|
|
3047
|
+
coc.create,
|
|
3048
|
+
typeMap,
|
|
3049
|
+
schemaBuilder
|
|
3050
|
+
);
|
|
3051
|
+
const cocSchema = z8.object({ where: whereSchema, create: createSchema }).strict();
|
|
3052
|
+
opSchemas["connectOrCreate"] = isList ? z8.union([cocSchema, z8.preprocess(coerceToArray, z8.array(cocSchema))]).optional() : cocSchema.optional();
|
|
3053
|
+
}
|
|
3054
|
+
if (config.create !== void 0) {
|
|
3055
|
+
if (!isPlainObject(config.create)) {
|
|
3056
|
+
throw new ShapeError(
|
|
3057
|
+
`create config on "${model}.${fieldName}" must be an object of field names`
|
|
3058
|
+
);
|
|
3059
|
+
}
|
|
3060
|
+
const createSchema = buildNestedDataSchema(
|
|
3061
|
+
relatedModelName,
|
|
3062
|
+
config.create,
|
|
3063
|
+
typeMap,
|
|
3064
|
+
schemaBuilder
|
|
3065
|
+
);
|
|
3066
|
+
opSchemas["create"] = isList ? z8.union([
|
|
3067
|
+
createSchema,
|
|
3068
|
+
z8.preprocess(coerceToArray, z8.array(createSchema))
|
|
3069
|
+
]).optional() : createSchema.optional();
|
|
3070
|
+
}
|
|
3071
|
+
if (config.createMany !== void 0) {
|
|
3072
|
+
if (!isList) {
|
|
3073
|
+
throw new ShapeError(
|
|
3074
|
+
`createMany is only valid on to-many relations ("${model}.${fieldName}")`
|
|
3075
|
+
);
|
|
3076
|
+
}
|
|
3077
|
+
if (!isPlainObject(config.createMany)) {
|
|
3078
|
+
throw new ShapeError(
|
|
3079
|
+
`createMany config on "${model}.${fieldName}" must be an object`
|
|
3080
|
+
);
|
|
3081
|
+
}
|
|
3082
|
+
const cmConfig = config.createMany;
|
|
3083
|
+
if (!cmConfig.data || !isPlainObject(cmConfig.data)) {
|
|
3084
|
+
throw new ShapeError(
|
|
3085
|
+
`createMany on "${model}.${fieldName}" requires "data" object`
|
|
3086
|
+
);
|
|
3087
|
+
}
|
|
3088
|
+
const dataSchema = buildNestedDataSchema(
|
|
3089
|
+
relatedModelName,
|
|
3090
|
+
cmConfig.data,
|
|
3091
|
+
typeMap,
|
|
3092
|
+
schemaBuilder
|
|
3093
|
+
);
|
|
3094
|
+
const cmSchemaFields = {
|
|
3095
|
+
data: z8.preprocess(coerceToArray, z8.array(dataSchema))
|
|
3096
|
+
};
|
|
3097
|
+
if ("skipDuplicates" in cmConfig) {
|
|
3098
|
+
cmSchemaFields["skipDuplicates"] = z8.boolean().optional();
|
|
3099
|
+
}
|
|
3100
|
+
opSchemas["createMany"] = z8.object(cmSchemaFields).strict().optional();
|
|
3101
|
+
}
|
|
3102
|
+
if (config.disconnect !== void 0) {
|
|
3103
|
+
if (config.disconnect === true) {
|
|
3104
|
+
if (isList) {
|
|
3105
|
+
throw new ShapeError(
|
|
3106
|
+
`disconnect on to-many relation "${model}.${fieldName}" requires field config, not true`
|
|
3107
|
+
);
|
|
3108
|
+
}
|
|
3109
|
+
opSchemas["disconnect"] = z8.literal(true).optional();
|
|
3110
|
+
} else if (isPlainObject(config.disconnect)) {
|
|
3111
|
+
const disconnectSchema = buildWhereFieldsSchema(
|
|
3112
|
+
relatedModelName,
|
|
3113
|
+
config.disconnect,
|
|
3114
|
+
typeMap,
|
|
3115
|
+
schemaBuilder
|
|
3116
|
+
);
|
|
3117
|
+
if (isList) {
|
|
3118
|
+
opSchemas["disconnect"] = z8.union([
|
|
3119
|
+
disconnectSchema,
|
|
3120
|
+
z8.preprocess(coerceToArray, z8.array(disconnectSchema))
|
|
3121
|
+
]).optional();
|
|
3122
|
+
} else {
|
|
3123
|
+
opSchemas["disconnect"] = z8.union([z8.literal(true), disconnectSchema]).optional();
|
|
3124
|
+
}
|
|
3125
|
+
} else {
|
|
3126
|
+
throw new ShapeError(
|
|
3127
|
+
`disconnect config on "${model}.${fieldName}" must be true (to-one) or an object of field names`
|
|
3128
|
+
);
|
|
3129
|
+
}
|
|
3130
|
+
}
|
|
3131
|
+
if (config.delete !== void 0) {
|
|
3132
|
+
if (config.delete === true) {
|
|
3133
|
+
if (isList) {
|
|
3134
|
+
throw new ShapeError(
|
|
3135
|
+
`delete on to-many relation "${model}.${fieldName}" requires field config, not true`
|
|
3136
|
+
);
|
|
3137
|
+
}
|
|
3138
|
+
opSchemas["delete"] = z8.literal(true).optional();
|
|
3139
|
+
} else if (isPlainObject(config.delete)) {
|
|
3140
|
+
const deleteSchema = buildWhereFieldsSchema(
|
|
3141
|
+
relatedModelName,
|
|
3142
|
+
config.delete,
|
|
3143
|
+
typeMap,
|
|
3144
|
+
schemaBuilder
|
|
3145
|
+
);
|
|
3146
|
+
if (isList) {
|
|
3147
|
+
opSchemas["delete"] = z8.union([
|
|
3148
|
+
deleteSchema,
|
|
3149
|
+
z8.preprocess(coerceToArray, z8.array(deleteSchema))
|
|
3150
|
+
]).optional();
|
|
3151
|
+
} else {
|
|
3152
|
+
opSchemas["delete"] = z8.union([z8.literal(true), deleteSchema]).optional();
|
|
3153
|
+
}
|
|
3154
|
+
} else {
|
|
3155
|
+
throw new ShapeError(
|
|
3156
|
+
`delete config on "${model}.${fieldName}" must be true (to-one) or an object of field names`
|
|
3157
|
+
);
|
|
3158
|
+
}
|
|
3159
|
+
}
|
|
3160
|
+
if (config.delete !== void 0) {
|
|
3161
|
+
if (config.delete === true) {
|
|
3162
|
+
if (isList) {
|
|
3163
|
+
throw new ShapeError(
|
|
3164
|
+
`delete on to-many relation "${model}.${fieldName}" requires field config, not true`
|
|
3165
|
+
);
|
|
3166
|
+
}
|
|
3167
|
+
opSchemas["delete"] = z8.literal(true).optional();
|
|
3168
|
+
} else if (isPlainObject(config.delete)) {
|
|
3169
|
+
const deleteSchema = buildWhereFieldsSchema(
|
|
3170
|
+
relatedModelName,
|
|
3171
|
+
config.delete,
|
|
3172
|
+
typeMap,
|
|
3173
|
+
schemaBuilder
|
|
3174
|
+
);
|
|
3175
|
+
opSchemas["delete"] = isList ? z8.union([
|
|
3176
|
+
deleteSchema,
|
|
3177
|
+
z8.preprocess(coerceToArray, z8.array(deleteSchema))
|
|
3178
|
+
]).optional() : deleteSchema.optional();
|
|
3179
|
+
} else {
|
|
3180
|
+
throw new ShapeError(
|
|
3181
|
+
`delete config on "${model}.${fieldName}" must be true (to-one) or an object of field names`
|
|
3182
|
+
);
|
|
3183
|
+
}
|
|
3184
|
+
}
|
|
3185
|
+
if (config.set !== void 0) {
|
|
3186
|
+
if (!isList) {
|
|
3187
|
+
throw new ShapeError(
|
|
3188
|
+
`set is only valid on to-many relations ("${model}.${fieldName}")`
|
|
3189
|
+
);
|
|
3190
|
+
}
|
|
3191
|
+
if (!isPlainObject(config.set)) {
|
|
3192
|
+
throw new ShapeError(
|
|
3193
|
+
`set config on "${model}.${fieldName}" must be an object of field names`
|
|
3194
|
+
);
|
|
3195
|
+
}
|
|
3196
|
+
const setSchema = buildWhereFieldsSchema(
|
|
3197
|
+
relatedModelName,
|
|
3198
|
+
config.set,
|
|
3199
|
+
typeMap,
|
|
3200
|
+
schemaBuilder
|
|
3201
|
+
);
|
|
3202
|
+
opSchemas["set"] = z8.preprocess(coerceToArray, z8.array(setSchema)).optional();
|
|
3203
|
+
}
|
|
3204
|
+
if (config.update !== void 0) {
|
|
3205
|
+
if (!isPlainObject(config.update)) {
|
|
3206
|
+
throw new ShapeError(
|
|
3207
|
+
`update config on "${model}.${fieldName}" must be an object`
|
|
3208
|
+
);
|
|
3209
|
+
}
|
|
3210
|
+
const updateConfig = config.update;
|
|
3211
|
+
if (isList) {
|
|
3212
|
+
if (!updateConfig.where || !isPlainObject(updateConfig.where)) {
|
|
3213
|
+
throw new ShapeError(
|
|
3214
|
+
`update on to-many "${model}.${fieldName}" requires "where" object`
|
|
3215
|
+
);
|
|
3216
|
+
}
|
|
3217
|
+
if (!updateConfig.data || !isPlainObject(updateConfig.data)) {
|
|
3218
|
+
throw new ShapeError(
|
|
3219
|
+
`update on to-many "${model}.${fieldName}" requires "data" object`
|
|
3220
|
+
);
|
|
3221
|
+
}
|
|
3222
|
+
const whereSchema = buildWhereFieldsSchema(
|
|
3223
|
+
relatedModelName,
|
|
3224
|
+
updateConfig.where,
|
|
3225
|
+
typeMap,
|
|
3226
|
+
schemaBuilder
|
|
3227
|
+
);
|
|
3228
|
+
const dataSchema = buildNestedDataSchema(
|
|
3229
|
+
relatedModelName,
|
|
3230
|
+
updateConfig.data,
|
|
3231
|
+
typeMap,
|
|
3232
|
+
schemaBuilder
|
|
3233
|
+
);
|
|
3234
|
+
const updateSchema = z8.object({ where: whereSchema, data: dataSchema }).strict();
|
|
3235
|
+
opSchemas["update"] = z8.union([
|
|
3236
|
+
updateSchema,
|
|
3237
|
+
z8.preprocess(coerceToArray, z8.array(updateSchema))
|
|
3238
|
+
]).optional();
|
|
3239
|
+
} else {
|
|
3240
|
+
const dataSchema = buildNestedDataSchema(
|
|
3241
|
+
relatedModelName,
|
|
3242
|
+
updateConfig,
|
|
3243
|
+
typeMap,
|
|
3244
|
+
schemaBuilder
|
|
3245
|
+
);
|
|
3246
|
+
opSchemas["update"] = dataSchema.optional();
|
|
3247
|
+
}
|
|
3248
|
+
}
|
|
3249
|
+
if (config.upsert !== void 0) {
|
|
3250
|
+
if (!isPlainObject(config.upsert)) {
|
|
3251
|
+
throw new ShapeError(
|
|
3252
|
+
`upsert config on "${model}.${fieldName}" must be an object`
|
|
3253
|
+
);
|
|
3254
|
+
}
|
|
3255
|
+
const upsertConfig = config.upsert;
|
|
3256
|
+
if (!upsertConfig.create || !isPlainObject(upsertConfig.create)) {
|
|
3257
|
+
throw new ShapeError(
|
|
3258
|
+
`upsert on "${model}.${fieldName}" requires "create" object`
|
|
3259
|
+
);
|
|
3260
|
+
}
|
|
3261
|
+
if (!upsertConfig.update || !isPlainObject(upsertConfig.update)) {
|
|
3262
|
+
throw new ShapeError(
|
|
3263
|
+
`upsert on "${model}.${fieldName}" requires "update" object`
|
|
3264
|
+
);
|
|
3265
|
+
}
|
|
3266
|
+
const createSchema = buildNestedDataSchema(
|
|
3267
|
+
relatedModelName,
|
|
3268
|
+
upsertConfig.create,
|
|
3269
|
+
typeMap,
|
|
3270
|
+
schemaBuilder
|
|
3271
|
+
);
|
|
3272
|
+
const updateSchema = buildNestedDataSchema(
|
|
3273
|
+
relatedModelName,
|
|
3274
|
+
upsertConfig.update,
|
|
3275
|
+
typeMap,
|
|
3276
|
+
schemaBuilder
|
|
3277
|
+
);
|
|
3278
|
+
if (isList) {
|
|
3279
|
+
if (!upsertConfig.where || !isPlainObject(upsertConfig.where)) {
|
|
3280
|
+
throw new ShapeError(
|
|
3281
|
+
`upsert on to-many "${model}.${fieldName}" requires "where" object`
|
|
3282
|
+
);
|
|
3283
|
+
}
|
|
3284
|
+
const whereSchema = buildWhereFieldsSchema(
|
|
3285
|
+
relatedModelName,
|
|
3286
|
+
upsertConfig.where,
|
|
3287
|
+
typeMap,
|
|
3288
|
+
schemaBuilder
|
|
3289
|
+
);
|
|
3290
|
+
const upsertSchema = z8.object({
|
|
3291
|
+
where: whereSchema,
|
|
3292
|
+
create: createSchema,
|
|
3293
|
+
update: updateSchema
|
|
3294
|
+
}).strict();
|
|
3295
|
+
opSchemas["upsert"] = z8.union([
|
|
3296
|
+
upsertSchema,
|
|
3297
|
+
z8.preprocess(coerceToArray, z8.array(upsertSchema))
|
|
3298
|
+
]).optional();
|
|
3299
|
+
} else {
|
|
3300
|
+
if (upsertConfig.where) {
|
|
3301
|
+
const whereSchema = buildWhereFieldsSchema(
|
|
3302
|
+
relatedModelName,
|
|
3303
|
+
upsertConfig.where,
|
|
3304
|
+
typeMap,
|
|
3305
|
+
schemaBuilder
|
|
3306
|
+
);
|
|
3307
|
+
const upsertSchema = z8.object({
|
|
3308
|
+
where: whereSchema,
|
|
3309
|
+
create: createSchema,
|
|
3310
|
+
update: updateSchema
|
|
3311
|
+
}).strict();
|
|
3312
|
+
opSchemas["upsert"] = upsertSchema.optional();
|
|
3313
|
+
} else {
|
|
3314
|
+
const upsertSchema = z8.object({ create: createSchema, update: updateSchema }).strict();
|
|
3315
|
+
opSchemas["upsert"] = upsertSchema.optional();
|
|
3316
|
+
}
|
|
3317
|
+
}
|
|
3318
|
+
}
|
|
3319
|
+
if (config.updateMany !== void 0) {
|
|
3320
|
+
if (!isList) {
|
|
3321
|
+
throw new ShapeError(
|
|
3322
|
+
`updateMany is only valid on to-many relations ("${model}.${fieldName}")`
|
|
3323
|
+
);
|
|
3324
|
+
}
|
|
3325
|
+
if (!isPlainObject(config.updateMany)) {
|
|
3326
|
+
throw new ShapeError(
|
|
3327
|
+
`updateMany config on "${model}.${fieldName}" must be an object`
|
|
3328
|
+
);
|
|
3329
|
+
}
|
|
3330
|
+
const umConfig = config.updateMany;
|
|
3331
|
+
if (!umConfig.where || !isPlainObject(umConfig.where)) {
|
|
3332
|
+
throw new ShapeError(
|
|
3333
|
+
`updateMany on "${model}.${fieldName}" requires "where" object`
|
|
3334
|
+
);
|
|
3335
|
+
}
|
|
3336
|
+
if (!umConfig.data || !isPlainObject(umConfig.data)) {
|
|
3337
|
+
throw new ShapeError(
|
|
3338
|
+
`updateMany on "${model}.${fieldName}" requires "data" object`
|
|
3339
|
+
);
|
|
3340
|
+
}
|
|
3341
|
+
const whereSchema = buildWhereFieldsSchema(
|
|
3342
|
+
relatedModelName,
|
|
3343
|
+
umConfig.where,
|
|
3344
|
+
typeMap,
|
|
3345
|
+
schemaBuilder
|
|
3346
|
+
);
|
|
3347
|
+
const dataSchema = buildNestedDataSchema(
|
|
3348
|
+
relatedModelName,
|
|
3349
|
+
umConfig.data,
|
|
3350
|
+
typeMap,
|
|
3351
|
+
schemaBuilder
|
|
3352
|
+
);
|
|
3353
|
+
const umSchema = z8.object({ where: whereSchema, data: dataSchema }).strict();
|
|
3354
|
+
opSchemas["updateMany"] = z8.union([umSchema, z8.preprocess(coerceToArray, z8.array(umSchema))]).optional();
|
|
3355
|
+
}
|
|
3356
|
+
if (config.deleteMany !== void 0) {
|
|
3357
|
+
if (!isList) {
|
|
3358
|
+
throw new ShapeError(
|
|
3359
|
+
`deleteMany is only valid on to-many relations ("${model}.${fieldName}")`
|
|
3360
|
+
);
|
|
3361
|
+
}
|
|
3362
|
+
if (!isPlainObject(config.deleteMany)) {
|
|
3363
|
+
throw new ShapeError(
|
|
3364
|
+
`deleteMany config on "${model}.${fieldName}" must be an object`
|
|
3365
|
+
);
|
|
3366
|
+
}
|
|
3367
|
+
const dmConfig = config.deleteMany;
|
|
3368
|
+
if (!dmConfig.where || !isPlainObject(dmConfig.where)) {
|
|
3369
|
+
throw new ShapeError(
|
|
3370
|
+
`deleteMany on "${model}.${fieldName}" requires "where" object`
|
|
3371
|
+
);
|
|
3372
|
+
}
|
|
3373
|
+
const whereSchema = buildWhereFieldsSchema(
|
|
3374
|
+
relatedModelName,
|
|
3375
|
+
dmConfig.where,
|
|
3376
|
+
typeMap,
|
|
3377
|
+
schemaBuilder
|
|
3378
|
+
);
|
|
3379
|
+
const dmSchema = z8.object({ where: whereSchema }).strict();
|
|
3380
|
+
opSchemas["deleteMany"] = z8.union([dmSchema, z8.preprocess(coerceToArray, z8.array(dmSchema))]).optional();
|
|
3381
|
+
}
|
|
3382
|
+
return z8.object(opSchemas).strict();
|
|
3383
|
+
}
|
|
2875
3384
|
function buildDataSchema(model, dataConfig, mode, typeMap, schemaBuilder, zodDefaults) {
|
|
2876
3385
|
const modelFields = typeMap[model];
|
|
2877
3386
|
if (!modelFields)
|
|
@@ -2884,12 +3393,32 @@ function buildDataSchema(model, dataConfig, mode, typeMap, schemaBuilder, zodDef
|
|
|
2884
3393
|
const fieldMeta = modelFields[fieldName];
|
|
2885
3394
|
if (!fieldMeta)
|
|
2886
3395
|
throw new ShapeError(`Unknown field "${fieldName}" on model "${model}"`);
|
|
2887
|
-
if (fieldMeta.isRelation)
|
|
2888
|
-
|
|
3396
|
+
if (fieldMeta.isRelation) {
|
|
3397
|
+
if (!isPlainObject(value)) {
|
|
3398
|
+
throw new ShapeError(
|
|
3399
|
+
`Relation field "${fieldName}" on model "${model}" requires a relation write config object`
|
|
3400
|
+
);
|
|
3401
|
+
}
|
|
3402
|
+
schemaMap[fieldName] = buildRelationWriteSchema(
|
|
3403
|
+
model,
|
|
3404
|
+
fieldName,
|
|
3405
|
+
fieldMeta.type,
|
|
3406
|
+
fieldMeta.isList,
|
|
3407
|
+
value,
|
|
3408
|
+
typeMap,
|
|
3409
|
+
schemaBuilder
|
|
3410
|
+
).optional();
|
|
3411
|
+
continue;
|
|
3412
|
+
}
|
|
2889
3413
|
if (fieldMeta.isUpdatedAt)
|
|
2890
|
-
throw new ShapeError(
|
|
3414
|
+
throw new ShapeError(
|
|
3415
|
+
`updatedAt field "${fieldName}" cannot be used in data shape`
|
|
3416
|
+
);
|
|
2891
3417
|
if (typeof value === "function") {
|
|
2892
|
-
let baseSchema = schemaBuilder.buildBaseFieldSchema(
|
|
3418
|
+
let baseSchema = schemaBuilder.buildBaseFieldSchema(
|
|
3419
|
+
model,
|
|
3420
|
+
fieldName
|
|
3421
|
+
);
|
|
2893
3422
|
let refined;
|
|
2894
3423
|
try {
|
|
2895
3424
|
refined = value(baseSchema);
|
|
@@ -2900,7 +3429,9 @@ function buildDataSchema(model, dataConfig, mode, typeMap, schemaBuilder, zodDef
|
|
|
2900
3429
|
);
|
|
2901
3430
|
}
|
|
2902
3431
|
if (!isZodSchema(refined)) {
|
|
2903
|
-
throw new ShapeError(
|
|
3432
|
+
throw new ShapeError(
|
|
3433
|
+
`Inline refine for "${model}.${fieldName}" must return a Zod schema`
|
|
3434
|
+
);
|
|
2904
3435
|
}
|
|
2905
3436
|
let fieldSchema = refined;
|
|
2906
3437
|
const handlesUndefined = schemaProducesValueForUndefined(fieldSchema);
|
|
@@ -2921,7 +3452,10 @@ function buildDataSchema(model, dataConfig, mode, typeMap, schemaBuilder, zodDef
|
|
|
2921
3452
|
}
|
|
2922
3453
|
schemaMap[fieldName] = fieldSchema;
|
|
2923
3454
|
} else if (value === true) {
|
|
2924
|
-
let fieldSchema = schemaBuilder.buildFieldSchema(
|
|
3455
|
+
let fieldSchema = schemaBuilder.buildFieldSchema(
|
|
3456
|
+
model,
|
|
3457
|
+
fieldName
|
|
3458
|
+
);
|
|
2925
3459
|
const isZodDefaultField = zodDefaultSet !== void 0 && zodDefaultSet.has(fieldName);
|
|
2926
3460
|
if (mode === "create") {
|
|
2927
3461
|
if (!fieldMeta.isRequired) {
|
|
@@ -2941,7 +3475,10 @@ function buildDataSchema(model, dataConfig, mode, typeMap, schemaBuilder, zodDef
|
|
|
2941
3475
|
schemaMap[fieldName] = fieldSchema;
|
|
2942
3476
|
} else {
|
|
2943
3477
|
const actualValue = isForcedValue(value) ? value.value : value;
|
|
2944
|
-
let fieldSchema = schemaBuilder.buildFieldSchema(
|
|
3478
|
+
let fieldSchema = schemaBuilder.buildFieldSchema(
|
|
3479
|
+
model,
|
|
3480
|
+
fieldName
|
|
3481
|
+
);
|
|
2945
3482
|
if (!fieldMeta.isRequired) {
|
|
2946
3483
|
fieldSchema = fieldSchema.nullable();
|
|
2947
3484
|
}
|