@gabrielbryk/json-schema-to-zod 2.7.2
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/.prettierrc.json +3 -0
- package/CONTRIBUTING.md +9 -0
- package/LICENSE +15 -0
- package/README.md +157 -0
- package/createIndex.ts +32 -0
- package/dist/cjs/Types.js +2 -0
- package/dist/cjs/cli.js +70 -0
- package/dist/cjs/index.js +44 -0
- package/dist/cjs/jsonSchemaToZod.js +78 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/parsers/parseAllOf.js +40 -0
- package/dist/cjs/parsers/parseAnyOf.js +18 -0
- package/dist/cjs/parsers/parseArray.js +71 -0
- package/dist/cjs/parsers/parseBoolean.js +7 -0
- package/dist/cjs/parsers/parseConst.js +7 -0
- package/dist/cjs/parsers/parseDefault.js +8 -0
- package/dist/cjs/parsers/parseEnum.js +21 -0
- package/dist/cjs/parsers/parseIfThenElse.js +34 -0
- package/dist/cjs/parsers/parseMultipleType.js +10 -0
- package/dist/cjs/parsers/parseNot.js +12 -0
- package/dist/cjs/parsers/parseNull.js +7 -0
- package/dist/cjs/parsers/parseNullable.js +12 -0
- package/dist/cjs/parsers/parseNumber.js +74 -0
- package/dist/cjs/parsers/parseObject.js +286 -0
- package/dist/cjs/parsers/parseOneOf.js +53 -0
- package/dist/cjs/parsers/parseSchema.js +285 -0
- package/dist/cjs/parsers/parseSimpleDiscriminatedOneOf.js +29 -0
- package/dist/cjs/parsers/parseString.js +77 -0
- package/dist/cjs/utils/anyOrUnknown.js +14 -0
- package/dist/cjs/utils/cliTools.js +108 -0
- package/dist/cjs/utils/half.js +7 -0
- package/dist/cjs/utils/jsdocs.js +20 -0
- package/dist/cjs/utils/omit.js +10 -0
- package/dist/cjs/utils/withMessage.js +22 -0
- package/dist/cjs/zodToJsonSchema.js +89 -0
- package/dist/esm/Types.js +1 -0
- package/dist/esm/cli.js +68 -0
- package/dist/esm/index.js +28 -0
- package/dist/esm/jsonSchemaToZod.js +74 -0
- package/dist/esm/package.json +1 -0
- package/dist/esm/parsers/parseAllOf.js +37 -0
- package/dist/esm/parsers/parseAnyOf.js +14 -0
- package/dist/esm/parsers/parseArray.js +67 -0
- package/dist/esm/parsers/parseBoolean.js +3 -0
- package/dist/esm/parsers/parseConst.js +3 -0
- package/dist/esm/parsers/parseDefault.js +4 -0
- package/dist/esm/parsers/parseEnum.js +17 -0
- package/dist/esm/parsers/parseIfThenElse.js +30 -0
- package/dist/esm/parsers/parseMultipleType.js +6 -0
- package/dist/esm/parsers/parseNot.js +8 -0
- package/dist/esm/parsers/parseNull.js +3 -0
- package/dist/esm/parsers/parseNullable.js +8 -0
- package/dist/esm/parsers/parseNumber.js +70 -0
- package/dist/esm/parsers/parseObject.js +283 -0
- package/dist/esm/parsers/parseOneOf.js +49 -0
- package/dist/esm/parsers/parseSchema.js +281 -0
- package/dist/esm/parsers/parseSimpleDiscriminatedOneOf.js +25 -0
- package/dist/esm/parsers/parseString.js +73 -0
- package/dist/esm/utils/anyOrUnknown.js +10 -0
- package/dist/esm/utils/cliTools.js +102 -0
- package/dist/esm/utils/half.js +3 -0
- package/dist/esm/utils/jsdocs.js +15 -0
- package/dist/esm/utils/omit.js +6 -0
- package/dist/esm/utils/withMessage.js +19 -0
- package/dist/esm/zodToJsonSchema.js +86 -0
- package/dist/types/Types.d.ts +125 -0
- package/dist/types/cli.d.ts +2 -0
- package/dist/types/index.d.ts +28 -0
- package/dist/types/jsonSchemaToZod.d.ts +2 -0
- package/dist/types/parsers/parseAllOf.d.ts +4 -0
- package/dist/types/parsers/parseAnyOf.d.ts +4 -0
- package/dist/types/parsers/parseArray.d.ts +4 -0
- package/dist/types/parsers/parseBoolean.d.ts +4 -0
- package/dist/types/parsers/parseConst.d.ts +4 -0
- package/dist/types/parsers/parseDefault.d.ts +2 -0
- package/dist/types/parsers/parseEnum.d.ts +4 -0
- package/dist/types/parsers/parseIfThenElse.d.ts +6 -0
- package/dist/types/parsers/parseMultipleType.d.ts +4 -0
- package/dist/types/parsers/parseNot.d.ts +4 -0
- package/dist/types/parsers/parseNull.d.ts +4 -0
- package/dist/types/parsers/parseNullable.d.ts +7 -0
- package/dist/types/parsers/parseNumber.d.ts +4 -0
- package/dist/types/parsers/parseObject.d.ts +4 -0
- package/dist/types/parsers/parseOneOf.d.ts +4 -0
- package/dist/types/parsers/parseSchema.d.ts +50 -0
- package/dist/types/parsers/parseSimpleDiscriminatedOneOf.d.ts +2 -0
- package/dist/types/parsers/parseString.d.ts +4 -0
- package/dist/types/utils/anyOrUnknown.d.ts +9 -0
- package/dist/types/utils/cliTools.d.ts +28 -0
- package/dist/types/utils/half.d.ts +1 -0
- package/dist/types/utils/jsdocs.d.ts +3 -0
- package/dist/types/utils/omit.d.ts +1 -0
- package/dist/types/utils/withMessage.d.ts +10 -0
- package/dist/types/zodToJsonSchema.d.ts +26 -0
- package/jest.config.js +4 -0
- package/package.json +83 -0
- package/postcjs.js +1 -0
- package/postesm.js +1 -0
- package/scripts/generateWorkflowSchema.ts +82 -0
package/.prettierrc.json
ADDED
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Hey, thanks for wanting to contribute.
|
|
4
|
+
|
|
5
|
+
Before you open a PR, make sure to open an issue and discuss the problem you want to solve. I will not consider PRs without issues.
|
|
6
|
+
|
|
7
|
+
I use [gitmoji](https://gitmoji.dev/) for my commit messages because I think it's fun. I encourage you to do the same, but won't enforce it.
|
|
8
|
+
|
|
9
|
+
I check PRs and issues very rarely so please be patient.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
ISC License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2021, Stefan Terdell
|
|
4
|
+
|
|
5
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
6
|
+
purpose with or without fee is hereby granted, provided that the above
|
|
7
|
+
copyright notice and this permission notice appear in all copies.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
10
|
+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
11
|
+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
12
|
+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
13
|
+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
14
|
+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
15
|
+
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# Json-Schema-to-Zod
|
|
2
|
+
|
|
3
|
+
[](https://npmjs.org/package/@gabrielbryk/json-schema-to-zod)
|
|
4
|
+
[](https://npmjs.org/package/@gabrielbryk/json-schema-to-zod)
|
|
5
|
+
|
|
6
|
+
# Notice of maintenance fork
|
|
7
|
+
|
|
8
|
+
The original package is being deprecated upstream, but this fork (<https://github.com/gabrielbryk/json-schema-to-zod>) continues maintenance and publishes to `@gabrielbryk/json-schema-to-zod` on npm.
|
|
9
|
+
|
|
10
|
+
## Summary
|
|
11
|
+
|
|
12
|
+
A runtime package and CLI tool to convert JSON schema (draft 4+) objects or files into Zod schemas in the form of JavaScript code.
|
|
13
|
+
|
|
14
|
+
Before v2 it used [`prettier`](https://www.npmjs.com/package/prettier) for formatting and [`json-refs`](https://www.npmjs.com/package/json-refs) to resolve schemas. To replicate the previous behaviour, please use their respective CLI tools.
|
|
15
|
+
|
|
16
|
+
Since v2 the CLI supports piped JSON.
|
|
17
|
+
|
|
18
|
+
_Looking for the exact opposite? Check out [zod-to-json-schema](https://npmjs.org/package/zod-to-json-schema)_
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
### Online
|
|
23
|
+
|
|
24
|
+
[Just paste your JSON schemas here!](https://stefanterdell.github.io/json-schema-to-zod-react/)
|
|
25
|
+
|
|
26
|
+
### CLI
|
|
27
|
+
|
|
28
|
+
#### Simplest example
|
|
29
|
+
|
|
30
|
+
```console
|
|
31
|
+
npm i -g @gabrielbryk/json-schema-to-zod
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
```console
|
|
35
|
+
json-schema-to-zod -i mySchema.json -o mySchema.ts
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
#### Example with `$refs` resolved and output formatted
|
|
39
|
+
|
|
40
|
+
```console
|
|
41
|
+
npm i -g @gabrielbryk/json-schema-to-zod json-refs prettier
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
```console
|
|
45
|
+
json-refs resolve mySchema.json | json-schema-to-zod | prettier --parser typescript > mySchema.ts
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
#### Options
|
|
49
|
+
|
|
50
|
+
| Flag | Shorthand | Function |
|
|
51
|
+
| -------------- | --------- | ---------------------------------------------------------------------------------------------- |
|
|
52
|
+
| `--input` | `-i` | JSON or a source file path. Required if no data is piped. |
|
|
53
|
+
| `--output` | `-o` | A file path to write to. If not supplied stdout will be used. |
|
|
54
|
+
| `--name` | `-n` | The name of the schema in the output |
|
|
55
|
+
| `--depth` | `-d` | Maximum depth of recursion in schema before falling back to `z.any()`. Defaults to 0. |
|
|
56
|
+
| `--module` | `-m` | Module syntax; `esm`, `cjs` or none. Defaults to `esm` in the CLI and `none` programmaticly. |
|
|
57
|
+
| `--type` | `-t` | Export a named type along with the schema. Requires `name` to be set and `module` to be `esm`. |
|
|
58
|
+
| `--noImport` | `-ni` | Removes the `import { z } from 'zod';` or equivalent from the output. |
|
|
59
|
+
| `--withJsdocs` | `-wj` | Generate jsdocs off of the description property. |
|
|
60
|
+
|
|
61
|
+
### Programmatic
|
|
62
|
+
|
|
63
|
+
#### Simple example
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
import { jsonSchemaToZod } from "@gabrielbryk/json-schema-to-zod";
|
|
67
|
+
|
|
68
|
+
const myObject = {
|
|
69
|
+
type: "object",
|
|
70
|
+
properties: {
|
|
71
|
+
hello: {
|
|
72
|
+
type: "string",
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const module = jsonSchemaToZod(myObject, { module: "esm" });
|
|
78
|
+
|
|
79
|
+
// `type` can be either a string or - outside of the CLI - a boolean. If its `true`, the name of the type will be the name of the schema with a capitalized first letter.
|
|
80
|
+
const moduleWithType = jsonSchemaToZod(myObject, {
|
|
81
|
+
name: "mySchema",
|
|
82
|
+
module: "esm",
|
|
83
|
+
type: true,
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
const cjs = jsonSchemaToZod(myObject, { module: "cjs", name: "mySchema" });
|
|
87
|
+
|
|
88
|
+
const justTheSchema = jsonSchemaToZod(myObject);
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
##### `module`
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
import { z } from "zod";
|
|
95
|
+
|
|
96
|
+
export default z.object({ hello: z.string().optional() });
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
##### `moduleWithType`
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
import { z } from "zod";
|
|
103
|
+
|
|
104
|
+
export const mySchema = z.object({ hello: z.string().optional() });
|
|
105
|
+
export type MySchema = z.infer<typeof mySchema>;
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
##### `cjs`
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
const { z } = require("zod");
|
|
112
|
+
|
|
113
|
+
module.exports = { mySchema: z.object({ hello: z.string().optional() }) };
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
##### `justTheSchema`
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
z.object({ hello: z.string().optional() });
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
#### Example with `$refs` resolved and output formatted
|
|
123
|
+
|
|
124
|
+
```typescript
|
|
125
|
+
import { z } from "zod";
|
|
126
|
+
import { resolveRefs } from "json-refs";
|
|
127
|
+
import { format } from "prettier";
|
|
128
|
+
import jsonSchemaToZod from "@gabrielbryk/json-schema-to-zod";
|
|
129
|
+
|
|
130
|
+
async function example(jsonSchema: Record<string, unknown>): Promise<string> {
|
|
131
|
+
const { resolved } = await resolveRefs(jsonSchema);
|
|
132
|
+
const code = jsonSchemaToZod(resolved);
|
|
133
|
+
const formatted = await format(code, { parser: "typescript" });
|
|
134
|
+
|
|
135
|
+
return formatted;
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
#### Overriding a parser
|
|
140
|
+
|
|
141
|
+
You can pass a function to the `parserOverride` option, which represents a function that receives the current schema node and the reference object, and should return a string when it wants to replace a default output. If the default output should be used for the node just return void.
|
|
142
|
+
|
|
143
|
+
#### Schema factoring
|
|
144
|
+
|
|
145
|
+
Factored schemas (like object schemas with "oneOf" etc.) is only partially supported. Here be dragons.
|
|
146
|
+
|
|
147
|
+
#### Use at Runtime
|
|
148
|
+
|
|
149
|
+
The output of this package is not meant to be used at runtime. JSON Schema and Zod does not overlap 100% and the scope of the parsers are purposefully limited in order to help the author avoid a permanent state of chaotic insanity. As this may cause some details of the original schema to be lost in translation, it is instead recommended to use tools such as [Ajv](https://ajv.js.org/) to validate your runtime values directly against the original JSON Schema.
|
|
150
|
+
|
|
151
|
+
That said, it's possible in most cases to use `eval`. Here's an example that you shouldn't use:
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
const zodSchema = eval(jsonSchemaToZod({ type: "string" }, { module: "cjs" }));
|
|
155
|
+
|
|
156
|
+
zodSchema.safeParse("Please just use Ajv instead");
|
|
157
|
+
```
|
package/createIndex.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { readdirSync, writeFileSync, statSync } from "fs";
|
|
2
|
+
|
|
3
|
+
const ignore = ["src/index.ts", "src/cli.ts", "src/utils/cliTools.ts"];
|
|
4
|
+
|
|
5
|
+
function checkSrcDir(path: string): string[] {
|
|
6
|
+
const lines: string[] = [];
|
|
7
|
+
|
|
8
|
+
for (const item of readdirSync(path)) {
|
|
9
|
+
const itemPath = path + "/" + item;
|
|
10
|
+
|
|
11
|
+
if (ignore.includes(itemPath)) {
|
|
12
|
+
continue;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (statSync(itemPath).isDirectory()) {
|
|
16
|
+
lines.push(...checkSrcDir(itemPath));
|
|
17
|
+
} else if (item.endsWith(".ts")) {
|
|
18
|
+
lines.push('export * from "./' + itemPath.slice(4, -2) + 'js"');
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return lines;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const lines = checkSrcDir("src");
|
|
26
|
+
|
|
27
|
+
lines.push(
|
|
28
|
+
'import { jsonSchemaToZod } from "./jsonSchemaToZod.js"',
|
|
29
|
+
"export default jsonSchemaToZod",
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
writeFileSync("./src/index.ts", lines.join("\n"));
|
package/dist/cjs/cli.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const jsonSchemaToZod_js_1 = require("./jsonSchemaToZod.js");
|
|
5
|
+
const fs_1 = require("fs");
|
|
6
|
+
const path_1 = require("path");
|
|
7
|
+
const cliTools_js_1 = require("./utils/cliTools.js");
|
|
8
|
+
const params = {
|
|
9
|
+
input: {
|
|
10
|
+
shorthand: "i",
|
|
11
|
+
value: "string",
|
|
12
|
+
required: process.stdin.isTTY &&
|
|
13
|
+
"input is required when no JSON or file path is piped",
|
|
14
|
+
description: "JSON or a source file path. Required if no data is piped.",
|
|
15
|
+
},
|
|
16
|
+
output: {
|
|
17
|
+
shorthand: "o",
|
|
18
|
+
value: "string",
|
|
19
|
+
description: "A file path to write to. If not supplied stdout will be used.",
|
|
20
|
+
},
|
|
21
|
+
name: {
|
|
22
|
+
shorthand: "n",
|
|
23
|
+
value: "string",
|
|
24
|
+
description: "The name of the schema in the output.",
|
|
25
|
+
},
|
|
26
|
+
depth: {
|
|
27
|
+
shorthand: "d",
|
|
28
|
+
value: "number",
|
|
29
|
+
description: "Maximum depth of recursion before falling back to z.any(). Defaults to 0.",
|
|
30
|
+
},
|
|
31
|
+
module: {
|
|
32
|
+
shorthand: "m",
|
|
33
|
+
value: ["esm", "cjs", "none"],
|
|
34
|
+
description: "Module syntax; 'esm', 'cjs' or 'none'. Defaults to 'esm'.",
|
|
35
|
+
},
|
|
36
|
+
type: {
|
|
37
|
+
shorthand: "t",
|
|
38
|
+
value: "string",
|
|
39
|
+
description: "The name of the (optional) inferred type export."
|
|
40
|
+
},
|
|
41
|
+
noImport: {
|
|
42
|
+
shorthand: "ni",
|
|
43
|
+
description: "Removes the `import { z } from 'zod';` or equivalent from the output."
|
|
44
|
+
},
|
|
45
|
+
withJsdocs: {
|
|
46
|
+
shorthand: "wj",
|
|
47
|
+
description: "Generate jsdocs off of the description property.",
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
async function main() {
|
|
51
|
+
const args = (0, cliTools_js_1.parseArgs)(params, process.argv, true);
|
|
52
|
+
const input = args.input || (await (0, cliTools_js_1.readPipe)());
|
|
53
|
+
const jsonSchema = (0, cliTools_js_1.parseOrReadJSON)(input);
|
|
54
|
+
const zodSchema = (0, jsonSchemaToZod_js_1.jsonSchemaToZod)(jsonSchema, {
|
|
55
|
+
name: args.name,
|
|
56
|
+
depth: args.depth,
|
|
57
|
+
module: args.module || "esm",
|
|
58
|
+
noImport: args.noImport,
|
|
59
|
+
type: args.type,
|
|
60
|
+
withJsdocs: args.withJsdocs,
|
|
61
|
+
});
|
|
62
|
+
if (args.output) {
|
|
63
|
+
(0, fs_1.mkdirSync)((0, path_1.dirname)(args.output), { recursive: true });
|
|
64
|
+
(0, fs_1.writeFileSync)(args.output, zodSchema);
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
console.log(zodSchema);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
void main();
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./Types.js"), exports);
|
|
18
|
+
__exportStar(require("./jsonSchemaToZod.js"), exports);
|
|
19
|
+
__exportStar(require("./parsers/parseAllOf.js"), exports);
|
|
20
|
+
__exportStar(require("./parsers/parseAnyOf.js"), exports);
|
|
21
|
+
__exportStar(require("./parsers/parseArray.js"), exports);
|
|
22
|
+
__exportStar(require("./parsers/parseBoolean.js"), exports);
|
|
23
|
+
__exportStar(require("./parsers/parseConst.js"), exports);
|
|
24
|
+
__exportStar(require("./parsers/parseDefault.js"), exports);
|
|
25
|
+
__exportStar(require("./parsers/parseEnum.js"), exports);
|
|
26
|
+
__exportStar(require("./parsers/parseIfThenElse.js"), exports);
|
|
27
|
+
__exportStar(require("./parsers/parseMultipleType.js"), exports);
|
|
28
|
+
__exportStar(require("./parsers/parseNot.js"), exports);
|
|
29
|
+
__exportStar(require("./parsers/parseNull.js"), exports);
|
|
30
|
+
__exportStar(require("./parsers/parseNullable.js"), exports);
|
|
31
|
+
__exportStar(require("./parsers/parseNumber.js"), exports);
|
|
32
|
+
__exportStar(require("./parsers/parseObject.js"), exports);
|
|
33
|
+
__exportStar(require("./parsers/parseOneOf.js"), exports);
|
|
34
|
+
__exportStar(require("./parsers/parseSchema.js"), exports);
|
|
35
|
+
__exportStar(require("./parsers/parseSimpleDiscriminatedOneOf.js"), exports);
|
|
36
|
+
__exportStar(require("./parsers/parseString.js"), exports);
|
|
37
|
+
__exportStar(require("./utils/anyOrUnknown.js"), exports);
|
|
38
|
+
__exportStar(require("./utils/half.js"), exports);
|
|
39
|
+
__exportStar(require("./utils/jsdocs.js"), exports);
|
|
40
|
+
__exportStar(require("./utils/omit.js"), exports);
|
|
41
|
+
__exportStar(require("./utils/withMessage.js"), exports);
|
|
42
|
+
__exportStar(require("./zodToJsonSchema.js"), exports);
|
|
43
|
+
const jsonSchemaToZod_js_1 = require("./jsonSchemaToZod.js");
|
|
44
|
+
exports.default = jsonSchemaToZod_js_1.jsonSchemaToZod;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.jsonSchemaToZod = void 0;
|
|
4
|
+
const parseSchema_js_1 = require("./parsers/parseSchema.js");
|
|
5
|
+
const jsdocs_js_1 = require("./utils/jsdocs.js");
|
|
6
|
+
const jsonSchemaToZod = (schema, { module, name, type, noImport, ...rest } = {}) => {
|
|
7
|
+
if (type && (!name || module !== "esm")) {
|
|
8
|
+
throw new Error("Option `type` requires `name` to be set and `module` to be `esm`");
|
|
9
|
+
}
|
|
10
|
+
const declarations = new Map();
|
|
11
|
+
const refNameByPointer = new Map();
|
|
12
|
+
const usedNames = new Set();
|
|
13
|
+
const exportRefs = rest.exportRefs ?? true;
|
|
14
|
+
const withMeta = rest.withMeta ?? true;
|
|
15
|
+
if (name)
|
|
16
|
+
usedNames.add(name);
|
|
17
|
+
const parsedSchema = (0, parseSchema_js_1.parseSchema)(schema, {
|
|
18
|
+
module,
|
|
19
|
+
name,
|
|
20
|
+
path: [],
|
|
21
|
+
seen: new Map(),
|
|
22
|
+
declarations,
|
|
23
|
+
inProgress: new Set(),
|
|
24
|
+
refNameByPointer,
|
|
25
|
+
usedNames,
|
|
26
|
+
root: schema,
|
|
27
|
+
currentSchemaName: name,
|
|
28
|
+
...rest,
|
|
29
|
+
withMeta,
|
|
30
|
+
});
|
|
31
|
+
const declarationBlock = declarations.size
|
|
32
|
+
? Array.from(declarations.entries())
|
|
33
|
+
.map(([refName, value]) => {
|
|
34
|
+
const shouldExport = exportRefs && module === "esm";
|
|
35
|
+
const decl = `${shouldExport ? "export " : ""}const ${refName} = ${value}`;
|
|
36
|
+
return decl;
|
|
37
|
+
})
|
|
38
|
+
.join("\n")
|
|
39
|
+
: "";
|
|
40
|
+
const jsdocs = rest.withJsdocs && typeof schema !== "boolean" && schema.description
|
|
41
|
+
? (0, jsdocs_js_1.expandJsdocs)(schema.description)
|
|
42
|
+
: "";
|
|
43
|
+
const lines = [];
|
|
44
|
+
if (module === "cjs" && !noImport) {
|
|
45
|
+
lines.push(`const { z } = require("zod")`);
|
|
46
|
+
}
|
|
47
|
+
if (module === "esm" && !noImport) {
|
|
48
|
+
lines.push(`import { z } from "zod"`);
|
|
49
|
+
}
|
|
50
|
+
if (declarationBlock) {
|
|
51
|
+
lines.push(declarationBlock);
|
|
52
|
+
}
|
|
53
|
+
if (module === "cjs") {
|
|
54
|
+
const payload = name ? `{ ${JSON.stringify(name)}: ${parsedSchema} }` : parsedSchema;
|
|
55
|
+
lines.push(`${jsdocs}module.exports = ${payload}`);
|
|
56
|
+
}
|
|
57
|
+
else if (module === "esm") {
|
|
58
|
+
lines.push(`${jsdocs}export ${name ? `const ${name} =` : `default`} ${parsedSchema}`);
|
|
59
|
+
}
|
|
60
|
+
else if (name) {
|
|
61
|
+
lines.push(`${jsdocs}const ${name} = ${parsedSchema}`);
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
lines.push(`${jsdocs}${parsedSchema}`);
|
|
65
|
+
}
|
|
66
|
+
let typeLine;
|
|
67
|
+
if (type && name) {
|
|
68
|
+
let typeName = typeof type === "string"
|
|
69
|
+
? type
|
|
70
|
+
: `${name[0].toUpperCase()}${name.substring(1)}`;
|
|
71
|
+
typeLine = `export type ${typeName} = z.infer<typeof ${name}>`;
|
|
72
|
+
}
|
|
73
|
+
const joined = lines.filter(Boolean).join("\n\n");
|
|
74
|
+
const combined = typeLine ? `${joined}\n${typeLine}` : joined;
|
|
75
|
+
const shouldEndWithNewline = module === "esm" || module === "cjs";
|
|
76
|
+
return `${combined}${shouldEndWithNewline ? "\n" : ""}`;
|
|
77
|
+
};
|
|
78
|
+
exports.jsonSchemaToZod = jsonSchemaToZod;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"commonjs"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseAllOf = parseAllOf;
|
|
4
|
+
const parseSchema_js_1 = require("./parseSchema.js");
|
|
5
|
+
const half_js_1 = require("../utils/half.js");
|
|
6
|
+
const originalIndex = Symbol("Original index");
|
|
7
|
+
const ensureOriginalIndex = (arr) => {
|
|
8
|
+
let newArr = [];
|
|
9
|
+
for (let i = 0; i < arr.length; i++) {
|
|
10
|
+
const item = arr[i];
|
|
11
|
+
if (typeof item === "boolean") {
|
|
12
|
+
newArr.push(item ? { [originalIndex]: i } : { [originalIndex]: i, not: {} });
|
|
13
|
+
}
|
|
14
|
+
else if (originalIndex in item) {
|
|
15
|
+
return arr;
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
newArr.push({ ...item, [originalIndex]: i });
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return newArr;
|
|
22
|
+
};
|
|
23
|
+
function parseAllOf(schema, refs) {
|
|
24
|
+
if (schema.allOf.length === 0) {
|
|
25
|
+
return "z.never()";
|
|
26
|
+
}
|
|
27
|
+
else if (schema.allOf.length === 1) {
|
|
28
|
+
const item = schema.allOf[0];
|
|
29
|
+
return (0, parseSchema_js_1.parseSchema)(item, {
|
|
30
|
+
...refs,
|
|
31
|
+
path: [...refs.path, "allOf", item[originalIndex]],
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
const [left, right] = (0, half_js_1.half)(ensureOriginalIndex(schema.allOf));
|
|
36
|
+
return `z.intersection(${parseAllOf({ allOf: left }, refs)}, ${parseAllOf({
|
|
37
|
+
allOf: right,
|
|
38
|
+
}, refs)})`;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseAnyOf = void 0;
|
|
4
|
+
const parseSchema_js_1 = require("./parseSchema.js");
|
|
5
|
+
const anyOrUnknown_js_1 = require("../utils/anyOrUnknown.js");
|
|
6
|
+
const parseAnyOf = (schema, refs) => {
|
|
7
|
+
return schema.anyOf.length
|
|
8
|
+
? schema.anyOf.length === 1
|
|
9
|
+
? (0, parseSchema_js_1.parseSchema)(schema.anyOf[0], {
|
|
10
|
+
...refs,
|
|
11
|
+
path: [...refs.path, "anyOf", 0],
|
|
12
|
+
})
|
|
13
|
+
: `z.union([${schema.anyOf
|
|
14
|
+
.map((schema, i) => (0, parseSchema_js_1.parseSchema)(schema, { ...refs, path: [...refs.path, "anyOf", i] }))
|
|
15
|
+
.join(", ")}])`
|
|
16
|
+
: (0, anyOrUnknown_js_1.anyOrUnknown)(refs);
|
|
17
|
+
};
|
|
18
|
+
exports.parseAnyOf = parseAnyOf;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseArray = void 0;
|
|
4
|
+
const withMessage_js_1 = require("../utils/withMessage.js");
|
|
5
|
+
const parseSchema_js_1 = require("./parseSchema.js");
|
|
6
|
+
const anyOrUnknown_js_1 = require("../utils/anyOrUnknown.js");
|
|
7
|
+
const parseArray = (schema, refs) => {
|
|
8
|
+
if (Array.isArray(schema.items)) {
|
|
9
|
+
let tuple = `z.tuple([${schema.items.map((v, i) => (0, parseSchema_js_1.parseSchema)(v, { ...refs, path: [...refs.path, "items", i] }))}])`;
|
|
10
|
+
if (schema.contains) {
|
|
11
|
+
const containsSchema = (0, parseSchema_js_1.parseSchema)(schema.contains, {
|
|
12
|
+
...refs,
|
|
13
|
+
path: [...refs.path, "contains"],
|
|
14
|
+
});
|
|
15
|
+
const minContains = schema.minContains ?? (schema.contains ? 1 : undefined);
|
|
16
|
+
const maxContains = schema.maxContains;
|
|
17
|
+
tuple += `.superRefine((arr, ctx) => {
|
|
18
|
+
const matches = arr.filter((item) => ${containsSchema}.safeParse(item).success).length;
|
|
19
|
+
if (${minContains ?? 0} && matches < ${minContains ?? 0}) {
|
|
20
|
+
ctx.addIssue({ code: "custom", message: "Array contains too few matching items" });
|
|
21
|
+
}
|
|
22
|
+
if (${maxContains ?? "undefined"} !== undefined && matches > ${maxContains ?? "undefined"}) {
|
|
23
|
+
ctx.addIssue({ code: "custom", message: "Array contains too many matching items" });
|
|
24
|
+
}
|
|
25
|
+
})`;
|
|
26
|
+
}
|
|
27
|
+
return tuple;
|
|
28
|
+
}
|
|
29
|
+
let r = !schema.items
|
|
30
|
+
? `z.array(${(0, anyOrUnknown_js_1.anyOrUnknown)(refs)})`
|
|
31
|
+
: `z.array(${(0, parseSchema_js_1.parseSchema)(schema.items, {
|
|
32
|
+
...refs,
|
|
33
|
+
path: [...refs.path, "items"],
|
|
34
|
+
})})`;
|
|
35
|
+
r += (0, withMessage_js_1.withMessage)(schema, "minItems", ({ json }) => [
|
|
36
|
+
`.min(${json}`,
|
|
37
|
+
", ",
|
|
38
|
+
")",
|
|
39
|
+
]);
|
|
40
|
+
r += (0, withMessage_js_1.withMessage)(schema, "maxItems", ({ json }) => [
|
|
41
|
+
`.max(${json}`,
|
|
42
|
+
", ",
|
|
43
|
+
")",
|
|
44
|
+
]);
|
|
45
|
+
if (schema.uniqueItems === true) {
|
|
46
|
+
r += (0, withMessage_js_1.withMessage)(schema, "uniqueItems", () => [
|
|
47
|
+
".unique(",
|
|
48
|
+
"",
|
|
49
|
+
")",
|
|
50
|
+
]);
|
|
51
|
+
}
|
|
52
|
+
if (schema.contains) {
|
|
53
|
+
const containsSchema = (0, parseSchema_js_1.parseSchema)(schema.contains, {
|
|
54
|
+
...refs,
|
|
55
|
+
path: [...refs.path, "contains"],
|
|
56
|
+
});
|
|
57
|
+
const minContains = schema.minContains ?? (schema.contains ? 1 : undefined);
|
|
58
|
+
const maxContains = schema.maxContains;
|
|
59
|
+
r += `.superRefine((arr, ctx) => {
|
|
60
|
+
const matches = arr.filter((item) => ${containsSchema}.safeParse(item).success).length;
|
|
61
|
+
if (${minContains ?? 0} && matches < ${minContains ?? 0}) {
|
|
62
|
+
ctx.addIssue({ code: "custom", message: "Array contains too few matching items" });
|
|
63
|
+
}
|
|
64
|
+
if (${maxContains ?? "undefined"} !== undefined && matches > ${maxContains ?? "undefined"}) {
|
|
65
|
+
ctx.addIssue({ code: "custom", message: "Array contains too many matching items" });
|
|
66
|
+
}
|
|
67
|
+
})`;
|
|
68
|
+
}
|
|
69
|
+
return r;
|
|
70
|
+
};
|
|
71
|
+
exports.parseArray = parseArray;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseDefault = void 0;
|
|
4
|
+
const anyOrUnknown_js_1 = require("../utils/anyOrUnknown.js");
|
|
5
|
+
const parseDefault = (_schema, refs) => {
|
|
6
|
+
return (0, anyOrUnknown_js_1.anyOrUnknown)(refs);
|
|
7
|
+
};
|
|
8
|
+
exports.parseDefault = parseDefault;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseEnum = void 0;
|
|
4
|
+
const parseEnum = (schema) => {
|
|
5
|
+
if (schema.enum.length === 0) {
|
|
6
|
+
return "z.never()";
|
|
7
|
+
}
|
|
8
|
+
else if (schema.enum.length === 1) {
|
|
9
|
+
// union does not work when there is only one element
|
|
10
|
+
return `z.literal(${JSON.stringify(schema.enum[0])})`;
|
|
11
|
+
}
|
|
12
|
+
else if (schema.enum.every((x) => typeof x === "string")) {
|
|
13
|
+
return `z.enum([${schema.enum.map((x) => JSON.stringify(x))}])`;
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
return `z.union([${schema.enum
|
|
17
|
+
.map((x) => `z.literal(${JSON.stringify(x)})`)
|
|
18
|
+
.join(", ")}])`;
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
exports.parseEnum = parseEnum;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseIfThenElse = void 0;
|
|
4
|
+
const parseSchema_js_1 = require("./parseSchema.js");
|
|
5
|
+
const parseIfThenElse = (schema, refs) => {
|
|
6
|
+
const $if = (0, parseSchema_js_1.parseSchema)(schema.if, { ...refs, path: [...refs.path, "if"] });
|
|
7
|
+
const $then = (0, parseSchema_js_1.parseSchema)(schema.then, {
|
|
8
|
+
...refs,
|
|
9
|
+
path: [...refs.path, "then"],
|
|
10
|
+
});
|
|
11
|
+
const $else = (0, parseSchema_js_1.parseSchema)(schema.else, {
|
|
12
|
+
...refs,
|
|
13
|
+
path: [...refs.path, "else"],
|
|
14
|
+
});
|
|
15
|
+
let result = `z.union([${$then}, ${$else}]).superRefine((value,ctx) => {
|
|
16
|
+
const result = ${$if}.safeParse(value).success
|
|
17
|
+
? ${$then}.safeParse(value)
|
|
18
|
+
: ${$else}.safeParse(value);
|
|
19
|
+
if (!result.success) {
|
|
20
|
+
result.error.issues.forEach((issue) => ctx.addIssue({...issue}))
|
|
21
|
+
}
|
|
22
|
+
})`;
|
|
23
|
+
// Store original if/then/else for JSON Schema round-trip
|
|
24
|
+
if (refs.preserveJsonSchemaForRoundTrip) {
|
|
25
|
+
const conditionalMeta = JSON.stringify({
|
|
26
|
+
if: schema.if,
|
|
27
|
+
then: schema.then,
|
|
28
|
+
else: schema.else,
|
|
29
|
+
});
|
|
30
|
+
result += `.meta({ __jsonSchema: { conditional: ${conditionalMeta} } })`;
|
|
31
|
+
}
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
exports.parseIfThenElse = parseIfThenElse;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseMultipleType = void 0;
|
|
4
|
+
const parseSchema_js_1 = require("./parseSchema.js");
|
|
5
|
+
const parseMultipleType = (schema, refs) => {
|
|
6
|
+
return `z.union([${schema.type
|
|
7
|
+
.map((type) => (0, parseSchema_js_1.parseSchema)({ ...schema, type }, { ...refs, withoutDefaults: true }))
|
|
8
|
+
.join(", ")}])`;
|
|
9
|
+
};
|
|
10
|
+
exports.parseMultipleType = parseMultipleType;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseNot = void 0;
|
|
4
|
+
const parseSchema_js_1 = require("./parseSchema.js");
|
|
5
|
+
const anyOrUnknown_js_1 = require("../utils/anyOrUnknown.js");
|
|
6
|
+
const parseNot = (schema, refs) => {
|
|
7
|
+
return `${(0, anyOrUnknown_js_1.anyOrUnknown)(refs)}.refine((value) => !${(0, parseSchema_js_1.parseSchema)(schema.not, {
|
|
8
|
+
...refs,
|
|
9
|
+
path: [...refs.path, "not"],
|
|
10
|
+
})}.safeParse(value).success, "Invalid input: Should NOT be valid against schema")`;
|
|
11
|
+
};
|
|
12
|
+
exports.parseNot = parseNot;
|