prisma-guard 1.9.1 → 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.
@@ -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: () => TCtx) => {
161
+ extension: <TCtx extends Record<string, unknown> = Record<string, unknown>>(contextFn?: () => TCtx) => {
162
162
  name: string;
163
163
  model: TModelExt;
164
164
  query: {
@@ -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: () => TCtx) => {
161
+ extension: <TCtx extends Record<string, unknown> = Record<string, unknown>>(contextFn?: () => TCtx) => {
162
162
  name: string;
163
163
  model: TModelExt;
164
164
  query: {
@@ -131,6 +131,47 @@ 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
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"]),
@@ -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
- return z2.array(itemBase);
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
- if (!fieldMeta.isRequired) {
214
- return z2.array(z2.union([enumSchema, z2.null()]));
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
- if (!fieldMeta.isRequired) {
238
- return z2.array(z2.union([scalar, z2.null()]));
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;
@@ -1149,9 +1167,12 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
1149
1167
  );
1150
1168
  }
1151
1169
  if (key === "NOT") {
1152
- fieldSchemas[key] = z4.union([elementSchema, z4.array(elementSchema).min(1)]).optional();
1170
+ fieldSchemas[key] = z4.union([
1171
+ elementSchema,
1172
+ z4.preprocess(coerceToArray, z4.array(elementSchema).min(1))
1173
+ ]).optional();
1153
1174
  } else {
1154
- fieldSchemas[key] = z4.array(elementSchema).min(1).optional();
1175
+ fieldSchemas[key] = z4.preprocess(coerceToArray, z4.array(elementSchema).min(1)).optional();
1155
1176
  }
1156
1177
  }
1157
1178
  if (hasWhereForced(result.forced)) {
@@ -1333,14 +1354,26 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
1333
1354
  }
1334
1355
  if (hasClientOps) {
1335
1356
  const opObj = z4.object(opSchemas).strict();
1336
- fieldSchemas[fieldName] = opObj.refine(
1357
+ const refined = opObj.refine(
1337
1358
  (v) => clientOpKeys.some(
1338
1359
  (k) => v[k] !== void 0
1339
1360
  ),
1340
1361
  {
1341
1362
  message: `At least one operator required for where field "${fieldName}"`
1342
1363
  }
1343
- ).optional();
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
+ }
1344
1377
  }
1345
1378
  if (Object.keys(fieldForced).length > 0) {
1346
1379
  scalarConditions[fieldName] = fieldForced;
@@ -1442,7 +1475,7 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
1442
1475
  (v) => fieldKeys.some((k) => v[k] !== void 0),
1443
1476
  { message: "orderBy must specify at least one field" }
1444
1477
  );
1445
- return z5.union([singleSchema, z5.array(singleSchema).min(1)]).optional();
1478
+ return z5.union([singleSchema, z5.preprocess(coerceToArray, z5.array(singleSchema).min(1))]).optional();
1446
1479
  }
1447
1480
  function buildTakeSchema(config) {
1448
1481
  if (!Number.isFinite(config.max) || !Number.isInteger(config.max)) {
@@ -1513,7 +1546,7 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
1513
1546
  throw new ShapeError(`List field "${fieldName}" cannot be used in distinct`);
1514
1547
  }
1515
1548
  const enumSchema = z5.enum(distinctConfig);
1516
- return z5.union([enumSchema, z5.array(enumSchema).min(1)]).optional();
1549
+ return z5.union([enumSchema, z5.preprocess(coerceToArray, z5.array(enumSchema).min(1))]).optional();
1517
1550
  }
1518
1551
  function buildBySchema(model, byConfig) {
1519
1552
  if (byConfig.length === 0) {
@@ -1535,7 +1568,7 @@ function createArgsBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
1535
1568
  throw new ShapeError(`List field "${fieldName}" cannot be used in by`);
1536
1569
  }
1537
1570
  const enumSchema = z5.enum(byConfig);
1538
- return z5.union([enumSchema, z5.array(enumSchema).min(1)]);
1571
+ return z5.union([enumSchema, z5.preprocess(coerceToArray, z5.array(enumSchema).min(1))]);
1539
1572
  }
1540
1573
  function buildHavingSchema(model, havingConfig) {
1541
1574
  const modelFields = typeMap[model];
@@ -2222,7 +2255,7 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2222
2255
  ),
2223
2256
  { message: "orderBy must specify at least one field" }
2224
2257
  );
2225
- 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();
2226
2259
  } else {
2227
2260
  const groupByOrderFields = {};
2228
2261
  for (const [fieldName, config] of Object.entries(shape.orderBy)) {
@@ -2265,7 +2298,7 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2265
2298
  ),
2266
2299
  { message: "orderBy must specify at least one field" }
2267
2300
  );
2268
- 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();
2269
2302
  }
2270
2303
  } else {
2271
2304
  schemaFields["orderBy"] = argsBuilder.buildOrderBySchema(
@@ -3916,7 +3949,9 @@ function createModelGuardExtension(config) {
3916
3949
 
3917
3950
  // src/runtime/guard.ts
3918
3951
  function createGuard(config) {
3919
- const scalarBase = createScalarBase(config.guardConfig.strictDecimal ?? false);
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 ?? { warn: (msg) => console.warn(msg) };
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)}`, { cause: 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(contextFn());
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 {