zod-to-x 1.2.0 → 1.2.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 +44 -71
- package/dist/core/ast_node.js +31 -21
- package/dist/core/ast_types.d.ts +2 -0
- package/dist/core/transpiler.d.ts +1 -1
- package/dist/core/transpiler.js +4 -1
- package/dist/lib/zod_ext.d.ts +11 -7
- package/dist/lib/zod_ext.js +7 -0
- package/dist/transpilers/cpp/nlohmann.d.ts +1 -1
- package/dist/transpilers/cpp/nlohmann.js +26 -10
- package/dist/transpilers/cpp/runner.d.ts +1 -1
- package/dist/transpilers/cpp/runner.js +8 -7
- package/dist/transpilers/typescript/runner.d.ts +1 -1
- package/dist/transpilers/typescript/runner.js +6 -2
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -14,36 +14,16 @@
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
## Why Use [`@zod-to-x`](https://github.com/rroumenov/zod-to-x)?
|
|
17
|
-
|
|
17
|
+
Managing data consistency across multiple layers and languages is a common challenge in modern software development. [`@zod-to-x`](https://github.com/rroumenov/zod-to-x) solves this by allowing you to define your data models once and effortlessly transpile them into multiple programming languages. Here’s why it stands out:
|
|
18
18
|
|
|
19
|
-
1. Centralized Data Definition
|
|
20
|
-
|
|
19
|
+
1. **Centralized Data Definition**
|
|
20
|
+
Define your data structures in one place using the powerful [`@zod`]((https://github.com/colinhacks/zod)) library. This eliminates redundancy, reduces inconsistencies, and simplifies maintenance across your entire codebase, all while allowing you to continue leveraging any npm package in the [`@zod`]((https://github.com/colinhacks/zod)) ecosystem like [`@zod-to-json-schema`](https://github.com/StefanTerdell/zod-to-json-schema)
|
|
21
21
|
|
|
22
|
-
2. Multi-Language Compatibility
|
|
23
|
-
|
|
22
|
+
2. **Multi-Language Compatibility**
|
|
23
|
+
Generate data models for TypeScript, Protobuf V3 and C++ (with languages like Golang on the roadmap). No more manually rewriting models for different platforms.
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
- More Languages: Support for additional languages like C++ is on the roadmap.
|
|
28
|
-
|
|
29
|
-
3. Enhanced Productivity
|
|
30
|
-
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.
|
|
31
|
-
|
|
32
|
-
4. Built on Zod's Robust Ecosystem
|
|
33
|
-
[`@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:
|
|
34
|
-
|
|
35
|
-
- Leverage Zod's wide array of schema types and validations.
|
|
36
|
-
- Maintain compatibility with existing Zod-based projects.
|
|
37
|
-
- Easily integrate with tools like [`@zod-to-json-schema`](https://github.com/StefanTerdell/zod-to-json-schema).
|
|
38
|
-
|
|
39
|
-
5. Flexible Output Options
|
|
40
|
-
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.
|
|
41
|
-
|
|
42
|
-
6. Transparent and Extendable
|
|
43
|
-
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.
|
|
44
|
-
|
|
45
|
-
7. Ideal for Cross-Language Development
|
|
46
|
-
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.
|
|
25
|
+
3. **Enhanced Productivity**
|
|
26
|
+
Automate the transpilation of data models to save time, reduce errors, and let your team focus on business logic instead of boilerplate code.
|
|
47
27
|
|
|
48
28
|
|
|
49
29
|
|
|
@@ -67,39 +47,36 @@ This extension appends a `zod2x` method to:
|
|
|
67
47
|
- ZodUnion
|
|
68
48
|
- ZodDiscriminatedUnion
|
|
69
49
|
- ZodIntersection
|
|
50
|
+
- ZodLiteral
|
|
70
51
|
|
|
71
52
|
## Quick start
|
|
72
|
-
### 1) Define a data model using Zod schemas
|
|
73
53
|
```ts
|
|
74
54
|
import { z } from "zod";
|
|
55
|
+
import { extendZod, Zod2Ast, Zod2Ts } from "zod-to-x";
|
|
56
|
+
extendZod(z); // The extend step can be skipped if it has already been done.
|
|
75
57
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
58
|
+
/**
|
|
59
|
+
* 1) Define a data model using Zod schemas
|
|
60
|
+
*/
|
|
80
61
|
const VisitorSchema = z.object({
|
|
81
62
|
id: z.string().uuid(),
|
|
82
63
|
name: z.string(),
|
|
83
64
|
email: z.string().email(),
|
|
84
65
|
visitDate: z.date(),
|
|
85
66
|
comments: z.string().optional(),
|
|
86
|
-
}).zod2x("Visitor");
|
|
87
|
-
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
### 2) Build an AST node of the Zod schema
|
|
91
|
-
```ts
|
|
92
|
-
import { Zod2Ast } from "zod-to-x";
|
|
67
|
+
}).zod2x("Visitor"); // Add your expected output type name using the 'zod2x' method.
|
|
93
68
|
|
|
69
|
+
/**
|
|
70
|
+
* 2) Build an AST node of the Zod schema
|
|
71
|
+
*/
|
|
94
72
|
const visitorNodes = new Zod2Ast().build(VisitorSchema);
|
|
95
|
-
```
|
|
96
73
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
const
|
|
102
|
-
console.log(
|
|
74
|
+
/**
|
|
75
|
+
* 3) Generate types in the desired language.
|
|
76
|
+
* Depending on the transpiled language, data models can be generated using classes.
|
|
77
|
+
*/
|
|
78
|
+
const tsVisitorAsInterface: string = new Zod2Ts().transpile(visitorNodes);
|
|
79
|
+
console.log(tsVisitorAsInterface)
|
|
103
80
|
// output:
|
|
104
81
|
// export interface Visitor {
|
|
105
82
|
// id: string;
|
|
@@ -108,14 +85,9 @@ console.log(tsVisitor)
|
|
|
108
85
|
// visitDate: Date;
|
|
109
86
|
// comments?: string;
|
|
110
87
|
// }
|
|
111
|
-
```
|
|
112
|
-
Depending on the transpiled language, data models can be generated using classes:
|
|
113
|
-
|
|
114
|
-
```ts
|
|
115
|
-
import { Zod2Ts } from "zod-to-x";
|
|
116
88
|
|
|
117
|
-
const
|
|
118
|
-
console.log(
|
|
89
|
+
const tsVisitorAsClass: string = new Zod2Ts({outType: "class"}).transpile(visitorNodes);
|
|
90
|
+
console.log(tsVisitorAsClass)
|
|
119
91
|
// output:
|
|
120
92
|
// export class Visitor {
|
|
121
93
|
// id: string;
|
|
@@ -135,11 +107,11 @@ console.log(tsVisitor)
|
|
|
135
107
|
```
|
|
136
108
|
|
|
137
109
|
|
|
138
|
-
|
|
139
|
-
- [Zod Schemas](test/
|
|
110
|
+
Example of supported schemas with its outputs can be found in the `test` folder:
|
|
111
|
+
- [Zod Schemas](test/common)
|
|
140
112
|
- [Typescript outputs](test/test_zod2ts)
|
|
141
113
|
- [Protobuf V3 outputs](test/test_zod2proto3/)
|
|
142
|
-
- [C++
|
|
114
|
+
- [C++ outputs](test/test_zod2cpp/)
|
|
143
115
|
|
|
144
116
|
|
|
145
117
|
|
|
@@ -150,29 +122,29 @@ Common options:
|
|
|
150
122
|
- **includeComments**: Determines whether to include comments in the transpiled code. Defaults to `true`.
|
|
151
123
|
- **skipDiscriminatorNodes**: prevents the inclusion of `ZodEnum` or `ZodNativeEnum` schemas that are used solely as discriminator keys in a `ZodDiscriminatedUnion`. Defaults to `false`.
|
|
152
124
|
|
|
153
|
-
### Typescript
|
|
154
|
-
|
|
125
|
+
### 1) Typescript
|
|
126
|
+
- Options:
|
|
155
127
|
- **outType**: Output transpilation using Typescript interfaces or Classes. Defaults to `interface`.
|
|
156
128
|
|
|
157
|
-
### Protobuf V3
|
|
158
|
-
|
|
129
|
+
### 2) Protobuf V3
|
|
130
|
+
- Options:
|
|
159
131
|
- **packageName**: Name of the protobuf file package.
|
|
160
132
|
- **useCamelCase**: Protobuf follows the snake_case convention for field names, but camelCase can also be used. Defaults to `false`.
|
|
161
133
|
|
|
162
|
-
|
|
134
|
+
- Limitations:
|
|
163
135
|
- `oneof` fields support only unions of `ZodObject` schemas.
|
|
136
|
+
- `ZodTuple` is supported only for items of the same type.
|
|
164
137
|
|
|
165
138
|
|
|
166
|
-
### C++
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
#### Options:
|
|
139
|
+
### 3) C++
|
|
140
|
+
`Nlohmann` dependency is used for data serialization/deserialization. For *C++11*, `Boost` dependency is used. For *C++17* or newer, standard libraries are used.
|
|
141
|
+
- Options:
|
|
170
142
|
- **includeNulls**: When serializing, include all values even if `null`. Defaults to `false`.
|
|
171
143
|
- **namespace**: Name of the namespace containing the output code.
|
|
172
144
|
- **outType**: Output transpilation using C++ Structs or Classes. Defaults to `struct`.
|
|
173
145
|
- **skipSerialize**: Remove Nlohmann JSON serialization/deserialization. Defaults to `false`.
|
|
174
146
|
|
|
175
|
-
|
|
147
|
+
- Limitations:
|
|
176
148
|
- `ZodIntersection` is supported only for intersection of `ZodObject` schemas.
|
|
177
149
|
|
|
178
150
|
|
|
@@ -191,18 +163,19 @@ Common options:
|
|
|
191
163
|
| `z.nativeEnum()` | Native `enum` | `enum` | `enum class T: int`
|
|
192
164
|
| `z.array()` | `T[]` | `repeated` field | `std::vector<T>`
|
|
193
165
|
| `z.set()` | `Set<T>` | `repeated` field | `std::set<T>`
|
|
194
|
-
| `z.tuple()` | `[T1, T2, T3]` | `repeated` field
|
|
166
|
+
| `z.tuple()` | `[T1, T2, T3]` | `repeated` field | `std::tuple<T1, T2, T3>`
|
|
195
167
|
| `z.object()` | `interface` or `class` | `message` | `struct` or `class`
|
|
196
168
|
| `z.record()` | `Record<string, T>` | `map<string, K>` | `std::unordered_map<T>`
|
|
197
169
|
| `z.map()` | `Map<string, T>` | `map<string, K>` | `std::unordered_map<T>`
|
|
198
|
-
| `z.union()`
|
|
199
|
-
| `z.
|
|
170
|
+
| `z.union()` <sup>(2)</sup> | `T1 \| T2` or `type` | `oneof` | `std::variant<T, K>` (`boost::variant<T, K>` for C++11)
|
|
171
|
+
| `z.discriminatedUnion()`| `T1 \| T2` or `type` | `oneof` | `std::variant<T, K>` (`boost::variant<T, K>` for C++11)
|
|
172
|
+
| `z.intersection()` <sup>(1)</sup> | `T1 & T2` or `type` | Not supported | `struct` or `class` with `inheritance`
|
|
200
173
|
| `z.any()` | `any` | `google.protobuf.Any` | `nlohmann::json`
|
|
201
174
|
| `z.optional()` | `T \| undefined` | Not supported | `std::optional<T>` (`boost::optional<T>` for C++11)
|
|
202
175
|
| `z.nullable()` | `T \| null` | Not supported | `std::optional<T>` (`boost::optional<T>` for C++11)
|
|
203
176
|
|
|
204
|
-
<sup>(1)</sup>
|
|
205
|
-
<sup>(2)</sup> Consider to use
|
|
177
|
+
<sup>(1)</sup> Consider to use Zod's merge instead of ZodIntersection when possible.
|
|
178
|
+
<sup>(2)</sup> Consider to use ZodDiscriminatedUnion when possible. In languages like C++, deserialization is O(1) against the O(n) of the ZodUnion.
|
|
206
179
|
|
|
207
180
|
## Additional utils
|
|
208
181
|
- `zod2JsonSchemaDefinitions`
|
package/dist/core/ast_node.js
CHANGED
|
@@ -28,7 +28,7 @@ class Zod2Ast {
|
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
zodToAST(schema, opt) {
|
|
31
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
31
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
|
|
32
32
|
const def = schema._def;
|
|
33
33
|
if (schema instanceof zod_1.ZodString) {
|
|
34
34
|
return {
|
|
@@ -88,10 +88,19 @@ class Zod2Ast {
|
|
|
88
88
|
};
|
|
89
89
|
}
|
|
90
90
|
else if (schema instanceof zod_1.ZodLiteral) {
|
|
91
|
+
let parentEnumName = undefined;
|
|
92
|
+
let parentEnumKey = undefined;
|
|
93
|
+
if ((_c = def.zod2x) === null || _c === void 0 ? void 0 : _c.parentEnum) {
|
|
94
|
+
parentEnumName = (_e = (_d = def.zod2x) === null || _d === void 0 ? void 0 : _d.parentEnum._def.zod2x) === null || _e === void 0 ? void 0 : _e.typeName;
|
|
95
|
+
parentEnumKey = (_g = this._getEnumValues((_f = def.zod2x) === null || _f === void 0 ? void 0 : _f.parentEnum).find((i) => i[1] === def.value)) === null || _g === void 0 ? void 0 : _g[0];
|
|
96
|
+
this.zodToAST((_h = def.zod2x) === null || _h === void 0 ? void 0 : _h.parentEnum, { isInjectedEnum: true });
|
|
97
|
+
}
|
|
91
98
|
return {
|
|
92
99
|
type: zod_1.ZodFirstPartyTypeKind.ZodLiteral,
|
|
93
100
|
value: def.value,
|
|
94
101
|
description: schema.description,
|
|
102
|
+
parentEnumName,
|
|
103
|
+
parentEnumKey,
|
|
95
104
|
};
|
|
96
105
|
}
|
|
97
106
|
else if (schema instanceof zod_1.ZodRecord) {
|
|
@@ -124,14 +133,14 @@ class Zod2Ast {
|
|
|
124
133
|
};
|
|
125
134
|
}
|
|
126
135
|
else if (schema instanceof zod_1.ZodNativeEnum || schema instanceof zod_1.ZodEnum) {
|
|
127
|
-
let name = (
|
|
136
|
+
let name = (_j = def.zod2x) === null || _j === void 0 ? void 0 : _j.typeName;
|
|
128
137
|
const item = {
|
|
129
138
|
type: def.typeName,
|
|
130
|
-
name: (
|
|
139
|
+
name: (_k = def.zod2x) === null || _k === void 0 ? void 0 : _k.typeName,
|
|
131
140
|
values: this._getEnumValues(schema),
|
|
132
141
|
description: def.description,
|
|
133
142
|
};
|
|
134
|
-
if (opt === null || opt === void 0 ? void 0 : opt.
|
|
143
|
+
if (opt === null || opt === void 0 ? void 0 : opt.isInjectedEnum) {
|
|
135
144
|
if (!this.nodes.has(name) && !this.discriminatorNodes.has(name)) {
|
|
136
145
|
this.discriminatorNodes.set(name, item);
|
|
137
146
|
}
|
|
@@ -147,42 +156,43 @@ class Zod2Ast {
|
|
|
147
156
|
return this._createDefinition(name, def.typeName);
|
|
148
157
|
}
|
|
149
158
|
else if (schema instanceof zod_1.ZodObject) {
|
|
150
|
-
let name = (
|
|
159
|
+
let name = (_l = def.zod2x) === null || _l === void 0 ? void 0 : _l.typeName;
|
|
151
160
|
let discriminantValue = undefined;
|
|
152
161
|
if (!this.nodes.has(name)) {
|
|
153
162
|
const properties = {};
|
|
154
163
|
for (const key in def.shape()) {
|
|
155
164
|
properties[key] = this.zodToAST(def.shape()[key]);
|
|
156
|
-
if ((opt === null || opt === void 0 ? void 0 : opt.discriminantKey) && key === (opt === null || opt === void 0 ? void 0 : opt.discriminantKey)) {
|
|
157
|
-
if (properties[key].type === zod_1.ZodFirstPartyTypeKind.ZodLiteral) {
|
|
158
|
-
discriminantValue = String(properties[key].value);
|
|
159
|
-
}
|
|
160
|
-
else {
|
|
161
|
-
console.warn(`Consider to set '${key}' key of '${name}' as ZodLiteral`);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
165
|
}
|
|
165
166
|
this.nodes.set(name, {
|
|
166
167
|
type: zod_1.ZodFirstPartyTypeKind.ZodObject,
|
|
167
|
-
name: (
|
|
168
|
+
name: (_m = def.zod2x) === null || _m === void 0 ? void 0 : _m.typeName,
|
|
168
169
|
properties,
|
|
169
170
|
description: schema.description,
|
|
170
171
|
});
|
|
171
172
|
}
|
|
173
|
+
if (opt === null || opt === void 0 ? void 0 : opt.discriminantKey) {
|
|
174
|
+
const item = this.nodes.get(name);
|
|
175
|
+
if (Object.keys(item.properties).includes(opt.discriminantKey)) {
|
|
176
|
+
const key = opt.discriminantKey;
|
|
177
|
+
if (item.properties[key].type === zod_1.ZodFirstPartyTypeKind.ZodLiteral) {
|
|
178
|
+
discriminantValue = String(item.properties[key].value);
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
console.warn(`Consider to set '${key}' key of '${name}' as ZodLiteral`);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
172
185
|
return this._createDefinition(name, def.typeName, discriminantValue);
|
|
173
186
|
}
|
|
174
187
|
else if (schema instanceof zod_1.ZodUnion || schema instanceof zod_1.ZodDiscriminatedUnion) {
|
|
175
|
-
let name = (
|
|
188
|
+
let name = (_o = def.zod2x) === null || _o === void 0 ? void 0 : _o.typeName;
|
|
176
189
|
const item = {
|
|
177
190
|
type: def.typeName,
|
|
178
|
-
name: (
|
|
191
|
+
name: (_p = def.zod2x) === null || _p === void 0 ? void 0 : _p.typeName,
|
|
179
192
|
options: def.options.map((i) => this.zodToAST(i, { discriminantKey: def.discriminator })),
|
|
180
193
|
description: schema.description,
|
|
181
194
|
discriminantKey: def.discriminator,
|
|
182
195
|
};
|
|
183
|
-
if ((_j = def.zod2x) === null || _j === void 0 ? void 0 : _j.discriminatorEnum) {
|
|
184
|
-
this.zodToAST((_k = def.zod2x) === null || _k === void 0 ? void 0 : _k.discriminatorEnum, { isUnionDiscriminator: true });
|
|
185
|
-
}
|
|
186
196
|
if (name && !this.nodes.has(name)) {
|
|
187
197
|
this.nodes.set(name, item);
|
|
188
198
|
return this._createDefinition(name, def.typeName);
|
|
@@ -190,10 +200,10 @@ class Zod2Ast {
|
|
|
190
200
|
return item;
|
|
191
201
|
}
|
|
192
202
|
else if (schema instanceof zod_1.ZodIntersection) {
|
|
193
|
-
let name = (
|
|
203
|
+
let name = (_q = def.zod2x) === null || _q === void 0 ? void 0 : _q.typeName;
|
|
194
204
|
const item = {
|
|
195
205
|
type: zod_1.ZodFirstPartyTypeKind.ZodIntersection,
|
|
196
|
-
name: (
|
|
206
|
+
name: (_r = def.zod2x) === null || _r === void 0 ? void 0 : _r.typeName,
|
|
197
207
|
left: this.zodToAST(def.left),
|
|
198
208
|
right: this.zodToAST(def.right),
|
|
199
209
|
description: schema.description,
|
package/dist/core/ast_types.d.ts
CHANGED
|
@@ -25,7 +25,7 @@ export declare abstract class Zod2X<T extends IZodToXOpt> {
|
|
|
25
25
|
min?: number;
|
|
26
26
|
max?: number;
|
|
27
27
|
}): string;
|
|
28
|
-
protected abstract getLiteralStringType(value: string | number): string | number;
|
|
28
|
+
protected abstract getLiteralStringType(value: string | number, parentEnumNameKey?: [string, string]): string | number;
|
|
29
29
|
protected abstract getAnyType(): string;
|
|
30
30
|
protected abstract getDateType(): string;
|
|
31
31
|
protected abstract getTupleType(itemsType: string[]): string;
|
package/dist/core/transpiler.js
CHANGED
|
@@ -59,7 +59,10 @@ class Zod2X {
|
|
|
59
59
|
varType = this.getDateType();
|
|
60
60
|
}
|
|
61
61
|
else if (token.type === zod_1.ZodFirstPartyTypeKind.ZodLiteral) {
|
|
62
|
-
|
|
62
|
+
const parentEnum = token.parentEnumName && token.parentEnumKey
|
|
63
|
+
? [token.parentEnumName, token.parentEnumKey]
|
|
64
|
+
: undefined;
|
|
65
|
+
varType = this.getLiteralStringType(token.value, parentEnum);
|
|
63
66
|
}
|
|
64
67
|
else if (token.type === zod_1.ZodFirstPartyTypeKind.ZodSet) {
|
|
65
68
|
varType = this.getSetType(this.getAttributeType(token.value));
|
package/dist/lib/zod_ext.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { EnumLike, UnknownKeysParam, z, ZodEnum, ZodNativeEnum, ZodRawShape, ZodTypeAny, ZodUnionOptions } from "zod";
|
|
2
2
|
export interface Zod2xMetadata {
|
|
3
3
|
typeName: string;
|
|
4
|
-
|
|
4
|
+
parentEnum?: ZodEnum<any> | ZodNativeEnum<any>;
|
|
5
5
|
}
|
|
6
6
|
declare module "zod" {
|
|
7
7
|
interface ZodTypeDef {
|
|
@@ -9,27 +9,31 @@ declare module "zod" {
|
|
|
9
9
|
}
|
|
10
10
|
interface ZodObject<T extends ZodRawShape, UnknownKeys extends UnknownKeysParam = UnknownKeysParam, Catchall extends ZodTypeAny = ZodTypeAny> {
|
|
11
11
|
zod2x(this: ZodObject<T, UnknownKeys, Catchall>, typeName: string): this;
|
|
12
|
-
zod2x(this: ZodObject<T, UnknownKeys, Catchall>, opt: Zod2xMetadata): this;
|
|
12
|
+
zod2x(this: ZodObject<T, UnknownKeys, Catchall>, opt: Pick<Zod2xMetadata, "typeName">): this;
|
|
13
13
|
}
|
|
14
14
|
interface ZodEnum<T extends [string, ...string[]]> {
|
|
15
15
|
zod2x(this: ZodEnum<T>, typeName: string): this;
|
|
16
|
-
zod2x(this: ZodEnum<T>, opt: Zod2xMetadata): this;
|
|
16
|
+
zod2x(this: ZodEnum<T>, opt: Pick<Zod2xMetadata, "typeName">): this;
|
|
17
17
|
}
|
|
18
18
|
interface ZodNativeEnum<T extends EnumLike = EnumLike> {
|
|
19
19
|
zod2x(this: ZodNativeEnum<T>, typeName: string): this;
|
|
20
|
-
zod2x(this: ZodNativeEnum<T>, opt: Zod2xMetadata): this;
|
|
20
|
+
zod2x(this: ZodNativeEnum<T>, opt: Pick<Zod2xMetadata, "typeName">): this;
|
|
21
21
|
}
|
|
22
22
|
interface ZodDiscriminatedUnion<Discriminator extends string, Options extends z.ZodDiscriminatedUnionOption<Discriminator>[]> {
|
|
23
23
|
zod2x(this: ZodDiscriminatedUnion<Discriminator, Options>, typeName: string): this;
|
|
24
|
-
zod2x(this: ZodDiscriminatedUnion<Discriminator, Options>, opt: Zod2xMetadata): this;
|
|
24
|
+
zod2x(this: ZodDiscriminatedUnion<Discriminator, Options>, opt: Pick<Zod2xMetadata, "typeName">): this;
|
|
25
25
|
}
|
|
26
26
|
interface ZodUnion<T extends ZodUnionOptions> {
|
|
27
27
|
zod2x(this: ZodUnion<ZodUnionOptions>, typeName: string): this;
|
|
28
|
-
zod2x(this: ZodUnion<ZodUnionOptions>, opt: Zod2xMetadata): this;
|
|
28
|
+
zod2x(this: ZodUnion<ZodUnionOptions>, opt: Pick<Zod2xMetadata, "typeName">): this;
|
|
29
29
|
}
|
|
30
30
|
interface ZodIntersection<T extends ZodTypeAny, U extends ZodTypeAny> {
|
|
31
31
|
zod2x(this: ZodIntersection<T, U>, typeName: string): this;
|
|
32
|
-
zod2x(this: ZodIntersection<T, U>, opt: Zod2xMetadata): this;
|
|
32
|
+
zod2x(this: ZodIntersection<T, U>, opt: Pick<Zod2xMetadata, "typeName">): this;
|
|
33
|
+
}
|
|
34
|
+
interface ZodLiteral<T extends ZodTypeAny> {
|
|
35
|
+
zod2x(this: ZodLiteral<T>, parentEnum: ZodNativeEnum | ZodEnum<any>): this;
|
|
36
|
+
zod2x(this: ZodLiteral<T>, opt: Pick<Zod2xMetadata, "parentEnum">): this;
|
|
33
37
|
}
|
|
34
38
|
}
|
|
35
39
|
export declare function extendZod(zod: typeof z): void;
|
package/dist/lib/zod_ext.js
CHANGED
|
@@ -25,4 +25,11 @@ function extendZod(zod) {
|
|
|
25
25
|
if (typeof zod.ZodIntersection.prototype.zod2x === "undefined") {
|
|
26
26
|
zod.ZodIntersection.prototype.zod2x = getZod2XConstructor();
|
|
27
27
|
}
|
|
28
|
+
if (typeof zod.ZodLiteral.prototype.zod2x === "undefined") {
|
|
29
|
+
zod.ZodLiteral.prototype.zod2x = function (opt) {
|
|
30
|
+
return new this.constructor(Object.assign(Object.assign({}, this._def), { zod2x: opt instanceof zod.ZodEnum || opt instanceof zod.ZodNativeEnum
|
|
31
|
+
? { parentEnum: opt }
|
|
32
|
+
: opt }));
|
|
33
|
+
};
|
|
34
|
+
}
|
|
28
35
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare function getNlohmannOptionalHelper(indent: number, useBoost
|
|
1
|
+
export declare function getNlohmannOptionalHelper(indent: number, includeNulls: boolean, useBoost: boolean, namespace: string): string[];
|
|
@@ -1,11 +1,33 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getNlohmannOptionalHelper = getNlohmannOptionalHelper;
|
|
4
|
-
function getNlohmannOptionalHelper(indent, useBoost) {
|
|
4
|
+
function getNlohmannOptionalHelper(indent, includeNulls, useBoost, namespace) {
|
|
5
5
|
const optType = useBoost ? "boost::optional" : "std::optional";
|
|
6
|
+
const setOpt = includeNulls
|
|
7
|
+
? [
|
|
8
|
+
`template <typename T>`,
|
|
9
|
+
`void set_opt(json& j, const std::string& key, const ${optType}<T>& opt) {`,
|
|
10
|
+
`${" ".repeat(indent)}if (opt) {`,
|
|
11
|
+
`${" ".repeat(indent * 2)}j[key] = *opt;`,
|
|
12
|
+
`${" ".repeat(indent)}}`,
|
|
13
|
+
`${" ".repeat(indent)}else {`,
|
|
14
|
+
`${" ".repeat(indent * 2)}j[key] = nullptr;`,
|
|
15
|
+
`${" ".repeat(indent)}}`,
|
|
16
|
+
`}`,
|
|
17
|
+
`#endif\n`,
|
|
18
|
+
]
|
|
19
|
+
: [
|
|
20
|
+
`template <typename T>`,
|
|
21
|
+
`void set_opt(json& j, const std::string& key, const ${optType}<T>& opt) {`,
|
|
22
|
+
`${" ".repeat(indent)}if (opt) {`,
|
|
23
|
+
`${" ".repeat(indent * 2)}j[key] = *opt;`,
|
|
24
|
+
`${" ".repeat(indent)}}`,
|
|
25
|
+
`}`,
|
|
26
|
+
`#endif\n`,
|
|
27
|
+
];
|
|
6
28
|
return [
|
|
7
|
-
|
|
8
|
-
|
|
29
|
+
`#ifndef NLOHMANN_OPTIONAL_HELPER_${namespace}`,
|
|
30
|
+
`#define NLOHMANN_OPTIONAL_HELPER_${namespace}`,
|
|
9
31
|
"template <typename T>",
|
|
10
32
|
`${optType}<T> get_opt(const json& j, const std::string& key) {`,
|
|
11
33
|
`${" ".repeat(indent)}auto it = j.find(key);`,
|
|
@@ -14,12 +36,6 @@ function getNlohmannOptionalHelper(indent, useBoost) {
|
|
|
14
36
|
`${" ".repeat(indent)}}`,
|
|
15
37
|
`${" ".repeat(indent)}return ${optType}<T>();`,
|
|
16
38
|
`}\n`,
|
|
17
|
-
|
|
18
|
-
`void set_opt(json& j, const std::string& key, const ${optType}<T>& opt) {`,
|
|
19
|
-
`${" ".repeat(indent)}if (opt) {`,
|
|
20
|
-
`${" ".repeat(indent * 2)}j[key] = *opt;`,
|
|
21
|
-
`${" ".repeat(indent)}}`,
|
|
22
|
-
`}`,
|
|
23
|
-
`#endif\n`,
|
|
39
|
+
...setOpt,
|
|
24
40
|
];
|
|
25
41
|
}
|
|
@@ -32,7 +32,7 @@ export declare class Zod2Cpp extends Zod2X<IZod2CppOpt> {
|
|
|
32
32
|
max?: number;
|
|
33
33
|
}) => string;
|
|
34
34
|
protected getArrayType(arrayType: string, arrayDeep: number): string;
|
|
35
|
-
protected getLiteralStringType(value: string | number): string;
|
|
35
|
+
protected getLiteralStringType(value: string | number, parentEnumNameKey?: [string, string]): string;
|
|
36
36
|
protected getMapType(keyType: string, valueType: string): string;
|
|
37
37
|
protected getRecordType(keyType: string, valueType: string): string;
|
|
38
38
|
protected _getOptional(type: string): string;
|
|
@@ -83,8 +83,8 @@ class Zod2Cpp extends core_1.Zod2X {
|
|
|
83
83
|
this.imports.add(this.lib.nlohmann);
|
|
84
84
|
this.output.push("");
|
|
85
85
|
this.output.push(`namespace ${this.opt.namespace} {`);
|
|
86
|
-
if (this.imports.has(this.lib.optional)
|
|
87
|
-
this.serializers.unshift(...(0, nlohmann_1.getNlohmannOptionalHelper)(this.opt.indent, this.useBoost));
|
|
86
|
+
if (this.imports.has(this.lib.optional)) {
|
|
87
|
+
this.serializers.unshift(...(0, nlohmann_1.getNlohmannOptionalHelper)(this.opt.indent, this.opt.includeNulls === true, this.useBoost, this.opt.namespace));
|
|
88
88
|
}
|
|
89
89
|
this.serializers = this.serializers.map((i) => `${this.indent[1]}${i}`);
|
|
90
90
|
this.output.push(...this.serializers);
|
|
@@ -102,13 +102,14 @@ class Zod2Cpp extends core_1.Zod2X {
|
|
|
102
102
|
}
|
|
103
103
|
return output;
|
|
104
104
|
}
|
|
105
|
-
getLiteralStringType(value) {
|
|
106
|
-
|
|
105
|
+
getLiteralStringType(value, parentEnumNameKey) {
|
|
106
|
+
var _a;
|
|
107
|
+
return ((_a = parentEnumNameKey === null || parentEnumNameKey === void 0 ? void 0 : parentEnumNameKey[0]) !== null && _a !== void 0 ? _a : (isNaN(Number(value))
|
|
107
108
|
? this.getStringType()
|
|
108
109
|
: this.getNumberType(Number.isInteger(value), {
|
|
109
110
|
min: value,
|
|
110
111
|
max: value,
|
|
111
|
-
});
|
|
112
|
+
})));
|
|
112
113
|
}
|
|
113
114
|
getMapType(keyType, valueType) {
|
|
114
115
|
this.imports.add(this.lib.map);
|
|
@@ -261,7 +262,7 @@ class Zod2Cpp extends core_1.Zod2X {
|
|
|
261
262
|
_createStructSerializer(parent, childs) {
|
|
262
263
|
this._push0(this.serializers, `inline void to_json(json& j, const ${parent}& x) {`);
|
|
263
264
|
childs.forEach((i) => {
|
|
264
|
-
if (i.required
|
|
265
|
+
if (i.required) {
|
|
265
266
|
this._push1(this.serializers, `j["${i.origName}"] = x.${i.snakeName};`);
|
|
266
267
|
}
|
|
267
268
|
else {
|
|
@@ -285,7 +286,7 @@ class Zod2Cpp extends core_1.Zod2X {
|
|
|
285
286
|
_createClassSerializer(parent, childs) {
|
|
286
287
|
this._push0(this.serializers, `inline void to_json(json& j, const ${parent}& x) {`);
|
|
287
288
|
childs.forEach((i) => {
|
|
288
|
-
if (i.required
|
|
289
|
+
if (i.required) {
|
|
289
290
|
this._push1(this.serializers, `j["${i.origName}"] = x.get_${i.snakeName}();`);
|
|
290
291
|
}
|
|
291
292
|
else {
|
|
@@ -17,7 +17,7 @@ export declare class Zod2Ts extends Zod2X<IZod2TsOpt> {
|
|
|
17
17
|
protected getIntersectionType: (itemsType: string[]) => string;
|
|
18
18
|
protected getNumberType: () => string;
|
|
19
19
|
protected getArrayType(arrayType: string, arrayDeep: number): string;
|
|
20
|
-
protected getLiteralStringType(value: string | number): string | number;
|
|
20
|
+
protected getLiteralStringType(value: string | number, parentEnumNameKey?: [string, string]): string | number;
|
|
21
21
|
protected getMapType(keyType: string, valueType: string): string;
|
|
22
22
|
protected getRecordType(keyType: string, valueType: string): string;
|
|
23
23
|
protected transpileEnum(data: (ASTEnum | ASTNativeEnum) & ASTCommon): void;
|
|
@@ -39,8 +39,12 @@ class Zod2Ts extends core_1.Zod2X {
|
|
|
39
39
|
}
|
|
40
40
|
return output;
|
|
41
41
|
}
|
|
42
|
-
getLiteralStringType(value) {
|
|
43
|
-
return
|
|
42
|
+
getLiteralStringType(value, parentEnumNameKey) {
|
|
43
|
+
return parentEnumNameKey
|
|
44
|
+
? `${parentEnumNameKey[0]}.${parentEnumNameKey[1]}`
|
|
45
|
+
: isNaN(Number(value))
|
|
46
|
+
? `"${value}"`
|
|
47
|
+
: value;
|
|
44
48
|
}
|
|
45
49
|
getMapType(keyType, valueType) {
|
|
46
50
|
return `Map<${keyType}, ${valueType}>`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zod-to-x",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "Multi language types generation from Zod schemas.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"files": [
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
"build": "tsc && tsc-alias",
|
|
11
11
|
"format:check": "prettier --check .",
|
|
12
12
|
"test": "jest",
|
|
13
|
+
"test:cpp": "bash ./test/test_zod2cpp/test_cpp.sh",
|
|
13
14
|
"ts-run": "ts-node -r tsconfig-paths/register",
|
|
14
15
|
"prepare": "husky"
|
|
15
16
|
},
|