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.
package/dist/runtime/index.d.cts
CHANGED
|
@@ -84,6 +84,7 @@ interface NestedIncludeArgs {
|
|
|
84
84
|
}
|
|
85
85
|
interface NestedSelectArgs {
|
|
86
86
|
select?: Record<string, true | NestedSelectArgs>;
|
|
87
|
+
include?: Record<string, true | NestedIncludeArgs>;
|
|
87
88
|
where?: Record<string, unknown>;
|
|
88
89
|
orderBy?: Record<string, OrderByFieldConfig>;
|
|
89
90
|
cursor?: Record<string, true>;
|
package/dist/runtime/index.d.ts
CHANGED
|
@@ -84,6 +84,7 @@ interface NestedIncludeArgs {
|
|
|
84
84
|
}
|
|
85
85
|
interface NestedSelectArgs {
|
|
86
86
|
select?: Record<string, true | NestedSelectArgs>;
|
|
87
|
+
include?: Record<string, true | NestedIncludeArgs>;
|
|
87
88
|
where?: Record<string, unknown>;
|
|
88
89
|
orderBy?: Record<string, OrderByFieldConfig>;
|
|
89
90
|
cursor?: Record<string, true>;
|
package/dist/runtime/index.js
CHANGED
|
@@ -132,7 +132,7 @@ import { z as z3 } from "zod";
|
|
|
132
132
|
// src/runtime/zod-type-map.ts
|
|
133
133
|
import { z as z2 } from "zod";
|
|
134
134
|
var SCALAR_OPERATORS = {
|
|
135
|
-
String: /* @__PURE__ */ new Set(["equals", "not", "contains", "startsWith", "endsWith", "in", "notIn"]),
|
|
135
|
+
String: /* @__PURE__ */ new Set(["equals", "not", "contains", "startsWith", "endsWith", "in", "notIn", "gt", "gte", "lt", "lte"]),
|
|
136
136
|
Int: /* @__PURE__ */ new Set(["equals", "not", "gt", "gte", "lt", "lte", "in", "notIn"]),
|
|
137
137
|
Float: /* @__PURE__ */ new Set(["equals", "not", "gt", "gte", "lt", "lte", "in", "notIn"]),
|
|
138
138
|
Decimal: /* @__PURE__ */ new Set(["equals", "not", "gt", "gte", "lt", "lte", "in", "notIn"]),
|
|
@@ -708,6 +708,9 @@ function applyBuiltShape(built, body, isUniqueMethod) {
|
|
|
708
708
|
const hasWhereInSchema = "where" in built.zodSchema.shape;
|
|
709
709
|
if (isPlainObject(body)) {
|
|
710
710
|
const bodyObj = body;
|
|
711
|
+
if ("select" in bodyObj && "include" in bodyObj) {
|
|
712
|
+
throw new ShapeError('Request cannot define both "include" and "select"');
|
|
713
|
+
}
|
|
711
714
|
if ("where" in bodyObj) {
|
|
712
715
|
if (!hasWhereInSchema) {
|
|
713
716
|
const { where: _, ...rest } = bodyObj;
|
|
@@ -1685,6 +1688,7 @@ var KNOWN_NESTED_INCLUDE_KEYS = /* @__PURE__ */ new Set([
|
|
|
1685
1688
|
]);
|
|
1686
1689
|
var KNOWN_NESTED_SELECT_KEYS = /* @__PURE__ */ new Set([
|
|
1687
1690
|
"select",
|
|
1691
|
+
"include",
|
|
1688
1692
|
"where",
|
|
1689
1693
|
"orderBy",
|
|
1690
1694
|
"cursor",
|
|
@@ -1938,10 +1942,13 @@ function createProjectionBuilder(typeMap, enumMap, deps) {
|
|
|
1938
1942
|
KNOWN_NESTED_SELECT_KEYS,
|
|
1939
1943
|
`nested select for "${fieldName}" on model "${model}"`
|
|
1940
1944
|
);
|
|
1945
|
+
if (config.select && config.include) {
|
|
1946
|
+
throw new ShapeError(`Nested select for "${fieldName}" cannot define both "select" and "include".`);
|
|
1947
|
+
}
|
|
1941
1948
|
if (!fieldMeta.isList) {
|
|
1942
1949
|
if (config.where || config.orderBy || config.cursor || config.take || config.skip) {
|
|
1943
1950
|
throw new ShapeError(
|
|
1944
|
-
`Relation "${fieldName}" on model "${model}" is to-one. Only "select"
|
|
1951
|
+
`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.`
|
|
1945
1952
|
);
|
|
1946
1953
|
}
|
|
1947
1954
|
}
|
|
@@ -1957,6 +1964,16 @@ function createProjectionBuilder(typeMap, enumMap, deps) {
|
|
|
1957
1964
|
relForced._countWherePlacement = "select";
|
|
1958
1965
|
}
|
|
1959
1966
|
}
|
|
1967
|
+
if (config.include) {
|
|
1968
|
+
const nested = buildIncludeSchema(fieldMeta.type, config.include, currentDepth + 1);
|
|
1969
|
+
nestedSchemas["include"] = nested.schema;
|
|
1970
|
+
if (Object.keys(nested.forcedTree).length > 0)
|
|
1971
|
+
relForced.include = nested.forcedTree;
|
|
1972
|
+
if (Object.keys(nested.forcedCountWhere).length > 0) {
|
|
1973
|
+
relForced._countWhere = nested.forcedCountWhere;
|
|
1974
|
+
relForced._countWherePlacement = "include";
|
|
1975
|
+
}
|
|
1976
|
+
}
|
|
1960
1977
|
if (config.where) {
|
|
1961
1978
|
const { schema: whereSchema, forced } = deps.buildWhereSchema(
|
|
1962
1979
|
fieldMeta.type,
|
|
@@ -2096,11 +2113,6 @@ function createQueryBuilder(typeMap, enumMap, uniqueMap, scalarBase) {
|
|
|
2096
2113
|
if (UNIQUE_WHERE_METHODS.has(method) && !shape.where) {
|
|
2097
2114
|
throw new ShapeError(`${method} shape must define "where"`);
|
|
2098
2115
|
}
|
|
2099
|
-
if (shape.include && shape.select) {
|
|
2100
|
-
throw new ShapeError(
|
|
2101
|
-
'Shape config cannot define both "include" and "select".'
|
|
2102
|
-
);
|
|
2103
|
-
}
|
|
2104
2116
|
if (method === "groupBy" && !shape.by)
|
|
2105
2117
|
throw new ShapeError('groupBy shape must define "by"');
|
|
2106
2118
|
if (method === "groupBy" && (shape.include || shape.select)) {
|
|
@@ -3066,6 +3078,8 @@ function buildDefaultSelectInput(config) {
|
|
|
3066
3078
|
const nested = {};
|
|
3067
3079
|
if (value.select)
|
|
3068
3080
|
nested.select = buildDefaultSelectInput(value.select);
|
|
3081
|
+
if (value.include)
|
|
3082
|
+
nested.include = buildDefaultIncludeInput(value.include);
|
|
3069
3083
|
result[key] = Object.keys(nested).length > 0 ? nested : true;
|
|
3070
3084
|
}
|
|
3071
3085
|
}
|
|
@@ -3114,6 +3128,41 @@ function buildDefaultProjectionBody(shape) {
|
|
|
3114
3128
|
}
|
|
3115
3129
|
return {};
|
|
3116
3130
|
}
|
|
3131
|
+
function applyClientProjectionOverrides(shapeDefault, clientProjection) {
|
|
3132
|
+
const result = { ...shapeDefault };
|
|
3133
|
+
for (const [key, clientValue] of Object.entries(clientProjection)) {
|
|
3134
|
+
const defaultValue = result[key];
|
|
3135
|
+
if (defaultValue === void 0) {
|
|
3136
|
+
result[key] = clientValue;
|
|
3137
|
+
continue;
|
|
3138
|
+
}
|
|
3139
|
+
if (clientValue === true) {
|
|
3140
|
+
result[key] = true;
|
|
3141
|
+
continue;
|
|
3142
|
+
}
|
|
3143
|
+
if (isPlainObject(clientValue)) {
|
|
3144
|
+
if (!isPlainObject(defaultValue)) {
|
|
3145
|
+
result[key] = clientValue;
|
|
3146
|
+
continue;
|
|
3147
|
+
}
|
|
3148
|
+
const merged = { ...defaultValue };
|
|
3149
|
+
const clientObj = clientValue;
|
|
3150
|
+
for (const [argKey, argValue] of Object.entries(clientObj)) {
|
|
3151
|
+
const defaultArgValue = merged[argKey];
|
|
3152
|
+
if ((argKey === "select" || argKey === "include") && isPlainObject(argValue) && isPlainObject(defaultArgValue)) {
|
|
3153
|
+
merged[argKey] = applyClientProjectionOverrides(
|
|
3154
|
+
defaultArgValue,
|
|
3155
|
+
argValue
|
|
3156
|
+
);
|
|
3157
|
+
} else {
|
|
3158
|
+
merged[argKey] = argValue;
|
|
3159
|
+
}
|
|
3160
|
+
}
|
|
3161
|
+
result[key] = merged;
|
|
3162
|
+
}
|
|
3163
|
+
}
|
|
3164
|
+
return result;
|
|
3165
|
+
}
|
|
3117
3166
|
function hasClientControlledValues(obj) {
|
|
3118
3167
|
for (const value of Object.values(obj)) {
|
|
3119
3168
|
if (isForcedValue(value))
|
|
@@ -3176,6 +3225,8 @@ function checkSelectForClientArgs(config) {
|
|
|
3176
3225
|
return true;
|
|
3177
3226
|
if (value.select && checkSelectForClientArgs(value.select))
|
|
3178
3227
|
return true;
|
|
3228
|
+
if (value.include && checkIncludeForClientArgs(value.include))
|
|
3229
|
+
return true;
|
|
3179
3230
|
}
|
|
3180
3231
|
return false;
|
|
3181
3232
|
}
|
|
@@ -3311,9 +3362,6 @@ function createModelGuardExtension(config) {
|
|
|
3311
3362
|
return queryBuilder.buildWhereSchema(modelName, whereConfig);
|
|
3312
3363
|
}
|
|
3313
3364
|
function buildProjectionSchema(shape) {
|
|
3314
|
-
if (shape.select && shape.include) {
|
|
3315
|
-
throw new ShapeError('Shape cannot define both "select" and "include"');
|
|
3316
|
-
}
|
|
3317
3365
|
const schemaFields = {};
|
|
3318
3366
|
let forcedIncludeTree = {};
|
|
3319
3367
|
let forcedSelectTree = {};
|
|
@@ -3365,6 +3413,11 @@ function createModelGuardExtension(config) {
|
|
|
3365
3413
|
`Guard shape does not define "select" or "include" for ${method} return projection`
|
|
3366
3414
|
);
|
|
3367
3415
|
}
|
|
3416
|
+
if ("select" in parsed && "include" in parsed) {
|
|
3417
|
+
throw new ShapeError(
|
|
3418
|
+
'Request body cannot define both "select" and "include"'
|
|
3419
|
+
);
|
|
3420
|
+
}
|
|
3368
3421
|
if (!hasShapeProjection)
|
|
3369
3422
|
return {};
|
|
3370
3423
|
if (!hasBodyProjection && !enforceProjection)
|
|
@@ -3458,6 +3511,29 @@ function createModelGuardExtension(config) {
|
|
|
3458
3511
|
}
|
|
3459
3512
|
return where;
|
|
3460
3513
|
}
|
|
3514
|
+
function buildEffectiveReadBody(resolved) {
|
|
3515
|
+
const hasShapeProjection = !!resolved.shape.select || !!resolved.shape.include;
|
|
3516
|
+
if (!hasShapeProjection)
|
|
3517
|
+
return resolved.body;
|
|
3518
|
+
const defaultProjection = buildDefaultProjectionBody(resolved.shape);
|
|
3519
|
+
const hasBodyProjection = "select" in resolved.body || "include" in resolved.body;
|
|
3520
|
+
if (!hasBodyProjection) {
|
|
3521
|
+
return { ...resolved.body, ...defaultProjection };
|
|
3522
|
+
}
|
|
3523
|
+
const merged = { ...resolved.body };
|
|
3524
|
+
if ("select" in resolved.body && "select" in defaultProjection && isPlainObject(resolved.body.select) && isPlainObject(defaultProjection.select)) {
|
|
3525
|
+
merged.select = applyClientProjectionOverrides(
|
|
3526
|
+
defaultProjection.select,
|
|
3527
|
+
resolved.body.select
|
|
3528
|
+
);
|
|
3529
|
+
} else if ("include" in resolved.body && "include" in defaultProjection && isPlainObject(resolved.body.include) && isPlainObject(defaultProjection.include)) {
|
|
3530
|
+
merged.include = applyClientProjectionOverrides(
|
|
3531
|
+
defaultProjection.include,
|
|
3532
|
+
resolved.body.include
|
|
3533
|
+
);
|
|
3534
|
+
}
|
|
3535
|
+
return merged;
|
|
3536
|
+
}
|
|
3461
3537
|
function makeReadMethod(method) {
|
|
3462
3538
|
return (body) => {
|
|
3463
3539
|
const caller = resolveCaller();
|
|
@@ -3473,17 +3549,7 @@ function createModelGuardExtension(config) {
|
|
|
3473
3549
|
resolved.wasDynamic
|
|
3474
3550
|
);
|
|
3475
3551
|
const isUnique = UNIQUE_READ_METHODS.has(method);
|
|
3476
|
-
|
|
3477
|
-
const hasShapeProjection = !!resolved.shape.select || !!resolved.shape.include;
|
|
3478
|
-
if (hasShapeProjection) {
|
|
3479
|
-
const hasBodyProjection = "select" in resolved.body || "include" in resolved.body;
|
|
3480
|
-
if (!hasBodyProjection) {
|
|
3481
|
-
effectiveBody = {
|
|
3482
|
-
...resolved.body,
|
|
3483
|
-
...buildDefaultProjectionBody(resolved.shape)
|
|
3484
|
-
};
|
|
3485
|
-
}
|
|
3486
|
-
}
|
|
3552
|
+
const effectiveBody = buildEffectiveReadBody(resolved);
|
|
3487
3553
|
const args = applyBuiltShape(built, effectiveBody, isUnique);
|
|
3488
3554
|
if (isUnique && args.where) {
|
|
3489
3555
|
validateResolvedUniqueWhere(
|