@nxgt/graphql-validation 0.0.0-stage → 0.1.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 (95) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +209 -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/constraints.d.ts +16 -0
  8. package/dist/builder/constraints.d.ts.map +1 -0
  9. package/dist/builder/input-schema.d.ts +31 -0
  10. package/dist/builder/input-schema.d.ts.map +1 -0
  11. package/dist/builder/leaf.d.ts +14 -0
  12. package/dist/builder/leaf.d.ts.map +1 -0
  13. package/dist/chunks/index-n3hypgpf.js +315 -0
  14. package/dist/chunks/index-n3hypgpf.js.map +37 -0
  15. package/dist/cli.d.ts +3 -0
  16. package/dist/cli.d.ts.map +1 -0
  17. package/dist/cli.js +69 -0
  18. package/dist/cli.js.map +11 -0
  19. package/dist/constraint-directive.d.ts +21 -0
  20. package/dist/constraint-directive.d.ts.map +1 -0
  21. package/dist/formats/all.d.ts +9 -0
  22. package/dist/formats/all.d.ts.map +1 -0
  23. package/dist/formats/byte.d.ts +2 -0
  24. package/dist/formats/byte.d.ts.map +1 -0
  25. package/dist/formats/date-time.d.ts +2 -0
  26. package/dist/formats/date-time.d.ts.map +1 -0
  27. package/dist/formats/date.d.ts +2 -0
  28. package/dist/formats/date.d.ts.map +1 -0
  29. package/dist/formats/email.d.ts +2 -0
  30. package/dist/formats/email.d.ts.map +1 -0
  31. package/dist/formats/format.d.ts +15 -0
  32. package/dist/formats/format.d.ts.map +1 -0
  33. package/dist/formats/index.d.ts +13 -0
  34. package/dist/formats/index.d.ts.map +1 -0
  35. package/dist/formats/ipv4.d.ts +2 -0
  36. package/dist/formats/ipv4.d.ts.map +1 -0
  37. package/dist/formats/ipv6.d.ts +2 -0
  38. package/dist/formats/ipv6.d.ts.map +1 -0
  39. package/dist/formats/uri.d.ts +2 -0
  40. package/dist/formats/uri.d.ts.map +1 -0
  41. package/dist/formats/uuid.d.ts +2 -0
  42. package/dist/formats/uuid.d.ts.map +1 -0
  43. package/dist/index.d.ts +6 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +315 -0
  46. package/dist/index.js.map +16 -0
  47. package/dist/rules/all.d.ts +16 -0
  48. package/dist/rules/all.d.ts.map +1 -0
  49. package/dist/rules/contains.d.ts +2 -0
  50. package/dist/rules/contains.d.ts.map +1 -0
  51. package/dist/rules/ends-with.d.ts +2 -0
  52. package/dist/rules/ends-with.d.ts.map +1 -0
  53. package/dist/rules/exclusive-max.d.ts +2 -0
  54. package/dist/rules/exclusive-max.d.ts.map +1 -0
  55. package/dist/rules/exclusive-min.d.ts +2 -0
  56. package/dist/rules/exclusive-min.d.ts.map +1 -0
  57. package/dist/rules/format.d.ts +2 -0
  58. package/dist/rules/format.d.ts.map +1 -0
  59. package/dist/rules/index.d.ts +26 -0
  60. package/dist/rules/index.d.ts.map +1 -0
  61. package/dist/rules/max-items.d.ts +2 -0
  62. package/dist/rules/max-items.d.ts.map +1 -0
  63. package/dist/rules/max-length.d.ts +2 -0
  64. package/dist/rules/max-length.d.ts.map +1 -0
  65. package/dist/rules/max.d.ts +2 -0
  66. package/dist/rules/max.d.ts.map +1 -0
  67. package/dist/rules/min-items.d.ts +2 -0
  68. package/dist/rules/min-items.d.ts.map +1 -0
  69. package/dist/rules/min-length.d.ts +2 -0
  70. package/dist/rules/min-length.d.ts.map +1 -0
  71. package/dist/rules/min.d.ts +2 -0
  72. package/dist/rules/min.d.ts.map +1 -0
  73. package/dist/rules/multiple-of.d.ts +2 -0
  74. package/dist/rules/multiple-of.d.ts.map +1 -0
  75. package/dist/rules/not-contains.d.ts +2 -0
  76. package/dist/rules/not-contains.d.ts.map +1 -0
  77. package/dist/rules/pattern.d.ts +2 -0
  78. package/dist/rules/pattern.d.ts.map +1 -0
  79. package/dist/rules/rule.d.ts +55 -0
  80. package/dist/rules/rule.d.ts.map +1 -0
  81. package/dist/rules/starts-with.d.ts +2 -0
  82. package/dist/rules/starts-with.d.ts.map +1 -0
  83. package/dist/typedefs-command.d.ts +10 -0
  84. package/dist/typedefs-command.d.ts.map +1 -0
  85. package/dist/validated.d.ts +22 -0
  86. package/dist/validated.d.ts.map +1 -0
  87. package/dist/with-validation.d.ts +26 -0
  88. package/dist/with-validation.d.ts.map +1 -0
  89. package/docs/README.md +15 -0
  90. package/docs/guide/constraints.md +291 -0
  91. package/docs/guide/errors.md +194 -0
  92. package/docs/roadmap.md +30 -0
  93. package/docs/troubleshooting.md +260 -0
  94. package/graphql/constraint.graphqls +20 -0
  95. package/package.json +67 -5
@@ -0,0 +1,315 @@
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 constraintOf(issue) {
281
+ const fields = issue;
282
+ return Object.values(rules).find((rule) => rule.owns(fields))?.argument;
283
+ }
284
+
285
+ // src/constraint-directive.ts
286
+ var constraintTypeDefs2 = `directive @constraint(
287
+ ${Object.values(rules).map((rule) => ` ${rule.argument}: ${rule.type}`).join(`
288
+ `)}
289
+ ) on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION
290
+ `;
291
+ var allowed = new Set([
292
+ DirectiveLocation.ARGUMENT_DEFINITION,
293
+ DirectiveLocation.INPUT_FIELD_DEFINITION
294
+ ]);
295
+ function assertOwnConstraint(directive) {
296
+ const problems = [
297
+ ...directive.isRepeatable ? ["repeatable, and only its first use is read"] : [],
298
+ ...directive.locations.filter((location) => !allowed.has(location)).map((location) => `allowed on ${location}`),
299
+ ...directive.args.flatMap((arg) => {
300
+ const rule = rules[arg.name];
301
+ if (!rule)
302
+ return [`declares ${arg.name}, which no rule reads`];
303
+ const type = String(arg.type);
304
+ return type === rule.type ? [] : [`declares ${arg.name}: ${type}, not ${rule.type}`];
305
+ })
306
+ ];
307
+ if (problems.length > 0) {
308
+ throw new Error(`This schema's @constraint is not constraintTypeDefs': it is ${problems.join("; ")}. Declare it with constraintTypeDefs.`);
309
+ }
310
+ }
311
+
312
+ export { rules, applyRule, constraintOf, constraintTypeDefs2, assertOwnConstraint };
313
+
314
+ //# debugId=4D959B1CB64DEA2664756E2164756E21
315
+ //# sourceMappingURL=index-n3hypgpf.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/** 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": "4D959B1CB64DEA2664756E2164756E21",
36
+ "names": []
37
+ }
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,69 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ constraintTypeDefs2
4
+ } from "./chunks/index-n3hypgpf.js";
5
+
6
+ // src/typedefs-command.ts
7
+ import { mkdir, writeFile } from "node:fs/promises";
8
+ import { dirname } from "node:path";
9
+ var DEFAULT_OUT = "generated/graphql/constraint.graphqls";
10
+ var usage = `Usage: nxgt-graphql-validation typedefs [--out [<file>]]
11
+
12
+ typedefs print the SDL of @constraint
13
+ --out [<file>] write it to <file> instead, creating its folder
14
+ (default: ${DEFAULT_OUT})
15
+ --help, -h show this help
16
+ `;
17
+ function graphqls() {
18
+ return `# The @constraint directive of @nxgt/graphql-validation, for your IDE.
19
+ # Generated by \`nxgt-graphql-validation typedefs\`: do not edit.
20
+
21
+ ${constraintTypeDefs2}`;
22
+ }
23
+ function refuse(message) {
24
+ process.stderr.write(`${message}
25
+
26
+ ${usage}`);
27
+ return 2;
28
+ }
29
+ async function main(argv) {
30
+ if (argv.includes("--help") || argv.includes("-h")) {
31
+ process.stdout.write(usage);
32
+ return 0;
33
+ }
34
+ const [command, ...rest] = argv;
35
+ if (command === undefined)
36
+ return refuse("No command.");
37
+ if (command !== "typedefs")
38
+ return refuse(`Unknown command "${command}".`);
39
+ if (rest.length === 0) {
40
+ process.stdout.write(graphqls());
41
+ return 0;
42
+ }
43
+ const [flag, file, ...extra] = rest;
44
+ if (flag !== "--out" || extra.length > 0 || file === "" || file?.startsWith("-")) {
45
+ return refuse(`Unexpected arguments: ${rest.join(" ")}`);
46
+ }
47
+ const out = file ?? DEFAULT_OUT;
48
+ try {
49
+ await mkdir(dirname(out), { recursive: true });
50
+ await writeFile(out, graphqls());
51
+ } catch (error) {
52
+ process.stderr.write(`typedefs failed: ${error.message}
53
+ `);
54
+ return 1;
55
+ }
56
+ process.stdout.write(`Wrote ${out}
57
+ `);
58
+ return 0;
59
+ }
60
+
61
+ // src/cli.ts
62
+ process.stdout.on("error", (error) => {
63
+ if (error.code !== "EPIPE")
64
+ throw error;
65
+ });
66
+ process.exitCode = await main(process.argv.slice(2));
67
+
68
+ //# debugId=675FAE0D80D1DEF264756E2164756E21
69
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1,11 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/typedefs-command.ts", "../src/cli.ts"],
4
+ "sourcesContent": [
5
+ "// The `typedefs` command of the bin, apart from `cli.ts` so a spec can run\n// it without spawning a process. Its flags read as `nxgt-graphql-scalars\n// typedefs`' do, so both bins are used the same way.\nimport { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname } from 'node:path';\nimport { constraintTypeDefs } from './constraint-directive';\n\n/** Where `--out` writes when it is given no file. */\nexport const DEFAULT_OUT = 'generated/graphql/constraint.graphqls';\n\nconst usage = `Usage: nxgt-graphql-validation typedefs [--out [<file>]]\n\n typedefs print the SDL of @constraint\n --out [<file>] write it to <file> instead, creating its folder\n (default: ${DEFAULT_OUT})\n --help, -h show this help\n`;\n\n/** The `.graphqls` file's content: a header, then the SDL. */\nexport function graphqls(): string {\n\treturn `# The @constraint directive of @nxgt/graphql-validation, for your IDE.\\n# Generated by \\`nxgt-graphql-validation typedefs\\`: do not edit.\\n\\n${constraintTypeDefs}`;\n}\n\nfunction refuse(message: string): number {\n\tprocess.stderr.write(`${message}\\n\\n${usage}`);\n\treturn 2;\n}\n\n/**\n * Runs the bin on `argv`: 0 done, 1 the file could not be written, 2 a usage\n * error (nxgt-mongo-backup's convention). `--help` anywhere wins.\n */\nexport async function main(argv: readonly string[]): Promise<number> {\n\tif (argv.includes('--help') || argv.includes('-h')) {\n\t\tprocess.stdout.write(usage);\n\t\treturn 0;\n\t}\n\tconst [command, ...rest] = argv;\n\tif (command === undefined) return refuse('No command.');\n\tif (command !== 'typedefs') return refuse(`Unknown command \"${command}\".`);\n\tif (rest.length === 0) {\n\t\tprocess.stdout.write(graphqls());\n\t\treturn 0;\n\t}\n\tconst [flag, file, ...extra] = rest;\n\tif (\n\t\tflag !== '--out' ||\n\t\textra.length > 0 ||\n\t\tfile === '' ||\n\t\tfile?.startsWith('-')\n\t) {\n\t\treturn refuse(`Unexpected arguments: ${rest.join(' ')}`);\n\t}\n\tconst out = file ?? DEFAULT_OUT;\n\ttry {\n\t\tawait mkdir(dirname(out), { recursive: true });\n\t\tawait writeFile(out, graphqls());\n\t} catch (error) {\n\t\tprocess.stderr.write(`typedefs failed: ${(error as Error).message}\\n`);\n\t\treturn 1;\n\t}\n\tprocess.stdout.write(`Wrote ${out}\\n`);\n\treturn 0;\n}\n",
6
+ "#!/usr/bin/env node\n/**\n * The `nxgt-graphql-validation` bin. One command, `typedefs`: the SDL of\n * `@constraint` — what `constraintTypeDefs` holds — on standard output or\n * into a file, so an IDE's GraphQL plugin knows the directive without a\n * running server. It reads nothing and writes only the file it is given.\n */\nimport { main } from './typedefs-command';\n\n// A reader that closed the pipe (`| head`) wants no more: not an error.\nprocess.stdout.on('error', (error: NodeJS.ErrnoException) => {\n\tif (error.code !== 'EPIPE') throw error;\n});\n\nprocess.exitCode = await main(process.argv.slice(2));\n"
7
+ ],
8
+ "mappings": ";;;;;;AAGA;AACA;AAIO,IAAM,cAAc;AAE3B,IAAM,QAAQ;AAAA;AAAA;AAAA;AAAA,iCAImB;AAAA;AAAA;AAK1B,SAAS,QAAQ,GAAW;AAAA,EAClC,OAAO;AAAA;AAAA;AAAA,EAAgJ;AAAA;AAGxJ,SAAS,MAAM,CAAC,SAAyB;AAAA,EACxC,QAAQ,OAAO,MAAM,GAAG;AAAA;AAAA,EAAc,OAAO;AAAA,EAC7C,OAAO;AAAA;AAOR,eAAsB,IAAI,CAAC,MAA0C;AAAA,EACpE,IAAI,KAAK,SAAS,QAAQ,KAAK,KAAK,SAAS,IAAI,GAAG;AAAA,IACnD,QAAQ,OAAO,MAAM,KAAK;AAAA,IAC1B,OAAO;AAAA,EACR;AAAA,EACA,OAAO,YAAY,QAAQ;AAAA,EAC3B,IAAI,YAAY;AAAA,IAAW,OAAO,OAAO,aAAa;AAAA,EACtD,IAAI,YAAY;AAAA,IAAY,OAAO,OAAO,oBAAoB,WAAW;AAAA,EACzE,IAAI,KAAK,WAAW,GAAG;AAAA,IACtB,QAAQ,OAAO,MAAM,SAAS,CAAC;AAAA,IAC/B,OAAO;AAAA,EACR;AAAA,EACA,OAAO,MAAM,SAAS,SAAS;AAAA,EAC/B,IACC,SAAS,WACT,MAAM,SAAS,KACf,SAAS,MACT,MAAM,WAAW,GAAG,GACnB;AAAA,IACD,OAAO,OAAO,yBAAyB,KAAK,KAAK,GAAG,GAAG;AAAA,EACxD;AAAA,EACA,MAAM,MAAM,QAAQ;AAAA,EACpB,IAAI;AAAA,IACH,MAAM,MAAM,QAAQ,GAAG,GAAG,EAAE,WAAW,KAAK,CAAC;AAAA,IAC7C,MAAM,UAAU,KAAK,SAAS,CAAC;AAAA,IAC9B,OAAO,OAAO;AAAA,IACf,QAAQ,OAAO,MAAM,oBAAqB,MAAgB;AAAA,CAAW;AAAA,IACrE,OAAO;AAAA;AAAA,EAER,QAAQ,OAAO,MAAM,SAAS;AAAA,CAAO;AAAA,EACrC,OAAO;AAAA;;;ACpDR,QAAQ,OAAO,GAAG,SAAS,CAAC,UAAiC;AAAA,EAC5D,IAAI,MAAM,SAAS;AAAA,IAAS,MAAM;AAAA,CAClC;AAED,QAAQ,WAAW,MAAM,KAAK,QAAQ,KAAK,MAAM,CAAC,CAAC;",
9
+ "debugId": "675FAE0D80D1DEF264756E2164756E21",
10
+ "names": []
11
+ }
@@ -0,0 +1,21 @@
1
+ import { type GraphQLDirective } from 'graphql';
2
+ /**
3
+ * The SDL of `@constraint`, to add to a schema-first server's `typeDefs`,
4
+ * written from the rules: an argument is declared once its rule exists.
5
+ *
6
+ * Its arguments are graphql-constraint-directive's, minus `uniqueTypeName`
7
+ * (a detail of that package's scalar wrapping). It is allowed on arguments
8
+ * and input fields only, where that package also allows output fields: a
9
+ * resolver's result is the output scalars' job, and a directive that checked
10
+ * nothing there would be a promise broken in silence.
11
+ */
12
+ export declare const constraintTypeDefs: string;
13
+ /**
14
+ * Fails when the schema's `@constraint` is not the one
15
+ * {@link constraintTypeDefs} declares — graphql-constraint-directive's, say,
16
+ * kept from a migration. Its extra locations would be accepted and checked
17
+ * by nothing, its extra arguments mean nothing here, and an argument of
18
+ * another type would reach a rule as the wrong kind of value.
19
+ */
20
+ export declare function assertOwnConstraint(directive: GraphQLDirective): void;
21
+ //# sourceMappingURL=constraint-directive.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constraint-directive.d.ts","sourceRoot":"","sources":["../src/constraint-directive.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAGnE;;;;;;;;;GASG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAKhC,CAAC;AAOF;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,gBAAgB,GAAG,IAAI,CAwBrE"}
@@ -0,0 +1,9 @@
1
+ export * from './byte';
2
+ export * from './date';
3
+ export * from './date-time';
4
+ export * from './email';
5
+ export * from './ipv4';
6
+ export * from './ipv6';
7
+ export * from './uri';
8
+ export * from './uuid';
9
+ //# sourceMappingURL=all.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"all.d.ts","sourceRoot":"","sources":["../../src/formats/all.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,OAAO,CAAC;AACtB,cAAc,QAAQ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const byteFormat: import("./format").Format<"byte">;
2
+ //# sourceMappingURL=byte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"byte.d.ts","sourceRoot":"","sources":["../../src/formats/byte.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,UAAU,mCAIrB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const dateTimeFormat: import("./format").Format<"date-time">;
2
+ //# sourceMappingURL=date-time.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"date-time.d.ts","sourceRoot":"","sources":["../../src/formats/date-time.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,cAAc,wCAIzB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const dateFormat: import("./format").Format<"date">;
2
+ //# sourceMappingURL=date.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"date.d.ts","sourceRoot":"","sources":["../../src/formats/date.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,UAAU,mCAIrB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const emailFormat: import("./format").Format<"email">;
2
+ //# sourceMappingURL=email.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"email.d.ts","sourceRoot":"","sources":["../../src/formats/email.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,WAAW,oCAItB,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { z } from 'zod';
2
+ /** A string schema, plain or a format (`z.email()` is not a `z.ZodString`). */
3
+ export type StringSchema = z.ZodString | z.ZodStringFormat;
4
+ /**
5
+ * One value of `@constraint(format: "...")`: the schema it stands for, as a
6
+ * schema at startup and as source for a code generator.
7
+ */
8
+ export interface Format<N extends string = string> {
9
+ readonly name: N;
10
+ readonly toZod: () => StringSchema;
11
+ readonly toCode: () => string;
12
+ }
13
+ /** Declares a format, with its name kept literal. */
14
+ export declare function defineFormat<const N extends string>(format: Format<N>): Format<N>;
15
+ //# sourceMappingURL=format.d.ts.map
@@ -0,0 +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;;;GAGG;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,EAAE,MAAM,MAAM,CAAC;CAC9B;AAED,qDAAqD;AACrD,wBAAgB,YAAY,CAAC,KAAK,CAAC,CAAC,SAAS,MAAM,EAClD,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,GACf,MAAM,CAAC,CAAC,CAAC,CAEX"}
@@ -0,0 +1,13 @@
1
+ import * as all from './all';
2
+ import type { Format } from './format';
3
+ /**
4
+ * Every format, keyed by the value `@constraint(format: "...")` takes.
5
+ * Derived from what `./all` exports, so a new format is one file and one
6
+ * line there.
7
+ */
8
+ export declare const formats: { readonly [N in FormatName]: Format<N>; };
9
+ /** A value `@constraint(format: "...")` takes. */
10
+ export type FormatName = (typeof all)[keyof typeof all]['name'];
11
+ /** The format named `name`, or an error that lists the known ones. */
12
+ export declare function formatNamed(name: string): Format;
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/formats/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,OAAO,CAAC;AAC7B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAEvC;;;;GAIG;AACH,eAAO,MAAM,OAAO,EAEf,EAAE,QAAQ,EAAE,CAAC,IAAI,UAAU,GAAG,MAAM,CAAC,CAAC,CAAC,GAAE,CAAC;AAE/C,kDAAkD;AAClD,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,GAAG,CAAC,CAAC,MAAM,OAAO,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC;AAEhE,sEAAsE;AACtE,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKhD"}
@@ -0,0 +1,2 @@
1
+ export declare const ipv4Format: import("./format").Format<"ipv4">;
2
+ //# sourceMappingURL=ipv4.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ipv4.d.ts","sourceRoot":"","sources":["../../src/formats/ipv4.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,UAAU,mCAIrB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const ipv6Format: import("./format").Format<"ipv6">;
2
+ //# sourceMappingURL=ipv6.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ipv6.d.ts","sourceRoot":"","sources":["../../src/formats/ipv6.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,UAAU,mCAIrB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const uriFormat: import("./format").Format<"uri">;
2
+ //# sourceMappingURL=uri.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uri.d.ts","sourceRoot":"","sources":["../../src/formats/uri.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,SAAS,kCAIpB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const uuidFormat: import("./format").Format<"uuid">;
2
+ //# sourceMappingURL=uuid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uuid.d.ts","sourceRoot":"","sources":["../../src/formats/uuid.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,UAAU,mCAIrB,CAAC"}