prisma-guard 1.16.0 → 1.18.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.
@@ -241,7 +241,18 @@ var SCALAR_OPERATORS = {
241
241
  BigInt: /* @__PURE__ */ new Set(["equals", "not", "gt", "gte", "lt", "lte", "in", "notIn"]),
242
242
  Boolean: /* @__PURE__ */ new Set(["equals", "not"]),
243
243
  DateTime: /* @__PURE__ */ new Set(["equals", "not", "gt", "gte", "lt", "lte", "in", "notIn"]),
244
- Bytes: /* @__PURE__ */ new Set([])
244
+ Bytes: /* @__PURE__ */ new Set([]),
245
+ Json: /* @__PURE__ */ new Set([
246
+ "equals",
247
+ "not",
248
+ "path",
249
+ "string_contains",
250
+ "string_starts_with",
251
+ "string_ends_with",
252
+ "array_contains",
253
+ "array_starts_with",
254
+ "array_ends_with"
255
+ ])
245
256
  };
246
257
  var SCALAR_LIST_OPERATORS = /* @__PURE__ */ new Set([
247
258
  "has",
@@ -260,6 +271,16 @@ var COMPARABLE_TYPES = /* @__PURE__ */ new Set([
260
271
  "String",
261
272
  "DateTime"
262
273
  ]);
274
+ var JSON_STRING_OPERATORS = /* @__PURE__ */ new Set([
275
+ "string_contains",
276
+ "string_starts_with",
277
+ "string_ends_with"
278
+ ]);
279
+ var JSON_ARRAY_OPERATORS = /* @__PURE__ */ new Set([
280
+ "array_contains",
281
+ "array_starts_with",
282
+ "array_ends_with"
283
+ ]);
263
284
  function getSupportedOperators(fieldMeta) {
264
285
  if (fieldMeta.isList)
265
286
  return [...SCALAR_LIST_OPERATORS];
@@ -312,6 +333,24 @@ function createScalarListOperatorSchema(fieldMeta, operator, enumMap, scalarBase
312
333
  }
313
334
  return import_zod2.z.preprocess(coerceToArray, import_zod2.z.array(itemBase));
314
335
  }
336
+ function createJsonOperatorSchema(fieldMeta, operator) {
337
+ const jsonValue = import_zod2.z.unknown();
338
+ if (operator === "equals" || operator === "not") {
339
+ return !fieldMeta.isRequired ? import_zod2.z.union([jsonValue, import_zod2.z.null()]) : jsonValue;
340
+ }
341
+ if (operator === "path") {
342
+ return import_zod2.z.preprocess(coerceToArray, import_zod2.z.array(import_zod2.z.string()).min(1));
343
+ }
344
+ if (JSON_STRING_OPERATORS.has(operator)) {
345
+ return import_zod2.z.string();
346
+ }
347
+ if (JSON_ARRAY_OPERATORS.has(operator)) {
348
+ return jsonValue;
349
+ }
350
+ throw new ShapeError(
351
+ `Operator "${operator}" not supported for Json fields`
352
+ );
353
+ }
315
354
  function createOperatorSchema(fieldMeta, operator, enumMap, scalarBase) {
316
355
  if (fieldMeta.isList) {
317
356
  return createScalarListOperatorSchema(
@@ -338,6 +377,15 @@ function createOperatorSchema(fieldMeta, operator, enumMap, scalarBase) {
338
377
  const itemSchema = !fieldMeta.isRequired ? import_zod2.z.union([enumSchema, import_zod2.z.null()]) : enumSchema;
339
378
  return import_zod2.z.preprocess(coerceToArray, import_zod2.z.array(itemSchema));
340
379
  }
380
+ if (fieldMeta.type === "Json") {
381
+ const supportedOps2 = SCALAR_OPERATORS["Json"];
382
+ if (!supportedOps2 || !supportedOps2.has(operator)) {
383
+ throw new ShapeError(
384
+ `Operator "${operator}" not supported for type "Json"`
385
+ );
386
+ }
387
+ return createJsonOperatorSchema(fieldMeta, operator);
388
+ }
341
389
  const supportedOps = SCALAR_OPERATORS[fieldMeta.type];
342
390
  if (!supportedOps) {
343
391
  throw new ShapeError(`Unknown scalar type for operator: ${fieldMeta.type}`);
@@ -1095,13 +1143,18 @@ function validateUniqueEquality(model, where, method, uniqueMap, typeMap) {
1095
1143
  }
1096
1144
 
1097
1145
  // src/runtime/query-builder-where.ts
1098
- var UNSUPPORTED_WHERE_TYPES = /* @__PURE__ */ new Set(["Json", "Bytes"]);
1146
+ var UNSUPPORTED_WHERE_TYPES = /* @__PURE__ */ new Set(["Bytes"]);
1099
1147
  var STRING_MODE_OPS = /* @__PURE__ */ new Set([
1100
1148
  "contains",
1101
1149
  "startsWith",
1102
1150
  "endsWith",
1103
1151
  "equals"
1104
1152
  ]);
1153
+ var JSON_STRING_MODE_OPS = /* @__PURE__ */ new Set([
1154
+ "string_contains",
1155
+ "string_starts_with",
1156
+ "string_ends_with"
1157
+ ]);
1105
1158
  var MAX_WHERE_DEPTH = 10;
1106
1159
  function safeStringify(v) {
1107
1160
  if (typeof v === "bigint")
@@ -1197,6 +1250,13 @@ function mergeRelationForcedMaps(target, source) {
1197
1250
  }
1198
1251
  }
1199
1252
  }
1253
+ function isModeCompatibleOp(fieldType, op) {
1254
+ if (fieldType === "String")
1255
+ return STRING_MODE_OPS.has(op);
1256
+ if (fieldType === "Json")
1257
+ return JSON_STRING_MODE_OPS.has(op);
1258
+ return false;
1259
+ }
1200
1260
  function createWhereBuilder(typeMap, enumMap, scalarBase) {
1201
1261
  function buildWhereSchema(model, whereConfig, depth) {
1202
1262
  const currentDepth = depth ?? 0;
@@ -1399,7 +1459,7 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
1399
1459
  const opSchemas = {};
1400
1460
  const fieldForced = {};
1401
1461
  let hasClientOps = false;
1402
- let hasStringModeOp = false;
1462
+ let hasModeCompatibleOp = false;
1403
1463
  const clientOpKeys = [];
1404
1464
  let modeConfigValue = void 0;
1405
1465
  let hasModeConfig = false;
@@ -1418,8 +1478,8 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
1418
1478
  ).optional();
1419
1479
  hasClientOps = true;
1420
1480
  clientOpKeys.push(op);
1421
- if (fieldMeta.type === "String" && !fieldMeta.isList && STRING_MODE_OPS.has(op)) {
1422
- hasStringModeOp = true;
1481
+ if (!fieldMeta.isList && isModeCompatibleOp(fieldMeta.type, op)) {
1482
+ hasModeCompatibleOp = true;
1423
1483
  }
1424
1484
  } else {
1425
1485
  const actualOpValue = isForcedValue(opValue) ? opValue.value : opValue;
@@ -1438,15 +1498,15 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
1438
1498
  );
1439
1499
  }
1440
1500
  fieldForced[op] = parsed;
1441
- if (fieldMeta.type === "String" && !fieldMeta.isList && STRING_MODE_OPS.has(op)) {
1442
- hasStringModeOp = true;
1501
+ if (!fieldMeta.isList && isModeCompatibleOp(fieldMeta.type, op)) {
1502
+ hasModeCompatibleOp = true;
1443
1503
  }
1444
1504
  }
1445
1505
  }
1446
1506
  if (!hasClientOps && Object.keys(fieldForced).length === 0) {
1447
1507
  if (hasModeConfig) {
1448
1508
  throw new ShapeError(
1449
- `Where field "${fieldName}" on model "${model}" has "mode" but no operators. Add at least one operator (contains, startsWith, endsWith, equals).`
1509
+ `Where field "${fieldName}" on model "${model}" has "mode" but no operators. Add at least one compatible operator.`
1450
1510
  );
1451
1511
  }
1452
1512
  throw new ShapeError(
@@ -1454,9 +1514,9 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
1454
1514
  );
1455
1515
  }
1456
1516
  if (hasModeConfig) {
1457
- if (!hasStringModeOp) {
1517
+ if (!hasModeCompatibleOp) {
1458
1518
  throw new ShapeError(
1459
- `"mode" on where field "${fieldName}" on model "${model}" requires a compatible String operator (contains, startsWith, endsWith, equals)`
1519
+ `"mode" on where field "${fieldName}" on model "${model}" requires a compatible operator (String: contains, startsWith, endsWith, equals; Json: string_contains, string_starts_with, string_ends_with)`
1460
1520
  );
1461
1521
  }
1462
1522
  if (modeConfigValue === true) {
@@ -1474,7 +1534,7 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
1474
1534
  }
1475
1535
  fieldForced["mode"] = parsed;
1476
1536
  }
1477
- } else if (hasStringModeOp) {
1537
+ } else if (hasModeCompatibleOp) {
1478
1538
  opSchemas["mode"] = import_zod4.z.enum(["default", "insensitive"]).optional();
1479
1539
  }
1480
1540
  if (hasClientOps) {
@@ -1487,7 +1547,7 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
1487
1547
  message: `At least one operator required for where field "${fieldName}"`
1488
1548
  }
1489
1549
  );
1490
- if ("equals" in opSchemas) {
1550
+ if ("equals" in opSchemas && fieldMeta.type !== "Json") {
1491
1551
  const equalsBase = createOperatorSchema(
1492
1552
  fieldMeta,
1493
1553
  "equals",
@@ -3734,6 +3794,17 @@ var PROJECTION_MUTATION_METHODS = /* @__PURE__ */ new Set([
3734
3794
  "updateManyAndReturn"
3735
3795
  ]);
3736
3796
  var BATCH_CREATE_METHODS = /* @__PURE__ */ new Set(["createMany", "createManyAndReturn"]);
3797
+ function normalizeUniqueWhere(where) {
3798
+ const result = {};
3799
+ for (const [key, value] of Object.entries(where)) {
3800
+ if (key !== "AND" && key !== "OR" && key !== "NOT" && isPlainObject(value) && "equals" in value && Object.keys(value).length === 1) {
3801
+ result[key] = value.equals;
3802
+ } else {
3803
+ result[key] = value;
3804
+ }
3805
+ }
3806
+ return result;
3807
+ }
3737
3808
  function buildDefaultSelectInput(config) {
3738
3809
  const result = {};
3739
3810
  for (const [key, value] of Object.entries(config)) {
@@ -4343,7 +4414,7 @@ function createModelGuardExtension(config) {
4343
4414
  dataSchema,
4344
4415
  method
4345
4416
  );
4346
- const where = isUniqueWhere ? requireWhere(
4417
+ let where = isUniqueWhere ? requireWhere(
4347
4418
  resolved.shape,
4348
4419
  resolved.body.where,
4349
4420
  method,
@@ -4364,6 +4435,7 @@ function createModelGuardExtension(config) {
4364
4435
  }
4365
4436
  if (isUniqueWhere) {
4366
4437
  validateResolvedUniqueWhere(modelName, where, method, uniqueMap);
4438
+ where = normalizeUniqueWhere(where);
4367
4439
  }
4368
4440
  const args = { data, where };
4369
4441
  if (supportsProjection) {
@@ -4402,7 +4474,7 @@ function createModelGuardExtension(config) {
4402
4474
  );
4403
4475
  }
4404
4476
  maybeValidateUniqueWhere(modelName, resolved.shape, method);
4405
- const where = isUniqueWhere ? requireWhere(
4477
+ let where = isUniqueWhere ? requireWhere(
4406
4478
  resolved.shape,
4407
4479
  resolved.body.where,
4408
4480
  method,
@@ -4423,6 +4495,7 @@ function createModelGuardExtension(config) {
4423
4495
  }
4424
4496
  if (isUniqueWhere) {
4425
4497
  validateResolvedUniqueWhere(modelName, where, method, uniqueMap);
4498
+ where = normalizeUniqueWhere(where);
4426
4499
  }
4427
4500
  const args = { where };
4428
4501
  if (supportsProjection) {
@@ -4507,7 +4580,7 @@ function createModelGuardExtension(config) {
4507
4580
  );
4508
4581
  validateResolvedUniqueWhere(modelName, where, "upsert", uniqueMap);
4509
4582
  const args = {
4510
- where,
4583
+ where: normalizeUniqueWhere(where),
4511
4584
  create: createData,
4512
4585
  update: updateData
4513
4586
  };