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.
@@ -161,8 +161,49 @@ var import_zod3 = require("zod");
161
161
 
162
162
  // src/runtime/zod-type-map.ts
163
163
  var import_zod2 = require("zod");
164
+
165
+ // src/shared/utils.ts
166
+ function isPlainObject(v) {
167
+ if (typeof v !== "object" || v === null || Array.isArray(v))
168
+ return false;
169
+ const proto = Object.getPrototypeOf(v);
170
+ return proto === Object.prototype || proto === null;
171
+ }
172
+ function schemaProducesValueForUndefined(schema) {
173
+ const result = schema.safeParse(void 0);
174
+ return result.success && result.data !== void 0;
175
+ }
176
+ function isZodSchema(value) {
177
+ if (value == null || typeof value !== "object")
178
+ return false;
179
+ const v = value;
180
+ return typeof v.parse === "function" && typeof v.optional === "function";
181
+ }
182
+ function coerceToArray(value) {
183
+ if (Array.isArray(value))
184
+ return value;
185
+ if (value === null || value === void 0)
186
+ return value;
187
+ if (typeof value !== "object")
188
+ return value;
189
+ const keys = Object.keys(value);
190
+ if (keys.length === 0)
191
+ return [];
192
+ const allNumeric = keys.every((k) => /^\d+$/.test(k));
193
+ if (!allNumeric)
194
+ return value;
195
+ const sorted = keys.map(Number).sort((a, b) => a - b);
196
+ const obj = value;
197
+ const result = [];
198
+ for (const idx of sorted) {
199
+ result.push(obj[String(idx)]);
200
+ }
201
+ return result;
202
+ }
203
+
204
+ // src/runtime/zod-type-map.ts
164
205
  var SCALAR_OPERATORS = {
165
- String: /* @__PURE__ */ new Set(["equals", "not", "contains", "startsWith", "endsWith", "in", "notIn"]),
206
+ String: /* @__PURE__ */ new Set(["equals", "not", "contains", "startsWith", "endsWith", "in", "notIn", "gt", "gte", "lt", "lte"]),
166
207
  Int: /* @__PURE__ */ new Set(["equals", "not", "gt", "gte", "lt", "lte", "in", "notIn"]),
167
208
  Float: /* @__PURE__ */ new Set(["equals", "not", "gt", "gte", "lt", "lte", "in", "notIn"]),
168
209
  Decimal: /* @__PURE__ */ new Set(["equals", "not", "gt", "gte", "lt", "lte", "in", "notIn"]),
@@ -212,17 +253,16 @@ function createScalarListOperatorSchema(fieldMeta, operator, enumMap, scalarBase
212
253
  if (operator === "isEmpty") {
213
254
  return import_zod2.z.boolean();
214
255
  }
215
- if (operator === "equals") {
216
- const itemMeta2 = { ...fieldMeta, isList: false };
217
- const itemBase2 = createBaseType(itemMeta2, enumMap, scalarBase);
218
- return fieldMeta.isRequired ? import_zod2.z.array(itemBase2) : import_zod2.z.union([import_zod2.z.array(itemBase2), import_zod2.z.null()]);
219
- }
220
256
  const itemMeta = { ...fieldMeta, isList: false };
221
257
  const itemBase = createBaseType(itemMeta, enumMap, scalarBase);
222
258
  if (operator === "has") {
223
259
  return !fieldMeta.isRequired ? import_zod2.z.union([itemBase, import_zod2.z.null()]) : itemBase;
224
260
  }
225
- return import_zod2.z.array(itemBase);
261
+ if (operator === "equals") {
262
+ const arrSchema = import_zod2.z.array(itemBase);
263
+ return fieldMeta.isRequired ? import_zod2.z.preprocess(coerceToArray, arrSchema) : import_zod2.z.union([import_zod2.z.preprocess(coerceToArray, arrSchema), import_zod2.z.null()]);
264
+ }
265
+ return import_zod2.z.preprocess(coerceToArray, import_zod2.z.array(itemBase));
226
266
  }
227
267
  function createOperatorSchema(fieldMeta, operator, enumMap, scalarBase) {
228
268
  if (fieldMeta.isList) {
@@ -240,10 +280,8 @@ function createOperatorSchema(fieldMeta, operator, enumMap, scalarBase) {
240
280
  if (operator === "equals" || operator === "not") {
241
281
  return !fieldMeta.isRequired ? import_zod2.z.union([enumSchema, import_zod2.z.null()]) : enumSchema;
242
282
  }
243
- if (!fieldMeta.isRequired) {
244
- return import_zod2.z.array(import_zod2.z.union([enumSchema, import_zod2.z.null()]));
245
- }
246
- return import_zod2.z.array(enumSchema);
283
+ const itemSchema = !fieldMeta.isRequired ? import_zod2.z.union([enumSchema, import_zod2.z.null()]) : enumSchema;
284
+ return import_zod2.z.preprocess(coerceToArray, import_zod2.z.array(itemSchema));
247
285
  }
248
286
  const supportedOps = SCALAR_OPERATORS[fieldMeta.type];
249
287
  if (!supportedOps) {
@@ -264,32 +302,12 @@ function createOperatorSchema(fieldMeta, operator, enumMap, scalarBase) {
264
302
  return !fieldMeta.isRequired ? import_zod2.z.union([scalar, import_zod2.z.null()]) : scalar;
265
303
  }
266
304
  if (operator === "in" || operator === "notIn") {
267
- if (!fieldMeta.isRequired) {
268
- return import_zod2.z.array(import_zod2.z.union([scalar, import_zod2.z.null()]));
269
- }
270
- return import_zod2.z.array(scalar);
305
+ const itemSchema = !fieldMeta.isRequired ? import_zod2.z.union([scalar, import_zod2.z.null()]) : scalar;
306
+ return import_zod2.z.preprocess(coerceToArray, import_zod2.z.array(itemSchema));
271
307
  }
272
308
  return scalar;
273
309
  }
274
310
 
275
- // src/shared/utils.ts
276
- function isPlainObject(v) {
277
- if (typeof v !== "object" || v === null || Array.isArray(v))
278
- return false;
279
- const proto = Object.getPrototypeOf(v);
280
- return proto === Object.prototype || proto === null;
281
- }
282
- function schemaProducesValueForUndefined(schema) {
283
- const result = schema.safeParse(void 0);
284
- return result.success && result.data !== void 0;
285
- }
286
- function isZodSchema(value) {
287
- if (value == null || typeof value !== "object")
288
- return false;
289
- const v = value;
290
- return typeof v.parse === "function" && typeof v.optional === "function";
291
- }
292
-
293
311
  // src/runtime/schema-builder.ts
294
312
  var DEFAULT_MAX_CACHE = 500;
295
313
  var DEFAULT_MAX_DEPTH = 5;
@@ -738,6 +756,9 @@ function applyBuiltShape(built, body, isUniqueMethod) {
738
756
  const hasWhereInSchema = "where" in built.zodSchema.shape;
739
757
  if (isPlainObject(body)) {
740
758
  const bodyObj = body;
759
+ if ("select" in bodyObj && "include" in bodyObj) {
760
+ throw new ShapeError('Request cannot define both "include" and "select"');
761
+ }
741
762
  if ("where" in bodyObj) {
742
763
  if (!hasWhereInSchema) {
743
764
  const { where: _, ...rest } = bodyObj;
@@ -1176,9 +1197,12 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
1176
1197
  );
1177
1198
  }
1178
1199
  if (key === "NOT") {
1179
- fieldSchemas[key] = import_zod4.z.union([elementSchema, import_zod4.z.array(elementSchema).min(1)]).optional();
1200
+ fieldSchemas[key] = import_zod4.z.union([
1201
+ elementSchema,
1202
+ import_zod4.z.preprocess(coerceToArray, import_zod4.z.array(elementSchema).min(1))
1203
+ ]).optional();
1180
1204
  } else {
1181
- fieldSchemas[key] = import_zod4.z.array(elementSchema).min(1).optional();
1205
+ fieldSchemas[key] = import_zod4.z.preprocess(coerceToArray, import_zod4.z.array(elementSchema).min(1)).optional();
1182
1206
  }
1183
1207
  }
1184
1208
  if (hasWhereForced(result.forced)) {
@@ -1360,14 +1384,26 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
1360
1384
  }
1361
1385
  if (hasClientOps) {
1362
1386
  const opObj = import_zod4.z.object(opSchemas).strict();
1363
- fieldSchemas[fieldName] = opObj.refine(
1387
+ const refined = opObj.refine(
1364
1388
  (v) => clientOpKeys.some(
1365
1389
  (k) => v[k] !== void 0
1366
1390
  ),
1367
1391
  {
1368
1392
  message: `At least one operator required for where field "${fieldName}"`
1369
1393
  }
1370
- ).optional();
1394
+ );
1395
+ if ("equals" in opSchemas) {
1396
+ const equalsBase = createOperatorSchema(
1397
+ fieldMeta,
1398
+ "equals",
1399
+ enumMap,
1400
+ scalarBase
1401
+ );
1402
+ const shorthand = equalsBase.transform((v) => ({ equals: v }));
1403
+ fieldSchemas[fieldName] = import_zod4.z.union([refined, shorthand]).optional();
1404
+ } else {
1405
+ fieldSchemas[fieldName] = refined.optional();
1406
+ }
1371
1407
  }
1372
1408
  if (Object.keys(fieldForced).length > 0) {
1373
1409
  scalarConditions[fieldName] = fieldForced;
@@ -1469,7 +1505,7 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
1469
1505
  (v) => fieldKeys.some((k) => v[k] !== void 0),
1470
1506
  { message: "orderBy must specify at least one field" }
1471
1507
  );
1472
- return import_zod5.z.union([singleSchema, import_zod5.z.array(singleSchema).min(1)]).optional();
1508
+ return import_zod5.z.union([singleSchema, import_zod5.z.preprocess(coerceToArray, import_zod5.z.array(singleSchema).min(1))]).optional();
1473
1509
  }
1474
1510
  function buildTakeSchema(config) {
1475
1511
  if (!Number.isFinite(config.max) || !Number.isInteger(config.max)) {
@@ -1540,7 +1576,7 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
1540
1576
  throw new ShapeError(`List field "${fieldName}" cannot be used in distinct`);
1541
1577
  }
1542
1578
  const enumSchema = import_zod5.z.enum(distinctConfig);
1543
- return import_zod5.z.union([enumSchema, import_zod5.z.array(enumSchema).min(1)]).optional();
1579
+ return import_zod5.z.union([enumSchema, import_zod5.z.preprocess(coerceToArray, import_zod5.z.array(enumSchema).min(1))]).optional();
1544
1580
  }
1545
1581
  function buildBySchema(model, byConfig) {
1546
1582
  if (byConfig.length === 0) {
@@ -1562,7 +1598,7 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
1562
1598
  throw new ShapeError(`List field "${fieldName}" cannot be used in by`);
1563
1599
  }
1564
1600
  const enumSchema = import_zod5.z.enum(byConfig);
1565
- return import_zod5.z.union([enumSchema, import_zod5.z.array(enumSchema).min(1)]);
1601
+ return import_zod5.z.union([enumSchema, import_zod5.z.preprocess(coerceToArray, import_zod5.z.array(enumSchema).min(1))]);
1566
1602
  }
1567
1603
  function buildHavingSchema(model, havingConfig) {
1568
1604
  const modelFields = typeMap[model];
@@ -2140,11 +2176,6 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2140
2176
  if (UNIQUE_WHERE_METHODS.has(method) && !shape.where) {
2141
2177
  throw new ShapeError(`${method} shape must define "where"`);
2142
2178
  }
2143
- if (shape.include && shape.select) {
2144
- throw new ShapeError(
2145
- 'Shape config cannot define both "include" and "select".'
2146
- );
2147
- }
2148
2179
  if (method === "groupBy" && !shape.by)
2149
2180
  throw new ShapeError('groupBy shape must define "by"');
2150
2181
  if (method === "groupBy" && (shape.include || shape.select)) {
@@ -2254,7 +2285,7 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2254
2285
  ),
2255
2286
  { message: "orderBy must specify at least one field" }
2256
2287
  );
2257
- schemaFields["orderBy"] = import_zod7.z.union([singleSchema, import_zod7.z.array(singleSchema).min(1)]).optional();
2288
+ schemaFields["orderBy"] = import_zod7.z.union([singleSchema, import_zod7.z.preprocess(coerceToArray, import_zod7.z.array(singleSchema).min(1))]).optional();
2258
2289
  } else {
2259
2290
  const groupByOrderFields = {};
2260
2291
  for (const [fieldName, config] of Object.entries(shape.orderBy)) {
@@ -2297,7 +2328,7 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2297
2328
  ),
2298
2329
  { message: "orderBy must specify at least one field" }
2299
2330
  );
2300
- schemaFields["orderBy"] = import_zod7.z.union([singleSchema, import_zod7.z.array(singleSchema).min(1)]).optional();
2331
+ schemaFields["orderBy"] = import_zod7.z.union([singleSchema, import_zod7.z.preprocess(coerceToArray, import_zod7.z.array(singleSchema).min(1))]).optional();
2301
2332
  }
2302
2333
  } else {
2303
2334
  schemaFields["orderBy"] = argsBuilder.buildOrderBySchema(
@@ -3394,9 +3425,6 @@ function createModelGuardExtension(config) {
3394
3425
  return queryBuilder.buildWhereSchema(modelName, whereConfig);
3395
3426
  }
3396
3427
  function buildProjectionSchema(shape) {
3397
- if (shape.select && shape.include) {
3398
- throw new ShapeError('Shape cannot define both "select" and "include"');
3399
- }
3400
3428
  const schemaFields = {};
3401
3429
  let forcedIncludeTree = {};
3402
3430
  let forcedSelectTree = {};
@@ -3448,6 +3476,11 @@ function createModelGuardExtension(config) {
3448
3476
  `Guard shape does not define "select" or "include" for ${method} return projection`
3449
3477
  );
3450
3478
  }
3479
+ if ("select" in parsed && "include" in parsed) {
3480
+ throw new ShapeError(
3481
+ 'Request body cannot define both "select" and "include"'
3482
+ );
3483
+ }
3451
3484
  if (!hasShapeProjection)
3452
3485
  return {};
3453
3486
  if (!hasBodyProjection && !enforceProjection)
@@ -3946,7 +3979,9 @@ function createModelGuardExtension(config) {
3946
3979
 
3947
3980
  // src/runtime/guard.ts
3948
3981
  function createGuard(config) {
3949
- const scalarBase = createScalarBase(config.guardConfig.strictDecimal ?? false);
3982
+ const scalarBase = createScalarBase(
3983
+ config.guardConfig.strictDecimal ?? false
3984
+ );
3950
3985
  const schemaBuilder = createSchemaBuilder(
3951
3986
  config.typeMap,
3952
3987
  config.zodChains,
@@ -3960,11 +3995,15 @@ function createGuard(config) {
3960
3995
  config.uniqueMap ?? {},
3961
3996
  scalarBase
3962
3997
  );
3963
- const log = config.logger ?? { warn: (msg) => console.warn(msg) };
3998
+ const log = config.logger ?? {
3999
+ warn: (msg) => console.warn(msg)
4000
+ };
3964
4001
  const wrapZodErrors = config.wrapZodErrors ?? false;
3965
4002
  function rethrowZod(err) {
3966
4003
  if (err instanceof import_zod10.ZodError) {
3967
- throw new ShapeError(`Validation failed: ${formatZodError(err)}`, { cause: err });
4004
+ throw new ShapeError(`Validation failed: ${formatZodError(err)}`, {
4005
+ cause: err
4006
+ });
3968
4007
  }
3969
4008
  throw err;
3970
4009
  }
@@ -4001,6 +4040,7 @@ function createGuard(config) {
4001
4040
  };
4002
4041
  },
4003
4042
  extension: (contextFn) => {
4043
+ const effectiveContextFn = contextFn ?? (() => ({}));
4004
4044
  const scopeRoots = /* @__PURE__ */ new Set();
4005
4045
  for (const entries of Object.values(config.scopeMap)) {
4006
4046
  for (const entry of entries) {
@@ -4008,7 +4048,7 @@ function createGuard(config) {
4008
4048
  }
4009
4049
  }
4010
4050
  const scopeCtxFn = () => {
4011
- const ctx = validateContext(contextFn());
4051
+ const ctx = validateContext(effectiveContextFn());
4012
4052
  const scopeCtx = {};
4013
4053
  for (const key of Object.keys(ctx)) {
4014
4054
  if (!scopeRoots.has(key))
@@ -4038,7 +4078,7 @@ function createGuard(config) {
4038
4078
  uniqueMap: config.uniqueMap ?? {},
4039
4079
  scopeMap: config.scopeMap,
4040
4080
  guardConfig: config.guardConfig,
4041
- contextFn,
4081
+ contextFn: effectiveContextFn,
4042
4082
  wrapZodErrors
4043
4083
  });
4044
4084
  return {