Skip to content

Commit cddfc94

Browse files
committed
Package
1 parent 9294492 commit cddfc94

File tree

15 files changed

+2015
-1345
lines changed

15 files changed

+2015
-1345
lines changed

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,7 @@
11
node_modules
2+
dist
3+
.DS_Store
4+
*.log
5+
coverage
6+
.nyc_output
7+
.vscode

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2025 Mark Probst
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in
13+
all copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
THE SOFTWARE.

README.md

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
# zod-from-json-schema
2+
3+
A library that creates [Zod](https://github.com/colinhacks/zod) types from [JSON Schema](https://json-schema.org/) at runtime. This is in contrast to [json-schema-to-zod](https://www.npmjs.com/package/json-schema-to-zod), which generates JavaScript source code.
4+
5+
## Installation
6+
7+
```bash
8+
npm install zod-from-json-schema
9+
```
10+
11+
## Usage
12+
13+
This package supports both ESM and CommonJS formats.
14+
15+
### ESM (ES Modules)
16+
17+
```typescript
18+
import { convertJsonSchemaToZod } from 'zod-from-json-schema';
19+
20+
// Define a JSON Schema
21+
const jsonSchema = {
22+
$schema: "http://json-schema.org/draft-07/schema#",
23+
type: "object",
24+
properties: {
25+
name: { type: "string", minLength: 2, maxLength: 50 },
26+
age: { type: "integer", minimum: 0, maximum: 120 },
27+
email: { type: "string", pattern: "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$" },
28+
tags: {
29+
type: "array",
30+
items: { type: "string" },
31+
uniqueItems: true,
32+
minItems: 1
33+
}
34+
},
35+
required: ["name", "email"],
36+
additionalProperties: false
37+
};
38+
39+
// Convert JSON Schema to Zod schema
40+
const zodSchema = convertJsonSchemaToZod(jsonSchema);
41+
42+
// Use the Zod schema to validate data
43+
try {
44+
const validData = zodSchema.parse({
45+
name: "John Doe",
46+
47+
age: 30,
48+
tags: ["user", "premium"]
49+
});
50+
console.log("Valid data:", validData);
51+
} catch (error) {
52+
console.error("Validation error:", error);
53+
}
54+
```
55+
56+
### CommonJS
57+
58+
```javascript
59+
const { convertJsonSchemaToZod } = require('zod-from-json-schema');
60+
61+
// Define a JSON Schema
62+
const jsonSchema = {
63+
$schema: "http://json-schema.org/draft-07/schema#",
64+
type: "object",
65+
properties: {
66+
name: { type: "string", minLength: 2, maxLength: 50 },
67+
age: { type: "integer", minimum: 0, maximum: 120 }
68+
},
69+
required: ["name"],
70+
additionalProperties: false
71+
};
72+
73+
// Convert JSON Schema to Zod schema
74+
const zodSchema = convertJsonSchemaToZod(jsonSchema);
75+
76+
// Use the Zod schema to validate data
77+
const validData = zodSchema.parse({
78+
name: "John Doe",
79+
age: 30
80+
});
81+
```
82+
83+
## Supported JSON Schema Features
84+
85+
This library supports the following JSON Schema features:
86+
87+
### Basic Types
88+
- `string`
89+
- `number`
90+
- `integer`
91+
- `boolean`
92+
- `null`
93+
- `object` (with properties and required fields)
94+
- `array`
95+
96+
### String Validations
97+
- `minLength`
98+
- `maxLength`
99+
- `pattern` (regular expressions)
100+
101+
### Number Validations
102+
- `minimum`
103+
- `maximum`
104+
- `exclusiveMinimum`
105+
- `exclusiveMaximum`
106+
- `multipleOf`
107+
108+
### Array Validations
109+
- `minItems`
110+
- `maxItems`
111+
- `uniqueItems`
112+
113+
### Object Validations
114+
- `required` (required properties)
115+
- `additionalProperties` (controls passthrough behavior)
116+
117+
### Schema Composition
118+
- `const` (literal values)
119+
- `enum` (enumerated values)
120+
- `anyOf` (union)
121+
- `allOf` (intersection)
122+
- `oneOf` (union)
123+
124+
### Additional
125+
- `description` (carried over to Zod schemas)
126+
127+
## License
128+
129+
MIT

build.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
const { build } = require('esbuild');
2+
const { copyFile } = require('fs/promises');
3+
const { resolve } = require('path');
4+
5+
async function buildPackage() {
6+
try {
7+
// Build ESM version
8+
await build({
9+
entryPoints: ['./src/index.ts'],
10+
outfile: './dist/index.mjs',
11+
format: 'esm',
12+
platform: 'node',
13+
target: 'es2018',
14+
bundle: true,
15+
external: ['zod'],
16+
});
17+
18+
// Build CommonJS version
19+
await build({
20+
entryPoints: ['./src/index.ts'],
21+
outfile: './dist/index.js',
22+
format: 'cjs',
23+
platform: 'node',
24+
target: 'es2018',
25+
bundle: true,
26+
external: ['zod'],
27+
});
28+
29+
// Copy the TypeScript declarations
30+
await copyFile(
31+
resolve('./dist/index.d.ts'),
32+
resolve('./dist/index.d.mts')
33+
).catch(err => {
34+
// Ignore if the file doesn't exist, as TypeScript doesn't generate .d.mts files
35+
if (err.code !== 'ENOENT') {
36+
throw err;
37+
}
38+
});
39+
40+
console.log('✅ Build completed');
41+
} catch (err) {
42+
console.error('❌ Build failed:', err);
43+
process.exit(1);
44+
}
45+
}
46+
47+
buildPackage();

example.js

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// This example demonstrates how to use zod-from-json-schema
2+
const { convertJsonSchemaToZod } = require('./dist/index');
3+
4+
// Define a JSON Schema
5+
const jsonSchema = {
6+
type: "object",
7+
properties: {
8+
name: {
9+
type: "string",
10+
minLength: 2,
11+
maxLength: 50,
12+
description: "User's full name"
13+
},
14+
age: {
15+
type: "integer",
16+
minimum: 0,
17+
maximum: 120,
18+
description: "User's age in years"
19+
},
20+
email: {
21+
type: "string",
22+
pattern: "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
23+
description: "User's email address"
24+
},
25+
tags: {
26+
type: "array",
27+
items: { type: "string" },
28+
uniqueItems: true,
29+
minItems: 1,
30+
description: "User's tags or categories"
31+
}
32+
},
33+
required: ["name", "email"],
34+
additionalProperties: false,
35+
description: "A user profile schema"
36+
};
37+
38+
// Convert JSON Schema to Zod schema
39+
const zodSchema = convertJsonSchemaToZod(jsonSchema);
40+
41+
// Example of valid data
42+
const validData = {
43+
name: "John Doe",
44+
45+
age: 30,
46+
tags: ["user", "premium"]
47+
};
48+
49+
// Validate the data
50+
try {
51+
const validated = zodSchema.parse(validData);
52+
console.log("✅ Valid data:", validated);
53+
} catch (error) {
54+
console.error("❌ Validation error:", error.errors);
55+
}
56+
57+
// Example of invalid data
58+
const invalidData = {
59+
name: "J", // Too short - minLength is 2
60+
email: "not-an-email", // Invalid email format
61+
age: 150, // Above maximum of 120
62+
tags: ["user", "user"] // Duplicate items - uniqueItems is true
63+
};
64+
65+
// Validate the invalid data (will throw an error)
66+
try {
67+
const validated = zodSchema.parse(invalidData);
68+
console.log("Valid data:", validated);
69+
} catch (error) {
70+
console.error("❌ Validation errors:", error.format());
71+
}
72+
73+
// Example of safeParse - doesn't throw errors
74+
const safeResult = zodSchema.safeParse(invalidData);
75+
if (safeResult.success) {
76+
console.log("✅ Valid data:", safeResult.data);
77+
} else {
78+
console.log("❌ Invalid data, issues:");
79+
console.log(safeResult.error.format());
80+
}

examples/README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# zod-from-json-schema Examples
2+
3+
This directory contains examples showing how to use zod-from-json-schema in both CommonJS and ESM environments.
4+
5+
## Running the examples
6+
7+
To run the CommonJS example:
8+
9+
```bash
10+
node cjs-example.cjs
11+
```
12+
13+
To run the ESM example:
14+
15+
```bash
16+
node esm-example.mjs
17+
```
18+
19+
## Notes
20+
21+
- The CommonJS example uses `.cjs` extension and `require()` syntax
22+
- The ESM example uses `.mjs` extension and `import` syntax
23+
- Both examples import directly from the local build in `../dist/`
24+
- When using in your own project, you would import from `zod-from-json-schema` instead

examples/cjs-example.cjs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// CommonJS Example
2+
const { convertJsonSchemaToZod } = require('../dist/index.js');
3+
4+
// Define a JSON Schema
5+
const jsonSchema = {
6+
type: "object",
7+
properties: {
8+
name: {
9+
type: "string",
10+
minLength: 2,
11+
maxLength: 50,
12+
description: "User's full name"
13+
},
14+
age: {
15+
type: "integer",
16+
minimum: 0,
17+
maximum: 120,
18+
description: "User's age in years"
19+
}
20+
},
21+
required: ["name"],
22+
additionalProperties: false
23+
};
24+
25+
// Convert JSON Schema to Zod schema
26+
const zodSchema = convertJsonSchemaToZod(jsonSchema);
27+
28+
// Example of valid data
29+
const validData = {
30+
name: "John Doe",
31+
age: 30
32+
};
33+
34+
// Validate the data
35+
try {
36+
const validated = zodSchema.parse(validData);
37+
console.log("✅ CJS - Valid data:", validated);
38+
} catch (error) {
39+
console.error("❌ CJS - Validation error:", error.errors);
40+
}

0 commit comments

Comments
 (0)