@nxgt/graphql-validation 0.2.1 → 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 +64 -5
- package/dist/builder/check-constraints.d.ts +6 -1
- package/dist/builder/check-constraints.d.ts.map +1 -1
- package/dist/builder/input-code.d.ts +14 -1
- package/dist/builder/input-code.d.ts.map +1 -1
- package/dist/builder/input-schema.d.ts +3 -1
- package/dist/builder/input-schema.d.ts.map +1 -1
- package/dist/builder/leaf.d.ts +2 -2
- package/dist/builder/leaf.d.ts.map +1 -1
- package/dist/chunks/index-twevz7yc.js +527 -0
- package/dist/chunks/index-twevz7yc.js.map +26 -0
- package/dist/chunks/{index-rbxe5m3y.js → index-xcaf9kes.js} +24 -97
- package/dist/chunks/index-xcaf9kes.js.map +27 -0
- package/dist/cli.js +1 -1
- package/dist/codegen.d.ts +1 -0
- package/dist/codegen.d.ts.map +1 -1
- package/dist/codegen.js +19 -9
- package/dist/codegen.js.map +3 -3
- package/dist/formats/byte.d.ts +1 -1
- package/dist/formats/byte.d.ts.map +1 -1
- package/dist/formats/date-time.d.ts +1 -1
- package/dist/formats/date-time.d.ts.map +1 -1
- package/dist/formats/date.d.ts +1 -1
- package/dist/formats/date.d.ts.map +1 -1
- package/dist/formats/email.d.ts +1 -1
- package/dist/formats/email.d.ts.map +1 -1
- package/dist/formats/format.d.ts +17 -3
- package/dist/formats/format.d.ts.map +1 -1
- package/dist/formats/index.d.ts +6 -8
- package/dist/formats/index.d.ts.map +1 -1
- package/dist/formats/ipv4.d.ts +1 -1
- package/dist/formats/ipv4.d.ts.map +1 -1
- package/dist/formats/ipv6.d.ts +1 -1
- package/dist/formats/ipv6.d.ts.map +1 -1
- package/dist/formats/marked.d.ts +42 -0
- package/dist/formats/marked.d.ts.map +1 -0
- package/dist/formats/registry.d.ts +50 -0
- package/dist/formats/registry.d.ts.map +1 -0
- package/dist/formats/uri.d.ts +1 -1
- package/dist/formats/uri.d.ts.map +1 -1
- package/dist/formats/uuid.d.ts +1 -1
- package/dist/formats/uuid.d.ts.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -5
- package/dist/index.js.map +3 -3
- package/dist/rules/format.d.ts.map +1 -1
- package/dist/rules/index.d.ts +8 -3
- package/dist/rules/index.d.ts.map +1 -1
- package/dist/rules/rule.d.ts +19 -2
- package/dist/rules/rule.d.ts.map +1 -1
- package/dist/with-validation.d.ts +17 -1
- package/dist/with-validation.d.ts.map +1 -1
- package/docs/README.md +1 -1
- package/docs/guide/constraints.md +149 -4
- package/docs/guide/errors.md +4 -1
- package/docs/roadmap.md +19 -15
- package/docs/troubleshooting.md +157 -4
- package/package.json +2 -2
- package/dist/chunks/index-rbxe5m3y.js.map +0 -37
- package/dist/chunks/index-s1kkmg35.js +0 -266
- package/dist/chunks/index-s1kkmg35.js.map +0 -14
|
@@ -17,8 +17,8 @@ var __export = (target, all) => {
|
|
|
17
17
|
import { DirectiveLocation } from "graphql";
|
|
18
18
|
|
|
19
19
|
// src/rules/all.ts
|
|
20
|
-
var
|
|
21
|
-
__export(
|
|
20
|
+
var exports_all = {};
|
|
21
|
+
__export(exports_all, {
|
|
22
22
|
containsRule: () => containsRule,
|
|
23
23
|
endsWithRule: () => endsWithRule,
|
|
24
24
|
exclusiveMaxRule: () => exclusiveMaxRule,
|
|
@@ -37,6 +37,7 @@ __export(exports_all2, {
|
|
|
37
37
|
});
|
|
38
38
|
|
|
39
39
|
// src/rules/rule.ts
|
|
40
|
+
var RULE_PARAM = "nxgtConstraint";
|
|
40
41
|
function defineRule(rule) {
|
|
41
42
|
return rule;
|
|
42
43
|
}
|
|
@@ -78,90 +79,6 @@ var exclusiveMinRule = defineRule({
|
|
|
78
79
|
toCode: (schema, value) => `${schema}.gt(${value})`,
|
|
79
80
|
owns: (issue) => issue.code === "too_small" && issue.origin === "number" && issue.inclusive === false
|
|
80
81
|
});
|
|
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
82
|
// src/rules/format.ts
|
|
166
83
|
var NARROWING = new Set(["starts_with", "ends_with", "includes", "regex"]);
|
|
167
84
|
var formatRule = defineRule({
|
|
@@ -169,9 +86,16 @@ var formatRule = defineRule({
|
|
|
169
86
|
type: "String",
|
|
170
87
|
target: "string",
|
|
171
88
|
base: true,
|
|
172
|
-
toZod: (_schema, value) =>
|
|
173
|
-
toCode: (_schema, value) =>
|
|
174
|
-
|
|
89
|
+
toZod: (_schema, value, { formats }) => formats.named(value).toZod(),
|
|
90
|
+
toCode: (_schema, value, { formats, formatCode }) => {
|
|
91
|
+
const format = formats.named(value);
|
|
92
|
+
if (format.toCode)
|
|
93
|
+
return format.toCode();
|
|
94
|
+
if (formatCode)
|
|
95
|
+
return formatCode(value);
|
|
96
|
+
throw new Error(`@constraint(format: "${value}") is one of the application's formats: its source is the code generator's to write, through inputCode's format option.`);
|
|
97
|
+
},
|
|
98
|
+
owns: (issue) => issue.params?.[RULE_PARAM] === "format" || issue.code === "invalid_format" && !NARROWING.has(issue.format ?? "")
|
|
175
99
|
});
|
|
176
100
|
// src/rules/max.ts
|
|
177
101
|
var maxRule = defineRule({
|
|
@@ -272,17 +196,20 @@ var startsWithRule = defineRule({
|
|
|
272
196
|
owns: (issue) => issue.format === "starts_with"
|
|
273
197
|
});
|
|
274
198
|
// src/rules/index.ts
|
|
275
|
-
var rules = Object.fromEntries(Object.values(
|
|
276
|
-
function applyRule(rule, schema, value) {
|
|
199
|
+
var rules = Object.fromEntries(Object.values(exports_all).map((rule) => [rule.argument, rule]));
|
|
200
|
+
function applyRule(rule, schema, value, context) {
|
|
277
201
|
const toZod = rule.toZod;
|
|
278
|
-
return toZod(schema, value);
|
|
202
|
+
return toZod(schema, value, context);
|
|
279
203
|
}
|
|
280
|
-
function applyRuleCode(rule, source, value) {
|
|
204
|
+
function applyRuleCode(rule, source, value, context) {
|
|
281
205
|
const toCode = rule.toCode;
|
|
282
|
-
return toCode(source, value);
|
|
206
|
+
return toCode(source, value, context);
|
|
283
207
|
}
|
|
284
208
|
function constraintOf(issue) {
|
|
285
209
|
const fields = issue;
|
|
210
|
+
const marked = fields.params?.[RULE_PARAM];
|
|
211
|
+
if (typeof marked === "string" && Object.hasOwn(rules, marked))
|
|
212
|
+
return marked;
|
|
286
213
|
return Object.values(rules).find((rule) => rule.owns(fields))?.argument;
|
|
287
214
|
}
|
|
288
215
|
|
|
@@ -313,7 +240,7 @@ function assertOwnConstraint(directive) {
|
|
|
313
240
|
}
|
|
314
241
|
}
|
|
315
242
|
|
|
316
|
-
export { rules, applyRule, applyRuleCode, constraintOf, constraintTypeDefs2, assertOwnConstraint };
|
|
243
|
+
export { __export, RULE_PARAM, rules, applyRule, applyRuleCode, constraintOf, constraintTypeDefs2, assertOwnConstraint };
|
|
317
244
|
|
|
318
|
-
//# debugId=
|
|
319
|
-
//# sourceMappingURL=index-
|
|
245
|
+
//# debugId=AD9C9BDBBBE92EA564756E2164756E21
|
|
246
|
+
//# sourceMappingURL=index-xcaf9kes.js.map
|
|
@@ -0,0 +1,27 @@
|
|
|
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/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';\nimport type { FormatRegistry } from '../formats/registry';\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/**\n * What a rule may read besides its value: the formats `format` resolves\n * against, the built-in ones and the application's own, and, when writing\n * source, how to write one of the application's (`InputCodeOptions.format`).\n */\nexport interface RuleContext {\n\treadonly formats: FormatRegistry;\n\treadonly formatCode?: ((name: string) => string) | undefined;\n}\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: (\n\t\tschema: Targets[K],\n\t\tvalue: ValueOf[T],\n\t\tcontext: RuleContext,\n\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: (\n\t\tschema: string,\n\t\tvalue: ValueOf[T],\n\t\tcontext: RuleContext,\n\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\treadonly params?: Readonly<Record<string, unknown>>;\n}\n\n/**\n * The `params` key that marks an issue as one argument's whatever its code:\n * an application format's issues carry `format` there, so a `.regex()` or a\n * `.refine()` inside one is not read as `pattern` or `notContains`.\n */\nexport const RULE_PARAM = 'nxgtConstraint';\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 { defineRule, RULE_PARAM } 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, { formats }) => formats.named(value).toZod(),\n\ttoCode: (_schema, value, { formats, formatCode }) => {\n\t\tconst format = formats.named(value);\n\t\tif (format.toCode) return format.toCode();\n\t\tif (formatCode) return formatCode(value);\n\t\tthrow new Error(\n\t\t\t`@constraint(format: \"${value}\") is one of the application's formats: its source is the code generator's to write, through inputCode's format option.`,\n\t\t);\n\t},\n\t// An application format's issues are marked, whatever their code\n\t// (`custom` for a `.refine()`): see FormatRegistry.\n\towns: (issue) =>\n\t\tissue.params?.[RULE_PARAM] === 'format' ||\n\t\t(issue.code === 'invalid_format' && !NARROWING.has(issue.format ?? '')),\n});\n",
|
|
12
|
+
"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",
|
|
13
|
+
"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",
|
|
14
|
+
"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",
|
|
15
|
+
"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",
|
|
16
|
+
"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",
|
|
17
|
+
"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",
|
|
18
|
+
"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",
|
|
19
|
+
"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",
|
|
20
|
+
"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",
|
|
21
|
+
"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",
|
|
22
|
+
"import type { z } from 'zod';\nimport * as all from './all';\nimport { type IssueFields, RULE_PARAM, type RuleContext } 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\tcontext: RuleContext,\n): z.ZodType {\n\tconst toZod = rule.toZod as unknown as (\n\t\tschema: z.ZodType,\n\t\tvalue: string | number,\n\t\tcontext: RuleContext,\n\t) => z.ZodType;\n\treturn toZod(schema, value, context);\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\tcontext: RuleContext,\n): string {\n\tconst toCode = rule.toCode as (\n\t\tschema: string,\n\t\tvalue: string | number,\n\t\tcontext: RuleContext,\n\t) => string;\n\treturn toCode(source, value, context);\n}\n\n/**\n * The `@constraint` argument whose rule refused with this issue, if any: the\n * one the issue is marked with (an application format's), else the one rule\n * that owns its shape.\n */\nexport function constraintOf(\n\tissue: z.core.$ZodIssue,\n): ConstraintArgument | undefined {\n\tconst fields = issue as unknown as IssueFields;\n\tconst marked = fields.params?.[RULE_PARAM];\n\tif (typeof marked === 'string' && Object.hasOwn(rules, marked))\n\t\treturn marked as ConstraintArgument;\n\treturn Object.values(rules).find((rule) => rule.owns(fields))?.argument;\n}\n"
|
|
23
|
+
],
|
|
24
|
+
"mappings": "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",
|
|
25
|
+
"debugId": "AD9C9BDBBBE92EA564756E2164756E21",
|
|
26
|
+
"names": []
|
|
27
|
+
}
|
package/dist/cli.js
CHANGED
package/dist/codegen.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { checkConstraints } from './builder/check-constraints.js';
|
|
2
2
|
export { type Constraint, constraintsOn } from './builder/constraints.js';
|
|
3
3
|
export { type InputCodeOptions, inputCode } from './builder/input-code.js';
|
|
4
|
+
export type { FormatSchemas } from './formats/registry.js';
|
|
4
5
|
//# sourceMappingURL=codegen.d.ts.map
|
package/dist/codegen.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codegen.d.ts","sourceRoot":"","sources":["../src/codegen.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,KAAK,UAAU,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,KAAK,gBAAgB,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC"}
|
|
1
|
+
{"version":3,"file":"codegen.d.ts","sourceRoot":"","sources":["../src/codegen.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,KAAK,UAAU,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,KAAK,gBAAgB,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACxE,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC"}
|
package/dist/codegen.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
applyRuleCode
|
|
3
|
-
} from "./chunks/index-
|
|
3
|
+
} from "./chunks/index-xcaf9kes.js";
|
|
4
4
|
import {
|
|
5
|
+
registryOf,
|
|
5
6
|
constraintsOn2,
|
|
6
7
|
assertLeafTargets,
|
|
7
8
|
assertObjectTargets,
|
|
8
9
|
baseCode,
|
|
9
10
|
checkConstraints2
|
|
10
|
-
} from "./chunks/index-
|
|
11
|
+
} from "./chunks/index-twevz7yc.js";
|
|
11
12
|
// src/builder/input-code.ts
|
|
12
13
|
import {
|
|
13
14
|
getNamedType,
|
|
@@ -15,8 +16,13 @@ import {
|
|
|
15
16
|
isListType,
|
|
16
17
|
isNonNullType
|
|
17
18
|
} from "graphql";
|
|
18
|
-
function inputCode(type, constraints, where, named, options = {}) {
|
|
19
|
-
const write = {
|
|
19
|
+
function inputCode(type, constraints, where, named, options = {}, formats) {
|
|
20
|
+
const write = {
|
|
21
|
+
where,
|
|
22
|
+
named,
|
|
23
|
+
options,
|
|
24
|
+
formats: registryOf(formats)
|
|
25
|
+
};
|
|
20
26
|
return typedCode(write, type, constraints);
|
|
21
27
|
}
|
|
22
28
|
function typedCode(write, type, constraints) {
|
|
@@ -30,7 +36,7 @@ function requiredCode(write, type, constraints) {
|
|
|
30
36
|
if (isListType(type)) {
|
|
31
37
|
const own = constraints.filter(({ rule }) => rule.target === "list");
|
|
32
38
|
const items = constraints.filter(({ rule }) => rule.target !== "list");
|
|
33
|
-
const code = applyCode(`z.array(${typedCode(write, type.ofType, items)})`, own);
|
|
39
|
+
const code = applyCode(write, `z.array(${typedCode(write, type.ofType, items)})`, own);
|
|
34
40
|
if (!write.options.list)
|
|
35
41
|
return code;
|
|
36
42
|
const single = requiredCode(write, getNamedType(type), []);
|
|
@@ -41,10 +47,14 @@ function requiredCode(write, type, constraints) {
|
|
|
41
47
|
return write.named(type);
|
|
42
48
|
}
|
|
43
49
|
assertLeafTargets(type, constraints, write.where);
|
|
44
|
-
return applyCode(baseCode(type) ?? write.named(type), constraints);
|
|
50
|
+
return applyCode(write, baseCode(type) ?? write.named(type), constraints);
|
|
45
51
|
}
|
|
46
|
-
function applyCode(source, constraints) {
|
|
47
|
-
|
|
52
|
+
function applyCode(write, source, constraints) {
|
|
53
|
+
const context = {
|
|
54
|
+
formats: write.formats,
|
|
55
|
+
formatCode: write.options.format
|
|
56
|
+
};
|
|
57
|
+
return constraints.reduce((code, { rule, value }) => applyRuleCode(rule, code, value, context), source);
|
|
48
58
|
}
|
|
49
59
|
export {
|
|
50
60
|
checkConstraints2 as checkConstraints,
|
|
@@ -52,5 +62,5 @@ export {
|
|
|
52
62
|
inputCode
|
|
53
63
|
};
|
|
54
64
|
|
|
55
|
-
//# debugId=
|
|
65
|
+
//# debugId=95B0758BEEE7072864756E2164756E21
|
|
56
66
|
//# sourceMappingURL=codegen.js.map
|
package/dist/codegen.js.map
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/builder/input-code.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import {\n\ttype GraphQLInputType,\n\ttype GraphQLList,\n\ttype GraphQLNamedInputType,\n\tgetNamedType,\n\tisInputObjectType,\n\tisListType,\n\tisNonNullType,\n} from 'graphql';\nimport { applyRuleCode } from '../rules';\nimport type { Constraint } from './constraints';\nimport { assertLeafTargets, assertObjectTargets, baseCode } from './leaf';\n\n/**\n * The source of the schema of one argument or input field: what\n * `InputSchemas` builds at startup, written for a code generator. The\n * source names zod as a free `z`.\n *\n * The runtime leaves what graphql already checked to graphql; generated\n * code checks every value, so each named type comes from `named`: an input\n * object's or an enum's schema by name, a custom scalar's from a mapping.\n * The built-in scalars are written here, with their constraints. A\n * constraint that cannot apply fails as it does at startup.\n */\nexport function inputCode(\n\ttype: GraphQLInputType,\n\tconstraints: readonly Constraint[],\n\twhere: string,\n\tnamed: (type: GraphQLNamedInputType) => string,\n\toptions: InputCodeOptions = {},\n): string {\n\tconst write: Write = {
|
|
5
|
+
"import {\n\ttype GraphQLInputType,\n\ttype GraphQLList,\n\ttype GraphQLNamedInputType,\n\tgetNamedType,\n\tisInputObjectType,\n\tisListType,\n\tisNonNullType,\n} from 'graphql';\nimport {\n\ttype FormatRegistry,\n\ttype FormatSchemas,\n\tregistryOf,\n} from '../formats/registry';\nimport { applyRuleCode } from '../rules';\nimport type { Constraint } from './constraints';\nimport { assertLeafTargets, assertObjectTargets, baseCode } from './leaf';\n\n/**\n * The source of the schema of one argument or input field: what\n * `InputSchemas` builds at startup, written for a code generator. The\n * source names zod as a free `z`.\n *\n * The runtime leaves what graphql already checked to graphql; generated\n * code checks every value, so each named type comes from `named`: an input\n * object's or an enum's schema by name, a custom scalar's from a mapping.\n * The built-in scalars are written here, with their constraints. A\n * constraint that cannot apply fails as it does at startup.\n *\n * `formats` are the application's own, as `withValidation` takes them: a\n * name among them is a known format, which a built-in one is not. Their\n * source is `options.format`'s to write.\n */\nexport function inputCode(\n\ttype: GraphQLInputType,\n\tconstraints: readonly Constraint[],\n\twhere: string,\n\tnamed: (type: GraphQLNamedInputType) => string,\n\toptions: InputCodeOptions = {},\n\tformats?: FormatSchemas,\n): string {\n\tconst write: Write = {\n\t\twhere,\n\t\tnamed,\n\t\toptions,\n\t\tformats: registryOf(formats),\n\t};\n\treturn typedCode(write, type, constraints);\n}\n\n/** How `inputCode` writes what a generator may want written otherwise. */\nexport interface InputCodeOptions {\n\t/**\n\t * A list's schema, given its `type`, `code` (the array with every rule)\n\t * and `single` (the list's named type, non-null, without rules): to\n\t * take a single value for a list, as graphql does, `single` wrapped then\n\t * piped into `code`. Default: `code`.\n\t */\n\treadonly list?: (list: {\n\t\treadonly type: GraphQLList<GraphQLInputType>;\n\t\treadonly code: string;\n\t\treadonly single: string;\n\t}) => string;\n\t/**\n\t * The source of one of the application's formats, given its name (a key\n\t * of the `formats` record): a reference to the application's own schema,\n\t * which the rules after `format` narrow (`formatSchemas.slug.max(40)`).\n\t * A built-in format is written inline and never reaches it. Without it,\n\t * a field using one of the application's formats throws.\n\t */\n\treadonly format?: (name: string) => string;\n}\n\ninterface Write {\n\treadonly where: string;\n\treadonly named: (type: GraphQLNamedInputType) => string;\n\treadonly options: InputCodeOptions;\n\treadonly formats: FormatRegistry;\n}\n\nfunction typedCode(\n\twrite: Write,\n\ttype: GraphQLInputType,\n\tconstraints: readonly Constraint[],\n): string {\n\tif (isNonNullType(type)) return requiredCode(write, type.ofType, constraints);\n\treturn `${requiredCode(write, type, constraints)}.nullish()`;\n}\n\nfunction requiredCode(\n\twrite: Write,\n\ttype: GraphQLInputType,\n\tconstraints: readonly Constraint[],\n): string {\n\tif (isNonNullType(type)) return requiredCode(write, type.ofType, constraints);\n\tif (isListType(type)) {\n\t\t// minItems and maxItems are the list's; every other rule is its items'.\n\t\tconst own = constraints.filter(({ rule }) => rule.target === 'list');\n\t\tconst items = constraints.filter(({ rule }) => rule.target !== 'list');\n\t\tconst code = applyCode(\n\t\t\twrite,\n\t\t\t`z.array(${typedCode(write, type.ofType, items)})`,\n\t\t\town,\n\t\t);\n\t\tif (!write.options.list) return code;\n\t\tconst single = requiredCode(write, getNamedType(type), []);\n\t\treturn write.options.list({ type, code, single });\n\t}\n\tif (isInputObjectType(type)) {\n\t\tassertObjectTargets(type.name, constraints, write.where);\n\t\treturn write.named(type);\n\t}\n\tassertLeafTargets(type, constraints, write.where);\n\treturn applyCode(write, baseCode(type) ?? write.named(type), constraints);\n}\n\nfunction applyCode(\n\twrite: Write,\n\tsource: string,\n\tconstraints: readonly Constraint[],\n): string {\n\tconst context = {\n\t\tformats: write.formats,\n\t\tformatCode: write.options.format,\n\t};\n\treturn constraints.reduce(\n\t\t(code, { rule, value }) => applyRuleCode(rule, code, value, context),\n\t\tsource,\n\t);\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": "
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": ";;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiCO,SAAS,SAAS,CACxB,MACA,aACA,OACA,OACA,UAA4B,CAAC,GAC7B,SACS;AAAA,EACT,MAAM,QAAe;AAAA,IACpB;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS,WAAW,OAAO;AAAA,EAC5B;AAAA,EACA,OAAO,UAAU,OAAO,MAAM,WAAW;AAAA;AAiC1C,SAAS,SAAS,CACjB,OACA,MACA,aACS;AAAA,EACT,IAAI,cAAc,IAAI;AAAA,IAAG,OAAO,aAAa,OAAO,KAAK,QAAQ,WAAW;AAAA,EAC5E,OAAO,GAAG,aAAa,OAAO,MAAM,WAAW;AAAA;AAGhD,SAAS,YAAY,CACpB,OACA,MACA,aACS;AAAA,EACT,IAAI,cAAc,IAAI;AAAA,IAAG,OAAO,aAAa,OAAO,KAAK,QAAQ,WAAW;AAAA,EAC5E,IAAI,WAAW,IAAI,GAAG;AAAA,IAErB,MAAM,MAAM,YAAY,OAAO,GAAG,WAAW,KAAK,WAAW,MAAM;AAAA,IACnE,MAAM,QAAQ,YAAY,OAAO,GAAG,WAAW,KAAK,WAAW,MAAM;AAAA,IACrE,MAAM,OAAO,UACZ,OACA,WAAW,UAAU,OAAO,KAAK,QAAQ,KAAK,MAC9C,GACD;AAAA,IACA,IAAI,CAAC,MAAM,QAAQ;AAAA,MAAM,OAAO;AAAA,IAChC,MAAM,SAAS,aAAa,OAAO,aAAa,IAAI,GAAG,CAAC,CAAC;AAAA,IACzD,OAAO,MAAM,QAAQ,KAAK,EAAE,MAAM,MAAM,OAAO,CAAC;AAAA,EACjD;AAAA,EACA,IAAI,kBAAkB,IAAI,GAAG;AAAA,IAC5B,oBAAoB,KAAK,MAAM,aAAa,MAAM,KAAK;AAAA,IACvD,OAAO,MAAM,MAAM,IAAI;AAAA,EACxB;AAAA,EACA,kBAAkB,MAAM,aAAa,MAAM,KAAK;AAAA,EAChD,OAAO,UAAU,OAAO,SAAS,IAAI,KAAK,MAAM,MAAM,IAAI,GAAG,WAAW;AAAA;AAGzE,SAAS,SAAS,CACjB,OACA,QACA,aACS;AAAA,EACT,MAAM,UAAU;AAAA,IACf,SAAS,MAAM;AAAA,IACf,YAAY,MAAM,QAAQ;AAAA,EAC3B;AAAA,EACA,OAAO,YAAY,OAClB,CAAC,QAAQ,MAAM,YAAY,cAAc,MAAM,MAAM,OAAO,OAAO,GACnE,MACD;AAAA;",
|
|
8
|
+
"debugId": "95B0758BEEE7072864756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
package/dist/formats/byte.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const byteFormat: import("./format.js").
|
|
1
|
+
export declare const byteFormat: import("./format.js").BuiltInFormat<"byte">;
|
|
2
2
|
//# sourceMappingURL=byte.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"byte.d.ts","sourceRoot":"","sources":["../../src/formats/byte.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"byte.d.ts","sourceRoot":"","sources":["../../src/formats/byte.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,UAAU,0CAIrB,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const dateTimeFormat: import("./format.js").
|
|
1
|
+
export declare const dateTimeFormat: import("./format.js").BuiltInFormat<"date-time">;
|
|
2
2
|
//# sourceMappingURL=date-time.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"date-time.d.ts","sourceRoot":"","sources":["../../src/formats/date-time.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,cAAc,
|
|
1
|
+
{"version":3,"file":"date-time.d.ts","sourceRoot":"","sources":["../../src/formats/date-time.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,cAAc,+CAIzB,CAAC"}
|
package/dist/formats/date.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const dateFormat: import("./format.js").
|
|
1
|
+
export declare const dateFormat: import("./format.js").BuiltInFormat<"date">;
|
|
2
2
|
//# sourceMappingURL=date.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"date.d.ts","sourceRoot":"","sources":["../../src/formats/date.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"date.d.ts","sourceRoot":"","sources":["../../src/formats/date.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,UAAU,0CAIrB,CAAC"}
|
package/dist/formats/email.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const emailFormat: import("./format.js").
|
|
1
|
+
export declare const emailFormat: import("./format.js").BuiltInFormat<"email">;
|
|
2
2
|
//# sourceMappingURL=email.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"email.d.ts","sourceRoot":"","sources":["../../src/formats/email.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"email.d.ts","sourceRoot":"","sources":["../../src/formats/email.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,WAAW,2CAItB,CAAC"}
|
package/dist/formats/format.d.ts
CHANGED
|
@@ -1,15 +1,29 @@
|
|
|
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
|
/**
|
|
5
6
|
* One value of `@constraint(format: "...")`: the schema it stands for, as a
|
|
6
|
-
* schema at startup and as source for a code generator.
|
|
7
|
+
* schema at startup and, for a built-in one, as source for a code generator.
|
|
8
|
+
* A format of the application's own has no `toCode`: the generator writes a
|
|
9
|
+
* reference to the application's schema instead.
|
|
7
10
|
*/
|
|
8
11
|
export interface Format<N extends string = string> {
|
|
9
12
|
readonly name: N;
|
|
10
13
|
readonly toZod: () => StringSchema;
|
|
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;
|
|
22
|
+
}
|
|
23
|
+
/** A format this package ships: written twice, as a schema and as source. */
|
|
24
|
+
export interface BuiltInFormat<N extends string = string> extends Format<N> {
|
|
11
25
|
readonly toCode: () => string;
|
|
12
26
|
}
|
|
13
|
-
/** Declares a format, with its name kept literal. */
|
|
14
|
-
export declare function defineFormat<const N extends string>(format:
|
|
27
|
+
/** Declares a built-in format, with its name kept literal. */
|
|
28
|
+
export declare function defineFormat<const N extends string>(format: BuiltInFormat<N>): BuiltInFormat<N>;
|
|
15
29
|
//# sourceMappingURL=format.d.ts.map
|
|
@@ -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;
|
|
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"}
|
package/dist/formats/index.d.ts
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import * as all from './all.js';
|
|
2
|
-
import type {
|
|
2
|
+
import type { BuiltInFormat } from './format.js';
|
|
3
3
|
/**
|
|
4
|
-
* Every format, keyed by the value `@constraint(format: "...")`
|
|
5
|
-
* Derived from what `./all` exports, so a new format is one file and
|
|
6
|
-
* line there.
|
|
4
|
+
* Every built-in format, keyed by the value `@constraint(format: "...")`
|
|
5
|
+
* takes. Derived from what `./all` exports, so a new format is one file and
|
|
6
|
+
* one line there.
|
|
7
7
|
*/
|
|
8
|
-
export declare const formats: { readonly [N in FormatName]:
|
|
9
|
-
/** A value `@constraint(format: "...")` takes. */
|
|
8
|
+
export declare const formats: { readonly [N in FormatName]: BuiltInFormat<N>; };
|
|
9
|
+
/** A value `@constraint(format: "...")` takes without the application's formats. */
|
|
10
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
11
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +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,
|
|
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,aAAa,EAAE,MAAM,UAAU,CAAC;AAE9C;;;;GAIG;AACH,eAAO,MAAM,OAAO,EAEf,EAAE,QAAQ,EAAE,CAAC,IAAI,UAAU,GAAG,aAAa,CAAC,CAAC,CAAC,GAAE,CAAC;AAEtD,oFAAoF;AACpF,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,GAAG,CAAC,CAAC,MAAM,OAAO,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC"}
|
package/dist/formats/ipv4.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const ipv4Format: import("./format.js").
|
|
1
|
+
export declare const ipv4Format: import("./format.js").BuiltInFormat<"ipv4">;
|
|
2
2
|
//# sourceMappingURL=ipv4.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ipv4.d.ts","sourceRoot":"","sources":["../../src/formats/ipv4.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"ipv4.d.ts","sourceRoot":"","sources":["../../src/formats/ipv4.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,UAAU,0CAIrB,CAAC"}
|
package/dist/formats/ipv6.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const ipv6Format: import("./format.js").
|
|
1
|
+
export declare const ipv6Format: import("./format.js").BuiltInFormat<"ipv6">;
|
|
2
2
|
//# sourceMappingURL=ipv6.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ipv6.d.ts","sourceRoot":"","sources":["../../src/formats/ipv6.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"ipv6.d.ts","sourceRoot":"","sources":["../../src/formats/ipv6.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,UAAU,0CAIrB,CAAC"}
|
|
@@ -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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { Format, StringSchema } from './format.js';
|
|
2
|
+
import { type FormatName } from './index.js';
|
|
3
|
+
/**
|
|
4
|
+
* The application's own formats, keyed by the name `@constraint(format:
|
|
5
|
+
* "...")` gives them: each a Zod string schema, `z.string()` or a string
|
|
6
|
+
* format (`z.email()`), narrowed (`.regex()`, `.refine()`) but never
|
|
7
|
+
* transformed nor rewritten (`.trim()`, `.toLowerCase()`, `z.url()`,
|
|
8
|
+
* `z.coerce.string()`), so the resolver receives what was sent.
|
|
9
|
+
*/
|
|
10
|
+
export type FormatSchemas = {
|
|
11
|
+
readonly [name: string]: StringSchema;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* `F` with every key that names a built-in format typed `never`, so
|
|
15
|
+
* replacing one is a type error before it is a startup error. The keys are
|
|
16
|
+
* optional: a record typed wider than its literal (`FormatSchemas`,
|
|
17
|
+
* `Record<string, z.ZodString>`) may hold none of them, and passes.
|
|
18
|
+
*/
|
|
19
|
+
export type OwnFormats<F extends FormatSchemas> = F & {
|
|
20
|
+
readonly [K in keyof F & FormatName]?: never;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Every format `@constraint(format: "...")` can name: the built-in ones,
|
|
24
|
+
* then the application's own. A lookup is one `Map` read, however many
|
|
25
|
+
* formats there are.
|
|
26
|
+
*/
|
|
27
|
+
export declare class FormatRegistry {
|
|
28
|
+
#private;
|
|
29
|
+
/**
|
|
30
|
+
* Fails, naming the format, on a bad name, a built-in's name, a schema
|
|
31
|
+
* that is not a string's, one zod cannot run, or one that rewrites the
|
|
32
|
+
* value.
|
|
33
|
+
*/
|
|
34
|
+
constructor(own?: FormatSchemas);
|
|
35
|
+
/** The format named `name`, or an error that lists the known ones. */
|
|
36
|
+
named(name: string): Format;
|
|
37
|
+
/**
|
|
38
|
+
* The format of the application that last went async, then forgotten: read
|
|
39
|
+
* right after a synchronous parse threw zod's `$ZodAsyncError`, it names the
|
|
40
|
+
* format that made it throw (zod stops at the first check that returns a
|
|
41
|
+
* promise, and only an application's format can).
|
|
42
|
+
*/
|
|
43
|
+
takeAsync(): string | undefined;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* The registry of a set of formats, built (and checked) once per record: a
|
|
47
|
+
* code generator hands the same record for every field.
|
|
48
|
+
*/
|
|
49
|
+
export declare function registryOf(own?: FormatSchemas): FormatRegistry;
|
|
50
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
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/formats/uri.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const uriFormat: import("./format.js").
|
|
1
|
+
export declare const uriFormat: import("./format.js").BuiltInFormat<"uri">;
|
|
2
2
|
//# sourceMappingURL=uri.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uri.d.ts","sourceRoot":"","sources":["../../src/formats/uri.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,SAAS,
|
|
1
|
+
{"version":3,"file":"uri.d.ts","sourceRoot":"","sources":["../../src/formats/uri.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,SAAS,yCAIpB,CAAC"}
|
package/dist/formats/uuid.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const uuidFormat: import("./format.js").
|
|
1
|
+
export declare const uuidFormat: import("./format.js").BuiltInFormat<"uuid">;
|
|
2
2
|
//# sourceMappingURL=uuid.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uuid.d.ts","sourceRoot":"","sources":["../../src/formats/uuid.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"uuid.d.ts","sourceRoot":"","sources":["../../src/formats/uuid.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,UAAU,0CAIrB,CAAC"}
|