@nxgt/graphql-validation 0.5.0 → 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.
Files changed (35) hide show
  1. package/README.md +54 -6
  2. package/dist/bad-user-input.d.ts +17 -2
  3. package/dist/bad-user-input.d.ts.map +1 -1
  4. package/dist/builder/check-constraints.d.ts +4 -2
  5. package/dist/builder/check-constraints.d.ts.map +1 -1
  6. package/dist/builder/declared.d.ts +12 -0
  7. package/dist/builder/declared.d.ts.map +1 -0
  8. package/dist/chunks/{index-xcaf9kes.js → index-atwkcfg3.js} +5 -5
  9. package/dist/chunks/{index-xcaf9kes.js.map → index-atwkcfg3.js.map} +2 -2
  10. package/dist/chunks/{index-twevz7yc.js → index-w9pw7fsk.js} +68 -34
  11. package/dist/chunks/{index-twevz7yc.js.map → index-w9pw7fsk.js.map} +6 -5
  12. package/dist/cli.js +1 -1
  13. package/dist/codegen.js +2 -2
  14. package/dist/index.d.ts +3 -1
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +380 -10
  17. package/dist/index.js.map +10 -5
  18. package/dist/limits/describe.d.ts +9 -0
  19. package/dist/limits/describe.d.ts.map +1 -0
  20. package/dist/limits/introspection.d.ts +12 -0
  21. package/dist/limits/introspection.d.ts.map +1 -0
  22. package/dist/limits/list-size.d.ts +15 -0
  23. package/dist/limits/list-size.d.ts.map +1 -0
  24. package/dist/limits/max-depth.d.ts +28 -0
  25. package/dist/limits/max-depth.d.ts.map +1 -0
  26. package/dist/limits/max-list-cost.d.ts +62 -0
  27. package/dist/limits/max-list-cost.d.ts.map +1 -0
  28. package/dist/with-validation.d.ts.map +1 -1
  29. package/docs/README.md +1 -0
  30. package/docs/guide/constraints.md +3 -3
  31. package/docs/guide/errors.md +12 -3
  32. package/docs/guide/query-limits.md +206 -0
  33. package/docs/roadmap.md +4 -0
  34. package/docs/troubleshooting.md +53 -0
  35. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  constraintTypeDefs2
4
- } from "./chunks/index-xcaf9kes.js";
4
+ } from "./chunks/index-atwkcfg3.js";
5
5
 
6
6
  // src/typedefs-command.ts
7
7
  import { mkdir, writeFile } from "node:fs/promises";
package/dist/codegen.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  applyRuleCode
3
- } from "./chunks/index-xcaf9kes.js";
3
+ } from "./chunks/index-atwkcfg3.js";
4
4
  import {
5
5
  registryOf,
6
6
  constraintsOn2,
@@ -8,7 +8,7 @@ import {
8
8
  assertObjectTargets,
9
9
  baseCode,
10
10
  checkConstraints2
11
- } from "./chunks/index-twevz7yc.js";
11
+ } from "./chunks/index-w9pw7fsk.js";
12
12
  // src/builder/input-code.ts
13
13
  import {
14
14
  getNamedType,
package/dist/index.d.ts CHANGED
@@ -1,10 +1,12 @@
1
- export { type BadUserInputExtensions, badUserInput, type ValidationIssue, } from './bad-user-input.js';
1
+ export { type BadUserInputExtensions, badUserInput, type ConstraintValue, type ValidationIssue, } from './bad-user-input.js';
2
2
  export { constraintTypeDefs } from './constraint-directive.js';
3
3
  export { FIELD_CODES, fieldIssueOf } from './field-issue-of.js';
4
4
  export type { FormatName } from './formats/index.js';
5
5
  export type { StringSchema } from './formats/format.js';
6
6
  export type { FormatSchemas, OwnFormats } from './formats/registry.js';
7
7
  export { type FieldError, type FieldIssue, type FieldsErrorOptions, fieldsError, INVALID_INPUT, type InvalidInputOptions, type IssueParams, inputPath, invalidInputError, type Translate, } from './invalid-input.js';
8
+ export { type MaxDepthOptions, maxDepth } from './limits/max-depth.js';
9
+ export { type MaxListCostOptions, maxListCost } from './limits/max-list-cost.js';
8
10
  export type { ConstraintArgument } from './rules/index.js';
9
11
  export { type ArgsSchema, type ArgsSchemaFor, type SchemaOf, validated, } from './validated.js';
10
12
  export { type WithValidationOptions, withValidation, } from './with-validation.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,sBAAsB,EAC3B,YAAY,EACZ,KAAK,eAAe,GACpB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAC7D,YAAY,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC5C,YAAY,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACpE,OAAO,EACN,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,kBAAkB,EACvB,WAAW,EACX,aAAa,EACb,KAAK,mBAAmB,EACxB,KAAK,WAAW,EAChB,SAAS,EACT,iBAAiB,EACjB,KAAK,SAAS,GACd,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAClD,OAAO,EACN,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,QAAQ,EACb,SAAS,GACT,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,KAAK,qBAAqB,EAC1B,cAAc,GACd,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,sBAAsB,EAC3B,YAAY,EACZ,KAAK,eAAe,EACpB,KAAK,eAAe,GACpB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAC7D,YAAY,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC5C,YAAY,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACpE,OAAO,EACN,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,kBAAkB,EACvB,WAAW,EACX,aAAa,EACb,KAAK,mBAAmB,EACxB,KAAK,WAAW,EAChB,SAAS,EACT,iBAAiB,EACjB,KAAK,SAAS,GACd,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,KAAK,eAAe,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACpE,OAAO,EAAE,KAAK,kBAAkB,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC9E,YAAY,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAClD,OAAO,EACN,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,QAAQ,EACb,SAAS,GACT,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,KAAK,qBAAqB,EAC1B,cAAc,GACd,MAAM,mBAAmB,CAAC"}
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  constraintOf,
3
3
  constraintTypeDefs2
4
- } from "./chunks/index-xcaf9kes.js";
4
+ } from "./chunks/index-atwkcfg3.js";
5
5
  import {
6
6
  checkConstraints2
7
- } from "./chunks/index-twevz7yc.js";
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 ? { path, message: issue.message, code: issue.code, constraint } : { path, message: issue.message, code: issue.code };
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,6 +131,361 @@ 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) {
@@ -145,21 +506,21 @@ import {
145
506
  } from "graphql";
146
507
  var wrapped = Symbol.for("@nxgt/graphql-validation/wrapped");
147
508
  var wrappedWith = Symbol.for("@nxgt/graphql-validation/formats");
148
- function checking(schema, where, resolve) {
509
+ function checking(schema, where, resolve, constraintOf) {
149
510
  const check = async (source, args, context, info) => await resolve(source, await parseArgs(schema, args, where, constraintOf), context, info);
150
511
  check[wrapped] = true;
151
512
  return check;
152
513
  }
153
- function wrap(field, args, where, subscription) {
514
+ function wrap(field, args, where, subscription, constraintOf) {
154
515
  const subscribe = field.subscribe ?? (subscription ? defaultFieldResolver : undefined);
155
516
  if (subscribe) {
156
517
  if (!subscribe[wrapped])
157
- field.subscribe = checking(args, where, subscribe);
518
+ field.subscribe = checking(args, where, subscribe, constraintOf);
158
519
  return;
159
520
  }
160
521
  const resolve = field.resolve ?? defaultFieldResolver;
161
522
  if (!resolve[wrapped])
162
- field.resolve = checking(args, where, resolve);
523
+ field.resolve = checking(args, where, resolve, constraintOf);
163
524
  }
164
525
  function withValidation(schema, options = {}) {
165
526
  const formats = options.formats ?? {};
@@ -168,9 +529,16 @@ function withValidation(schema, options = {}) {
168
529
  if (before && !sameFormats(before, formats)) {
169
530
  throw new Error("withValidation: this schema is already wrapped with other formats. Call withValidation once, with every format.");
170
531
  }
171
- const directive = checkConstraints2(schema, (type, field, args) => {
532
+ const directive = checkConstraints2(schema, (type, field, args, declared) => {
172
533
  const subscription = type === schema.getSubscriptionType();
173
- wrap(field, args, `${type.name}.${field.name}`, subscription);
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);
174
542
  }, formats);
175
543
  if (!directive) {
176
544
  throw new Error("withValidation: this schema declares no @constraint directive. Add constraintTypeDefs to its type definitions.");
@@ -192,9 +560,11 @@ export {
192
560
  fieldsError,
193
561
  inputPath,
194
562
  invalidInputError,
563
+ maxDepth,
564
+ maxListCost,
195
565
  validated,
196
566
  withValidation
197
567
  };
198
568
 
199
- //# debugId=DE46FB4511D84A4364756E2164756E21
569
+ //# debugId=E43868C11AE8F6A464756E2164756E21
200
570
  //# sourceMappingURL=index.js.map