@nxgt/graphql-validation 0.4.1 → 0.6.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/README.md +59 -8
- package/dist/bad-user-input.d.ts +17 -2
- package/dist/bad-user-input.d.ts.map +1 -1
- package/dist/builder/check-constraints.d.ts +4 -2
- package/dist/builder/check-constraints.d.ts.map +1 -1
- package/dist/builder/declared.d.ts +12 -0
- package/dist/builder/declared.d.ts.map +1 -0
- package/dist/chunks/{index-xcaf9kes.js → index-atwkcfg3.js} +5 -5
- package/dist/chunks/{index-xcaf9kes.js.map → index-atwkcfg3.js.map} +2 -2
- package/dist/chunks/{index-twevz7yc.js → index-w9pw7fsk.js} +68 -34
- package/dist/chunks/{index-twevz7yc.js.map → index-w9pw7fsk.js.map} +6 -5
- package/dist/cli.js +1 -1
- package/dist/codegen.js +2 -2
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +385 -11
- package/dist/index.js.map +11 -6
- package/dist/limits/describe.d.ts +9 -0
- package/dist/limits/describe.d.ts.map +1 -0
- package/dist/limits/introspection.d.ts +12 -0
- package/dist/limits/introspection.d.ts.map +1 -0
- package/dist/limits/list-size.d.ts +15 -0
- package/dist/limits/list-size.d.ts.map +1 -0
- package/dist/limits/max-depth.d.ts +28 -0
- package/dist/limits/max-depth.d.ts.map +1 -0
- package/dist/limits/max-list-cost.d.ts +62 -0
- package/dist/limits/max-list-cost.d.ts.map +1 -0
- package/dist/validated.d.ts +28 -1
- package/dist/validated.d.ts.map +1 -1
- package/dist/with-validation.d.ts.map +1 -1
- package/docs/README.md +1 -0
- package/docs/guide/constraints.md +3 -3
- package/docs/guide/errors.md +78 -4
- package/docs/guide/query-limits.md +206 -0
- package/docs/roadmap.md +13 -2
- package/docs/troubleshooting.md +53 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
constraintOf,
|
|
3
3
|
constraintTypeDefs2
|
|
4
|
-
} from "./chunks/index-
|
|
4
|
+
} from "./chunks/index-atwkcfg3.js";
|
|
5
5
|
import {
|
|
6
6
|
checkConstraints2
|
|
7
|
-
} from "./chunks/index-
|
|
7
|
+
} from "./chunks/index-w9pw7fsk.js";
|
|
8
8
|
|
|
9
9
|
// src/bad-user-input.ts
|
|
10
10
|
import { GraphQLError } from "graphql";
|
|
@@ -12,7 +12,13 @@ function issuesOf(error, constraintOf) {
|
|
|
12
12
|
return error.issues.map((issue) => {
|
|
13
13
|
const path = issue.path.map((key) => typeof key === "number" ? key : String(key));
|
|
14
14
|
const constraint = constraintOf?.(issue);
|
|
15
|
-
return constraint ? {
|
|
15
|
+
return constraint ? {
|
|
16
|
+
path,
|
|
17
|
+
message: issue.message,
|
|
18
|
+
code: issue.code,
|
|
19
|
+
constraint: constraint.argument,
|
|
20
|
+
value: constraint.value
|
|
21
|
+
} : { path, message: issue.message, code: issue.code };
|
|
16
22
|
});
|
|
17
23
|
}
|
|
18
24
|
function errorOf(where, issues) {
|
|
@@ -125,37 +131,396 @@ function codeOf(issue) {
|
|
|
125
131
|
return FIELD_CODES.invalid;
|
|
126
132
|
}
|
|
127
133
|
}
|
|
134
|
+
// src/limits/max-depth.ts
|
|
135
|
+
import {
|
|
136
|
+
GraphQLError as GraphQLError3
|
|
137
|
+
} from "graphql";
|
|
138
|
+
|
|
139
|
+
// src/limits/describe.ts
|
|
140
|
+
function operationLabel(operation) {
|
|
141
|
+
return operation.name ? `Operation "${operation.name.value}"` : "Operation";
|
|
142
|
+
}
|
|
143
|
+
function assertInteger(option, value, min, max = Number.MAX_SAFE_INTEGER) {
|
|
144
|
+
if (!Number.isInteger(value) || value < min || value >= max) {
|
|
145
|
+
throw new RangeError(`${option} must be an integer from ${min} to ${max - 1}.`);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// src/limits/introspection.ts
|
|
150
|
+
import {
|
|
151
|
+
isEnumType,
|
|
152
|
+
isInputObjectType,
|
|
153
|
+
isInterfaceType,
|
|
154
|
+
isObjectType,
|
|
155
|
+
isUnionType,
|
|
156
|
+
SchemaMetaFieldDef,
|
|
157
|
+
TypeMetaFieldDef
|
|
158
|
+
} from "graphql";
|
|
159
|
+
function isIntrospectionRoot(name) {
|
|
160
|
+
return name === "__schema" || name === "__type";
|
|
161
|
+
}
|
|
162
|
+
function introspectionRoot(name) {
|
|
163
|
+
if (name === "__schema")
|
|
164
|
+
return SchemaMetaFieldDef;
|
|
165
|
+
if (name === "__type")
|
|
166
|
+
return TypeMetaFieldDef;
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
var largest = new WeakMap;
|
|
170
|
+
var typeCounts = new WeakMap;
|
|
171
|
+
function typeCount(schema) {
|
|
172
|
+
let count = typeCounts.get(schema);
|
|
173
|
+
if (count === undefined) {
|
|
174
|
+
count = Object.keys(schema.getTypeMap()).length;
|
|
175
|
+
typeCounts.set(schema, count);
|
|
176
|
+
}
|
|
177
|
+
return count;
|
|
178
|
+
}
|
|
179
|
+
function largestCount(schema) {
|
|
180
|
+
const known = largest.get(schema);
|
|
181
|
+
if (known !== undefined)
|
|
182
|
+
return known;
|
|
183
|
+
let max = schema.getDirectives().length;
|
|
184
|
+
for (const directive of schema.getDirectives()) {
|
|
185
|
+
max = Math.max(max, directive.args.length, directive.locations.length);
|
|
186
|
+
}
|
|
187
|
+
for (const type of Object.values(schema.getTypeMap())) {
|
|
188
|
+
max = Math.max(max, countsOf(schema, type));
|
|
189
|
+
}
|
|
190
|
+
largest.set(schema, max);
|
|
191
|
+
return max;
|
|
192
|
+
}
|
|
193
|
+
function countsOf(schema, type) {
|
|
194
|
+
if (isObjectType(type) || isInterfaceType(type)) {
|
|
195
|
+
const fields = Object.values(type.getFields());
|
|
196
|
+
return Math.max(fields.length, type.getInterfaces().length, isInterfaceType(type) ? schema.getPossibleTypes(type).length : 0, ...fields.map((field) => field.args.length));
|
|
197
|
+
}
|
|
198
|
+
if (isInputObjectType(type))
|
|
199
|
+
return Object.keys(type.getFields()).length;
|
|
200
|
+
if (isEnumType(type))
|
|
201
|
+
return type.getValues().length;
|
|
202
|
+
if (isUnionType(type))
|
|
203
|
+
return type.getTypes().length;
|
|
204
|
+
return 0;
|
|
205
|
+
}
|
|
206
|
+
function introspectionSize(schema, field) {
|
|
207
|
+
return field === "types" ? typeCount(schema) : largestCount(schema);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// src/limits/max-depth.ts
|
|
211
|
+
function depthOf(depth, selectionSet) {
|
|
212
|
+
let deepest = 0;
|
|
213
|
+
for (const selection of selectionSet.selections) {
|
|
214
|
+
let here = 0;
|
|
215
|
+
if (selection.kind === "Field") {
|
|
216
|
+
const name = selection.name.value;
|
|
217
|
+
if (name === "__typename")
|
|
218
|
+
continue;
|
|
219
|
+
if (depth.ignoreIntrospection && isIntrospectionRoot(name))
|
|
220
|
+
continue;
|
|
221
|
+
here = 1 + (selection.selectionSet ? depthOf(depth, selection.selectionSet) : 0);
|
|
222
|
+
} else if (selection.kind === "InlineFragment") {
|
|
223
|
+
here = depthOf(depth, selection.selectionSet);
|
|
224
|
+
} else {
|
|
225
|
+
here = fragmentDepth(depth, selection.name.value);
|
|
226
|
+
}
|
|
227
|
+
if (here > deepest)
|
|
228
|
+
deepest = here;
|
|
229
|
+
}
|
|
230
|
+
return deepest;
|
|
231
|
+
}
|
|
232
|
+
function fragmentDepth(depth, name) {
|
|
233
|
+
const known = depth.fragmentDepths.get(name);
|
|
234
|
+
if (known !== undefined)
|
|
235
|
+
return known;
|
|
236
|
+
const fragment = depth.getFragment(name);
|
|
237
|
+
if (!fragment || depth.measuring.has(name))
|
|
238
|
+
return 0;
|
|
239
|
+
depth.measuring.add(name);
|
|
240
|
+
const result = depthOf(depth, fragment.selectionSet);
|
|
241
|
+
depth.measuring.delete(name);
|
|
242
|
+
depth.fragmentDepths.set(name, result);
|
|
243
|
+
return result;
|
|
244
|
+
}
|
|
245
|
+
function maxDepth(options) {
|
|
246
|
+
const limit = options.depth;
|
|
247
|
+
assertInteger("maxDepth: depth", limit, 1);
|
|
248
|
+
return (context) => {
|
|
249
|
+
const walk = {
|
|
250
|
+
getFragment: (name) => context.getFragment(name),
|
|
251
|
+
fragmentDepths: new Map,
|
|
252
|
+
measuring: new Set,
|
|
253
|
+
ignoreIntrospection: options.ignoreIntrospection ?? false
|
|
254
|
+
};
|
|
255
|
+
return {
|
|
256
|
+
OperationDefinition(operation) {
|
|
257
|
+
const depth = depthOf(walk, operation.selectionSet);
|
|
258
|
+
if (depth > limit) {
|
|
259
|
+
context.reportError(new GraphQLError3(`${operationLabel(operation)} is ${depth} levels deep, more than the ${limit} allowed`, {
|
|
260
|
+
nodes: [operation],
|
|
261
|
+
extensions: { code: "QUERY_TOO_DEEP", depth, limit }
|
|
262
|
+
}));
|
|
263
|
+
}
|
|
264
|
+
return false;
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
// src/limits/max-list-cost.ts
|
|
270
|
+
import {
|
|
271
|
+
GraphQLError as GraphQLError4,
|
|
272
|
+
getNamedType,
|
|
273
|
+
getNullableType,
|
|
274
|
+
isInterfaceType as isInterfaceType2,
|
|
275
|
+
isListType,
|
|
276
|
+
isObjectType as isObjectType2
|
|
277
|
+
} from "graphql";
|
|
278
|
+
|
|
279
|
+
// src/limits/list-size.ts
|
|
280
|
+
import {
|
|
281
|
+
isAbstractType
|
|
282
|
+
} from "graphql";
|
|
283
|
+
var CEILING = Number.MAX_SAFE_INTEGER;
|
|
284
|
+
var CANONICAL_INTEGER = /^(0|[1-9]\d*)$/;
|
|
285
|
+
function sizeOf(value) {
|
|
286
|
+
if (typeof value === "string") {
|
|
287
|
+
return CANONICAL_INTEGER.test(value) ? Math.min(Number(value), CEILING) : undefined;
|
|
288
|
+
}
|
|
289
|
+
if (typeof value === "bigint") {
|
|
290
|
+
return value >= 0n ? Math.min(Number(value), CEILING) : undefined;
|
|
291
|
+
}
|
|
292
|
+
return typeof value === "number" && Number.isInteger(value) && value >= 0 ? Math.min(value, CEILING) : undefined;
|
|
293
|
+
}
|
|
294
|
+
function literalSize(value) {
|
|
295
|
+
if (value.kind === "IntValue" || value.kind === "FloatValue") {
|
|
296
|
+
return sizeOf(Number(value.value));
|
|
297
|
+
}
|
|
298
|
+
return value.kind === "StringValue" ? sizeOf(value.value) : undefined;
|
|
299
|
+
}
|
|
300
|
+
function defaultSizeOf(argument) {
|
|
301
|
+
if (!argument)
|
|
302
|
+
return;
|
|
303
|
+
if ("defaultValue" in argument) {
|
|
304
|
+
const size = sizeOf(argument.defaultValue);
|
|
305
|
+
if (size !== undefined)
|
|
306
|
+
return size;
|
|
307
|
+
}
|
|
308
|
+
if (!("default" in argument))
|
|
309
|
+
return;
|
|
310
|
+
const fallback = argument.default;
|
|
311
|
+
if (typeof fallback !== "object" || fallback === null)
|
|
312
|
+
return;
|
|
313
|
+
if ("value" in fallback)
|
|
314
|
+
return sizeOf(fallback.value);
|
|
315
|
+
if ("literal" in fallback && typeof fallback.literal === "object") {
|
|
316
|
+
const literal = fallback.literal;
|
|
317
|
+
return literal !== null && "kind" in literal ? literalSize(literal) : undefined;
|
|
318
|
+
}
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
var profiles = new WeakMap;
|
|
322
|
+
function profileOf(cost, parent, definition) {
|
|
323
|
+
let bySizes = profiles.get(cost.schema);
|
|
324
|
+
if (!bySizes) {
|
|
325
|
+
bySizes = new WeakMap;
|
|
326
|
+
profiles.set(cost.schema, bySizes);
|
|
327
|
+
}
|
|
328
|
+
let byField = bySizes.get(cost.sizeArguments);
|
|
329
|
+
if (!byField) {
|
|
330
|
+
byField = new Map;
|
|
331
|
+
bySizes.set(cost.sizeArguments, byField);
|
|
332
|
+
}
|
|
333
|
+
const key = `${parent?.name}.${definition.name}`;
|
|
334
|
+
const known = byField.get(key);
|
|
335
|
+
if (known)
|
|
336
|
+
return known;
|
|
337
|
+
const definitions = [definition];
|
|
338
|
+
if (isAbstractType(parent)) {
|
|
339
|
+
for (const type of cost.schema.getPossibleTypes(parent)) {
|
|
340
|
+
const implemented = type.getFields()[definition.name];
|
|
341
|
+
if (implemented)
|
|
342
|
+
definitions.push(implemented);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
const profile = {
|
|
346
|
+
largest: cost.sizeArguments.map(() => {
|
|
347
|
+
return;
|
|
348
|
+
}),
|
|
349
|
+
someLack: cost.sizeArguments.map(() => false),
|
|
350
|
+
someBare: false
|
|
351
|
+
};
|
|
352
|
+
for (const field of definitions) {
|
|
353
|
+
let any = false;
|
|
354
|
+
cost.sizeArguments.forEach((name, index) => {
|
|
355
|
+
const size = defaultSizeOf(field.args.find((arg) => arg.name === name));
|
|
356
|
+
if (size === undefined) {
|
|
357
|
+
profile.someLack[index] = true;
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
any = true;
|
|
361
|
+
profile.largest[index] = Math.max(profile.largest[index] ?? 0, size);
|
|
362
|
+
});
|
|
363
|
+
if (!any)
|
|
364
|
+
profile.someBare = true;
|
|
365
|
+
}
|
|
366
|
+
byField.set(key, profile);
|
|
367
|
+
return profile;
|
|
368
|
+
}
|
|
369
|
+
function argumentSize(cost, profile, index, node) {
|
|
370
|
+
const largest = profile.largest[index];
|
|
371
|
+
if (!node)
|
|
372
|
+
return largest;
|
|
373
|
+
const literal = literalSize(node.value);
|
|
374
|
+
if (literal !== undefined)
|
|
375
|
+
return literal;
|
|
376
|
+
return profile.someLack[index] ? Math.max(largest ?? 0, cost.defaultFirst) : largest;
|
|
377
|
+
}
|
|
378
|
+
function listSize(cost, parent, definition, args) {
|
|
379
|
+
const profile = profileOf(cost, parent, definition);
|
|
380
|
+
let size;
|
|
381
|
+
let given = false;
|
|
382
|
+
cost.sizeArguments.forEach((name, index) => {
|
|
383
|
+
const node = args?.find((arg) => arg.name.value === name);
|
|
384
|
+
if (node)
|
|
385
|
+
given = true;
|
|
386
|
+
const said = argumentSize(cost, profile, index, node);
|
|
387
|
+
if (said !== undefined)
|
|
388
|
+
size = Math.max(size ?? 0, said);
|
|
389
|
+
});
|
|
390
|
+
if (!given && profile.someBare)
|
|
391
|
+
size = Math.max(size ?? 0, cost.defaultFirst);
|
|
392
|
+
return size ?? cost.defaultFirst;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// src/limits/max-list-cost.ts
|
|
396
|
+
var DEFAULT_SIZE_ARGUMENTS = ["first", "last", "limit"];
|
|
397
|
+
var CEILING2 = Number.MAX_SAFE_INTEGER;
|
|
398
|
+
var add = (a, b) => Math.min(CEILING2, a + b);
|
|
399
|
+
var multiply = (a, b) => Math.min(CEILING2, a * b);
|
|
400
|
+
function fieldOf(cost, parent, name) {
|
|
401
|
+
if (parent === cost.schema.getQueryType() && isIntrospectionRoot(name)) {
|
|
402
|
+
return introspectionRoot(name);
|
|
403
|
+
}
|
|
404
|
+
return isObjectType2(parent) || isInterfaceType2(parent) ? parent.getFields()[name] : undefined;
|
|
405
|
+
}
|
|
406
|
+
function costOf(cost, selectionSet, parent) {
|
|
407
|
+
let total = 0;
|
|
408
|
+
for (const selection of selectionSet.selections) {
|
|
409
|
+
if (selection.kind === "Field") {
|
|
410
|
+
const name = selection.name.value;
|
|
411
|
+
if (name === "__typename")
|
|
412
|
+
continue;
|
|
413
|
+
if (isIntrospectionRoot(name) && cost.ignoreIntrospection)
|
|
414
|
+
continue;
|
|
415
|
+
const definition = fieldOf(cost, parent, name);
|
|
416
|
+
if (!definition)
|
|
417
|
+
continue;
|
|
418
|
+
let inner = 0;
|
|
419
|
+
if (selection.selectionSet) {
|
|
420
|
+
inner = costOf(cost, selection.selectionSet, getNamedType(definition.type));
|
|
421
|
+
if (isListType(getNullableType(definition.type))) {
|
|
422
|
+
const size = parent?.name.startsWith("__") ? introspectionSize(cost.schema, name) : listSize(cost, parent, definition, selection.arguments);
|
|
423
|
+
inner = multiply(inner, size);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
total = add(total, add(1, inner));
|
|
427
|
+
} else if (selection.kind === "InlineFragment") {
|
|
428
|
+
const condition = selection.typeCondition ? cost.schema.getType(selection.typeCondition.name.value) : parent;
|
|
429
|
+
total = add(total, costOf(cost, selection.selectionSet, condition));
|
|
430
|
+
} else {
|
|
431
|
+
total = add(total, fragmentCost(cost, selection.name.value));
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
return total;
|
|
435
|
+
}
|
|
436
|
+
function fragmentCost(cost, name) {
|
|
437
|
+
const known = cost.fragmentCosts.get(name);
|
|
438
|
+
if (known !== undefined)
|
|
439
|
+
return known;
|
|
440
|
+
const fragment = cost.getFragment(name);
|
|
441
|
+
if (!fragment || cost.costing.has(name))
|
|
442
|
+
return 0;
|
|
443
|
+
cost.costing.add(name);
|
|
444
|
+
const result = costOf(cost, fragment.selectionSet, cost.schema.getType(fragment.typeCondition.name.value));
|
|
445
|
+
cost.costing.delete(name);
|
|
446
|
+
cost.fragmentCosts.set(name, result);
|
|
447
|
+
return result;
|
|
448
|
+
}
|
|
449
|
+
function rootType(schema, operation) {
|
|
450
|
+
const type = operation.operation === "query" ? schema.getQueryType() : operation.operation === "mutation" ? schema.getMutationType() : schema.getSubscriptionType();
|
|
451
|
+
return type ?? undefined;
|
|
452
|
+
}
|
|
453
|
+
function maxListCost(options) {
|
|
454
|
+
const { budget, defaultFirst } = options;
|
|
455
|
+
const sizeArguments = Object.freeze([
|
|
456
|
+
...options.sizeArguments ?? DEFAULT_SIZE_ARGUMENTS
|
|
457
|
+
]);
|
|
458
|
+
assertInteger("maxListCost: budget", budget, 0);
|
|
459
|
+
assertInteger("maxListCost: defaultFirst", defaultFirst, 0);
|
|
460
|
+
return (context) => {
|
|
461
|
+
const schema = context.getSchema();
|
|
462
|
+
const cost = {
|
|
463
|
+
schema,
|
|
464
|
+
sizeArguments,
|
|
465
|
+
defaultFirst,
|
|
466
|
+
ignoreIntrospection: options.ignoreIntrospection ?? false,
|
|
467
|
+
getFragment: (name) => context.getFragment(name),
|
|
468
|
+
fragmentCosts: new Map,
|
|
469
|
+
costing: new Set
|
|
470
|
+
};
|
|
471
|
+
return {
|
|
472
|
+
OperationDefinition(operation) {
|
|
473
|
+
const total = costOf(cost, operation.selectionSet, rootType(schema, operation));
|
|
474
|
+
if (total > budget) {
|
|
475
|
+
context.reportError(new GraphQLError4(`${operationLabel(operation)} costs ${total}, more than the ${budget} allowed`, {
|
|
476
|
+
nodes: [operation],
|
|
477
|
+
extensions: {
|
|
478
|
+
code: "QUERY_TOO_COSTLY",
|
|
479
|
+
cost: total,
|
|
480
|
+
limit: budget
|
|
481
|
+
}
|
|
482
|
+
}));
|
|
483
|
+
}
|
|
484
|
+
return false;
|
|
485
|
+
}
|
|
486
|
+
};
|
|
487
|
+
};
|
|
488
|
+
}
|
|
128
489
|
// src/validated.ts
|
|
129
490
|
import { z } from "zod";
|
|
130
491
|
function validated(schema, resolve) {
|
|
131
|
-
const
|
|
492
|
+
const fixed = typeof schema === "function" ? undefined : zodOf(schema);
|
|
132
493
|
return async (source, args, context, info) => {
|
|
133
494
|
const where = `${info.parentType.name}.${info.fieldName}`;
|
|
495
|
+
const checked = fixed ?? zodOf(await schema(context, info));
|
|
134
496
|
const parsed = await parseArgs(checked, args, where);
|
|
135
497
|
return await resolve(source, parsed, context, info);
|
|
136
498
|
};
|
|
137
499
|
}
|
|
500
|
+
function zodOf(schema) {
|
|
501
|
+
return "_zod" in schema ? schema : z.object(schema);
|
|
502
|
+
}
|
|
138
503
|
// src/with-validation.ts
|
|
139
504
|
import {
|
|
140
505
|
defaultFieldResolver
|
|
141
506
|
} from "graphql";
|
|
142
507
|
var wrapped = Symbol.for("@nxgt/graphql-validation/wrapped");
|
|
143
508
|
var wrappedWith = Symbol.for("@nxgt/graphql-validation/formats");
|
|
144
|
-
function checking(schema, where, resolve) {
|
|
509
|
+
function checking(schema, where, resolve, constraintOf) {
|
|
145
510
|
const check = async (source, args, context, info) => await resolve(source, await parseArgs(schema, args, where, constraintOf), context, info);
|
|
146
511
|
check[wrapped] = true;
|
|
147
512
|
return check;
|
|
148
513
|
}
|
|
149
|
-
function wrap(field, args, where, subscription) {
|
|
514
|
+
function wrap(field, args, where, subscription, constraintOf) {
|
|
150
515
|
const subscribe = field.subscribe ?? (subscription ? defaultFieldResolver : undefined);
|
|
151
516
|
if (subscribe) {
|
|
152
517
|
if (!subscribe[wrapped])
|
|
153
|
-
field.subscribe = checking(args, where, subscribe);
|
|
518
|
+
field.subscribe = checking(args, where, subscribe, constraintOf);
|
|
154
519
|
return;
|
|
155
520
|
}
|
|
156
521
|
const resolve = field.resolve ?? defaultFieldResolver;
|
|
157
522
|
if (!resolve[wrapped])
|
|
158
|
-
field.resolve = checking(args, where, resolve);
|
|
523
|
+
field.resolve = checking(args, where, resolve, constraintOf);
|
|
159
524
|
}
|
|
160
525
|
function withValidation(schema, options = {}) {
|
|
161
526
|
const formats = options.formats ?? {};
|
|
@@ -164,9 +529,16 @@ function withValidation(schema, options = {}) {
|
|
|
164
529
|
if (before && !sameFormats(before, formats)) {
|
|
165
530
|
throw new Error("withValidation: this schema is already wrapped with other formats. Call withValidation once, with every format.");
|
|
166
531
|
}
|
|
167
|
-
const directive = checkConstraints2(schema, (type, field, args) => {
|
|
532
|
+
const directive = checkConstraints2(schema, (type, field, args, declared) => {
|
|
168
533
|
const subscription = type === schema.getSubscriptionType();
|
|
169
|
-
|
|
534
|
+
const named = (issue) => {
|
|
535
|
+
const argument = constraintOf(issue);
|
|
536
|
+
if (!argument)
|
|
537
|
+
return;
|
|
538
|
+
const found = declared(issue.path).find(({ rule }) => rule.argument === argument);
|
|
539
|
+
return found && { argument, value: found.value };
|
|
540
|
+
};
|
|
541
|
+
wrap(field, args, `${type.name}.${field.name}`, subscription, named);
|
|
170
542
|
}, formats);
|
|
171
543
|
if (!directive) {
|
|
172
544
|
throw new Error("withValidation: this schema declares no @constraint directive. Add constraintTypeDefs to its type definitions.");
|
|
@@ -188,9 +560,11 @@ export {
|
|
|
188
560
|
fieldsError,
|
|
189
561
|
inputPath,
|
|
190
562
|
invalidInputError,
|
|
563
|
+
maxDepth,
|
|
564
|
+
maxListCost,
|
|
191
565
|
validated,
|
|
192
566
|
withValidation
|
|
193
567
|
};
|
|
194
568
|
|
|
195
|
-
//# debugId=
|
|
569
|
+
//# debugId=E43868C11AE8F6A464756E2164756E21
|
|
196
570
|
//# sourceMappingURL=index.js.map
|