@nxgt/graphql-validation 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +235 -2
  3. package/dist/bad-user-input.d.ts +35 -0
  4. package/dist/bad-user-input.d.ts.map +1 -0
  5. package/dist/builder/args-schema.d.ts +17 -0
  6. package/dist/builder/args-schema.d.ts.map +1 -0
  7. package/dist/builder/check-constraints.d.ts +15 -0
  8. package/dist/builder/check-constraints.d.ts.map +1 -0
  9. package/dist/builder/constraints.d.ts +16 -0
  10. package/dist/builder/constraints.d.ts.map +1 -0
  11. package/dist/builder/input-code.d.ts +29 -0
  12. package/dist/builder/input-code.d.ts.map +1 -0
  13. package/dist/builder/input-schema.d.ts +31 -0
  14. package/dist/builder/input-schema.d.ts.map +1 -0
  15. package/dist/builder/leaf.d.ts +24 -0
  16. package/dist/builder/leaf.d.ts.map +1 -0
  17. package/dist/chunks/index-rbxe5m3y.js +319 -0
  18. package/dist/chunks/index-rbxe5m3y.js.map +37 -0
  19. package/dist/chunks/index-s1kkmg35.js +266 -0
  20. package/dist/chunks/index-s1kkmg35.js.map +14 -0
  21. package/dist/cli.d.ts +3 -0
  22. package/dist/cli.d.ts.map +1 -0
  23. package/dist/cli.js +69 -0
  24. package/dist/cli.js.map +11 -0
  25. package/dist/codegen.d.ts +4 -0
  26. package/dist/codegen.d.ts.map +1 -0
  27. package/dist/codegen.js +56 -0
  28. package/dist/codegen.js.map +10 -0
  29. package/dist/constraint-directive.d.ts +21 -0
  30. package/dist/constraint-directive.d.ts.map +1 -0
  31. package/dist/formats/all.d.ts +9 -0
  32. package/dist/formats/all.d.ts.map +1 -0
  33. package/dist/formats/byte.d.ts +2 -0
  34. package/dist/formats/byte.d.ts.map +1 -0
  35. package/dist/formats/date-time.d.ts +2 -0
  36. package/dist/formats/date-time.d.ts.map +1 -0
  37. package/dist/formats/date.d.ts +2 -0
  38. package/dist/formats/date.d.ts.map +1 -0
  39. package/dist/formats/email.d.ts +2 -0
  40. package/dist/formats/email.d.ts.map +1 -0
  41. package/dist/formats/format.d.ts +15 -0
  42. package/dist/formats/format.d.ts.map +1 -0
  43. package/dist/formats/index.d.ts +13 -0
  44. package/dist/formats/index.d.ts.map +1 -0
  45. package/dist/formats/ipv4.d.ts +2 -0
  46. package/dist/formats/ipv4.d.ts.map +1 -0
  47. package/dist/formats/ipv6.d.ts +2 -0
  48. package/dist/formats/ipv6.d.ts.map +1 -0
  49. package/dist/formats/uri.d.ts +2 -0
  50. package/dist/formats/uri.d.ts.map +1 -0
  51. package/dist/formats/uuid.d.ts +2 -0
  52. package/dist/formats/uuid.d.ts.map +1 -0
  53. package/dist/index.d.ts +6 -0
  54. package/dist/index.d.ts.map +1 -0
  55. package/dist/index.js +84 -0
  56. package/dist/index.js.map +12 -0
  57. package/dist/rules/all.d.ts +16 -0
  58. package/dist/rules/all.d.ts.map +1 -0
  59. package/dist/rules/contains.d.ts +2 -0
  60. package/dist/rules/contains.d.ts.map +1 -0
  61. package/dist/rules/ends-with.d.ts +2 -0
  62. package/dist/rules/ends-with.d.ts.map +1 -0
  63. package/dist/rules/exclusive-max.d.ts +2 -0
  64. package/dist/rules/exclusive-max.d.ts.map +1 -0
  65. package/dist/rules/exclusive-min.d.ts +2 -0
  66. package/dist/rules/exclusive-min.d.ts.map +1 -0
  67. package/dist/rules/format.d.ts +2 -0
  68. package/dist/rules/format.d.ts.map +1 -0
  69. package/dist/rules/index.d.ts +28 -0
  70. package/dist/rules/index.d.ts.map +1 -0
  71. package/dist/rules/max-items.d.ts +2 -0
  72. package/dist/rules/max-items.d.ts.map +1 -0
  73. package/dist/rules/max-length.d.ts +2 -0
  74. package/dist/rules/max-length.d.ts.map +1 -0
  75. package/dist/rules/max.d.ts +2 -0
  76. package/dist/rules/max.d.ts.map +1 -0
  77. package/dist/rules/min-items.d.ts +2 -0
  78. package/dist/rules/min-items.d.ts.map +1 -0
  79. package/dist/rules/min-length.d.ts +2 -0
  80. package/dist/rules/min-length.d.ts.map +1 -0
  81. package/dist/rules/min.d.ts +2 -0
  82. package/dist/rules/min.d.ts.map +1 -0
  83. package/dist/rules/multiple-of.d.ts +2 -0
  84. package/dist/rules/multiple-of.d.ts.map +1 -0
  85. package/dist/rules/not-contains.d.ts +2 -0
  86. package/dist/rules/not-contains.d.ts.map +1 -0
  87. package/dist/rules/pattern.d.ts +2 -0
  88. package/dist/rules/pattern.d.ts.map +1 -0
  89. package/dist/rules/rule.d.ts +55 -0
  90. package/dist/rules/rule.d.ts.map +1 -0
  91. package/dist/rules/starts-with.d.ts +2 -0
  92. package/dist/rules/starts-with.d.ts.map +1 -0
  93. package/dist/typedefs-command.d.ts +10 -0
  94. package/dist/typedefs-command.d.ts.map +1 -0
  95. package/dist/validated.d.ts +22 -0
  96. package/dist/validated.d.ts.map +1 -0
  97. package/dist/with-validation.d.ts +26 -0
  98. package/dist/with-validation.d.ts.map +1 -0
  99. package/docs/README.md +15 -0
  100. package/docs/guide/constraints.md +291 -0
  101. package/docs/guide/errors.md +194 -0
  102. package/docs/roadmap.md +31 -0
  103. package/docs/troubleshooting.md +260 -0
  104. package/graphql/constraint.graphqls +20 -0
  105. package/package.json +73 -5
@@ -0,0 +1,319 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __returnValue = (v) => v;
3
+ function __exportSetter(name, newValue) {
4
+ this[name] = __returnValue.bind(null, newValue);
5
+ }
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, {
9
+ get: all[name],
10
+ enumerable: true,
11
+ configurable: true,
12
+ set: __exportSetter.bind(all, name)
13
+ });
14
+ };
15
+
16
+ // src/constraint-directive.ts
17
+ import { DirectiveLocation } from "graphql";
18
+
19
+ // src/rules/all.ts
20
+ var exports_all2 = {};
21
+ __export(exports_all2, {
22
+ containsRule: () => containsRule,
23
+ endsWithRule: () => endsWithRule,
24
+ exclusiveMaxRule: () => exclusiveMaxRule,
25
+ exclusiveMinRule: () => exclusiveMinRule,
26
+ formatRule: () => formatRule,
27
+ maxItemsRule: () => maxItemsRule,
28
+ maxLengthRule: () => maxLengthRule,
29
+ maxRule: () => maxRule,
30
+ minItemsRule: () => minItemsRule,
31
+ minLengthRule: () => minLengthRule,
32
+ minRule: () => minRule,
33
+ multipleOfRule: () => multipleOfRule,
34
+ notContainsRule: () => notContainsRule,
35
+ patternRule: () => patternRule,
36
+ startsWithRule: () => startsWithRule
37
+ });
38
+
39
+ // src/rules/rule.ts
40
+ function defineRule(rule) {
41
+ return rule;
42
+ }
43
+ var literal = (value) => JSON.stringify(value);
44
+
45
+ // src/rules/contains.ts
46
+ var containsRule = defineRule({
47
+ argument: "contains",
48
+ type: "String",
49
+ target: "string",
50
+ toZod: (schema, value) => schema.includes(value),
51
+ toCode: (schema, value) => `${schema}.includes(${literal(value)})`,
52
+ owns: (issue) => issue.format === "includes"
53
+ });
54
+ // src/rules/ends-with.ts
55
+ var endsWithRule = defineRule({
56
+ argument: "endsWith",
57
+ type: "String",
58
+ target: "string",
59
+ toZod: (schema, value) => schema.endsWith(value),
60
+ toCode: (schema, value) => `${schema}.endsWith(${literal(value)})`,
61
+ owns: (issue) => issue.format === "ends_with"
62
+ });
63
+ // src/rules/exclusive-max.ts
64
+ var exclusiveMaxRule = defineRule({
65
+ argument: "exclusiveMax",
66
+ type: "Float",
67
+ target: "number",
68
+ toZod: (schema, value) => schema.lt(value),
69
+ toCode: (schema, value) => `${schema}.lt(${value})`,
70
+ owns: (issue) => issue.code === "too_big" && issue.origin === "number" && issue.inclusive === false
71
+ });
72
+ // src/rules/exclusive-min.ts
73
+ var exclusiveMinRule = defineRule({
74
+ argument: "exclusiveMin",
75
+ type: "Float",
76
+ target: "number",
77
+ toZod: (schema, value) => schema.gt(value),
78
+ toCode: (schema, value) => `${schema}.gt(${value})`,
79
+ owns: (issue) => issue.code === "too_small" && issue.origin === "number" && issue.inclusive === false
80
+ });
81
+ // src/formats/all.ts
82
+ var exports_all = {};
83
+ __export(exports_all, {
84
+ byteFormat: () => byteFormat,
85
+ dateFormat: () => dateFormat,
86
+ dateTimeFormat: () => dateTimeFormat,
87
+ emailFormat: () => emailFormat,
88
+ ipv4Format: () => ipv4Format,
89
+ ipv6Format: () => ipv6Format,
90
+ uriFormat: () => uriFormat,
91
+ uuidFormat: () => uuidFormat
92
+ });
93
+
94
+ // src/formats/byte.ts
95
+ import { z } from "zod";
96
+
97
+ // src/formats/format.ts
98
+ function defineFormat(format) {
99
+ return format;
100
+ }
101
+
102
+ // src/formats/byte.ts
103
+ var byteFormat = defineFormat({
104
+ name: "byte",
105
+ toZod: () => z.base64(),
106
+ toCode: () => "z.base64()"
107
+ });
108
+ // src/formats/date.ts
109
+ import { z as z2 } from "zod";
110
+ var dateFormat = defineFormat({
111
+ name: "date",
112
+ toZod: () => z2.iso.date(),
113
+ toCode: () => "z.iso.date()"
114
+ });
115
+ // src/formats/date-time.ts
116
+ import { z as z3 } from "zod";
117
+ var dateTimeFormat = defineFormat({
118
+ name: "date-time",
119
+ toZod: () => z3.iso.datetime({ offset: true }),
120
+ toCode: () => "z.iso.datetime({ offset: true })"
121
+ });
122
+ // src/formats/email.ts
123
+ import { z as z4 } from "zod";
124
+ var emailFormat = defineFormat({
125
+ name: "email",
126
+ toZod: () => z4.email(),
127
+ toCode: () => "z.email()"
128
+ });
129
+ // src/formats/ipv4.ts
130
+ import { z as z5 } from "zod";
131
+ var ipv4Format = defineFormat({
132
+ name: "ipv4",
133
+ toZod: () => z5.ipv4(),
134
+ toCode: () => "z.ipv4()"
135
+ });
136
+ // src/formats/ipv6.ts
137
+ import { z as z6 } from "zod";
138
+ var ipv6Format = defineFormat({
139
+ name: "ipv6",
140
+ toZod: () => z6.ipv6(),
141
+ toCode: () => "z.ipv6()"
142
+ });
143
+ // src/formats/uri.ts
144
+ import { z as z7 } from "zod";
145
+ var uriFormat = defineFormat({
146
+ name: "uri",
147
+ toZod: () => z7.url({ protocol: /^(https?|ftp)$/ }),
148
+ toCode: () => "z.url({ protocol: /^(https?|ftp)$/ })"
149
+ });
150
+ // src/formats/uuid.ts
151
+ import { z as z8 } from "zod";
152
+ var uuidFormat = defineFormat({
153
+ name: "uuid",
154
+ toZod: () => z8.uuid(),
155
+ toCode: () => "z.uuid()"
156
+ });
157
+ // src/formats/index.ts
158
+ var formats = Object.fromEntries(Object.values(exports_all).map((format) => [format.name, format]));
159
+ function formatNamed(name) {
160
+ if (Object.hasOwn(formats, name))
161
+ return formats[name];
162
+ throw new Error(`Unknown @constraint format "${name}". Known formats: ${Object.keys(formats).join(", ")}.`);
163
+ }
164
+
165
+ // src/rules/format.ts
166
+ var NARROWING = new Set(["starts_with", "ends_with", "includes", "regex"]);
167
+ var formatRule = defineRule({
168
+ argument: "format",
169
+ type: "String",
170
+ target: "string",
171
+ base: true,
172
+ toZod: (_schema, value) => formatNamed(value).toZod(),
173
+ toCode: (_schema, value) => formatNamed(value).toCode(),
174
+ owns: (issue) => issue.code === "invalid_format" && !NARROWING.has(issue.format ?? "")
175
+ });
176
+ // src/rules/max.ts
177
+ var maxRule = defineRule({
178
+ argument: "max",
179
+ type: "Float",
180
+ target: "number",
181
+ toZod: (schema, value) => schema.lte(value),
182
+ toCode: (schema, value) => `${schema}.lte(${value})`,
183
+ owns: (issue) => issue.code === "too_big" && issue.origin === "number" && issue.inclusive === true
184
+ });
185
+ // src/rules/max-items.ts
186
+ var maxItemsRule = defineRule({
187
+ argument: "maxItems",
188
+ type: "Int",
189
+ target: "list",
190
+ toZod: (schema, value) => schema.max(value),
191
+ toCode: (schema, value) => `${schema}.max(${value})`,
192
+ owns: (issue) => issue.code === "too_big" && issue.origin === "array"
193
+ });
194
+ // src/rules/max-length.ts
195
+ var maxLengthRule = defineRule({
196
+ argument: "maxLength",
197
+ type: "Int",
198
+ target: "string",
199
+ toZod: (schema, value) => schema.max(value),
200
+ toCode: (schema, value) => `${schema}.max(${value})`,
201
+ owns: (issue) => issue.code === "too_big" && issue.origin === "string"
202
+ });
203
+ // src/rules/min.ts
204
+ var minRule = defineRule({
205
+ argument: "min",
206
+ type: "Float",
207
+ target: "number",
208
+ toZod: (schema, value) => schema.gte(value),
209
+ toCode: (schema, value) => `${schema}.gte(${value})`,
210
+ owns: (issue) => issue.code === "too_small" && issue.origin === "number" && issue.inclusive === true
211
+ });
212
+ // src/rules/min-items.ts
213
+ var minItemsRule = defineRule({
214
+ argument: "minItems",
215
+ type: "Int",
216
+ target: "list",
217
+ toZod: (schema, value) => schema.min(value),
218
+ toCode: (schema, value) => `${schema}.min(${value})`,
219
+ owns: (issue) => issue.code === "too_small" && issue.origin === "array"
220
+ });
221
+ // src/rules/min-length.ts
222
+ var minLengthRule = defineRule({
223
+ argument: "minLength",
224
+ type: "Int",
225
+ target: "string",
226
+ toZod: (schema, value) => schema.min(value),
227
+ toCode: (schema, value) => `${schema}.min(${value})`,
228
+ owns: (issue) => issue.code === "too_small" && issue.origin === "string"
229
+ });
230
+ // src/rules/multiple-of.ts
231
+ var multipleOfRule = defineRule({
232
+ argument: "multipleOf",
233
+ type: "Float",
234
+ target: "number",
235
+ toZod: (schema, value) => schema.multipleOf(value),
236
+ toCode: (schema, value) => `${schema}.multipleOf(${value})`,
237
+ owns: (issue) => issue.code === "not_multiple_of"
238
+ });
239
+ // src/rules/not-contains.ts
240
+ var message = (value) => `Must not contain ${literal(value)}`;
241
+ var notContainsRule = defineRule({
242
+ argument: "notContains",
243
+ type: "String",
244
+ target: "string",
245
+ toZod: (schema, value) => schema.refine((input) => !input.includes(value), message(value)),
246
+ toCode: (schema, value) => `${schema}.refine((input) => !input.includes(${literal(value)}), ${literal(message(value))})`,
247
+ owns: (issue) => issue.code === "custom"
248
+ });
249
+ // src/rules/pattern.ts
250
+ function compile(value) {
251
+ try {
252
+ return new RegExp(value);
253
+ } catch (error) {
254
+ throw new Error(`Invalid @constraint pattern ${literal(value)}: ${error.message}`);
255
+ }
256
+ }
257
+ var patternRule = defineRule({
258
+ argument: "pattern",
259
+ type: "String",
260
+ target: "string",
261
+ toZod: (schema, value) => schema.regex(compile(value)),
262
+ toCode: (schema, value) => `${schema}.regex(new RegExp(${literal(compile(value).source)}))`,
263
+ owns: (issue) => issue.format === "regex"
264
+ });
265
+ // src/rules/starts-with.ts
266
+ var startsWithRule = defineRule({
267
+ argument: "startsWith",
268
+ type: "String",
269
+ target: "string",
270
+ toZod: (schema, value) => schema.startsWith(value),
271
+ toCode: (schema, value) => `${schema}.startsWith(${literal(value)})`,
272
+ owns: (issue) => issue.format === "starts_with"
273
+ });
274
+ // src/rules/index.ts
275
+ var rules = Object.fromEntries(Object.values(exports_all2).map((rule) => [rule.argument, rule]));
276
+ function applyRule(rule, schema, value) {
277
+ const toZod = rule.toZod;
278
+ return toZod(schema, value);
279
+ }
280
+ function applyRuleCode(rule, source, value) {
281
+ const toCode = rule.toCode;
282
+ return toCode(source, value);
283
+ }
284
+ function constraintOf(issue) {
285
+ const fields = issue;
286
+ return Object.values(rules).find((rule) => rule.owns(fields))?.argument;
287
+ }
288
+
289
+ // src/constraint-directive.ts
290
+ var constraintTypeDefs2 = `directive @constraint(
291
+ ${Object.values(rules).map((rule) => ` ${rule.argument}: ${rule.type}`).join(`
292
+ `)}
293
+ ) on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION
294
+ `;
295
+ var allowed = new Set([
296
+ DirectiveLocation.ARGUMENT_DEFINITION,
297
+ DirectiveLocation.INPUT_FIELD_DEFINITION
298
+ ]);
299
+ function assertOwnConstraint(directive) {
300
+ const problems = [
301
+ ...directive.isRepeatable ? ["repeatable, and only its first use is read"] : [],
302
+ ...directive.locations.filter((location) => !allowed.has(location)).map((location) => `allowed on ${location}`),
303
+ ...directive.args.flatMap((arg) => {
304
+ const rule = rules[arg.name];
305
+ if (!rule)
306
+ return [`declares ${arg.name}, which no rule reads`];
307
+ const type = String(arg.type);
308
+ return type === rule.type ? [] : [`declares ${arg.name}: ${type}, not ${rule.type}`];
309
+ })
310
+ ];
311
+ if (problems.length > 0) {
312
+ throw new Error(`This schema's @constraint is not constraintTypeDefs': it is ${problems.join("; ")}. Declare it with constraintTypeDefs.`);
313
+ }
314
+ }
315
+
316
+ export { rules, applyRule, applyRuleCode, constraintOf, constraintTypeDefs2, assertOwnConstraint };
317
+
318
+ //# debugId=0FAF783CE1246B6764756E2164756E21
319
+ //# sourceMappingURL=index-rbxe5m3y.js.map
@@ -0,0 +1,37 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/constraint-directive.ts", "../src/rules/rule.ts", "../src/rules/contains.ts", "../src/rules/ends-with.ts", "../src/rules/exclusive-max.ts", "../src/rules/exclusive-min.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/rules/format.ts", "../src/rules/max.ts", "../src/rules/max-items.ts", "../src/rules/max-length.ts", "../src/rules/min.ts", "../src/rules/min-items.ts", "../src/rules/min-length.ts", "../src/rules/multiple-of.ts", "../src/rules/not-contains.ts", "../src/rules/pattern.ts", "../src/rules/starts-with.ts", "../src/rules/index.ts"],
4
+ "sourcesContent": [
5
+ "import { DirectiveLocation, type GraphQLDirective } from 'graphql';\nimport { rules } from './rules';\n\n/**\n * The SDL of `@constraint`, to add to a schema-first server's `typeDefs`,\n * written from the rules: an argument is declared once its rule exists.\n *\n * Its arguments are graphql-constraint-directive's, minus `uniqueTypeName`\n * (a detail of that package's scalar wrapping). It is allowed on arguments\n * and input fields only, where that package also allows output fields: a\n * resolver's result is the output scalars' job, and a directive that checked\n * nothing there would be a promise broken in silence.\n */\nexport const constraintTypeDefs: string = `directive @constraint(\n${Object.values(rules)\n\t.map((rule) => `\\t${rule.argument}: ${rule.type}`)\n\t.join('\\n')}\n) on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION\n`;\n\nconst allowed = new Set<string>([\n\tDirectiveLocation.ARGUMENT_DEFINITION,\n\tDirectiveLocation.INPUT_FIELD_DEFINITION,\n]);\n\n/**\n * Fails when the schema's `@constraint` is not the one\n * {@link constraintTypeDefs} declares — graphql-constraint-directive's, say,\n * kept from a migration. Its extra locations would be accepted and checked\n * by nothing, its extra arguments mean nothing here, and an argument of\n * another type would reach a rule as the wrong kind of value.\n */\nexport function assertOwnConstraint(directive: GraphQLDirective): void {\n\tconst problems = [\n\t\t...(directive.isRepeatable\n\t\t\t? ['repeatable, and only its first use is read']\n\t\t\t: []),\n\t\t...directive.locations\n\t\t\t.filter((location) => !allowed.has(location))\n\t\t\t.map((location) => `allowed on ${location}`),\n\t\t...directive.args.flatMap((arg) => {\n\t\t\tconst rule = (rules as Record<string, { type: string } | undefined>)[\n\t\t\t\targ.name\n\t\t\t];\n\t\t\tif (!rule) return [`declares ${arg.name}, which no rule reads`];\n\t\t\tconst type = String(arg.type);\n\t\t\treturn type === rule.type\n\t\t\t\t? []\n\t\t\t\t: [`declares ${arg.name}: ${type}, not ${rule.type}`];\n\t\t}),\n\t];\n\tif (problems.length > 0) {\n\t\tthrow new Error(\n\t\t\t`This schema's @constraint is not constraintTypeDefs': it is ${problems.join('; ')}. Declare it with constraintTypeDefs.`,\n\t\t);\n\t}\n}\n",
6
+ "import type { z } from 'zod';\nimport type { StringSchema } from '../formats/format';\n\n/** The schema each kind of rule narrows. */\nexport interface Targets {\n\tstring: StringSchema;\n\tnumber: z.ZodNumber;\n\tlist: z.ZodArray<z.ZodType>;\n}\n\nexport type Target = keyof Targets;\n\n/** What a `@constraint` argument's value can be. */\ninterface ValueOf {\n\tInt: number;\n\tFloat: number;\n\tString: string;\n}\n\n/**\n * One `@constraint` argument: its GraphQL type in the directive's SDL, the\n * kind of value it narrows, and the same narrowing twice — `toZod` applied to\n * a schema at startup, `toCode` written as source by a code generator. The\n * spec beside each rule proves the two accept and refuse the same values.\n *\n * A `base` rule (only `format`) replaces the schema instead of narrowing it,\n * so a builder applies it before every other rule of its target.\n */\nexport interface Rule<\n\tA extends string = string,\n\tT extends keyof ValueOf = keyof ValueOf,\n\tK extends Target = Target,\n> {\n\treadonly argument: A;\n\treadonly type: T;\n\treadonly target: K;\n\treadonly base?: true;\n\treadonly toZod: (schema: Targets[K], value: ValueOf[T]) => Targets[K];\n\t/**\n\t * `schema` is the source of the schema this rule narrows. The source names\n\t * zod as a free `z`: the generated file imports it.\n\t */\n\treadonly toCode: (schema: string, value: ValueOf[T]) => string;\n\t/**\n\t * Whether a Zod issue is this rule's refusal, so the error a client gets\n\t * names the rule (`constraint: 'minLength'`), which does not change with\n\t * Zod's own issue codes.\n\t */\n\treadonly owns: (issue: IssueFields) => boolean;\n}\n\n/** The fields of a Zod issue a rule recognises its refusal by. */\nexport interface IssueFields {\n\treadonly code: string;\n\treadonly origin?: string;\n\treadonly format?: string;\n\treadonly inclusive?: boolean;\n}\n\n/** Declares a rule, with its argument name kept literal. */\nexport function defineRule<\n\tconst A extends string,\n\tT extends keyof ValueOf,\n\tK extends Target,\n>(rule: Rule<A, T, K>): Rule<A, T, K> {\n\treturn rule;\n}\n\n/** A string literal as source: quotes and escapes included. */\nexport const literal = (value: string): string => JSON.stringify(value);\n",
7
+ "import { defineRule, literal } from './rule';\n\nexport const containsRule = defineRule({\n\targument: 'contains',\n\ttype: 'String',\n\ttarget: 'string',\n\ttoZod: (schema, value) => schema.includes(value),\n\ttoCode: (schema, value) => `${schema}.includes(${literal(value)})`,\n\towns: (issue) => issue.format === 'includes',\n});\n",
8
+ "import { defineRule, literal } from './rule';\n\nexport const endsWithRule = defineRule({\n\targument: 'endsWith',\n\ttype: 'String',\n\ttarget: 'string',\n\ttoZod: (schema, value) => schema.endsWith(value),\n\ttoCode: (schema, value) => `${schema}.endsWith(${literal(value)})`,\n\towns: (issue) => issue.format === 'ends_with',\n});\n",
9
+ "import { defineRule } from './rule';\n\nexport const exclusiveMaxRule = defineRule({\n\targument: 'exclusiveMax',\n\ttype: 'Float',\n\ttarget: 'number',\n\ttoZod: (schema, value) => schema.lt(value),\n\ttoCode: (schema, value) => `${schema}.lt(${value})`,\n\towns: (issue) =>\n\t\tissue.code === 'too_big' &&\n\t\tissue.origin === 'number' &&\n\t\tissue.inclusive === false,\n});\n",
10
+ "import { defineRule } from './rule';\n\nexport const exclusiveMinRule = defineRule({\n\targument: 'exclusiveMin',\n\ttype: 'Float',\n\ttarget: 'number',\n\ttoZod: (schema, value) => schema.gt(value),\n\ttoCode: (schema, value) => `${schema}.gt(${value})`,\n\towns: (issue) =>\n\t\tissue.code === 'too_small' &&\n\t\tissue.origin === 'number' &&\n\t\tissue.inclusive === false,\n});\n",
11
+ "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",
12
+ "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 as source for a code generator.\n */\nexport interface Format<N extends string = string> {\n\treadonly name: N;\n\treadonly toZod: () => StringSchema;\n\treadonly toCode: () => string;\n}\n\n/** Declares a format, with its name kept literal. */\nexport function defineFormat<const N extends string>(\n\tformat: Format<N>,\n): Format<N> {\n\treturn format;\n}\n",
13
+ "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",
14
+ "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",
15
+ "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",
16
+ "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",
17
+ "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",
18
+ "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",
19
+ "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",
20
+ "import * as all from './all';\nimport type { Format } from './format';\n\n/**\n * Every format, keyed by the value `@constraint(format: \"...\")` takes.\n * Derived from what `./all` exports, so a new format is one file and one\n * line there.\n */\nexport const formats = Object.fromEntries(\n\tObject.values(all).map((format) => [format.name, format]),\n) as { readonly [N in FormatName]: Format<N> };\n\n/** A value `@constraint(format: \"...\")` takes. */\nexport type FormatName = (typeof all)[keyof typeof all]['name'];\n\n/** The format named `name`, or an error that lists the known ones. */\nexport function formatNamed(name: string): Format {\n\tif (Object.hasOwn(formats, name)) return formats[name as FormatName];\n\tthrow new Error(\n\t\t`Unknown @constraint format \"${name}\". Known formats: ${Object.keys(formats).join(', ')}.`,\n\t);\n}\n",
21
+ "import { formatNamed } from '../formats';\nimport { defineRule } from './rule';\n\n// The string rules' own formats; every other invalid_format is a format's.\nconst NARROWING = new Set(['starts_with', 'ends_with', 'includes', 'regex']);\n\nexport const formatRule = defineRule({\n\targument: 'format',\n\ttype: 'String',\n\ttarget: 'string',\n\tbase: true,\n\ttoZod: (_schema, value) => formatNamed(value).toZod(),\n\ttoCode: (_schema, value) => formatNamed(value).toCode(),\n\towns: (issue) =>\n\t\tissue.code === 'invalid_format' && !NARROWING.has(issue.format ?? ''),\n});\n",
22
+ "import { defineRule } from './rule';\n\nexport const maxRule = defineRule({\n\targument: 'max',\n\ttype: 'Float',\n\ttarget: 'number',\n\ttoZod: (schema, value) => schema.lte(value),\n\ttoCode: (schema, value) => `${schema}.lte(${value})`,\n\towns: (issue) =>\n\t\tissue.code === 'too_big' &&\n\t\tissue.origin === 'number' &&\n\t\tissue.inclusive === true,\n});\n",
23
+ "import { defineRule } from './rule';\n\nexport const maxItemsRule = defineRule({\n\targument: 'maxItems',\n\ttype: 'Int',\n\ttarget: 'list',\n\ttoZod: (schema, value) => schema.max(value),\n\ttoCode: (schema, value) => `${schema}.max(${value})`,\n\towns: (issue) => issue.code === 'too_big' && issue.origin === 'array',\n});\n",
24
+ "import { defineRule } from './rule';\n\nexport const maxLengthRule = defineRule({\n\targument: 'maxLength',\n\ttype: 'Int',\n\ttarget: 'string',\n\ttoZod: (schema, value) => schema.max(value),\n\ttoCode: (schema, value) => `${schema}.max(${value})`,\n\towns: (issue) => issue.code === 'too_big' && issue.origin === 'string',\n});\n",
25
+ "import { defineRule } from './rule';\n\nexport const minRule = defineRule({\n\targument: 'min',\n\ttype: 'Float',\n\ttarget: 'number',\n\ttoZod: (schema, value) => schema.gte(value),\n\ttoCode: (schema, value) => `${schema}.gte(${value})`,\n\towns: (issue) =>\n\t\tissue.code === 'too_small' &&\n\t\tissue.origin === 'number' &&\n\t\tissue.inclusive === true,\n});\n",
26
+ "import { defineRule } from './rule';\n\nexport const minItemsRule = defineRule({\n\targument: 'minItems',\n\ttype: 'Int',\n\ttarget: 'list',\n\ttoZod: (schema, value) => schema.min(value),\n\ttoCode: (schema, value) => `${schema}.min(${value})`,\n\towns: (issue) => issue.code === 'too_small' && issue.origin === 'array',\n});\n",
27
+ "import { defineRule } from './rule';\n\nexport const minLengthRule = defineRule({\n\targument: 'minLength',\n\ttype: 'Int',\n\ttarget: 'string',\n\ttoZod: (schema, value) => schema.min(value),\n\ttoCode: (schema, value) => `${schema}.min(${value})`,\n\towns: (issue) => issue.code === 'too_small' && issue.origin === 'string',\n});\n",
28
+ "import { defineRule } from './rule';\n\nexport const multipleOfRule = defineRule({\n\targument: 'multipleOf',\n\ttype: 'Float',\n\ttarget: 'number',\n\ttoZod: (schema, value) => schema.multipleOf(value),\n\ttoCode: (schema, value) => `${schema}.multipleOf(${value})`,\n\towns: (issue) => issue.code === 'not_multiple_of',\n});\n",
29
+ "import { defineRule, literal } from './rule';\n\nconst message = (value: string) => `Must not contain ${literal(value)}`;\n\nexport const notContainsRule = defineRule({\n\targument: 'notContains',\n\ttype: 'String',\n\ttarget: 'string',\n\t// `refine` keeps the schema's own type, so later rules still chain.\n\ttoZod: (schema, value) =>\n\t\tschema.refine((input) => !input.includes(value), message(value)),\n\ttoCode: (schema, value) =>\n\t\t`${schema}.refine((input) => !input.includes(${literal(value)}), ${literal(message(value))})`,\n\towns: (issue) => issue.code === 'custom',\n});\n",
30
+ "import { defineRule, literal } from './rule';\n\n/** The pattern as a RegExp, or an error that names the argument. */\nfunction compile(value: string): RegExp {\n\ttry {\n\t\treturn new RegExp(value);\n\t} catch (error) {\n\t\tthrow new Error(\n\t\t\t`Invalid @constraint pattern ${literal(value)}: ${(error as Error).message}`,\n\t\t);\n\t}\n}\n\nexport const patternRule = defineRule({\n\targument: 'pattern',\n\ttype: 'String',\n\ttarget: 'string',\n\ttoZod: (schema, value) => schema.regex(compile(value)),\n\ttoCode: (schema, value) =>\n\t\t`${schema}.regex(new RegExp(${literal(compile(value).source)}))`,\n\towns: (issue) => issue.format === 'regex',\n});\n",
31
+ "import { defineRule, literal } from './rule';\n\nexport const startsWithRule = defineRule({\n\targument: 'startsWith',\n\ttype: 'String',\n\ttarget: 'string',\n\ttoZod: (schema, value) => schema.startsWith(value),\n\ttoCode: (schema, value) => `${schema}.startsWith(${literal(value)})`,\n\towns: (issue) => issue.format === 'starts_with',\n});\n",
32
+ "import type { z } from 'zod';\nimport * as all from './all';\nimport type { IssueFields } from './rule';\n\n/**\n * One of the rules, as its own type: a builder narrows it on `target`, so a\n * number schema never reaches a string rule.\n */\nexport type RegisteredRule = (typeof all)[keyof typeof all];\n\n/** An argument `@constraint` takes. */\nexport type ConstraintArgument = RegisteredRule['argument'];\n\n/**\n * Every rule, keyed by its `@constraint` argument. Derived from what\n * `./all` exports, so a new rule is one file and one line there, and the\n * directive's SDL follows.\n */\nexport const rules = Object.fromEntries(\n\tObject.values(all).map((rule) => [rule.argument, rule]),\n) as {\n\treadonly [A in ConstraintArgument]: Extract<RegisteredRule, { argument: A }>;\n};\n\n/**\n * Applies a rule to a schema its caller has already matched to the rule's\n * target: the one place the rule's typed `toZod` meets a schema built from\n * GraphQL types, which the compiler cannot relate.\n */\nexport function applyRule(\n\trule: RegisteredRule,\n\tschema: z.ZodType,\n\tvalue: string | number,\n): z.ZodType {\n\tconst toZod = rule.toZod as unknown as (\n\t\tschema: z.ZodType,\n\t\tvalue: string | number,\n\t) => z.ZodType;\n\treturn toZod(schema, value);\n}\n\n/** `applyRule` for source: the rule's typed `toCode` on a schema's source. */\nexport function applyRuleCode(\n\trule: RegisteredRule,\n\tsource: string,\n\tvalue: string | number,\n): string {\n\tconst toCode = rule.toCode as (\n\t\tschema: string,\n\t\tvalue: string | number,\n\t) => string;\n\treturn toCode(source, value);\n}\n\n/** The `@constraint` argument whose rule refused with this issue, if any. */\nexport function constraintOf(\n\tissue: z.core.$ZodIssue,\n): ConstraintArgument | undefined {\n\tconst fields = issue as unknown as IssueFields;\n\treturn Object.values(rules).find((rule) => rule.owns(fields))?.argument;\n}\n"
33
+ ],
34
+ "mappings": "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",
35
+ "debugId": "0FAF783CE1246B6764756E2164756E21",
36
+ "names": []
37
+ }
@@ -0,0 +1,266 @@
1
+ import {
2
+ rules,
3
+ applyRule,
4
+ assertOwnConstraint
5
+ } from "./index-rbxe5m3y.js";
6
+
7
+ // src/builder/constraints.ts
8
+ import {
9
+ getDirectiveValues
10
+ } from "graphql";
11
+ function constraintsOn2(directive, node) {
12
+ if (!directive || !node)
13
+ return [];
14
+ const values = getDirectiveValues(directive, { directives: node.directives ?? [] }) ?? {};
15
+ return Object.entries(values).filter(([, value]) => value !== undefined && value !== null).map(([argument, value]) => ({
16
+ rule: rules[argument],
17
+ value
18
+ })).sort((a, b) => Number(Boolean(b.rule.base)) - Number(Boolean(a.rule.base)));
19
+ }
20
+
21
+ // src/builder/check-constraints.ts
22
+ import {
23
+ isInterfaceType,
24
+ isObjectType
25
+ } from "graphql";
26
+
27
+ // src/builder/args-schema.ts
28
+ import { z } from "zod";
29
+ function argsSchemaOf(inputs, parent, field) {
30
+ if (!field.args.some((arg) => inputs.needsCheck(arg)))
31
+ return;
32
+ return z.object(Object.fromEntries(field.args.map((arg) => [
33
+ arg.name,
34
+ inputs.of(arg, `${parent}.${field.name}(${arg.name}:)`)
35
+ ])));
36
+ }
37
+ function signature(inputs, arg) {
38
+ return constraintsOn2(inputs.directive, arg.astNode).map(({ rule, value }) => `${rule.argument}: ${JSON.stringify(value)}`).sort().join(", ");
39
+ }
40
+ var written = (signature) => signature ? `@constraint(${signature})` : "no @constraint";
41
+ function assertInterfaceConstraintsKept(inputs, type) {
42
+ for (const contract of type.getInterfaces()) {
43
+ for (const [name, declared] of Object.entries(contract.getFields())) {
44
+ const field = type.getFields()[name];
45
+ for (const arg of declared.args) {
46
+ const wanted = signature(inputs, arg);
47
+ if (!wanted)
48
+ continue;
49
+ const own = field?.args.find(({ name: argName }) => argName === arg.name);
50
+ const found = own ? signature(inputs, own) : wanted;
51
+ if (found !== wanted) {
52
+ const verb = found ? "differs on" : "is not repeated on";
53
+ throw new Error(`@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.`);
54
+ }
55
+ }
56
+ }
57
+ }
58
+ }
59
+
60
+ // src/builder/input-schema.ts
61
+ import {
62
+ getNamedType,
63
+ isInputObjectType,
64
+ isListType,
65
+ isNonNullType,
66
+ valueFromAST
67
+ } from "graphql";
68
+ import { z as z3 } from "zod";
69
+
70
+ // src/builder/leaf.ts
71
+ import {
72
+ GraphQLBoolean,
73
+ GraphQLFloat,
74
+ GraphQLID,
75
+ GraphQLInt,
76
+ GraphQLString
77
+ } from "graphql";
78
+ import { z as z2 } from "zod";
79
+ var kinds = {
80
+ [GraphQLString.name]: "string",
81
+ [GraphQLID.name]: "string",
82
+ [GraphQLInt.name]: "number",
83
+ [GraphQLFloat.name]: "number"
84
+ };
85
+ function baseOf(type) {
86
+ if (type.name === GraphQLInt.name)
87
+ return z2.number().int();
88
+ return kinds[type.name] === "number" ? z2.number() : z2.string();
89
+ }
90
+ function assertLeafTargets(type, constraints, where) {
91
+ const misplaced = constraints.find(({ rule }) => rule.target === "list");
92
+ if (misplaced)
93
+ throw misplacedOn(misplaced, where, type.name);
94
+ const kind = kinds[type.name];
95
+ const wrong = constraints.find(({ rule }) => rule.target !== kind);
96
+ if (wrong)
97
+ throw misplacedOn(wrong, where, type.name);
98
+ }
99
+ function assertObjectTargets(typeName, constraints, where) {
100
+ const first = constraints.find(({ rule }) => rule.target === "list") ?? constraints[0];
101
+ if (first)
102
+ throw misplacedOn(first, where, typeName);
103
+ }
104
+ function misplacedOn({ rule }, where, typeName) {
105
+ return new Error(`@constraint(${rule.argument}) on ${where} needs ${describeTarget(rule.target)}, not ${typeName}.`);
106
+ }
107
+ function leafSchema(type, constraints, where) {
108
+ if (constraints.length === 0)
109
+ return z2.unknown();
110
+ assertLeafTargets(type, constraints, where);
111
+ let schema = baseOf(type);
112
+ for (const { rule, value } of constraints) {
113
+ schema = applyRule(rule, schema, value);
114
+ }
115
+ return schema;
116
+ }
117
+ function baseCode(type) {
118
+ if (type.name === GraphQLInt.name)
119
+ return "z.int32()";
120
+ if (type.name === GraphQLFloat.name)
121
+ return "z.number()";
122
+ if (type.name === GraphQLBoolean.name)
123
+ return "z.boolean()";
124
+ return kinds[type.name] === "string" ? "z.string()" : undefined;
125
+ }
126
+ function describeTarget(target) {
127
+ if (target === "string")
128
+ return "a String or an ID";
129
+ if (target === "number")
130
+ return "an Int or a Float";
131
+ return "a list";
132
+ }
133
+
134
+ // src/builder/input-schema.ts
135
+ class InputSchemas {
136
+ directive;
137
+ #objects = new Map;
138
+ #defaults = [];
139
+ #constrained = new Set;
140
+ constructor(schema) {
141
+ this.directive = schema.getDirective("constraint") ?? undefined;
142
+ const objects = Object.values(schema.getTypeMap()).filter(isInputObjectType);
143
+ for (let changed = true;changed; ) {
144
+ changed = false;
145
+ for (const type of objects) {
146
+ if (this.#constrained.has(type.name))
147
+ continue;
148
+ const constrained = Object.values(type.getFields()).some((field) => constraintsOn2(this.directive, field.astNode).length > 0 || this.isConstrained(field.type));
149
+ if (constrained) {
150
+ this.#constrained.add(type.name);
151
+ changed = true;
152
+ }
153
+ }
154
+ }
155
+ }
156
+ isConstrained(type) {
157
+ const named = getNamedType(type);
158
+ return isInputObjectType(named) && this.#constrained.has(named.name);
159
+ }
160
+ buildAll(schema) {
161
+ for (const type of Object.values(schema.getTypeMap())) {
162
+ if (isInputObjectType(type))
163
+ this.#object(type);
164
+ }
165
+ }
166
+ needsCheck(input) {
167
+ return constraintsOn2(this.directive, input.astNode).length > 0 || this.isConstrained(input.type);
168
+ }
169
+ of(input, where) {
170
+ const schema = this.#typed(input.type, constraintsOn2(this.directive, input.astNode), where);
171
+ const literal = input.astNode?.defaultValue;
172
+ if (literal)
173
+ this.#defaults.push({ schema, literal, type: input.type, where });
174
+ return schema;
175
+ }
176
+ checkDefaults() {
177
+ for (const { schema, literal, type, where } of this.#defaults.splice(0)) {
178
+ const value = valueFromAST(literal, type);
179
+ if (value === undefined)
180
+ continue;
181
+ const result = schema.safeParse(value);
182
+ if (!result.success) {
183
+ throw new Error(`The default value of ${where} breaks its @constraint: ${result.error.issues[0]?.message}`);
184
+ }
185
+ }
186
+ }
187
+ #typed(type, constraints, where) {
188
+ if (isNonNullType(type))
189
+ return this.#required(type.ofType, constraints, where);
190
+ return this.#required(type, constraints, where).nullish();
191
+ }
192
+ #required(type, constraints, where) {
193
+ if (isNonNullType(type))
194
+ return this.#required(type.ofType, constraints, where);
195
+ if (isListType(type)) {
196
+ const own = constraints.filter(({ rule }) => rule.target === "list");
197
+ const items = constraints.filter(({ rule }) => rule.target !== "list");
198
+ let list = z3.array(this.#typed(type.ofType, items, where));
199
+ for (const { rule, value } of own)
200
+ list = applyRule(rule, list, value);
201
+ return list;
202
+ }
203
+ if (isInputObjectType(type)) {
204
+ assertObjectTargets(type.name, constraints, where);
205
+ return this.#object(type);
206
+ }
207
+ return leafSchema(type, constraints, where);
208
+ }
209
+ #object(type) {
210
+ if (!this.isConstrained(type))
211
+ return z3.unknown();
212
+ const built = this.#objects.get(type.name);
213
+ if (built)
214
+ return built;
215
+ let schema;
216
+ this.#objects.set(type.name, z3.lazy(() => schema));
217
+ schema = z3.object(Object.fromEntries(Object.values(type.getFields()).map((field) => [
218
+ field.name,
219
+ this.of(field, `${type.name}.${field.name}`)
220
+ ])));
221
+ this.#objects.set(type.name, schema);
222
+ return schema;
223
+ }
224
+ }
225
+
226
+ // src/builder/check-constraints.ts
227
+ function checkConstraints2(schema, onArgs) {
228
+ const inputs = new InputSchemas(schema);
229
+ if (!inputs.directive)
230
+ return;
231
+ assertOwnConstraint(inputs.directive);
232
+ inputs.buildAll(schema);
233
+ assertNoDirectiveArgumentConstrained(inputs, schema);
234
+ for (const type of Object.values(schema.getTypeMap())) {
235
+ if (type.name.startsWith("__"))
236
+ continue;
237
+ if (isInterfaceType(type)) {
238
+ for (const field of Object.values(type.getFields()))
239
+ argsSchemaOf(inputs, type.name, field);
240
+ }
241
+ if (!isObjectType(type))
242
+ continue;
243
+ assertInterfaceConstraintsKept(inputs, type);
244
+ for (const field of Object.values(type.getFields())) {
245
+ const args = argsSchemaOf(inputs, type.name, field);
246
+ if (args)
247
+ onArgs?.(type, field, args);
248
+ }
249
+ }
250
+ inputs.checkDefaults();
251
+ return inputs.directive;
252
+ }
253
+ function assertNoDirectiveArgumentConstrained(inputs, schema) {
254
+ for (const directive of schema.getDirectives()) {
255
+ for (const arg of directive.args) {
256
+ if (constraintsOn2(inputs.directive, arg.astNode).length > 0) {
257
+ throw new Error(`@constraint on @${directive.name}(${arg.name}:) checks nothing: a directive's argument reaches no resolver. Remove it.`);
258
+ }
259
+ }
260
+ }
261
+ }
262
+
263
+ export { constraintsOn2, assertLeafTargets, assertObjectTargets, baseCode, checkConstraints2 };
264
+
265
+ //# debugId=7C317F3D691975BE64756E2164756E21
266
+ //# sourceMappingURL=index-s1kkmg35.js.map