@nxgt/graphql-validation 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -133,7 +133,9 @@ refusal reads as your schema writes it, and its issue carries
133
133
  built-in name (`email`, …) is a type error and refused at startup, and so is
134
134
  a schema that rewrites the value (a custom `.check()` that does fails the
135
135
  request, naming the format). An async check (`.refine(async …)`) works in a
136
- request, and runs once per value. Call `withValidation` once, with every
136
+ request, and runs once per value. Your format runs through Zod's public API
137
+ only (`safeParseAsync`, `check`, `refine`, `catch`), so a Zod 4 release that
138
+ changes Zod's internals does not break it. Call `withValidation` once, with every
137
139
  format: a second call with the same record wraps nothing; with other
138
140
  formats, or none, it throws. Without `formats`, nothing changes. Details in
139
141
  [Constraints](docs/guide/constraints.md#your-own-formats).
@@ -1 +1 @@
1
- {"version":3,"file":"leaf.d.ts","sourceRoot":"","sources":["../../src/builder/leaf.ts"],"names":[],"mappings":"AAAA,OAAO,EAKN,KAAK,eAAe,EAEpB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAehD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAChC,IAAI,EAAE,eAAe,EACrB,WAAW,EAAE,SAAS,UAAU,EAAE,EAClC,KAAK,EAAE,MAAM,GACX,IAAI,CAMN;AAED,2EAA2E;AAC3E,wBAAgB,mBAAmB,CAClC,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,SAAS,UAAU,EAAE,EAClC,KAAK,EAAE,MAAM,GACX,IAAI,CAIN;AAYD;;;;GAIG;AACH,wBAAgB,UAAU,CACzB,IAAI,EAAE,eAAe,EACrB,WAAW,EAAE,SAAS,UAAU,EAAE,EAClC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,WAAW,GAClB,CAAC,CAAC,OAAO,CAQX;AAED,wEAAwE;AACxE,wBAAgB,QAAQ,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,GAAG,SAAS,CAMlE;AAED,iDAAiD;AACjD,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAIrD"}
1
+ {"version":3,"file":"leaf.d.ts","sourceRoot":"","sources":["../../src/builder/leaf.ts"],"names":[],"mappings":"AAAA,OAAO,EAKN,KAAK,eAAe,EAEpB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAehD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAChC,IAAI,EAAE,eAAe,EACrB,WAAW,EAAE,SAAS,UAAU,EAAE,EAClC,KAAK,EAAE,MAAM,GACX,IAAI,CAMN;AAED,2EAA2E;AAC3E,wBAAgB,mBAAmB,CAClC,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,SAAS,UAAU,EAAE,EAClC,KAAK,EAAE,MAAM,GACX,IAAI,CAIN;AAYD;;;;GAIG;AACH,wBAAgB,UAAU,CACzB,IAAI,EAAE,eAAe,EACrB,WAAW,EAAE,SAAS,UAAU,EAAE,EAClC,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,WAAW,GAClB,CAAC,CAAC,OAAO,CAmBX;AAED,wEAAwE;AACxE,wBAAgB,QAAQ,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,GAAG,SAAS,CAMlE;AAED,iDAAiD;AACjD,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAIrD"}
@@ -26,9 +26,6 @@ import {
26
26
  isObjectType
27
27
  } from "graphql";
28
28
 
29
- // src/formats/registry.ts
30
- import { z as z9 } from "zod";
31
-
32
29
  // src/formats/all.ts
33
30
  var exports_all = {};
34
31
  __export(exports_all, {
@@ -108,6 +105,99 @@ var uuidFormat = defineFormat({
108
105
  // src/formats/index.ts
109
106
  var formats = Object.fromEntries(Object.values(exports_all).map((format) => [format.name, format]));
110
107
 
108
+ // src/formats/marked.ts
109
+ import { z as z9 } from "zod";
110
+ class Refused {
111
+ issues;
112
+ constructor(issues) {
113
+ this.issues = issues;
114
+ }
115
+ }
116
+ var SENTINEL = "nxgtSentinel";
117
+ function marked(name, schema, onAsync) {
118
+ let done = false;
119
+ let outcome;
120
+ const probe = schema.check((ctx) => {
121
+ if (ctx.issues.length > 0)
122
+ ctx.issues.push(marker("plain", ctx.value));
123
+ }).refine(() => false, {
124
+ params: { [SENTINEL]: "when" },
125
+ when: (payload) => payload.issues.length > 0
126
+ }).catch((ctx) => new Refused(ctx.error.issues)).refine((value) => {
127
+ done = true;
128
+ outcome = value;
129
+ return true;
130
+ });
131
+ return (narrow) => {
132
+ let stored = [];
133
+ const replay = narrow(z9.string().check((ctx) => {
134
+ ctx.issues.push(...stored);
135
+ }));
136
+ const raise = (ctx, result, async) => {
137
+ let next = true;
138
+ if (result instanceof Refused) {
139
+ const kinds = new Set(result.issues.map(sentinelOf));
140
+ if (!async && !kinds.has("plain"))
141
+ next = kinds.has("when") ? undefined : false;
142
+ stored = result.issues.filter((issue) => sentinelOf(issue) === undefined).map((issue) => raw(issue, ctx.value, next, "format"));
143
+ } else if (result !== ctx.value) {
144
+ throw new Error(`The format "${name}" rewrote the value it checked: a format checks the value and never changes it, so the server and the client check the value as it was sent. Refuse what is not canonical with .regex() or .refine() instead of setting payload.value in a .check().`);
145
+ }
146
+ let replayed;
147
+ try {
148
+ replayed = replay.safeParse(ctx.value);
149
+ } finally {
150
+ stored = [];
151
+ }
152
+ if (replayed.success)
153
+ return;
154
+ for (const issue of replayed.error.issues) {
155
+ const own = paramsOf(issue)?.[RULE_PARAM] === "format";
156
+ ctx.issues.push(raw(issue, ctx.value, own ? next : true));
157
+ }
158
+ };
159
+ return z9.string().check((ctx) => {
160
+ done = false;
161
+ outcome = undefined;
162
+ const pending = probe.safeParseAsync(ctx.value);
163
+ if (done) {
164
+ pending.catch(() => {});
165
+ raise(ctx, outcome, false);
166
+ return;
167
+ }
168
+ const later = pending.then((result) => raise(ctx, result.success ? result.data : undefined, true));
169
+ later.catch(() => {});
170
+ onAsync();
171
+ return later;
172
+ });
173
+ };
174
+ }
175
+ function marker(kind, value) {
176
+ return {
177
+ code: "custom",
178
+ message: "",
179
+ input: value,
180
+ params: { [SENTINEL]: kind },
181
+ continue: true
182
+ };
183
+ }
184
+ function paramsOf(issue) {
185
+ return "params" in issue ? issue.params : undefined;
186
+ }
187
+ function sentinelOf(issue) {
188
+ return paramsOf(issue)?.[SENTINEL];
189
+ }
190
+ function raw(issue, input, next, constraint) {
191
+ const params = constraint ? { ...paramsOf(issue), [RULE_PARAM]: constraint } : paramsOf(issue);
192
+ const { continue: _, ...rest } = issue;
193
+ return {
194
+ ...rest,
195
+ input,
196
+ ...params && { params },
197
+ ...next !== undefined && { continue: next }
198
+ };
199
+ }
200
+
111
201
  // src/formats/registry.ts
112
202
  var NAME = /^[a-z][a-z0-9-]*$/;
113
203
 
@@ -128,15 +218,16 @@ class FormatRegistry {
128
218
  throw new Error(`The format "${name}" is not a Zod string schema: write z.string() or a string format such as z.email(), narrowed with .regex() or .refine(), never transformed.`);
129
219
  }
130
220
  if (!runnable(schema)) {
131
- throw new Error(`The format "${name}" cannot be run: its definition reads type: 'string' but it has no _zod.run, so it was not built by zod 4. Pass the schema z.string() or a string format returns, not an object shaped like one.`);
221
+ throw new Error(`The format "${name}" cannot be run: its definition reads type: 'string' but it has no safeParseAsync, check, refine or catch, so it is not a schema of zod 4's classic API. Pass the schema z.string() or a string format returns, not an object shaped like one.`);
132
222
  }
133
223
  if (rewrites(schema)) {
134
224
  throw new Error(`The format "${name}" rewrites the value (.trim(), .toLowerCase(), .toUpperCase(), .normalize(), .slugify(), .overwrite(), z.url(), z.httpUrl() or z.coerce.string()): refuse what is not canonical with .regex() or .refine() instead, so the server and the client check the value as it was sent.`);
135
225
  }
136
- const own = marked(name, schema, () => {
226
+ const narrowed = marked(name, schema, () => {
137
227
  this.#async = name;
138
228
  });
139
- this.#formats.set(name, { name, toZod: () => own });
229
+ const own = narrowed((schema) => schema);
230
+ this.#formats.set(name, { name, toZod: () => own, narrowed });
140
231
  }
141
232
  }
142
233
  named(name) {
@@ -155,7 +246,8 @@ function isStringSchema(value) {
155
246
  return definition(value)?.type === "string";
156
247
  }
157
248
  function runnable(schema) {
158
- return typeof schema?._zod?.run === "function";
249
+ const api = schema;
250
+ return ["safeParseAsync", "check", "refine", "catch"].every((method) => typeof api[method] === "function");
159
251
  }
160
252
  function rewrites(schema) {
161
253
  const def = definition(schema);
@@ -169,34 +261,6 @@ function rewrites(schema) {
169
261
  function definition(value) {
170
262
  return value?._zod?.def;
171
263
  }
172
- function marked(name, schema, onAsync) {
173
- return z9.string().superRefine((value, ctx) => {
174
- const raise = (result) => {
175
- if (result.issues.length === 0 && result.value !== value) {
176
- throw new Error(`The format "${name}" rewrote the value it checked: a format checks the value and never changes it, so the server and the client check the value as it was sent. Refuse what is not canonical with .regex() or .refine() instead of setting payload.value in a .check().`);
177
- }
178
- for (const raw of result.issues) {
179
- const issue = z9.core.util.finalizeIssue(raw, RUN, z9.core.config());
180
- const params = "params" in issue ? issue.params : undefined;
181
- ctx.addIssue({
182
- ...issue,
183
- params: { ...params, [RULE_PARAM]: "format" },
184
- ...raw.continue === false && { continue: false }
185
- });
186
- }
187
- };
188
- const result = schema._zod.run({ value, issues: [] }, RUN);
189
- if (!(result instanceof Promise)) {
190
- raise(result);
191
- return;
192
- }
193
- const pending = result.then(raise);
194
- pending.catch(() => {});
195
- onAsync();
196
- return pending;
197
- });
198
- }
199
- var RUN = { async: true };
200
264
  var builtInRegistry = new FormatRegistry;
201
265
  var registries = new WeakMap;
202
266
  function registryOf(own) {
@@ -294,11 +358,12 @@ function leafSchema(type, constraints, where, context) {
294
358
  if (constraints.length === 0)
295
359
  return z11.unknown();
296
360
  assertLeafTargets(type, constraints, where);
297
- let schema = baseOf(type);
298
- for (const { rule, value } of constraints) {
299
- schema = applyRule(rule, schema, value, context);
300
- }
301
- return schema;
361
+ const [first, ...rest] = constraints;
362
+ const narrow = (schema) => rest.reduce((narrowed, { rule, value }) => applyRule(rule, narrowed, value, context), schema);
363
+ const narrowed = first?.rule === rules.format ? context.formats.named(String(first.value)).narrowed : undefined;
364
+ if (narrowed)
365
+ return narrowed(narrow);
366
+ return constraints.reduce((schema, { rule, value }) => applyRule(rule, schema, value, context), baseOf(type));
302
367
  }
303
368
  function baseCode(type) {
304
369
  if (type.name === GraphQLInt.name)
@@ -458,5 +523,5 @@ function assertNoDirectiveArgumentConstrained(inputs, schema) {
458
523
 
459
524
  export { registryOf, constraintsOn2, assertLeafTargets, assertObjectTargets, baseCode, checkConstraints2 };
460
525
 
461
- //# debugId=3026B70F7346E03264756E2164756E21
462
- //# sourceMappingURL=index-1mzzydy3.js.map
526
+ //# debugId=F2C2C0D2BA61CB1B64756E2164756E21
527
+ //# sourceMappingURL=index-twevz7yc.js.map
@@ -0,0 +1,26 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/builder/constraints.ts", "../src/builder/check-constraints.ts", "../src/formats/byte.ts", "../src/formats/format.ts", "../src/formats/date.ts", "../src/formats/date-time.ts", "../src/formats/email.ts", "../src/formats/ipv4.ts", "../src/formats/ipv6.ts", "../src/formats/uri.ts", "../src/formats/uuid.ts", "../src/formats/index.ts", "../src/formats/marked.ts", "../src/formats/registry.ts", "../src/builder/args-schema.ts", "../src/builder/input-schema.ts", "../src/builder/leaf.ts"],
4
+ "sourcesContent": [
5
+ "import {\n\ttype DirectiveNode,\n\ttype GraphQLDirective,\n\tgetDirectiveValues,\n} from 'graphql';\nimport { type RegisteredRule, rules } from '../rules';\n\n/** One `@constraint` argument written on an argument or an input field. */\nexport interface Constraint {\n\treadonly rule: RegisteredRule;\n\treadonly value: string | number;\n}\n\n/**\n * The constraints written on a node, base rules (`format`) first so the\n * others narrow the schema they produce. Empty when the schema declares no\n * `@constraint` or the node carries none.\n */\nexport function constraintsOn(\n\tdirective: GraphQLDirective | undefined,\n\tnode:\n\t\t| { readonly directives?: ReadonlyArray<DirectiveNode> | undefined }\n\t\t| null\n\t\t| undefined,\n): Constraint[] {\n\tif (!directive || !node) return [];\n\tconst values =\n\t\tgetDirectiveValues(directive, { directives: node.directives ?? [] }) ?? {};\n\treturn Object.entries(values)\n\t\t.filter(([, value]) => value !== undefined && value !== null)\n\t\t.map(([argument, value]) => ({\n\t\t\trule: rules[argument as keyof typeof rules],\n\t\t\tvalue: value as string | number,\n\t\t}))\n\t\t.sort(\n\t\t\t(a, b) => Number(Boolean(b.rule.base)) - Number(Boolean(a.rule.base)),\n\t\t);\n}\n",
6
+ "import {\n\ttype GraphQLDirective,\n\ttype GraphQLField,\n\ttype GraphQLObjectType,\n\ttype GraphQLSchema,\n\tisInterfaceType,\n\tisObjectType,\n} from 'graphql';\nimport type { z } from 'zod';\nimport { assertOwnConstraint } from '../constraint-directive';\nimport { type FormatSchemas, registryOf } from '../formats/registry';\nimport { argsSchemaOf, assertInterfaceConstraintsKept } from './args-schema';\nimport { constraintsOn } from './constraints';\nimport { InputSchemas } from './input-schema';\n\n/**\n * Runs every check `withValidation` makes at startup, so a code generator\n * refuses the same schemas: the declaration is `constraintTypeDefs`', every\n * constraint applies where it is written (in every input type), none sits on\n * a directive's argument, objects keep their interfaces' constraints, and no\n * default value breaks its own. `onArgs` receives each object field's\n * arguments schema, for a field with something to check.\n *\n * `formats` are the application's own, which `@constraint(format: \"...\")`\n * may name beside the built-in ones; they are checked first (name, no\n * built-in replaced, a Zod string schema each).\n *\n * Returns the `@constraint` directive, or `undefined` when the schema\n * declares none (and so carries no constraint).\n */\nexport function checkConstraints(\n\tschema: GraphQLSchema,\n\tonArgs?: (\n\t\ttype: GraphQLObjectType,\n\t\tfield: GraphQLField<unknown, unknown>,\n\t\targs: z.ZodType,\n\t) => void,\n\tformats?: FormatSchemas,\n): GraphQLDirective | undefined {\n\tconst inputs = new InputSchemas(schema, registryOf(formats));\n\tif (!inputs.directive) return undefined;\n\tassertOwnConstraint(inputs.directive);\n\tinputs.buildAll(schema);\n\tassertNoDirectiveArgumentConstrained(inputs, schema);\n\tfor (const type of Object.values(schema.getTypeMap())) {\n\t\tif (type.name.startsWith('__')) continue;\n\t\t// An interface's fields resolve on its objects: built for their errors only.\n\t\tif (isInterfaceType(type)) {\n\t\t\tfor (const field of Object.values(type.getFields()))\n\t\t\t\targsSchemaOf(inputs, type.name, field);\n\t\t}\n\t\tif (!isObjectType(type)) continue;\n\t\tassertInterfaceConstraintsKept(inputs, type);\n\t\tfor (const field of Object.values(type.getFields()) as GraphQLField<\n\t\t\tunknown,\n\t\t\tunknown\n\t\t>[]) {\n\t\t\tconst args = argsSchemaOf(inputs, type.name, field);\n\t\t\tif (args) onArgs?.(type, field, args);\n\t\t}\n\t}\n\tinputs.checkDefaults();\n\treturn inputs.directive;\n}\n\n/**\n * Fails on a `@constraint` written on a directive's argument: graphql allows\n * it there (ARGUMENT_DEFINITION), but no resolver receives that argument, so\n * it would check nothing.\n */\nfunction assertNoDirectiveArgumentConstrained(\n\tinputs: InputSchemas,\n\tschema: GraphQLSchema,\n): void {\n\tfor (const directive of schema.getDirectives()) {\n\t\tfor (const arg of directive.args) {\n\t\t\tif (constraintsOn(inputs.directive, arg.astNode).length > 0) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`@constraint on @${directive.name}(${arg.name}:) checks nothing: a directive's argument reaches no resolver. Remove it.`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n}\n",
7
+ "import { z } from 'zod';\nimport { defineFormat } from './format';\n\nexport const byteFormat = defineFormat({\n\tname: 'byte',\n\ttoZod: () => z.base64(),\n\ttoCode: () => 'z.base64()',\n});\n",
8
+ "import type { z } from 'zod';\nimport type { Narrow } from './marked';\n\n/** A string schema, plain or a format (`z.email()` is not a `z.ZodString`). */\nexport type StringSchema = z.ZodString | z.ZodStringFormat;\n\n/**\n * One value of `@constraint(format: \"...\")`: the schema it stands for, as a\n * schema at startup and, for a built-in one, as source for a code generator.\n * A format of the application's own has no `toCode`: the generator writes a\n * reference to the application's schema instead.\n */\nexport interface Format<N extends string = string> {\n\treadonly name: N;\n\treadonly toZod: () => StringSchema;\n\treadonly toCode?: () => string;\n\t/**\n\t * An application's format, narrowed by the rules written after it\n\t * (`leafSchema` hands them): they run inside it, after its checks, so\n\t * they see its abort even once it went async. A built-in format has none:\n\t * the rules are chained on `toZod()`.\n\t */\n\treadonly narrowed?: (narrow: Narrow) => StringSchema;\n}\n\n/** A format this package ships: written twice, as a schema and as source. */\nexport interface BuiltInFormat<N extends string = string> extends Format<N> {\n\treadonly toCode: () => string;\n}\n\n/** Declares a built-in format, with its name kept literal. */\nexport function defineFormat<const N extends string>(\n\tformat: BuiltInFormat<N>,\n): BuiltInFormat<N> {\n\treturn format;\n}\n",
9
+ "import { z } from 'zod';\nimport { defineFormat } from './format';\n\nexport const dateFormat = defineFormat({\n\tname: 'date',\n\ttoZod: () => z.iso.date(),\n\ttoCode: () => 'z.iso.date()',\n});\n",
10
+ "import { z } from 'zod';\nimport { defineFormat } from './format';\n\n// RFC 3339 with an offset, in its canonical spelling only: an uppercase `T`\n// and `Z`, seconds present. graphql-constraint-directive (validator's\n// isRFC3339) also takes a lowercase `t`, `z` or a space.\nexport const dateTimeFormat = defineFormat({\n\tname: 'date-time',\n\ttoZod: () => z.iso.datetime({ offset: true }),\n\ttoCode: () => 'z.iso.datetime({ offset: true })',\n});\n",
11
+ "import { z } from 'zod';\nimport { defineFormat } from './format';\n\nexport const emailFormat = defineFormat({\n\tname: 'email',\n\ttoZod: () => z.email(),\n\ttoCode: () => 'z.email()',\n});\n",
12
+ "import { z } from 'zod';\nimport { defineFormat } from './format';\n\nexport const ipv4Format = defineFormat({\n\tname: 'ipv4',\n\ttoZod: () => z.ipv4(),\n\ttoCode: () => 'z.ipv4()',\n});\n",
13
+ "import { z } from 'zod';\nimport { defineFormat } from './format';\n\nexport const ipv6Format = defineFormat({\n\tname: 'ipv6',\n\ttoZod: () => z.ipv6(),\n\ttoCode: () => 'z.ipv6()',\n});\n",
14
+ "import { z } from 'zod';\nimport { defineFormat } from './format';\n\n// graphql-constraint-directive's `uri` is validator's isURL: http, https or\n// ftp. The scheme is required here, where isURL lets `example.com` through,\n// and nothing else gets in: no `javascript:`, no `mailto:`.\nexport const uriFormat = defineFormat({\n\tname: 'uri',\n\ttoZod: () => z.url({ protocol: /^(https?|ftp)$/ }),\n\ttoCode: () => 'z.url({ protocol: /^(https?|ftp)$/ })',\n});\n",
15
+ "import { z } from 'zod';\nimport { defineFormat } from './format';\n\nexport const uuidFormat = defineFormat({\n\tname: 'uuid',\n\ttoZod: () => z.uuid(),\n\ttoCode: () => 'z.uuid()',\n});\n",
16
+ "import * as all from './all';\nimport type { BuiltInFormat } from './format';\n\n/**\n * Every built-in format, keyed by the value `@constraint(format: \"...\")`\n * takes. Derived from what `./all` exports, so a new format is one file and\n * one line there.\n */\nexport const formats = Object.fromEntries(\n\tObject.values(all).map((format) => [format.name, format]),\n) as { readonly [N in FormatName]: BuiltInFormat<N> };\n\n/** A value `@constraint(format: \"...\")` takes without the application's formats. */\nexport type FormatName = (typeof all)[keyof typeof all]['name'];\n",
17
+ "import { z } from 'zod';\nimport { RULE_PARAM } from '../rules/rule';\nimport type { StringSchema } from './format';\n\n/** The rules written after a format, applied to the schema they narrow. */\nexport type Narrow = (schema: StringSchema) => z.ZodType;\n\n/** The issues of a refused run, as the value `.catch()` hands on. */\nclass Refused {\n\tconstructor(readonly issues: readonly z.core.$ZodIssue[]) {}\n}\n\n/** Where our own refinements mark the issues they add. */\nconst SENTINEL = 'nxgtSentinel';\n\n/**\n * The application's schema as a plain string schema, narrowed by the rules\n * written after it (`narrow`), each of its issues re-raised as it was (code,\n * message, and an abort that stops those rules) and marked as the format's:\n * a `.regex()` inside it is the format's refusal, not `pattern`'s. The value\n * is checked, never changed: a schema that still returns another value (a\n * custom `.check()` setting `payload.value`, which `rewrites` cannot see)\n * throws, naming the format, as a resolver's bug would.\n *\n * Only zod's public API runs the schema, whatever zod 4 copy it comes from:\n * `safeParseAsync`, `check` pushing to `ctx.issues`, `refine` (with\n * `when`), `catch`, and the issues they return. A zod release that changes\n * its internals changes nothing here.\n *\n * - **Once per value, never a dropped promise.** The schema runs through\n * `safeParseAsync` only, never a synchronous `safeParse` that would start\n * an async check and drop its promise. A `.catch()` and a `.refine()`\n * chained last tell, as soon as the call returns, whether the run\n * finished synchronously (zod runs a schema's checks within the call\n * until one returns a promise): then its result is used at once, so a\n * synchronous parse (a default value's check at startup) still works.\n * Otherwise the promise is returned to the enclosing parse, with a\n * handler, and `onAsync` is told: a synchronous parse throws zod's async\n * error and `checkDefaults` names the format.\n * - **An abort** is read from two refinements chained after the schema's\n * checks: a plain one, which zod skips after any issue that does not\n * continue (`abort: true`, an issue a `.check()` pushed with no\n * `continue`), and one with a `when`, skipped only after `continue:\n * false`. Each marks a refused run's issues when it ran. The issues are\n * then replayed, with that same `continue`, through a `z.string()`\n * narrowed by the rules, so zod itself decides which rules run, as it does\n * on the client where they are chained on the schema.\n * - **Once async**, zod on the client runs the rules before the async\n * check's issues arrive, whatever its abort: the rules run here too, and\n * the format's issues come first.\n */\nexport function marked(\n\tname: string,\n\tschema: StringSchema,\n\tonAsync: () => void,\n): (narrow: Narrow) => StringSchema {\n\tlet done = false;\n\tlet outcome: unknown;\n\tconst probe = schema\n\t\t.check((ctx) => {\n\t\t\tif (ctx.issues.length > 0) ctx.issues.push(marker('plain', ctx.value));\n\t\t})\n\t\t.refine(() => false, {\n\t\t\tparams: { [SENTINEL]: 'when' },\n\t\t\twhen: (payload) => payload.issues.length > 0,\n\t\t})\n\t\t.catch((ctx) => new Refused(ctx.error.issues) as unknown as string)\n\t\t.refine((value) => {\n\t\t\tdone = true;\n\t\t\toutcome = value;\n\t\t\treturn true;\n\t\t});\n\n\treturn (narrow) => {\n\t\tlet stored: z.core.$ZodRawIssue[] = [];\n\t\tconst replay = narrow(\n\t\t\tz.string().check((ctx) => {\n\t\t\t\tctx.issues.push(...stored);\n\t\t\t}),\n\t\t);\n\n\t\tconst raise = (\n\t\t\tctx: z.core.ParsePayload<string>,\n\t\t\tresult: unknown,\n\t\t\tasync: boolean,\n\t\t) => {\n\t\t\tlet next: boolean | undefined = true;\n\t\t\tif (result instanceof Refused) {\n\t\t\t\tconst kinds = new Set(result.issues.map(sentinelOf));\n\t\t\t\t// Both ran: every issue continues. Only the `when` one: an issue\n\t\t\t\t// that does not continue. Neither: an explicit abort.\n\t\t\t\tif (!async && !kinds.has('plain'))\n\t\t\t\t\tnext = kinds.has('when') ? undefined : false;\n\t\t\t\tstored = result.issues\n\t\t\t\t\t.filter((issue) => sentinelOf(issue) === undefined)\n\t\t\t\t\t.map((issue) => raw(issue, ctx.value, next, 'format'));\n\t\t\t} else if (result !== ctx.value) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`The format \"${name}\" rewrote the value it checked: a format checks the value and never changes it, so the server and the client check the value as it was sent. Refuse what is not canonical with .regex() or .refine() instead of setting payload.value in a .check().`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tlet replayed: z.ZodSafeParseResult<unknown>;\n\t\t\ttry {\n\t\t\t\treplayed = replay.safeParse(ctx.value);\n\t\t\t} finally {\n\t\t\t\tstored = [];\n\t\t\t}\n\t\t\tif (replayed.success) return;\n\t\t\tfor (const issue of replayed.error.issues) {\n\t\t\t\tconst own = paramsOf(issue)?.[RULE_PARAM] === 'format';\n\t\t\t\tctx.issues.push(raw(issue, ctx.value, own ? next : true));\n\t\t\t}\n\t\t};\n\n\t\treturn z.string().check((ctx) => {\n\t\t\tdone = false;\n\t\t\toutcome = undefined;\n\t\t\tconst pending = probe.safeParseAsync(ctx.value);\n\t\t\tif (done) {\n\t\t\t\tpending.catch(() => {});\n\t\t\t\traise(ctx, outcome, false);\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\tconst later = pending.then((result) =>\n\t\t\t\traise(ctx, result.success ? result.data : undefined, true),\n\t\t\t);\n\t\t\tlater.catch(() => {});\n\t\t\tonAsync();\n\t\t\treturn later;\n\t\t}) as unknown as StringSchema;\n\t};\n}\n\nfunction marker(kind: string, value: string): z.core.$ZodRawIssue {\n\treturn {\n\t\tcode: 'custom',\n\t\tmessage: '',\n\t\tinput: value,\n\t\tparams: { [SENTINEL]: kind },\n\t\tcontinue: true,\n\t};\n}\n\nfunction paramsOf(\n\tissue: z.core.$ZodIssue,\n): Record<string, unknown> | undefined {\n\treturn 'params' in issue\n\t\t? (issue.params as Record<string, unknown> | undefined)\n\t\t: undefined;\n}\n\nfunction sentinelOf(issue: z.core.$ZodIssue): unknown {\n\treturn paramsOf(issue)?.[SENTINEL];\n}\n\n/** A finalised issue raised again; marked `constraint` when given. */\nfunction raw(\n\tissue: z.core.$ZodIssue,\n\tinput: string,\n\tnext: boolean | undefined,\n\tconstraint?: string,\n): z.core.$ZodRawIssue {\n\tconst params = constraint\n\t\t? { ...paramsOf(issue), [RULE_PARAM]: constraint }\n\t\t: paramsOf(issue);\n\tconst { continue: _, ...rest } = issue as z.core.$ZodIssue & {\n\t\tcontinue?: boolean;\n\t};\n\treturn {\n\t\t...rest,\n\t\tinput,\n\t\t...(params && { params }),\n\t\t...(next !== undefined && { continue: next }),\n\t} as z.core.$ZodRawIssue;\n}\n",
18
+ "import type { Format, StringSchema } from './format';\nimport { formats as builtIns, type FormatName } from './index';\nimport { marked } from './marked';\n\n/**\n * The application's own formats, keyed by the name `@constraint(format:\n * \"...\")` gives them: each a Zod string schema, `z.string()` or a string\n * format (`z.email()`), narrowed (`.regex()`, `.refine()`) but never\n * transformed nor rewritten (`.trim()`, `.toLowerCase()`, `z.url()`,\n * `z.coerce.string()`), so the resolver receives what was sent.\n */\nexport type FormatSchemas = { readonly [name: string]: StringSchema };\n\n/**\n * `F` with every key that names a built-in format typed `never`, so\n * replacing one is a type error before it is a startup error. The keys are\n * optional: a record typed wider than its literal (`FormatSchemas`,\n * `Record<string, z.ZodString>`) may hold none of them, and passes.\n */\nexport type OwnFormats<F extends FormatSchemas> = F & {\n\treadonly [K in keyof F & FormatName]?: never;\n};\n\nconst NAME = /^[a-z][a-z0-9-]*$/;\n\n/**\n * Every format `@constraint(format: \"...\")` can name: the built-in ones,\n * then the application's own. A lookup is one `Map` read, however many\n * formats there are.\n */\nexport class FormatRegistry {\n\treadonly #formats = new Map<string, Format>();\n\t#async: string | undefined;\n\n\t/**\n\t * Fails, naming the format, on a bad name, a built-in's name, a schema\n\t * that is not a string's, one zod cannot run, or one that rewrites the\n\t * value.\n\t */\n\tconstructor(own: FormatSchemas = {}) {\n\t\tfor (const format of Object.values(builtIns))\n\t\t\tthis.#formats.set(format.name, format);\n\t\tfor (const [name, schema] of Object.entries(own)) {\n\t\t\tif (!NAME.test(name)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Invalid format name ${JSON.stringify(name)}: write it in lowercase letters, digits and hyphens, starting with a letter.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (this.#formats.has(name)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`The format \"${name}\" is built in: give yours another name.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!isStringSchema(schema)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`The format \"${name}\" is not a Zod string schema: write z.string() or a string format such as z.email(), narrowed with .regex() or .refine(), never transformed.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!runnable(schema)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`The format \"${name}\" cannot be run: its definition reads type: 'string' but it has no safeParseAsync, check, refine or catch, so it is not a schema of zod 4's classic API. Pass the schema z.string() or a string format returns, not an object shaped like one.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (rewrites(schema)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`The format \"${name}\" rewrites the value (.trim(), .toLowerCase(), .toUpperCase(), .normalize(), .slugify(), .overwrite(), z.url(), z.httpUrl() or z.coerce.string()): refuse what is not canonical with .regex() or .refine() instead, so the server and the client check the value as it was sent.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst narrowed = marked(name, schema, () => {\n\t\t\t\tthis.#async = name;\n\t\t\t});\n\t\t\tconst own = narrowed((schema) => schema);\n\t\t\tthis.#formats.set(name, { name, toZod: () => own, narrowed });\n\t\t}\n\t}\n\n\t/** The format named `name`, or an error that lists the known ones. */\n\tnamed(name: string): Format {\n\t\tconst format = this.#formats.get(name);\n\t\tif (format) return format;\n\t\tthrow new Error(\n\t\t\t`Unknown @constraint format \"${name}\". Known formats: ${[...this.#formats.keys()].join(', ')}.`,\n\t\t);\n\t}\n\n\t/**\n\t * The format of the application that last went async, then forgotten: read\n\t * right after a synchronous parse threw zod's `$ZodAsyncError`, it names the\n\t * format that made it throw (zod stops at the first check that returns a\n\t * promise, and only an application's format can).\n\t */\n\ttakeAsync(): string | undefined {\n\t\tconst name = this.#async;\n\t\tthis.#async = undefined;\n\t\treturn name;\n\t}\n}\n\n/**\n * Whether a value is a Zod string schema, read from its definition rather\n * than `instanceof`, so a schema from another copy of zod is recognised. A\n * transform or a codec is a pipe, `.optional()` an optional: neither passes.\n */\nfunction isStringSchema(value: unknown): value is StringSchema {\n\treturn definition(value)?.type === 'string';\n}\n\n/**\n * Whether zod can run the schema through the public API `marked` uses on\n * every value, so a definition alone (an object that only reads `type:\n * 'string'`) fails startup rather than each request.\n */\nfunction runnable(schema: StringSchema): boolean {\n\tconst api = schema as unknown as Record<string, unknown>;\n\treturn ['safeParseAsync', 'check', 'refine', 'catch'].every(\n\t\t(method) => typeof api[method] === 'function',\n\t);\n}\n\n/**\n * Whether a string schema rewrites the value it checks, though it stays\n * `type: 'string'`: `z.coerce.string()` (`coerce: true`) turns a number\n * into a string; `z.url()`, `z.httpUrl()` and `.url()` (`format: 'url'`, as\n * the schema or as one of its checks) trim the value and drop its tabs and\n * newlines, or normalise it; `.trim()`, `.toLowerCase()`, `.toUpperCase()`,\n * `.normalize()`, `.slugify()` and `.overwrite()` are each a check whose\n * definition reads `check: 'overwrite'`. Every other string format of zod 4\n * only checks. `format: 'url'` is read as the format's name, so a\n * `z.stringFormat('url', …)` of the application's is refused too. The\n * server checks the value as sent; a client chaining rules on a rewriting\n * schema would check the rewritten one. A custom check that sets the value\n * cannot be read here: `marked` catches it when it runs.\n */\nfunction rewrites(schema: StringSchema): boolean {\n\tconst def = definition(schema);\n\tif (def?.coerce || def?.format === 'url') return true;\n\treturn (def?.checks ?? []).some((check) => {\n\t\tconst own = definition(check);\n\t\treturn own?.check === 'overwrite' || own?.format === 'url';\n\t});\n}\n\ntype Definition = {\n\ttype?: unknown;\n\tcoerce?: unknown;\n\tformat?: unknown;\n\tcheck?: unknown;\n\tchecks?: readonly unknown[];\n};\n\nfunction definition(value: unknown): Definition | undefined {\n\treturn (value as { _zod?: { def?: Definition } } | null)?._zod?.def;\n}\n\nconst builtInRegistry = new FormatRegistry();\nconst registries = new WeakMap<FormatSchemas, FormatRegistry>();\n\n/**\n * The registry of a set of formats, built (and checked) once per record: a\n * code generator hands the same record for every field.\n */\nexport function registryOf(own?: FormatSchemas): FormatRegistry {\n\tif (!own) return builtInRegistry;\n\tlet registry = registries.get(own);\n\tif (!registry) {\n\t\tregistry = new FormatRegistry(own);\n\t\tregistries.set(own, registry);\n\t}\n\treturn registry;\n}\n",
19
+ "import type { GraphQLArgument, GraphQLField, GraphQLObjectType } from 'graphql';\nimport { z } from 'zod';\nimport { constraintsOn } from './constraints';\nimport type { InputSchemas } from './input-schema';\n\n/**\n * The schema of a field's arguments, or `undefined` when none of them can\n * break a constraint, so a field with nothing to check is left untouched.\n * `parent` is the type's name, for errors: `Mutation.signUp(input:)`.\n */\nexport function argsSchemaOf(\n\tinputs: InputSchemas,\n\tparent: string,\n\tfield: GraphQLField<unknown, unknown>,\n): z.ZodType | undefined {\n\tif (!field.args.some((arg) => inputs.needsCheck(arg))) return undefined;\n\treturn z.object(\n\t\tObject.fromEntries(\n\t\t\tfield.args.map((arg) => [\n\t\t\t\targ.name,\n\t\t\t\tinputs.of(arg, `${parent}.${field.name}(${arg.name}:)`),\n\t\t\t]),\n\t\t),\n\t);\n}\n\n/** The constraints of an argument as written, sorted: `maxLength: 5, min: 1`. */\nfunction signature(inputs: InputSchemas, arg: GraphQLArgument): string {\n\treturn constraintsOn(inputs.directive, arg.astNode)\n\t\t.map(({ rule, value }) => `${rule.argument}: ${JSON.stringify(value)}`)\n\t\t.sort()\n\t\t.join(', ');\n}\n\n/** A signature as it reads in an error. */\nconst written = (signature: string) =>\n\tsignature ? `@constraint(${signature})` : 'no @constraint';\n\n/**\n * Fails when an object type's field does not repeat the `@constraint` its\n * interface writes on an argument. The object's field is the one that\n * resolves, and graphql lets it redeclare the argument bare: the interface's\n * constraint would then check nothing, in silence.\n */\nexport function assertInterfaceConstraintsKept(\n\tinputs: InputSchemas,\n\ttype: GraphQLObjectType,\n): void {\n\tfor (const contract of type.getInterfaces()) {\n\t\tfor (const [name, declared] of Object.entries(contract.getFields())) {\n\t\t\tconst field = type.getFields()[name];\n\t\t\tfor (const arg of declared.args) {\n\t\t\t\tconst wanted = signature(inputs, arg);\n\t\t\t\tif (!wanted) continue;\n\t\t\t\tconst own = field?.args.find(\n\t\t\t\t\t({ name: argName }) => argName === arg.name,\n\t\t\t\t);\n\t\t\t\tconst found = own ? signature(inputs, own) : wanted;\n\t\t\t\tif (found !== wanted) {\n\t\t\t\t\tconst verb = found ? 'differs on' : 'is not repeated on';\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`@constraint on ${contract.name}.${name}(${arg.name}:) ${verb} ${type.name}.${name}(${arg.name}:), which resolves it (${written(wanted)} there, ${written(found)} here). Write the same @constraint on both.`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n",
20
+ "import {\n\ttype ConstValueNode,\n\ttype GraphQLArgument,\n\ttype GraphQLDirective,\n\ttype GraphQLInputField,\n\ttype GraphQLInputObjectType,\n\ttype GraphQLInputType,\n\ttype GraphQLSchema,\n\tgetNamedType,\n\tisInputObjectType,\n\tisListType,\n\tisNonNullType,\n\tvalueFromAST,\n} from 'graphql';\nimport { z } from 'zod';\nimport { type FormatRegistry, registryOf } from '../formats/registry';\nimport { applyRule } from '../rules';\nimport type { RuleContext } from '../rules/rule';\nimport { type Constraint, constraintsOn } from './constraints';\nimport { assertObjectTargets, leafSchema } from './leaf';\n\n/**\n * Builds the schemas of the arguments and input fields of one GraphQL\n * schema, once each: an input type is walked a single time however many\n * fields use it, and a recursive one (`input Filter { and: [Filter!] }`) is\n * reached through `z.lazy`.\n */\nexport class InputSchemas {\n\treadonly directive: GraphQLDirective | undefined;\n\treadonly #context: RuleContext;\n\treadonly #objects = new Map<string, z.ZodType>();\n\treadonly #defaults: {\n\t\tschema: z.ZodType;\n\t\tliteral: ConstValueNode;\n\t\ttype: GraphQLInputType;\n\t\twhere: string;\n\t}[] = [];\n\t/** The input types a value can break a constraint inside. */\n\treadonly #constrained = new Set<string>();\n\n\t/** `formats`: the built-in ones by default, the application's added. */\n\tconstructor(schema: GraphQLSchema, formats: FormatRegistry = registryOf()) {\n\t\tthis.#context = { formats };\n\t\tthis.directive = schema.getDirective('constraint') ?? undefined;\n\t\tconst objects = Object.values(schema.getTypeMap()).filter(\n\t\t\tisInputObjectType,\n\t\t);\n\t\t// A fixpoint, not a memoised walk: in a cycle, a type visited while it\n\t\t// is still being decided would be cached as unconstrained for good.\n\t\tfor (let changed = true; changed; ) {\n\t\t\tchanged = false;\n\t\t\tfor (const type of objects) {\n\t\t\t\tif (this.#constrained.has(type.name)) continue;\n\t\t\t\tconst constrained = Object.values(type.getFields()).some(\n\t\t\t\t\t(field) =>\n\t\t\t\t\t\tconstraintsOn(this.directive, field.astNode).length > 0 ||\n\t\t\t\t\t\tthis.isConstrained(field.type),\n\t\t\t\t);\n\t\t\t\tif (constrained) {\n\t\t\t\t\tthis.#constrained.add(type.name);\n\t\t\t\t\tchanged = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Whether a value of this type can break a constraint anywhere inside. */\n\tisConstrained(type: GraphQLInputType): boolean {\n\t\tconst named = getNamedType(type);\n\t\treturn isInputObjectType(named) && this.#constrained.has(named.name);\n\t}\n\n\t/**\n\t * Builds every constrained input type, reached by an argument or not, so\n\t * a constraint that cannot apply fails at startup wherever it is written.\n\t */\n\tbuildAll(schema: GraphQLSchema): void {\n\t\tfor (const type of Object.values(schema.getTypeMap())) {\n\t\t\tif (isInputObjectType(type)) this.#object(type);\n\t\t}\n\t}\n\n\t/** Whether an argument or input field needs checking at all. */\n\tneedsCheck(input: GraphQLArgument | GraphQLInputField): boolean {\n\t\treturn (\n\t\t\tconstraintsOn(this.directive, input.astNode).length > 0 ||\n\t\t\tthis.isConstrained(input.type)\n\t\t);\n\t}\n\n\t/** The schema of one argument or input field, `where` naming it in errors. */\n\tof(input: GraphQLArgument | GraphQLInputField, where: string): z.ZodType {\n\t\tconst schema = this.#typed(\n\t\t\tinput.type,\n\t\t\tconstraintsOn(this.directive, input.astNode),\n\t\t\twhere,\n\t\t);\n\t\tconst literal = input.astNode?.defaultValue;\n\t\tif (literal)\n\t\t\tthis.#defaults.push({ schema, literal, type: input.type, where });\n\t\treturn schema;\n\t}\n\n\t/**\n\t * Fails when a default value breaks its own constraint: every request that\n\t * leaves the value out would be refused for something the client never\n\t * sent. Run once every schema is built, so a recursive type is complete.\n\t */\n\tcheckDefaults(): void {\n\t\tfor (const { schema, literal, type, where } of this.#defaults.splice(0)) {\n\t\t\t// Coerced as graphql coerces it: a single value for a list, an input\n\t\t\t// object's own field defaults. One graphql refuses is its to report.\n\t\t\tconst value = valueFromAST(literal, type);\n\t\t\tif (value === undefined) continue;\n\t\t\tlet result: z.ZodSafeParseResult<unknown>;\n\t\t\ttry {\n\t\t\t\tresult = schema.safeParse(value);\n\t\t\t} catch (error) {\n\t\t\t\t// Thrown by this zod: only the formats' wrapper, ours, goes async.\n\t\t\t\tif (!(error instanceof z.core.$ZodAsyncError)) throw error;\n\t\t\t\tconst format = this.#context.formats.takeAsync();\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`The default value of ${where} cannot be checked at startup: ${format ? `the format \"${format}\"` : 'its format'} checks asynchronously, and a default value is checked synchronously. Drop the default, or move the async check out of the format into validated().`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!result.success) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`The default value of ${where} breaks its @constraint: ${result.error.issues[0]?.message}`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t#typed(\n\t\ttype: GraphQLInputType,\n\t\tconstraints: readonly Constraint[],\n\t\twhere: string,\n\t): z.ZodType {\n\t\tif (isNonNullType(type))\n\t\t\treturn this.#required(type.ofType, constraints, where);\n\t\treturn this.#required(type, constraints, where).nullish();\n\t}\n\n\t#required(\n\t\ttype: GraphQLInputType,\n\t\tconstraints: readonly Constraint[],\n\t\twhere: string,\n\t): z.ZodType {\n\t\tif (isNonNullType(type))\n\t\t\treturn this.#required(type.ofType, constraints, where);\n\t\tif (isListType(type)) {\n\t\t\t// minItems and maxItems are the list's; every other rule is its items'.\n\t\t\tconst own = constraints.filter(({ rule }) => rule.target === 'list');\n\t\t\tconst items = constraints.filter(({ rule }) => rule.target !== 'list');\n\t\t\tlet list: z.ZodType = z.array(this.#typed(type.ofType, items, where));\n\t\t\tfor (const { rule, value } of own)\n\t\t\t\tlist = applyRule(rule, list, value, this.#context);\n\t\t\treturn list;\n\t\t}\n\t\tif (isInputObjectType(type)) {\n\t\t\tassertObjectTargets(type.name, constraints, where);\n\t\t\treturn this.#object(type);\n\t\t}\n\t\treturn leafSchema(type, constraints, where, this.#context);\n\t}\n\n\t#object(type: GraphQLInputObjectType): z.ZodType {\n\t\tif (!this.isConstrained(type)) return z.unknown();\n\t\tconst built = this.#objects.get(type.name);\n\t\tif (built) return built;\n\t\t// Registered before the walk, so a field that comes back here ends.\n\t\tlet schema: z.ZodType | undefined;\n\t\tthis.#objects.set(\n\t\t\ttype.name,\n\t\t\tz.lazy(() => schema as z.ZodType),\n\t\t);\n\t\tschema = z.object(\n\t\t\tObject.fromEntries(\n\t\t\t\tObject.values(type.getFields()).map((field) => [\n\t\t\t\t\tfield.name,\n\t\t\t\t\tthis.of(field, `${type.name}.${field.name}`),\n\t\t\t\t]),\n\t\t\t),\n\t\t);\n\t\tthis.#objects.set(type.name, schema);\n\t\treturn schema;\n\t}\n}\n",
21
+ "import {\n\tGraphQLBoolean,\n\tGraphQLFloat,\n\tGraphQLID,\n\tGraphQLInt,\n\ttype GraphQLLeafType,\n\tGraphQLString,\n} from 'graphql';\nimport { z } from 'zod';\nimport { applyRule, rules } from '../rules';\nimport type { RuleContext, Target } from '../rules/rule';\nimport type { Constraint } from './constraints';\n\n/** The kind of value each built-in scalar holds once graphql parsed it. */\nconst kinds: Record<string, Exclude<Target, 'list'>> = {\n\t[GraphQLString.name]: 'string',\n\t[GraphQLID.name]: 'string',\n\t[GraphQLInt.name]: 'number',\n\t[GraphQLFloat.name]: 'number',\n};\n\nfunction baseOf(type: GraphQLLeafType): z.ZodType {\n\tif (type.name === GraphQLInt.name) return z.number().int();\n\treturn kinds[type.name] === 'number' ? z.number() : z.string();\n}\n\n/**\n * Fails unless every constraint applies to a value of `type`: `minLength` on\n * an `Int`, anything on a custom scalar or an enum, fails, naming `where`.\n * The runtime and the code generator refuse the same schemas with the same\n * message.\n */\nexport function assertLeafTargets(\n\ttype: GraphQLLeafType,\n\tconstraints: readonly Constraint[],\n\twhere: string,\n): void {\n\tconst misplaced = constraints.find(({ rule }) => rule.target === 'list');\n\tif (misplaced) throw misplacedOn(misplaced, where, type.name);\n\tconst kind = kinds[type.name];\n\tconst wrong = constraints.find(({ rule }) => rule.target !== kind);\n\tif (wrong) throw misplacedOn(wrong, where, type.name);\n}\n\n/** Fails when an input object carries a constraint: none applies to it. */\nexport function assertObjectTargets(\n\ttypeName: string,\n\tconstraints: readonly Constraint[],\n\twhere: string,\n): void {\n\tconst first =\n\t\tconstraints.find(({ rule }) => rule.target === 'list') ?? constraints[0];\n\tif (first) throw misplacedOn(first, where, typeName);\n}\n\nfunction misplacedOn(\n\t{ rule }: Constraint,\n\twhere: string,\n\ttypeName: string,\n): Error {\n\treturn new Error(\n\t\t`@constraint(${rule.argument}) on ${where} needs ${describeTarget(rule.target)}, not ${typeName}.`,\n\t);\n}\n\n/**\n * The schema of a scalar or enum value with its constraints applied. A leaf\n * without any is left as graphql parsed it. A constraint that cannot apply\n * fails here, at startup.\n */\nexport function leafSchema(\n\ttype: GraphQLLeafType,\n\tconstraints: readonly Constraint[],\n\twhere: string,\n\tcontext: RuleContext,\n): z.ZodType {\n\tif (constraints.length === 0) return z.unknown();\n\tassertLeafTargets(type, constraints, where);\n\tconst [first, ...rest] = constraints;\n\tconst narrow = (schema: z.ZodType) =>\n\t\trest.reduce(\n\t\t\t(narrowed, { rule, value }) => applyRule(rule, narrowed, value, context),\n\t\t\tschema,\n\t\t);\n\t// An application's format runs the rules after it inside itself.\n\tconst narrowed =\n\t\tfirst?.rule === rules.format\n\t\t\t? context.formats.named(String(first.value)).narrowed\n\t\t\t: undefined;\n\tif (narrowed) return narrowed(narrow);\n\treturn constraints.reduce(\n\t\t(schema, { rule, value }) => applyRule(rule, schema, value, context),\n\t\tbaseOf(type),\n\t);\n}\n\n/** The source of a built-in scalar's schema, before its constraints. */\nexport function baseCode(type: GraphQLLeafType): string | undefined {\n\t// graphql's Int is 32-bit: the client refuses what it refuses.\n\tif (type.name === GraphQLInt.name) return 'z.int32()';\n\tif (type.name === GraphQLFloat.name) return 'z.number()';\n\tif (type.name === GraphQLBoolean.name) return 'z.boolean()';\n\treturn kinds[type.name] === 'string' ? 'z.string()' : undefined;\n}\n\n/** What a rule's target reads as in an error. */\nexport function describeTarget(target: Target): string {\n\tif (target === 'string') return 'a String or an ID';\n\tif (target === 'number') return 'an Int or a Float';\n\treturn 'a list';\n}\n"
22
+ ],
23
+ "mappings": "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",
24
+ "debugId": "F2C2C0D2BA61CB1B64756E2164756E21",
25
+ "names": []
26
+ }
package/dist/codegen.js CHANGED
@@ -8,7 +8,7 @@ import {
8
8
  assertObjectTargets,
9
9
  baseCode,
10
10
  checkConstraints2
11
- } from "./chunks/index-1mzzydy3.js";
11
+ } from "./chunks/index-twevz7yc.js";
12
12
  // src/builder/input-code.ts
13
13
  import {
14
14
  getNamedType,
@@ -1,4 +1,5 @@
1
1
  import type { z } from 'zod';
2
+ import type { Narrow } from './marked.js';
2
3
  /** A string schema, plain or a format (`z.email()` is not a `z.ZodString`). */
3
4
  export type StringSchema = z.ZodString | z.ZodStringFormat;
4
5
  /**
@@ -11,6 +12,13 @@ export interface Format<N extends string = string> {
11
12
  readonly name: N;
12
13
  readonly toZod: () => StringSchema;
13
14
  readonly toCode?: () => string;
15
+ /**
16
+ * An application's format, narrowed by the rules written after it
17
+ * (`leafSchema` hands them): they run inside it, after its checks, so
18
+ * they see its abort even once it went async. A built-in format has none:
19
+ * the rules are chained on `toZod()`.
20
+ */
21
+ readonly narrowed?: (narrow: Narrow) => StringSchema;
14
22
  }
15
23
  /** A format this package ships: written twice, as a schema and as source. */
16
24
  export interface BuiltInFormat<N extends string = string> extends Format<N> {
@@ -1 +1 @@
1
- {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/formats/format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAE7B,+EAA+E;AAC/E,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,eAAe,CAAC;AAE3D;;;;;GAKG;AACH,MAAM,WAAW,MAAM,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM;IAChD,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IACjB,QAAQ,CAAC,KAAK,EAAE,MAAM,YAAY,CAAC;IACnC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,MAAM,CAAC;CAC/B;AAED,6EAA6E;AAC7E,MAAM,WAAW,aAAa,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,CAAE,SAAQ,MAAM,CAAC,CAAC,CAAC;IAC1E,QAAQ,CAAC,MAAM,EAAE,MAAM,MAAM,CAAC;CAC9B;AAED,8DAA8D;AAC9D,wBAAgB,YAAY,CAAC,KAAK,CAAC,CAAC,SAAS,MAAM,EAClD,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,GACtB,aAAa,CAAC,CAAC,CAAC,CAElB"}
1
+ {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/formats/format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAEvC,+EAA+E;AAC/E,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,eAAe,CAAC;AAE3D;;;;;GAKG;AACH,MAAM,WAAW,MAAM,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM;IAChD,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IACjB,QAAQ,CAAC,KAAK,EAAE,MAAM,YAAY,CAAC;IACnC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,MAAM,CAAC;IAC/B;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,YAAY,CAAC;CACrD;AAED,6EAA6E;AAC7E,MAAM,WAAW,aAAa,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,CAAE,SAAQ,MAAM,CAAC,CAAC,CAAC;IAC1E,QAAQ,CAAC,MAAM,EAAE,MAAM,MAAM,CAAC;CAC9B;AAED,8DAA8D;AAC9D,wBAAgB,YAAY,CAAC,KAAK,CAAC,CAAC,SAAS,MAAM,EAClD,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,GACtB,aAAa,CAAC,CAAC,CAAC,CAElB"}
@@ -0,0 +1,42 @@
1
+ import { z } from 'zod';
2
+ import type { StringSchema } from './format.js';
3
+ /** The rules written after a format, applied to the schema they narrow. */
4
+ export type Narrow = (schema: StringSchema) => z.ZodType;
5
+ /**
6
+ * The application's schema as a plain string schema, narrowed by the rules
7
+ * written after it (`narrow`), each of its issues re-raised as it was (code,
8
+ * message, and an abort that stops those rules) and marked as the format's:
9
+ * a `.regex()` inside it is the format's refusal, not `pattern`'s. The value
10
+ * is checked, never changed: a schema that still returns another value (a
11
+ * custom `.check()` setting `payload.value`, which `rewrites` cannot see)
12
+ * throws, naming the format, as a resolver's bug would.
13
+ *
14
+ * Only zod's public API runs the schema, whatever zod 4 copy it comes from:
15
+ * `safeParseAsync`, `check` pushing to `ctx.issues`, `refine` (with
16
+ * `when`), `catch`, and the issues they return. A zod release that changes
17
+ * its internals changes nothing here.
18
+ *
19
+ * - **Once per value, never a dropped promise.** The schema runs through
20
+ * `safeParseAsync` only, never a synchronous `safeParse` that would start
21
+ * an async check and drop its promise. A `.catch()` and a `.refine()`
22
+ * chained last tell, as soon as the call returns, whether the run
23
+ * finished synchronously (zod runs a schema's checks within the call
24
+ * until one returns a promise): then its result is used at once, so a
25
+ * synchronous parse (a default value's check at startup) still works.
26
+ * Otherwise the promise is returned to the enclosing parse, with a
27
+ * handler, and `onAsync` is told: a synchronous parse throws zod's async
28
+ * error and `checkDefaults` names the format.
29
+ * - **An abort** is read from two refinements chained after the schema's
30
+ * checks: a plain one, which zod skips after any issue that does not
31
+ * continue (`abort: true`, an issue a `.check()` pushed with no
32
+ * `continue`), and one with a `when`, skipped only after `continue:
33
+ * false`. Each marks a refused run's issues when it ran. The issues are
34
+ * then replayed, with that same `continue`, through a `z.string()`
35
+ * narrowed by the rules, so zod itself decides which rules run, as it does
36
+ * on the client where they are chained on the schema.
37
+ * - **Once async**, zod on the client runs the rules before the async
38
+ * check's issues arrive, whatever its abort: the rules run here too, and
39
+ * the format's issues come first.
40
+ */
41
+ export declare function marked(name: string, schema: StringSchema, onAsync: () => void): (narrow: Narrow) => StringSchema;
42
+ //# sourceMappingURL=marked.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"marked.d.ts","sourceRoot":"","sources":["../../src/formats/marked.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAE7C,2EAA2E;AAC3E,MAAM,MAAM,MAAM,GAAG,CAAC,MAAM,EAAE,YAAY,KAAK,CAAC,CAAC,OAAO,CAAC;AAUzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAgB,MAAM,CACrB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,MAAM,IAAI,GACjB,CAAC,MAAM,EAAE,MAAM,KAAK,YAAY,CA4ElC"}
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/formats/registry.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACrD,OAAO,EAAuB,KAAK,UAAU,EAAE,MAAM,SAAS,CAAC;AAE/D;;;;;;GAMG;AACH,MAAM,MAAM,aAAa,GAAG;IAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,GAAG,YAAY,CAAA;CAAE,CAAC;AAEtE;;;;;GAKG;AACH,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,aAAa,IAAI,CAAC,GAAG;IACrD,QAAQ,EAAE,CAAC,IAAI,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,EAAE,KAAK;CAC5C,CAAC;AAIF;;;;GAIG;AACH,qBAAa,cAAc;;IAI1B;;;;OAIG;gBACS,GAAG,GAAE,aAAkB;IAoCnC,sEAAsE;IACtE,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAQ3B;;;;;OAKG;IACH,SAAS,IAAI,MAAM,GAAG,SAAS;CAK/B;AA4HD;;;GAGG;AACH,wBAAgB,UAAU,CAAC,GAAG,CAAC,EAAE,aAAa,GAAG,cAAc,CAQ9D"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/formats/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACrD,OAAO,EAAuB,KAAK,UAAU,EAAE,MAAM,SAAS,CAAC;AAG/D;;;;;;GAMG;AACH,MAAM,MAAM,aAAa,GAAG;IAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,GAAG,YAAY,CAAA;CAAE,CAAC;AAEtE;;;;;GAKG;AACH,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,aAAa,IAAI,CAAC,GAAG;IACrD,QAAQ,EAAE,CAAC,IAAI,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,EAAE,KAAK;CAC5C,CAAC;AAIF;;;;GAIG;AACH,qBAAa,cAAc;;IAI1B;;;;OAIG;gBACS,GAAG,GAAE,aAAkB;IAqCnC,sEAAsE;IACtE,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAQ3B;;;;;OAKG;IACH,SAAS,IAAI,MAAM,GAAG,SAAS;CAK/B;AA6DD;;;GAGG;AACH,wBAAgB,UAAU,CAAC,GAAG,CAAC,EAAE,aAAa,GAAG,cAAc,CAQ9D"}
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunks/index-xcaf9kes.js";
5
5
  import {
6
6
  checkConstraints2
7
- } from "./chunks/index-1mzzydy3.js";
7
+ } from "./chunks/index-twevz7yc.js";
8
8
 
9
9
  // src/bad-user-input.ts
10
10
  import { GraphQLError } from "graphql";
@@ -302,10 +302,9 @@ What a format of your own is:
302
302
  then at most 64 characters. A check of yours with `abort: true`
303
303
  (`.refine(…, { message, abort: true })`) stops the rules after it, on the
304
304
  server as in a generated client: only its issue is returned. Once an async
305
- check of your format is pending, the rules have already run on the server:
306
- their issues come first (the error's message is then a rule's, not your
307
- format's) and the abort stops nothing. Put an aborting check before any
308
- async one.
305
+ check of your format is pending, a client has already run the rules, so
306
+ the abort stops nothing on either side; the server lists your format's
307
+ issues first. Put an aborting check before any async one.
309
308
  - **Its messages are yours.** A refusal reads as your schema writes it (the
310
309
  package's own messages never name the value; yours may, so keep the input
311
310
  out of them if your logs or clients should not see it). Every issue your
@@ -319,13 +318,30 @@ What a format of your own is:
319
318
  - **Named in lowercase letters, digits and hyphens**, starting with a letter
320
319
  (`siret`, `work-email`, `iso-6346`). A built-in name (`email`, `uuid`, …)
321
320
  cannot be replaced: it is a type error, and refused at startup.
322
- - **An async check stays async.** `withValidation` parses asynchronously, so a
323
- `.refine(async …)` works in a request, from this package's zod or another
324
- copy. It runs once per value, and when it rejects (`db down`) the operation
325
- fails with that error, as a resolver's would. A default value is checked
326
- at startup synchronously, so a field whose format is async cannot have a
321
+ - **An async check stays async, and runs once.** `withValidation` parses
322
+ asynchronously, so a `.refine(async …)` (or an async `.superRefine()`, or
323
+ any check returning a promise) works in a request, from this package's zod
324
+ or another copy. It runs once per value, from the first, and when it
325
+ rejects (`db down`) the operation fails with that error, as a resolver's
326
+ would: no rejection is left unhandled. A default value is checked at
327
+ startup synchronously, so a field whose format is async cannot have a
327
328
  default: startup throws `The default value of Query.a(s:) cannot be checked
328
- at startup: the format "free" checks asynchronously, …`.
329
+ at startup: the format "free" checks asynchronously, …`. A check that
330
+ throws on the default value reads the same, since its error ends a run
331
+ startup cannot wait for.
332
+
333
+ - **Only Zod's public API runs it.** Your format is parsed with
334
+ `safeParseAsync` only, never a synchronous `safeParse` that would start an
335
+ async check and drop it; a `.catch()` and `.refine()`s chained after your
336
+ checks tell whether the run finished at once and which abort stopped it,
337
+ and the rules after it run inside it, replayed on its issues as Zod runs
338
+ them when chained on your schema. No Zod internal is called, so a Zod 4
339
+ release that changes its internals changes nothing here, and a format
340
+ from another copy of Zod (another version included) gets its messages
341
+ from that copy's configuration (`z.config()`). Startup still reads the
342
+ schema's definition (`_zod.def`, Zod's introspection) to refuse what
343
+ rewrites the value. The cost, measured on Bun 1.4.2 against 0.3.0: about
344
+ 0.1 µs more per accepted value and 1.5 µs more per refused one.
329
345
 
330
346
  Call `withValidation` once, with every format. A second call on the same
331
347
  schema wraps nothing when its record has the same names, each the very same
@@ -124,15 +124,17 @@ resolver:
124
124
  const formatSchemas = { code: z.string().regex(/^[0-9]+$/) }; // not .transform(Number)
125
125
  ```
126
126
 
127
- ### `The format "code" cannot be run: its definition reads type: 'string' but it has no _zod.run, so it was not built by zod 4. Pass the schema z.string() or a string format returns, not an object shaped like one.`
127
+ ### `The format "code" cannot be run: its definition reads type: 'string' but it has no safeParseAsync, check, refine or catch, so it is not a schema of zod 4's classic API. Pass the schema z.string() or a string format returns, not an object shaped like one.`
128
128
 
129
129
  **When:** calling `withValidation` (or generating with
130
130
  `@nxgt/graphql-codegen-zod`) with `formats` whose value has a string
131
- schema's definition (`_zod.def.type` is `'string'`) but no `_zod.run`: an
132
- object built by hand or a test double shaped like a schema. A record typed
133
- loosely (`as never`, `any`) gets past the compiler; this check does not.
134
- **Why:** every request runs the format through its `_zod.run`; without it,
135
- each request would fail with `schema._zod.run is not a function`, a message
131
+ schema's definition (`_zod.def.type` is `'string'`) but not the methods of
132
+ Zod's classic API: an object built by hand, a test double shaped like a
133
+ schema, or a `zod/mini` schema. A record typed loosely (`as never`, `any`)
134
+ gets past the compiler; this check does not.
135
+ **Why:** every request runs the format through `safeParseAsync`, and reads
136
+ its abort and its result through `check`, `refine` and `catch`; without them,
137
+ each request would fail with `schema.safeParseAsync is not a function`, a message
136
138
  that reaches the client. Startup refuses it instead.
137
139
  **Fix:** pass the schema zod built, not an object shaped like one:
138
140
 
@@ -334,12 +336,16 @@ type Query { a(name: String = "xy" @constraint(minLength: 2)): Int }
334
336
 
335
337
  **When:** calling `withValidation` (or `checkConstraints`), on an argument or
336
338
  input field with a default value whose format is one of yours with an async
337
- check (`.refine(async …)`), from this package's zod or another copy.
339
+ check (`.refine(async …)`, an async `.superRefine()`, any check returning a
340
+ promise), from this package's zod or another copy, or whose check throws on
341
+ the default value: its error ends a run startup cannot wait for, so it reads
342
+ as async too.
338
343
  **Why:** a default value is checked at startup, synchronously; Zod refuses
339
344
  to run an async check there. In a request, the arguments are parsed
340
345
  asynchronously and the check works.
341
346
  **Fix:** drop the default, or keep the async check out of the format and run
342
- it with [`validated`](guide/errors.md#validated).
347
+ it with [`validated`](guide/errors.md#validated); a check that throws is a
348
+ bug to fix in the format.
343
349
 
344
350
  ### `@constraint on @cached(ttl:) checks nothing: a directive's argument reaches no resolver. Remove it.`
345
351
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nxgt/graphql-validation",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "Validate GraphQL arguments and input fields with @constraint directives, checked by Zod schemas, for graphql 16 and 17",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1,25 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../src/builder/constraints.ts", "../src/builder/check-constraints.ts", "../src/formats/registry.ts", "../src/formats/byte.ts", "../src/formats/format.ts", "../src/formats/date.ts", "../src/formats/date-time.ts", "../src/formats/email.ts", "../src/formats/ipv4.ts", "../src/formats/ipv6.ts", "../src/formats/uri.ts", "../src/formats/uuid.ts", "../src/formats/index.ts", "../src/builder/args-schema.ts", "../src/builder/input-schema.ts", "../src/builder/leaf.ts"],
4
- "sourcesContent": [
5
- "import {\n\ttype DirectiveNode,\n\ttype GraphQLDirective,\n\tgetDirectiveValues,\n} from 'graphql';\nimport { type RegisteredRule, rules } from '../rules';\n\n/** One `@constraint` argument written on an argument or an input field. */\nexport interface Constraint {\n\treadonly rule: RegisteredRule;\n\treadonly value: string | number;\n}\n\n/**\n * The constraints written on a node, base rules (`format`) first so the\n * others narrow the schema they produce. Empty when the schema declares no\n * `@constraint` or the node carries none.\n */\nexport function constraintsOn(\n\tdirective: GraphQLDirective | undefined,\n\tnode:\n\t\t| { readonly directives?: ReadonlyArray<DirectiveNode> | undefined }\n\t\t| null\n\t\t| undefined,\n): Constraint[] {\n\tif (!directive || !node) return [];\n\tconst values =\n\t\tgetDirectiveValues(directive, { directives: node.directives ?? [] }) ?? {};\n\treturn Object.entries(values)\n\t\t.filter(([, value]) => value !== undefined && value !== null)\n\t\t.map(([argument, value]) => ({\n\t\t\trule: rules[argument as keyof typeof rules],\n\t\t\tvalue: value as string | number,\n\t\t}))\n\t\t.sort(\n\t\t\t(a, b) => Number(Boolean(b.rule.base)) - Number(Boolean(a.rule.base)),\n\t\t);\n}\n",
6
- "import {\n\ttype GraphQLDirective,\n\ttype GraphQLField,\n\ttype GraphQLObjectType,\n\ttype GraphQLSchema,\n\tisInterfaceType,\n\tisObjectType,\n} from 'graphql';\nimport type { z } from 'zod';\nimport { assertOwnConstraint } from '../constraint-directive';\nimport { type FormatSchemas, registryOf } from '../formats/registry';\nimport { argsSchemaOf, assertInterfaceConstraintsKept } from './args-schema';\nimport { constraintsOn } from './constraints';\nimport { InputSchemas } from './input-schema';\n\n/**\n * Runs every check `withValidation` makes at startup, so a code generator\n * refuses the same schemas: the declaration is `constraintTypeDefs`', every\n * constraint applies where it is written (in every input type), none sits on\n * a directive's argument, objects keep their interfaces' constraints, and no\n * default value breaks its own. `onArgs` receives each object field's\n * arguments schema, for a field with something to check.\n *\n * `formats` are the application's own, which `@constraint(format: \"...\")`\n * may name beside the built-in ones; they are checked first (name, no\n * built-in replaced, a Zod string schema each).\n *\n * Returns the `@constraint` directive, or `undefined` when the schema\n * declares none (and so carries no constraint).\n */\nexport function checkConstraints(\n\tschema: GraphQLSchema,\n\tonArgs?: (\n\t\ttype: GraphQLObjectType,\n\t\tfield: GraphQLField<unknown, unknown>,\n\t\targs: z.ZodType,\n\t) => void,\n\tformats?: FormatSchemas,\n): GraphQLDirective | undefined {\n\tconst inputs = new InputSchemas(schema, registryOf(formats));\n\tif (!inputs.directive) return undefined;\n\tassertOwnConstraint(inputs.directive);\n\tinputs.buildAll(schema);\n\tassertNoDirectiveArgumentConstrained(inputs, schema);\n\tfor (const type of Object.values(schema.getTypeMap())) {\n\t\tif (type.name.startsWith('__')) continue;\n\t\t// An interface's fields resolve on its objects: built for their errors only.\n\t\tif (isInterfaceType(type)) {\n\t\t\tfor (const field of Object.values(type.getFields()))\n\t\t\t\targsSchemaOf(inputs, type.name, field);\n\t\t}\n\t\tif (!isObjectType(type)) continue;\n\t\tassertInterfaceConstraintsKept(inputs, type);\n\t\tfor (const field of Object.values(type.getFields()) as GraphQLField<\n\t\t\tunknown,\n\t\t\tunknown\n\t\t>[]) {\n\t\t\tconst args = argsSchemaOf(inputs, type.name, field);\n\t\t\tif (args) onArgs?.(type, field, args);\n\t\t}\n\t}\n\tinputs.checkDefaults();\n\treturn inputs.directive;\n}\n\n/**\n * Fails on a `@constraint` written on a directive's argument: graphql allows\n * it there (ARGUMENT_DEFINITION), but no resolver receives that argument, so\n * it would check nothing.\n */\nfunction assertNoDirectiveArgumentConstrained(\n\tinputs: InputSchemas,\n\tschema: GraphQLSchema,\n): void {\n\tfor (const directive of schema.getDirectives()) {\n\t\tfor (const arg of directive.args) {\n\t\t\tif (constraintsOn(inputs.directive, arg.astNode).length > 0) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`@constraint on @${directive.name}(${arg.name}:) checks nothing: a directive's argument reaches no resolver. Remove it.`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n}\n",
7
- "import { z } from 'zod';\nimport { RULE_PARAM } from '../rules/rule';\nimport type { Format, StringSchema } from './format';\nimport { formats as builtIns, type FormatName } from './index';\n\n/**\n * The application's own formats, keyed by the name `@constraint(format:\n * \"...\")` gives them: each a Zod string schema, `z.string()` or a string\n * format (`z.email()`), narrowed (`.regex()`, `.refine()`) but never\n * transformed nor rewritten (`.trim()`, `.toLowerCase()`, `z.url()`,\n * `z.coerce.string()`), so the resolver receives what was sent.\n */\nexport type FormatSchemas = { readonly [name: string]: StringSchema };\n\n/**\n * `F` with every key that names a built-in format typed `never`, so\n * replacing one is a type error before it is a startup error. The keys are\n * optional: a record typed wider than its literal (`FormatSchemas`,\n * `Record<string, z.ZodString>`) may hold none of them, and passes.\n */\nexport type OwnFormats<F extends FormatSchemas> = F & {\n\treadonly [K in keyof F & FormatName]?: never;\n};\n\nconst NAME = /^[a-z][a-z0-9-]*$/;\n\n/**\n * Every format `@constraint(format: \"...\")` can name: the built-in ones,\n * then the application's own. A lookup is one `Map` read, however many\n * formats there are.\n */\nexport class FormatRegistry {\n\treadonly #formats = new Map<string, Format>();\n\t#async: string | undefined;\n\n\t/**\n\t * Fails, naming the format, on a bad name, a built-in's name, a schema\n\t * that is not a string's, one zod cannot run, or one that rewrites the\n\t * value.\n\t */\n\tconstructor(own: FormatSchemas = {}) {\n\t\tfor (const format of Object.values(builtIns))\n\t\t\tthis.#formats.set(format.name, format);\n\t\tfor (const [name, schema] of Object.entries(own)) {\n\t\t\tif (!NAME.test(name)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Invalid format name ${JSON.stringify(name)}: write it in lowercase letters, digits and hyphens, starting with a letter.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (this.#formats.has(name)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`The format \"${name}\" is built in: give yours another name.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!isStringSchema(schema)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`The format \"${name}\" is not a Zod string schema: write z.string() or a string format such as z.email(), narrowed with .regex() or .refine(), never transformed.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!runnable(schema)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`The format \"${name}\" cannot be run: its definition reads type: 'string' but it has no _zod.run, so it was not built by zod 4. Pass the schema z.string() or a string format returns, not an object shaped like one.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (rewrites(schema)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`The format \"${name}\" rewrites the value (.trim(), .toLowerCase(), .toUpperCase(), .normalize(), .slugify(), .overwrite(), z.url(), z.httpUrl() or z.coerce.string()): refuse what is not canonical with .regex() or .refine() instead, so the server and the client check the value as it was sent.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst own = marked(name, schema, () => {\n\t\t\t\tthis.#async = name;\n\t\t\t});\n\t\t\tthis.#formats.set(name, { name, toZod: () => own });\n\t\t}\n\t}\n\n\t/** The format named `name`, or an error that lists the known ones. */\n\tnamed(name: string): Format {\n\t\tconst format = this.#formats.get(name);\n\t\tif (format) return format;\n\t\tthrow new Error(\n\t\t\t`Unknown @constraint format \"${name}\". Known formats: ${[...this.#formats.keys()].join(', ')}.`,\n\t\t);\n\t}\n\n\t/**\n\t * The format of the application that last went async, then forgotten: read\n\t * right after a synchronous parse threw zod's `$ZodAsyncError`, it names the\n\t * format that made it throw (zod stops at the first check that returns a\n\t * promise, and only an application's format can).\n\t */\n\ttakeAsync(): string | undefined {\n\t\tconst name = this.#async;\n\t\tthis.#async = undefined;\n\t\treturn name;\n\t}\n}\n\n/**\n * Whether a value is a Zod string schema, read from its definition rather\n * than `instanceof`, so a schema from another copy of zod is recognised. A\n * transform or a codec is a pipe, `.optional()` an optional: neither passes.\n */\nfunction isStringSchema(value: unknown): value is StringSchema {\n\treturn definition(value)?.type === 'string';\n}\n\n/**\n * Whether zod can run the schema: `marked` calls its `_zod.run` on every\n * value, so a definition alone (an object that only reads `type: 'string'`)\n * would pass startup and fail each request instead.\n */\nfunction runnable(schema: StringSchema): boolean {\n\treturn (\n\t\ttypeof (schema as { _zod?: { run?: unknown } } | null)?._zod?.run ===\n\t\t'function'\n\t);\n}\n\n/**\n * Whether a string schema rewrites the value it checks, though it stays\n * `type: 'string'`: `z.coerce.string()` (`coerce: true`) turns a number\n * into a string; `z.url()`, `z.httpUrl()` and `.url()` (`format: 'url'`, as\n * the schema or as one of its checks) trim the value and drop its tabs and\n * newlines, or normalise it; `.trim()`, `.toLowerCase()`, `.toUpperCase()`,\n * `.normalize()`, `.slugify()` and `.overwrite()` are each a check whose\n * definition reads `check: 'overwrite'`. Every other string format of zod 4\n * only checks. `format: 'url'` is read as the format's name, so a\n * `z.stringFormat('url', …)` of the application's is refused too. The\n * server checks the value as sent; a client chaining rules on a rewriting\n * schema would check the rewritten one. A custom check that sets the value\n * cannot be read here: `marked` catches it when it runs.\n */\nfunction rewrites(schema: StringSchema): boolean {\n\tconst def = definition(schema);\n\tif (def?.coerce || def?.format === 'url') return true;\n\treturn (def?.checks ?? []).some((check) => {\n\t\tconst own = definition(check);\n\t\treturn own?.check === 'overwrite' || own?.format === 'url';\n\t});\n}\n\ntype Definition = {\n\ttype?: unknown;\n\tcoerce?: unknown;\n\tformat?: unknown;\n\tcheck?: unknown;\n\tchecks?: readonly unknown[];\n};\n\nfunction definition(value: unknown): Definition | undefined {\n\treturn (value as { _zod?: { def?: Definition } } | null)?._zod?.def;\n}\n\n/**\n * The application's schema as a plain string schema the rules can narrow,\n * each of its issues re-raised as it was (code, message, and an abort that\n * stops the rules chained after it) and marked as the format's: a\n * `.regex()` inside it is the format's refusal, not `pattern`'s.\n * The value is checked, never changed: a schema that still returns another\n * value (a custom `.check()` setting `payload.value`, which `rewrites`\n * cannot see) throws, naming the format, as a resolver's bug would.\n *\n * The schema runs once per value, through its own `_zod.run` (what its\n * `safeParse` and `safeParseAsync` call) with `async: true`: a schema whose\n * checks are all synchronous returns its result at once, one with an async\n * check returns a promise, whatever zod copy it comes from. Nothing is\n * started and dropped, as a synchronous `safeParse` would drop the promise of\n * an async refine before running it again. That promise, returned to the\n * enclosing parse, gets a handler too: a synchronous parse (a default\n * value's check) throws zod's async error and drops it, and its rejection\n * must not surface as an unhandled one. `onAsync` is told before it is\n * returned.\n */\nfunction marked(\n\tname: string,\n\tschema: StringSchema,\n\tonAsync: () => void,\n): StringSchema {\n\treturn z.string().superRefine((value, ctx) => {\n\t\tconst raise = (result: z.core.ParsePayload<unknown>) => {\n\t\t\tif (result.issues.length === 0 && result.value !== value) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`The format \"${name}\" rewrote the value it checked: a format checks the value and never changes it, so the server and the client check the value as it was sent. Refuse what is not canonical with .regex() or .refine() instead of setting payload.value in a .check().`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tfor (const raw of result.issues) {\n\t\t\t\t// Finalised as the schema's own parse would: its message settled.\n\t\t\t\tconst issue = z.core.util.finalizeIssue(raw, RUN, z.core.config());\n\t\t\t\tconst params = 'params' in issue ? issue.params : undefined;\n\t\t\t\tctx.addIssue({\n\t\t\t\t\t...issue,\n\t\t\t\t\tparams: { ...params, [RULE_PARAM]: 'format' },\n\t\t\t\t\t// finalizeIssue drops `continue`: an aborting check of the format\n\t\t\t\t\t// (`.refine(…, { abort: true })`) still stops the rules after it,\n\t\t\t\t\t// as it does in the generated client. Once the format has gone\n\t\t\t\t\t// async, zod has already run those rules: the abort then stops\n\t\t\t\t\t// nothing, on the server only.\n\t\t\t\t\t...(raw.continue === false && { continue: false }),\n\t\t\t\t} as Parameters<typeof ctx.addIssue>[0]);\n\t\t\t}\n\t\t};\n\t\tconst result = schema._zod.run({ value, issues: [] }, RUN);\n\t\tif (!(result instanceof Promise)) {\n\t\t\traise(result);\n\t\t\treturn undefined;\n\t\t}\n\t\tconst pending = result.then(raise);\n\t\tpending.catch(() => {});\n\t\tonAsync();\n\t\treturn pending;\n\t});\n}\n\n/** How a format runs: async allowed, so an async check is never dropped. */\nconst RUN: z.core.ParseContextInternal = { async: true };\n\nconst builtInRegistry = new FormatRegistry();\nconst registries = new WeakMap<FormatSchemas, FormatRegistry>();\n\n/**\n * The registry of a set of formats, built (and checked) once per record: a\n * code generator hands the same record for every field.\n */\nexport function registryOf(own?: FormatSchemas): FormatRegistry {\n\tif (!own) return builtInRegistry;\n\tlet registry = registries.get(own);\n\tif (!registry) {\n\t\tregistry = new FormatRegistry(own);\n\t\tregistries.set(own, registry);\n\t}\n\treturn registry;\n}\n",
8
- "import { z } from 'zod';\nimport { defineFormat } from './format';\n\nexport const byteFormat = defineFormat({\n\tname: 'byte',\n\ttoZod: () => z.base64(),\n\ttoCode: () => 'z.base64()',\n});\n",
9
- "import type { z } from 'zod';\n\n/** A string schema, plain or a format (`z.email()` is not a `z.ZodString`). */\nexport type StringSchema = z.ZodString | z.ZodStringFormat;\n\n/**\n * One value of `@constraint(format: \"...\")`: the schema it stands for, as a\n * schema at startup and, for a built-in one, as source for a code generator.\n * A format of the application's own has no `toCode`: the generator writes a\n * reference to the application's schema instead.\n */\nexport interface Format<N extends string = string> {\n\treadonly name: N;\n\treadonly toZod: () => StringSchema;\n\treadonly toCode?: () => string;\n}\n\n/** A format this package ships: written twice, as a schema and as source. */\nexport interface BuiltInFormat<N extends string = string> extends Format<N> {\n\treadonly toCode: () => string;\n}\n\n/** Declares a built-in format, with its name kept literal. */\nexport function defineFormat<const N extends string>(\n\tformat: BuiltInFormat<N>,\n): BuiltInFormat<N> {\n\treturn format;\n}\n",
10
- "import { z } from 'zod';\nimport { defineFormat } from './format';\n\nexport const dateFormat = defineFormat({\n\tname: 'date',\n\ttoZod: () => z.iso.date(),\n\ttoCode: () => 'z.iso.date()',\n});\n",
11
- "import { z } from 'zod';\nimport { defineFormat } from './format';\n\n// RFC 3339 with an offset, in its canonical spelling only: an uppercase `T`\n// and `Z`, seconds present. graphql-constraint-directive (validator's\n// isRFC3339) also takes a lowercase `t`, `z` or a space.\nexport const dateTimeFormat = defineFormat({\n\tname: 'date-time',\n\ttoZod: () => z.iso.datetime({ offset: true }),\n\ttoCode: () => 'z.iso.datetime({ offset: true })',\n});\n",
12
- "import { z } from 'zod';\nimport { defineFormat } from './format';\n\nexport const emailFormat = defineFormat({\n\tname: 'email',\n\ttoZod: () => z.email(),\n\ttoCode: () => 'z.email()',\n});\n",
13
- "import { z } from 'zod';\nimport { defineFormat } from './format';\n\nexport const ipv4Format = defineFormat({\n\tname: 'ipv4',\n\ttoZod: () => z.ipv4(),\n\ttoCode: () => 'z.ipv4()',\n});\n",
14
- "import { z } from 'zod';\nimport { defineFormat } from './format';\n\nexport const ipv6Format = defineFormat({\n\tname: 'ipv6',\n\ttoZod: () => z.ipv6(),\n\ttoCode: () => 'z.ipv6()',\n});\n",
15
- "import { z } from 'zod';\nimport { defineFormat } from './format';\n\n// graphql-constraint-directive's `uri` is validator's isURL: http, https or\n// ftp. The scheme is required here, where isURL lets `example.com` through,\n// and nothing else gets in: no `javascript:`, no `mailto:`.\nexport const uriFormat = defineFormat({\n\tname: 'uri',\n\ttoZod: () => z.url({ protocol: /^(https?|ftp)$/ }),\n\ttoCode: () => 'z.url({ protocol: /^(https?|ftp)$/ })',\n});\n",
16
- "import { z } from 'zod';\nimport { defineFormat } from './format';\n\nexport const uuidFormat = defineFormat({\n\tname: 'uuid',\n\ttoZod: () => z.uuid(),\n\ttoCode: () => 'z.uuid()',\n});\n",
17
- "import * as all from './all';\nimport type { BuiltInFormat } from './format';\n\n/**\n * Every built-in format, keyed by the value `@constraint(format: \"...\")`\n * takes. Derived from what `./all` exports, so a new format is one file and\n * one line there.\n */\nexport const formats = Object.fromEntries(\n\tObject.values(all).map((format) => [format.name, format]),\n) as { readonly [N in FormatName]: BuiltInFormat<N> };\n\n/** A value `@constraint(format: \"...\")` takes without the application's formats. */\nexport type FormatName = (typeof all)[keyof typeof all]['name'];\n",
18
- "import type { GraphQLArgument, GraphQLField, GraphQLObjectType } from 'graphql';\nimport { z } from 'zod';\nimport { constraintsOn } from './constraints';\nimport type { InputSchemas } from './input-schema';\n\n/**\n * The schema of a field's arguments, or `undefined` when none of them can\n * break a constraint, so a field with nothing to check is left untouched.\n * `parent` is the type's name, for errors: `Mutation.signUp(input:)`.\n */\nexport function argsSchemaOf(\n\tinputs: InputSchemas,\n\tparent: string,\n\tfield: GraphQLField<unknown, unknown>,\n): z.ZodType | undefined {\n\tif (!field.args.some((arg) => inputs.needsCheck(arg))) return undefined;\n\treturn z.object(\n\t\tObject.fromEntries(\n\t\t\tfield.args.map((arg) => [\n\t\t\t\targ.name,\n\t\t\t\tinputs.of(arg, `${parent}.${field.name}(${arg.name}:)`),\n\t\t\t]),\n\t\t),\n\t);\n}\n\n/** The constraints of an argument as written, sorted: `maxLength: 5, min: 1`. */\nfunction signature(inputs: InputSchemas, arg: GraphQLArgument): string {\n\treturn constraintsOn(inputs.directive, arg.astNode)\n\t\t.map(({ rule, value }) => `${rule.argument}: ${JSON.stringify(value)}`)\n\t\t.sort()\n\t\t.join(', ');\n}\n\n/** A signature as it reads in an error. */\nconst written = (signature: string) =>\n\tsignature ? `@constraint(${signature})` : 'no @constraint';\n\n/**\n * Fails when an object type's field does not repeat the `@constraint` its\n * interface writes on an argument. The object's field is the one that\n * resolves, and graphql lets it redeclare the argument bare: the interface's\n * constraint would then check nothing, in silence.\n */\nexport function assertInterfaceConstraintsKept(\n\tinputs: InputSchemas,\n\ttype: GraphQLObjectType,\n): void {\n\tfor (const contract of type.getInterfaces()) {\n\t\tfor (const [name, declared] of Object.entries(contract.getFields())) {\n\t\t\tconst field = type.getFields()[name];\n\t\t\tfor (const arg of declared.args) {\n\t\t\t\tconst wanted = signature(inputs, arg);\n\t\t\t\tif (!wanted) continue;\n\t\t\t\tconst own = field?.args.find(\n\t\t\t\t\t({ name: argName }) => argName === arg.name,\n\t\t\t\t);\n\t\t\t\tconst found = own ? signature(inputs, own) : wanted;\n\t\t\t\tif (found !== wanted) {\n\t\t\t\t\tconst verb = found ? 'differs on' : 'is not repeated on';\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`@constraint on ${contract.name}.${name}(${arg.name}:) ${verb} ${type.name}.${name}(${arg.name}:), which resolves it (${written(wanted)} there, ${written(found)} here). Write the same @constraint on both.`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n",
19
- "import {\n\ttype ConstValueNode,\n\ttype GraphQLArgument,\n\ttype GraphQLDirective,\n\ttype GraphQLInputField,\n\ttype GraphQLInputObjectType,\n\ttype GraphQLInputType,\n\ttype GraphQLSchema,\n\tgetNamedType,\n\tisInputObjectType,\n\tisListType,\n\tisNonNullType,\n\tvalueFromAST,\n} from 'graphql';\nimport { z } from 'zod';\nimport { type FormatRegistry, registryOf } from '../formats/registry';\nimport { applyRule } from '../rules';\nimport type { RuleContext } from '../rules/rule';\nimport { type Constraint, constraintsOn } from './constraints';\nimport { assertObjectTargets, leafSchema } from './leaf';\n\n/**\n * Builds the schemas of the arguments and input fields of one GraphQL\n * schema, once each: an input type is walked a single time however many\n * fields use it, and a recursive one (`input Filter { and: [Filter!] }`) is\n * reached through `z.lazy`.\n */\nexport class InputSchemas {\n\treadonly directive: GraphQLDirective | undefined;\n\treadonly #context: RuleContext;\n\treadonly #objects = new Map<string, z.ZodType>();\n\treadonly #defaults: {\n\t\tschema: z.ZodType;\n\t\tliteral: ConstValueNode;\n\t\ttype: GraphQLInputType;\n\t\twhere: string;\n\t}[] = [];\n\t/** The input types a value can break a constraint inside. */\n\treadonly #constrained = new Set<string>();\n\n\t/** `formats`: the built-in ones by default, the application's added. */\n\tconstructor(schema: GraphQLSchema, formats: FormatRegistry = registryOf()) {\n\t\tthis.#context = { formats };\n\t\tthis.directive = schema.getDirective('constraint') ?? undefined;\n\t\tconst objects = Object.values(schema.getTypeMap()).filter(\n\t\t\tisInputObjectType,\n\t\t);\n\t\t// A fixpoint, not a memoised walk: in a cycle, a type visited while it\n\t\t// is still being decided would be cached as unconstrained for good.\n\t\tfor (let changed = true; changed; ) {\n\t\t\tchanged = false;\n\t\t\tfor (const type of objects) {\n\t\t\t\tif (this.#constrained.has(type.name)) continue;\n\t\t\t\tconst constrained = Object.values(type.getFields()).some(\n\t\t\t\t\t(field) =>\n\t\t\t\t\t\tconstraintsOn(this.directive, field.astNode).length > 0 ||\n\t\t\t\t\t\tthis.isConstrained(field.type),\n\t\t\t\t);\n\t\t\t\tif (constrained) {\n\t\t\t\t\tthis.#constrained.add(type.name);\n\t\t\t\t\tchanged = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Whether a value of this type can break a constraint anywhere inside. */\n\tisConstrained(type: GraphQLInputType): boolean {\n\t\tconst named = getNamedType(type);\n\t\treturn isInputObjectType(named) && this.#constrained.has(named.name);\n\t}\n\n\t/**\n\t * Builds every constrained input type, reached by an argument or not, so\n\t * a constraint that cannot apply fails at startup wherever it is written.\n\t */\n\tbuildAll(schema: GraphQLSchema): void {\n\t\tfor (const type of Object.values(schema.getTypeMap())) {\n\t\t\tif (isInputObjectType(type)) this.#object(type);\n\t\t}\n\t}\n\n\t/** Whether an argument or input field needs checking at all. */\n\tneedsCheck(input: GraphQLArgument | GraphQLInputField): boolean {\n\t\treturn (\n\t\t\tconstraintsOn(this.directive, input.astNode).length > 0 ||\n\t\t\tthis.isConstrained(input.type)\n\t\t);\n\t}\n\n\t/** The schema of one argument or input field, `where` naming it in errors. */\n\tof(input: GraphQLArgument | GraphQLInputField, where: string): z.ZodType {\n\t\tconst schema = this.#typed(\n\t\t\tinput.type,\n\t\t\tconstraintsOn(this.directive, input.astNode),\n\t\t\twhere,\n\t\t);\n\t\tconst literal = input.astNode?.defaultValue;\n\t\tif (literal)\n\t\t\tthis.#defaults.push({ schema, literal, type: input.type, where });\n\t\treturn schema;\n\t}\n\n\t/**\n\t * Fails when a default value breaks its own constraint: every request that\n\t * leaves the value out would be refused for something the client never\n\t * sent. Run once every schema is built, so a recursive type is complete.\n\t */\n\tcheckDefaults(): void {\n\t\tfor (const { schema, literal, type, where } of this.#defaults.splice(0)) {\n\t\t\t// Coerced as graphql coerces it: a single value for a list, an input\n\t\t\t// object's own field defaults. One graphql refuses is its to report.\n\t\t\tconst value = valueFromAST(literal, type);\n\t\t\tif (value === undefined) continue;\n\t\t\tlet result: z.ZodSafeParseResult<unknown>;\n\t\t\ttry {\n\t\t\t\tresult = schema.safeParse(value);\n\t\t\t} catch (error) {\n\t\t\t\t// Thrown by this zod: only the formats' wrapper, ours, goes async.\n\t\t\t\tif (!(error instanceof z.core.$ZodAsyncError)) throw error;\n\t\t\t\tconst format = this.#context.formats.takeAsync();\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`The default value of ${where} cannot be checked at startup: ${format ? `the format \"${format}\"` : 'its format'} checks asynchronously, and a default value is checked synchronously. Drop the default, or move the async check out of the format into validated().`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!result.success) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`The default value of ${where} breaks its @constraint: ${result.error.issues[0]?.message}`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t#typed(\n\t\ttype: GraphQLInputType,\n\t\tconstraints: readonly Constraint[],\n\t\twhere: string,\n\t): z.ZodType {\n\t\tif (isNonNullType(type))\n\t\t\treturn this.#required(type.ofType, constraints, where);\n\t\treturn this.#required(type, constraints, where).nullish();\n\t}\n\n\t#required(\n\t\ttype: GraphQLInputType,\n\t\tconstraints: readonly Constraint[],\n\t\twhere: string,\n\t): z.ZodType {\n\t\tif (isNonNullType(type))\n\t\t\treturn this.#required(type.ofType, constraints, where);\n\t\tif (isListType(type)) {\n\t\t\t// minItems and maxItems are the list's; every other rule is its items'.\n\t\t\tconst own = constraints.filter(({ rule }) => rule.target === 'list');\n\t\t\tconst items = constraints.filter(({ rule }) => rule.target !== 'list');\n\t\t\tlet list: z.ZodType = z.array(this.#typed(type.ofType, items, where));\n\t\t\tfor (const { rule, value } of own)\n\t\t\t\tlist = applyRule(rule, list, value, this.#context);\n\t\t\treturn list;\n\t\t}\n\t\tif (isInputObjectType(type)) {\n\t\t\tassertObjectTargets(type.name, constraints, where);\n\t\t\treturn this.#object(type);\n\t\t}\n\t\treturn leafSchema(type, constraints, where, this.#context);\n\t}\n\n\t#object(type: GraphQLInputObjectType): z.ZodType {\n\t\tif (!this.isConstrained(type)) return z.unknown();\n\t\tconst built = this.#objects.get(type.name);\n\t\tif (built) return built;\n\t\t// Registered before the walk, so a field that comes back here ends.\n\t\tlet schema: z.ZodType | undefined;\n\t\tthis.#objects.set(\n\t\t\ttype.name,\n\t\t\tz.lazy(() => schema as z.ZodType),\n\t\t);\n\t\tschema = z.object(\n\t\t\tObject.fromEntries(\n\t\t\t\tObject.values(type.getFields()).map((field) => [\n\t\t\t\t\tfield.name,\n\t\t\t\t\tthis.of(field, `${type.name}.${field.name}`),\n\t\t\t\t]),\n\t\t\t),\n\t\t);\n\t\tthis.#objects.set(type.name, schema);\n\t\treturn schema;\n\t}\n}\n",
20
- "import {\n\tGraphQLBoolean,\n\tGraphQLFloat,\n\tGraphQLID,\n\tGraphQLInt,\n\ttype GraphQLLeafType,\n\tGraphQLString,\n} from 'graphql';\nimport { z } from 'zod';\nimport { applyRule } from '../rules';\nimport type { RuleContext, Target } from '../rules/rule';\nimport type { Constraint } from './constraints';\n\n/** The kind of value each built-in scalar holds once graphql parsed it. */\nconst kinds: Record<string, Exclude<Target, 'list'>> = {\n\t[GraphQLString.name]: 'string',\n\t[GraphQLID.name]: 'string',\n\t[GraphQLInt.name]: 'number',\n\t[GraphQLFloat.name]: 'number',\n};\n\nfunction baseOf(type: GraphQLLeafType): z.ZodType {\n\tif (type.name === GraphQLInt.name) return z.number().int();\n\treturn kinds[type.name] === 'number' ? z.number() : z.string();\n}\n\n/**\n * Fails unless every constraint applies to a value of `type`: `minLength` on\n * an `Int`, anything on a custom scalar or an enum, fails, naming `where`.\n * The runtime and the code generator refuse the same schemas with the same\n * message.\n */\nexport function assertLeafTargets(\n\ttype: GraphQLLeafType,\n\tconstraints: readonly Constraint[],\n\twhere: string,\n): void {\n\tconst misplaced = constraints.find(({ rule }) => rule.target === 'list');\n\tif (misplaced) throw misplacedOn(misplaced, where, type.name);\n\tconst kind = kinds[type.name];\n\tconst wrong = constraints.find(({ rule }) => rule.target !== kind);\n\tif (wrong) throw misplacedOn(wrong, where, type.name);\n}\n\n/** Fails when an input object carries a constraint: none applies to it. */\nexport function assertObjectTargets(\n\ttypeName: string,\n\tconstraints: readonly Constraint[],\n\twhere: string,\n): void {\n\tconst first =\n\t\tconstraints.find(({ rule }) => rule.target === 'list') ?? constraints[0];\n\tif (first) throw misplacedOn(first, where, typeName);\n}\n\nfunction misplacedOn(\n\t{ rule }: Constraint,\n\twhere: string,\n\ttypeName: string,\n): Error {\n\treturn new Error(\n\t\t`@constraint(${rule.argument}) on ${where} needs ${describeTarget(rule.target)}, not ${typeName}.`,\n\t);\n}\n\n/**\n * The schema of a scalar or enum value with its constraints applied. A leaf\n * without any is left as graphql parsed it. A constraint that cannot apply\n * fails here, at startup.\n */\nexport function leafSchema(\n\ttype: GraphQLLeafType,\n\tconstraints: readonly Constraint[],\n\twhere: string,\n\tcontext: RuleContext,\n): z.ZodType {\n\tif (constraints.length === 0) return z.unknown();\n\tassertLeafTargets(type, constraints, where);\n\tlet schema = baseOf(type);\n\tfor (const { rule, value } of constraints) {\n\t\tschema = applyRule(rule, schema, value, context);\n\t}\n\treturn schema;\n}\n\n/** The source of a built-in scalar's schema, before its constraints. */\nexport function baseCode(type: GraphQLLeafType): string | undefined {\n\t// graphql's Int is 32-bit: the client refuses what it refuses.\n\tif (type.name === GraphQLInt.name) return 'z.int32()';\n\tif (type.name === GraphQLFloat.name) return 'z.number()';\n\tif (type.name === GraphQLBoolean.name) return 'z.boolean()';\n\treturn kinds[type.name] === 'string' ? 'z.string()' : undefined;\n}\n\n/** What a rule's target reads as in an error. */\nexport function describeTarget(target: Target): string {\n\tif (target === 'string') return 'a String or an ID';\n\tif (target === 'number') return 'an Int or a Float';\n\treturn 'a list';\n}\n"
21
- ],
22
- "mappings": "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",
23
- "debugId": "3026B70F7346E03264756E2164756E21",
24
- "names": []
25
- }