@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
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export type Param = {
|
|
2
|
+
shorthand?: string;
|
|
3
|
+
description?: string;
|
|
4
|
+
required?: boolean | string | undefined;
|
|
5
|
+
} & ({
|
|
6
|
+
value?: "boolean";
|
|
7
|
+
} | {
|
|
8
|
+
value: "number";
|
|
9
|
+
} | {
|
|
10
|
+
value: "string";
|
|
11
|
+
} | {
|
|
12
|
+
value: {
|
|
13
|
+
[key: number]: string;
|
|
14
|
+
};
|
|
15
|
+
});
|
|
16
|
+
export type Params = {
|
|
17
|
+
[name: string]: Param;
|
|
18
|
+
};
|
|
19
|
+
type InferReturnType<T extends Params> = {
|
|
20
|
+
[name in keyof T]: (T[name]["value"] extends "number" ? number : T[name]["value"] extends "string" ? string : T[name]["value"] extends {
|
|
21
|
+
[key: number]: string;
|
|
22
|
+
} ? T[name]["value"][number] : T[name]["value"] extends never ? boolean : boolean) | (T[name]["required"] extends string | true ? never : undefined);
|
|
23
|
+
};
|
|
24
|
+
export declare function parseArgs<T extends Params>(params: T, args: string[], help?: boolean | string): InferReturnType<T>;
|
|
25
|
+
export declare function parseOrReadJSON(jsonOrPath: string): unknown;
|
|
26
|
+
export declare function readPipe(): Promise<string>;
|
|
27
|
+
export declare function printParams(params: Record<string, Param>): void;
|
|
28
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const half: <T>(arr: T[]) => [T[], T[]];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const omit: <T extends object, K extends keyof T>(obj: T, ...keys: K[]) => Omit<T, K>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { JsonSchemaObject } from "../Types.js";
|
|
2
|
+
type Opener = string;
|
|
3
|
+
type MessagePrefix = string;
|
|
4
|
+
type Closer = string;
|
|
5
|
+
type Builder = [Opener, Closer] | [Opener, MessagePrefix, Closer];
|
|
6
|
+
export declare function withMessage(schema: JsonSchemaObject, key: string, get: (props: {
|
|
7
|
+
value: unknown;
|
|
8
|
+
json: string;
|
|
9
|
+
}) => Builder | void): string;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Post-processor for Zod's z.toJSONSchema() output.
|
|
3
|
+
*
|
|
4
|
+
* When `preserveJsonSchemaForRoundTrip` was used during JSON Schema → Zod conversion,
|
|
5
|
+
* this function reconstructs the original JSON Schema features from the stored __jsonSchema meta.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* 1. Convert JSON Schema to Zod code with `preserveJsonSchemaForRoundTrip: true`
|
|
9
|
+
* 2. Evaluate the Zod code to get a schema instance
|
|
10
|
+
* 3. Call Zod's `z.toJSONSchema(schema)` to get JSON Schema output
|
|
11
|
+
* 4. Pass that output to `reconstructJsonSchema()` to restore preserved features
|
|
12
|
+
*
|
|
13
|
+
* Handles:
|
|
14
|
+
* - patternProperties (stored in __jsonSchema.patternProperties)
|
|
15
|
+
* - if/then/else conditionals (stored in __jsonSchema.conditional)
|
|
16
|
+
*/
|
|
17
|
+
type JsonSchemaObject = Record<string, unknown>;
|
|
18
|
+
/**
|
|
19
|
+
* Recursively process a JSON Schema to reconstruct original features from __jsonSchema meta.
|
|
20
|
+
*
|
|
21
|
+
* Handles special cases:
|
|
22
|
+
* - allOf[object, {__jsonSchema: {conditional: ...}}] -> object with if/then/else at top level
|
|
23
|
+
* - patternProperties meta -> patternProperties at current level
|
|
24
|
+
*/
|
|
25
|
+
export declare function reconstructJsonSchema(schema: JsonSchemaObject): JsonSchemaObject;
|
|
26
|
+
export {};
|
package/jest.config.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@gabrielbryk/json-schema-to-zod",
|
|
3
|
+
"version": "2.7.2",
|
|
4
|
+
"description": "Converts JSON schema objects or files into Zod schemas",
|
|
5
|
+
"types": "./dist/types/index.d.ts",
|
|
6
|
+
"bin": "./dist/cjs/cli.js",
|
|
7
|
+
"main": "./dist/cjs/index.js",
|
|
8
|
+
"module": "./dist/esm/index.js",
|
|
9
|
+
"exports": {
|
|
10
|
+
"import": {
|
|
11
|
+
"types": "./dist/types/index.d.ts",
|
|
12
|
+
"default": "./dist/esm/index.js"
|
|
13
|
+
},
|
|
14
|
+
"require": {
|
|
15
|
+
"types": "./dist/types/index.d.ts",
|
|
16
|
+
"default": "./dist/cjs/index.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"c8": {
|
|
20
|
+
"exclude": [
|
|
21
|
+
"dist",
|
|
22
|
+
"createIndex.ts",
|
|
23
|
+
"jest.config.js",
|
|
24
|
+
"postcjs.js",
|
|
25
|
+
"postesm.js",
|
|
26
|
+
"test"
|
|
27
|
+
]
|
|
28
|
+
},
|
|
29
|
+
"keywords": [
|
|
30
|
+
"zod",
|
|
31
|
+
"json",
|
|
32
|
+
"schema",
|
|
33
|
+
"converter",
|
|
34
|
+
"cli"
|
|
35
|
+
],
|
|
36
|
+
"author": "Stefan Terdell",
|
|
37
|
+
"contributors": [
|
|
38
|
+
"Chen (https://github.com/werifu)",
|
|
39
|
+
"Nuno Carduso (https://github.com/ncardoso-barracuda)",
|
|
40
|
+
"Lars Strojny (https://github.com/lstrojny)",
|
|
41
|
+
"Navtoj Chahal (https://github.com/navtoj)",
|
|
42
|
+
"Ben McCann (https://github.com/benmccann)",
|
|
43
|
+
"Dmitry Zakharov (https://github.com/DZakh)",
|
|
44
|
+
"Michel Turpin (https://github.com/grimly)",
|
|
45
|
+
"David Barratt (https://github.com/davidbarratt)",
|
|
46
|
+
"pevisscher (https://github.com/pevisscher)",
|
|
47
|
+
"Aidin Abedi (https://github.com/aidinabedi)",
|
|
48
|
+
"Brett Zamir (https://github.com/brettz9)",
|
|
49
|
+
"vForgeOne (https://github.com/vforgeone)",
|
|
50
|
+
"Adrian Ordonez (https://github.com/adrianord)",
|
|
51
|
+
"Jonas Reucher (https://github.com/Mantls)",
|
|
52
|
+
"Nicolas Forstner (https://github.com/nlsfnr)",
|
|
53
|
+
"Jordyn https://github.com/ColourfulMelon"
|
|
54
|
+
],
|
|
55
|
+
"license": "ISC",
|
|
56
|
+
"repository": {
|
|
57
|
+
"type": "git",
|
|
58
|
+
"url": "https://github.com/gabrielbryk/json-schema-to-zod"
|
|
59
|
+
},
|
|
60
|
+
"publishConfig": {
|
|
61
|
+
"access": "public"
|
|
62
|
+
},
|
|
63
|
+
"devDependencies": {
|
|
64
|
+
"@types/json-schema": "^7.0.15",
|
|
65
|
+
"@types/node": "^20.9.0",
|
|
66
|
+
"fast-diff": "^1.3.0",
|
|
67
|
+
"js-yaml": "^4.1.0",
|
|
68
|
+
"rimraf": "^5.0.5",
|
|
69
|
+
"tsx": "^4.1.1",
|
|
70
|
+
"typescript": "^5.2.2",
|
|
71
|
+
"zod": "^4.1.13"
|
|
72
|
+
},
|
|
73
|
+
"scripts": {
|
|
74
|
+
"build:types": "tsc -p tsconfig.types.json",
|
|
75
|
+
"build:cjs": "tsc -p tsconfig.cjs.json && node postcjs.js",
|
|
76
|
+
"build:esm": "tsc -p tsconfig.esm.json && node postesm.js",
|
|
77
|
+
"build": "pnpm gen && pnpm test && rimraf ./dist && pnpm build:types && pnpm build:cjs && pnpm build:esm",
|
|
78
|
+
"dry": "pnpm build && pnpm publish --dry-run",
|
|
79
|
+
"dev": "tsx watch test/index.ts",
|
|
80
|
+
"gen": "tsx ./createIndex.ts",
|
|
81
|
+
"test": "tsx test/index.ts"
|
|
82
|
+
}
|
|
83
|
+
}
|
package/postcjs.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require("fs").writeFileSync("./dist/cjs/package.json", '{"type":"commonjs"}', "utf-8")
|
package/postesm.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require("fs").writeFileSync("./dist/esm/package.json", '{"type":"module"}', "utf-8")
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { readFileSync, mkdirSync, writeFileSync } from "fs";
|
|
2
|
+
import { dirname, join } from "path";
|
|
3
|
+
import yaml from "js-yaml";
|
|
4
|
+
import jsonSchemaToZod from "../src/index.js";
|
|
5
|
+
|
|
6
|
+
const WORKFLOW_SOURCE = "test/fixtures/workflow.yaml";
|
|
7
|
+
const OUTPUT_DIR = "test/output/workflow";
|
|
8
|
+
const SCHEMA_DIR = join(OUTPUT_DIR, "schemas");
|
|
9
|
+
const OUTPUT_INDEX = join(OUTPUT_DIR, "index.ts");
|
|
10
|
+
|
|
11
|
+
function main() {
|
|
12
|
+
const schema = yaml.load(readFileSync(WORKFLOW_SOURCE, "utf8")) as any;
|
|
13
|
+
|
|
14
|
+
const generated = jsonSchemaToZod(schema, {
|
|
15
|
+
module: "esm",
|
|
16
|
+
name: "workflowSchema",
|
|
17
|
+
exportRefs: true,
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const lines = generated
|
|
21
|
+
.split("\n")
|
|
22
|
+
.map((line) => line.trimEnd())
|
|
23
|
+
.filter((line, idx, arr) => !(line === "" && arr[idx - 1] === ""));
|
|
24
|
+
|
|
25
|
+
const importLines = lines.filter((line) => line.startsWith("import "));
|
|
26
|
+
|
|
27
|
+
// Extract blocks: export const Name = ... (until next export const or end)
|
|
28
|
+
const blocks: { name: string; lines: string[]; exported: boolean }[] = [];
|
|
29
|
+
let current: { name: string; lines: string[]; exported: boolean } | null = null;
|
|
30
|
+
|
|
31
|
+
for (const line of lines) {
|
|
32
|
+
const match = line.match(/^(export\s+)?const ([A-Za-z_$][A-Za-z0-9_$]*)\s*=\s*(.*)/);
|
|
33
|
+
if (match) {
|
|
34
|
+
if (current) blocks.push(current);
|
|
35
|
+
const [, expKeyword, name] = match;
|
|
36
|
+
current = { name, exported: Boolean(expKeyword), lines: [line] };
|
|
37
|
+
} else if (current) {
|
|
38
|
+
current.lines.push(line);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (current) blocks.push(current);
|
|
42
|
+
|
|
43
|
+
const names = new Set(blocks.map((b) => b.name));
|
|
44
|
+
|
|
45
|
+
mkdirSync(SCHEMA_DIR, { recursive: true });
|
|
46
|
+
|
|
47
|
+
for (const block of blocks) {
|
|
48
|
+
const normalizedLines = block.lines.map((l, idx) =>
|
|
49
|
+
idx === 0 ? l.replace(/^\s*(export\s+)?const\s+/, "export const ") : l,
|
|
50
|
+
);
|
|
51
|
+
const content = normalizedLines.join("\n");
|
|
52
|
+
const deps = Array.from(names)
|
|
53
|
+
.filter((n) => n !== block.name)
|
|
54
|
+
.filter((n) => new RegExp(`\\b${n}\\b`).test(content));
|
|
55
|
+
|
|
56
|
+
const importDepLines = deps.map(
|
|
57
|
+
(dep) => `import { ${dep} } from "./${dep}.js"`,
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
const fileContent = [
|
|
61
|
+
...importLines,
|
|
62
|
+
...importDepLines,
|
|
63
|
+
content,
|
|
64
|
+
"",
|
|
65
|
+
].join("\n");
|
|
66
|
+
|
|
67
|
+
writeFileSync(join(SCHEMA_DIR, `${block.name}.ts`), fileContent);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// index exports all and the root schema
|
|
71
|
+
const exportLines = Array.from(
|
|
72
|
+
new Set(
|
|
73
|
+
blocks.map((b) => `export { ${b.name} } from "./schemas/${b.name}.js"`),
|
|
74
|
+
),
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
writeFileSync(OUTPUT_INDEX, exportLines.join("\n") + "\n");
|
|
78
|
+
|
|
79
|
+
console.log(`Generated per-schema files in ${SCHEMA_DIR} and index at ${OUTPUT_INDEX}`);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
main();
|