zod-to-x 1.4.0 → 1.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -3,15 +3,14 @@
3
3
  <em style="font-size: smaller;">Image generated using Canvas AI.</em>
4
4
  </p>
5
5
  <p align="center">
6
- <a href="https://github.com/rroumenov/zod-to-x/releases" target="_blank" style="text-decoration: none;">
7
- <button style="padding: 6px 12px; font-size: 14px; background-color: #2ea44f; color: white; border: 1px solid rgba(27, 31, 35, 0.15); border-radius: 6px; cursor: pointer; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji';">
8
- View Changelog
9
- </button>
6
+ <a href="https://github.com/rroumenov/zod-to-x/releases" target="_blank">
7
+ <img src="https://img.shields.io/badge/View%20Changelog-brightgreen?style=for-the-badge" alt="View Changelog">
10
8
  </a>
11
- <a href="https://playcode.io/2277071" target="_blank" style="text-decoration: none; margin-left: 10px;">
12
- <button style="padding: 6px 12px; font-size: 14px; background-color: #0366d6; color: white; border: 1px solid rgba(27, 31, 35, 0.15); border-radius: 6px; cursor: pointer; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji';">
13
- Try it on Playcode
14
- </button>
9
+ <a href="https://playcode.io/2277071" target="_blank" style="margin-left: 10px;">
10
+ <img src="https://img.shields.io/badge/Try%20it%20on%20Playcode-blue?style=for-the-badge" alt="Try it on Playcode">
11
+ </a>
12
+ <a href="https://github.com/rroumenov/zod-to-x/issues" target="_blank" style="margin-left: 10px;">
13
+ <img src="https://img.shields.io/badge/Need%20Help%3F-orange?style=for-the-badge" alt="Need Help?">
15
14
  </a>
16
15
  </p>
17
16
 
@@ -72,7 +71,7 @@ This extension appends a `zod2x` method to:
72
71
  ## Quick start
73
72
  ```ts
74
73
  import { z } from "zod";
75
- import { extendZod, Zod2Ast, Zod2Ts } from "zod-to-x";
74
+ import { extendZod, Zod2Ast, Zod2XTranspilers } from "zod-to-x";
76
75
  extendZod(z); // The extend step can be skipped if it has already been done.
77
76
 
78
77
  /**
@@ -95,7 +94,7 @@ const visitorNodes = new Zod2Ast().build(VisitorSchema);
95
94
  * 3) Generate types in the desired language.
96
95
  * Depending on the transpiled language, data models can be generated using classes.
97
96
  */
98
- const tsVisitorAsInterface: string = new Zod2Ts().transpile(visitorNodes);
97
+ const tsVisitorAsInterface: string = new Zod2XTranspilers.Zod2Ts().transpile(visitorNodes);
99
98
  console.log(tsVisitorAsInterface)
100
99
  // output:
101
100
  // export interface Visitor {
@@ -106,7 +105,7 @@ console.log(tsVisitorAsInterface)
106
105
  // comments?: string;
107
106
  // }
108
107
 
109
- const tsVisitorAsClass: string = new Zod2Ts({outType: "class"}).transpile(visitorNodes);
108
+ const tsVisitorAsClass: string = new Zod2XTranspilers.Zod2Ts({outType: "class"}).transpile(visitorNodes);
110
109
  console.log(tsVisitorAsClass)
111
110
  // output:
112
111
  // export class Visitor {
@@ -256,9 +255,13 @@ inline void from_json(const json& j, Message& x) {
256
255
  ## Layered modeling
257
256
  To improve Separation of Concerns (SoC), the Dependency Rule, and Maintainability, a new layer-based modeling approach was introduced in `v1.4.0`. This approach establishes relationships between models in separate files, which are transpiled into file imports. This feature provides a powerful tool not only for type systems with robust architectures, such as Clean, Hexagonal, or Layered, but also enforces their usage.
258
257
 
259
- To achieve this, two new components are included:
258
+ To achieve this, new components are included:
260
259
  - **Zod2XModel**: With layered modeling, data is defined using classes. Inheriting this abstract class provides metadata management to handle relationships and also simplifies transpilation by including a `transpile()` method that receives the target language class.
261
- - **Layer**: A class decorator that defines class metadata, including a reference to the output file of the modeled data, a namespace under which its types are grouped, and an integer index representing the layer number. It can also be used as a decorator factory to define custom layers. Out of the box, four layers are provided: *Domain*, *Application*, *Infrastructure*, and *Presentation*.
260
+ - **Layer**: A class decorator that defines class metadata, including a reference to the output file of the modeled data, a namespace under which its types are grouped, and an integer index representing the layer number. It can also be used as a decorator factory to define custom layers. Out of the box, four layers are provided: *Domain*, *Application*, *Infrastructure*, and *Presentation*. Parameters:
261
+ - **namespace**: Defines the namespace under which the types are grouped.
262
+ - **file**: Specifies the expected output file where the transpiled types will be saved.
263
+ - **externalInheritance**: When a type from one layer is imported into another layer without modifications, it is transpiled as a new type inheriting from the imported type. This ensures type consistency across layers while maintaining reusability. See example (4) below. The default value is `true`.
264
+ - **Zod2XMixin**: A function that enables the creation of layers by extending multiple data models, thereby simplifying their definition and organization.
262
265
 
263
266
  ### Usage example
264
267
  1. Define a Domain model, such as a User entity:
@@ -319,7 +322,7 @@ class UserDtos extends Zod2XModel {
319
322
  }
320
323
 
321
324
  const userDtos = new UserDtos();
322
- console.log(userDtos.transpile(Transpilers.Zod2Ts))
325
+ console.log(userDtos.transpile(Zod2XTranspilers.Zod2Ts))
323
326
  // Output:
324
327
  // import * as USER from "./user.entity"; <--- Reusing models from other layers.
325
328
 
@@ -347,13 +350,128 @@ console.log(userDtos.transpile(Transpilers.Zod2Ts))
347
350
  ```
348
351
  **(*)** Any modification of an existing model (in this case, `userEntity`) will lose the relation with that model, but not its children. In the case of the `CreateUserUseCaseDto` type, the `role` field will remain linked to the existing one in the `user.entity` file.
349
352
 
353
+ 3 - Are your models too large? Simplify them!
354
+ If you are dealing with complex models whose definitions are too extensive, split them into multiple classes and then combine them using `Zod2XMixin` as shown below:
355
+ ```ts
356
+ // Sub-models do not require a layer decorator; it is applied automatically when inherited by the main model.
357
+
358
+ // Sub-model 1
359
+ class CreateUserUseCaseDto {
360
+ createUserUseCaseDto = userModels.userEntity.omit({ id: true });
361
+ }
362
+
363
+ // Sub-model 2
364
+ class CreateUserUseCaseResultDto {
365
+ createUserUseCaseResultDto = userModels.userEntity
366
+ .omit({ role: true })
367
+ .extend({
368
+ createdAt: z.date(),
369
+ updatedAt: z.date(),
370
+ });
371
+ }
372
+
373
+ // Main model
374
+ @Application({ namespace: "USER_DTOS", file: "user.dtos" })
375
+ class UserDtos extends Zod2XMixin(
376
+ [CreateUserUseCaseDto, CreateUserUseCaseResultDto], // Inherit the desired sub-models.
377
+ Zod2XModel // Zod2XModel must still be the base class.
378
+ ) {}
379
+
380
+ export const userDtos = new UserDtos();
381
+ console.log(userDtos.transpile(Zod2XTranspilers.Zod2Ts))
382
+ // Output (same as above):
383
+ // import * as USER from "./user.entity"; <--- Reusing models from other layers.
384
+
385
+ // export interface CreateUserUseCaseDto {
386
+ // name: string;
387
+ // email: string;
388
+ // age?: number;
389
+ // role: USER.UserRole;
390
+ // }
391
+
392
+ // export interface CreateUserUseCaseResultDto {
393
+ // id: string;
394
+ // name: string;
395
+ // email: string;
396
+ // age?: number;
397
+ // createdAt: Date;
398
+ // updatedAt: Date;
399
+ // }
400
+
401
+ // export interface UserDtos {
402
+ // createUserUseCaseDto: CreateUserUseCaseDto;
403
+ // createUserUseCaseResultDto: CreateUserUseCaseResultDto;
404
+ // }
405
+ ```
406
+
407
+ 4 - Difference of using **externalInheritance** (defaults) or not.
408
+ ```ts
409
+ // Default output (externalInheritance = true)
410
+ @Application({ namespace: "USER_DTOS", file: "user.dtos" })
411
+ class UserDtos extends Zod2XModel {
412
+
413
+ createUserUseCaseDto = userModels.userEntity.omit({ id: true });
414
+
415
+ createUserUseCaseResultDto = userModels.userEntity;
416
+ }
417
+
418
+ // Output:
419
+ // import * as USER from "./user.entity";
420
+
421
+ // export interface CreateUserUseCaseDto {
422
+ // name: string;
423
+ // email: string;
424
+ // age?: number;
425
+ // role: USER.UserRole;
426
+ // }
427
+
428
+ // export interface CreateUserUseCaseResultDto extends USER.UserEntity {}
429
+
430
+ // export interface UserDtos {
431
+ // createUserUseCaseDto: CreateUserUseCaseDto;
432
+ // createUserUseCaseResultDto: CreateUserUseCaseResultDto;
433
+ // }
434
+
435
+ // ---------------
436
+ // If `USER.UserEntity` were a Union or a Discriminated Union, the output would be a Type equivalent to `USER.UserEntity` rather than an Interface that extends it.
437
+
438
+ ```
439
+
440
+ ```ts
441
+ // Output without externalInheritance
442
+ @Application({ namespace: "USER_DTOS", file: "user.dtos", externalInheritance: false})
443
+ class UserDtos extends Zod2XModel {
444
+
445
+ createUserUseCaseDto = userModels.userEntity.omit({ id: true });
446
+
447
+ createUserUseCaseResultDto = userModels.userEntity;
448
+ }
449
+
450
+ // Output:
451
+ // import * as USER from "./user.entity";
452
+
453
+ // export interface CreateUserUseCaseDto {
454
+ // name: string;
455
+ // email: string;
456
+ // age?: number;
457
+ // role: USER.UserRole;
458
+ // }
459
+
460
+ // export interface UserDtos {
461
+ // createUserUseCaseDto: CreateUserUseCaseDto;
462
+ // createUserUseCaseResultDto: USER.UserEntity;
463
+ // }
464
+
465
+ // ---------------
466
+ // In this case, the type of `createUserUseCaseResultDto` is inferred from the parent model (`UserDtos`), but there is no explicit definition of the type itself.
467
+ ```
468
+
350
469
 
351
470
  ## Supported output languages
352
471
  Common options:
353
472
  - **header**: Text to add as a comment at the beginning of the output.
354
473
  - **indent**: Number of spaces to use for indentation in the generated code. Defaults to 4 if not specified.
355
474
  - **includeComments**: Determines whether to include comments in the transpiled code. Defaults to `true`.
356
- - **skipDiscriminatorNodes**: prevents the inclusion of `ZodEnum` or `ZodNativeEnum` schemas that are used solely as discriminator keys in a `ZodDiscriminatedUnion`. Defaults to `false`.
357
475
 
358
476
  ### 0) ASTNode
359
477
  - Options:
@@ -23,14 +23,6 @@ export declare class Zod2Ast {
23
23
  * Transpilerable nodes of current data model
24
24
  */
25
25
  private nodes;
26
- /**
27
- * Transpilerable nodes of external data models (used for layered modeling)
28
- */
29
- private externalNodes;
30
- /**
31
- * Additional transpilerable nodes supplied by ZodDiscriminatedUnion
32
- */
33
- private discriminatorNodes;
34
26
  /**
35
27
  * Lazy schemas for further analysis
36
28
  */
@@ -87,7 +79,6 @@ export declare class Zod2Ast {
87
79
  */
88
80
  private _unionAstNodes;
89
81
  private _getNames;
90
- private _getNode;
91
82
  private _getEnumAst;
92
83
  private _getObjectAst;
93
84
  private _getUnionAst;
@@ -13,8 +13,6 @@ class Zod2Ast {
13
13
  constructor(opt = {}) {
14
14
  var _a;
15
15
  this.nodes = new Map();
16
- this.externalNodes = new Map();
17
- this.discriminatorNodes = new Map();
18
16
  this.lazyPointers = [];
19
17
  this.warnings = [];
20
18
  this.opt = Object.assign(Object.assign({}, opt), { strict: (_a = opt.strict) !== null && _a !== void 0 ? _a : true });
@@ -27,14 +25,20 @@ class Zod2Ast {
27
25
  * @param layerMetadata
28
26
  * @returns
29
27
  */
30
- _getTranspilerableFile(itemName, layerMetadata) {
31
- if (this.opt.layer && layerMetadata) {
32
- if (this.opt.layer.index < layerMetadata.index) {
28
+ _getTranspilerableFile(itemName, metadata) {
29
+ var _a;
30
+ const layer = (_a = metadata === null || metadata === void 0 ? void 0 : metadata.parentLayer) !== null && _a !== void 0 ? _a : metadata === null || metadata === void 0 ? void 0 : metadata.layer;
31
+ if (this.opt.layer && layer) {
32
+ if (this.opt.layer.index < layer.index) {
33
33
  throw new errors_1.BadLayerDefinitionError(`${itemName}: Layer with number ${this.opt.layer.index} can only use models` +
34
- `from the same or lower layer. Found layer with number ${layerMetadata.index}`);
34
+ `from the same or lower layer. Found layer with number ${layer.index}`);
35
35
  }
36
- if (this.opt.layer.file !== layerMetadata.file) {
37
- return { parentFile: layerMetadata.file, parentNamespace: layerMetadata.namespace };
36
+ if (this.opt.layer.file !== layer.file) {
37
+ return {
38
+ parentFile: layer.file,
39
+ parentNamespace: layer.namespace,
40
+ parentTypeName: metadata === null || metadata === void 0 ? void 0 : metadata.parentTypeName,
41
+ };
38
42
  }
39
43
  }
40
44
  return {};
@@ -144,63 +148,51 @@ class Zod2Ast {
144
148
  };
145
149
  }
146
150
  _getNames(schema, errorString) {
147
- var _a, _b;
151
+ var _a;
148
152
  const name = (_a = schema._zod2x) === null || _a === void 0 ? void 0 : _a.typeName;
149
153
  if (!name) {
150
154
  throw new errors_1.AstTypeNameDefinitionError(errorString);
151
155
  }
152
- return Object.assign({ name, typeName: schema._def.typeName }, this._getTranspilerableFile(name, (_b = schema._zod2x) === null || _b === void 0 ? void 0 : _b.layer));
153
- }
154
- _getNode(fileName) {
155
- return fileName ? this.externalNodes : this.nodes;
156
+ return Object.assign({ name, zodTypeName: schema._def.typeName }, this._getTranspilerableFile(name, schema._zod2x));
156
157
  }
157
158
  _getEnumAst(schema, opt) {
158
- const { name, typeName, parentFile, parentNamespace } = this._getNames(schema, "ZodEnum/ZodNativeEnum type must have a typeName. Use zod2x method to provide one.");
159
+ const { name, zodTypeName, parentFile, parentNamespace, parentTypeName } = this._getNames(schema, "ZodEnum/ZodNativeEnum type must have a typeName. Use zod2x method to provide one.");
159
160
  const item = {
160
- type: typeName,
161
+ type: zodTypeName,
161
162
  name,
162
163
  values: this._getEnumValues(schema),
163
164
  description: schema._def.description,
164
165
  parentFile,
165
166
  parentNamespace,
167
+ parentTypeName,
168
+ isFromDiscriminatedUnion: opt === null || opt === void 0 ? void 0 : opt.isInjectedEnum,
166
169
  };
167
- const node = this._getNode(parentFile);
168
- if (opt === null || opt === void 0 ? void 0 : opt.isInjectedEnum) {
169
- if (!node.has(name) && !this.discriminatorNodes.has(name)) {
170
- this.discriminatorNodes.set(name, item);
171
- }
172
- }
173
- else {
174
- if (!node.has(name)) {
175
- node.set(name, item);
176
- }
177
- if (this.discriminatorNodes.has(name)) {
178
- this.discriminatorNodes.delete(name);
179
- }
170
+ if (!this.nodes.has(name)) {
171
+ this.nodes.set(name, item);
180
172
  }
181
- return this._createDefinition(name, typeName, undefined, parentNamespace);
173
+ return this._createDefinition(name, zodTypeName, undefined, parentNamespace);
182
174
  }
183
175
  _getObjectAst(schema, opt) {
184
- const { name, typeName, parentFile, parentNamespace } = this._getNames(schema, "ZodObject type must have a typeName. Use zod2x method to provide one.");
176
+ const { name, zodTypeName, parentFile, parentNamespace, parentTypeName } = this._getNames(schema, "ZodObject type must have a typeName. Use zod2x method to provide one.");
185
177
  let discriminantValue = undefined;
186
178
  const shape = schema._def.shape();
187
- const node = this._getNode(parentFile);
188
- if (!node.has(name)) {
179
+ if (!this.nodes.has(name)) {
189
180
  const properties = {};
190
181
  for (const key in shape) {
191
182
  properties[key] = this._zodToAST(shape[key]);
192
183
  }
193
- node.set(name, {
184
+ this.nodes.set(name, {
194
185
  type: zod_1.ZodFirstPartyTypeKind.ZodObject,
195
186
  name,
196
187
  properties,
197
188
  description: schema.description,
198
189
  parentFile,
199
190
  parentNamespace,
191
+ parentTypeName,
200
192
  });
201
193
  }
202
194
  if (opt === null || opt === void 0 ? void 0 : opt.discriminantKey) {
203
- const item = node.get(name);
195
+ const item = this.nodes.get(name);
204
196
  if (Object.keys(item.properties).includes(opt.discriminantKey)) {
205
197
  const key = opt.discriminantKey;
206
198
  if (item.properties[key].type === zod_1.ZodFirstPartyTypeKind.ZodLiteral) {
@@ -213,22 +205,22 @@ class Zod2Ast {
213
205
  }
214
206
  }
215
207
  }
216
- return this._createDefinition(name, typeName, discriminantValue, parentNamespace);
208
+ return this._createDefinition(name, zodTypeName, discriminantValue, parentTypeName ? undefined : parentNamespace);
217
209
  }
218
210
  _getUnionAst(schema) {
219
211
  const def = schema._def;
220
212
  const discriminator = schema instanceof zod_1.ZodDiscriminatedUnion ? schema._def.discriminator : undefined;
221
- const { name, typeName, parentFile, parentNamespace } = this._getNames(schema, "ZodUnion/ZodDiscriminatedUnion type must have a typeName. " +
213
+ const { name, zodTypeName, parentFile, parentNamespace, parentTypeName } = this._getNames(schema, "ZodUnion/ZodDiscriminatedUnion type must have a typeName. " +
222
214
  "Use zod2x method to provide one.");
223
- const node = this._getNode(parentFile);
224
215
  const item = {
225
- type: typeName,
216
+ type: zodTypeName,
226
217
  name,
227
218
  options: def.options.map((i) => this._zodToAST(i, { discriminantKey: discriminator })),
228
219
  description: schema.description,
229
220
  discriminantKey: discriminator,
230
221
  parentFile,
231
222
  parentNamespace,
223
+ parentTypeName,
232
224
  };
233
225
  if (!def.options.every((i) => i instanceof zod_1.ZodObject)) {
234
226
  this.warnings.push("Union of non-object types is a bad data modeling practice, " +
@@ -246,15 +238,14 @@ class Zod2Ast {
246
238
  `${item.options.map((i) => i.reference).join(", ")}`,
247
239
  };
248
240
  }
249
- if (name && !node.has(name)) {
250
- node.set(name, item);
241
+ if (name && !this.nodes.has(name)) {
242
+ this.nodes.set(name, item);
251
243
  }
252
- return this._createDefinition(name, typeName, undefined, parentNamespace);
244
+ return this._createDefinition(name, zodTypeName, undefined, parentTypeName ? undefined : parentNamespace);
253
245
  }
254
246
  _getIntersectionAst(schema) {
255
247
  const def = schema._def;
256
- const { name, typeName, parentFile, parentNamespace } = this._getNames(schema, "ZodIntersection type must have a typeName. Use zod2x method to provide one.");
257
- const node = this._getNode(parentFile);
248
+ const { name, zodTypeName, parentFile, parentNamespace, parentTypeName } = this._getNames(schema, "ZodIntersection type must have a typeName. Use zod2x method to provide one.");
258
249
  const item = {
259
250
  type: zod_1.ZodFirstPartyTypeKind.ZodIntersection,
260
251
  name,
@@ -263,6 +254,7 @@ class Zod2Ast {
263
254
  description: schema.description,
264
255
  parentFile,
265
256
  parentNamespace,
257
+ parentTypeName,
266
258
  };
267
259
  if (def.left._def.typeName !== "ZodObject" || def.right._def.typeName !== "ZodObject") {
268
260
  this.warnings.push("Intersection of non-object is a bad data modeling practice, " +
@@ -279,10 +271,10 @@ class Zod2Ast {
279
271
  `${item.right.reference}`,
280
272
  };
281
273
  }
282
- if (name && !node.has(name)) {
283
- node.set(name, item);
274
+ if (name && !this.nodes.has(name)) {
275
+ this.nodes.set(name, item);
284
276
  }
285
- return this._createDefinition(name, typeName, undefined, parentNamespace);
277
+ return this._createDefinition(name, zodTypeName, undefined, parentTypeName ? undefined : parentNamespace);
286
278
  }
287
279
  /**
288
280
  * Build the AST node of provided Zod Schema
@@ -450,8 +442,6 @@ class Zod2Ast {
450
442
  }
451
443
  return {
452
444
  nodes: this.nodes,
453
- externalNodes: this.externalNodes,
454
- discriminatorNodes: this.discriminatorNodes,
455
445
  warnings: this.warnings,
456
446
  };
457
447
  }
@@ -8,6 +8,19 @@ export type ASTCommon = {
8
8
  isNullable?: boolean;
9
9
  isOptional?: boolean;
10
10
  };
11
+ export type ASTLayerMetadata = {
12
+ /**
13
+ * File where the transpilerable model is defined and the reference used to group imports.
14
+ * Used to generate import statements in the transpiled code.
15
+ */
16
+ parentFile?: string;
17
+ parentNamespace?: string;
18
+ /**
19
+ * For Layered Modeling.
20
+ * Stores the used type from an external model. Used to create models inheritance.
21
+ */
22
+ parentTypeName?: string;
23
+ };
11
24
  /**
12
25
  * AST (Abstract Syntax Tree) type for each Zod Schema that encapsulates
13
26
  * additional information beyond just the schema type.
@@ -48,17 +61,25 @@ export type ASTEnum = {
48
61
  type: ZodFirstPartyTypeKind.ZodEnum;
49
62
  name: string;
50
63
  values: [string, string | number][];
51
- };
64
+ /**
65
+ * The enum is injected using zod2x method during ZodDiscriminatedUnion creation.
66
+ */
67
+ isFromDiscriminatedUnion?: boolean;
68
+ } & ASTLayerMetadata;
52
69
  export type ASTNativeEnum = {
53
70
  type: ZodFirstPartyTypeKind.ZodNativeEnum;
54
71
  name: string;
55
72
  values: [string, string | number][];
56
- };
73
+ /**
74
+ * The enum is injected using zod2x method during ZodDiscriminatedUnion creation.
75
+ */
76
+ isFromDiscriminatedUnion?: boolean;
77
+ } & ASTLayerMetadata;
57
78
  export type ASTObject = {
58
79
  type: ZodFirstPartyTypeKind.ZodObject;
59
80
  name: string;
60
81
  properties: Record<string, ASTNode>;
61
- };
82
+ } & ASTLayerMetadata;
62
83
  export type ASTUnion = {
63
84
  type: ZodFirstPartyTypeKind.ZodUnion;
64
85
  name: string;
@@ -68,13 +89,13 @@ export type ASTUnion = {
68
89
  * have a variant type or discriminated union cannot be used.
69
90
  */
70
91
  newObject?: ASTCommon & ASTObject;
71
- };
92
+ } & ASTLayerMetadata;
72
93
  export type ASTDiscriminatedUnion = {
73
94
  type: ZodFirstPartyTypeKind.ZodDiscriminatedUnion;
74
95
  name: string;
75
96
  options: ASTNode[];
76
97
  discriminantKey?: string;
77
- };
98
+ } & ASTLayerMetadata;
78
99
  export type ASTIntersection = {
79
100
  type: ZodFirstPartyTypeKind.ZodIntersection;
80
101
  name: string;
@@ -85,7 +106,7 @@ export type ASTIntersection = {
85
106
  * support multiple inheritance.
86
107
  */
87
108
  newObject?: ASTCommon & ASTObject;
88
- };
109
+ } & ASTLayerMetadata;
89
110
  /**
90
111
  * Represents a type definition in the AST. Used to reduce node size and identify
91
112
  * schemas that can be referenced in a transpilation process.
@@ -119,17 +140,8 @@ export type ASTNode = ASTCommon & ({
119
140
  /**
120
141
  * Represents schemas that can be directly transpiled into types in other programming languages.
121
142
  */
122
- export type TranspilerableTypes = ASTCommon & (ASTEnum | ASTNativeEnum | ASTObject | ASTUnion | ASTDiscriminatedUnion | ASTIntersection) & {
123
- /**
124
- * File where the transpilerable model is defined and the reference used to group imports.
125
- * Used to generate import statements in the transpiled code.
126
- */
127
- parentFile?: string;
128
- parentNamespace?: string;
129
- };
143
+ export type TranspilerableTypes = ASTCommon & (ASTEnum | ASTNativeEnum | ASTObject | ASTUnion | ASTDiscriminatedUnion | ASTIntersection);
130
144
  export type ASTNodes = {
131
145
  nodes: Map<string, TranspilerableTypes>;
132
- externalNodes: Map<string, TranspilerableTypes>;
133
- discriminatorNodes: Map<string, TranspilerableTypes>;
134
146
  warnings: string[];
135
147
  };
@@ -19,13 +19,6 @@ export interface IZodToXOpt extends Record<string, any> {
19
19
  * Defaults to `true`.
20
20
  */
21
21
  includeComments?: boolean;
22
- /**
23
- * When set to `true`, this option excludes discriminator enums from the output types.
24
- * Specifically, it prevents the inclusion of `ZodEnum` or `ZodNativeEnum` schemas that are used
25
- * solely as discriminator keys in a `ZodDiscriminatedUnion`. This helps avoid adding
26
- * enum types to the generated output when unnecessary.
27
- */
28
- skipDiscriminatorNodes?: boolean;
29
22
  /**
30
23
  * Every external type will be imported from the file where it is defined. Default: true
31
24
  */
@@ -39,7 +32,9 @@ export interface IZodToXOpt extends Record<string, any> {
39
32
  export declare abstract class Zod2X<T extends IZodToXOpt> {
40
33
  protected output: string[];
41
34
  protected indent: TIndentationLevels;
35
+ protected preImports: Set<string>;
42
36
  protected imports: Set<string>;
37
+ protected postImports: Set<string>;
43
38
  protected opt: Partial<T>;
44
39
  protected constructor(opt: Partial<T>);
45
40
  /**
@@ -60,6 +55,15 @@ export declare abstract class Zod2X<T extends IZodToXOpt> {
60
55
  * @param typeName
61
56
  */
62
57
  protected abstract getTypeFromExternalNamespace(namespace: string, typeName: string): string;
58
+ /**
59
+ * For Layered Modeling.
60
+ * If a property type is an imported type, without any modification, the transpiled type will be
61
+ * an inherited type from the imported type.
62
+ * @param name
63
+ * @param parentNamespace
64
+ * @param parentTypeName
65
+ */
66
+ protected abstract addExtendedType(name: string, parentNamespace: string, parentTypeName: string): void;
63
67
  /**
64
68
  * Returns a comment.
65
69
  */
@@ -183,13 +187,30 @@ export declare abstract class Zod2X<T extends IZodToXOpt> {
183
187
  * @returns A string representing the type in the target language.
184
188
  */
185
189
  protected getAttributeType(token: ASTNode | TranspilerableTypes): string;
190
+ /**
191
+ * Adds an external type import to the transpiler's imports if the provided transpiled item
192
+ * is located into another file and namespace, and if the `useImports` option is not disabled.
193
+ *
194
+ * @param item - An object of type `TranspilerableTypes` containing information
195
+ * about the type to be imported, including its parent file and namespace.
196
+ * @returns `true` if the import was successfully added, otherwise `false`.
197
+ */
198
+ protected addExternalTypeImport(item: TranspilerableTypes): boolean;
186
199
  /**
187
200
  * Transpiles a single item from the transpiler queue.
188
201
  * @param item - The transpilerable type to transpile.
189
202
  */
190
203
  private _transpileItem;
191
- private _getTranspilerableNodes;
192
- private _getImports;
204
+ /**
205
+ * Constructs and returns an array of strings representing the header section
206
+ * of the transpiled output. The header may include custom comments, pre-imports,
207
+ * imports, and post-imports, depending on the provided options and internal state.
208
+ *
209
+ * Each section is separated by an empty string for readability.
210
+ *
211
+ * @returns An array of strings representing the header section.
212
+ *
213
+ */
193
214
  private _getHeader;
194
215
  /**
195
216
  * Transpiles a queue of AST nodes into the target language.