zod-to-x 1.0.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/LICENSE +21 -0
- package/README.md +334 -0
- package/package.json +49 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 rroumenov
|
|
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 all
|
|
13
|
+
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 THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
# zod-to-x
|
|
2
|
+
[`@zod-to-x`](https://github.com/rroumenov/zod-to-x) is a Zod-based library designed to establish a centralized methodology for defining data structures. It allows you to transpile these definitions into various programming languages in a clear and straightforward way. This tool addresses a fundamental requirement of any software: having a clear understanding of the data it handles.
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
## Table of contents
|
|
7
|
+
- [Why use `@zod-to-x`](#why-use-zod-to-x)
|
|
8
|
+
- [Installation](#installation)
|
|
9
|
+
- [Quick start](#quick-start)
|
|
10
|
+
- [Supported output languages](#supported-output-languages)
|
|
11
|
+
- [Mapping of supported Zod Types](#mapping-of-supported-zod-types)
|
|
12
|
+
- [Additional utils](#additional-utils)
|
|
13
|
+
- [Known limitations](#known-limitations)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
## Why Use [`@zod-to-x`](https://github.com/rroumenov/zod-to-x)?
|
|
18
|
+
In modern software development, managing data consistency across multiple layers and languages is a persistent challenge. [`@zod-to-x`](https://github.com/rroumenov/zod-to-x) tackles this problem head-on by enabling you to define your data models once, in a centralized and expressive way, and then effortlessly transpile these models into multiple programming languages. Here's why [`@zod-to-x`](https://github.com/rroumenov/zod-to-x) stands out:
|
|
19
|
+
|
|
20
|
+
1. Centralized Data Definition
|
|
21
|
+
With [`@zod-to-x`](https://github.com/rroumenov/zod-to-x), you define your data structures in one place using the powerful Zod library. This eliminates redundancy, reduces the risk of inconsistencies, and simplifies maintenance across your codebase.
|
|
22
|
+
|
|
23
|
+
2. Multi-Language Compatibility
|
|
24
|
+
Gone are the days of manually rewriting data models for different platforms. [`@zod-to-x`](https://github.com/rroumenov/zod-to-x) lets you generate data types for:
|
|
25
|
+
|
|
26
|
+
- TypeScript: Build strong, type-safe interfaces or classes for front-end and back-end applications.
|
|
27
|
+
- Protobuf V3: Seamlessly integrate with gRPC and other Protobuf-based systems.
|
|
28
|
+
- More Languages: Support for additional languages like C++ is on the roadmap.
|
|
29
|
+
|
|
30
|
+
3. Enhanced Productivity
|
|
31
|
+
By automating the transpilation of data models, [`@zod-to-x`](https://github.com/rroumenov/zod-to-x) allows your team to focus on writing business logic instead of boilerplate code. Changes to schemas are propagated automatically, saving time and minimizing errors.
|
|
32
|
+
|
|
33
|
+
4. Built on Zod's Robust Ecosystem
|
|
34
|
+
[`@zod-to-x`](https://github.com/rroumenov/zod-to-x) extends the capabilities of Zod, a popular and intuitive schema validation library. This means you can:
|
|
35
|
+
|
|
36
|
+
- Leverage Zod's wide array of schema types and validations.
|
|
37
|
+
- Maintain compatibility with existing Zod-based projects.
|
|
38
|
+
- Easily integrate with tools like [`@zod-to-json-schema`](https://github.com/StefanTerdell/zod-to-json-schema).
|
|
39
|
+
|
|
40
|
+
5. Flexible Output Options
|
|
41
|
+
Whether you need plain interfaces, full-fledged classes with constructors, or Protobuf definitions, [`@zod-to-x`](https://github.com/rroumenov/zod-to-x) can adapt to your specific needs with customizable output formats.
|
|
42
|
+
|
|
43
|
+
6. Transparent and Extendable
|
|
44
|
+
The library is designed to be lightweight, transparent, and easy to integrate into existing workflows. Its extendable architecture ensures it can evolve to meet your project’s growing demands.
|
|
45
|
+
|
|
46
|
+
7. Ideal for Cross-Language Development
|
|
47
|
+
If your application spans multiple languages—like a front-end in TypeScript, a back-end in Python, and microservices in Protobuf—[`@zod-to-x`](https://github.com/rroumenov/zod-to-x) simplifies the process of keeping data structures consistent across the stack.
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
## Installation
|
|
52
|
+
### 1) Install [`@zod-to-x`](https://github.com/rroumenov/zod-to-x) and [`@zod`]((https://github.com/colinhacks/zod)) dependency.
|
|
53
|
+
```bash
|
|
54
|
+
npm install zod-to-x
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### 2) Extend Zod using the `extendZod` method after the first [`@zod`]((https://github.com/colinhacks/zod)) import:
|
|
58
|
+
```ts
|
|
59
|
+
import { z } from "zod";
|
|
60
|
+
import { extendZod } from "zod-to-x";
|
|
61
|
+
extendZod(z);
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
This extension appends a `zod2x` method to:
|
|
65
|
+
- ZodEnum
|
|
66
|
+
- ZodNativeEnum
|
|
67
|
+
- ZodObject
|
|
68
|
+
- ZodUnion
|
|
69
|
+
- ZodDiscriminatedUnion
|
|
70
|
+
- ZodIntersection
|
|
71
|
+
|
|
72
|
+
## Quick start
|
|
73
|
+
### 1) Define a data model using Zod schemas
|
|
74
|
+
```ts
|
|
75
|
+
import { z } from "zod";
|
|
76
|
+
|
|
77
|
+
// Skip the extend step if it has already been done.
|
|
78
|
+
import { extendZod } from "zod-to-x";
|
|
79
|
+
extendZod(z);
|
|
80
|
+
|
|
81
|
+
const VisitorSchema = z.object({
|
|
82
|
+
id: z.string().uuid(),
|
|
83
|
+
name: z.string(),
|
|
84
|
+
email: z.string().email(),
|
|
85
|
+
visitDate: z.date(),
|
|
86
|
+
comments: z.string().optional(),
|
|
87
|
+
}).zod2x("Visitor"); // Add your expected output type name using the 'zod2x' method.
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### 2) Build an AST node of the Zod schema
|
|
92
|
+
```ts
|
|
93
|
+
import { Zod2Ast } from "zod-to-x";
|
|
94
|
+
|
|
95
|
+
const visitorNodes = new Zod2Ast().build(VisitorSchema);
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### 3) Generate types in the desired language
|
|
99
|
+
```ts
|
|
100
|
+
import { Zod2Ts } from "zod-to-x";
|
|
101
|
+
|
|
102
|
+
const tsVisitor: string = new Zod2Ts().transpile(visitorNodes);
|
|
103
|
+
console.log(tsVisitor)
|
|
104
|
+
// output:
|
|
105
|
+
// export interface Visitor {
|
|
106
|
+
// id: string;
|
|
107
|
+
// name: string;
|
|
108
|
+
// email: string;
|
|
109
|
+
// visitDate: Date;
|
|
110
|
+
// comments?: string;
|
|
111
|
+
// }
|
|
112
|
+
```
|
|
113
|
+
Depending on the transpiled language, data models can be generated using classes:
|
|
114
|
+
|
|
115
|
+
```ts
|
|
116
|
+
import { Zod2Ts } from "zod-to-x";
|
|
117
|
+
|
|
118
|
+
const tsVisitor: string = new Zod2Ts({outType: "class"}).transpile(visitorNodes);
|
|
119
|
+
console.log(tsVisitor)
|
|
120
|
+
// output:
|
|
121
|
+
// export class Visitor {
|
|
122
|
+
// id: string;
|
|
123
|
+
// name: string;
|
|
124
|
+
// email: string;
|
|
125
|
+
// visitDate: Date;
|
|
126
|
+
// comments?: string;
|
|
127
|
+
|
|
128
|
+
// constructor(data: Visitor) {
|
|
129
|
+
// this.id = data.id;
|
|
130
|
+
// this.name = data.name;
|
|
131
|
+
// this.email = data.email;
|
|
132
|
+
// this.visitDate = data.visitdate;
|
|
133
|
+
// this.comments = data.comments;
|
|
134
|
+
// }
|
|
135
|
+
// }
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
A complete and more complex schema definition with its outputs can be found in the `test` folder:
|
|
140
|
+
- [Zod Schemas](test/data)
|
|
141
|
+
- [Typescript outputs](test/test_zod2ts)
|
|
142
|
+
- [Protobuf V3 outputs](test/test_zod2proto3/)
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
## Supported output languages
|
|
147
|
+
Common options:
|
|
148
|
+
- **header**: Text to add as a comment at the beginning of the output.
|
|
149
|
+
- **indent**: Number of spaces to use for indentation in the generated code. Defaults to 4 if not specified.
|
|
150
|
+
- **includeComments**: Determines whether to include comments in the transpiled code. Defaults to `true`.
|
|
151
|
+
|
|
152
|
+
### · **Typescript**
|
|
153
|
+
Options:
|
|
154
|
+
- **outType**: Output transpilation using Typescript interfaces or Classes.
|
|
155
|
+
|
|
156
|
+
### · Protobuf V3
|
|
157
|
+
Options:
|
|
158
|
+
- **packageName**: Name of the protobuf file package.
|
|
159
|
+
- **useCamelCase**: Protobuf follows the snake_case convention for field names, but camelCase can also be used. Defaults to `false`.
|
|
160
|
+
|
|
161
|
+
### · C++ (upcoming)
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
## Mapping of supported Zod Types
|
|
166
|
+
|
|
167
|
+
| Zod Type | TypeScript | Protobuf |
|
|
168
|
+
|-------------------|-----------------------------|-----------------------------------------------|
|
|
169
|
+
| `z.string()` | `string` | `string` |
|
|
170
|
+
| `z.number()` | `number` | `double`, `uint32`, `uint64`, `ìnt32`, `int64`|
|
|
171
|
+
| `z.bigint()` | `number` | `int64`, `uint64` |
|
|
172
|
+
| `z.boolean()` | `boolean` | `bool` |
|
|
173
|
+
| `z.date()` | `Date` | `google.protobuf.Timestamp` |
|
|
174
|
+
| `z.literal()` | Literal value (`'value'`) | `number` or `string` |
|
|
175
|
+
| `z.enum()` | `enum` | `enum` |
|
|
176
|
+
| `z.nativeEnum()` | Native `enum` | `enum` |
|
|
177
|
+
| `z.array()` | `T[]` | `repeated` field |
|
|
178
|
+
| `z.set()` | `Set<T>` | `repeated` field |
|
|
179
|
+
| `z.tuple()` | `[T1, T2, T3]` | Not supported |
|
|
180
|
+
| `z.object()` | `interface` or `class` | `message` |
|
|
181
|
+
| `z.record()` | `Record<string, T>` | `map<string, K>` |
|
|
182
|
+
| `z.union()` | `T1 \| T2` or `type` | `oneof` |
|
|
183
|
+
| `z.intersection()`| `T1 & T2` or `type` | Not supported |
|
|
184
|
+
| `z.any()` | `any` | `google.protobuf.Any` |
|
|
185
|
+
| `z.optional()` | `T \| undefined` | Not supported |
|
|
186
|
+
| `z.nullable()` | `T \| null` | Not supported |
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
## Additional utils
|
|
191
|
+
- `zod2JsonSchemaDefinitions`
|
|
192
|
+
In case of use of libraries like [`@zod-to-json-schema`](https://github.com/StefanTerdell/zod-to-json-schema), the provided zod extension can also be used
|
|
193
|
+
as a JSON Schema definitions mapper:
|
|
194
|
+
```ts
|
|
195
|
+
import { z } from 'zod';
|
|
196
|
+
import { extendZod, zod2JsonSchemaDefinitions } from 'zod-to-x';
|
|
197
|
+
import { zodToJsonSchema } from 'zod-to-json-schema';
|
|
198
|
+
|
|
199
|
+
extendZod(z);
|
|
200
|
+
|
|
201
|
+
const Address = z.object({
|
|
202
|
+
street: z.string(),
|
|
203
|
+
city: z.string(),
|
|
204
|
+
zipCode: z.string().nullable(),
|
|
205
|
+
}).zod2x("UserAddress");
|
|
206
|
+
|
|
207
|
+
const UserRole = z.union([
|
|
208
|
+
z.literal('admin'),
|
|
209
|
+
z.literal('editor'),
|
|
210
|
+
z.literal('viewer')
|
|
211
|
+
]).zod2x("UserRole");
|
|
212
|
+
|
|
213
|
+
const StatusEnum = z.enum([
|
|
214
|
+
'active',
|
|
215
|
+
'inactive',
|
|
216
|
+
'pending']
|
|
217
|
+
)
|
|
218
|
+
.describe("This is a UserStatus enumerate description.")
|
|
219
|
+
.zod2x("UserStatus");
|
|
220
|
+
|
|
221
|
+
export const UserModel = z.object({
|
|
222
|
+
address: Address,
|
|
223
|
+
roles: z.array(UserRole),
|
|
224
|
+
status: StatusEnum,
|
|
225
|
+
friends: z.lazy((): ZodType => UserModel.array().optional().nullable()),
|
|
226
|
+
// [... more attributes]
|
|
227
|
+
})
|
|
228
|
+
.describe("This is a UserModel interface description.")
|
|
229
|
+
.zod2x("UserModel");
|
|
230
|
+
|
|
231
|
+
const userDefinitions = zod2JsonSchemaDefinitions(UserModel);
|
|
232
|
+
const userJsonSchema = zodToJsonSchema(UserModel, {definitions: userDefinitions});
|
|
233
|
+
console.log(userJsonSchema);
|
|
234
|
+
// output:
|
|
235
|
+
// {
|
|
236
|
+
// "$ref": "#/definitions/UserModel",
|
|
237
|
+
// "definitions": {
|
|
238
|
+
// "UserAddress": {
|
|
239
|
+
// "type": "object",
|
|
240
|
+
// "properties": {
|
|
241
|
+
// "street": {
|
|
242
|
+
// "type": "string"
|
|
243
|
+
// },
|
|
244
|
+
// "city": {
|
|
245
|
+
// "type": "string"
|
|
246
|
+
// },
|
|
247
|
+
// "zipCode": {
|
|
248
|
+
// "type": [
|
|
249
|
+
// "string",
|
|
250
|
+
// "null"
|
|
251
|
+
// ]
|
|
252
|
+
// }
|
|
253
|
+
// },
|
|
254
|
+
// "required": [
|
|
255
|
+
// "street",
|
|
256
|
+
// "city",
|
|
257
|
+
// "zipCode"
|
|
258
|
+
// ],
|
|
259
|
+
// "additionalProperties": false
|
|
260
|
+
// },
|
|
261
|
+
// "UserRole": {
|
|
262
|
+
// "type": "string",
|
|
263
|
+
// "enum": [
|
|
264
|
+
// "admin",
|
|
265
|
+
// "editor",
|
|
266
|
+
// "viewer"
|
|
267
|
+
// ]
|
|
268
|
+
// },
|
|
269
|
+
// "UserStatus": {
|
|
270
|
+
// "type": "string",
|
|
271
|
+
// "enum": [
|
|
272
|
+
// "active",
|
|
273
|
+
// "inactive",
|
|
274
|
+
// "pending"
|
|
275
|
+
// ],
|
|
276
|
+
// "description": "This is a UserStatus enumerate description."
|
|
277
|
+
// },
|
|
278
|
+
// "UserModel": {
|
|
279
|
+
// "type": "object",
|
|
280
|
+
// "properties": {
|
|
281
|
+
// "address": {
|
|
282
|
+
// "$ref": "#/definitions/UserAddress"
|
|
283
|
+
// },
|
|
284
|
+
// "roles": {
|
|
285
|
+
// "type": "array",
|
|
286
|
+
// "items": {
|
|
287
|
+
// "$ref": "#/definitions/UserRole"
|
|
288
|
+
// }
|
|
289
|
+
// },
|
|
290
|
+
// "status": {
|
|
291
|
+
// "$ref": "#/definitions/UserStatus"
|
|
292
|
+
// },
|
|
293
|
+
// "friends": {
|
|
294
|
+
// "anyOf": [
|
|
295
|
+
// {
|
|
296
|
+
// "anyOf": [
|
|
297
|
+
// {
|
|
298
|
+
// "not": {}
|
|
299
|
+
// },
|
|
300
|
+
// {
|
|
301
|
+
// "type": "array",
|
|
302
|
+
// "items": {
|
|
303
|
+
// "$ref": "#/definitions/UserModel"
|
|
304
|
+
// },
|
|
305
|
+
// "description": "This is a UserModel interface description."
|
|
306
|
+
// }
|
|
307
|
+
// ],
|
|
308
|
+
// "description": "This is a UserModel interface description."
|
|
309
|
+
// },
|
|
310
|
+
// {
|
|
311
|
+
// "type": "null"
|
|
312
|
+
// }
|
|
313
|
+
// ],
|
|
314
|
+
// "description": "This is a UserModel interface description."
|
|
315
|
+
// },
|
|
316
|
+
// },
|
|
317
|
+
// "required": [
|
|
318
|
+
// "address",
|
|
319
|
+
// "roles",
|
|
320
|
+
// "status",
|
|
321
|
+
// ],
|
|
322
|
+
// "additionalProperties": false,
|
|
323
|
+
// "description": "This is a UserModel interface description."
|
|
324
|
+
// }
|
|
325
|
+
// },
|
|
326
|
+
// "$schema": "http://json-schema.org/draft-07/schema#"
|
|
327
|
+
// }
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
## Known limitations
|
|
333
|
+
- Protobuf V3:
|
|
334
|
+
- `oneof` fields support only unions of `ZodObject` schemas.
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "zod-to-x",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "Multi language types generation from Zod schemas.",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"files": ["/dist"],
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc && tsc-alias",
|
|
9
|
+
"test": "jest",
|
|
10
|
+
"ts-run": "ts-node -r tsconfig-paths/register"
|
|
11
|
+
},
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "git+https://github.com/rroumenov/zod-to-x.git"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"zod",
|
|
18
|
+
"transpiler",
|
|
19
|
+
"schema",
|
|
20
|
+
"type",
|
|
21
|
+
"generator",
|
|
22
|
+
"zod-to-ts",
|
|
23
|
+
"zod-to-typescript",
|
|
24
|
+
"typescript",
|
|
25
|
+
"typescript-generator",
|
|
26
|
+
"type-generation",
|
|
27
|
+
"protobuf"
|
|
28
|
+
],
|
|
29
|
+
"author": "Radoslav Roumenov Krastev",
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"bugs": {
|
|
32
|
+
"url": "https://github.com/rroumenov/zod-to-x/issues"
|
|
33
|
+
},
|
|
34
|
+
"homepage": "https://github.com/rroumenov/zod-to-x#readme",
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"zod": "^3.23.8"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@types/jest": "29.5.14",
|
|
40
|
+
"jest": "^29.7.0",
|
|
41
|
+
"jest-diff": "^29.7.0",
|
|
42
|
+
"protobufjs": "7.4.0",
|
|
43
|
+
"ts-jest": "^29.2.5",
|
|
44
|
+
"ts-node": "^10.9.2",
|
|
45
|
+
"tsc-alias": "^1.8.10",
|
|
46
|
+
"tsconfig-paths": "4.2.0",
|
|
47
|
+
"typescript": "^5.6.3"
|
|
48
|
+
}
|
|
49
|
+
}
|