prisma-guard 1.8.0 → 1.9.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.
@@ -162,7 +162,7 @@ var import_zod3 = require("zod");
162
162
  // src/runtime/zod-type-map.ts
163
163
  var import_zod2 = require("zod");
164
164
  var SCALAR_OPERATORS = {
165
- String: /* @__PURE__ */ new Set(["equals", "not", "contains", "startsWith", "endsWith", "in", "notIn"]),
165
+ String: /* @__PURE__ */ new Set(["equals", "not", "contains", "startsWith", "endsWith", "in", "notIn", "gt", "gte", "lt", "lte"]),
166
166
  Int: /* @__PURE__ */ new Set(["equals", "not", "gt", "gte", "lt", "lte", "in", "notIn"]),
167
167
  Float: /* @__PURE__ */ new Set(["equals", "not", "gt", "gte", "lt", "lte", "in", "notIn"]),
168
168
  Decimal: /* @__PURE__ */ new Set(["equals", "not", "gt", "gte", "lt", "lte", "in", "notIn"]),
@@ -738,6 +738,9 @@ function applyBuiltShape(built, body, isUniqueMethod) {
738
738
  const hasWhereInSchema = "where" in built.zodSchema.shape;
739
739
  if (isPlainObject(body)) {
740
740
  const bodyObj = body;
741
+ if ("select" in bodyObj && "include" in bodyObj) {
742
+ throw new ShapeError('Request cannot define both "include" and "select"');
743
+ }
741
744
  if ("where" in bodyObj) {
742
745
  if (!hasWhereInSchema) {
743
746
  const { where: _, ...rest } = bodyObj;
@@ -1715,6 +1718,7 @@ var KNOWN_NESTED_INCLUDE_KEYS = /* @__PURE__ */ new Set([
1715
1718
  ]);
1716
1719
  var KNOWN_NESTED_SELECT_KEYS = /* @__PURE__ */ new Set([
1717
1720
  "select",
1721
+ "include",
1718
1722
  "where",
1719
1723
  "orderBy",
1720
1724
  "cursor",
@@ -1968,10 +1972,13 @@ function createProjectionBuilder(typeMap, enumMap, deps) {
1968
1972
  KNOWN_NESTED_SELECT_KEYS,
1969
1973
  `nested select for "${fieldName}" on model "${model}"`
1970
1974
  );
1975
+ if (config.select && config.include) {
1976
+ throw new ShapeError(`Nested select for "${fieldName}" cannot define both "select" and "include".`);
1977
+ }
1971
1978
  if (!fieldMeta.isList) {
1972
1979
  if (config.where || config.orderBy || config.cursor || config.take || config.skip) {
1973
1980
  throw new ShapeError(
1974
- `Relation "${fieldName}" on model "${model}" is to-one. Only "select" is supported for to-one nested reads, not where/orderBy/cursor/take/skip.`
1981
+ `Relation "${fieldName}" on model "${model}" is to-one. Only "select" and "include" are supported for to-one nested reads, not where/orderBy/cursor/take/skip.`
1975
1982
  );
1976
1983
  }
1977
1984
  }
@@ -1987,6 +1994,16 @@ function createProjectionBuilder(typeMap, enumMap, deps) {
1987
1994
  relForced._countWherePlacement = "select";
1988
1995
  }
1989
1996
  }
1997
+ if (config.include) {
1998
+ const nested = buildIncludeSchema(fieldMeta.type, config.include, currentDepth + 1);
1999
+ nestedSchemas["include"] = nested.schema;
2000
+ if (Object.keys(nested.forcedTree).length > 0)
2001
+ relForced.include = nested.forcedTree;
2002
+ if (Object.keys(nested.forcedCountWhere).length > 0) {
2003
+ relForced._countWhere = nested.forcedCountWhere;
2004
+ relForced._countWherePlacement = "include";
2005
+ }
2006
+ }
1990
2007
  if (config.where) {
1991
2008
  const { schema: whereSchema, forced } = deps.buildWhereSchema(
1992
2009
  fieldMeta.type,
@@ -2126,11 +2143,6 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
2126
2143
  if (UNIQUE_WHERE_METHODS.has(method) && !shape.where) {
2127
2144
  throw new ShapeError(`${method} shape must define "where"`);
2128
2145
  }
2129
- if (shape.include && shape.select) {
2130
- throw new ShapeError(
2131
- 'Shape config cannot define both "include" and "select".'
2132
- );
2133
- }
2134
2146
  if (method === "groupBy" && !shape.by)
2135
2147
  throw new ShapeError('groupBy shape must define "by"');
2136
2148
  if (method === "groupBy" && (shape.include || shape.select)) {
@@ -3096,6 +3108,8 @@ function buildDefaultSelectInput(config) {
3096
3108
  const nested = {};
3097
3109
  if (value.select)
3098
3110
  nested.select = buildDefaultSelectInput(value.select);
3111
+ if (value.include)
3112
+ nested.include = buildDefaultIncludeInput(value.include);
3099
3113
  result[key] = Object.keys(nested).length > 0 ? nested : true;
3100
3114
  }
3101
3115
  }
@@ -3144,6 +3158,41 @@ function buildDefaultProjectionBody(shape) {
3144
3158
  }
3145
3159
  return {};
3146
3160
  }
3161
+ function applyClientProjectionOverrides(shapeDefault, clientProjection) {
3162
+ const result = { ...shapeDefault };
3163
+ for (const [key, clientValue] of Object.entries(clientProjection)) {
3164
+ const defaultValue = result[key];
3165
+ if (defaultValue === void 0) {
3166
+ result[key] = clientValue;
3167
+ continue;
3168
+ }
3169
+ if (clientValue === true) {
3170
+ result[key] = true;
3171
+ continue;
3172
+ }
3173
+ if (isPlainObject(clientValue)) {
3174
+ if (!isPlainObject(defaultValue)) {
3175
+ result[key] = clientValue;
3176
+ continue;
3177
+ }
3178
+ const merged = { ...defaultValue };
3179
+ const clientObj = clientValue;
3180
+ for (const [argKey, argValue] of Object.entries(clientObj)) {
3181
+ const defaultArgValue = merged[argKey];
3182
+ if ((argKey === "select" || argKey === "include") && isPlainObject(argValue) && isPlainObject(defaultArgValue)) {
3183
+ merged[argKey] = applyClientProjectionOverrides(
3184
+ defaultArgValue,
3185
+ argValue
3186
+ );
3187
+ } else {
3188
+ merged[argKey] = argValue;
3189
+ }
3190
+ }
3191
+ result[key] = merged;
3192
+ }
3193
+ }
3194
+ return result;
3195
+ }
3147
3196
  function hasClientControlledValues(obj) {
3148
3197
  for (const value of Object.values(obj)) {
3149
3198
  if (isForcedValue(value))
@@ -3206,6 +3255,8 @@ function checkSelectForClientArgs(config) {
3206
3255
  return true;
3207
3256
  if (value.select && checkSelectForClientArgs(value.select))
3208
3257
  return true;
3258
+ if (value.include && checkIncludeForClientArgs(value.include))
3259
+ return true;
3209
3260
  }
3210
3261
  return false;
3211
3262
  }
@@ -3341,9 +3392,6 @@ function createModelGuardExtension(config) {
3341
3392
  return queryBuilder.buildWhereSchema(modelName, whereConfig);
3342
3393
  }
3343
3394
  function buildProjectionSchema(shape) {
3344
- if (shape.select && shape.include) {
3345
- throw new ShapeError('Shape cannot define both "select" and "include"');
3346
- }
3347
3395
  const schemaFields = {};
3348
3396
  let forcedIncludeTree = {};
3349
3397
  let forcedSelectTree = {};
@@ -3395,6 +3443,11 @@ function createModelGuardExtension(config) {
3395
3443
  `Guard shape does not define "select" or "include" for ${method} return projection`
3396
3444
  );
3397
3445
  }
3446
+ if ("select" in parsed && "include" in parsed) {
3447
+ throw new ShapeError(
3448
+ 'Request body cannot define both "select" and "include"'
3449
+ );
3450
+ }
3398
3451
  if (!hasShapeProjection)
3399
3452
  return {};
3400
3453
  if (!hasBodyProjection && !enforceProjection)
@@ -3488,6 +3541,29 @@ function createModelGuardExtension(config) {
3488
3541
  }
3489
3542
  return where;
3490
3543
  }
3544
+ function buildEffectiveReadBody(resolved) {
3545
+ const hasShapeProjection = !!resolved.shape.select || !!resolved.shape.include;
3546
+ if (!hasShapeProjection)
3547
+ return resolved.body;
3548
+ const defaultProjection = buildDefaultProjectionBody(resolved.shape);
3549
+ const hasBodyProjection = "select" in resolved.body || "include" in resolved.body;
3550
+ if (!hasBodyProjection) {
3551
+ return { ...resolved.body, ...defaultProjection };
3552
+ }
3553
+ const merged = { ...resolved.body };
3554
+ if ("select" in resolved.body && "select" in defaultProjection && isPlainObject(resolved.body.select) && isPlainObject(defaultProjection.select)) {
3555
+ merged.select = applyClientProjectionOverrides(
3556
+ defaultProjection.select,
3557
+ resolved.body.select
3558
+ );
3559
+ } else if ("include" in resolved.body && "include" in defaultProjection && isPlainObject(resolved.body.include) && isPlainObject(defaultProjection.include)) {
3560
+ merged.include = applyClientProjectionOverrides(
3561
+ defaultProjection.include,
3562
+ resolved.body.include
3563
+ );
3564
+ }
3565
+ return merged;
3566
+ }
3491
3567
  function makeReadMethod(method) {
3492
3568
  return (body) => {
3493
3569
  const caller = resolveCaller();
@@ -3503,17 +3579,7 @@ function createModelGuardExtension(config) {
3503
3579
  resolved.wasDynamic
3504
3580
  );
3505
3581
  const isUnique = UNIQUE_READ_METHODS.has(method);
3506
- let effectiveBody = resolved.body;
3507
- const hasShapeProjection = !!resolved.shape.select || !!resolved.shape.include;
3508
- if (hasShapeProjection) {
3509
- const hasBodyProjection = "select" in resolved.body || "include" in resolved.body;
3510
- if (!hasBodyProjection) {
3511
- effectiveBody = {
3512
- ...resolved.body,
3513
- ...buildDefaultProjectionBody(resolved.shape)
3514
- };
3515
- }
3516
- }
3582
+ const effectiveBody = buildEffectiveReadBody(resolved);
3517
3583
  const args = applyBuiltShape(built, effectiveBody, isUnique);
3518
3584
  if (isUnique && args.where) {
3519
3585
  validateResolvedUniqueWhere(