@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.
Files changed (37) hide show
  1. package/README.md +59 -8
  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 +4 -2
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +385 -11
  17. package/dist/index.js.map +11 -6
  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/validated.d.ts +28 -1
  29. package/dist/validated.d.ts.map +1 -1
  30. package/dist/with-validation.d.ts.map +1 -1
  31. package/docs/README.md +1 -0
  32. package/docs/guide/constraints.md +3 -3
  33. package/docs/guide/errors.md +78 -4
  34. package/docs/guide/query-limits.md +206 -0
  35. package/docs/roadmap.md +13 -2
  36. package/docs/troubleshooting.md +53 -0
  37. package/package.json +1 -1
package/dist/index.js.map CHANGED
@@ -1,14 +1,19 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/bad-user-input.ts", "../src/invalid-input.ts", "../src/field-issue-of.ts", "../src/validated.ts", "../src/with-validation.ts"],
3
+ "sources": ["../src/bad-user-input.ts", "../src/invalid-input.ts", "../src/field-issue-of.ts", "../src/limits/max-depth.ts", "../src/limits/describe.ts", "../src/limits/introspection.ts", "../src/limits/max-list-cost.ts", "../src/limits/list-size.ts", "../src/validated.ts", "../src/with-validation.ts"],
4
4
  "sourcesContent": [
5
- "import { GraphQLError } from 'graphql';\nimport type { z } from 'zod';\nimport type { ConstraintArgument } from './rules';\n\n/** One reason an input was refused, at its path inside the arguments. */\nexport interface ValidationIssue {\n\t/** `['input', 'address', 'zip']`: the argument, then the input fields. */\n\treadonly path: readonly (string | number)[];\n\treadonly message: string;\n\t/** Zod's issue code: `too_small`, `invalid_format`, `custom`, ... */\n\treadonly code: string;\n\t/**\n\t * The `@constraint` argument that refused (`minLength`, `format`), when a\n\t * directive did: stable across Zod versions, unlike `code`. Absent for a\n\t * refusal of `validated()`'s own schema.\n\t */\n\treadonly constraint?: ConstraintArgument;\n}\n\n/** The `extensions` of the error an invalid input becomes. */\nexport type BadUserInputExtensions = {\n\treadonly code: 'BAD_USER_INPUT';\n\treadonly issues: readonly ValidationIssue[];\n};\n\n/** Names the `@constraint` argument behind an issue, when there is one. */\nexport type ConstraintOf = (\n\tissue: z.core.$ZodIssue,\n) => ConstraintArgument | undefined;\n\nfunction issuesOf(\n\terror: z.ZodError,\n\tconstraintOf?: ConstraintOf,\n): ValidationIssue[] {\n\treturn error.issues.map((issue) => {\n\t\tconst path = issue.path.map((key) =>\n\t\t\ttypeof key === 'number' ? key : String(key),\n\t\t);\n\t\tconst constraint = constraintOf?.(issue);\n\t\treturn constraint\n\t\t\t? { path, message: issue.message, code: issue.code, constraint }\n\t\t\t: { path, message: issue.message, code: issue.code };\n\t});\n}\n\nfunction errorOf(where: string, issues: ValidationIssue[]): GraphQLError {\n\tconst [first] = issues;\n\tconst reason = first\n\t\t? `${first.path.join('.') || 'arguments'}: ${first.message}`\n\t\t: 'refused';\n\tconst extensions: BadUserInputExtensions = { code: 'BAD_USER_INPUT', issues };\n\treturn new GraphQLError(`Invalid arguments for ${where}. ${reason}`, {\n\t\textensions,\n\t});\n}\n\n/**\n * The one error an invalid input becomes: `extensions.code` is\n * `BAD_USER_INPUT`, the code Apollo and most clients already read, and\n * `extensions.issues` lists every reason with its path, so a form can show\n * each one beside its field. The message names the field and the first\n * reason, for a log line.\n */\nexport function badUserInput(where: string, error: z.ZodError): GraphQLError {\n\treturn errorOf(where, issuesOf(error));\n}\n\n/** The parsed arguments, or the error above, its issues named by `constraintOf`. */\nexport async function parseArgs(\n\tschema: z.ZodType,\n\targs: unknown,\n\twhere: string,\n\tconstraintOf?: ConstraintOf,\n): Promise<unknown> {\n\tconst result = await schema.safeParseAsync(args);\n\tif (!result.success)\n\t\tthrow errorOf(where, issuesOf(result.error, constraintOf));\n\treturn result.data;\n}\n",
5
+ "import { GraphQLError } from 'graphql';\nimport type { z } from 'zod';\nimport type { ConstraintArgument } from './rules';\n\n/** One reason an input was refused, at its path inside the arguments. */\nexport interface ValidationIssue {\n\t/** `['input', 'address', 'zip']`: the argument, then the input fields. */\n\treadonly path: readonly (string | number)[];\n\treadonly message: string;\n\t/** Zod's issue code: `too_small`, `invalid_format`, `custom`, ... */\n\treadonly code: string;\n\t/**\n\t * The `@constraint` argument that refused (`minLength`, `format`), when a\n\t * directive did: stable across Zod versions, unlike `code`. Absent for a\n\t * refusal of `validated()`'s own schema.\n\t */\n\treadonly constraint?: ConstraintArgument;\n\t/**\n\t * What that `@constraint` argument was declared with, exactly as written\n\t * (`100` for `maxLength: 100`, `\"email\"` for `format: \"email\"`), so a\n\t * client can say \"at most 100 characters\" without parsing `message`.\n\t * Present exactly when `constraint` is.\n\t */\n\treadonly value?: ConstraintValue;\n}\n\n/** What a `@constraint` argument is declared with: a number or a string. */\nexport type ConstraintValue = string | number;\n\n/** The `extensions` of the error an invalid input becomes. */\nexport type BadUserInputExtensions = {\n\treadonly code: 'BAD_USER_INPUT';\n\treadonly issues: readonly ValidationIssue[];\n};\n\n/**\n * Names the `@constraint` argument behind an issue, and what it was declared\n * with, when there is one.\n */\nexport type ConstraintOf = (\n\tissue: z.core.$ZodIssue,\n) => { argument: ConstraintArgument; value: ConstraintValue } | undefined;\n\nfunction issuesOf(\n\terror: z.ZodError,\n\tconstraintOf?: ConstraintOf,\n): ValidationIssue[] {\n\treturn error.issues.map((issue) => {\n\t\tconst path = issue.path.map((key) =>\n\t\t\ttypeof key === 'number' ? key : String(key),\n\t\t);\n\t\tconst constraint = constraintOf?.(issue);\n\t\treturn constraint\n\t\t\t? {\n\t\t\t\t\tpath,\n\t\t\t\t\tmessage: issue.message,\n\t\t\t\t\tcode: issue.code,\n\t\t\t\t\tconstraint: constraint.argument,\n\t\t\t\t\tvalue: constraint.value,\n\t\t\t\t}\n\t\t\t: { path, message: issue.message, code: issue.code };\n\t});\n}\n\nfunction errorOf(where: string, issues: ValidationIssue[]): GraphQLError {\n\tconst [first] = issues;\n\tconst reason = first\n\t\t? `${first.path.join('.') || 'arguments'}: ${first.message}`\n\t\t: 'refused';\n\tconst extensions: BadUserInputExtensions = { code: 'BAD_USER_INPUT', issues };\n\treturn new GraphQLError(`Invalid arguments for ${where}. ${reason}`, {\n\t\textensions,\n\t});\n}\n\n/**\n * The one error an invalid input becomes: `extensions.code` is\n * `BAD_USER_INPUT`, the code Apollo and most clients already read, and\n * `extensions.issues` lists every reason with its path, so a form can show\n * each one beside its field. The message names the field and the first\n * reason, for a log line.\n */\nexport function badUserInput(where: string, error: z.ZodError): GraphQLError {\n\treturn errorOf(where, issuesOf(error));\n}\n\n/** The parsed arguments, or the error above, its issues named by `constraintOf`. */\nexport async function parseArgs(\n\tschema: z.ZodType,\n\targs: unknown,\n\twhere: string,\n\tconstraintOf?: ConstraintOf,\n): Promise<unknown> {\n\tconst result = await schema.safeParseAsync(args);\n\tif (!result.success)\n\t\tthrow errorOf(where, issuesOf(result.error, constraintOf));\n\treturn result.data;\n}\n",
6
6
  "import { GraphQLError, type GraphQLErrorOptions } from 'graphql';\n\n/** The code of the error `invalidInputError` builds, and its default message. */\nexport const INVALID_INPUT = 'validation.errors.invalid-input';\n\n/** Values a message is built from, such as `{ min: 2 }`. */\nexport type IssueParams = Record<string, string | number>;\n\n/** One field at fault: where it is, why, and what the reason's message needs. */\nexport interface FieldIssue {\n\t/** The field inside the input, dotted: `person.firstName`, `tags.1`. */\n\treadonly path: string;\n\t/** A code your client and your translations know: `validation.errors.too-short`. */\n\treadonly code: string;\n\t/** Values the message needs; an object with no key counts as none. */\n\treadonly params?: IssueParams;\n}\n\n/** One entry of `extensions.fields`: a `FieldIssue` with its message. */\nexport interface FieldError {\n\treadonly path: string;\n\treadonly code: string;\n\t/** `translate(code, params)`, or the code itself without a translator. */\n\treadonly message: string;\n\t/** Present only when the issue had params with at least one key. */\n\treadonly params?: IssueParams;\n}\n\n/** Turns a code (and its params) into the text a person reads. */\nexport type Translate = (code: string, params?: IssueParams) => string;\n\n/** The options of `invalidInputError`: GraphQL's own, and a translator. */\nexport type InvalidInputOptions = GraphQLErrorOptions & {\n\treadonly translate?: Translate;\n};\n\n/** The options of `fieldsError`: also an HTTP status and the error's own params. */\nexport type FieldsErrorOptions = InvalidInputOptions & {\n\t/** `extensions.http.status`, for a server that reads it (409, ...). */\n\treadonly status?: number;\n\treadonly params?: IssueParams;\n};\n\n/** `params` itself, or `undefined` when it holds no key: never `{}`. */\nfunction paramsOf(params: IssueParams | undefined): IssueParams | undefined {\n\treturn params && Object.keys(params).length > 0 ? params : undefined;\n}\n\nfunction messageOf(\n\tcode: string,\n\tparams: IssueParams | undefined,\n\ttranslate: Translate | undefined,\n): string {\n\treturn translate?.(code, params) ?? code;\n}\n\nfunction fieldsOf(\n\tissues: readonly FieldIssue[],\n\ttranslate: Translate | undefined,\n): FieldError[] {\n\treturn issues.map(({ path, code, params: given }) => {\n\t\tconst params = paramsOf(given);\n\t\treturn {\n\t\t\tpath,\n\t\t\tcode,\n\t\t\tmessage: messageOf(code, params, translate),\n\t\t\t...(params && { params }),\n\t\t};\n\t});\n}\n\n/**\n * One 400 error listing every field at fault, for an API that answers invalid\n * input this way: `extensions` is `{ code: 'validation.errors.invalid-input',\n * http: { status: 400 }, fields }`, each field with its translated message\n * (the code itself without `translate`), in the order given. GraphQL's\n * options (`originalError`, `path`, `nodes`, ...) are kept; an `extensions`\n * among them is replaced by this one.\n */\nexport function invalidInputError(\n\tissues: readonly FieldIssue[],\n\toptions: InvalidInputOptions = {},\n): GraphQLError {\n\tconst { translate, ...graphql } = options;\n\treturn new GraphQLError(messageOf(INVALID_INPUT, undefined, translate), {\n\t\t...graphql,\n\t\textensions: {\n\t\t\tcode: INVALID_INPUT,\n\t\t\thttp: { status: 400 },\n\t\t\tfields: fieldsOf(issues, translate),\n\t\t},\n\t});\n}\n\n/**\n * A refusal of your own (a 409 conflict, say) that names the fields at\n * fault: `extensions` is `{ code, params?, http?: { status }, fields }`, the\n * fields worded as `invalidInputError` words them, the message\n * `translate(code, params)` or the code. An `extensions` among the options\n * is replaced by this one.\n */\nexport function fieldsError(\n\tcode: string,\n\tissues: readonly FieldIssue[],\n\toptions: FieldsErrorOptions = {},\n): GraphQLError {\n\tconst { translate, status, params: given, ...graphql } = options;\n\tconst params = paramsOf(given);\n\treturn new GraphQLError(messageOf(code, params, translate), {\n\t\t...graphql,\n\t\textensions: {\n\t\t\tcode,\n\t\t\t...(params && { params }),\n\t\t\t...(status && { http: { status } }),\n\t\t\tfields: fieldsOf(issues, translate),\n\t\t},\n\t});\n}\n\n/**\n * A GraphQL or Zod path as a `FieldIssue` path: dotted, without the leading\n * `input` argument when a field follows it, a symbol written as\n * `String(key)`. `['input', 'person', 'firstName']` is `person.firstName`,\n * `['input', 'tags', 1]` is `tags.1`, `['first']` and `['input']` stay as\n * they are.\n */\nexport function inputPath(path: readonly PropertyKey[]): string {\n\tconst [first, ...rest] = path;\n\treturn (first === 'input' && rest.length > 0 ? rest : path)\n\t\t.map((key) => String(key))\n\t\t.join('.');\n}\n",
7
7
  "import type { z } from 'zod';\nimport { type FieldIssue, inputPath } from './invalid-input';\n\n/**\n * The codes `fieldIssueOf` gives, each under `validation.errors.`: a string's\n * length (`too-short`, `too-long`), a number's or bigint's bound or multiple\n * (`out-of-range`), a list's or set's size (`too-few`, `too-many`), a named\n * format or a pattern (`invalid-format`), anything else (`invalid`).\n */\nexport const FIELD_CODES = {\n\ttooShort: 'validation.errors.too-short',\n\ttooLong: 'validation.errors.too-long',\n\toutOfRange: 'validation.errors.out-of-range',\n\ttooFew: 'validation.errors.too-few',\n\ttooMany: 'validation.errors.too-many',\n\tinvalidFormat: 'validation.errors.invalid-format',\n\tinvalid: 'validation.errors.invalid',\n} as const;\n\n/** The string checks Zod reports as `invalid_format` that are not a format. */\nconst TEXT_CHECKS: ReadonlySet<string> = new Set([\n\t'starts_with',\n\t'ends_with',\n\t'includes',\n]);\n\n/**\n * A Zod issue as a `FieldIssue`, for `invalidInputError`: its path through\n * `inputPath` (dotted, a leading `input` dropped) and one of `FIELD_CODES`,\n * without params. `too-short` / `too-long` for a string's length,\n * `out-of-range` for a number's or bigint's bound or a multiple, `too-few` /\n * `too-many` for a list's or set's size, `invalid-format` for a named format\n * or a pattern, `invalid` for anything else (a prefix, a suffix or a\n * substring included).\n */\nexport function fieldIssueOf(issue: z.core.$ZodIssue): FieldIssue {\n\treturn { path: inputPath(issue.path), code: codeOf(issue) };\n}\n\nfunction codeOf(issue: z.core.$ZodIssue): string {\n\tswitch (issue.code) {\n\t\tcase 'too_small':\n\t\tcase 'too_big': {\n\t\t\tconst small = issue.code === 'too_small';\n\t\t\tswitch (issue.origin) {\n\t\t\t\tcase 'string':\n\t\t\t\t\treturn small ? FIELD_CODES.tooShort : FIELD_CODES.tooLong;\n\t\t\t\tcase 'number':\n\t\t\t\tcase 'bigint':\n\t\t\t\t\treturn FIELD_CODES.outOfRange;\n\t\t\t\tcase 'array':\n\t\t\t\tcase 'set':\n\t\t\t\t\treturn small ? FIELD_CODES.tooFew : FIELD_CODES.tooMany;\n\t\t\t\tdefault:\n\t\t\t\t\treturn FIELD_CODES.invalid;\n\t\t\t}\n\t\t}\n\t\tcase 'not_multiple_of':\n\t\t\treturn FIELD_CODES.outOfRange;\n\t\tcase 'invalid_format':\n\t\t\t// A prefix, a suffix or a substring is not a format: only a named\n\t\t\t// format (`email`, `uuid`, …) or a pattern is.\n\t\t\treturn TEXT_CHECKS.has(issue.format)\n\t\t\t\t? FIELD_CODES.invalid\n\t\t\t\t: FIELD_CODES.invalidFormat;\n\t\tdefault:\n\t\t\treturn FIELD_CODES.invalid;\n\t}\n}\n",
8
- "import type { GraphQLFieldResolver, GraphQLResolveInfo } from 'graphql';\nimport { z } from 'zod';\nimport { parseArgs } from './bad-user-input';\n\n/** An object schema of the arguments, or its shape. */\nexport type ArgsSchema = z.ZodType<Record<string, unknown>> | z.ZodRawShape;\n\n/** The schema `ArgsSchema` stands for. */\nexport type SchemaOf<S extends ArgsSchema> = S extends z.ZodType\n\t? S\n\t: z.ZodObject<S & z.ZodRawShape>;\n\n/**\n * A resolver whose arguments are checked by `schema` before it runs, for what\n * a `@constraint` cannot say: a rule across arguments, a business refinement,\n * an async check. It receives the parsed arguments (`z.output`), defaults and\n * transforms applied; an invalid input is the same `BAD_USER_INPUT` error as\n * the directives'.\n *\n * ```ts\n * signUp: validated(\n * z.object({ input: signUpSchema }).refine(({ input }) => input.password !== input.email),\n * (_, { input }) => users.create(input),\n * )\n * ```\n */\nexport function validated<\n\tS extends ArgsSchema,\n\tTSource = unknown,\n\tTContext = unknown,\n\tTResult = unknown,\n>(\n\tschema: S,\n\tresolve: (\n\t\tsource: TSource,\n\t\targs: z.output<SchemaOf<S>>,\n\t\tcontext: TContext,\n\t\tinfo: GraphQLResolveInfo,\n\t) => TResult,\n): GraphQLFieldResolver<\n\tTSource,\n\tTContext,\n\tz.input<SchemaOf<S>>,\n\tPromise<Awaited<TResult>>\n> {\n\t// `_zod`, not `instanceof`: a schema from another copy of zod is still one.\n\tconst checked = (\n\t\t'_zod' in schema ? schema : z.object(schema as z.ZodRawShape)\n\t) as z.ZodType;\n\treturn async (source, args, context, info): Promise<Awaited<TResult>> => {\n\t\tconst where = `${info.parentType.name}.${info.fieldName}`;\n\t\tconst parsed = (await parseArgs(checked, args, where)) as z.output<\n\t\t\tSchemaOf<S>\n\t\t>;\n\t\treturn await resolve(source, parsed, context, info);\n\t};\n}\n",
9
- "import {\n\tdefaultFieldResolver,\n\ttype GraphQLField,\n\ttype GraphQLFieldResolver,\n\ttype GraphQLSchema,\n} from 'graphql';\nimport type { z } from 'zod';\nimport { parseArgs } from './bad-user-input';\nimport { checkConstraints } from './builder/check-constraints';\nimport type { FormatSchemas, OwnFormats } from './formats/registry';\nimport { constraintOf } from './rules';\n\n// Symbol.for: two copies of the package in one tree still wrap a field once.\nconst wrapped = Symbol.for('@nxgt/graphql-validation/wrapped');\n// The formats a schema was wrapped with, kept on the schema itself.\nconst wrappedWith = Symbol.for('@nxgt/graphql-validation/formats');\n\n/** What `withValidation` takes besides the schema. */\nexport interface WithValidationOptions<\n\tF extends FormatSchemas = FormatSchemas,\n> {\n\t/**\n\t * The application's own formats, which `@constraint(format: \"...\")` may\n\t * name beside the built-in ones: one Zod string schema each, keyed by its\n\t * name (lowercase letters, digits and hyphens). A built-in name is a type\n\t * error, and refused at startup.\n\t */\n\treadonly formats?: OwnFormats<F>;\n}\n\ntype Resolver = GraphQLFieldResolver<unknown, unknown> & { [wrapped]?: true };\n\nfunction checking(\n\tschema: z.ZodType,\n\twhere: string,\n\tresolve: Resolver,\n): Resolver {\n\tconst check: Resolver = async (source, args, context, info) =>\n\t\tawait resolve(\n\t\t\tsource,\n\t\t\tawait parseArgs(schema, args, where, constraintOf),\n\t\t\tcontext,\n\t\t\tinfo,\n\t\t);\n\tcheck[wrapped] = true;\n\treturn check;\n}\n\n/**\n * Wraps a field once. A subscription field is checked in `subscribe`, which\n * runs once per subscription — graphql's default one when the field has none\n * — and its `resolve` runs once per event, with the same arguments, already\n * checked.\n */\nfunction wrap(\n\tfield: GraphQLField<unknown, unknown>,\n\targs: z.ZodType,\n\twhere: string,\n\tsubscription: boolean,\n): void {\n\tconst subscribe = (field.subscribe ??\n\t\t(subscription ? defaultFieldResolver : undefined)) as Resolver | undefined;\n\tif (subscribe) {\n\t\tif (!subscribe[wrapped]) field.subscribe = checking(args, where, subscribe);\n\t\treturn;\n\t}\n\tconst resolve = (field.resolve ?? defaultFieldResolver) as Resolver;\n\tif (!resolve[wrapped]) field.resolve = checking(args, where, resolve);\n}\n\n/**\n * Checks every `@constraint` of `schema` before the resolvers run. Each\n * field with a constrained argument — directly, or anywhere inside an input\n * type it takes — gets its resolver (and its `subscribe`) wrapped: the\n * arguments are parsed by the Zod schema the directives describe, the\n * resolver receives the parsed value, and an invalid input becomes one\n * `BAD_USER_INPUT` error. Fields with nothing to check are left untouched.\n *\n * The schema is built here, once: a constraint that cannot apply (a\n * `minLength` on an `Int`, an unknown format, a bad pattern) throws now, not\n * on the first request. The resolvers are wrapped in place and the same\n * schema is returned, so it goes wherever it went before; calling it twice\n * wraps nothing twice. Call it last, once every resolver is attached: a\n * resolver set on a field afterwards replaces the check.\n *\n * A `@constraint` on an interface's argument must be repeated on each\n * object's field, which is the one that resolves; a field that drops it\n * fails here.\n *\n * The directives are read from the SDL (`astNode`), so a schema built from\n * type definitions — `buildSchema`, `makeExecutableSchema`, Yoga, Apollo —\n * is checked; a code-first schema with no SDL has no `@constraint` to read.\n *\n * `options.formats` adds the application's own formats; wrapping a schema\n * again throws unless the record has the same names, each the very same\n * schema (no formats after some, or some after none, throws too), since its\n * fields are already checked against the first ones.\n */\nexport function withValidation<\n\tS extends GraphQLSchema,\n\t// biome-ignore lint/complexity/noBannedTypes: no formats of its own by default\n\tconst F extends FormatSchemas = {},\n>(schema: S, options: WithValidationOptions<F> = {}): S {\n\tconst formats: FormatSchemas = options.formats ?? {};\n\tconst holder = schema as unknown as { [wrappedWith]?: FormatSchemas };\n\tconst before = holder[wrappedWith];\n\tif (before && !sameFormats(before, formats)) {\n\t\tthrow new Error(\n\t\t\t'withValidation: this schema is already wrapped with other formats. Call withValidation once, with every format.',\n\t\t);\n\t}\n\tconst directive = checkConstraints(\n\t\tschema,\n\t\t(type, field, args) => {\n\t\t\tconst subscription = type === schema.getSubscriptionType();\n\t\t\twrap(field, args, `${type.name}.${field.name}`, subscription);\n\t\t},\n\t\tformats,\n\t);\n\tif (!directive) {\n\t\tthrow new Error(\n\t\t\t'withValidation: this schema declares no @constraint directive. Add constraintTypeDefs to its type definitions.',\n\t\t);\n\t}\n\tif (!before) Object.defineProperty(schema, wrappedWith, { value: formats });\n\treturn schema;\n}\n\n/** The same names, each the very same schema. */\nfunction sameFormats(a: FormatSchemas, b: FormatSchemas): boolean {\n\tconst names = Object.keys(a);\n\treturn (\n\t\tnames.length === Object.keys(b).length &&\n\t\tnames.every((name) => Object.hasOwn(b, name) && a[name] === b[name])\n\t);\n}\n"
8
+ "import {\n\ttype FragmentDefinitionNode,\n\tGraphQLError,\n\ttype SelectionSetNode,\n\ttype ValidationContext,\n\ttype ValidationRule,\n} from 'graphql';\nimport { assertInteger, operationLabel } from './describe';\nimport { isIntrospectionRoot } from './introspection';\n\n/** Options of {@link maxDepth}. */\nexport interface MaxDepthOptions {\n\t/** The deepest nesting of field selections an operation may have (at least 1). */\n\tdepth: number;\n\t/**\n\t * Do not count `__schema` and `__type` (default `false`). Only where\n\t * introspection is disabled or the client is trusted, e.g. GraphiQL in\n\t * development: the standard introspection query (`getIntrospectionQuery()`) is 15 levels deep.\n\t */\n\tignoreIntrospection?: boolean;\n}\n\n/** What a walk of one document needs: what it has measured so far. */\ninterface DepthContext {\n\tgetFragment: (name: string) => FragmentDefinitionNode | null | undefined;\n\tfragmentDepths: Map<string, number>;\n\tmeasuring: Set<string>;\n\tignoreIntrospection: boolean;\n}\n\n/** The depth of `selectionSet`: 0 when it selects no field. */\nfunction depthOf(depth: DepthContext, selectionSet: SelectionSetNode): number {\n\tlet deepest = 0;\n\tfor (const selection of selectionSet.selections) {\n\t\tlet here = 0;\n\t\tif (selection.kind === 'Field') {\n\t\t\tconst name = selection.name.value;\n\t\t\tif (name === '__typename') continue;\n\t\t\tif (depth.ignoreIntrospection && isIntrospectionRoot(name)) continue;\n\t\t\there =\n\t\t\t\t1 +\n\t\t\t\t(selection.selectionSet ? depthOf(depth, selection.selectionSet) : 0);\n\t\t} else if (selection.kind === 'InlineFragment') {\n\t\t\there = depthOf(depth, selection.selectionSet);\n\t\t} else {\n\t\t\there = fragmentDepth(depth, selection.name.value);\n\t\t}\n\t\tif (here > deepest) deepest = here;\n\t}\n\treturn deepest;\n}\n\n/** The depth of the named fragment, measured once. */\nfunction fragmentDepth(depth: DepthContext, name: string): number {\n\tconst known = depth.fragmentDepths.get(name);\n\tif (known !== undefined) return known;\n\tconst fragment = depth.getFragment(name);\n\t// A cycle is NoFragmentCyclesRule's to report; here it adds nothing.\n\tif (!fragment || depth.measuring.has(name)) return 0;\n\tdepth.measuring.add(name);\n\tconst result = depthOf(depth, fragment.selectionSet);\n\tdepth.measuring.delete(name);\n\tdepth.fragmentDepths.set(name, result);\n\treturn result;\n}\n\n/**\n * A graphql-js validation rule refusing an operation nested deeper than\n * `depth` fields: a top-level field is depth 1.\n *\n * Named fragments are followed (each measured once), inline fragments add no\n * depth, and `__typename` does not count. One `GraphQLError` per\n * operation, with `extensions: { code: 'QUERY_TOO_DEEP', depth, limit }`,\n * `depth` being the operation's real depth.\n *\n * ```ts\n * validate(schema, document, [...specifiedRules, maxDepth({ depth: 8 })]);\n * // graphql-yoga: onValidate: ({ addValidationRule }) => addValidationRule(maxDepth({ depth: 8 }))\n * ```\n */\nexport function maxDepth(options: MaxDepthOptions): ValidationRule {\n\tconst limit = options.depth;\n\tassertInteger('maxDepth: depth', limit, 1);\n\treturn (context: ValidationContext) => {\n\t\tconst walk: DepthContext = {\n\t\t\tgetFragment: (name) => context.getFragment(name),\n\t\t\tfragmentDepths: new Map(),\n\t\t\tmeasuring: new Set(),\n\t\t\tignoreIntrospection: options.ignoreIntrospection ?? false,\n\t\t};\n\t\treturn {\n\t\t\tOperationDefinition(operation) {\n\t\t\t\tconst depth = depthOf(walk, operation.selectionSet);\n\t\t\t\tif (depth > limit) {\n\t\t\t\t\tcontext.reportError(\n\t\t\t\t\t\tnew GraphQLError(\n\t\t\t\t\t\t\t`${operationLabel(operation)} is ${depth} levels deep, more than the ${limit} allowed`,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tnodes: [operation],\n\t\t\t\t\t\t\t\textensions: { code: 'QUERY_TOO_DEEP', depth, limit },\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t},\n\t\t};\n\t};\n}\n",
9
+ "import type { OperationDefinitionNode } from 'graphql';\n\n/** `Operation \"Name\"`, or `Operation` for an anonymous one. */\nexport function operationLabel(operation: OperationDefinitionNode): string {\n\treturn operation.name ? `Operation \"${operation.name.value}\"` : 'Operation';\n}\n\n/**\n * Throws a `RangeError` unless `value` is an integer from `min` up to, and\n * excluding, `max` (default: `Number.MAX_SAFE_INTEGER`, where a cost is clamped).\n */\nexport function assertInteger(\n\toption: string,\n\tvalue: number,\n\tmin: number,\n\tmax = Number.MAX_SAFE_INTEGER,\n): void {\n\tif (!Number.isInteger(value) || value < min || value >= max) {\n\t\tthrow new RangeError(\n\t\t\t`${option} must be an integer from ${min} to ${max - 1}.`,\n\t\t);\n\t}\n}\n",
10
+ "import {\n\ttype GraphQLField,\n\ttype GraphQLNamedType,\n\ttype GraphQLSchema,\n\tisEnumType,\n\tisInputObjectType,\n\tisInterfaceType,\n\tisObjectType,\n\tisUnionType,\n\tSchemaMetaFieldDef,\n\tTypeMetaFieldDef,\n} from 'graphql';\n\n/** The meta-fields that read the schema; `__typename` is not one. */\nexport function isIntrospectionRoot(name: string): boolean {\n\treturn name === '__schema' || name === '__type';\n}\n\n/** The definition of `__schema` or `__type`, selected on the query root. */\nexport function introspectionRoot(\n\tname: string,\n): GraphQLField<unknown, unknown> | undefined {\n\tif (name === '__schema') return SchemaMetaFieldDef;\n\tif (name === '__type') return TypeMetaFieldDef;\n\treturn undefined;\n}\n\n/** The largest list the introspection types can return for `schema`, by schema. */\nconst largest = new WeakMap<GraphQLSchema, number>();\n\nconst typeCounts = new WeakMap<GraphQLSchema, number>();\n\nfunction typeCount(schema: GraphQLSchema): number {\n\tlet count = typeCounts.get(schema);\n\tif (count === undefined) {\n\t\tcount = Object.keys(schema.getTypeMap()).length;\n\t\ttypeCounts.set(schema, count);\n\t}\n\treturn count;\n}\n\nfunction largestCount(schema: GraphQLSchema): number {\n\tconst known = largest.get(schema);\n\tif (known !== undefined) return known;\n\tlet max = schema.getDirectives().length;\n\tfor (const directive of schema.getDirectives()) {\n\t\tmax = Math.max(max, directive.args.length, directive.locations.length);\n\t}\n\tfor (const type of Object.values(schema.getTypeMap())) {\n\t\tmax = Math.max(max, countsOf(schema, type));\n\t}\n\tlargest.set(schema, max);\n\treturn max;\n}\n\n/** The longest of a type's fields, input fields, enum values, interfaces, possible types and arguments. */\nfunction countsOf(schema: GraphQLSchema, type: GraphQLNamedType): number {\n\tif (isObjectType(type) || isInterfaceType(type)) {\n\t\tconst fields = Object.values(type.getFields());\n\t\treturn Math.max(\n\t\t\tfields.length,\n\t\t\ttype.getInterfaces().length,\n\t\t\tisInterfaceType(type) ? schema.getPossibleTypes(type).length : 0,\n\t\t\t...fields.map((field) => field.args.length),\n\t\t);\n\t}\n\tif (isInputObjectType(type)) return Object.keys(type.getFields()).length;\n\tif (isEnumType(type)) return type.getValues().length;\n\tif (isUnionType(type)) return type.getTypes().length;\n\treturn 0;\n}\n\n/**\n * The most items the introspection list `parent.field` can hold in `schema`:\n * the number of types for `__Schema.types`, else the largest list anywhere in\n * the schema. Not `defaultFirst`: a query asks no size of them.\n */\nexport function introspectionSize(\n\tschema: GraphQLSchema,\n\tfield: string,\n): number {\n\treturn field === 'types' ? typeCount(schema) : largestCount(schema);\n}\n",
11
+ "import {\n\ttype FragmentDefinitionNode,\n\tGraphQLError,\n\ttype GraphQLField,\n\ttype GraphQLNamedType,\n\ttype GraphQLSchema,\n\tgetNamedType,\n\tgetNullableType,\n\tisInterfaceType,\n\tisListType,\n\tisObjectType,\n\ttype OperationDefinitionNode,\n\ttype SelectionSetNode,\n\ttype ValidationContext,\n\ttype ValidationRule,\n} from 'graphql';\nimport { assertInteger, operationLabel } from './describe';\nimport {\n\tintrospectionRoot,\n\tintrospectionSize,\n\tisIntrospectionRoot,\n} from './introspection';\nimport { listSize, type SizeContext } from './list-size';\n\n/** Options of {@link maxListCost}. */\nexport interface MaxListCostOptions {\n\t/** The most an operation may cost (at least 0). */\n\tbudget: number;\n\t/** The size of a list field whose size cannot be read (an integer of at least 0). */\n\tdefaultFirst: number;\n\t/**\n\t * The argument names that size a list. Each one given, or defaulted in the\n\t * SDL, says a size (an Int, a canonical-integer string or an integral Float)\n\t * and the largest wins. Default `['first', 'last', 'limit']`.\n\t */\n\tsizeArguments?: readonly string[];\n\t/**\n\t * Do not cost `__schema` and `__type` (default `false`). Only where\n\t * introspection is disabled or the client is trusted, e.g. GraphiQL in\n\t * development: the standard introspection query is costly (on the order of\n\t * 200,000 on a one-field schema).\n\t */\n\tignoreIntrospection?: boolean;\n}\n\nconst DEFAULT_SIZE_ARGUMENTS = ['first', 'last', 'limit'] as const;\n\n/** Costs are plain numbers, held below this so a hostile query never reaches `Infinity`. */\nconst CEILING = Number.MAX_SAFE_INTEGER;\n\nconst add = (a: number, b: number) => Math.min(CEILING, a + b);\nconst multiply = (a: number, b: number) => Math.min(CEILING, a * b);\n\n/** What a walk of one document needs: the options, and what it has measured so far. */\ninterface CostContext extends SizeContext {\n\tignoreIntrospection: boolean;\n\tgetFragment: (name: string) => FragmentDefinitionNode | null | undefined;\n\tfragmentCosts: Map<string, number>;\n\tcosting: Set<string>;\n}\n\n/** The definition of the field `name` on `parent`, meta-fields of the query root included. */\nfunction fieldOf(\n\tcost: CostContext,\n\tparent: GraphQLNamedType | undefined,\n\tname: string,\n): GraphQLField<unknown, unknown> | undefined {\n\tif (parent === cost.schema.getQueryType() && isIntrospectionRoot(name)) {\n\t\treturn introspectionRoot(name);\n\t}\n\treturn isObjectType(parent) || isInterfaceType(parent)\n\t\t? parent.getFields()[name]\n\t\t: undefined;\n}\n\n/** The cost of `selectionSet` selected on `parent`. */\nfunction costOf(\n\tcost: CostContext,\n\tselectionSet: SelectionSetNode,\n\tparent: GraphQLNamedType | undefined,\n): number {\n\tlet total = 0;\n\tfor (const selection of selectionSet.selections) {\n\t\tif (selection.kind === 'Field') {\n\t\t\tconst name = selection.name.value;\n\t\t\tif (name === '__typename') continue;\n\t\t\tif (isIntrospectionRoot(name) && cost.ignoreIntrospection) continue;\n\t\t\tconst definition = fieldOf(cost, parent, name);\n\t\t\t// An unknown field is another rule's to report.\n\t\t\tif (!definition) continue;\n\t\t\tlet inner = 0;\n\t\t\tif (selection.selectionSet) {\n\t\t\t\tinner = costOf(\n\t\t\t\t\tcost,\n\t\t\t\t\tselection.selectionSet,\n\t\t\t\t\tgetNamedType(definition.type),\n\t\t\t\t);\n\t\t\t\tif (isListType(getNullableType(definition.type))) {\n\t\t\t\t\tconst size = parent?.name.startsWith('__')\n\t\t\t\t\t\t? introspectionSize(cost.schema, name)\n\t\t\t\t\t\t: listSize(cost, parent, definition, selection.arguments);\n\t\t\t\t\tinner = multiply(inner, size);\n\t\t\t\t}\n\t\t\t}\n\t\t\ttotal = add(total, add(1, inner));\n\t\t} else if (selection.kind === 'InlineFragment') {\n\t\t\tconst condition = selection.typeCondition\n\t\t\t\t? cost.schema.getType(selection.typeCondition.name.value)\n\t\t\t\t: parent;\n\t\t\ttotal = add(total, costOf(cost, selection.selectionSet, condition));\n\t\t} else {\n\t\t\ttotal = add(total, fragmentCost(cost, selection.name.value));\n\t\t}\n\t}\n\treturn total;\n}\n\n/** The cost of the named fragment, computed once. */\nfunction fragmentCost(cost: CostContext, name: string): number {\n\tconst known = cost.fragmentCosts.get(name);\n\tif (known !== undefined) return known;\n\tconst fragment = cost.getFragment(name);\n\t// A cycle is NoFragmentCyclesRule's to report; here it adds nothing.\n\tif (!fragment || cost.costing.has(name)) return 0;\n\tcost.costing.add(name);\n\tconst result = costOf(\n\t\tcost,\n\t\tfragment.selectionSet,\n\t\tcost.schema.getType(fragment.typeCondition.name.value),\n\t);\n\tcost.costing.delete(name);\n\tcost.fragmentCosts.set(name, result);\n\treturn result;\n}\n\n/** The type an operation selects on. */\nfunction rootType(schema: GraphQLSchema, operation: OperationDefinitionNode) {\n\tconst type =\n\t\toperation.operation === 'query'\n\t\t\t? schema.getQueryType()\n\t\t\t: operation.operation === 'mutation'\n\t\t\t\t? schema.getMutationType()\n\t\t\t\t: schema.getSubscriptionType();\n\treturn type ?? undefined;\n}\n\n/**\n * A graphql-js validation rule refusing an operation whose cost is more than\n * `budget`, to stop a client from exploiting list cycles (`Folder.items`,\n * `Item.folder`, `Folder.items`, …) for a cost growing exponentially.\n *\n * The cost of an operation is the sum, over every selected field, of the\n * product of the sizes of the list fields enclosing it: a field costs 1, and a\n * list field multiplies the cost of its sub-selection by its size.\n * `__typename` costs nothing. `__schema` and `__type` are costed like any\n * field, their lists sized by the schema itself (`__Schema.types` is the number\n * of types, the other lists the longest list anywhere in the schema), unless\n * `ignoreIntrospection` is set.\n *\n * The size of a list field is the largest size its `sizeArguments` (default\n * `first`, `last`, `limit`) say. A literal Int, a String holding a canonical\n * integer (`\"1000\"`) or an integral Float (`1e3`) of at least 0 says that\n * number. Anything else (a negative literal, a variable, since validation has\n * no variable values) says the argument's SDL default when it has a usable one,\n * `defaultFirst` otherwise; an argument not given says its SDL default, or\n * nothing. When nothing is said the size is `defaultFirst`. On an interface the\n * largest default over its possible types is used. Hence no subtree ever costs\n * less than nothing: a negative `first` on one field cannot cancel the cost of\n * its sibling. A field whose type (once unwrapped from non-null) is a list is\n * one list, nested `[[X]]` included.\n *\n * Named fragments are followed, each costed once. Inline fragments and\n * fragments on an abstract type are summed branch by branch, so the cost of a\n * query on an interface or a union is overestimated, never underestimated.\n *\n * One `GraphQLError` per operation, with\n * `extensions: { code: 'QUERY_TOO_COSTLY', cost, limit }`. `cost` is exact up\n * to `Number.MAX_SAFE_INTEGER`, which it never exceeds.\n *\n * ```ts\n * const rule = maxListCost({ budget: 10_000, defaultFirst: 50 });\n * validate(schema, document, [...specifiedRules, rule]);\n * // graphql-yoga: onValidate: ({ addValidationRule }) => addValidationRule(rule)\n * ```\n */\nexport function maxListCost(options: MaxListCostOptions): ValidationRule {\n\tconst { budget, defaultFirst } = options;\n\t// A copy: a caller changing its array later must not desync the schema\n\t// cache keyed by it.\n\tconst sizeArguments = Object.freeze([\n\t\t...(options.sizeArguments ?? DEFAULT_SIZE_ARGUMENTS),\n\t]);\n\tassertInteger('maxListCost: budget', budget, 0);\n\tassertInteger('maxListCost: defaultFirst', defaultFirst, 0);\n\n\treturn (context: ValidationContext) => {\n\t\tconst schema = context.getSchema();\n\t\tconst cost: CostContext = {\n\t\t\tschema,\n\t\t\tsizeArguments,\n\t\t\tdefaultFirst,\n\t\t\tignoreIntrospection: options.ignoreIntrospection ?? false,\n\t\t\tgetFragment: (name) => context.getFragment(name),\n\t\t\tfragmentCosts: new Map(),\n\t\t\tcosting: new Set(),\n\t\t};\n\t\treturn {\n\t\t\tOperationDefinition(operation) {\n\t\t\t\tconst total = costOf(\n\t\t\t\t\tcost,\n\t\t\t\t\toperation.selectionSet,\n\t\t\t\t\trootType(schema, operation),\n\t\t\t\t);\n\t\t\t\tif (total > budget) {\n\t\t\t\t\tcontext.reportError(\n\t\t\t\t\t\tnew GraphQLError(\n\t\t\t\t\t\t\t`${operationLabel(operation)} costs ${total}, more than the ${budget} allowed`,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tnodes: [operation],\n\t\t\t\t\t\t\t\textensions: {\n\t\t\t\t\t\t\t\t\tcode: 'QUERY_TOO_COSTLY',\n\t\t\t\t\t\t\t\t\tcost: total,\n\t\t\t\t\t\t\t\t\tlimit: budget,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t},\n\t\t};\n\t};\n}\n",
12
+ "import {\n\ttype ArgumentNode,\n\ttype GraphQLField,\n\ttype GraphQLNamedType,\n\ttype GraphQLSchema,\n\tisAbstractType,\n\ttype ValueNode,\n} from 'graphql';\n\n/** Sizes are plain numbers, held below this so a hostile query never reaches `Infinity`. */\nconst CEILING = Number.MAX_SAFE_INTEGER;\n\n/** What sizing a list needs: the schema and the options of the rule. */\nexport interface SizeContext {\n\tschema: GraphQLSchema;\n\tsizeArguments: readonly string[];\n\tdefaultFirst: number;\n}\n\nconst CANONICAL_INTEGER = /^(0|[1-9]\\d*)$/;\n\n/**\n * The one reading of a size, wherever it comes from (a literal, a default): a\n * non-negative integral number or bigint, or a canonical-integer string,\n * clamped to the ceiling. Anything else says nothing.\n */\nfunction sizeOf(value: unknown): number | undefined {\n\tif (typeof value === 'string') {\n\t\treturn CANONICAL_INTEGER.test(value)\n\t\t\t? Math.min(Number(value), CEILING)\n\t\t\t: undefined;\n\t}\n\t// A bigint is how a Long scalar's default is held once its real scalar is\n\t// swapped in.\n\tif (typeof value === 'bigint') {\n\t\treturn value >= 0n ? Math.min(Number(value), CEILING) : undefined;\n\t}\n\treturn typeof value === 'number' && Number.isInteger(value) && value >= 0\n\t\t? Math.min(value, CEILING)\n\t\t: undefined;\n}\n\n/** The size a literal gives: an Int, a canonical-integer String or an integral Float (`1e3`). */\nfunction literalSize(value: ValueNode): number | undefined {\n\tif (value.kind === 'IntValue' || value.kind === 'FloatValue') {\n\t\treturn sizeOf(Number(value.value));\n\t}\n\treturn value.kind === 'StringValue' ? sizeOf(value.value) : undefined;\n}\n\n/**\n * An argument's SDL default as a size. graphql 16 holds it as `defaultValue`;\n * graphql 17 as `default`, `{ value }` or `{ literal }`.\n */\nfunction defaultSizeOf(argument: object | undefined): number | undefined {\n\tif (!argument) return undefined;\n\tif ('defaultValue' in argument) {\n\t\tconst size = sizeOf(argument.defaultValue);\n\t\tif (size !== undefined) return size;\n\t}\n\tif (!('default' in argument)) return undefined;\n\tconst fallback = argument.default;\n\tif (typeof fallback !== 'object' || fallback === null) return undefined;\n\tif ('value' in fallback) return sizeOf(fallback.value);\n\tif ('literal' in fallback && typeof fallback.literal === 'object') {\n\t\tconst literal = fallback.literal;\n\t\treturn literal !== null && 'kind' in literal\n\t\t\t? literalSize(literal as ValueNode)\n\t\t\t: undefined;\n\t}\n\treturn undefined;\n}\n\n/**\n * What the schema alone says of one list field and the fields implementing it,\n * per size argument (in `sizeArguments` order): the largest default, whether\n * some definition has none, and whether some definition has no default at all.\n */\ninterface Profile {\n\tlargest: (number | undefined)[];\n\tsomeLack: boolean[];\n\tsomeBare: boolean;\n}\n\nconst profiles = new WeakMap<\n\tGraphQLSchema,\n\tWeakMap<readonly string[], Map<string, Profile>>\n>();\n\nfunction profileOf(\n\tcost: SizeContext,\n\tparent: GraphQLNamedType | undefined,\n\tdefinition: GraphQLField<unknown, unknown>,\n): Profile {\n\tlet bySizes = profiles.get(cost.schema);\n\tif (!bySizes) {\n\t\tbySizes = new WeakMap();\n\t\tprofiles.set(cost.schema, bySizes);\n\t}\n\tlet byField = bySizes.get(cost.sizeArguments);\n\tif (!byField) {\n\t\tbyField = new Map();\n\t\tbySizes.set(cost.sizeArguments, byField);\n\t}\n\tconst key = `${parent?.name}.${definition.name}`;\n\tconst known = byField.get(key);\n\tif (known) return known;\n\n\t// On an interface the object types' own fields count too: each may\n\t// declare another default, and the query cannot say which comes back.\n\tconst definitions = [definition];\n\tif (isAbstractType(parent)) {\n\t\tfor (const type of cost.schema.getPossibleTypes(parent)) {\n\t\t\tconst implemented = type.getFields()[definition.name];\n\t\t\tif (implemented) definitions.push(implemented);\n\t\t}\n\t}\n\tconst profile: Profile = {\n\t\tlargest: cost.sizeArguments.map(() => undefined),\n\t\tsomeLack: cost.sizeArguments.map(() => false),\n\t\tsomeBare: false,\n\t};\n\tfor (const field of definitions) {\n\t\tlet any = false;\n\t\tcost.sizeArguments.forEach((name, index) => {\n\t\t\tconst size = defaultSizeOf(field.args.find((arg) => arg.name === name));\n\t\t\tif (size === undefined) {\n\t\t\t\tprofile.someLack[index] = true;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tany = true;\n\t\t\tprofile.largest[index] = Math.max(profile.largest[index] ?? 0, size);\n\t\t});\n\t\tif (!any) profile.someBare = true;\n\t}\n\tbyField.set(key, profile);\n\treturn profile;\n}\n\n/** The size a size argument says, `undefined` when it says nothing. */\nfunction argumentSize(\n\tcost: SizeContext,\n\tprofile: Profile,\n\tindex: number,\n\tnode: ArgumentNode | undefined,\n): number | undefined {\n\tconst largest = profile.largest[index];\n\tif (!node) return largest;\n\tconst literal = literalSize(node.value);\n\tif (literal !== undefined) return literal;\n\t// Given but unusable (a variable, a negative number): the argument's own\n\t// default, else defaultFirst.\n\treturn profile.someLack[index]\n\t\t? Math.max(largest ?? 0, cost.defaultFirst)\n\t\t: largest;\n}\n\n/**\n * The size of the list `definition` returns on `parent`, as selected by\n * `args`: the largest its size arguments say, and `defaultFirst` when none\n * says anything. The schema's part is memoized, so a selection costs\n * `sizeArguments.length` steps whatever the number of possible types.\n */\nexport function listSize(\n\tcost: SizeContext,\n\tparent: GraphQLNamedType | undefined,\n\tdefinition: GraphQLField<unknown, unknown>,\n\targs: readonly ArgumentNode[] | undefined,\n): number {\n\tconst profile = profileOf(cost, parent, definition);\n\tlet size: number | undefined;\n\tlet given = false;\n\tcost.sizeArguments.forEach((name, index) => {\n\t\tconst node = args?.find((arg) => arg.name.value === name);\n\t\tif (node) given = true;\n\t\tconst said = argumentSize(cost, profile, index, node);\n\t\tif (said !== undefined) size = Math.max(size ?? 0, said);\n\t});\n\t// Nothing given: a definition without any default is sized defaultFirst.\n\tif (!given && profile.someBare) size = Math.max(size ?? 0, cost.defaultFirst);\n\treturn size ?? cost.defaultFirst;\n}\n",
13
+ "import type { GraphQLFieldResolver, GraphQLResolveInfo } from 'graphql';\nimport { z } from 'zod';\nimport { parseArgs } from './bad-user-input';\n\n/** An object schema of the arguments, or its shape. */\nexport type ArgsSchema = z.ZodType<Record<string, unknown>> | z.ZodRawShape;\n\n/** The schema `ArgsSchema` stands for. */\nexport type SchemaOf<S extends ArgsSchema> = S extends z.ZodType\n\t? S\n\t: S extends z.ZodRawShape\n\t\t? // Mapped, not `S & z.ZodRawShape`: the intersection's index signature\n\t\t\t// would type every argument `unknown`.\n\t\t\tz.ZodObject<{ [K in keyof S]: S[K] }>\n\t\t: never;\n\n/**\n * What `validated` takes: the schema, or a function that builds it for each\n * call from the request's context and the field's `info`, for checks that\n * need them (a uniqueness query in the request's database, a rule that\n * depends on the viewer).\n */\nexport type ArgsSchemaFor<S extends ArgsSchema, TContext = unknown> =\n\t| S\n\t| SchemaFactory<S, TContext>;\n\ntype SchemaFactory<S extends ArgsSchema, TContext> = (\n\tcontext: TContext,\n\tinfo: GraphQLResolveInfo,\n) => S | Promise<S>;\n\n/**\n * A resolver whose arguments are checked by `schema` before it runs, for what\n * a `@constraint` cannot say: a rule across arguments, a business refinement,\n * an async check. It receives the parsed arguments (`z.output`), defaults and\n * transforms applied; an invalid input is the same `BAD_USER_INPUT` error as\n * the directives'.\n *\n * ```ts\n * signUp: validated(\n * z.object({ input: signUpSchema }).refine(({ input }) => input.password !== input.email),\n * (_, { input }) => users.create(input),\n * )\n * ```\n *\n * A check that needs the request takes a function in place of the schema:\n * it is called on each call, with the context and `info`, and returns the\n * schema (or a promise of it). What it throws reaches the client as it is,\n * not as `BAD_USER_INPUT`.\n *\n * ```ts\n * rename: validated(\n * (ctx: Context) => ({\n * name: z.string().refine(async (name) => !(await ctx.db.users.exists({ name })), 'taken'),\n * }),\n * (_, { name }, ctx) => ctx.db.users.rename(ctx.viewer, name),\n * )\n * ```\n */\nexport function validated<\n\tS extends ArgsSchema,\n\tTSource = unknown,\n\tTContext = unknown,\n\tTResult = unknown,\n>(\n\tschema: SchemaFactory<S, TContext>,\n\tresolve: (\n\t\tsource: TSource,\n\t\targs: z.output<SchemaOf<S>>,\n\t\tcontext: TContext,\n\t\tinfo: GraphQLResolveInfo,\n\t) => TResult,\n): GraphQLFieldResolver<\n\tTSource,\n\tTContext,\n\tz.input<SchemaOf<S>>,\n\tPromise<Awaited<TResult>>\n>;\nexport function validated<\n\tS extends ArgsSchema,\n\tTSource = unknown,\n\tTContext = unknown,\n\tTResult = unknown,\n>(\n\tschema: S,\n\tresolve: (\n\t\tsource: TSource,\n\t\targs: z.output<SchemaOf<S>>,\n\t\tcontext: TContext,\n\t\tinfo: GraphQLResolveInfo,\n\t) => TResult,\n): GraphQLFieldResolver<\n\tTSource,\n\tTContext,\n\tz.input<SchemaOf<S>>,\n\tPromise<Awaited<TResult>>\n>;\nexport function validated<\n\tS extends ArgsSchema,\n\tTSource = unknown,\n\tTContext = unknown,\n\tTResult = unknown,\n>(\n\tschema: ArgsSchemaFor<S, TContext>,\n\tresolve: (\n\t\tsource: TSource,\n\t\targs: z.output<SchemaOf<S>>,\n\t\tcontext: TContext,\n\t\tinfo: GraphQLResolveInfo,\n\t) => TResult,\n): GraphQLFieldResolver<\n\tTSource,\n\tTContext,\n\tz.input<SchemaOf<S>>,\n\tPromise<Awaited<TResult>>\n>;\nexport function validated<\n\tS extends ArgsSchema,\n\tTSource = unknown,\n\tTContext = unknown,\n\tTResult = unknown,\n>(\n\tschema: ArgsSchemaFor<S, TContext>,\n\tresolve: (\n\t\tsource: TSource,\n\t\targs: z.output<SchemaOf<S>>,\n\t\tcontext: TContext,\n\t\tinfo: GraphQLResolveInfo,\n\t) => TResult,\n): GraphQLFieldResolver<\n\tTSource,\n\tTContext,\n\tz.input<SchemaOf<S>>,\n\tPromise<Awaited<TResult>>\n> {\n\tconst fixed = typeof schema === 'function' ? undefined : zodOf(schema);\n\treturn async (source, args, context, info): Promise<Awaited<TResult>> => {\n\t\tconst where = `${info.parentType.name}.${info.fieldName}`;\n\t\tconst checked =\n\t\t\tfixed ??\n\t\t\tzodOf(await (schema as SchemaFactory<S, TContext>)(context, info));\n\t\tconst parsed = (await parseArgs(checked, args, where)) as z.output<\n\t\t\tSchemaOf<S>\n\t\t>;\n\t\treturn await resolve(source, parsed, context, info);\n\t};\n}\n\n/** The schema itself, or the object schema of a shape. */\nfunction zodOf(schema: ArgsSchema): z.ZodType {\n\t// `_zod`, not `instanceof`: a schema from another copy of zod is still one.\n\treturn (\n\t\t'_zod' in schema ? schema : z.object(schema as z.ZodRawShape)\n\t) as z.ZodType;\n}\n",
14
+ "import {\n\tdefaultFieldResolver,\n\ttype GraphQLField,\n\ttype GraphQLFieldResolver,\n\ttype GraphQLSchema,\n} from 'graphql';\nimport type { z } from 'zod';\nimport { type ConstraintOf, parseArgs } from './bad-user-input';\nimport { checkConstraints } from './builder/check-constraints';\nimport type { FormatSchemas, OwnFormats } from './formats/registry';\nimport { constraintOf } from './rules';\n\n// Symbol.for: two copies of the package in one tree still wrap a field once.\nconst wrapped = Symbol.for('@nxgt/graphql-validation/wrapped');\n// The formats a schema was wrapped with, kept on the schema itself.\nconst wrappedWith = Symbol.for('@nxgt/graphql-validation/formats');\n\n/** What `withValidation` takes besides the schema. */\nexport interface WithValidationOptions<\n\tF extends FormatSchemas = FormatSchemas,\n> {\n\t/**\n\t * The application's own formats, which `@constraint(format: \"...\")` may\n\t * name beside the built-in ones: one Zod string schema each, keyed by its\n\t * name (lowercase letters, digits and hyphens). A built-in name is a type\n\t * error, and refused at startup.\n\t */\n\treadonly formats?: OwnFormats<F>;\n}\n\ntype Resolver = GraphQLFieldResolver<unknown, unknown> & { [wrapped]?: true };\n\nfunction checking(\n\tschema: z.ZodType,\n\twhere: string,\n\tresolve: Resolver,\n\tconstraintOf: ConstraintOf,\n): Resolver {\n\tconst check: Resolver = async (source, args, context, info) =>\n\t\tawait resolve(\n\t\t\tsource,\n\t\t\tawait parseArgs(schema, args, where, constraintOf),\n\t\t\tcontext,\n\t\t\tinfo,\n\t\t);\n\tcheck[wrapped] = true;\n\treturn check;\n}\n\n/**\n * Wraps a field once. A subscription field is checked in `subscribe`, which\n * runs once per subscription — graphql's default one when the field has none\n * — and its `resolve` runs once per event, with the same arguments, already\n * checked.\n */\nfunction wrap(\n\tfield: GraphQLField<unknown, unknown>,\n\targs: z.ZodType,\n\twhere: string,\n\tsubscription: boolean,\n\tconstraintOf: ConstraintOf,\n): void {\n\tconst subscribe = (field.subscribe ??\n\t\t(subscription ? defaultFieldResolver : undefined)) as Resolver | undefined;\n\tif (subscribe) {\n\t\tif (!subscribe[wrapped])\n\t\t\tfield.subscribe = checking(args, where, subscribe, constraintOf);\n\t\treturn;\n\t}\n\tconst resolve = (field.resolve ?? defaultFieldResolver) as Resolver;\n\tif (!resolve[wrapped])\n\t\tfield.resolve = checking(args, where, resolve, constraintOf);\n}\n\n/**\n * Checks every `@constraint` of `schema` before the resolvers run. Each\n * field with a constrained argument — directly, or anywhere inside an input\n * type it takes — gets its resolver (and its `subscribe`) wrapped: the\n * arguments are parsed by the Zod schema the directives describe, the\n * resolver receives the parsed value, and an invalid input becomes one\n * `BAD_USER_INPUT` error. Fields with nothing to check are left untouched.\n *\n * The schema is built here, once: a constraint that cannot apply (a\n * `minLength` on an `Int`, an unknown format, a bad pattern) throws now, not\n * on the first request. The resolvers are wrapped in place and the same\n * schema is returned, so it goes wherever it went before; calling it twice\n * wraps nothing twice. Call it last, once every resolver is attached: a\n * resolver set on a field afterwards replaces the check.\n *\n * A `@constraint` on an interface's argument must be repeated on each\n * object's field, which is the one that resolves; a field that drops it\n * fails here.\n *\n * The directives are read from the SDL (`astNode`), so a schema built from\n * type definitions — `buildSchema`, `makeExecutableSchema`, Yoga, Apollo —\n * is checked; a code-first schema with no SDL has no `@constraint` to read.\n *\n * `options.formats` adds the application's own formats; wrapping a schema\n * again throws unless the record has the same names, each the very same\n * schema (no formats after some, or some after none, throws too), since its\n * fields are already checked against the first ones.\n */\nexport function withValidation<\n\tS extends GraphQLSchema,\n\t// biome-ignore lint/complexity/noBannedTypes: no formats of its own by default\n\tconst F extends FormatSchemas = {},\n>(schema: S, options: WithValidationOptions<F> = {}): S {\n\tconst formats: FormatSchemas = options.formats ?? {};\n\tconst holder = schema as unknown as { [wrappedWith]?: FormatSchemas };\n\tconst before = holder[wrappedWith];\n\tif (before && !sameFormats(before, formats)) {\n\t\tthrow new Error(\n\t\t\t'withValidation: this schema is already wrapped with other formats. Call withValidation once, with every format.',\n\t\t);\n\t}\n\tconst directive = checkConstraints(\n\t\tschema,\n\t\t(type, field, args, declared) => {\n\t\t\tconst subscription = type === schema.getSubscriptionType();\n\t\t\t// The rule that refused, with the value this field's SDL declares at the path.\n\t\t\tconst named: ConstraintOf = (issue) => {\n\t\t\t\tconst argument = constraintOf(issue);\n\t\t\t\tif (!argument) return undefined;\n\t\t\t\t// Found: the SDL carries the constraints (interfaces repeat theirs,\n\t\t\t\t// assertInterfaceConstraintsKept), so a miss drops `constraint` by design.\n\t\t\t\tconst found = declared(issue.path).find(\n\t\t\t\t\t({ rule }) => rule.argument === argument,\n\t\t\t\t);\n\t\t\t\treturn found && { argument, value: found.value };\n\t\t\t};\n\t\t\twrap(field, args, `${type.name}.${field.name}`, subscription, named);\n\t\t},\n\t\tformats,\n\t);\n\tif (!directive) {\n\t\tthrow new Error(\n\t\t\t'withValidation: this schema declares no @constraint directive. Add constraintTypeDefs to its type definitions.',\n\t\t);\n\t}\n\tif (!before) Object.defineProperty(schema, wrappedWith, { value: formats });\n\treturn schema;\n}\n\n/** The same names, each the very same schema. */\nfunction sameFormats(a: FormatSchemas, b: FormatSchemas): boolean {\n\tconst names = Object.keys(a);\n\treturn (\n\t\tnames.length === Object.keys(b).length &&\n\t\tnames.every((name) => Object.hasOwn(b, name) && a[name] === b[name])\n\t);\n}\n"
10
15
  ],
11
- "mappings": "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",
12
- "debugId": "BC885DEBB67481A464756E2164756E21",
16
+ "mappings": "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",
17
+ "debugId": "E43868C11AE8F6A464756E2164756E21",
13
18
  "names": []
14
19
  }
@@ -0,0 +1,9 @@
1
+ import type { OperationDefinitionNode } from 'graphql';
2
+ /** `Operation "Name"`, or `Operation` for an anonymous one. */
3
+ export declare function operationLabel(operation: OperationDefinitionNode): string;
4
+ /**
5
+ * Throws a `RangeError` unless `value` is an integer from `min` up to, and
6
+ * excluding, `max` (default: `Number.MAX_SAFE_INTEGER`, where a cost is clamped).
7
+ */
8
+ export declare function assertInteger(option: string, value: number, min: number, max?: number): void;
9
+ //# sourceMappingURL=describe.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"describe.d.ts","sourceRoot":"","sources":["../../src/limits/describe.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAC;AAEvD,+DAA+D;AAC/D,wBAAgB,cAAc,CAAC,SAAS,EAAE,uBAAuB,GAAG,MAAM,CAEzE;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAC5B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EACX,GAAG,SAA0B,GAC3B,IAAI,CAMN"}
@@ -0,0 +1,12 @@
1
+ import { type GraphQLField, type GraphQLSchema } from 'graphql';
2
+ /** The meta-fields that read the schema; `__typename` is not one. */
3
+ export declare function isIntrospectionRoot(name: string): boolean;
4
+ /** The definition of `__schema` or `__type`, selected on the query root. */
5
+ export declare function introspectionRoot(name: string): GraphQLField<unknown, unknown> | undefined;
6
+ /**
7
+ * The most items the introspection list `parent.field` can hold in `schema`:
8
+ * the number of types for `__Schema.types`, else the largest list anywhere in
9
+ * the schema. Not `defaultFirst`: a query asks no size of them.
10
+ */
11
+ export declare function introspectionSize(schema: GraphQLSchema, field: string): number;
12
+ //# sourceMappingURL=introspection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"introspection.d.ts","sourceRoot":"","sources":["../../src/limits/introspection.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,YAAY,EAEjB,KAAK,aAAa,EAQlB,MAAM,SAAS,CAAC;AAEjB,qEAAqE;AACrE,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED,4EAA4E;AAC5E,wBAAgB,iBAAiB,CAChC,IAAI,EAAE,MAAM,GACV,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,GAAG,SAAS,CAI5C;AA+CD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAChC,MAAM,EAAE,aAAa,EACrB,KAAK,EAAE,MAAM,GACX,MAAM,CAER"}
@@ -0,0 +1,15 @@
1
+ import { type ArgumentNode, type GraphQLField, type GraphQLNamedType, type GraphQLSchema } from 'graphql';
2
+ /** What sizing a list needs: the schema and the options of the rule. */
3
+ export interface SizeContext {
4
+ schema: GraphQLSchema;
5
+ sizeArguments: readonly string[];
6
+ defaultFirst: number;
7
+ }
8
+ /**
9
+ * The size of the list `definition` returns on `parent`, as selected by
10
+ * `args`: the largest its size arguments say, and `defaultFirst` when none
11
+ * says anything. The schema's part is memoized, so a selection costs
12
+ * `sizeArguments.length` steps whatever the number of possible types.
13
+ */
14
+ export declare function listSize(cost: SizeContext, parent: GraphQLNamedType | undefined, definition: GraphQLField<unknown, unknown>, args: readonly ArgumentNode[] | undefined): number;
15
+ //# sourceMappingURL=list-size.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-size.d.ts","sourceRoot":"","sources":["../../src/limits/list-size.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAGlB,MAAM,SAAS,CAAC;AAKjB,wEAAwE;AACxE,MAAM,WAAW,WAAW;IAC3B,MAAM,EAAE,aAAa,CAAC;IACtB,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,YAAY,EAAE,MAAM,CAAC;CACrB;AA4ID;;;;;GAKG;AACH,wBAAgB,QAAQ,CACvB,IAAI,EAAE,WAAW,EACjB,MAAM,EAAE,gBAAgB,GAAG,SAAS,EACpC,UAAU,EAAE,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,EAC1C,IAAI,EAAE,SAAS,YAAY,EAAE,GAAG,SAAS,GACvC,MAAM,CAaR"}
@@ -0,0 +1,28 @@
1
+ import { type ValidationRule } from 'graphql';
2
+ /** Options of {@link maxDepth}. */
3
+ export interface MaxDepthOptions {
4
+ /** The deepest nesting of field selections an operation may have (at least 1). */
5
+ depth: number;
6
+ /**
7
+ * Do not count `__schema` and `__type` (default `false`). Only where
8
+ * introspection is disabled or the client is trusted, e.g. GraphiQL in
9
+ * development: the standard introspection query (`getIntrospectionQuery()`) is 15 levels deep.
10
+ */
11
+ ignoreIntrospection?: boolean;
12
+ }
13
+ /**
14
+ * A graphql-js validation rule refusing an operation nested deeper than
15
+ * `depth` fields: a top-level field is depth 1.
16
+ *
17
+ * Named fragments are followed (each measured once), inline fragments add no
18
+ * depth, and `__typename` does not count. One `GraphQLError` per
19
+ * operation, with `extensions: { code: 'QUERY_TOO_DEEP', depth, limit }`,
20
+ * `depth` being the operation's real depth.
21
+ *
22
+ * ```ts
23
+ * validate(schema, document, [...specifiedRules, maxDepth({ depth: 8 })]);
24
+ * // graphql-yoga: onValidate: ({ addValidationRule }) => addValidationRule(maxDepth({ depth: 8 }))
25
+ * ```
26
+ */
27
+ export declare function maxDepth(options: MaxDepthOptions): ValidationRule;
28
+ //# sourceMappingURL=max-depth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"max-depth.d.ts","sourceRoot":"","sources":["../../src/limits/max-depth.ts"],"names":[],"mappings":"AAAA,OAAO,EAKN,KAAK,cAAc,EACnB,MAAM,SAAS,CAAC;AAIjB,mCAAmC;AACnC,MAAM,WAAW,eAAe;IAC/B,kFAAkF;IAClF,KAAK,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC9B;AA8CD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,cAAc,CA4BjE"}
@@ -0,0 +1,62 @@
1
+ import { type ValidationRule } from 'graphql';
2
+ /** Options of {@link maxListCost}. */
3
+ export interface MaxListCostOptions {
4
+ /** The most an operation may cost (at least 0). */
5
+ budget: number;
6
+ /** The size of a list field whose size cannot be read (an integer of at least 0). */
7
+ defaultFirst: number;
8
+ /**
9
+ * The argument names that size a list. Each one given, or defaulted in the
10
+ * SDL, says a size (an Int, a canonical-integer string or an integral Float)
11
+ * and the largest wins. Default `['first', 'last', 'limit']`.
12
+ */
13
+ sizeArguments?: readonly string[];
14
+ /**
15
+ * Do not cost `__schema` and `__type` (default `false`). Only where
16
+ * introspection is disabled or the client is trusted, e.g. GraphiQL in
17
+ * development: the standard introspection query is costly (on the order of
18
+ * 200,000 on a one-field schema).
19
+ */
20
+ ignoreIntrospection?: boolean;
21
+ }
22
+ /**
23
+ * A graphql-js validation rule refusing an operation whose cost is more than
24
+ * `budget`, to stop a client from exploiting list cycles (`Folder.items`,
25
+ * `Item.folder`, `Folder.items`, …) for a cost growing exponentially.
26
+ *
27
+ * The cost of an operation is the sum, over every selected field, of the
28
+ * product of the sizes of the list fields enclosing it: a field costs 1, and a
29
+ * list field multiplies the cost of its sub-selection by its size.
30
+ * `__typename` costs nothing. `__schema` and `__type` are costed like any
31
+ * field, their lists sized by the schema itself (`__Schema.types` is the number
32
+ * of types, the other lists the longest list anywhere in the schema), unless
33
+ * `ignoreIntrospection` is set.
34
+ *
35
+ * The size of a list field is the largest size its `sizeArguments` (default
36
+ * `first`, `last`, `limit`) say. A literal Int, a String holding a canonical
37
+ * integer (`"1000"`) or an integral Float (`1e3`) of at least 0 says that
38
+ * number. Anything else (a negative literal, a variable, since validation has
39
+ * no variable values) says the argument's SDL default when it has a usable one,
40
+ * `defaultFirst` otherwise; an argument not given says its SDL default, or
41
+ * nothing. When nothing is said the size is `defaultFirst`. On an interface the
42
+ * largest default over its possible types is used. Hence no subtree ever costs
43
+ * less than nothing: a negative `first` on one field cannot cancel the cost of
44
+ * its sibling. A field whose type (once unwrapped from non-null) is a list is
45
+ * one list, nested `[[X]]` included.
46
+ *
47
+ * Named fragments are followed, each costed once. Inline fragments and
48
+ * fragments on an abstract type are summed branch by branch, so the cost of a
49
+ * query on an interface or a union is overestimated, never underestimated.
50
+ *
51
+ * One `GraphQLError` per operation, with
52
+ * `extensions: { code: 'QUERY_TOO_COSTLY', cost, limit }`. `cost` is exact up
53
+ * to `Number.MAX_SAFE_INTEGER`, which it never exceeds.
54
+ *
55
+ * ```ts
56
+ * const rule = maxListCost({ budget: 10_000, defaultFirst: 50 });
57
+ * validate(schema, document, [...specifiedRules, rule]);
58
+ * // graphql-yoga: onValidate: ({ addValidationRule }) => addValidationRule(rule)
59
+ * ```
60
+ */
61
+ export declare function maxListCost(options: MaxListCostOptions): ValidationRule;
62
+ //# sourceMappingURL=max-list-cost.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"max-list-cost.d.ts","sourceRoot":"","sources":["../../src/limits/max-list-cost.ts"],"names":[],"mappings":"AAAA,OAAO,EAcN,KAAK,cAAc,EACnB,MAAM,SAAS,CAAC;AASjB,sCAAsC;AACtC,MAAM,WAAW,kBAAkB;IAClC,mDAAmD;IACnD,MAAM,EAAE,MAAM,CAAC;IACf,qFAAqF;IACrF,YAAY,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAuGD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,cAAc,CA+CvE"}
@@ -3,7 +3,17 @@ import { z } from 'zod';
3
3
  /** An object schema of the arguments, or its shape. */
4
4
  export type ArgsSchema = z.ZodType<Record<string, unknown>> | z.ZodRawShape;
5
5
  /** The schema `ArgsSchema` stands for. */
6
- export type SchemaOf<S extends ArgsSchema> = S extends z.ZodType ? S : z.ZodObject<S & z.ZodRawShape>;
6
+ export type SchemaOf<S extends ArgsSchema> = S extends z.ZodType ? S : S extends z.ZodRawShape ? z.ZodObject<{
7
+ [K in keyof S]: S[K];
8
+ }> : never;
9
+ /**
10
+ * What `validated` takes: the schema, or a function that builds it for each
11
+ * call from the request's context and the field's `info`, for checks that
12
+ * need them (a uniqueness query in the request's database, a rule that
13
+ * depends on the viewer).
14
+ */
15
+ export type ArgsSchemaFor<S extends ArgsSchema, TContext = unknown> = S | SchemaFactory<S, TContext>;
16
+ type SchemaFactory<S extends ArgsSchema, TContext> = (context: TContext, info: GraphQLResolveInfo) => S | Promise<S>;
7
17
  /**
8
18
  * A resolver whose arguments are checked by `schema` before it runs, for what
9
19
  * a `@constraint` cannot say: a rule across arguments, a business refinement,
@@ -17,6 +27,23 @@ export type SchemaOf<S extends ArgsSchema> = S extends z.ZodType ? S : z.ZodObje
17
27
  * (_, { input }) => users.create(input),
18
28
  * )
19
29
  * ```
30
+ *
31
+ * A check that needs the request takes a function in place of the schema:
32
+ * it is called on each call, with the context and `info`, and returns the
33
+ * schema (or a promise of it). What it throws reaches the client as it is,
34
+ * not as `BAD_USER_INPUT`.
35
+ *
36
+ * ```ts
37
+ * rename: validated(
38
+ * (ctx: Context) => ({
39
+ * name: z.string().refine(async (name) => !(await ctx.db.users.exists({ name })), 'taken'),
40
+ * }),
41
+ * (_, { name }, ctx) => ctx.db.users.rename(ctx.viewer, name),
42
+ * )
43
+ * ```
20
44
  */
45
+ export declare function validated<S extends ArgsSchema, TSource = unknown, TContext = unknown, TResult = unknown>(schema: SchemaFactory<S, TContext>, resolve: (source: TSource, args: z.output<SchemaOf<S>>, context: TContext, info: GraphQLResolveInfo) => TResult): GraphQLFieldResolver<TSource, TContext, z.input<SchemaOf<S>>, Promise<Awaited<TResult>>>;
21
46
  export declare function validated<S extends ArgsSchema, TSource = unknown, TContext = unknown, TResult = unknown>(schema: S, resolve: (source: TSource, args: z.output<SchemaOf<S>>, context: TContext, info: GraphQLResolveInfo) => TResult): GraphQLFieldResolver<TSource, TContext, z.input<SchemaOf<S>>, Promise<Awaited<TResult>>>;
47
+ export declare function validated<S extends ArgsSchema, TSource = unknown, TContext = unknown, TResult = unknown>(schema: ArgsSchemaFor<S, TContext>, resolve: (source: TSource, args: z.output<SchemaOf<S>>, context: TContext, info: GraphQLResolveInfo) => TResult): GraphQLFieldResolver<TSource, TContext, z.input<SchemaOf<S>>, Promise<Awaited<TResult>>>;
48
+ export {};
22
49
  //# sourceMappingURL=validated.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"validated.d.ts","sourceRoot":"","sources":["../src/validated.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AACxE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,uDAAuD;AACvD,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,WAAW,CAAC;AAE5E,0CAA0C;AAC1C,MAAM,MAAM,QAAQ,CAAC,CAAC,SAAS,UAAU,IAAI,CAAC,SAAS,CAAC,CAAC,OAAO,GAC7D,CAAC,GACD,CAAC,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,WAAW,CAAC,CAAC;AAElC;;;;;;;;;;;;;GAaG;AACH,wBAAgB,SAAS,CACxB,CAAC,SAAS,UAAU,EACpB,OAAO,GAAG,OAAO,EACjB,QAAQ,GAAG,OAAO,EAClB,OAAO,GAAG,OAAO,EAEjB,MAAM,EAAE,CAAC,EACT,OAAO,EAAE,CACR,MAAM,EAAE,OAAO,EACf,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAC3B,OAAO,EAAE,QAAQ,EACjB,IAAI,EAAE,kBAAkB,KACpB,OAAO,GACV,oBAAoB,CACtB,OAAO,EACP,QAAQ,EACR,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EACpB,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CACzB,CAYA"}
1
+ {"version":3,"file":"validated.d.ts","sourceRoot":"","sources":["../src/validated.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"with-validation.d.ts","sourceRoot":"","sources":["../src/with-validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAIN,KAAK,aAAa,EAClB,MAAM,SAAS,CAAC;AAIjB,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAQpE,sDAAsD;AACtD,MAAM,WAAW,qBAAqB,CACrC,CAAC,SAAS,aAAa,GAAG,aAAa;IAEvC;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;CACjC;AA0CD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,cAAc,CAC7B,CAAC,SAAS,aAAa,EAEvB,KAAK,CAAC,CAAC,SAAS,aAAa,GAAG,EAAE,EACjC,MAAM,EAAE,CAAC,EAAE,OAAO,GAAE,qBAAqB,CAAC,CAAC,CAAM,GAAG,CAAC,CAwBtD"}
1
+ {"version":3,"file":"with-validation.d.ts","sourceRoot":"","sources":["../src/with-validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAIN,KAAK,aAAa,EAClB,MAAM,SAAS,CAAC;AAIjB,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAQpE,sDAAsD;AACtD,MAAM,WAAW,qBAAqB,CACrC,CAAC,SAAS,aAAa,GAAG,aAAa;IAEvC;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;CACjC;AA8CD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,cAAc,CAC7B,CAAC,SAAS,aAAa,EAEvB,KAAK,CAAC,CAAC,SAAS,aAAa,GAAG,EAAE,EACjC,MAAM,EAAE,CAAC,EAAE,OAAO,GAAE,qBAAqB,CAAC,CAAC,CAAM,GAAG,CAAC,CAmCtD"}
package/docs/README.md CHANGED
@@ -6,6 +6,7 @@
6
6
  | --- | --- |
7
7
  | [Constraints](guide/constraints.md) | you write `@constraint` in your schema: setup with `withValidation`, every argument and its Zod equivalent, the formats and your own, lists and nested inputs |
8
8
  | [Answering invalid input as one error](guide/invalid-input.md) | your API answers invalid input as one 400 error with a list of fields (`invalidInputError`, `fieldIssueOf` for a Zod parse), or a refusal such as a 409 names the fields at fault (`fieldsError`) |
9
+ | [Limiting the depth and cost of a query](guide/query-limits.md) | a schema has list cycles and you want to refuse a query nested too deep or too costly (`maxDepth`, `maxListCost`), with graphql-js `validate` or graphql-yoga |
9
10
  | [Errors](guide/errors.md) | you handle the `BAD_USER_INPUT` error in a client, build it yourself with `badUserInput`, or add rules a directive cannot say with `validated` |
10
11
 
11
12
  ## Reference
@@ -313,11 +313,11 @@ What a format of your own is:
313
313
  - **Its messages are yours.** A refusal reads as your schema writes it (the
314
314
  package's own messages never name the value; yours may, so keep the input
315
315
  out of them if your logs or clients should not see it). Every issue your
316
- schema raises carries `constraint: "format"`, whatever its Zod `code` — a
317
- `.regex()` inside your format is the format's refusal, not `pattern`'s:
316
+ schema raises carries `constraint: "format"` and `value` the format's name, whatever
317
+ its Zod `code` — a `.regex()` inside your format is the format's refusal, not `pattern`'s:
318
318
 
319
319
  ```json
320
- { "path": ["input", "siret"], "message": "Invalid SIRET: write its 14 digits", "code": "invalid_format", "constraint": "format" }
320
+ { "path": ["input", "siret"], "message": "Invalid SIRET: write its 14 digits", "code": "invalid_format", "constraint": "format", "value": "siret" }
321
321
  ```
322
322
 
323
323
  - **Named in lowercase letters, digits and hyphens**, starting with a letter
@@ -24,9 +24,9 @@ An invalid input is **one** `GraphQLError`, thrown before your resolver runs:
24
24
  "extensions": {
25
25
  "code": "BAD_USER_INPUT",
26
26
  "issues": [
27
- { "path": ["input", "email"], "message": "Invalid email address", "code": "invalid_format", "constraint": "format" },
28
- { "path": ["input", "name"], "message": "Too small: expected string to have >=2 characters", "code": "too_small", "constraint": "minLength" },
29
- { "path": ["input", "tags"], "message": "Too big: expected array to have <=2 items", "code": "too_big", "constraint": "maxItems" }
27
+ { "path": ["input", "email"], "message": "Invalid email address", "code": "invalid_format", "constraint": "format", "value": "email" },
28
+ { "path": ["input", "name"], "message": "Too small: expected string to have >=2 characters", "code": "too_small", "constraint": "minLength", "value": 2 },
29
+ { "path": ["input", "tags"], "message": "Too big: expected array to have <=2 items", "code": "too_big", "constraint": "maxItems", "value": 2 }
30
30
  ]
31
31
  }
32
32
  }
@@ -48,6 +48,13 @@ meant for display in every language: map on `constraint` and `path` if you
48
48
  translate. Prefer `constraint` to `code`: it is the name in your schema, while
49
49
  `code` is Zod's and can change when Zod does across a major version.
50
50
 
51
+ `value` is what that argument was declared with, exactly as written: `100` for
52
+ `maxLength: 100`, `"^[0-9]{5}$"` for a `pattern`, `"email"` for
53
+ `format: "email"`. A client can say "at most 100 characters" from
54
+ `constraint` and `value` without parsing `message`. It is present exactly when
55
+ `constraint` is, so a refusal of a [`validated`](#validated) schema has
56
+ neither.
57
+
51
58
  ### Types
52
59
 
53
60
  ```ts
@@ -57,6 +64,8 @@ interface ValidationIssue {
57
64
  readonly code: string;
58
65
  /** The `@constraint` argument that refused; absent for `validated`'s own schema. */
59
66
  readonly constraint?: ConstraintArgument;
67
+ /** What that argument was declared with, as written; present exactly when `constraint` is. */
68
+ readonly value?: string | number;
60
69
  }
61
70
 
62
71
  type ConstraintArgument =
@@ -162,17 +171,82 @@ const claim = validated(
162
171
  );
163
172
  ```
164
173
 
174
+ ### A schema that reads the context
175
+
176
+ A check that needs the request (a uniqueness query in the request's database, a
177
+ rule that depends on the viewer) takes a function in place of the schema. It
178
+ receives the GraphQL context and the field's `info`, and returns the schema or
179
+ its shape, or a promise of either.
180
+
181
+ ```ts
182
+ import { validated } from '@nxgt/graphql-validation';
183
+ import { z } from 'zod';
184
+
185
+ type Context = {
186
+ viewer: { id: string; role: 'member' | 'admin' };
187
+ db: {
188
+ users: {
189
+ exists(filter: { name: string }): Promise<boolean>;
190
+ rename(id: string, name: string): Promise<unknown>;
191
+ };
192
+ };
193
+ };
194
+
195
+ // type Mutation { rename(name: String!, reason: String): User }
196
+ const rename = validated(
197
+ (ctx: Context) => ({
198
+ name: z
199
+ .string()
200
+ .min(3)
201
+ .refine(async (name) => !(await ctx.db.users.exists({ name })), 'already taken'),
202
+ // a rule that depends on the viewer
203
+ reason: ctx.viewer.role === 'admin' ? z.string().min(1) : z.string().optional(),
204
+ }),
205
+ (_, { name }, ctx) => ctx.db.users.rename(ctx.viewer.id, name),
206
+ );
207
+ ```
208
+
209
+ - The function runs **on each call**, before the arguments are parsed; a fixed
210
+ schema is still built once, up front.
211
+ - Its result is parsed exactly like a fixed schema, with the same
212
+ `BAD_USER_INPUT` error.
213
+ - What the function **throws** reaches the client as it is, not as
214
+ `BAD_USER_INPUT`: throw your own error for a missing session, say.
215
+ - On a field with both `@constraint` and a `validated` function, the directives
216
+ run first (`withValidation` wraps the field's resolver, which is the
217
+ `validated` one); then the function is called and its schema checks the
218
+ arguments.
219
+ - Annotate the function's `ctx` parameter: that is where the resolver's context
220
+ type comes from, and the arguments' types come from what the function returns.
221
+
222
+ The declared signature (the third overload takes `ArgsSchemaFor<S, TContext>`,
223
+ the schema or that function, for a helper that forwards either):
224
+
165
225
  ```ts
166
226
  import type { GraphQLFieldResolver, GraphQLResolveInfo } from 'graphql';
167
227
  import type { z } from 'zod';
168
228
 
169
229
  type ArgsSchema = z.ZodType<Record<string, unknown>> | z.ZodRawShape;
170
- type SchemaOf<S extends ArgsSchema> = S extends z.ZodType ? S : z.ZodObject<S & z.ZodRawShape>;
230
+ type SchemaOf<S extends ArgsSchema> = S extends z.ZodType
231
+ ? S
232
+ : S extends z.ZodRawShape
233
+ ? z.ZodObject<{ [K in keyof S]: S[K] }>
234
+ : never;
235
+ type SchemaFactory<S extends ArgsSchema, TContext> = (context: TContext, info: GraphQLResolveInfo) => S | Promise<S>;
236
+ type ArgsSchemaFor<S extends ArgsSchema, TContext = unknown> = S | SchemaFactory<S, TContext>;
171
237
 
238
+ declare function validated<S extends ArgsSchema, TSource = unknown, TContext = unknown, TResult = unknown>(
239
+ schema: SchemaFactory<S, TContext>,
240
+ resolve: (source: TSource, args: z.output<SchemaOf<S>>, context: TContext, info: GraphQLResolveInfo) => TResult,
241
+ ): GraphQLFieldResolver<TSource, TContext, z.input<SchemaOf<S>>, Promise<Awaited<TResult>>>;
172
242
  declare function validated<S extends ArgsSchema, TSource = unknown, TContext = unknown, TResult = unknown>(
173
243
  schema: S,
174
244
  resolve: (source: TSource, args: z.output<SchemaOf<S>>, context: TContext, info: GraphQLResolveInfo) => TResult,
175
245
  ): GraphQLFieldResolver<TSource, TContext, z.input<SchemaOf<S>>, Promise<Awaited<TResult>>>;
246
+ declare function validated<S extends ArgsSchema, TSource = unknown, TContext = unknown, TResult = unknown>(
247
+ schema: ArgsSchemaFor<S, TContext>,
248
+ resolve: (source: TSource, args: z.output<SchemaOf<S>>, context: TContext, info: GraphQLResolveInfo) => TResult,
249
+ ): GraphQLFieldResolver<TSource, TContext, z.input<SchemaOf<S>>, Promise<Awaited<TResult>>>;
176
250
  ```
177
251
 
178
252
  `validated` validates whatever the field's arguments are; it does not need