prisma-guard 1.15.0 → 1.17.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/generator/index.js +7 -13
- package/dist/generator/index.js.map +1 -1
- package/dist/runtime/index.cjs +189 -46
- package/dist/runtime/index.cjs.map +1 -1
- package/dist/runtime/index.js +189 -46
- package/dist/runtime/index.js.map +1 -1
- package/package.json +1 -1
package/dist/runtime/index.js
CHANGED
|
@@ -84,10 +84,7 @@ function isJsonSafe(value) {
|
|
|
84
84
|
return true;
|
|
85
85
|
}
|
|
86
86
|
var DECIMAL_REGEX = /^-?(\d+\.?\d*|\.\d+)([eE]-?\d+)?$/;
|
|
87
|
-
var decimalStringSchema = z.string().refine(
|
|
88
|
-
(s) => DECIMAL_REGEX.test(s),
|
|
89
|
-
"Invalid decimal string"
|
|
90
|
-
);
|
|
87
|
+
var decimalStringSchema = z.string().refine((s) => DECIMAL_REGEX.test(s), "Invalid decimal string");
|
|
91
88
|
var decimalObjectSchema = z.custom(
|
|
92
89
|
(v) => v !== null && typeof v === "object" && typeof v.toFixed === "function" && typeof v.toNumber === "function",
|
|
93
90
|
"Expected Decimal-compatible object"
|
|
@@ -113,18 +110,39 @@ function createScalarBase(strictDecimal) {
|
|
|
113
110
|
z.string().regex(/^-?\d+$/).transform((v) => BigInt(v))
|
|
114
111
|
]),
|
|
115
112
|
Boolean: () => z.boolean(),
|
|
116
|
-
DateTime: () => z.union([
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
Bytes: () => z.union([
|
|
122
|
-
z.string(),
|
|
123
|
-
z.custom((v) => v instanceof Uint8Array)
|
|
124
|
-
])
|
|
113
|
+
DateTime: () => z.union([z.date(), z.string().datetime({ offset: true })]).pipe(z.coerce.date()),
|
|
114
|
+
Json: () => z.unknown().refine(
|
|
115
|
+
isJsonSafe,
|
|
116
|
+
"Value must be JSON-serializable (no undefined, functions, symbols, class instances, NaN, Infinity, or circular references)"
|
|
117
|
+
),
|
|
118
|
+
Bytes: () => z.union([z.string(), z.custom((v) => v instanceof Uint8Array)])
|
|
125
119
|
};
|
|
126
120
|
}
|
|
127
121
|
var SCALAR_BASE = createScalarBase(false);
|
|
122
|
+
function wrapWithInputCoercion(fieldType, isList, schema) {
|
|
123
|
+
let itemCoercion = null;
|
|
124
|
+
switch (fieldType) {
|
|
125
|
+
case "String":
|
|
126
|
+
itemCoercion = z.union([z.string(), z.number().transform(String)]);
|
|
127
|
+
break;
|
|
128
|
+
case "Int":
|
|
129
|
+
itemCoercion = z.union([
|
|
130
|
+
z.number().int(),
|
|
131
|
+
z.string().regex(/^-?\d+$/).transform(Number)
|
|
132
|
+
]);
|
|
133
|
+
break;
|
|
134
|
+
case "Float":
|
|
135
|
+
itemCoercion = z.union([
|
|
136
|
+
z.number(),
|
|
137
|
+
z.string().regex(/^-?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$/).transform(Number)
|
|
138
|
+
]);
|
|
139
|
+
break;
|
|
140
|
+
default:
|
|
141
|
+
return schema;
|
|
142
|
+
}
|
|
143
|
+
const coercion = isList ? z.array(itemCoercion) : itemCoercion;
|
|
144
|
+
return coercion.pipe(schema);
|
|
145
|
+
}
|
|
128
146
|
|
|
129
147
|
// src/runtime/schema-builder.ts
|
|
130
148
|
import { z as z3 } from "zod";
|
|
@@ -173,19 +191,65 @@ function coerceToArray(value) {
|
|
|
173
191
|
|
|
174
192
|
// src/runtime/zod-type-map.ts
|
|
175
193
|
var SCALAR_OPERATORS = {
|
|
176
|
-
String: /* @__PURE__ */ new Set([
|
|
194
|
+
String: /* @__PURE__ */ new Set([
|
|
195
|
+
"equals",
|
|
196
|
+
"not",
|
|
197
|
+
"contains",
|
|
198
|
+
"startsWith",
|
|
199
|
+
"endsWith",
|
|
200
|
+
"in",
|
|
201
|
+
"notIn",
|
|
202
|
+
"gt",
|
|
203
|
+
"gte",
|
|
204
|
+
"lt",
|
|
205
|
+
"lte"
|
|
206
|
+
]),
|
|
177
207
|
Int: /* @__PURE__ */ new Set(["equals", "not", "gt", "gte", "lt", "lte", "in", "notIn"]),
|
|
178
208
|
Float: /* @__PURE__ */ new Set(["equals", "not", "gt", "gte", "lt", "lte", "in", "notIn"]),
|
|
179
209
|
Decimal: /* @__PURE__ */ new Set(["equals", "not", "gt", "gte", "lt", "lte", "in", "notIn"]),
|
|
180
210
|
BigInt: /* @__PURE__ */ new Set(["equals", "not", "gt", "gte", "lt", "lte", "in", "notIn"]),
|
|
181
211
|
Boolean: /* @__PURE__ */ new Set(["equals", "not"]),
|
|
182
212
|
DateTime: /* @__PURE__ */ new Set(["equals", "not", "gt", "gte", "lt", "lte", "in", "notIn"]),
|
|
183
|
-
Bytes: /* @__PURE__ */ new Set([])
|
|
213
|
+
Bytes: /* @__PURE__ */ new Set([]),
|
|
214
|
+
Json: /* @__PURE__ */ new Set([
|
|
215
|
+
"equals",
|
|
216
|
+
"not",
|
|
217
|
+
"path",
|
|
218
|
+
"string_contains",
|
|
219
|
+
"string_starts_with",
|
|
220
|
+
"string_ends_with",
|
|
221
|
+
"array_contains",
|
|
222
|
+
"array_starts_with",
|
|
223
|
+
"array_ends_with"
|
|
224
|
+
])
|
|
184
225
|
};
|
|
185
|
-
var SCALAR_LIST_OPERATORS = /* @__PURE__ */ new Set([
|
|
226
|
+
var SCALAR_LIST_OPERATORS = /* @__PURE__ */ new Set([
|
|
227
|
+
"has",
|
|
228
|
+
"hasEvery",
|
|
229
|
+
"hasSome",
|
|
230
|
+
"isEmpty",
|
|
231
|
+
"equals"
|
|
232
|
+
]);
|
|
186
233
|
var ENUM_OPERATORS = /* @__PURE__ */ new Set(["equals", "not", "in", "notIn"]);
|
|
187
234
|
var NUMERIC_TYPES = /* @__PURE__ */ new Set(["Int", "Float", "Decimal", "BigInt"]);
|
|
188
|
-
var COMPARABLE_TYPES = /* @__PURE__ */ new Set([
|
|
235
|
+
var COMPARABLE_TYPES = /* @__PURE__ */ new Set([
|
|
236
|
+
"Int",
|
|
237
|
+
"Float",
|
|
238
|
+
"Decimal",
|
|
239
|
+
"BigInt",
|
|
240
|
+
"String",
|
|
241
|
+
"DateTime"
|
|
242
|
+
]);
|
|
243
|
+
var JSON_STRING_OPERATORS = /* @__PURE__ */ new Set([
|
|
244
|
+
"string_contains",
|
|
245
|
+
"string_starts_with",
|
|
246
|
+
"string_ends_with"
|
|
247
|
+
]);
|
|
248
|
+
var JSON_ARRAY_OPERATORS = /* @__PURE__ */ new Set([
|
|
249
|
+
"array_contains",
|
|
250
|
+
"array_starts_with",
|
|
251
|
+
"array_ends_with"
|
|
252
|
+
]);
|
|
189
253
|
function getSupportedOperators(fieldMeta) {
|
|
190
254
|
if (fieldMeta.isList)
|
|
191
255
|
return [...SCALAR_LIST_OPERATORS];
|
|
@@ -220,7 +284,9 @@ function createBaseType(fieldMeta, enumMap, scalarBase) {
|
|
|
220
284
|
}
|
|
221
285
|
function createScalarListOperatorSchema(fieldMeta, operator, enumMap, scalarBase) {
|
|
222
286
|
if (!SCALAR_LIST_OPERATORS.has(operator)) {
|
|
223
|
-
throw new ShapeError(
|
|
287
|
+
throw new ShapeError(
|
|
288
|
+
`Operator "${operator}" not supported for scalar list fields`
|
|
289
|
+
);
|
|
224
290
|
}
|
|
225
291
|
if (operator === "isEmpty") {
|
|
226
292
|
return z2.boolean();
|
|
@@ -236,9 +302,32 @@ function createScalarListOperatorSchema(fieldMeta, operator, enumMap, scalarBase
|
|
|
236
302
|
}
|
|
237
303
|
return z2.preprocess(coerceToArray, z2.array(itemBase));
|
|
238
304
|
}
|
|
305
|
+
function createJsonOperatorSchema(fieldMeta, operator) {
|
|
306
|
+
const jsonValue = z2.unknown();
|
|
307
|
+
if (operator === "equals" || operator === "not") {
|
|
308
|
+
return !fieldMeta.isRequired ? z2.union([jsonValue, z2.null()]) : jsonValue;
|
|
309
|
+
}
|
|
310
|
+
if (operator === "path") {
|
|
311
|
+
return z2.preprocess(coerceToArray, z2.array(z2.string()).min(1));
|
|
312
|
+
}
|
|
313
|
+
if (JSON_STRING_OPERATORS.has(operator)) {
|
|
314
|
+
return z2.string();
|
|
315
|
+
}
|
|
316
|
+
if (JSON_ARRAY_OPERATORS.has(operator)) {
|
|
317
|
+
return jsonValue;
|
|
318
|
+
}
|
|
319
|
+
throw new ShapeError(
|
|
320
|
+
`Operator "${operator}" not supported for Json fields`
|
|
321
|
+
);
|
|
322
|
+
}
|
|
239
323
|
function createOperatorSchema(fieldMeta, operator, enumMap, scalarBase) {
|
|
240
324
|
if (fieldMeta.isList) {
|
|
241
|
-
return createScalarListOperatorSchema(
|
|
325
|
+
return createScalarListOperatorSchema(
|
|
326
|
+
fieldMeta,
|
|
327
|
+
operator,
|
|
328
|
+
enumMap,
|
|
329
|
+
scalarBase
|
|
330
|
+
);
|
|
242
331
|
}
|
|
243
332
|
if (fieldMeta.isEnum) {
|
|
244
333
|
const values = enumMap[fieldMeta.type];
|
|
@@ -246,7 +335,9 @@ function createOperatorSchema(fieldMeta, operator, enumMap, scalarBase) {
|
|
|
246
335
|
throw new ShapeError(`Unknown enum: ${fieldMeta.type}`);
|
|
247
336
|
}
|
|
248
337
|
if (!ENUM_OPERATORS.has(operator)) {
|
|
249
|
-
throw new ShapeError(
|
|
338
|
+
throw new ShapeError(
|
|
339
|
+
`Operator "${operator}" not supported for enum fields`
|
|
340
|
+
);
|
|
250
341
|
}
|
|
251
342
|
const enumSchema = z2.enum(values);
|
|
252
343
|
if (operator === "equals" || operator === "not") {
|
|
@@ -255,29 +346,43 @@ function createOperatorSchema(fieldMeta, operator, enumMap, scalarBase) {
|
|
|
255
346
|
const itemSchema = !fieldMeta.isRequired ? z2.union([enumSchema, z2.null()]) : enumSchema;
|
|
256
347
|
return z2.preprocess(coerceToArray, z2.array(itemSchema));
|
|
257
348
|
}
|
|
349
|
+
if (fieldMeta.type === "Json") {
|
|
350
|
+
const supportedOps2 = SCALAR_OPERATORS["Json"];
|
|
351
|
+
if (!supportedOps2 || !supportedOps2.has(operator)) {
|
|
352
|
+
throw new ShapeError(
|
|
353
|
+
`Operator "${operator}" not supported for type "Json"`
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
return createJsonOperatorSchema(fieldMeta, operator);
|
|
357
|
+
}
|
|
258
358
|
const supportedOps = SCALAR_OPERATORS[fieldMeta.type];
|
|
259
359
|
if (!supportedOps) {
|
|
260
360
|
throw new ShapeError(`Unknown scalar type for operator: ${fieldMeta.type}`);
|
|
261
361
|
}
|
|
262
362
|
if (supportedOps.size === 0) {
|
|
263
|
-
throw new ShapeError(
|
|
363
|
+
throw new ShapeError(
|
|
364
|
+
`Type "${fieldMeta.type}" does not support filter operators`
|
|
365
|
+
);
|
|
264
366
|
}
|
|
265
367
|
if (!supportedOps.has(operator)) {
|
|
266
|
-
throw new ShapeError(
|
|
368
|
+
throw new ShapeError(
|
|
369
|
+
`Operator "${operator}" not supported for type "${fieldMeta.type}"`
|
|
370
|
+
);
|
|
267
371
|
}
|
|
268
372
|
const factory = scalarBase[fieldMeta.type];
|
|
269
373
|
if (!factory) {
|
|
270
374
|
throw new ShapeError(`Unknown scalar type: ${fieldMeta.type}`);
|
|
271
375
|
}
|
|
272
376
|
const scalar = factory();
|
|
377
|
+
const coerced = wrapWithInputCoercion(fieldMeta.type, false, scalar);
|
|
273
378
|
if (operator === "equals" || operator === "not") {
|
|
274
|
-
return !fieldMeta.isRequired ? z2.union([
|
|
379
|
+
return !fieldMeta.isRequired ? z2.union([coerced, z2.null()]) : coerced;
|
|
275
380
|
}
|
|
276
381
|
if (operator === "in" || operator === "notIn") {
|
|
277
|
-
const itemSchema = !fieldMeta.isRequired ? z2.union([
|
|
382
|
+
const itemSchema = !fieldMeta.isRequired ? z2.union([coerced, z2.null()]) : coerced;
|
|
278
383
|
return z2.preprocess(coerceToArray, z2.array(itemSchema));
|
|
279
384
|
}
|
|
280
|
-
return
|
|
385
|
+
return coerced;
|
|
281
386
|
}
|
|
282
387
|
|
|
283
388
|
// src/runtime/schema-builder.ts
|
|
@@ -327,6 +432,9 @@ function createSchemaBuilder(typeMap, zodChains, enumMap, scalarBase, zodDefault
|
|
|
327
432
|
);
|
|
328
433
|
}
|
|
329
434
|
}
|
|
435
|
+
if (!fieldMeta.isEnum && !fieldMeta.isRelation && !fieldMeta.isUnsupported) {
|
|
436
|
+
result = wrapWithInputCoercion(fieldMeta.type, fieldMeta.isList, result);
|
|
437
|
+
}
|
|
330
438
|
lruSet(chainCache, cacheKey, result, DEFAULT_MAX_CACHE);
|
|
331
439
|
return result;
|
|
332
440
|
}
|
|
@@ -359,9 +467,13 @@ function createSchemaBuilder(typeMap, zodChains, enumMap, scalarBase, zodDefault
|
|
|
359
467
|
if (!modelFields[name])
|
|
360
468
|
throw new ShapeError(`Unknown field "${name}" on model "${model}"`);
|
|
361
469
|
if (modelFields[name].isRelation)
|
|
362
|
-
throw new ShapeError(
|
|
470
|
+
throw new ShapeError(
|
|
471
|
+
`Field "${name}" cannot be used in input schema (relation field)`
|
|
472
|
+
);
|
|
363
473
|
if (modelFields[name].isUpdatedAt)
|
|
364
|
-
throw new ShapeError(
|
|
474
|
+
throw new ShapeError(
|
|
475
|
+
`Field "${name}" cannot be used in input schema (updatedAt field)`
|
|
476
|
+
);
|
|
365
477
|
}
|
|
366
478
|
fieldNames = fieldNames.filter((n) => opts.pick.includes(n));
|
|
367
479
|
} else if (opts.omit) {
|
|
@@ -435,7 +547,9 @@ function createSchemaBuilder(typeMap, zodChains, enumMap, scalarBase, zodDefault
|
|
|
435
547
|
}
|
|
436
548
|
const effectiveMaxDepth = maxDepth ?? opts.maxDepth ?? DEFAULT_MAX_DEPTH;
|
|
437
549
|
if (depth > effectiveMaxDepth) {
|
|
438
|
-
throw new ShapeError(
|
|
550
|
+
throw new ShapeError(
|
|
551
|
+
`Maximum include depth (${effectiveMaxDepth}) exceeded`
|
|
552
|
+
);
|
|
439
553
|
}
|
|
440
554
|
const modelFields = typeMap[model];
|
|
441
555
|
if (!modelFields)
|
|
@@ -446,7 +560,9 @@ function createSchemaBuilder(typeMap, zodChains, enumMap, scalarBase, zodDefault
|
|
|
446
560
|
if (!modelFields[name])
|
|
447
561
|
throw new ShapeError(`Unknown field "${name}" on model "${model}"`);
|
|
448
562
|
if (modelFields[name].isRelation && !includeKeys.has(name)) {
|
|
449
|
-
throw new ShapeError(
|
|
563
|
+
throw new ShapeError(
|
|
564
|
+
`Field "${name}" is a relation on model "${model}". Use include: { ${name}: ... } instead of pick.`
|
|
565
|
+
);
|
|
450
566
|
}
|
|
451
567
|
}
|
|
452
568
|
}
|
|
@@ -479,10 +595,14 @@ function createSchemaBuilder(typeMap, zodChains, enumMap, scalarBase, zodDefault
|
|
|
479
595
|
if (!fieldMeta)
|
|
480
596
|
throw new ShapeError(`Unknown field "${relName}" on model "${model}"`);
|
|
481
597
|
if (!fieldMeta.isRelation)
|
|
482
|
-
throw new ShapeError(
|
|
598
|
+
throw new ShapeError(
|
|
599
|
+
`Field "${relName}" is not a relation on model "${model}"`
|
|
600
|
+
);
|
|
483
601
|
const relatedModel = fieldMeta.type;
|
|
484
602
|
if (!typeMap[relatedModel]) {
|
|
485
|
-
throw new ShapeError(
|
|
603
|
+
throw new ShapeError(
|
|
604
|
+
`Related model "${relatedModel}" not found in type map`
|
|
605
|
+
);
|
|
486
606
|
}
|
|
487
607
|
let relSchema = buildModelSchema(
|
|
488
608
|
relatedModel,
|
|
@@ -511,11 +631,17 @@ function createSchemaBuilder(typeMap, zodChains, enumMap, scalarBase, zodDefault
|
|
|
511
631
|
const countFields = {};
|
|
512
632
|
for (const relName of Object.keys(opts._count)) {
|
|
513
633
|
if (!modelFields[relName])
|
|
514
|
-
throw new ShapeError(
|
|
634
|
+
throw new ShapeError(
|
|
635
|
+
`Unknown field "${relName}" on model "${model}" in _count`
|
|
636
|
+
);
|
|
515
637
|
if (!modelFields[relName].isRelation)
|
|
516
|
-
throw new ShapeError(
|
|
638
|
+
throw new ShapeError(
|
|
639
|
+
`Field "${relName}" is not a relation on model "${model}" in _count`
|
|
640
|
+
);
|
|
517
641
|
if (!modelFields[relName].isList)
|
|
518
|
-
throw new ShapeError(
|
|
642
|
+
throw new ShapeError(
|
|
643
|
+
`Field "${relName}" is a to-one relation on model "${model}" in _count. Only to-many relations support _count.`
|
|
644
|
+
);
|
|
519
645
|
countFields[relName] = z3.number().int().min(0);
|
|
520
646
|
}
|
|
521
647
|
schemaMap["_count"] = z3.object(countFields);
|
|
@@ -527,7 +653,12 @@ function createSchemaBuilder(typeMap, zodChains, enumMap, scalarBase, zodDefault
|
|
|
527
653
|
}
|
|
528
654
|
return schema;
|
|
529
655
|
}
|
|
530
|
-
return {
|
|
656
|
+
return {
|
|
657
|
+
buildFieldSchema,
|
|
658
|
+
buildBaseFieldSchema,
|
|
659
|
+
buildInputSchema,
|
|
660
|
+
buildModelSchema
|
|
661
|
+
};
|
|
531
662
|
}
|
|
532
663
|
|
|
533
664
|
// src/runtime/query-builder.ts
|
|
@@ -981,13 +1112,18 @@ function validateUniqueEquality(model, where, method, uniqueMap, typeMap) {
|
|
|
981
1112
|
}
|
|
982
1113
|
|
|
983
1114
|
// src/runtime/query-builder-where.ts
|
|
984
|
-
var UNSUPPORTED_WHERE_TYPES = /* @__PURE__ */ new Set(["
|
|
1115
|
+
var UNSUPPORTED_WHERE_TYPES = /* @__PURE__ */ new Set(["Bytes"]);
|
|
985
1116
|
var STRING_MODE_OPS = /* @__PURE__ */ new Set([
|
|
986
1117
|
"contains",
|
|
987
1118
|
"startsWith",
|
|
988
1119
|
"endsWith",
|
|
989
1120
|
"equals"
|
|
990
1121
|
]);
|
|
1122
|
+
var JSON_STRING_MODE_OPS = /* @__PURE__ */ new Set([
|
|
1123
|
+
"string_contains",
|
|
1124
|
+
"string_starts_with",
|
|
1125
|
+
"string_ends_with"
|
|
1126
|
+
]);
|
|
991
1127
|
var MAX_WHERE_DEPTH = 10;
|
|
992
1128
|
function safeStringify(v) {
|
|
993
1129
|
if (typeof v === "bigint")
|
|
@@ -1083,6 +1219,13 @@ function mergeRelationForcedMaps(target, source) {
|
|
|
1083
1219
|
}
|
|
1084
1220
|
}
|
|
1085
1221
|
}
|
|
1222
|
+
function isModeCompatibleOp(fieldType, op) {
|
|
1223
|
+
if (fieldType === "String")
|
|
1224
|
+
return STRING_MODE_OPS.has(op);
|
|
1225
|
+
if (fieldType === "Json")
|
|
1226
|
+
return JSON_STRING_MODE_OPS.has(op);
|
|
1227
|
+
return false;
|
|
1228
|
+
}
|
|
1086
1229
|
function createWhereBuilder(typeMap, enumMap, scalarBase) {
|
|
1087
1230
|
function buildWhereSchema(model, whereConfig, depth) {
|
|
1088
1231
|
const currentDepth = depth ?? 0;
|
|
@@ -1285,7 +1428,7 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
|
|
|
1285
1428
|
const opSchemas = {};
|
|
1286
1429
|
const fieldForced = {};
|
|
1287
1430
|
let hasClientOps = false;
|
|
1288
|
-
let
|
|
1431
|
+
let hasModeCompatibleOp = false;
|
|
1289
1432
|
const clientOpKeys = [];
|
|
1290
1433
|
let modeConfigValue = void 0;
|
|
1291
1434
|
let hasModeConfig = false;
|
|
@@ -1304,8 +1447,8 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
|
|
|
1304
1447
|
).optional();
|
|
1305
1448
|
hasClientOps = true;
|
|
1306
1449
|
clientOpKeys.push(op);
|
|
1307
|
-
if (fieldMeta.
|
|
1308
|
-
|
|
1450
|
+
if (!fieldMeta.isList && isModeCompatibleOp(fieldMeta.type, op)) {
|
|
1451
|
+
hasModeCompatibleOp = true;
|
|
1309
1452
|
}
|
|
1310
1453
|
} else {
|
|
1311
1454
|
const actualOpValue = isForcedValue(opValue) ? opValue.value : opValue;
|
|
@@ -1324,15 +1467,15 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
|
|
|
1324
1467
|
);
|
|
1325
1468
|
}
|
|
1326
1469
|
fieldForced[op] = parsed;
|
|
1327
|
-
if (fieldMeta.
|
|
1328
|
-
|
|
1470
|
+
if (!fieldMeta.isList && isModeCompatibleOp(fieldMeta.type, op)) {
|
|
1471
|
+
hasModeCompatibleOp = true;
|
|
1329
1472
|
}
|
|
1330
1473
|
}
|
|
1331
1474
|
}
|
|
1332
1475
|
if (!hasClientOps && Object.keys(fieldForced).length === 0) {
|
|
1333
1476
|
if (hasModeConfig) {
|
|
1334
1477
|
throw new ShapeError(
|
|
1335
|
-
`Where field "${fieldName}" on model "${model}" has "mode" but no operators. Add at least one operator
|
|
1478
|
+
`Where field "${fieldName}" on model "${model}" has "mode" but no operators. Add at least one compatible operator.`
|
|
1336
1479
|
);
|
|
1337
1480
|
}
|
|
1338
1481
|
throw new ShapeError(
|
|
@@ -1340,9 +1483,9 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
|
|
|
1340
1483
|
);
|
|
1341
1484
|
}
|
|
1342
1485
|
if (hasModeConfig) {
|
|
1343
|
-
if (!
|
|
1486
|
+
if (!hasModeCompatibleOp) {
|
|
1344
1487
|
throw new ShapeError(
|
|
1345
|
-
`"mode" on where field "${fieldName}" on model "${model}" requires a compatible
|
|
1488
|
+
`"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)`
|
|
1346
1489
|
);
|
|
1347
1490
|
}
|
|
1348
1491
|
if (modeConfigValue === true) {
|
|
@@ -1360,7 +1503,7 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
|
|
|
1360
1503
|
}
|
|
1361
1504
|
fieldForced["mode"] = parsed;
|
|
1362
1505
|
}
|
|
1363
|
-
} else if (
|
|
1506
|
+
} else if (hasModeCompatibleOp) {
|
|
1364
1507
|
opSchemas["mode"] = z4.enum(["default", "insensitive"]).optional();
|
|
1365
1508
|
}
|
|
1366
1509
|
if (hasClientOps) {
|
|
@@ -1373,7 +1516,7 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
|
|
|
1373
1516
|
message: `At least one operator required for where field "${fieldName}"`
|
|
1374
1517
|
}
|
|
1375
1518
|
);
|
|
1376
|
-
if ("equals" in opSchemas) {
|
|
1519
|
+
if ("equals" in opSchemas && fieldMeta.type !== "Json") {
|
|
1377
1520
|
const equalsBase = createOperatorSchema(
|
|
1378
1521
|
fieldMeta,
|
|
1379
1522
|
"equals",
|