prisma-guard 1.4.1 → 1.5.1

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.
@@ -735,18 +735,23 @@ function mergeUniqueWhereForced(where, forced) {
735
735
  }
736
736
  function applyBuiltShape(built, body, isUniqueMethod) {
737
737
  let parseable = body;
738
- if (built.forcedOnlyWhereKeys.size > 0 && isPlainObject(body)) {
738
+ if (isPlainObject(body)) {
739
739
  const bodyObj = body;
740
740
  if (isPlainObject(bodyObj.where)) {
741
741
  const where = { ...bodyObj.where };
742
- let stripped = false;
743
- for (const key of built.forcedOnlyWhereKeys) {
744
- if (key in where) {
745
- delete where[key];
746
- stripped = true;
742
+ let modified = false;
743
+ if (built.forcedOnlyWhereKeys.size > 0) {
744
+ for (const key of built.forcedOnlyWhereKeys) {
745
+ if (key in where) {
746
+ delete where[key];
747
+ modified = true;
748
+ }
747
749
  }
748
750
  }
749
- if (stripped) {
751
+ if (Object.keys(where).length === 0 && hasWhereForced(built.forcedWhere)) {
752
+ const { where: _, ...rest } = bodyObj;
753
+ parseable = rest;
754
+ } else if (modified) {
750
755
  parseable = { ...bodyObj, where };
751
756
  }
752
757
  }
@@ -1277,7 +1282,14 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
1277
1282
  let hasClientOps = false;
1278
1283
  let hasStringModeOp = false;
1279
1284
  const clientOpKeys = [];
1285
+ let modeConfigValue = void 0;
1286
+ let hasModeConfig = false;
1280
1287
  for (const [op, opValue] of Object.entries(operators)) {
1288
+ if (op === "mode") {
1289
+ hasModeConfig = true;
1290
+ modeConfigValue = opValue;
1291
+ continue;
1292
+ }
1281
1293
  if (opValue === true) {
1282
1294
  opSchemas[op] = createOperatorSchema(
1283
1295
  fieldMeta,
@@ -1307,14 +1319,43 @@ function createWhereBuilder(typeMap, enumMap, scalarBase) {
1307
1319
  );
1308
1320
  }
1309
1321
  fieldForced[op] = parsed;
1322
+ if (fieldMeta.type === "String" && !fieldMeta.isList && STRING_MODE_OPS.has(op)) {
1323
+ hasStringModeOp = true;
1324
+ }
1310
1325
  }
1311
1326
  }
1312
1327
  if (!hasClientOps && Object.keys(fieldForced).length === 0) {
1328
+ if (hasModeConfig) {
1329
+ throw new ShapeError(
1330
+ `Where field "${fieldName}" on model "${model}" has "mode" but no operators. Add at least one operator (contains, startsWith, endsWith, equals).`
1331
+ );
1332
+ }
1313
1333
  throw new ShapeError(
1314
1334
  `Empty operator config for where field "${fieldName}" on model "${model}". Define at least one operator.`
1315
1335
  );
1316
1336
  }
1317
- if (hasStringModeOp) {
1337
+ if (hasModeConfig) {
1338
+ if (!hasStringModeOp) {
1339
+ throw new ShapeError(
1340
+ `"mode" on where field "${fieldName}" on model "${model}" requires a compatible String operator (contains, startsWith, endsWith, equals)`
1341
+ );
1342
+ }
1343
+ if (modeConfigValue === true) {
1344
+ opSchemas["mode"] = import_zod4.z.enum(["default", "insensitive"]).optional();
1345
+ } else {
1346
+ const actualModeValue = isForcedValue(modeConfigValue) ? modeConfigValue.value : modeConfigValue;
1347
+ const modeSchema = import_zod4.z.enum(["default", "insensitive"]);
1348
+ let parsed;
1349
+ try {
1350
+ parsed = modeSchema.parse(actualModeValue);
1351
+ } catch (err) {
1352
+ throw new ShapeError(
1353
+ `Invalid forced value for "${model}.${fieldName}.mode": ${err.message}`
1354
+ );
1355
+ }
1356
+ fieldForced["mode"] = parsed;
1357
+ }
1358
+ } else if (hasStringModeOp) {
1318
1359
  opSchemas["mode"] = import_zod4.z.enum(["default", "insensitive"]).optional();
1319
1360
  }
1320
1361
  if (hasClientOps) {
@@ -2100,9 +2141,11 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2100
2141
  }
2101
2142
  if (method === "count" && shape.include)
2102
2143
  throw new ShapeError('count does not support "include"');
2103
- if (method === "groupBy" && shape.orderBy) {
2144
+ if (method === "groupBy" && shape.orderBy && shape.orderBy !== true) {
2104
2145
  const bySet = new Set(shape.by);
2105
2146
  for (const fieldName of Object.keys(shape.orderBy)) {
2147
+ if (fieldName === "_count")
2148
+ continue;
2106
2149
  if (!bySet.has(fieldName)) {
2107
2150
  throw new ShapeError(
2108
2151
  `orderBy field "${fieldName}" must be included in "by" for groupBy`
@@ -2180,11 +2223,29 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2180
2223
  forcedSelectCountWhere = result.forcedCountWhere;
2181
2224
  }
2182
2225
  }
2183
- if (shape.orderBy)
2184
- schemaFields["orderBy"] = argsBuilder.buildOrderBySchema(
2185
- model,
2186
- shape.orderBy
2187
- );
2226
+ if (shape.orderBy) {
2227
+ if (method === "groupBy" && shape.orderBy === true && shape.by) {
2228
+ const sortEnum = import_zod7.z.enum(["asc", "desc"]);
2229
+ const groupByOrderFields = {};
2230
+ for (const field of shape.by) {
2231
+ groupByOrderFields[field] = sortEnum.optional();
2232
+ }
2233
+ groupByOrderFields["_count"] = sortEnum.optional();
2234
+ const fieldKeys = Object.keys(groupByOrderFields);
2235
+ const singleSchema = import_zod7.z.object(groupByOrderFields).strict().refine(
2236
+ (v) => fieldKeys.some(
2237
+ (k) => v[k] !== void 0
2238
+ ),
2239
+ { message: "orderBy must specify at least one field" }
2240
+ );
2241
+ schemaFields["orderBy"] = import_zod7.z.union([singleSchema, import_zod7.z.array(singleSchema).min(1)]).optional();
2242
+ } else {
2243
+ schemaFields["orderBy"] = argsBuilder.buildOrderBySchema(
2244
+ model,
2245
+ shape.orderBy
2246
+ );
2247
+ }
2248
+ }
2188
2249
  if (shape.cursor)
2189
2250
  schemaFields["cursor"] = argsBuilder.buildCursorSchema(
2190
2251
  model,