zod-to-x 1.2.1 → 1.3.0

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 CHANGED
@@ -7,9 +7,11 @@
7
7
  - [Why use `@zod-to-x`](#why-use-zod-to-x)
8
8
  - [Installation](#installation)
9
9
  - [Quick start](#quick-start)
10
+ - [Intersections and Unions](#intersections-and-unions)
10
11
  - [Supported output languages](#supported-output-languages)
11
12
  - [Mapping of supported Zod Types](#mapping-of-supported-zod-types)
12
13
  - [Additional utils](#additional-utils)
14
+ - [Changelog](#changelog)
13
15
 
14
16
 
15
17
 
@@ -17,7 +19,7 @@
17
19
  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
20
 
19
21
  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)
22
+ 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
23
 
22
24
  2. **Multi-Language Compatibility**
23
25
  Generate data models for TypeScript, Protobuf V3 and C++ (with languages like Golang on the roadmap). No more manually rewriting models for different platforms.
@@ -26,14 +28,14 @@ Generate data models for TypeScript, Protobuf V3 and C++ (with languages like Go
26
28
  Automate the transpilation of data models to save time, reduce errors, and let your team focus on business logic instead of boilerplate code.
27
29
 
28
30
 
29
-
30
31
  ## Installation
31
- ### 1) Install [`@zod-to-x`](https://github.com/rroumenov/zod-to-x) and [`@zod`]((https://github.com/colinhacks/zod)) dependency.
32
+ ### 1) Install [`@zod-to-x`](https://github.com/rroumenov/zod-to-x) and [`@zod(*)`](https://github.com/colinhacks/zod) dependency.
32
33
  ```bash
33
- npm install zod-to-x
34
+ npm install zod-to-x zod
34
35
  ```
36
+ (*) [`zod@3.22.0`](https://www.npmjs.com/package/zod/v/3.22.0) version or greather is required.
35
37
 
36
- ### 2) Extend Zod using the `extendZod` method after the first [`@zod`]((https://github.com/colinhacks/zod)) import:
38
+ ### 2) Extend Zod using the `extendZod` method after the first [`@zod`](https://github.com/colinhacks/zod) import:
37
39
  ```ts
38
40
  import { z } from "zod";
39
41
  import { extendZod } from "zod-to-x";
@@ -115,6 +117,124 @@ Example of supported schemas with its outputs can be found in the `test` folder:
115
117
 
116
118
 
117
119
 
120
+ ## Intersections and Unions
121
+ Starting from `v1.3.0`, a best practices helper is enabled by default when handling data intersections and unions:
122
+ - Intersections and Unions can only be performed between ZodObject schemas.
123
+ - Discriminant unions shall be used instead of Unions.
124
+
125
+ These rules help ensure that each data model follows the single responsibility principle. Otherwise, an error will be thrown when building an `ASTNode`.
126
+
127
+ **NOTE**: You can disable these rules at your own risk by setting the `strict` flag to `false` when building the `ASTNode` data model. However, any unexpected behavior or issues resulting from this will not be supported.
128
+
129
+ ### Expected outputs
130
+ - **For Intersections**: whenever possible, an intersection is transpiled into a struct/class that inherits from the intersected data models. Otherwise, a new struct/class is created, where attributes are the result of merging the intersected data models. Any shared key is overridden by the last matching type.
131
+ ```ts
132
+ const DataA = z.object({ keyA: z.string(), keyC: z.string() }).zod2x("DataA");
133
+ const DataB = z.object({ keyB: z.string(), keyC: z.number() }).zod2x("DataB");
134
+ const Intersection = z.intersection(DataA, DataB).zod2x("Intersection");
135
+
136
+ // C++ case (with inheritance)
137
+ // struct Intersection : public DataA, public DataB {
138
+ // // Intersection fields are inherited from base structs.
139
+ // };
140
+
141
+ // Typescript case (with attribute merging)
142
+ // class Intersection {
143
+ // keyA: string;
144
+ // keyB: string;
145
+ // keyC: number; // Shared key overriden using the last type.
146
+ // };
147
+ ```
148
+ - **For Unions**: whenever possible, a union is transpiled into a variant type composed of the united data models. Otherwise, a new struct/class is created, where attributes are the result of merging the intersected data models. Any common key is preserved as is (if only its requirement differs, it is changed to optional). Other keys are also set as optional.
149
+ ```ts
150
+ const DataA = z.object({ keyA: z.string(), keyD: z.string() }).zod2x("DataA");
151
+ const DataB = z.object({ keyB: z.string(), keyD: z.string() }).zod2x("DataB");
152
+ const Intersection = z.intersection(DataA, DataB).zod2x("Intersection");
153
+
154
+ // C++ case (with variant type)
155
+ // using Intersection = std::variant<DataA, DataB>;
156
+
157
+ // Typescript case (with attributes merge)
158
+ // class Intersection {
159
+ // keyA?: string; // Different keys are set as optional
160
+ // keyB?: string;
161
+ // keyD: number; // Shared key preserved as is.
162
+ // };
163
+ ```
164
+
165
+
166
+
167
+ ### Tips for discriminated unions
168
+ To enhance data modeling and the serialization/deserialization of a discriminated union type, two key steps should be considered:
169
+ - Using `ZodEnum` or `ZodNativeEnum` the define the discriminator key options.
170
+ - Using `ZodLiteral` to define the specific value of the discriminator key.
171
+
172
+ Example of discriminant definition:
173
+ ```ts
174
+ // Define message types
175
+ export const MsgType = z.enum(["TypeA", "TypeB"]).zod2x("MsgType");
176
+
177
+ // Define different message structures based on the 'msgType' value.
178
+ const MessageA = z
179
+ .object({
180
+ key: z.string(),
181
+
182
+ // Assign the type using the corresponding MsgType value and link it with 'zod2x'.
183
+ msgType: z.literal(MsgType.Values.TypeA).zod2x(MsgType),
184
+ })
185
+ .zod2x("MessageA");
186
+
187
+ const MessageB = z
188
+ .object({
189
+ otherKey: z.string(),
190
+
191
+ // Same process as MessageA.
192
+ msgType: z.literal(MsgType.Values.TypeB).zod2x(MsgType),
193
+ })
194
+ .zod2x("MessageB");
195
+
196
+ // Define the main Message type using ZodDiscriminatedUnion.
197
+ export const Message = z
198
+ .discriminatedUnion("msgType", [MessageA, MessageB])
199
+ .zod2x("Message");
200
+ ```
201
+
202
+ Example of C++ output:
203
+ ```cpp
204
+ // Discriminated union with direct serialization/deserialization
205
+ inline void from_json(const json& j, Message& x) {
206
+ const auto& k = j.at("msgType").get<std::string>();
207
+ if (k == "TypeA") {
208
+ x = j.get<MessageA>();
209
+ }
210
+ else if (k == "TypeB") {
211
+ x = j.get<MessageB>();
212
+ }
213
+ else {
214
+ throw std::runtime_error("Failed to deserialize Message: unknown format");
215
+ }
216
+ }
217
+
218
+
219
+
220
+ // Using a regular union or a discriminated union without the above approach:
221
+ // Fallback to try-catch for serialization/deserialization
222
+ inline void from_json(const json& j, Message& x) {
223
+ try {
224
+ x = j.get<MessageA>();
225
+ return;
226
+ } catch (const std::exception&) {
227
+ }
228
+ try {
229
+ x = j.get<MessageB>();
230
+ return;
231
+ } catch (const std::exception&) {
232
+ throw std::runtime_error("Failed to deserialize Message: unknown format");
233
+ }
234
+ }
235
+ ```
236
+
237
+
118
238
  ## Supported output languages
119
239
  Common options:
120
240
  - **header**: Text to add as a comment at the beginning of the output.
@@ -122,6 +242,10 @@ Common options:
122
242
  - **includeComments**: Determines whether to include comments in the transpiled code. Defaults to `true`.
123
243
  - **skipDiscriminatorNodes**: prevents the inclusion of `ZodEnum` or `ZodNativeEnum` schemas that are used solely as discriminator keys in a `ZodDiscriminatedUnion`. Defaults to `false`.
124
244
 
245
+ ### 0) ASTNode
246
+ - Options:
247
+ - **strict**: When true, it will throw an error if a bad data modeling practice is detected. Default is `true`.
248
+
125
249
  ### 1) Typescript
126
250
  - Options:
127
251
  - **outType**: Output transpilation using Typescript interfaces or Classes. Defaults to `interface`.
@@ -132,7 +256,6 @@ Common options:
132
256
  - **useCamelCase**: Protobuf follows the snake_case convention for field names, but camelCase can also be used. Defaults to `false`.
133
257
 
134
258
  - Limitations:
135
- - `oneof` fields support only unions of `ZodObject` schemas.
136
259
  - `ZodTuple` is supported only for items of the same type.
137
260
 
138
261
 
@@ -144,9 +267,6 @@ Common options:
144
267
  - **outType**: Output transpilation using C++ Structs or Classes. Defaults to `struct`.
145
268
  - **skipSerialize**: Remove Nlohmann JSON serialization/deserialization. Defaults to `false`.
146
269
 
147
- - Limitations:
148
- - `ZodIntersection` is supported only for intersection of `ZodObject` schemas.
149
-
150
270
 
151
271
 
152
272
  ## Mapping of supported Zod Types
@@ -315,4 +435,7 @@ console.log(userJsonSchema);
315
435
  // },
316
436
  // "$schema": "http://json-schema.org/draft-07/schema#"
317
437
  // }
318
- ```
438
+ ```
439
+
440
+ ## Changelog
441
+ View the changelog at [Releases](https://github.com/rroumenov/zod-to-x/releases).
@@ -1,12 +1,20 @@
1
1
  import { ZodObject, ZodRawShape } from "zod";
2
2
  import { ASTNodes } from "./ast_types";
3
+ interface IZod2AstOpt {
4
+ strict?: boolean;
5
+ }
3
6
  export declare class Zod2Ast {
4
7
  private nodes;
5
8
  private discriminatorNodes;
6
9
  private lazyPointers;
7
- constructor();
10
+ private warnings;
11
+ private opt;
12
+ constructor(opt?: IZod2AstOpt);
8
13
  private _createDefinition;
9
14
  private _getEnumValues;
10
- private zodToAST;
15
+ private _intersectAstNodes;
16
+ private _unionAstNodes;
17
+ private _zodToAST;
11
18
  build<T extends ZodRawShape>(schema: ZodObject<T>): ASTNodes;
12
19
  }
20
+ export {};
@@ -2,11 +2,18 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Zod2Ast = void 0;
4
4
  const zod_1 = require("zod");
5
+ const logger_1 = require("../utils/logger");
6
+ const errors_1 = require("./errors");
5
7
  class Zod2Ast {
6
- constructor() {
8
+ constructor(opt = {}) {
9
+ var _a;
7
10
  this.nodes = new Map();
8
11
  this.discriminatorNodes = new Map();
9
12
  this.lazyPointers = [];
13
+ this.warnings = [];
14
+ this.opt = {
15
+ strict: (_a = opt.strict) !== null && _a !== void 0 ? _a : true,
16
+ };
10
17
  }
11
18
  _createDefinition(ref, refType, discriminantValue) {
12
19
  return { type: "definition", reference: ref, referenceType: refType, discriminantValue };
@@ -27,8 +34,53 @@ class Zod2Ast {
27
34
  });
28
35
  }
29
36
  }
30
- zodToAST(schema, opt) {
31
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
37
+ _intersectAstNodes(left, right) {
38
+ const leftData = this.nodes.get(left.reference);
39
+ const rightData = this.nodes.get(right.reference);
40
+ return {
41
+ properties: Object.assign(Object.assign({}, leftData.properties), rightData.properties),
42
+ };
43
+ }
44
+ _unionAstNodes(options) {
45
+ const data = options.map((i) => this.nodes.get(i.reference));
46
+ return {
47
+ properties: data.reduce((acc, i, j) => {
48
+ var _a, _b;
49
+ for (const key in i.properties) {
50
+ if (acc[key]) {
51
+ acc[key] = structuredClone(acc[key]);
52
+ if (acc[key].type !== i.properties[key].type) {
53
+ this.warnings.push(`Merging properties with different types: ${acc[key].type} ` +
54
+ `(from ${(_a = data[j - 1]) === null || _a === void 0 ? void 0 : _a.name}) and ${i.properties[key].type} ` +
55
+ `(from ${i.name})`);
56
+ acc[key].type = i.properties[key].type;
57
+ }
58
+ if (acc[key].arrayDimension !== i.properties[key].arrayDimension) {
59
+ this.warnings.push(`Merging properties with different array dimensions: ` +
60
+ `${acc[key].arrayDimension} (from ${(_b = data[j - 1]) === null || _b === void 0 ? void 0 : _b.name}) and ` +
61
+ `${i.properties[key].arrayDimension} (from ${i.name})`);
62
+ acc[key].arrayDimension = Math.max(acc[key].arrayDimension || 0, i.properties[key].arrayDimension || 0);
63
+ }
64
+ if (acc[key].isNullable !== i.properties[key].isNullable) {
65
+ acc[key].isNullable = true;
66
+ }
67
+ if (acc[key].isOptional !== i.properties[key].isOptional) {
68
+ acc[key].isOptional = true;
69
+ }
70
+ if (i.properties[key].description) {
71
+ acc[key].description = i.properties[key].description;
72
+ }
73
+ }
74
+ else {
75
+ acc[key] = i.properties[key];
76
+ }
77
+ }
78
+ return acc;
79
+ }, {}),
80
+ };
81
+ }
82
+ _zodToAST(schema, opt) {
83
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
32
84
  const def = schema._def;
33
85
  if (schema instanceof zod_1.ZodString) {
34
86
  return {
@@ -67,15 +119,19 @@ class Zod2Ast {
67
119
  };
68
120
  }
69
121
  else if (schema instanceof zod_1.ZodNullable) {
70
- const subSchema = this.zodToAST(def.innerType);
122
+ const subSchema = this._zodToAST(def.innerType);
71
123
  return Object.assign(Object.assign({ isNullable: true }, subSchema), { description: schema.description || subSchema.description });
72
124
  }
73
125
  else if (schema instanceof zod_1.ZodOptional) {
74
- const subSchema = this.zodToAST(def.innerType);
126
+ const subSchema = this._zodToAST(def.innerType);
75
127
  return Object.assign(Object.assign({ isOptional: true }, subSchema), { description: schema.description || subSchema.description });
76
128
  }
129
+ else if (schema instanceof zod_1.ZodDefault) {
130
+ const subSchema = this._zodToAST(def.innerType);
131
+ return Object.assign(Object.assign({}, subSchema), { description: schema.description || subSchema.description });
132
+ }
77
133
  else if (schema instanceof zod_1.ZodArray) {
78
- const subSchema = this.zodToAST(def.type);
134
+ const subSchema = this._zodToAST(def.type);
79
135
  return Object.assign(Object.assign({}, subSchema), { description: schema.description || subSchema.description, arrayDimension: Number.isInteger(subSchema.arrayDimension)
80
136
  ? ++subSchema.arrayDimension
81
137
  : 1 });
@@ -83,7 +139,7 @@ class Zod2Ast {
83
139
  else if (schema instanceof zod_1.ZodSet) {
84
140
  return {
85
141
  type: zod_1.ZodFirstPartyTypeKind.ZodSet,
86
- value: this.zodToAST(def.valueType),
142
+ value: this._zodToAST(def.valueType),
87
143
  description: schema.description,
88
144
  };
89
145
  }
@@ -93,7 +149,7 @@ class Zod2Ast {
93
149
  if ((_c = def.zod2x) === null || _c === void 0 ? void 0 : _c.parentEnum) {
94
150
  parentEnumName = (_e = (_d = def.zod2x) === null || _d === void 0 ? void 0 : _d.parentEnum._def.zod2x) === null || _e === void 0 ? void 0 : _e.typeName;
95
151
  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 });
152
+ this._zodToAST((_h = def.zod2x) === null || _h === void 0 ? void 0 : _h.parentEnum, { isInjectedEnum: true });
97
153
  }
98
154
  return {
99
155
  type: zod_1.ZodFirstPartyTypeKind.ZodLiteral,
@@ -106,8 +162,8 @@ class Zod2Ast {
106
162
  else if (schema instanceof zod_1.ZodRecord) {
107
163
  return {
108
164
  type: zod_1.ZodFirstPartyTypeKind.ZodRecord,
109
- key: this.zodToAST(def.keyType),
110
- value: this.zodToAST(def.valueType),
165
+ key: this._zodToAST(def.keyType),
166
+ value: this._zodToAST(def.valueType),
111
167
  description: schema.description,
112
168
  };
113
169
  }
@@ -120,23 +176,27 @@ class Zod2Ast {
120
176
  else if (schema instanceof zod_1.ZodTuple) {
121
177
  return {
122
178
  type: zod_1.ZodFirstPartyTypeKind.ZodTuple,
123
- items: def.items.map(this.zodToAST.bind(this)),
179
+ items: def.items.map(this._zodToAST.bind(this)),
124
180
  description: schema.description,
125
181
  };
126
182
  }
127
183
  else if (schema instanceof zod_1.ZodMap) {
128
184
  return {
129
185
  type: zod_1.ZodFirstPartyTypeKind.ZodMap,
130
- key: this.zodToAST(def.keyType),
131
- value: this.zodToAST(def.valueType),
186
+ key: this._zodToAST(def.keyType),
187
+ value: this._zodToAST(def.valueType),
132
188
  description: schema.description,
133
189
  };
134
190
  }
135
191
  else if (schema instanceof zod_1.ZodNativeEnum || schema instanceof zod_1.ZodEnum) {
136
- let name = (_j = def.zod2x) === null || _j === void 0 ? void 0 : _j.typeName;
192
+ const name = (_j = def.zod2x) === null || _j === void 0 ? void 0 : _j.typeName;
193
+ if (!name) {
194
+ throw new errors_1.AstTypeNameDefinitionError("ZodEnum/ZodNativeEnum type must have a typeName. " +
195
+ "Use zod2x method to provide one.");
196
+ }
137
197
  const item = {
138
198
  type: def.typeName,
139
- name: (_k = def.zod2x) === null || _k === void 0 ? void 0 : _k.typeName,
199
+ name,
140
200
  values: this._getEnumValues(schema),
141
201
  description: def.description,
142
202
  };
@@ -156,16 +216,19 @@ class Zod2Ast {
156
216
  return this._createDefinition(name, def.typeName);
157
217
  }
158
218
  else if (schema instanceof zod_1.ZodObject) {
159
- let name = (_l = def.zod2x) === null || _l === void 0 ? void 0 : _l.typeName;
219
+ const name = (_k = def.zod2x) === null || _k === void 0 ? void 0 : _k.typeName;
160
220
  let discriminantValue = undefined;
221
+ if (!name) {
222
+ throw new errors_1.AstTypeNameDefinitionError("ZodObject type must have a typeName. Use zod2x method to provide one.");
223
+ }
161
224
  if (!this.nodes.has(name)) {
162
225
  const properties = {};
163
226
  for (const key in def.shape()) {
164
- properties[key] = this.zodToAST(def.shape()[key]);
227
+ properties[key] = this._zodToAST(def.shape()[key]);
165
228
  }
166
229
  this.nodes.set(name, {
167
230
  type: zod_1.ZodFirstPartyTypeKind.ZodObject,
168
- name: (_m = def.zod2x) === null || _m === void 0 ? void 0 : _m.typeName,
231
+ name,
169
232
  properties,
170
233
  description: schema.description,
171
234
  });
@@ -185,14 +248,34 @@ class Zod2Ast {
185
248
  return this._createDefinition(name, def.typeName, discriminantValue);
186
249
  }
187
250
  else if (schema instanceof zod_1.ZodUnion || schema instanceof zod_1.ZodDiscriminatedUnion) {
188
- let name = (_o = def.zod2x) === null || _o === void 0 ? void 0 : _o.typeName;
251
+ const name = (_l = def.zod2x) === null || _l === void 0 ? void 0 : _l.typeName;
252
+ if (!name) {
253
+ throw new errors_1.AstTypeNameDefinitionError("ZodUnion/ZodDiscriminatedUnion type must have a typeName. " +
254
+ "Use zod2x method to provide one.");
255
+ }
189
256
  const item = {
190
257
  type: def.typeName,
191
- name: (_p = def.zod2x) === null || _p === void 0 ? void 0 : _p.typeName,
192
- options: def.options.map((i) => this.zodToAST(i, { discriminantKey: def.discriminator })),
258
+ name,
259
+ options: def.options.map((i) => this._zodToAST(i, { discriminantKey: def.discriminator })),
193
260
  description: schema.description,
194
261
  discriminantKey: def.discriminator,
195
262
  };
263
+ if (!def.options.every((i) => i instanceof zod_1.ZodObject)) {
264
+ this.warnings.push("Union of non-object types is a bad data modeling practice, " +
265
+ "and could lead to unexpected results.");
266
+ }
267
+ else if (schema instanceof zod_1.ZodUnion) {
268
+ this.warnings.push("Using ZodUnion is a bad data modeling practice. " +
269
+ "Use ZodDiscriminatedUnion instead.");
270
+ item.newObject = {
271
+ name,
272
+ type: zod_1.ZodFirstPartyTypeKind.ZodObject,
273
+ properties: this._unionAstNodes(item.options).properties,
274
+ description: (schema.description ? `${schema.description} - ` : "") +
275
+ `Built from union of ` +
276
+ `${item.options.map((i) => i.reference).join(", ")}`,
277
+ };
278
+ }
196
279
  if (name && !this.nodes.has(name)) {
197
280
  this.nodes.set(name, item);
198
281
  return this._createDefinition(name, def.typeName);
@@ -200,28 +283,51 @@ class Zod2Ast {
200
283
  return item;
201
284
  }
202
285
  else if (schema instanceof zod_1.ZodIntersection) {
203
- let name = (_q = def.zod2x) === null || _q === void 0 ? void 0 : _q.typeName;
286
+ const name = (_m = def.zod2x) === null || _m === void 0 ? void 0 : _m.typeName;
287
+ if (!name) {
288
+ throw new errors_1.AstTypeNameDefinitionError("ZodIntersection type must have a typeName. Use zod2x method to provide one.");
289
+ }
204
290
  const item = {
205
291
  type: zod_1.ZodFirstPartyTypeKind.ZodIntersection,
206
- name: (_r = def.zod2x) === null || _r === void 0 ? void 0 : _r.typeName,
207
- left: this.zodToAST(def.left),
208
- right: this.zodToAST(def.right),
292
+ name,
293
+ left: this._zodToAST(def.left),
294
+ right: this._zodToAST(def.right),
209
295
  description: schema.description,
210
296
  };
297
+ if (def.left._def.typeName !== "ZodObject" || def.right._def.typeName !== "ZodObject") {
298
+ this.warnings.push("Intersection of non-object is a bad data modeling practice, " +
299
+ "and could lead to unexpected results.");
300
+ }
301
+ else {
302
+ item.newObject = {
303
+ type: zod_1.ZodFirstPartyTypeKind.ZodObject,
304
+ name,
305
+ properties: this._intersectAstNodes(item.left, item.right).properties,
306
+ description: (schema.description ? `${schema.description} - ` : "") +
307
+ `Built from intersection of ` +
308
+ `${item.left.reference} and ` +
309
+ `${item.right.reference}`,
310
+ };
311
+ }
211
312
  if (name && !this.nodes.has(name)) {
212
313
  this.nodes.set(name, item);
213
314
  return this._createDefinition(name, def.typeName);
214
315
  }
215
316
  return item;
216
317
  }
217
- else
218
- throw new Error(`Unsupported Zod type: ${schema}`);
318
+ else {
319
+ logger_1.log.warn(`Unsupported Zod type: ${JSON.stringify(schema)}`);
320
+ return {
321
+ type: zod_1.ZodFirstPartyTypeKind.ZodAny,
322
+ description: `Unsupported Zod type: ${schema._def.typeName}`,
323
+ };
324
+ }
219
325
  }
220
326
  build(schema) {
221
- this.zodToAST(schema);
327
+ this._zodToAST(schema);
222
328
  while (this.lazyPointers.length > 0) {
223
329
  const [pointer, schema] = this.lazyPointers.shift();
224
- const lazyResolve = this.zodToAST(schema);
330
+ const lazyResolve = this._zodToAST(schema);
225
331
  Object.keys(pointer).forEach((key) => {
226
332
  delete pointer[key];
227
333
  });
@@ -229,9 +335,13 @@ class Zod2Ast {
229
335
  pointer[key] = value;
230
336
  });
231
337
  }
338
+ if (this.opt.strict !== false && this.warnings.length > 0) {
339
+ throw new errors_1.AstNodeError(this.warnings.join("\n"));
340
+ }
232
341
  return {
233
342
  nodes: [...this.nodes.values()],
234
343
  discriminatorNodes: [...this.discriminatorNodes.values()],
344
+ warnings: this.warnings,
235
345
  };
236
346
  }
237
347
  }
@@ -1,4 +1,10 @@
1
1
  import { ZodFirstPartyTypeKind } from "zod";
2
+ export type ASTCommon = {
3
+ arrayDimension?: number;
4
+ description?: string;
5
+ isNullable?: boolean;
6
+ isOptional?: boolean;
7
+ };
2
8
  export type ASTLiteral = {
3
9
  type: ZodFirstPartyTypeKind.ZodLiteral;
4
10
  value: any;
@@ -50,6 +56,7 @@ export type ASTUnion = {
50
56
  type: ZodFirstPartyTypeKind.ZodUnion;
51
57
  name: string;
52
58
  options: ASTNode[];
59
+ newObject?: ASTCommon & ASTObject;
53
60
  };
54
61
  export type ASTDiscriminatedUnion = {
55
62
  type: ZodFirstPartyTypeKind.ZodDiscriminatedUnion;
@@ -62,12 +69,7 @@ export type ASTIntersection = {
62
69
  name: string;
63
70
  left: ASTNode;
64
71
  right: ASTNode;
65
- };
66
- export type ASTCommon = {
67
- arrayDimension?: number;
68
- description?: string;
69
- isNullable?: boolean;
70
- isOptional?: boolean;
72
+ newObject?: ASTCommon & ASTObject;
71
73
  };
72
74
  export type ASTDefintion = ASTCommon & {
73
75
  type: "definition";
@@ -91,4 +93,5 @@ export type TranspilerableTypes = ASTCommon & (ASTEnum | ASTNativeEnum | ASTObje
91
93
  export type ASTNodes = {
92
94
  nodes: TranspilerableTypes[];
93
95
  discriminatorNodes: TranspilerableTypes[];
96
+ warnings: string[];
94
97
  };
@@ -0,0 +1,9 @@
1
+ export declare class AstTypeNameDefinitionError extends Error {
2
+ constructor(message: string);
3
+ }
4
+ export declare class AstNodeError extends Error {
5
+ constructor(message: string);
6
+ }
7
+ export declare class NotTranspilerableTypeError extends Error {
8
+ constructor(message: string);
9
+ }
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NotTranspilerableTypeError = exports.AstNodeError = exports.AstTypeNameDefinitionError = void 0;
4
+ class AstTypeNameDefinitionError extends Error {
5
+ constructor(message) {
6
+ super(message);
7
+ this.name = "TypeNameDefinitionError";
8
+ }
9
+ }
10
+ exports.AstTypeNameDefinitionError = AstTypeNameDefinitionError;
11
+ class AstNodeError extends Error {
12
+ constructor(message) {
13
+ super(message);
14
+ this.name = "AstNodeError";
15
+ }
16
+ }
17
+ exports.AstNodeError = AstNodeError;
18
+ class NotTranspilerableTypeError extends Error {
19
+ constructor(message) {
20
+ super(message);
21
+ this.name = "NotTranspilerableTypeError";
22
+ }
23
+ }
24
+ exports.NotTranspilerableTypeError = NotTranspilerableTypeError;
@@ -1,3 +1,4 @@
1
1
  export { Zod2Ast } from "./ast_node";
2
2
  export * from "./ast_types";
3
3
  export { Zod2X, IZodToXOpt } from "./transpiler";
4
+ export * from "./errors";
@@ -20,3 +20,4 @@ Object.defineProperty(exports, "Zod2Ast", { enumerable: true, get: function () {
20
20
  __exportStar(require("./ast_types"), exports);
21
21
  var transpiler_1 = require("./transpiler");
22
22
  Object.defineProperty(exports, "Zod2X", { enumerable: true, get: function () { return transpiler_1.Zod2X; } });
23
+ __exportStar(require("./errors"), exports);
@@ -6,16 +6,12 @@ export interface IZodToXOpt extends Record<string, any> {
6
6
  includeComments?: boolean;
7
7
  skipDiscriminatorNodes?: boolean;
8
8
  }
9
- interface IInternalOpts {
10
- enableCompositeTypes: boolean;
11
- }
12
9
  export declare abstract class Zod2X<T extends IZodToXOpt> {
13
10
  protected output: string[];
14
11
  protected indent: TIndentationLevels;
15
12
  protected imports: Set<string>;
16
13
  protected opt: Partial<T>;
17
- private inOpt;
18
- protected constructor(inOpt: IInternalOpts, opt: Partial<T>);
14
+ protected constructor(opt: Partial<T>);
19
15
  protected abstract runBefore(): void;
20
16
  protected abstract runAfter(): void;
21
17
  protected abstract getComment(data: string, indent?: string): string;
@@ -39,15 +35,13 @@ export declare abstract class Zod2X<T extends IZodToXOpt> {
39
35
  protected abstract transpileStruct(data: ASTObject & ASTCommon): void;
40
36
  protected abstract transpileUnion(data: (ASTUnion | ASTDiscriminatedUnion) & ASTCommon): void;
41
37
  protected abstract transpileIntersection(data: ASTIntersection & ASTCommon): void;
42
- protected isTranspilerable(token: TranspilerableTypes): boolean | "";
38
+ protected isTranspilerable(token: TranspilerableTypes): token is (ASTCommon & ASTUnion) | (ASTCommon & ASTDiscriminatedUnion) | (ASTCommon & ASTIntersection) | (ASTCommon & ASTObject) | (ASTCommon & ASTEnum) | (ASTCommon & ASTNativeEnum);
43
39
  protected push0: (data: string) => number;
44
40
  protected push1: (data: string) => number;
45
41
  protected push2: (data: string) => number;
46
42
  protected push3: (data: string) => number;
47
43
  protected addComment(data?: string, indent?: string): void;
48
- private _checkCompositeFlag;
49
44
  protected getAttributeType(token: ASTNode | TranspilerableTypes): string;
50
45
  private _transpileItem;
51
46
  transpile(transpilerQueue: ASTNodes): string;
52
47
  }
53
- export {};
@@ -7,7 +7,7 @@ exports.Zod2X = void 0;
7
7
  const zod_1 = require("zod");
8
8
  const string_utils_1 = __importDefault(require("../utils/string_utils"));
9
9
  class Zod2X {
10
- constructor(inOpt, opt) {
10
+ constructor(opt) {
11
11
  this.push0 = (data) => this.output.push(`${this.indent[0]}${data}`);
12
12
  this.push1 = (data) => this.output.push(`${this.indent[1]}${data}`);
13
13
  this.push2 = (data) => this.output.push(`${this.indent[2]}${data}`);
@@ -16,28 +16,20 @@ class Zod2X {
16
16
  this.imports = new Set();
17
17
  this.indent = string_utils_1.default.getIndentationLevels(opt.indent || 4);
18
18
  this.opt = opt;
19
- this.inOpt = inOpt;
20
19
  }
21
20
  isTranspilerable(token) {
22
21
  return (token.type === zod_1.ZodFirstPartyTypeKind.ZodEnum ||
23
22
  token.type === zod_1.ZodFirstPartyTypeKind.ZodNativeEnum ||
24
23
  token.type === zod_1.ZodFirstPartyTypeKind.ZodObject ||
25
- (token.name &&
26
- (token.type === zod_1.ZodFirstPartyTypeKind.ZodUnion ||
27
- token.type === zod_1.ZodFirstPartyTypeKind.ZodDiscriminatedUnion ||
28
- token.type === zod_1.ZodFirstPartyTypeKind.ZodIntersection)));
24
+ token.type === zod_1.ZodFirstPartyTypeKind.ZodUnion ||
25
+ token.type === zod_1.ZodFirstPartyTypeKind.ZodDiscriminatedUnion ||
26
+ token.type === zod_1.ZodFirstPartyTypeKind.ZodIntersection);
29
27
  }
30
28
  addComment(data = "", indent = "") {
31
29
  if (data && this.opt.includeComments) {
32
30
  this.output.push(this.getComment(data, indent));
33
31
  }
34
32
  }
35
- _checkCompositeFlag() {
36
- if (!this.inOpt.enableCompositeTypes) {
37
- throw new Error(`Composite Types cannot be performed for this output Language. ` +
38
- `Add the missing 'typeName' to transpilerable schemas`);
39
- }
40
- }
41
33
  getAttributeType(token) {
42
34
  let varType = "";
43
35
  if (this.isTranspilerable(token)) {
@@ -87,19 +79,6 @@ class Zod2X {
87
79
  varType = this.getRecordType(key, value);
88
80
  }
89
81
  }
90
- else if (!token.name &&
91
- token.type === zod_1.ZodFirstPartyTypeKind.ZodIntersection) {
92
- this._checkCompositeFlag();
93
- const items = [token.left, token.right].map(this.getAttributeType.bind(this));
94
- varType = this.getIntersectionType(items);
95
- }
96
- else if (!token.name &&
97
- (token.type === zod_1.ZodFirstPartyTypeKind.ZodUnion ||
98
- token.type === zod_1.ZodFirstPartyTypeKind.ZodDiscriminatedUnion)) {
99
- this._checkCompositeFlag();
100
- const items = token.options.map(this.getAttributeType.bind(this));
101
- varType = this.getUnionType(items);
102
- }
103
82
  else {
104
83
  console.log(" # Unknown attribute equivalent for ---> ", token.type);
105
84
  }
@@ -19,7 +19,7 @@ declare module "zod" {
19
19
  zod2x(this: ZodNativeEnum<T>, typeName: string): this;
20
20
  zod2x(this: ZodNativeEnum<T>, opt: Pick<Zod2xMetadata, "typeName">): this;
21
21
  }
22
- interface ZodDiscriminatedUnion<Discriminator extends string, Options extends z.ZodDiscriminatedUnionOption<Discriminator>[]> {
22
+ interface ZodDiscriminatedUnion<Discriminator extends string, Options extends readonly z.ZodDiscriminatedUnionOption<Discriminator>[]> {
23
23
  zod2x(this: ZodDiscriminatedUnion<Discriminator, Options>, typeName: string): this;
24
24
  zod2x(this: ZodDiscriminatedUnion<Discriminator, Options>, opt: Pick<Zod2xMetadata, "typeName">): this;
25
25
  }
@@ -36,4 +36,4 @@ declare module "zod" {
36
36
  zod2x(this: ZodLiteral<T>, opt: Pick<Zod2xMetadata, "parentEnum">): this;
37
37
  }
38
38
  }
39
- export declare function extendZod(zod: typeof z): void;
39
+ export declare function extendZod(zod: any): void;
@@ -13,9 +13,7 @@ const nlohmann_1 = require("./nlohmann");
13
13
  const options_1 = require("./options");
14
14
  class Zod2Cpp extends core_1.Zod2X {
15
15
  constructor(opt = {}) {
16
- super({
17
- enableCompositeTypes: false,
18
- }, Object.assign(Object.assign({}, options_1.defaultOpts), opt));
16
+ super(Object.assign(Object.assign({}, options_1.defaultOpts), opt));
19
17
  this.getIntersectionType = () => {
20
18
  return "";
21
19
  };
@@ -144,7 +142,7 @@ class Zod2Cpp extends core_1.Zod2X {
144
142
  data.left.referenceType === zod_1.ZodFirstPartyTypeKind.ZodObject &&
145
143
  data.right.type === "definition" &&
146
144
  data.right.referenceType === zod_1.ZodFirstPartyTypeKind.ZodObject)) {
147
- throw new Error(`${data.name}: only intersection of ZodObjects is supported.`);
145
+ throw new core_1.NotTranspilerableTypeError(`${data.name}: only intersection of ZodObjects is supported.`);
148
146
  }
149
147
  const leftType = this.getAttributeType(data.left);
150
148
  const rightType = this.getAttributeType(data.right);
@@ -0,0 +1,6 @@
1
+ import { IZodToXOpt } from "../../core";
2
+ export interface IZod2ProtoV3Opt extends Omit<IZodToXOpt, "skipDiscriminatorNodes"> {
3
+ packageName?: string;
4
+ useCamelCase?: boolean;
5
+ }
6
+ export declare const defaultOpts: IZod2ProtoV3Opt;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defaultOpts = void 0;
4
+ exports.defaultOpts = {
5
+ includeComments: true,
6
+ indent: 4,
7
+ useCamelCase: false,
8
+ skipDiscriminatorNodes: true,
9
+ };
@@ -1,8 +1,5 @@
1
- import { ASTCommon, ASTDiscriminatedUnion, ASTEnum, ASTIntersection, ASTNativeEnum, ASTObject, ASTUnion, IZodToXOpt, Zod2X } from "../../core";
2
- interface IZod2ProtoV3Opt extends Omit<IZodToXOpt, "skipDiscriminatorNodes"> {
3
- packageName?: string;
4
- useCamelCase?: boolean;
5
- }
1
+ import { ASTCommon, ASTDiscriminatedUnion, ASTEnum, ASTIntersection, ASTNativeEnum, ASTObject, ASTUnion, Zod2X } from "../../core";
2
+ import { IZod2ProtoV3Opt } from "./options";
6
3
  export declare class Zod2ProtoV3 extends Zod2X<IZod2ProtoV3Opt> {
7
4
  constructor(opt?: IZod2ProtoV3Opt);
8
5
  protected getUnionType: () => string;
@@ -30,4 +27,3 @@ export declare class Zod2ProtoV3 extends Zod2X<IZod2ProtoV3Opt> {
30
27
  protected runAfter(): void;
31
28
  private _adaptField;
32
29
  }
33
- export {};
@@ -7,6 +7,7 @@ exports.Zod2ProtoV3 = void 0;
7
7
  const case_1 = __importDefault(require("case"));
8
8
  const core_1 = require("../../core");
9
9
  const number_limits_1 = require("../../utils/number_limits");
10
+ const options_1 = require("./options");
10
11
  const allowedKeyTypes = [
11
12
  "int32",
12
13
  "int64",
@@ -21,17 +22,9 @@ const allowedKeyTypes = [
21
22
  "bool",
22
23
  "string",
23
24
  ];
24
- const defaultOpts = {
25
- includeComments: true,
26
- indent: 4,
27
- useCamelCase: false,
28
- skipDiscriminatorNodes: true,
29
- };
30
25
  class Zod2ProtoV3 extends core_1.Zod2X {
31
26
  constructor(opt = {}) {
32
- super({
33
- enableCompositeTypes: true,
34
- }, Object.assign(Object.assign({}, defaultOpts), opt));
27
+ super(Object.assign(Object.assign({}, options_1.defaultOpts), opt));
35
28
  this.getUnionType = () => {
36
29
  return "";
37
30
  };
@@ -76,11 +69,11 @@ class Zod2ProtoV3 extends core_1.Zod2X {
76
69
  return this.getArrayType(itemsType[0], 1);
77
70
  }
78
71
  else {
79
- throw new Error("Protobuf v3 does not support mixed-type tuples. Consider defining a message type.");
72
+ throw new core_1.NotTranspilerableTypeError("Protobuf v3 does not support mixed-type tuples. Consider defining a message type.");
80
73
  }
81
74
  };
82
75
  this.getIntersectionType = (itemsType) => {
83
- throw new Error("Protobuf v3 does not support intersection types directly.");
76
+ throw new core_1.NotTranspilerableTypeError("Protobuf v3 does not support intersection types directly.");
84
77
  };
85
78
  }
86
79
  getArrayType(arrayType, arrayDeep) {
@@ -88,7 +81,7 @@ class Zod2ProtoV3 extends core_1.Zod2X {
88
81
  return `repeated ${arrayType}`;
89
82
  }
90
83
  else {
91
- throw new Error("Protobuf v3 does not support multidimensional arrays directly. " +
84
+ throw new core_1.NotTranspilerableTypeError("Protobuf v3 does not support multidimensional arrays directly. " +
92
85
  "You need to define nested message types for deeper arrays");
93
86
  }
94
87
  }
@@ -100,12 +93,12 @@ class Zod2ProtoV3 extends core_1.Zod2X {
100
93
  return this.getNumberType(Number.isInteger(value), { min: value, max: value });
101
94
  }
102
95
  else {
103
- throw new Error(`Protobuf v3 does not support Literals for this value type: ${value}`);
96
+ throw new core_1.NotTranspilerableTypeError(`Protobuf v3 does not support Literals for this value type: ${value}`);
104
97
  }
105
98
  }
106
99
  getMapType(keyType, valueType) {
107
100
  if (!allowedKeyTypes.includes(keyType)) {
108
- throw new Error(`Protobuf map keys must be an integral or string type, got '${keyType}'.`);
101
+ throw new core_1.NotTranspilerableTypeError(`Protobuf map keys must be an integral or string type, got '${keyType}'.`);
109
102
  }
110
103
  return `map<${keyType}, ${valueType}>`;
111
104
  }
@@ -117,14 +110,14 @@ class Zod2ProtoV3 extends core_1.Zod2X {
117
110
  this.push0(`enum ${data.name} {`);
118
111
  data.values.forEach(([key, value], index) => {
119
112
  if (Number.isInteger(key.at(0))) {
120
- throw new Error(`Enumerate item name cannot start with number: ${key}`);
113
+ throw new core_1.NotTranspilerableTypeError(`Enumerate item name cannot start with number: ${key}`);
121
114
  }
122
115
  this.push1(`${key} = ${index};`);
123
116
  });
124
117
  this.push0("}\n");
125
118
  }
126
119
  transpileIntersection(data) {
127
- throw new Error(`Protobuf does not support message intersections.`);
120
+ throw new core_1.NotTranspilerableTypeError(`Protobuf does not support message intersections.`);
128
121
  }
129
122
  transpileStruct(data) {
130
123
  this.addComment(data.description);
@@ -141,7 +134,7 @@ class Zod2ProtoV3 extends core_1.Zod2X {
141
134
  this.addComment(data.description);
142
135
  const attributesTypes = data.options.map(this.getAttributeType.bind(this));
143
136
  if (attributesTypes.find((i) => i.startsWith("map<") || i.startsWith("repeated "))) {
144
- throw new Error("Map and Repeated fields are not suported by Protobuf oneOf");
137
+ throw new core_1.NotTranspilerableTypeError("Map and Repeated fields are not suported by Protobuf oneOf");
145
138
  }
146
139
  this.push0(`message ${data.name} {`);
147
140
  this.push1(`oneof ${this._adaptField(data.name + "Oneof")} {`);
@@ -0,0 +1,5 @@
1
+ import { IZodToXOpt } from "../../core";
2
+ export interface IZod2TsOpt extends IZodToXOpt {
3
+ outType?: "interface" | "class";
4
+ }
5
+ export declare const defaultOpts: IZod2TsOpt;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defaultOpts = void 0;
4
+ exports.defaultOpts = {
5
+ includeComments: true,
6
+ indent: 4,
7
+ skipDiscriminatorNodes: false,
8
+ outType: "interface",
9
+ };
@@ -1,7 +1,5 @@
1
- import { ASTCommon, ASTDiscriminatedUnion, ASTEnum, ASTIntersection, ASTNativeEnum, ASTObject, ASTUnion, IZodToXOpt, Zod2X } from "../../core";
2
- interface IZod2TsOpt extends IZodToXOpt {
3
- outType?: "interface" | "class";
4
- }
1
+ import { ASTCommon, ASTDiscriminatedUnion, ASTEnum, ASTIntersection, ASTNativeEnum, ASTObject, ASTUnion, Zod2X } from "../../core";
2
+ import { IZod2TsOpt } from "./options";
5
3
  export declare class Zod2Ts extends Zod2X<IZod2TsOpt> {
6
4
  constructor(opt?: IZod2TsOpt);
7
5
  protected runAfter(): void;
@@ -28,4 +26,3 @@ export declare class Zod2Ts extends Zod2X<IZod2TsOpt> {
28
26
  private _transpileStructAsClass;
29
27
  private _transpileMember;
30
28
  }
31
- export {};
@@ -6,17 +6,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.Zod2Ts = void 0;
7
7
  const case_1 = __importDefault(require("case"));
8
8
  const core_1 = require("../../core");
9
- const defaultOpts = {
10
- includeComments: true,
11
- indent: 4,
12
- skipDiscriminatorNodes: false,
13
- outType: "interface",
14
- };
9
+ const options_1 = require("./options");
15
10
  class Zod2Ts extends core_1.Zod2X {
16
11
  constructor(opt = {}) {
17
- super({
18
- enableCompositeTypes: true,
19
- }, Object.assign(Object.assign({}, defaultOpts), opt));
12
+ super(Object.assign(Object.assign({}, options_1.defaultOpts), opt));
20
13
  this.getComment = (data, indent = "") => `${indent}// ${data}`;
21
14
  this.getAnyType = () => "any";
22
15
  this.getBooleanType = () => "boolean";
@@ -41,7 +34,7 @@ class Zod2Ts extends core_1.Zod2X {
41
34
  }
42
35
  getLiteralStringType(value, parentEnumNameKey) {
43
36
  return parentEnumNameKey
44
- ? `${parentEnumNameKey[0]}.${parentEnumNameKey[1]}`
37
+ ? `${parentEnumNameKey[0]}.${case_1.default.pascal(parentEnumNameKey[1])}`
45
38
  : isNaN(Number(value))
46
39
  ? `"${value}"`
47
40
  : value;
@@ -56,16 +49,24 @@ class Zod2Ts extends core_1.Zod2X {
56
49
  this.addComment(data.description);
57
50
  this.push0(`export enum ${data.name} {`);
58
51
  data.values.forEach((i) => {
59
- const keyValue = isNaN(Number(i[0].at(0))) ? i[0] : `"${i[0]}"`;
52
+ const key = case_1.default.pascal(i[0]);
53
+ const keyValue = isNaN(Number(key.at(0))) ? key : `"${key}"`;
60
54
  const enumValue = typeof i[1] === "string" ? `"${i[1]}"` : `${i[1]}`;
61
55
  this.push1(`${keyValue} = ${enumValue},`);
62
56
  });
63
57
  this.push0("}\n");
64
58
  }
65
59
  transpileIntersection(data) {
66
- this.addComment(data.description);
67
- const attributesTypes = [data.left, data.right].map(this.getAttributeType.bind(this));
68
- this.push0(`export type ${data.name} = ${this.getIntersectionType(attributesTypes)};\n`);
60
+ var _a;
61
+ if (this.opt.outType === "class" && data.newObject) {
62
+ this.addComment((_a = data.newObject) === null || _a === void 0 ? void 0 : _a.description);
63
+ this._transpileStructAsClass(data.newObject);
64
+ }
65
+ else {
66
+ this.addComment(data.description);
67
+ const attributesTypes = [data.left, data.right].map(this.getAttributeType.bind(this));
68
+ this.push0(`export type ${data.name} = ${this.getIntersectionType(attributesTypes)};\n`);
69
+ }
69
70
  }
70
71
  transpileStruct(data) {
71
72
  this.addComment(data.description);
@@ -77,9 +78,16 @@ class Zod2Ts extends core_1.Zod2X {
77
78
  }
78
79
  }
79
80
  transpileUnion(data) {
80
- this.addComment(data.description);
81
- const attributesTypes = data.options.map(this.getAttributeType.bind(this));
82
- this.push0(`export type ${data.name} = ${this.getUnionType(attributesTypes)};\n`);
81
+ var _a;
82
+ if (this.opt.outType === "class" && data.newObject) {
83
+ this.addComment((_a = data.newObject) === null || _a === void 0 ? void 0 : _a.description);
84
+ this._transpileStructAsClass(data.newObject);
85
+ }
86
+ else {
87
+ this.addComment(data.description);
88
+ const attributesTypes = data.options.map(this.getAttributeType.bind(this));
89
+ this.push0(`export type ${data.name} = ${this.getUnionType(attributesTypes)};\n`);
90
+ }
83
91
  }
84
92
  _transpileStructuAsInterface(data) {
85
93
  this.push0(`export interface ${data.name} {`);
@@ -0,0 +1,7 @@
1
+ export declare const log: {
2
+ info: (...args: any) => void;
3
+ error: (...args: any) => void;
4
+ warn: (...args: any) => void;
5
+ debug: (...args: any) => void;
6
+ trace: (...args: any) => void;
7
+ };
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.log = void 0;
4
+ const DEBUG = false;
5
+ function execute(fn) {
6
+ if (DEBUG) {
7
+ fn();
8
+ }
9
+ }
10
+ exports.log = {
11
+ info: (...args) => execute(() => console.log(args)),
12
+ error: (...args) => execute(() => console.error(args)),
13
+ warn: (...args) => execute(() => console.warn(args)),
14
+ debug: (...args) => execute(() => console.debug(args)),
15
+ trace: (...args) => execute(() => console.trace(args)),
16
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zod-to-x",
3
- "version": "1.2.1",
3
+ "version": "1.3.0",
4
4
  "description": "Multi language types generation from Zod schemas.",
5
5
  "main": "dist/index.js",
6
6
  "files": [
@@ -40,9 +40,11 @@
40
40
  "lint-staged": {
41
41
  "*.ts": "prettier --write"
42
42
  },
43
+ "peerDependencies": {
44
+ "zod": ">=3.22.3"
45
+ },
43
46
  "dependencies": {
44
- "case": "1.6.3",
45
- "zod": "^3.23.8"
47
+ "case": "1.6.3"
46
48
  },
47
49
  "devDependencies": {
48
50
  "@types/jest": "29.5.14",