@nxgt/graphql-validation 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +73 -6
- package/dist/bad-user-input.d.ts +17 -2
- package/dist/bad-user-input.d.ts.map +1 -1
- package/dist/builder/check-constraints.d.ts +4 -2
- package/dist/builder/check-constraints.d.ts.map +1 -1
- package/dist/builder/declared.d.ts +12 -0
- package/dist/builder/declared.d.ts.map +1 -0
- package/dist/chunks/{index-xcaf9kes.js → index-atwkcfg3.js} +5 -5
- package/dist/chunks/{index-xcaf9kes.js.map → index-atwkcfg3.js.map} +2 -2
- package/dist/chunks/{index-twevz7yc.js → index-w9pw7fsk.js} +68 -34
- package/dist/chunks/{index-twevz7yc.js.map → index-w9pw7fsk.js.map} +6 -5
- package/dist/cli.js +1 -1
- package/dist/codegen.js +2 -2
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +497 -10
- package/dist/index.js.map +13 -5
- package/dist/limits/cost-context.d.ts +26 -0
- package/dist/limits/cost-context.d.ts.map +1 -0
- package/dist/limits/describe.d.ts +9 -0
- package/dist/limits/describe.d.ts.map +1 -0
- package/dist/limits/introspection.d.ts +12 -0
- package/dist/limits/introspection.d.ts.map +1 -0
- package/dist/limits/list-size.d.ts +23 -0
- package/dist/limits/list-size.d.ts.map +1 -0
- package/dist/limits/max-depth.d.ts +28 -0
- package/dist/limits/max-depth.d.ts.map +1 -0
- package/dist/limits/max-fields.d.ts +35 -0
- package/dist/limits/max-fields.d.ts.map +1 -0
- package/dist/limits/max-list-cost.d.ts +77 -0
- package/dist/limits/max-list-cost.d.ts.map +1 -0
- package/dist/limits/pending-size.d.ts +13 -0
- package/dist/limits/pending-size.d.ts.map +1 -0
- package/dist/with-validation.d.ts.map +1 -1
- package/docs/README.md +1 -0
- package/docs/guide/constraints.md +3 -3
- package/docs/guide/errors.md +12 -3
- package/docs/guide/query-limits.md +311 -0
- package/docs/roadmap.md +9 -0
- package/docs/troubleshooting.md +73 -0
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1,14 +1,22 @@
|
|
|
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-fields.ts", "../src/limits/max-list-cost.ts", "../src/limits/cost-context.ts", "../src/limits/list-size.ts", "../src/limits/pending-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
|
|
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 {\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 SelectionSetNode,\n\ttype ValidationContext,\n\ttype ValidationRule,\n} from 'graphql';\nimport { assertInteger, operationLabel } from './describe';\nimport { isIntrospectionRoot } from './introspection';\n\n/** Options of {@link maxFields}. */\nexport interface MaxFieldsOptions {\n\t/** The most field selections an operation may have (at least 1). */\n\tlimit: 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()`)\n\t * selects 220 fields.\n\t */\n\tignoreIntrospection?: boolean;\n}\n\n/** What a walk of one document needs: what it has counted so far. */\ninterface FieldsContext {\n\tgetFragment: (name: string) => FragmentDefinitionNode | null | undefined;\n\tfragmentCounts: Map<string, number>;\n\tcounting: Set<string>;\n\tignoreIntrospection: boolean;\n}\n\n/** `a + b`, clamped where a count stops being exact. */\nfunction add(a: number, b: number): number {\n\treturn Math.min(a + b, Number.MAX_SAFE_INTEGER);\n}\n\n/** The field selections of `selectionSet`, nested ones included. */\nfunction countOf(walk: FieldsContext, selectionSet: SelectionSetNode): number {\n\tlet total = 0;\n\tfor (const selection of selectionSet.selections) {\n\t\tif (selection.kind === 'Field') {\n\t\t\tif (walk.ignoreIntrospection && isIntrospectionRoot(selection.name.value))\n\t\t\t\tcontinue;\n\t\t\ttotal = add(total, 1);\n\t\t\tif (selection.selectionSet)\n\t\t\t\ttotal = add(total, countOf(walk, selection.selectionSet));\n\t\t} else if (selection.kind === 'InlineFragment') {\n\t\t\ttotal = add(total, countOf(walk, selection.selectionSet));\n\t\t} else {\n\t\t\ttotal = add(total, fragmentCount(walk, selection.name.value));\n\t\t}\n\t}\n\treturn total;\n}\n\n/** The count of the named fragment, walked once. */\nfunction fragmentCount(walk: FieldsContext, name: string): number {\n\tconst known = walk.fragmentCounts.get(name);\n\tif (known !== undefined) return known;\n\tconst fragment = walk.getFragment(name);\n\t// A cycle is NoFragmentCyclesRule's to report; here it adds nothing.\n\tif (!fragment || walk.counting.has(name)) return 0;\n\twalk.counting.add(name);\n\tconst result = countOf(walk, fragment.selectionSet);\n\twalk.counting.delete(name);\n\twalk.fragmentCounts.set(name, result);\n\treturn result;\n}\n\n/**\n * A graphql-js validation rule refusing an operation that selects more than\n * `limit` fields: neither `maxDepth` nor `maxListCost` bounds breadth, so\n * thousands of aliases of a cheap field (or of `__typename`) pass both.\n *\n * Every field node counts 1, aliases and `__typename` included. A named\n * fragment counts at each spread (walked once), an inline fragment counts its\n * contents, and every branch of a union counts: nothing is pruned by type.\n * `@skip` and `@include` are not evaluated, so the count can be over the\n * document's field count. It counts the document, spreads expanded, not what the\n * executor runs: how often a field runs inside a list is `maxListCost`'s.\n * One `GraphQLError` per operation, with\n * `extensions: { code: 'QUERY_TOO_WIDE', fields, limit }`, `fields` being the\n * operation's real count (clamped at `Number.MAX_SAFE_INTEGER`).\n *\n * ```ts\n * validate(schema, document, [...specifiedRules, maxFields({ limit: 500 })]);\n * // graphql-yoga: onValidate: ({ addValidationRule }) => addValidationRule(maxFields({ limit: 500 }))\n * ```\n */\nexport function maxFields(options: MaxFieldsOptions): ValidationRule {\n\tconst limit = options.limit;\n\tassertInteger('maxFields: limit', limit, 1);\n\treturn (context: ValidationContext) => {\n\t\tconst walk: FieldsContext = {\n\t\t\tgetFragment: (name) => context.getFragment(name),\n\t\t\tfragmentCounts: new Map(),\n\t\t\tcounting: 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 fields = countOf(walk, operation.selectionSet);\n\t\t\t\tif (fields > 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)} selects ${fields} fields, 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_WIDE', fields, 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",
|
|
12
|
+
"import {\n\ttype FieldNode,\n\tGraphQLError,\n\ttype GraphQLField,\n\ttype GraphQLNamedType,\n\tgetNamedType,\n\tgetNullableType,\n\tisListType,\n\ttype SelectionSetNode,\n\ttype ValidationContext,\n\ttype ValidationRule,\n} from 'graphql';\nimport {\n\tadd,\n\ttype CostContext,\n\tfieldOf,\n\tmemoSize,\n\tmultiply,\n\tNO_PENDING,\n\trootType,\n} from './cost-context';\nimport { assertInteger, operationLabel } from './describe';\nimport { introspectionSize, isIntrospectionRoot } from './introspection';\nimport { statedSize } from './list-size';\nimport { listSizeUnder } from './pending-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']`. One on a\n\t * non-list field also sizes the lists declaring none directly on its return\n\t * type (a Relay connection's `edges` and `nodes`).\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/**\n * The cost of one selected field. `pending` is the size of the field whose\n * return type this selection is on: only a list declaring no size argument\n * takes it, and no field passes it on.\n */\nfunction fieldCost(\n\tcost: CostContext,\n\tparent: GraphQLNamedType | undefined,\n\tselection: FieldNode,\n\tdefinition: GraphQLField<unknown, unknown>,\n\tpending: number | undefined,\n): number {\n\tif (!selection.selectionSet) return 1;\n\tconst name = selection.name.value;\n\tconst type = getNamedType(definition.type);\n\tif (!isListType(getNullableType(definition.type))) {\n\t\t// An object field hands its own size, if it states one, to the lists\n\t\t// selected directly on it; the pending size stops here.\n\t\tconst stated = statedSize(cost, parent, definition, selection.arguments);\n\t\tconst inner = costOf(cost, selection.selectionSet, type, stated);\n\t\treturn add(1, inner);\n\t}\n\tconst inner = costOf(cost, selection.selectionSet, type, undefined);\n\tconst size = parent?.name.startsWith('__')\n\t\t? introspectionSize(cost.schema, name)\n\t\t: listSizeUnder(cost, parent, definition, selection.arguments, pending);\n\treturn add(1, multiply(inner, size));\n}\n\n/** The cost of `selectionSet` selected on `parent`, under the `pending` size of the field they are selected on. */\nfunction costOf(\n\tcost: CostContext,\n\tselectionSet: SelectionSetNode,\n\tparent: GraphQLNamedType | undefined,\n\tpending: number | 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\ttotal = add(\n\t\t\t\ttotal,\n\t\t\t\tfieldCost(cost, parent, selection, definition, pending),\n\t\t\t);\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(\n\t\t\t\ttotal,\n\t\t\t\tcostOf(cost, selection.selectionSet, condition, pending),\n\t\t\t);\n\t\t} else {\n\t\t\ttotal = add(total, fragmentCost(cost, selection.name.value, pending));\n\t\t}\n\t}\n\treturn total;\n}\n\n/** The cost of the named fragment spread under `pending`, computed once per size. */\nfunction fragmentCost(\n\tcost: CostContext,\n\tname: string,\n\tpending: number | undefined,\n): number {\n\tlet known = cost.fragmentCosts.get(name);\n\tif (!known) {\n\t\tknown = new Map();\n\t\tcost.fragmentCosts.set(name, known);\n\t}\n\tconst size = memoSize(known, pending);\n\tconst key = size ?? NO_PENDING;\n\tconst memo = known.get(key);\n\tif (memo !== undefined) return memo;\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\tsize,\n\t);\n\tcost.costing.delete(name);\n\tknown.set(key, result);\n\treturn result;\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 * A Relay connection puts the size on a field returning an object, with the\n * list below it (`items(first: 100) { edges { node { id } } }`). A field that\n * is not a list and states a size (by the same reading) hands it to the lists\n * selected directly on its return type, through inline fragments and fragment\n * spreads on that same selection set, and only to those declaring none of the\n * size arguments (`edges`, `nodes`): such a list takes it instead of\n * `defaultFirst`. A list declaring a size argument (`recent(first: Int)`)\n * reads its own, never the pending size. Crossing any other field (an object\n * field, `pageInfo`, a wrapper) ends it. A connection stating nothing hands\n * down nothing: its lists are sized `defaultFirst`.\n *\n * Named fragments are followed, each costed once per pending size (past eight\n * distinct sizes under one fragment a size is rounded up to a power of two, so\n * the work stays linear in the document and a cost only over-counts). 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\tundefined,\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",
|
|
13
|
+
"import {\n\ttype FragmentDefinitionNode,\n\ttype GraphQLField,\n\ttype GraphQLNamedType,\n\ttype GraphQLSchema,\n\tisInterfaceType,\n\tisObjectType,\n\ttype OperationDefinitionNode,\n} from 'graphql';\nimport { introspectionRoot, isIntrospectionRoot } from './introspection';\nimport type { SizeContext } from './list-size';\n\n/** Costs are plain numbers, held below this so a hostile query never reaches `Infinity`. */\nconst CEILING = Number.MAX_SAFE_INTEGER;\n\nexport const add = (a: number, b: number) => Math.min(CEILING, a + b);\nexport const 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. */\nexport interface CostContext extends SizeContext {\n\tignoreIntrospection: boolean;\n\tgetFragment: (name: string) => FragmentDefinitionNode | null | undefined;\n\tfragmentCosts: Map<string, Map<number, number>>;\n\tcosting: Set<string>;\n}\n\n/** The definition of the field `name` on `parent`, meta-fields of the query root included. */\nexport function 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 type an operation selects on. */\nexport function rootType(\n\tschema: GraphQLSchema,\n\toperation: OperationDefinitionNode,\n) {\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/** Distinct pending sizes costed exactly per fragment; further ones are rounded up. */\nconst EXACT_SIZES = 8;\n\n/** The key a fragment is memoized under: `-1` for no pending size. */\nexport const NO_PENDING = -1;\n\n/**\n * The pending size a fragment is costed under. A fragment spread under many\n * distinct sizes would be costed once per size, quadratic in a hostile\n * document; past `EXACT_SIZES` of them a new size is rounded up to a power of\n * two (a cost never lowers as a size grows, so it only over-counts, by less\n * than twice), which leaves at most `EXACT_SIZES` + 53 costings per fragment.\n */\nexport function memoSize(\n\tknown: ReadonlyMap<number, number>,\n\tpending: number | undefined,\n): number | undefined {\n\tif (pending === undefined || known.has(pending) || known.size < EXACT_SIZES) {\n\t\treturn pending;\n\t}\n\t// Math.log2 rounds near 2^k + d, so the power is checked, not trusted.\n\tlet rounded = 2 ** Math.ceil(Math.log2(Math.max(pending, 1)));\n\tif (rounded < pending) rounded *= 2;\n\treturn Math.min(CEILING, rounded);\n}\n",
|
|
14
|
+
"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\t/** Whether some definition declares any of the size arguments. */\n\tdeclares: boolean;\n\t/** Whether some definition declares none of them. */\n\tsomeUndeclared: 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\tdeclares: false,\n\t\tsomeUndeclared: 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\tif (field.args.some((arg) => cost.sizeArguments.includes(arg.name))) {\n\t\t\tprofile.declares = true;\n\t\t} else {\n\t\t\tprofile.someUndeclared = true;\n\t\t}\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 `definition` states on `parent`, as selected by `args`: the largest\n * its size arguments say, `undefined` when none says anything (none given, and\n * none declared with a default). The schema's part is memoized, so a selection\n * costs `sizeArguments.length` steps whatever the number of possible types.\n * A list uses it, and a field returning an object (a Relay connection) hands it\n * to the lists below it.\n */\nexport function statedSize(\n\tcost: SizeContext,\n\tparent: GraphQLNamedType | undefined,\n\tdefinition: GraphQLField<unknown, unknown>,\n\targs: readonly ArgumentNode[] | undefined,\n): number | undefined {\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 (size !== undefined && !given && profile.someBare) {\n\t\treturn Math.max(size, cost.defaultFirst);\n\t}\n\treturn size;\n}\n\n/**\n * Whether `definition` and the fields implementing it declare a size argument:\n * `'all'` of them, `'none'` of them, or `'some'` (an abstract parent whose\n * possible types differ).\n */\nexport function declaration(\n\tcost: SizeContext,\n\tparent: GraphQLNamedType | undefined,\n\tdefinition: GraphQLField<unknown, unknown>,\n): 'all' | 'none' | 'some' {\n\tconst { declares, someUndeclared } = profileOf(cost, parent, definition);\n\tif (!declares) return 'none';\n\treturn someUndeclared ? 'some' : 'all';\n}\n",
|
|
15
|
+
"import type { ArgumentNode, GraphQLField, GraphQLNamedType } from 'graphql';\nimport { declaration, type SizeContext, statedSize } from './list-size';\n\n/**\n * The size of the list `definition` on `parent`. `pending` is the size of the\n * field whose return type this list is selected on (a connection's `first`):\n * a list that declares none of the size arguments takes it, since the size\n * cannot be stated on the list itself. A list that declares one reads its own\n * arguments, else `defaultFirst`, and never the pending size. On an abstract\n * parent some possible types may declare one and others not: the largest of\n * both readings, since the query cannot say which comes back.\n */\nexport function listSizeUnder(\n\tcost: SizeContext,\n\tparent: GraphQLNamedType | undefined,\n\tdefinition: GraphQLField<unknown, unknown>,\n\targs: readonly ArgumentNode[] | undefined,\n\tpending: number | undefined,\n): number {\n\tconst own = () =>\n\t\tstatedSize(cost, parent, definition, args) ?? cost.defaultFirst;\n\tif (pending === undefined) return own();\n\tconst declared = declaration(cost, parent, definition);\n\tif (declared === 'none') return pending;\n\tif (declared === 'all') return own();\n\t// Mixed: a possible type declaring none takes the pending size, another reads its own.\n\treturn Math.max(pending, own());\n}\n",
|
|
8
16
|
"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",
|
|
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])
|
|
17
|
+
"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
18
|
],
|
|
11
|
-
"mappings": "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",
|
|
12
|
-
"debugId": "
|
|
19
|
+
"mappings": "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",
|
|
20
|
+
"debugId": "3B937DADAE820B8964756E2164756E21",
|
|
13
21
|
"names": []
|
|
14
22
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type FragmentDefinitionNode, type GraphQLField, type GraphQLNamedType, type GraphQLSchema, type OperationDefinitionNode } from 'graphql';
|
|
2
|
+
import type { SizeContext } from './list-size.js';
|
|
3
|
+
export declare const add: (a: number, b: number) => number;
|
|
4
|
+
export declare const multiply: (a: number, b: number) => number;
|
|
5
|
+
/** What a walk of one document needs: the options, and what it has measured so far. */
|
|
6
|
+
export interface CostContext extends SizeContext {
|
|
7
|
+
ignoreIntrospection: boolean;
|
|
8
|
+
getFragment: (name: string) => FragmentDefinitionNode | null | undefined;
|
|
9
|
+
fragmentCosts: Map<string, Map<number, number>>;
|
|
10
|
+
costing: Set<string>;
|
|
11
|
+
}
|
|
12
|
+
/** The definition of the field `name` on `parent`, meta-fields of the query root included. */
|
|
13
|
+
export declare function fieldOf(cost: CostContext, parent: GraphQLNamedType | undefined, name: string): GraphQLField<unknown, unknown> | undefined;
|
|
14
|
+
/** The type an operation selects on. */
|
|
15
|
+
export declare function rootType(schema: GraphQLSchema, operation: OperationDefinitionNode): import("graphql").GraphQLObjectType<any, any> | undefined;
|
|
16
|
+
/** The key a fragment is memoized under: `-1` for no pending size. */
|
|
17
|
+
export declare const NO_PENDING = -1;
|
|
18
|
+
/**
|
|
19
|
+
* The pending size a fragment is costed under. A fragment spread under many
|
|
20
|
+
* distinct sizes would be costed once per size, quadratic in a hostile
|
|
21
|
+
* document; past `EXACT_SIZES` of them a new size is rounded up to a power of
|
|
22
|
+
* two (a cost never lowers as a size grows, so it only over-counts, by less
|
|
23
|
+
* than twice), which leaves at most `EXACT_SIZES` + 53 costings per fragment.
|
|
24
|
+
*/
|
|
25
|
+
export declare function memoSize(known: ReadonlyMap<number, number>, pending: number | undefined): number | undefined;
|
|
26
|
+
//# sourceMappingURL=cost-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cost-context.d.ts","sourceRoot":"","sources":["../../src/limits/cost-context.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,sBAAsB,EAC3B,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAGlB,KAAK,uBAAuB,EAC5B,MAAM,SAAS,CAAC;AAEjB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAK/C,eAAO,MAAM,GAAG,GAAI,GAAG,MAAM,EAAE,GAAG,MAAM,WAA6B,CAAC;AACtE,eAAO,MAAM,QAAQ,GAAI,GAAG,MAAM,EAAE,GAAG,MAAM,WAA6B,CAAC;AAE3E,uFAAuF;AACvF,MAAM,WAAW,WAAY,SAAQ,WAAW;IAC/C,mBAAmB,EAAE,OAAO,CAAC;IAC7B,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,sBAAsB,GAAG,IAAI,GAAG,SAAS,CAAC;IACzE,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAChD,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACrB;AAED,8FAA8F;AAC9F,wBAAgB,OAAO,CACtB,IAAI,EAAE,WAAW,EACjB,MAAM,EAAE,gBAAgB,GAAG,SAAS,EACpC,IAAI,EAAE,MAAM,GACV,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,GAAG,SAAS,CAO5C;AAED,wCAAwC;AACxC,wBAAgB,QAAQ,CACvB,MAAM,EAAE,aAAa,EACrB,SAAS,EAAE,uBAAuB,6DASlC;AAKD,sEAAsE;AACtE,eAAO,MAAM,UAAU,KAAK,CAAC;AAE7B;;;;;;GAMG;AACH,wBAAgB,QAAQ,CACvB,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,EAClC,OAAO,EAAE,MAAM,GAAG,SAAS,GACzB,MAAM,GAAG,SAAS,CAQpB"}
|
|
@@ -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,23 @@
|
|
|
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 `definition` states on `parent`, as selected by `args`: the largest
|
|
10
|
+
* its size arguments say, `undefined` when none says anything (none given, and
|
|
11
|
+
* none declared with a default). The schema's part is memoized, so a selection
|
|
12
|
+
* costs `sizeArguments.length` steps whatever the number of possible types.
|
|
13
|
+
* A list uses it, and a field returning an object (a Relay connection) hands it
|
|
14
|
+
* to the lists below it.
|
|
15
|
+
*/
|
|
16
|
+
export declare function statedSize(cost: SizeContext, parent: GraphQLNamedType | undefined, definition: GraphQLField<unknown, unknown>, args: readonly ArgumentNode[] | undefined): number | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* Whether `definition` and the fields implementing it declare a size argument:
|
|
19
|
+
* `'all'` of them, `'none'` of them, or `'some'` (an abstract parent whose
|
|
20
|
+
* possible types differ).
|
|
21
|
+
*/
|
|
22
|
+
export declare function declaration(cost: SizeContext, parent: GraphQLNamedType | undefined, definition: GraphQLField<unknown, unknown>): 'all' | 'none' | 'some';
|
|
23
|
+
//# 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;AAuJD;;;;;;;GAOG;AACH,wBAAgB,UAAU,CACzB,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,GAAG,SAAS,CAepB;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAC1B,IAAI,EAAE,WAAW,EACjB,MAAM,EAAE,gBAAgB,GAAG,SAAS,EACpC,UAAU,EAAE,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,GACxC,KAAK,GAAG,MAAM,GAAG,MAAM,CAIzB"}
|
|
@@ -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,35 @@
|
|
|
1
|
+
import { type ValidationRule } from 'graphql';
|
|
2
|
+
/** Options of {@link maxFields}. */
|
|
3
|
+
export interface MaxFieldsOptions {
|
|
4
|
+
/** The most field selections an operation may have (at least 1). */
|
|
5
|
+
limit: 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()`)
|
|
10
|
+
* selects 220 fields.
|
|
11
|
+
*/
|
|
12
|
+
ignoreIntrospection?: boolean;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* A graphql-js validation rule refusing an operation that selects more than
|
|
16
|
+
* `limit` fields: neither `maxDepth` nor `maxListCost` bounds breadth, so
|
|
17
|
+
* thousands of aliases of a cheap field (or of `__typename`) pass both.
|
|
18
|
+
*
|
|
19
|
+
* Every field node counts 1, aliases and `__typename` included. A named
|
|
20
|
+
* fragment counts at each spread (walked once), an inline fragment counts its
|
|
21
|
+
* contents, and every branch of a union counts: nothing is pruned by type.
|
|
22
|
+
* `@skip` and `@include` are not evaluated, so the count can be over the
|
|
23
|
+
* document's field count. It counts the document, spreads expanded, not what the
|
|
24
|
+
* executor runs: how often a field runs inside a list is `maxListCost`'s.
|
|
25
|
+
* One `GraphQLError` per operation, with
|
|
26
|
+
* `extensions: { code: 'QUERY_TOO_WIDE', fields, limit }`, `fields` being the
|
|
27
|
+
* operation's real count (clamped at `Number.MAX_SAFE_INTEGER`).
|
|
28
|
+
*
|
|
29
|
+
* ```ts
|
|
30
|
+
* validate(schema, document, [...specifiedRules, maxFields({ limit: 500 })]);
|
|
31
|
+
* // graphql-yoga: onValidate: ({ addValidationRule }) => addValidationRule(maxFields({ limit: 500 }))
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export declare function maxFields(options: MaxFieldsOptions): ValidationRule;
|
|
35
|
+
//# sourceMappingURL=max-fields.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"max-fields.d.ts","sourceRoot":"","sources":["../../src/limits/max-fields.ts"],"names":[],"mappings":"AAAA,OAAO,EAKN,KAAK,cAAc,EACnB,MAAM,SAAS,CAAC;AAIjB,oCAAoC;AACpC,MAAM,WAAW,gBAAgB;IAChC,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAgDD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,cAAc,CA4BnE"}
|
|
@@ -0,0 +1,77 @@
|
|
|
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']`. One on a
|
|
12
|
+
* non-list field also sizes the lists declaring none directly on its return
|
|
13
|
+
* type (a Relay connection's `edges` and `nodes`).
|
|
14
|
+
*/
|
|
15
|
+
sizeArguments?: readonly string[];
|
|
16
|
+
/**
|
|
17
|
+
* Do not cost `__schema` and `__type` (default `false`). Only where
|
|
18
|
+
* introspection is disabled or the client is trusted, e.g. GraphiQL in
|
|
19
|
+
* development: the standard introspection query is costly (on the order of
|
|
20
|
+
* 200,000 on a one-field schema).
|
|
21
|
+
*/
|
|
22
|
+
ignoreIntrospection?: boolean;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* A graphql-js validation rule refusing an operation whose cost is more than
|
|
26
|
+
* `budget`, to stop a client from exploiting list cycles (`Folder.items`,
|
|
27
|
+
* `Item.folder`, `Folder.items`, …) for a cost growing exponentially.
|
|
28
|
+
*
|
|
29
|
+
* The cost of an operation is the sum, over every selected field, of the
|
|
30
|
+
* product of the sizes of the list fields enclosing it: a field costs 1, and a
|
|
31
|
+
* list field multiplies the cost of its sub-selection by its size.
|
|
32
|
+
* `__typename` costs nothing. `__schema` and `__type` are costed like any
|
|
33
|
+
* field, their lists sized by the schema itself (`__Schema.types` is the number
|
|
34
|
+
* of types, the other lists the longest list anywhere in the schema), unless
|
|
35
|
+
* `ignoreIntrospection` is set.
|
|
36
|
+
*
|
|
37
|
+
* The size of a list field is the largest size its `sizeArguments` (default
|
|
38
|
+
* `first`, `last`, `limit`) say. A literal Int, a String holding a canonical
|
|
39
|
+
* integer (`"1000"`) or an integral Float (`1e3`) of at least 0 says that
|
|
40
|
+
* number. Anything else (a negative literal, a variable, since validation has
|
|
41
|
+
* no variable values) says the argument's SDL default when it has a usable one,
|
|
42
|
+
* `defaultFirst` otherwise; an argument not given says its SDL default, or
|
|
43
|
+
* nothing. When nothing is said the size is `defaultFirst`. On an interface the
|
|
44
|
+
* largest default over its possible types is used. Hence no subtree ever costs
|
|
45
|
+
* less than nothing: a negative `first` on one field cannot cancel the cost of
|
|
46
|
+
* its sibling. A field whose type (once unwrapped from non-null) is a list is
|
|
47
|
+
* one list, nested `[[X]]` included.
|
|
48
|
+
*
|
|
49
|
+
* A Relay connection puts the size on a field returning an object, with the
|
|
50
|
+
* list below it (`items(first: 100) { edges { node { id } } }`). A field that
|
|
51
|
+
* is not a list and states a size (by the same reading) hands it to the lists
|
|
52
|
+
* selected directly on its return type, through inline fragments and fragment
|
|
53
|
+
* spreads on that same selection set, and only to those declaring none of the
|
|
54
|
+
* size arguments (`edges`, `nodes`): such a list takes it instead of
|
|
55
|
+
* `defaultFirst`. A list declaring a size argument (`recent(first: Int)`)
|
|
56
|
+
* reads its own, never the pending size. Crossing any other field (an object
|
|
57
|
+
* field, `pageInfo`, a wrapper) ends it. A connection stating nothing hands
|
|
58
|
+
* down nothing: its lists are sized `defaultFirst`.
|
|
59
|
+
*
|
|
60
|
+
* Named fragments are followed, each costed once per pending size (past eight
|
|
61
|
+
* distinct sizes under one fragment a size is rounded up to a power of two, so
|
|
62
|
+
* the work stays linear in the document and a cost only over-counts). Inline fragments and
|
|
63
|
+
* fragments on an abstract type are summed branch by branch, so the cost of a
|
|
64
|
+
* query on an interface or a union is overestimated, never underestimated.
|
|
65
|
+
*
|
|
66
|
+
* One `GraphQLError` per operation, with
|
|
67
|
+
* `extensions: { code: 'QUERY_TOO_COSTLY', cost, limit }`. `cost` is exact up
|
|
68
|
+
* to `Number.MAX_SAFE_INTEGER`, which it never exceeds.
|
|
69
|
+
*
|
|
70
|
+
* ```ts
|
|
71
|
+
* const rule = maxListCost({ budget: 10_000, defaultFirst: 50 });
|
|
72
|
+
* validate(schema, document, [...specifiedRules, rule]);
|
|
73
|
+
* // graphql-yoga: onValidate: ({ addValidationRule }) => addValidationRule(rule)
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
export declare function maxListCost(options: MaxListCostOptions): ValidationRule;
|
|
77
|
+
//# 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,EAUN,KAAK,cAAc,EACnB,MAAM,SAAS,CAAC;AAejB,sCAAsC;AACtC,MAAM,WAAW,kBAAkB;IAClC,mDAAmD;IACnD,MAAM,EAAE,MAAM,CAAC;IACf,qFAAqF;IACrF,YAAY,EAAE,MAAM,CAAC;IACrB;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAkGD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,cAAc,CAgDvE"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ArgumentNode, GraphQLField, GraphQLNamedType } from 'graphql';
|
|
2
|
+
import { type SizeContext } from './list-size.js';
|
|
3
|
+
/**
|
|
4
|
+
* The size of the list `definition` on `parent`. `pending` is the size of the
|
|
5
|
+
* field whose return type this list is selected on (a connection's `first`):
|
|
6
|
+
* a list that declares none of the size arguments takes it, since the size
|
|
7
|
+
* cannot be stated on the list itself. A list that declares one reads its own
|
|
8
|
+
* arguments, else `defaultFirst`, and never the pending size. On an abstract
|
|
9
|
+
* parent some possible types may declare one and others not: the largest of
|
|
10
|
+
* both readings, since the query cannot say which comes back.
|
|
11
|
+
*/
|
|
12
|
+
export declare function listSizeUnder(cost: SizeContext, parent: GraphQLNamedType | undefined, definition: GraphQLField<unknown, unknown>, args: readonly ArgumentNode[] | undefined, pending: number | undefined): number;
|
|
13
|
+
//# sourceMappingURL=pending-size.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pending-size.d.ts","sourceRoot":"","sources":["../../src/limits/pending-size.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAC5E,OAAO,EAAe,KAAK,WAAW,EAAc,MAAM,aAAa,CAAC;AAExE;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAC5B,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,EACzC,OAAO,EAAE,MAAM,GAAG,SAAS,GACzB,MAAM,CASR"}
|
|
@@ -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;
|
|
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, too costly or too wide (`maxDepth`, `maxListCost`, `maxFields`), 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"
|
|
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
|
package/docs/guide/errors.md
CHANGED
|
@@ -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 =
|