prisma-guard 1.9.0 → 1.10.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.d.cts
CHANGED
|
@@ -158,7 +158,7 @@ declare function createGuard<TModels extends TypeMap = TypeMap, TRoots extends s
|
|
|
158
158
|
input: (model: Extract<keyof TModels, string>, opts: InputOpts) => InputSchema;
|
|
159
159
|
model: (model: Extract<keyof TModels, string>, opts: ModelOpts) => zod.ZodObject<any, zod_v4_core.$strip>;
|
|
160
160
|
query: <TCtx = unknown>(model: Extract<keyof TModels, string>, method: QueryMethod, config_: ShapeOrFn<TCtx> | Record<string, ShapeOrFn<TCtx>>) => QuerySchema<TCtx>;
|
|
161
|
-
extension: <TCtx extends Record<string, unknown> = Record<string, unknown>>(contextFn
|
|
161
|
+
extension: <TCtx extends Record<string, unknown> = Record<string, unknown>>(contextFn?: () => TCtx) => {
|
|
162
162
|
name: string;
|
|
163
163
|
model: TModelExt;
|
|
164
164
|
query: {
|
package/dist/runtime/index.d.ts
CHANGED
|
@@ -158,7 +158,7 @@ declare function createGuard<TModels extends TypeMap = TypeMap, TRoots extends s
|
|
|
158
158
|
input: (model: Extract<keyof TModels, string>, opts: InputOpts) => InputSchema;
|
|
159
159
|
model: (model: Extract<keyof TModels, string>, opts: ModelOpts) => zod.ZodObject<any, zod_v4_core.$strip>;
|
|
160
160
|
query: <TCtx = unknown>(model: Extract<keyof TModels, string>, method: QueryMethod, config_: ShapeOrFn<TCtx> | Record<string, ShapeOrFn<TCtx>>) => QuerySchema<TCtx>;
|
|
161
|
-
extension: <TCtx extends Record<string, unknown> = Record<string, unknown>>(contextFn
|
|
161
|
+
extension: <TCtx extends Record<string, unknown> = Record<string, unknown>>(contextFn?: () => TCtx) => {
|
|
162
162
|
name: string;
|
|
163
163
|
model: TModelExt;
|
|
164
164
|
query: {
|
package/dist/runtime/index.js
CHANGED
|
@@ -131,8 +131,49 @@ import { z as z3 } from "zod";
|
|
|
131
131
|
|
|
132
132
|
// src/runtime/zod-type-map.ts
|
|
133
133
|
import { z as z2 } from "zod";
|
|
134
|
+
|
|
135
|
+
// src/shared/utils.ts
|
|
136
|
+
function isPlainObject(v) {
|
|
137
|
+
if (typeof v !== "object" || v === null || Array.isArray(v))
|
|
138
|
+
return false;
|
|
139
|
+
const proto = Object.getPrototypeOf(v);
|
|
140
|
+
return proto === Object.prototype || proto === null;
|
|
141
|
+
}
|
|
142
|
+
function schemaProducesValueForUndefined(schema) {
|
|
143
|
+
const result = schema.safeParse(void 0);
|
|
144
|
+
return result.success && result.data !== void 0;
|
|
145
|
+
}
|
|
146
|
+
function isZodSchema(value) {
|
|
147
|
+
if (value == null || typeof value !== "object")
|
|
148
|
+
return false;
|
|
149
|
+
const v = value;
|
|
150
|
+
return typeof v.parse === "function" && typeof v.optional === "function";
|
|
151
|
+
}
|
|
152
|
+
function coerceToArray(value) {
|
|
153
|
+
if (Array.isArray(value))
|
|
154
|
+
return value;
|
|
155
|
+
if (value === null || value === void 0)
|
|
156
|
+
return value;
|
|
157
|
+
if (typeof value !== "object")
|
|
158
|
+
return value;
|
|
159
|
+
const keys = Object.keys(value);
|
|
160
|
+
if (keys.length === 0)
|
|
161
|
+
return [];
|
|
162
|
+
const allNumeric = keys.every((k) => /^\d+$/.test(k));
|
|
163
|
+
if (!allNumeric)
|
|
164
|
+
return value;
|
|
165
|
+
const sorted = keys.map(Number).sort((a, b) => a - b);
|
|
166
|
+
const obj = value;
|
|
167
|
+
const result = [];
|
|
168
|
+
for (const idx of sorted) {
|
|
169
|
+
result.push(obj[String(idx)]);
|
|
170
|
+
}
|
|
171
|
+
return result;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// src/runtime/zod-type-map.ts
|
|
134
175
|
var SCALAR_OPERATORS = {
|
|
135
|
-
String: /* @__PURE__ */ new Set(["equals", "not", "contains", "startsWith", "endsWith", "in", "notIn"]),
|
|
176
|
+
String: /* @__PURE__ */ new Set(["equals", "not", "contains", "startsWith", "endsWith", "in", "notIn", "gt", "gte", "lt", "lte"]),
|
|
136
177
|
Int: /* @__PURE__ */ new Set(["equals", "not", "gt", "gte", "lt", "lte", "in", "notIn"]),
|
|
137
178
|
Float: /* @__PURE__ */ new Set(["equals", "not", "gt", "gte", "lt", "lte", "in", "notIn"]),
|
|
138
179
|
Decimal: /* @__PURE__ */ new Set(["equals", "not", "gt", "gte", "lt", "lte", "in", "notIn"]),
|
|
@@ -182,17 +223,16 @@ function createScalarListOperatorSchema(fieldMeta, operator, enumMap, scalarBase
|
|
|
182
223
|
if (operator === "isEmpty") {
|
|
183
224
|
return z2.boolean();
|
|
184
225
|
}
|
|
185
|
-
if (operator === "equals") {
|
|
186
|
-
const itemMeta2 = { ...fieldMeta, isList: false };
|
|
187
|
-
const itemBase2 = createBaseType(itemMeta2, enumMap, scalarBase);
|
|
188
|
-
return fieldMeta.isRequired ? z2.array(itemBase2) : z2.union([z2.array(itemBase2), z2.null()]);
|
|
189
|
-
}
|
|
190
226
|
const itemMeta = { ...fieldMeta, isList: false };
|
|
191
227
|
const itemBase = createBaseType(itemMeta, enumMap, scalarBase);
|
|
192
228
|
if (operator === "has") {
|
|
193
229
|
return !fieldMeta.isRequired ? z2.union([itemBase, z2.null()]) : itemBase;
|
|
194
230
|
}
|
|
195
|
-
|
|
231
|
+
if (operator === "equals") {
|
|
232
|
+
const arrSchema = z2.array(itemBase);
|
|
233
|
+
return fieldMeta.isRequired ? z2.preprocess(coerceToArray, arrSchema) : z2.union([z2.preprocess(coerceToArray, arrSchema), z2.null()]);
|
|
234
|
+
}
|
|
235
|
+
return z2.preprocess(coerceToArray, z2.array(itemBase));
|
|
196
236
|
}
|
|
197
237
|
function createOperatorSchema(fieldMeta, operator, enumMap, scalarBase) {
|
|
198
238
|
if (fieldMeta.isList) {
|
|
@@ -210,10 +250,8 @@ function createOperatorSchema(fieldMeta, operator, enumMap, scalarBase) {
|
|
|
210
250
|
if (operator === "equals" || operator === "not") {
|
|
211
251
|
return !fieldMeta.isRequired ? z2.union([enumSchema, z2.null()]) : enumSchema;
|
|
212
252
|
}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
}
|
|
216
|
-
return z2.array(enumSchema);
|
|
253
|
+
const itemSchema = !fieldMeta.isRequired ? z2.union([enumSchema, z2.null()]) : enumSchema;
|
|
254
|
+
return z2.preprocess(coerceToArray, z2.array(itemSchema));
|
|
217
255
|
}
|
|
218
256
|
const supportedOps = SCALAR_OPERATORS[fieldMeta.type];
|
|
219
257
|
if (!supportedOps) {
|
|
@@ -234,32 +272,12 @@ function createOperatorSchema(fieldMeta, operator, enumMap, scalarBase) {
|
|
|
234
272
|
return !fieldMeta.isRequired ? z2.union([scalar, z2.null()]) : scalar;
|
|
235
273
|
}
|
|
236
274
|
if (operator === "in" || operator === "notIn") {
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
}
|
|
240
|
-
return z2.array(scalar);
|
|
275
|
+
const itemSchema = !fieldMeta.isRequired ? z2.union([scalar, z2.null()]) : scalar;
|
|
276
|
+
return z2.preprocess(coerceToArray, z2.array(itemSchema));
|
|
241
277
|
}
|
|
242
278
|
return scalar;
|
|
243
279
|
}
|
|
244
280
|
|
|
245
|
-
// src/shared/utils.ts
|
|
246
|
-
function isPlainObject(v) {
|
|
247
|
-
if (typeof v !== "object" || v === null || Array.isArray(v))
|
|
248
|
-
return false;
|
|
249
|
-
const proto = Object.getPrototypeOf(v);
|
|
250
|
-
return proto === Object.prototype || proto === null;
|
|
251
|
-
}
|
|
252
|
-
function schemaProducesValueForUndefined(schema) {
|
|
253
|
-
const result = schema.safeParse(void 0);
|
|
254
|
-
return result.success && result.data !== void 0;
|
|
255
|
-
}
|
|
256
|
-
function isZodSchema(value) {
|
|
257
|
-
if (value == null || typeof value !== "object")
|
|
258
|
-
return false;
|
|
259
|
-
const v = value;
|
|
260
|
-
return typeof v.parse === "function" && typeof v.optional === "function";
|
|
261
|
-
}
|
|
262
|
-
|
|
263
281
|
// src/runtime/schema-builder.ts
|
|
264
282
|
var DEFAULT_MAX_CACHE = 500;
|
|
265
283
|
var DEFAULT_MAX_DEPTH = 5;
|
|
@@ -708,6 +726,9 @@ function applyBuiltShape(built, body, isUniqueMethod) {
|
|
|
708
726
|
const hasWhereInSchema = "where" in built.zodSchema.shape;
|
|
709
727
|
if (isPlainObject(body)) {
|
|
710
728
|
const bodyObj = body;
|
|
729
|
+
if ("select" in bodyObj && "include" in bodyObj) {
|
|
730
|
+
throw new ShapeError('Request cannot define both "include" and "select"');
|
|
731
|
+
}
|
|
711
732
|
if ("where" in bodyObj) {
|
|
712
733
|
if (!hasWhereInSchema) {
|
|
713
734
|
const { where: _, ...rest } = bodyObj;
|
|
@@ -1146,9 +1167,12 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
|
|
|
1146
1167
|
);
|
|
1147
1168
|
}
|
|
1148
1169
|
if (key === "NOT") {
|
|
1149
|
-
fieldSchemas[key] = z4.union([
|
|
1170
|
+
fieldSchemas[key] = z4.union([
|
|
1171
|
+
elementSchema,
|
|
1172
|
+
z4.preprocess(coerceToArray, z4.array(elementSchema).min(1))
|
|
1173
|
+
]).optional();
|
|
1150
1174
|
} else {
|
|
1151
|
-
fieldSchemas[key] = z4.array(elementSchema).min(1).optional();
|
|
1175
|
+
fieldSchemas[key] = z4.preprocess(coerceToArray, z4.array(elementSchema).min(1)).optional();
|
|
1152
1176
|
}
|
|
1153
1177
|
}
|
|
1154
1178
|
if (hasWhereForced(result.forced)) {
|
|
@@ -1330,14 +1354,26 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
|
|
|
1330
1354
|
}
|
|
1331
1355
|
if (hasClientOps) {
|
|
1332
1356
|
const opObj = z4.object(opSchemas).strict();
|
|
1333
|
-
|
|
1357
|
+
const refined = opObj.refine(
|
|
1334
1358
|
(v) => clientOpKeys.some(
|
|
1335
1359
|
(k) => v[k] !== void 0
|
|
1336
1360
|
),
|
|
1337
1361
|
{
|
|
1338
1362
|
message: `At least one operator required for where field "${fieldName}"`
|
|
1339
1363
|
}
|
|
1340
|
-
)
|
|
1364
|
+
);
|
|
1365
|
+
if ("equals" in opSchemas) {
|
|
1366
|
+
const equalsBase = createOperatorSchema(
|
|
1367
|
+
fieldMeta,
|
|
1368
|
+
"equals",
|
|
1369
|
+
enumMap,
|
|
1370
|
+
scalarBase
|
|
1371
|
+
);
|
|
1372
|
+
const shorthand = equalsBase.transform((v) => ({ equals: v }));
|
|
1373
|
+
fieldSchemas[fieldName] = z4.union([refined, shorthand]).optional();
|
|
1374
|
+
} else {
|
|
1375
|
+
fieldSchemas[fieldName] = refined.optional();
|
|
1376
|
+
}
|
|
1341
1377
|
}
|
|
1342
1378
|
if (Object.keys(fieldForced).length > 0) {
|
|
1343
1379
|
scalarConditions[fieldName] = fieldForced;
|
|
@@ -1439,7 +1475,7 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
1439
1475
|
(v) => fieldKeys.some((k) => v[k] !== void 0),
|
|
1440
1476
|
{ message: "orderBy must specify at least one field" }
|
|
1441
1477
|
);
|
|
1442
|
-
return z5.union([singleSchema, z5.array(singleSchema).min(1)]).optional();
|
|
1478
|
+
return z5.union([singleSchema, z5.preprocess(coerceToArray, z5.array(singleSchema).min(1))]).optional();
|
|
1443
1479
|
}
|
|
1444
1480
|
function buildTakeSchema(config) {
|
|
1445
1481
|
if (!Number.isFinite(config.max) || !Number.isInteger(config.max)) {
|
|
@@ -1510,7 +1546,7 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
1510
1546
|
throw new ShapeError(`List field "${fieldName}" cannot be used in distinct`);
|
|
1511
1547
|
}
|
|
1512
1548
|
const enumSchema = z5.enum(distinctConfig);
|
|
1513
|
-
return z5.union([enumSchema, z5.array(enumSchema).min(1)]).optional();
|
|
1549
|
+
return z5.union([enumSchema, z5.preprocess(coerceToArray, z5.array(enumSchema).min(1))]).optional();
|
|
1514
1550
|
}
|
|
1515
1551
|
function buildBySchema(model, byConfig) {
|
|
1516
1552
|
if (byConfig.length === 0) {
|
|
@@ -1532,7 +1568,7 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
1532
1568
|
throw new ShapeError(`List field "${fieldName}" cannot be used in by`);
|
|
1533
1569
|
}
|
|
1534
1570
|
const enumSchema = z5.enum(byConfig);
|
|
1535
|
-
return z5.union([enumSchema, z5.array(enumSchema).min(1)]);
|
|
1571
|
+
return z5.union([enumSchema, z5.preprocess(coerceToArray, z5.array(enumSchema).min(1))]);
|
|
1536
1572
|
}
|
|
1537
1573
|
function buildHavingSchema(model, havingConfig) {
|
|
1538
1574
|
const modelFields = typeMap[model];
|
|
@@ -2110,11 +2146,6 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
2110
2146
|
if (UNIQUE_WHERE_METHODS.has(method) && !shape.where) {
|
|
2111
2147
|
throw new ShapeError(`${method} shape must define "where"`);
|
|
2112
2148
|
}
|
|
2113
|
-
if (shape.include && shape.select) {
|
|
2114
|
-
throw new ShapeError(
|
|
2115
|
-
'Shape config cannot define both "include" and "select".'
|
|
2116
|
-
);
|
|
2117
|
-
}
|
|
2118
2149
|
if (method === "groupBy" && !shape.by)
|
|
2119
2150
|
throw new ShapeError('groupBy shape must define "by"');
|
|
2120
2151
|
if (method === "groupBy" && (shape.include || shape.select)) {
|
|
@@ -2224,7 +2255,7 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
2224
2255
|
),
|
|
2225
2256
|
{ message: "orderBy must specify at least one field" }
|
|
2226
2257
|
);
|
|
2227
|
-
schemaFields["orderBy"] = z7.union([singleSchema, z7.array(singleSchema).min(1)]).optional();
|
|
2258
|
+
schemaFields["orderBy"] = z7.union([singleSchema, z7.preprocess(coerceToArray, z7.array(singleSchema).min(1))]).optional();
|
|
2228
2259
|
} else {
|
|
2229
2260
|
const groupByOrderFields = {};
|
|
2230
2261
|
for (const [fieldName, config] of Object.entries(shape.orderBy)) {
|
|
@@ -2267,7 +2298,7 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
2267
2298
|
),
|
|
2268
2299
|
{ message: "orderBy must specify at least one field" }
|
|
2269
2300
|
);
|
|
2270
|
-
schemaFields["orderBy"] = z7.union([singleSchema, z7.array(singleSchema).min(1)]).optional();
|
|
2301
|
+
schemaFields["orderBy"] = z7.union([singleSchema, z7.preprocess(coerceToArray, z7.array(singleSchema).min(1))]).optional();
|
|
2271
2302
|
}
|
|
2272
2303
|
} else {
|
|
2273
2304
|
schemaFields["orderBy"] = argsBuilder.buildOrderBySchema(
|
|
@@ -3364,9 +3395,6 @@ function createModelGuardExtension(config) {
|
|
|
3364
3395
|
return queryBuilder.buildWhereSchema(modelName, whereConfig);
|
|
3365
3396
|
}
|
|
3366
3397
|
function buildProjectionSchema(shape) {
|
|
3367
|
-
if (shape.select && shape.include) {
|
|
3368
|
-
throw new ShapeError('Shape cannot define both "select" and "include"');
|
|
3369
|
-
}
|
|
3370
3398
|
const schemaFields = {};
|
|
3371
3399
|
let forcedIncludeTree = {};
|
|
3372
3400
|
let forcedSelectTree = {};
|
|
@@ -3418,6 +3446,11 @@ function createModelGuardExtension(config) {
|
|
|
3418
3446
|
`Guard shape does not define "select" or "include" for ${method} return projection`
|
|
3419
3447
|
);
|
|
3420
3448
|
}
|
|
3449
|
+
if ("select" in parsed && "include" in parsed) {
|
|
3450
|
+
throw new ShapeError(
|
|
3451
|
+
'Request body cannot define both "select" and "include"'
|
|
3452
|
+
);
|
|
3453
|
+
}
|
|
3421
3454
|
if (!hasShapeProjection)
|
|
3422
3455
|
return {};
|
|
3423
3456
|
if (!hasBodyProjection && !enforceProjection)
|
|
@@ -3916,7 +3949,9 @@ function createModelGuardExtension(config) {
|
|
|
3916
3949
|
|
|
3917
3950
|
// src/runtime/guard.ts
|
|
3918
3951
|
function createGuard(config) {
|
|
3919
|
-
const scalarBase = createScalarBase(
|
|
3952
|
+
const scalarBase = createScalarBase(
|
|
3953
|
+
config.guardConfig.strictDecimal ?? false
|
|
3954
|
+
);
|
|
3920
3955
|
const schemaBuilder = createSchemaBuilder(
|
|
3921
3956
|
config.typeMap,
|
|
3922
3957
|
config.zodChains,
|
|
@@ -3930,11 +3965,15 @@ function createGuard(config) {
|
|
|
3930
3965
|
config.uniqueMap ?? {},
|
|
3931
3966
|
scalarBase
|
|
3932
3967
|
);
|
|
3933
|
-
const log = config.logger ?? {
|
|
3968
|
+
const log = config.logger ?? {
|
|
3969
|
+
warn: (msg) => console.warn(msg)
|
|
3970
|
+
};
|
|
3934
3971
|
const wrapZodErrors = config.wrapZodErrors ?? false;
|
|
3935
3972
|
function rethrowZod(err) {
|
|
3936
3973
|
if (err instanceof ZodError) {
|
|
3937
|
-
throw new ShapeError(`Validation failed: ${formatZodError(err)}`, {
|
|
3974
|
+
throw new ShapeError(`Validation failed: ${formatZodError(err)}`, {
|
|
3975
|
+
cause: err
|
|
3976
|
+
});
|
|
3938
3977
|
}
|
|
3939
3978
|
throw err;
|
|
3940
3979
|
}
|
|
@@ -3971,6 +4010,7 @@ function createGuard(config) {
|
|
|
3971
4010
|
};
|
|
3972
4011
|
},
|
|
3973
4012
|
extension: (contextFn) => {
|
|
4013
|
+
const effectiveContextFn = contextFn ?? (() => ({}));
|
|
3974
4014
|
const scopeRoots = /* @__PURE__ */ new Set();
|
|
3975
4015
|
for (const entries of Object.values(config.scopeMap)) {
|
|
3976
4016
|
for (const entry of entries) {
|
|
@@ -3978,7 +4018,7 @@ function createGuard(config) {
|
|
|
3978
4018
|
}
|
|
3979
4019
|
}
|
|
3980
4020
|
const scopeCtxFn = () => {
|
|
3981
|
-
const ctx = validateContext(
|
|
4021
|
+
const ctx = validateContext(effectiveContextFn());
|
|
3982
4022
|
const scopeCtx = {};
|
|
3983
4023
|
for (const key of Object.keys(ctx)) {
|
|
3984
4024
|
if (!scopeRoots.has(key))
|
|
@@ -4008,7 +4048,7 @@ function createGuard(config) {
|
|
|
4008
4048
|
uniqueMap: config.uniqueMap ?? {},
|
|
4009
4049
|
scopeMap: config.scopeMap,
|
|
4010
4050
|
guardConfig: config.guardConfig,
|
|
4011
|
-
contextFn,
|
|
4051
|
+
contextFn: effectiveContextFn,
|
|
4012
4052
|
wrapZodErrors
|
|
4013
4053
|
});
|
|
4014
4054
|
return {
|