zod-to-x 1.6.1-dev.0 → 1.8.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
@@ -26,30 +26,38 @@
26
26
  <img src="https://img.shields.io/badge/TypeScript-3178C6?style=for-the-badge&logo=typescript&logoColor=white" alt="TypeScript">
27
27
  <img src="https://img.shields.io/badge/Python-3776AB?style=for-the-badge&logo=python&logoColor=white" alt="Python">
28
28
  <img src="https://img.shields.io/badge/C++-00599C?style=for-the-badge&logo=cplusplus&logoColor=white" alt="C++">
29
+ <img src="https://img.shields.io/badge/Go-00ADD8?style=for-the-badge&logo=go&logoColor=white" alt="Go">
30
+ <img src="https://img.shields.io/badge/Dart-0175C2?style=for-the-badge&logo=dart&logoColor=white" alt="Dart">
29
31
  <img src="https://img.shields.io/badge/Protobuf-4285F4?style=for-the-badge&logo=google&logoColor=white" alt="Protobuf">
30
32
  </p>
31
33
 
32
34
 
33
35
 
34
36
  ## Table of contents
35
- - [Why use `@zod-to-x`](#why-use-zod-to-x)
37
+ - [Table of contents](#table-of-contents)
38
+ - [Why Use `@zod-to-x`?](#why-use-zod-to-x)
36
39
  - [Installation](#installation)
40
+ - [1) Install `@zod-to-x` and `@zod(*)` dependency.](#1-install-zod-to-x-and-zod-dependency)
41
+ - [2) Extend Zod using the `extendZod` method after the first `@zod` import:](#2-extend-zod-using-the-extendzod-method-after-the-first-zod-import)
37
42
  - [Quick start](#quick-start)
38
43
  - [Intersections and Unions](#intersections-and-unions)
39
44
  - [Expected outputs](#expected-outputs)
40
45
  - [Tips for discriminated unions](#tips-for-discriminated-unions)
41
46
  - [Layered modeling](#layered-modeling)
42
47
  - [Usage example](#usage-example)
43
- - [Custom layers](#custom-layers)
48
+ - [Custom Layers](#custom-layers)
44
49
  - [Generic types](#generic-types)
45
50
  - [Currently supported output languages](#currently-supported-output-languages)
46
- - [Typescript](#1-typescript)
47
- - [Python](#2-python) <sup>*(new)*</sup>
48
- - [C++](#3-c)
51
+ - [0) ASTNode](#0-astnode)
52
+ - [1) Typescript](#1-typescript)
53
+ - [2) Python](#2-python)
54
+ - [3) C++](#3-c)
55
+ - [4) Go](#4-go)
56
+ - [5) Dart](#5-dart)
49
57
  - [Additional utils](#additional-utils)
50
- - [JSON Schema definitions](#1-zod2jsonschemadefinitions)
51
- - [Protobuf V3 generation](#2-zod2protov3)
52
- - [Mapping of supported Zod Types by Language](#mapping-of-supported-zod-types-by-langauge)
58
+ - [1) `zod2JsonSchemaDefinitions`](#1-zod2jsonschemadefinitions)
59
+ - [2) `zod2ProtoV3`](#2-zod2protov3)
60
+ - [Mapping of supported Zod Types by Langauge](#mapping-of-supported-zod-types-by-langauge)
53
61
  - [Considerations](#considerations)
54
62
 
55
63
 
@@ -61,7 +69,7 @@ Managing data consistency across multiple layers and languages is a common chall
61
69
  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)
62
70
 
63
71
  2. **Multi-Language Compatibility**
64
- Generate data models for TypeScript, Python (Pydantic), C++, and Protobuf V3 (with languages like Golang on the roadmap). No more manually rewriting models for different platforms.
72
+ Generate data models for TypeScript, Python (Pydantic), C++, Go, and Protobuf V3. No more manually rewriting models for different platforms.
65
73
 
66
74
  3. **Enhanced Productivity**
67
75
  Automate the transpilation of data models to save time, reduce errors, and let your team focus on business logic instead of boilerplate code.
@@ -647,6 +655,22 @@ Common options:
647
655
  - **keepKeys**: Specifies whether property names should follow the C++ naming convention (false) or remain as originally defined (true). The default is `false`.
648
656
  - [Examples](https://github.com/rroumenov/zod-to-x/blob/main/test/test_zod2cpp)
649
657
 
658
+ ### 4) Go
659
+ Generates idiomatic Go structs with `encoding/json` struct tags. Requires Go 1.18+ for generic type support.
660
+ - Options:
661
+ - **packageName**: The Go package name for the generated file. Defaults to `"models"`.
662
+ - **keepKeys**: Specifies whether field names should remain as originally defined (true) or be converted to exported PascalCase with the original name used in the JSON tag (false). The default is `false`.
663
+ - **useJsonTags**: Whether to emit `json:"fieldName"` struct tags. Defaults to `true`.
664
+ - [Examples](https://github.com/rroumenov/zod-to-x/blob/main/test/test_zod2go)
665
+
666
+ ### 5) Dart
667
+ `json_annotation` + `json_serializable` are used for JSON serialization/deserialization. The `.g.dart` part file is generated externally by `dart run build_runner build`.
668
+ - Options:
669
+ - **keepKeys**: Specifies whether property names should follow the Dart naming convention (false) or remain as originally defined (true). The default is `false`.
670
+ - **useJsonSerialization**: When true (default), emits `@JsonSerializable()`, `@JsonEnum`, `@JsonKey` annotations and `fromJson`/`toJson` stubs. Requires `package:json_annotation`.
671
+ - **partFile**: Filename (without extension) for the `part '${partFile}.g.dart'` directive. Automatically set when using layered modeling. If omitted, no `part` directive is emitted.
672
+ - [Examples](https://github.com/rroumenov/zod-to-x/blob/main/test/test_zod2dart)
673
+
650
674
 
651
675
 
652
676
  ## Additional utils
@@ -82,7 +82,7 @@ export declare class Zod2Ast {
82
82
  private _intersectAstNodes;
83
83
  /**
84
84
  * Merges multiple AST definitions into a single AST object containing combined properties.
85
- * - Equal properties mush have the same type and array dimension.
85
+ * - Equal properties must have the same type and array dimension.
86
86
  * - If a property is optional in one definition and required in another, it will be considered
87
87
  * optional in the merged object.
88
88
  * - If a property is nullable in one definition and non-nullable in another, it will be
@@ -160,19 +160,25 @@ class Zod2Ast {
160
160
  for (const schema of [left, right]) {
161
161
  const shape = schema._def.shape();
162
162
  for (const key in shape) {
163
+ const prevWasRequired = properties[key] !== undefined && !properties[key].isOptional;
163
164
  if (zod_helpers_1.ZodHelpers.isZodPromise(shape[key]) && zod_helpers_1.ZodHelpers.isZod2XGeneric(shape[key])) {
164
165
  properties[key] = new core_1.ASTGenericType(shape[key]._def.type.value);
165
166
  }
166
167
  else {
167
168
  properties[key] = this._zodToAST(shape[key]);
168
169
  }
170
+ if (prevWasRequired && properties[key].isOptional) {
171
+ // In intersection, if a property is required in one schema and optional in
172
+ // another, it should be considered required.
173
+ properties[key].isOptional = false;
174
+ }
169
175
  }
170
176
  }
171
177
  return { properties };
172
178
  }
173
179
  /**
174
180
  * Merges multiple AST definitions into a single AST object containing combined properties.
175
- * - Equal properties mush have the same type and array dimension.
181
+ * - Equal properties must have the same type and array dimension.
176
182
  * - If a property is optional in one definition and required in another, it will be considered
177
183
  * optional in the merged object.
178
184
  * - If a property is nullable in one definition and non-nullable in another, it will be
@@ -185,42 +191,49 @@ class Zod2Ast {
185
191
  _unionAstNodes(options) {
186
192
  let typeA, typeB;
187
193
  const data = options.map((i) => this.nodes.get(i.name));
188
- return {
189
- properties: data.reduce((acc, i, j) => {
190
- var _a, _b;
191
- for (const key in i.properties) {
192
- if (acc[key]) {
193
- acc[key] = structuredClone(acc[key]);
194
- typeA = acc[key].constructor.name;
195
- typeB = i.properties[key].constructor.name;
196
- if (typeA !== typeB) {
197
- this.warnings.push(`Merging properties with different types: ${typeA} ` +
198
- `(from ${(_a = data[j - 1]) === null || _a === void 0 ? void 0 : _a.name}) and ${typeB} ` +
199
- `(from ${i.name})`);
200
- }
201
- if (acc[key].arrayDimension !== i.properties[key].arrayDimension) {
202
- this.warnings.push(`Merging properties with different array dimensions: ` +
203
- `${acc[key].arrayDimension} (from ${(_b = data[j - 1]) === null || _b === void 0 ? void 0 : _b.name}) and ` +
204
- `${i.properties[key].arrayDimension} (from ${i.name})`);
205
- acc[key].arrayDimension = Math.max(acc[key].arrayDimension || 0, i.properties[key].arrayDimension || 0);
206
- }
207
- if (acc[key].isNullable !== i.properties[key].isNullable) {
208
- acc[key].isNullable = true;
209
- }
210
- if (acc[key].isOptional !== i.properties[key].isOptional) {
211
- acc[key].isOptional = true;
212
- }
213
- if (i.properties[key].description) {
214
- acc[key].description = i.properties[key].description;
215
- }
194
+ const properties = data.reduce((acc, i, j) => {
195
+ for (const key in i.properties) {
196
+ if (acc[key]) {
197
+ acc[key] = Object.assign(Object.create(Object.getPrototypeOf(acc[key])), acc[key]);
198
+ typeA = acc[key].constructor.name;
199
+ typeB = i.properties[key].constructor.name;
200
+ if (typeA !== typeB) {
201
+ this.warnings.push(`Merging properties with different types: ${typeA} ` +
202
+ `(from a previous variant) and ${typeB} ` +
203
+ `(from ${i.name})`);
204
+ }
205
+ if (acc[key].arrayDimension !== i.properties[key].arrayDimension) {
206
+ this.warnings.push(`Merging properties with different array dimensions: ` +
207
+ `${acc[key].arrayDimension} (from a previous variant) and ` +
208
+ `${i.properties[key].arrayDimension} (from ${i.name})`);
209
+ acc[key].arrayDimension = Math.max(acc[key].arrayDimension || 0, i.properties[key].arrayDimension || 0);
216
210
  }
217
- else {
218
- acc[key] = i.properties[key];
211
+ if (acc[key].isNullable !== i.properties[key].isNullable) {
212
+ acc[key].isNullable = true;
213
+ }
214
+ if (acc[key].isOptional !== i.properties[key].isOptional) {
215
+ acc[key].isOptional = true;
216
+ }
217
+ if (i.properties[key].description) {
218
+ acc[key].description = i.properties[key].description;
219
219
  }
220
220
  }
221
- return acc;
222
- }, {}),
223
- };
221
+ else {
222
+ acc[key] = i.properties[key]; // New property, just add it
223
+ }
224
+ }
225
+ return acc;
226
+ }, {});
227
+ for (const key in properties) {
228
+ if (!data.every((variant) => key in variant.properties)) {
229
+ // In Union, if a property is not present in all variants, it should be considered
230
+ // optional. Shallow-clone preserving prototype before mutating, to avoid corrupting
231
+ // the original cached AST node.
232
+ properties[key] = Object.assign(Object.create(Object.getPrototypeOf(properties[key])), properties[key]);
233
+ properties[key].isOptional = true;
234
+ }
235
+ }
236
+ return { properties };
224
237
  }
225
238
  /**
226
239
  * Retrieves the name and associated transpilerable file information for a given Zod schema.
@@ -99,7 +99,9 @@ function Layer(opt) {
99
99
  layer: opt,
100
100
  typeName: name,
101
101
  // Generics associated to parent, but related to current type.
102
- genericTypes: metadata.genericTypes,
102
+ genericTypes: metadata.isGenericChild === false
103
+ ? metadata.genericTypes
104
+ : undefined,
103
105
  isGenericChild: true,
104
106
  };
105
107
  }
@@ -44,5 +44,7 @@ export declare class Zod2XModel {
44
44
  transpile(target: Target<"Zod2Cpp17">, opt?: TargetOpt<"Zod2Cpp17">, astOpt?: AstOpt): string;
45
45
  transpile(target: Target<"Zod2Ts">, opt?: TargetOpt<"Zod2Ts">, astOpt?: AstOpt): string;
46
46
  transpile(target: Target<"Zod2Py">, opt?: TargetOpt<"Zod2Py">, astOpt?: AstOpt): string;
47
+ transpile(target: Target<"Zod2Go">, opt?: TargetOpt<"Zod2Go">, astOpt?: AstOpt): string;
48
+ transpile(target: Target<"Zod2Dart">, opt?: TargetOpt<"Zod2Dart">, astOpt?: AstOpt): string;
47
49
  }
48
50
  export {};
@@ -59,7 +59,7 @@ class Zod2XModel {
59
59
  return this.astNodes;
60
60
  }
61
61
  transpile(target, opt = {}, astOpt) {
62
- const transpilerInstance = new target(Object.assign(Object.assign({}, opt), { namespace: this.getLayerMetadata().namespace }));
62
+ const transpilerInstance = new target(Object.assign(Object.assign({}, opt), { namespace: this.getLayerMetadata().namespace, partFile: this.getLayerMetadata().file }));
63
63
  return transpilerInstance.transpile(this.getAstNode(astOpt));
64
64
  }
65
65
  }
@@ -28,8 +28,15 @@ export declare class Zod2Cpp extends Zod2X<IZod2CppOpt> {
28
28
  type?: "union" | "alias";
29
29
  isInternal?: boolean;
30
30
  templates?: string;
31
+ templateDefinition?: string;
32
+ templateList?: string;
31
33
  }): void;
32
34
  protected getGenericTemplatesTranslation(data: ASTNode): string | undefined;
35
+ /**
36
+ * Emits an alias/extension declaration early for layered references.
37
+ * It keeps concrete template translations and falls back to declared templates (e.g. <T>)
38
+ * for aliases of generic templates.
39
+ */
33
40
  protected checkExtendedTypeInclusion(data: ASTNode, type?: "union" | "alias"): boolean;
34
41
  protected runAfter(): void;
35
42
  protected getDateType: () => string;
@@ -60,8 +67,14 @@ export declare class Zod2Cpp extends Zod2X<IZod2CppOpt> {
60
67
  protected getMapType(keyType: string, valueType: string): string;
61
68
  protected getRecordType(keyType: string, valueType: string): string;
62
69
  protected _getOptional(type: string): string;
63
- protected _addExtendedTypeSerializer(typeName: string, parentNamespace: string): void;
64
- protected _addExtendedTypeDeserializer(typeName: string, parentNamespace: string): void;
70
+ protected _addExtendedTypeSerializer(typeName: string, parentNamespace: string, opt?: {
71
+ templateDefinition?: string;
72
+ templateList?: string;
73
+ }): void;
74
+ protected _addExtendedTypeDeserializer(typeName: string, parentNamespace: string, opt?: {
75
+ templateDefinition?: string;
76
+ templateList?: string;
77
+ }): void;
65
78
  protected transpileAliasedType(data: ASTAliasedTypes): void;
66
79
  /** Ex:
67
80
  * enum class EnumA: int {
@@ -100,6 +100,9 @@ class Zod2Cpp extends core_1.Zod2X {
100
100
  ? aliasOf
101
101
  : this.getTypeFromExternalNamespace(parentNamespace, aliasOf);
102
102
  const templates = (_a = opt === null || opt === void 0 ? void 0 : opt.templates) !== null && _a !== void 0 ? _a : "";
103
+ if (opt === null || opt === void 0 ? void 0 : opt.templateDefinition) {
104
+ this.push0(opt.templateDefinition);
105
+ }
103
106
  if ((opt === null || opt === void 0 ? void 0 : opt.type) === "union" || (opt === null || opt === void 0 ? void 0 : opt.type) === "alias") {
104
107
  this.push0(`using ${name} = ${extendedType}${templates};\n`);
105
108
  }
@@ -112,8 +115,14 @@ class Zod2Cpp extends core_1.Zod2X {
112
115
  }
113
116
  }
114
117
  if ((opt === null || opt === void 0 ? void 0 : opt.type) !== "alias" && parentNamespace !== undefined) {
115
- this._addExtendedTypeSerializer(name, parentNamespace);
116
- this._addExtendedTypeDeserializer(name, parentNamespace);
118
+ this._addExtendedTypeSerializer(name, parentNamespace, {
119
+ templateDefinition: opt === null || opt === void 0 ? void 0 : opt.templateDefinition,
120
+ templateList: opt === null || opt === void 0 ? void 0 : opt.templateList,
121
+ });
122
+ this._addExtendedTypeDeserializer(name, parentNamespace, {
123
+ templateDefinition: opt === null || opt === void 0 ? void 0 : opt.templateDefinition,
124
+ templateList: opt === null || opt === void 0 ? void 0 : opt.templateList,
125
+ });
117
126
  }
118
127
  }
119
128
  getGenericTemplatesTranslation(data) {
@@ -134,12 +143,28 @@ class Zod2Cpp extends core_1.Zod2X {
134
143
  ">");
135
144
  }
136
145
  }
146
+ /**
147
+ * Emits an alias/extension declaration early for layered references.
148
+ * It keeps concrete template translations and falls back to declared templates (e.g. <T>)
149
+ * for aliases of generic templates.
150
+ */
137
151
  checkExtendedTypeInclusion(data, type) {
152
+ const templatesMeta = data instanceof core_1.ASTObject && data.templates.size > 0
153
+ ? this._getTemplates(data.templates)
154
+ : undefined;
155
+ const translatedTemplates = this.getGenericTemplatesTranslation(data);
156
+ const templates = translatedTemplates || (templatesMeta === null || templatesMeta === void 0 ? void 0 : templatesMeta.templateList);
157
+ const templateList = translatedTemplates ? undefined : templatesMeta === null || templatesMeta === void 0 ? void 0 : templatesMeta.templateList;
158
+ const templateDefinition = translatedTemplates
159
+ ? undefined
160
+ : templatesMeta === null || templatesMeta === void 0 ? void 0 : templatesMeta.templateDefinition;
138
161
  if (this.isExternalTypeImport(data)) {
139
162
  if (data.aliasOf) {
140
163
  this.addExtendedType(data.name, data.parentNamespace, data.aliasOf, {
141
164
  type,
142
- templates: this.getGenericTemplatesTranslation(data),
165
+ templates,
166
+ templateDefinition,
167
+ templateList,
143
168
  });
144
169
  this.addExternalTypeImport(data);
145
170
  }
@@ -149,7 +174,9 @@ class Zod2Cpp extends core_1.Zod2X {
149
174
  this.addExtendedType(data.name, data.parentNamespace, data.aliasOf, {
150
175
  type,
151
176
  isInternal: true,
152
- templates: this.getGenericTemplatesTranslation(data),
177
+ templates,
178
+ templateDefinition,
179
+ templateList,
153
180
  });
154
181
  return true;
155
182
  }
@@ -205,13 +232,23 @@ class Zod2Cpp extends core_1.Zod2X {
205
232
  this.imports.add(this.lib.optional);
206
233
  return `boost::optional<${type}>`;
207
234
  }
208
- _addExtendedTypeSerializer(typeName, parentNamespace) {
209
- this._push0(this.serializers, `inline void to_json(${nlohmann_1.NLOHMANN}& j, const ${typeName}& x) {`);
235
+ _addExtendedTypeSerializer(typeName, parentNamespace, opt) {
236
+ var _a;
237
+ if (opt === null || opt === void 0 ? void 0 : opt.templateDefinition) {
238
+ this._push0(this.serializers, opt.templateDefinition);
239
+ }
240
+ const typeNameWithTemplates = `${typeName}${(_a = opt === null || opt === void 0 ? void 0 : opt.templateList) !== null && _a !== void 0 ? _a : ""}`;
241
+ this._push0(this.serializers, `inline void to_json(${nlohmann_1.NLOHMANN}& j, const ${typeNameWithTemplates}& x) {`);
210
242
  this._push1(this.serializers, `${parentNamespace}::to_json(j, x);`);
211
243
  this._push0(this.serializers, "}\n");
212
244
  }
213
- _addExtendedTypeDeserializer(typeName, parentNamespace) {
214
- this._push0(this.serializers, `inline void from_json(const ${nlohmann_1.NLOHMANN}& j, ${typeName}& x) {`);
245
+ _addExtendedTypeDeserializer(typeName, parentNamespace, opt) {
246
+ var _a;
247
+ if (opt === null || opt === void 0 ? void 0 : opt.templateDefinition) {
248
+ this._push0(this.serializers, opt.templateDefinition);
249
+ }
250
+ const typeNameWithTemplates = `${typeName}${(_a = opt === null || opt === void 0 ? void 0 : opt.templateList) !== null && _a !== void 0 ? _a : ""}`;
251
+ this._push0(this.serializers, `inline void from_json(const ${nlohmann_1.NLOHMANN}& j, ${typeNameWithTemplates}& x) {`);
215
252
  this._push1(this.serializers, `${parentNamespace}::from_json(j, x);`);
216
253
  this._push0(this.serializers, "}\n");
217
254
  }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Dart package imports for json_annotation / json_serializable.
3
+ */
4
+ export declare function getLibs(): {
5
+ jsonAnnotation: string;
6
+ };
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getLibs = getLibs;
4
+ /**
5
+ * Dart package imports for json_annotation / json_serializable.
6
+ */
7
+ function getLibs() {
8
+ return {
9
+ jsonAnnotation: "import 'package:json_annotation/json_annotation.dart';",
10
+ };
11
+ }
@@ -0,0 +1,21 @@
1
+ import { IZodToXOpt } from "../../core";
2
+ export interface IZod2DartOpt extends IZodToXOpt {
3
+ /**
4
+ * By default (false), class property names are converted to camelCase following Dart
5
+ * conventions. If set to true, the original property names are preserved as-is.
6
+ */
7
+ keepKeys?: boolean;
8
+ /**
9
+ * When true (default), emits `@JsonSerializable()` annotations, `@JsonEnum`, `@JsonKey`,
10
+ * and `fromJson`/`toJson` delegation stubs. Requires `package:json_annotation`.
11
+ * The `.g.dart` part file is generated externally by `dart run build_runner build`.
12
+ */
13
+ useJsonSerialization?: boolean;
14
+ /**
15
+ * Filename (without extension) used for the `part '${partFile}.g.dart';` directive.
16
+ * When using layered modeling, this is automatically set to the layer's `file` metadata.
17
+ * If omitted, no `part` directive is emitted.
18
+ */
19
+ partFile?: string;
20
+ }
21
+ export declare const defaultOpts: IZod2DartOpt;
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defaultOpts = void 0;
4
+ exports.defaultOpts = {
5
+ indent: 2,
6
+ includeComments: true,
7
+ useImports: true,
8
+ keepKeys: false,
9
+ useJsonSerialization: true,
10
+ };
@@ -0,0 +1,149 @@
1
+ import { ASTAliasedTypes, ASTEnum, ASTIntersection, ASTNode, ASTNodes, ASTObject, ASTUnion, Zod2X } from "../../core";
2
+ import { IZod2DartOpt } from "./options";
3
+ /**
4
+ * Transpiler for Zod schemas to Dart classes using package:json_annotation.
5
+ *
6
+ * The `.g.dart` part file is NOT generated by this transpiler — it must be produced
7
+ * externally via `dart run build_runner build`.
8
+ */
9
+ export declare class Zod2Dart extends Zod2X<IZod2DartOpt> {
10
+ protected readonly commentKey = "//";
11
+ protected lib: {
12
+ jsonAnnotation: string;
13
+ };
14
+ /**
15
+ * Maps a local struct/class name to the discriminated union names it participates in.
16
+ * Populated by a pre-scan of the AST before the normal transpile pass.
17
+ */
18
+ private _unionMembers;
19
+ /**
20
+ * Names of locally-defined discriminated union abstract classes.
21
+ * Used to emit @JsonKey(fromJson/toJson) when such a type appears as a field.
22
+ */
23
+ private _discriminatedUnionTypes;
24
+ /**
25
+ * Names of typedef-emitted types (alias, union typedef, struct extends).
26
+ * When these appear as field types in @JsonSerializable classes, we emit
27
+ * @JsonKey(fromJson: TypeName.fromJson) to prevent json_serializable from
28
+ * following the typedef chain and referencing transitive imports.
29
+ */
30
+ private _typedefNames;
31
+ /**
32
+ * Maps a disc union typedef name (e.g. "NewDiscriminatedUnionItem") to the
33
+ * fromJson function name of the underlying entity-level union
34
+ * (e.g. "discriminatedUnionItemFromJson").
35
+ * Populated during pre-scan when an ASTUnion node has aliasOf set.
36
+ */
37
+ private _discriminatedUnionDelegateFromJson;
38
+ /**
39
+ * Unified set of type names needing custom @JsonKey annotations.
40
+ * - Discriminated union types: fromJson = <camelName>FromJson (local function)
41
+ * - Typedef types: fromJson = _<camelName>FromJson (standalone wrapper)
42
+ * - TypedefList: list fromJson/toJson helpers
43
+ * _toJson helpers are emitted in runAfter() for all entries.
44
+ */
45
+ private _usedCustomFromJsonTypes;
46
+ /**
47
+ * Maps a type name (e.g. "GenericUserEntity") to its full Dart type with
48
+ * template args (e.g. "GenericUserEntity<SomeDtoResult>"). Used in runAfter()
49
+ * to generate helpers with correct generic return types and factory calls.
50
+ */
51
+ private _usedCustomFromJsonFullTypes;
52
+ /**
53
+ * Maps a typedef name to its full extended type (the right-hand side of the
54
+ * typedef). E.g. "AdminUserEntity" → "GenericUserEntity<AdminUserMetadata>".
55
+ * Populated in addExtendedType() when the extended type has generic args.
56
+ * Used in runAfter() to generate 2-arg fromJson calls for generic classes.
57
+ */
58
+ private _typedefToExtendedType;
59
+ constructor(opt?: IZod2DartOpt);
60
+ /**
61
+ * Overrides transpile() to pre-scan discriminated union memberships before the normal pass.
62
+ * This allows transpileStruct() to emit `implements UnionName` on member classes.
63
+ */
64
+ transpile(transpilerQueue: ASTNodes): string;
65
+ protected runBefore(): void;
66
+ protected runAfter(): void;
67
+ protected addImportFromFile(filename: string, _namespace: string): string;
68
+ protected getTypeFromExternalNamespace(_namespace: string, typeName: string): string;
69
+ protected getGenericTemplatesTranslation(data: ASTNode): string | undefined;
70
+ /**
71
+ * Emits an alias/extension declaration for cross-layer references.
72
+ */
73
+ protected checkExtendedTypeInclusion(data: ASTNode, type?: "union" | "alias"): boolean;
74
+ protected addExtendedType(name: string, parentNamespace: string, aliasOf: string, opt?: {
75
+ type?: "union" | "alias";
76
+ isInternal?: boolean;
77
+ templates?: string;
78
+ declaredTemplates?: string;
79
+ }): void;
80
+ protected getStringType: () => string;
81
+ protected getBooleanType: () => string;
82
+ protected getAnyType: () => string;
83
+ protected getDateType: () => string;
84
+ protected getNumberType(isInt: boolean, _range: {
85
+ min?: number;
86
+ max?: number;
87
+ }): string;
88
+ /**
89
+ * Returns the Dart type for a literal value.
90
+ * Dart has no structural literal types, so we return the underlying primitive type.
91
+ * When a parent enum is provided, returns the enum type name (not a member expression),
92
+ * since Dart enum members cannot be used as types.
93
+ */
94
+ protected getLiteralStringType(value: string | number | boolean, parentEnumNameKey?: [string, string]): string | number;
95
+ /** Ex: List<List<T>> for 2D array */
96
+ protected getArrayType(arrayType: string, arrayDeep: number): string;
97
+ /** Ex: Set<T> */
98
+ protected getSetType: (itemType: string) => string;
99
+ /** Ex: Map<K, V> */
100
+ protected getMapType: (keyType: string, valueType: string) => string;
101
+ /** Ex: Map<String, V> (record key is always String) */
102
+ protected getRecordType: (keyType: string, valueType: string) => string;
103
+ /** Ex: (T1, T2, T3) — Dart 3 positional record type */
104
+ protected getTupleType: (itemsType: string[]) => string;
105
+ /** Dart has no native union type; use Object */
106
+ protected getUnionType: (_itemsType: string[]) => string;
107
+ /** Dart has no native intersection type; use Object */
108
+ protected getIntersectionType: (_itemsType: string[]) => string;
109
+ protected transpileAliasedType(data: ASTAliasedTypes): void;
110
+ /**
111
+ * Emits a Dart enhanced enum with a typed `value` field and `@JsonEnum` annotation.
112
+ *
113
+ * All-string values:
114
+ * @JsonEnum(valueField: 'value')
115
+ * enum EnumItem {
116
+ * enum1('Enum1'),
117
+ * enum2('Enum2');
118
+ *
119
+ * const EnumItem(this.value);
120
+ * final String value;
121
+ * }
122
+ *
123
+ * Mixed (int + string): typedef alias with comment.
124
+ */
125
+ protected transpileEnum(data: ASTEnum): void;
126
+ protected transpileStruct(data: ASTObject): void;
127
+ /**
128
+ * Dart intersection:
129
+ * - If the AST produced a merged `newObject`, emit it as a flat class.
130
+ * - Otherwise emit a typedef alias to Object with a comment.
131
+ */
132
+ protected transpileIntersection(data: ASTIntersection): void;
133
+ /**
134
+ * Dart union:
135
+ * - Non-discriminated: typedef alias to Object with a comment listing member types.
136
+ * - Discriminated: abstract base class + factory unmarshal function using Dart 3 switch.
137
+ */
138
+ protected transpileUnion(data: ASTUnion): void;
139
+ /** Renders the full body of a Dart class for an ASTObject. */
140
+ private _transpileStructBody;
141
+ /** Renders a single class field declaration with optional `@JsonKey` annotation. */
142
+ private _transpileMember;
143
+ /**
144
+ * Emits `fromJson` factory and `toJson` method delegation stubs.
145
+ * For generic classes, extra `fromJsonT` / `toJsonT` function parameters are added
146
+ * as required by `json_serializable` with `genericArgumentFactories: true`.
147
+ */
148
+ private _emitFromToJson;
149
+ }