zod-to-x 2.4.0 → 2.6.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 +15 -0
- package/dist/core/ast-types/ast_common.d.ts +18 -1
- package/dist/core/ast-types/ast_common.js +11 -0
- package/dist/core/ast-types/ast_complex.d.ts +11 -2
- package/dist/core/ast-types/ast_complex.js +9 -0
- package/dist/core/ast-types/ast_simple.d.ts +6 -0
- package/dist/core/ast-types/ast_simple.js +6 -0
- package/dist/core/ast_node.d.ts +25 -0
- package/dist/core/ast_node.js +173 -53
- package/dist/core/transpiler.d.ts +32 -5
- package/dist/core/transpiler.js +62 -2
- package/dist/layered-modeling/layer.js +66 -32
- package/dist/layered-modeling/model.js +9 -5
- package/dist/lib/zod2x_metadata.d.ts +42 -0
- package/dist/lib/zod2x_metadata.js +78 -0
- package/dist/lib/zod_ext.d.ts +39 -29
- package/dist/lib/zod_ext.js +12 -11
- package/dist/lib/zod_helpers.d.ts +55 -5
- package/dist/lib/zod_helpers.js +114 -24
- package/dist/transpilers/cpp/runner.d.ts +8 -6
- package/dist/transpilers/cpp/runner.js +8 -50
- package/dist/transpilers/dart/runner.d.ts +11 -4
- package/dist/transpilers/dart/runner.js +48 -57
- package/dist/transpilers/go/runner.d.ts +8 -4
- package/dist/transpilers/go/runner.js +11 -46
- package/dist/transpilers/python/runner.d.ts +8 -6
- package/dist/transpilers/python/runner.js +8 -44
- package/dist/transpilers/typescript/runner.d.ts +7 -6
- package/dist/transpilers/typescript/runner.js +7 -45
- package/package.json +8 -4
package/dist/core/ast_node.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Zod2Ast = void 0;
|
|
4
4
|
const core_1 = require("../core");
|
|
5
|
+
const zod2x_metadata_1 = require("../lib/zod2x_metadata");
|
|
5
6
|
const zod_helpers_1 = require("../lib/zod_helpers");
|
|
6
7
|
const logger_1 = require("../utils/logger");
|
|
7
8
|
const errors_1 = require("./errors");
|
|
@@ -14,6 +15,7 @@ class Zod2Ast {
|
|
|
14
15
|
constructor(opt = {}) {
|
|
15
16
|
var _a;
|
|
16
17
|
this.nodes = new Map();
|
|
18
|
+
this.nodeSchemas = new Map();
|
|
17
19
|
this.lazyPointers = [];
|
|
18
20
|
this.warnings = [];
|
|
19
21
|
this.opt = Object.assign(Object.assign({}, opt), { strict: (_a = opt.strict) !== null && _a !== void 0 ? _a : true });
|
|
@@ -30,6 +32,77 @@ class Zod2Ast {
|
|
|
30
32
|
parentFile === undefined ||
|
|
31
33
|
((_a = this.opt.layer) === null || _a === void 0 ? void 0 : _a.file) === parentFile);
|
|
32
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* Returns the key used to store a transpilerable node. Types imported from other files are
|
|
37
|
+
* namespaced by their file, so they do not clash with local types that share the same name.
|
|
38
|
+
* Aliases of external types are local definitions.
|
|
39
|
+
*/
|
|
40
|
+
_getNodeKey(item) {
|
|
41
|
+
return item.parentFile !== undefined && item.aliasOf === undefined
|
|
42
|
+
? `${item.parentFile}::${item.name}`
|
|
43
|
+
: item.name;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Determines if two schemas that share the same type name represent the same definition.
|
|
47
|
+
* Schemas created from the same definition (`.zod2x()`, `.describe()`, `.meta()`, layer
|
|
48
|
+
* aliases) and instances of the same generic type are considered equal. Otherwise, a shallow
|
|
49
|
+
* structural comparison is performed.
|
|
50
|
+
*/
|
|
51
|
+
_isSameDefinition(a, b) {
|
|
52
|
+
var _a, _b;
|
|
53
|
+
if (a === b || a.def === b.def) {
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
if (((_a = (0, zod2x_metadata_1.resolveZod2xMetadata)(a)) === null || _a === void 0 ? void 0 : _a.genericTypes) !== undefined ||
|
|
57
|
+
((_b = (0, zod2x_metadata_1.resolveZod2xMetadata)(b)) === null || _b === void 0 ? void 0 : _b.genericTypes) !== undefined) {
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
if (a.def.type !== b.def.type) {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
const sameSignatures = (x, y) => x.length === y.length &&
|
|
64
|
+
x.every((i, j) => zod_helpers_1.ZodHelpers.getShallowSignature(i) === zod_helpers_1.ZodHelpers.getShallowSignature(y[j]));
|
|
65
|
+
if (zod_helpers_1.ZodHelpers.isZodObject(a) && zod_helpers_1.ZodHelpers.isZodObject(b)) {
|
|
66
|
+
const keysA = Object.keys(a.def.shape);
|
|
67
|
+
const keysB = Object.keys(b.def.shape);
|
|
68
|
+
return (keysA.length === keysB.length &&
|
|
69
|
+
keysA.every((key) => key in b.def.shape) &&
|
|
70
|
+
sameSignatures(keysA.map((key) => a.def.shape[key]), keysA.map((key) => b.def.shape[key])));
|
|
71
|
+
}
|
|
72
|
+
else if (zod_helpers_1.ZodHelpers.isZodEnum(a) && zod_helpers_1.ZodHelpers.isZodEnum(b)) {
|
|
73
|
+
return JSON.stringify(a.enum) === JSON.stringify(b.enum);
|
|
74
|
+
}
|
|
75
|
+
else if (zod_helpers_1.ZodHelpers.isZodAnyUnionType(a) && zod_helpers_1.ZodHelpers.isZodAnyUnionType(b)) {
|
|
76
|
+
return sameSignatures(a.def.options, b.def.options);
|
|
77
|
+
}
|
|
78
|
+
else if (zod_helpers_1.ZodHelpers.isZodIntersection(a) && zod_helpers_1.ZodHelpers.isZodIntersection(b)) {
|
|
79
|
+
return sameSignatures([a.def.left, a.def.right], [b.def.left, b.def.right]);
|
|
80
|
+
}
|
|
81
|
+
else if (zod_helpers_1.ZodHelpers.isZodArray(a) && zod_helpers_1.ZodHelpers.isZodArray(b)) {
|
|
82
|
+
return sameSignatures([a.element], [b.element]);
|
|
83
|
+
}
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Checks if a transpilerable node is already registered.
|
|
88
|
+
*
|
|
89
|
+
* @throws AstTypeNameDefinitionError - If the node key is used by a different schema.
|
|
90
|
+
*/
|
|
91
|
+
_hasNode(key, schema) {
|
|
92
|
+
const registered = this.nodeSchemas.get(key);
|
|
93
|
+
if (registered === undefined) {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
if (!this._isSameDefinition(registered, schema)) {
|
|
97
|
+
throw new errors_1.AstTypeNameDefinitionError(`Type name '${key}' is used by different schemas. Each transpilerable type ` +
|
|
98
|
+
`must have a unique name.`);
|
|
99
|
+
}
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
_setNode(key, schema, node) {
|
|
103
|
+
this.nodes.set(key, node);
|
|
104
|
+
this.nodeSchemas.set(key, schema);
|
|
105
|
+
}
|
|
33
106
|
/**
|
|
34
107
|
* Check if the layer of the item is compatible with the layer of the schema. If does and the
|
|
35
108
|
* transpilerable item is in a different file, it returns the file name.
|
|
@@ -44,19 +117,24 @@ class Zod2Ast {
|
|
|
44
117
|
if (this.opt.layer !== undefined && (metadata === null || metadata === void 0 ? void 0 : metadata.layer) !== undefined) {
|
|
45
118
|
if (Array.isArray(metadata.genericTypes)) {
|
|
46
119
|
// Check that all templates used with a generic type follows the layering rules
|
|
47
|
-
if (metadata.genericTypes.some((i) => this.opt.layer.index < i.layer.index)) {
|
|
120
|
+
if (metadata.genericTypes.some((i) => i.layer !== undefined && this.opt.layer.index < i.layer.index)) {
|
|
48
121
|
throw new errors_1.BadLayerDefinitionError(`${itemName}: Layer with number ${this.opt.layer.index} can only use models` +
|
|
49
122
|
`from the same or lower layer. Review templates used for generic ` +
|
|
50
123
|
`type ${metadata.typeName}.`);
|
|
51
124
|
}
|
|
52
125
|
}
|
|
53
|
-
const templatesTranslation = (_a = metadata
|
|
54
|
-
var _a
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
126
|
+
const templatesTranslation = (_a = metadata.genericTypes) === null || _a === void 0 ? void 0 : _a.map((i) => {
|
|
127
|
+
var _a;
|
|
128
|
+
if (i.typeName === undefined) {
|
|
129
|
+
// Not named types (basic types, arrays, ...) are used directly.
|
|
130
|
+
return { type: this._zodToAST(i.schema) };
|
|
131
|
+
}
|
|
132
|
+
const isExternal = i.layer !== undefined && ((_a = this.opt.layer) === null || _a === void 0 ? void 0 : _a.file) !== i.layer.file;
|
|
133
|
+
return {
|
|
134
|
+
parentFile: isExternal ? i.layer.file : undefined,
|
|
135
|
+
parentNamespace: isExternal ? i.layer.namespace : undefined,
|
|
58
136
|
aliasOf: i.typeName,
|
|
59
|
-
}
|
|
137
|
+
};
|
|
60
138
|
});
|
|
61
139
|
if (metadata.layer.file === this.opt.layer.file) {
|
|
62
140
|
// Case 1: Only layer exists and belongs to the same file
|
|
@@ -113,7 +191,7 @@ class Zod2Ast {
|
|
|
113
191
|
_createDefinition(node, constraints = {}, templatesTranslation = []) {
|
|
114
192
|
return new core_1.ASTDefinition({
|
|
115
193
|
name: node.name,
|
|
116
|
-
instanceType: node
|
|
194
|
+
instanceType: (0, core_1.getASTKind)(node),
|
|
117
195
|
parentFile: node.parentFile,
|
|
118
196
|
parentNamespace: node.parentNamespace,
|
|
119
197
|
aliasOf: node.aliasOf,
|
|
@@ -183,13 +261,13 @@ class Zod2Ast {
|
|
|
183
261
|
*/
|
|
184
262
|
_unionAstNodes(options) {
|
|
185
263
|
let typeA, typeB;
|
|
186
|
-
const data = options.map((i) => this.nodes.get(i
|
|
264
|
+
const data = options.map((i) => this.nodes.get(this._getNodeKey(i)));
|
|
187
265
|
const properties = data.reduce((acc, i, j) => {
|
|
188
266
|
for (const key in i.properties) {
|
|
189
267
|
if (acc[key]) {
|
|
190
268
|
acc[key] = Object.assign(Object.create(Object.getPrototypeOf(acc[key])), acc[key]);
|
|
191
|
-
typeA = acc[key]
|
|
192
|
-
typeB = i.properties[key]
|
|
269
|
+
typeA = (0, core_1.getASTKind)(acc[key]);
|
|
270
|
+
typeB = (0, core_1.getASTKind)(i.properties[key]);
|
|
193
271
|
if (typeA !== typeB) {
|
|
194
272
|
this.warnings.push(`Merging properties with different types: ${typeA} ` +
|
|
195
273
|
`(from a previous variant) and ${typeB} ` +
|
|
@@ -243,7 +321,7 @@ class Zod2Ast {
|
|
|
243
321
|
*/
|
|
244
322
|
_getNames(schema) {
|
|
245
323
|
var _a, _b, _c;
|
|
246
|
-
const name = (_a =
|
|
324
|
+
const name = (_a = (0, zod2x_metadata_1.resolveZod2xMetadata)(schema)) === null || _a === void 0 ? void 0 : _a.typeName;
|
|
247
325
|
if (!name) {
|
|
248
326
|
let itemProperties = ["Unknown type"];
|
|
249
327
|
if (zod_helpers_1.ZodHelpers.isZodObject(schema)) {
|
|
@@ -252,15 +330,15 @@ class Zod2Ast {
|
|
|
252
330
|
else if (zod_helpers_1.ZodHelpers.isZodAnyUnionType(schema)) {
|
|
253
331
|
itemProperties = schema.def.options.map((i) => {
|
|
254
332
|
var _a;
|
|
255
|
-
return ((_a =
|
|
333
|
+
return ((_a = (0, zod2x_metadata_1.resolveZod2xMetadata)(i)) === null || _a === void 0 ? void 0 : _a.typeName) || i.def.type;
|
|
256
334
|
});
|
|
257
335
|
}
|
|
258
336
|
else if (zod_helpers_1.ZodHelpers.isZodIntersection(schema)) {
|
|
259
337
|
const left = schema.def.left;
|
|
260
338
|
const right = schema.def.right;
|
|
261
339
|
itemProperties = [
|
|
262
|
-
((_b =
|
|
263
|
-
((_c =
|
|
340
|
+
((_b = (0, zod2x_metadata_1.resolveZod2xMetadata)(left)) === null || _b === void 0 ? void 0 : _b.typeName) || left.def.type,
|
|
341
|
+
((_c = (0, zod2x_metadata_1.resolveZod2xMetadata)(right)) === null || _c === void 0 ? void 0 : _c.typeName) || right.def.type,
|
|
264
342
|
];
|
|
265
343
|
}
|
|
266
344
|
else if (zod_helpers_1.ZodHelpers.isZodEnum(schema)) {
|
|
@@ -270,7 +348,8 @@ class Zod2Ast {
|
|
|
270
348
|
`avoid nesting schemas definitions. Otherwise, use zod2x method to provide one. ` +
|
|
271
349
|
`Affected type properties: ${itemProperties.join(", ")}`);
|
|
272
350
|
}
|
|
273
|
-
|
|
351
|
+
const metadata = (0, zod2x_metadata_1.resolveZod2xMetadata)(schema);
|
|
352
|
+
return Object.assign({ name, genericOf: metadata === null || metadata === void 0 ? void 0 : metadata.genericOf }, this._getTranspilerableFile(name, metadata));
|
|
274
353
|
}
|
|
275
354
|
/**
|
|
276
355
|
* Generates an Abstract Syntax Tree (AST) definition for a Zod enum schema.
|
|
@@ -293,8 +372,9 @@ class Zod2Ast {
|
|
|
293
372
|
aliasOf,
|
|
294
373
|
isFromDiscriminatedUnion: opt === null || opt === void 0 ? void 0 : opt.isInjectedEnum,
|
|
295
374
|
});
|
|
296
|
-
|
|
297
|
-
|
|
375
|
+
const key = this._getNodeKey(item);
|
|
376
|
+
if (!this._hasNode(key, schema)) {
|
|
377
|
+
this._setNode(key, schema, item);
|
|
298
378
|
}
|
|
299
379
|
return this._createDefinition(item);
|
|
300
380
|
}
|
|
@@ -309,10 +389,11 @@ class Zod2Ast {
|
|
|
309
389
|
*/
|
|
310
390
|
_getObjectAst(schema, opt) {
|
|
311
391
|
var _a;
|
|
312
|
-
const { name, parentFile, parentNamespace, aliasOf, templatesTranslation, isGenericChild } = this._getNames(schema);
|
|
392
|
+
const { name, parentFile, parentNamespace, aliasOf, templatesTranslation, isGenericChild, genericOf, } = this._getNames(schema);
|
|
313
393
|
let discriminantValue = undefined;
|
|
314
394
|
const shape = schema.def.shape;
|
|
315
|
-
|
|
395
|
+
const key = this._getNodeKey({ name, parentFile, aliasOf });
|
|
396
|
+
if (!this._hasNode(key, schema)) {
|
|
316
397
|
const properties = {};
|
|
317
398
|
const templates = new Set();
|
|
318
399
|
for (const key in shape) {
|
|
@@ -332,7 +413,7 @@ class Zod2Ast {
|
|
|
332
413
|
if (opt === null || opt === void 0 ? void 0 : opt.skipLayerClass) {
|
|
333
414
|
return {}; // Layer classes are not transpilerable
|
|
334
415
|
}
|
|
335
|
-
this.
|
|
416
|
+
this._setNode(key, schema, new core_1.ASTObject({
|
|
336
417
|
name,
|
|
337
418
|
properties,
|
|
338
419
|
description: (_a = schema.meta()) === null || _a === void 0 ? void 0 : _a.description,
|
|
@@ -341,9 +422,10 @@ class Zod2Ast {
|
|
|
341
422
|
aliasOf,
|
|
342
423
|
templates,
|
|
343
424
|
templatesTranslation: templatesTranslation || [],
|
|
425
|
+
genericOf,
|
|
344
426
|
}));
|
|
345
427
|
}
|
|
346
|
-
const item = this.nodes.get(
|
|
428
|
+
const item = this.nodes.get(key);
|
|
347
429
|
if (opt === null || opt === void 0 ? void 0 : opt.discriminantKey) {
|
|
348
430
|
if (Object.keys(item.properties).includes(opt.discriminantKey)) {
|
|
349
431
|
const key = opt.discriminantKey;
|
|
@@ -357,7 +439,7 @@ class Zod2Ast {
|
|
|
357
439
|
}
|
|
358
440
|
}
|
|
359
441
|
}
|
|
360
|
-
return this._createDefinition(
|
|
442
|
+
return this._createDefinition(item, { discriminantValue }, isGenericChild ? undefined : templatesTranslation);
|
|
361
443
|
}
|
|
362
444
|
/**
|
|
363
445
|
* Generates an Abstract Syntax Tree (AST) definition for a Zod union schema.
|
|
@@ -415,8 +497,9 @@ class Zod2Ast {
|
|
|
415
497
|
templatesTranslation: [],
|
|
416
498
|
});
|
|
417
499
|
}
|
|
418
|
-
|
|
419
|
-
|
|
500
|
+
const key = this._getNodeKey(item);
|
|
501
|
+
if (!this._hasNode(key, schema)) {
|
|
502
|
+
this._setNode(key, schema, item);
|
|
420
503
|
}
|
|
421
504
|
return this._createDefinition(item);
|
|
422
505
|
}
|
|
@@ -464,8 +547,9 @@ class Zod2Ast {
|
|
|
464
547
|
templatesTranslation: [],
|
|
465
548
|
});
|
|
466
549
|
}
|
|
467
|
-
|
|
468
|
-
|
|
550
|
+
const key = this._getNodeKey(item);
|
|
551
|
+
if (!this._hasNode(key, schema)) {
|
|
552
|
+
this._setNode(key, schema, item);
|
|
469
553
|
}
|
|
470
554
|
return this._createDefinition(item);
|
|
471
555
|
}
|
|
@@ -487,14 +571,16 @@ class Zod2Ast {
|
|
|
487
571
|
parentNamespace,
|
|
488
572
|
aliasOf,
|
|
489
573
|
});
|
|
490
|
-
|
|
491
|
-
|
|
574
|
+
const key = this._getNodeKey(item);
|
|
575
|
+
if (!this._hasNode(key, schema)) {
|
|
576
|
+
this._setNode(key, schema, item);
|
|
492
577
|
}
|
|
493
578
|
return this._createDefinition(item);
|
|
494
579
|
}
|
|
495
580
|
_getAliasAst(schema, item) {
|
|
496
581
|
var _a;
|
|
497
|
-
if (((_a =
|
|
582
|
+
if (((_a = (0, zod2x_metadata_1.resolveZod2xMetadata)(schema)) === null || _a === void 0 ? void 0 : _a.typeName) === undefined ||
|
|
583
|
+
this.opt.skipBasicTypes === true) {
|
|
498
584
|
return item;
|
|
499
585
|
}
|
|
500
586
|
const { name, parentFile, parentNamespace, aliasOf } = this._getNames(schema);
|
|
@@ -502,8 +588,9 @@ class Zod2Ast {
|
|
|
502
588
|
item.parentFile = parentFile;
|
|
503
589
|
item.parentNamespace = parentNamespace;
|
|
504
590
|
item.aliasOf = aliasOf;
|
|
505
|
-
|
|
506
|
-
|
|
591
|
+
const key = this._getNodeKey(item);
|
|
592
|
+
if (!this._hasNode(key, schema)) {
|
|
593
|
+
this._setNode(key, schema, item);
|
|
507
594
|
}
|
|
508
595
|
return this._createDefinition(item);
|
|
509
596
|
}
|
|
@@ -513,7 +600,7 @@ class Zod2Ast {
|
|
|
513
600
|
* @returns
|
|
514
601
|
*/
|
|
515
602
|
_zodToAST(schema, opt) {
|
|
516
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
|
|
603
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w;
|
|
517
604
|
if (zod_helpers_1.ZodHelpers.isZodString(schema)) {
|
|
518
605
|
return this._getAliasAst(schema, new core_1.ASTString({ description: (_a = schema.meta()) === null || _a === void 0 ? void 0 : _a.description }));
|
|
519
606
|
}
|
|
@@ -544,19 +631,33 @@ class Zod2Ast {
|
|
|
544
631
|
subSchema.description = ((_g = schema.meta()) === null || _g === void 0 ? void 0 : _g.description) || subSchema.description;
|
|
545
632
|
return subSchema;
|
|
546
633
|
}
|
|
547
|
-
else if (zod_helpers_1.ZodHelpers.
|
|
548
|
-
const subSchema = this._zodToAST(schema.def.
|
|
634
|
+
else if (zod_helpers_1.ZodHelpers.isZodNonOptional(schema)) {
|
|
635
|
+
const subSchema = this._zodToAST(schema.def.innerType, opt);
|
|
636
|
+
subSchema.isOptional = false;
|
|
549
637
|
subSchema.description = ((_h = schema.meta()) === null || _h === void 0 ? void 0 : _h.description) || subSchema.description;
|
|
550
638
|
return subSchema;
|
|
551
639
|
}
|
|
640
|
+
else if (zod_helpers_1.ZodHelpers.isZodTransparentWrapper(schema)) {
|
|
641
|
+
const subSchema = this._zodToAST(schema.def.innerType, opt);
|
|
642
|
+
subSchema.description = ((_j = schema.meta()) === null || _j === void 0 ? void 0 : _j.description) || subSchema.description;
|
|
643
|
+
return subSchema;
|
|
644
|
+
}
|
|
645
|
+
else if (zod_helpers_1.ZodHelpers.isZodPipe(schema)) {
|
|
646
|
+
const subSchema = this._zodToAST(zod_helpers_1.ZodHelpers.getPipeModelSchema(schema), opt);
|
|
647
|
+
subSchema.description = ((_k = schema.meta()) === null || _k === void 0 ? void 0 : _k.description) || subSchema.description;
|
|
648
|
+
return subSchema;
|
|
649
|
+
}
|
|
650
|
+
else if (zod_helpers_1.ZodHelpers.isZodUnknown(schema)) {
|
|
651
|
+
return new core_1.ASTAny({ description: (_l = schema.meta()) === null || _l === void 0 ? void 0 : _l.description });
|
|
652
|
+
}
|
|
552
653
|
else if (zod_helpers_1.ZodHelpers.isZodArray(schema)) {
|
|
553
654
|
const isParentArray = (opt === null || opt === void 0 ? void 0 : opt.calledFromArray) !== true;
|
|
554
655
|
const subSchema = this._zodToAST(schema.element, { calledFromArray: true });
|
|
555
|
-
subSchema.description = ((
|
|
656
|
+
subSchema.description = ((_m = schema.meta()) === null || _m === void 0 ? void 0 : _m.description) || subSchema.description;
|
|
556
657
|
subSchema.arrayDimension = Number.isInteger(subSchema.arrayDimension)
|
|
557
658
|
? ++subSchema.arrayDimension
|
|
558
659
|
: 1;
|
|
559
|
-
if (isParentArray && ((
|
|
660
|
+
if (isParentArray && ((_o = (0, zod2x_metadata_1.resolveZod2xMetadata)(schema)) === null || _o === void 0 ? void 0 : _o.typeName)) {
|
|
560
661
|
return this._getArrayAst(schema, subSchema);
|
|
561
662
|
}
|
|
562
663
|
else {
|
|
@@ -566,22 +667,22 @@ class Zod2Ast {
|
|
|
566
667
|
else if (zod_helpers_1.ZodHelpers.isZodSet(schema)) {
|
|
567
668
|
return this._getAliasAst(schema, new core_1.ASTSet({
|
|
568
669
|
value: this._zodToAST(schema.def.valueType),
|
|
569
|
-
description: (
|
|
670
|
+
description: (_p = schema.meta()) === null || _p === void 0 ? void 0 : _p.description,
|
|
570
671
|
}));
|
|
571
672
|
}
|
|
572
673
|
else if (zod_helpers_1.ZodHelpers.isZodLiteral(schema)) {
|
|
573
674
|
let parentEnum = undefined;
|
|
574
675
|
let parentEnumKey = undefined;
|
|
575
676
|
// TODO: Support multiple values
|
|
576
|
-
if ((
|
|
577
|
-
parentEnumKey = (
|
|
578
|
-
parentEnum = this._zodToAST((
|
|
677
|
+
if ((_q = (0, zod2x_metadata_1.resolveZod2xMetadata)(schema)) === null || _q === void 0 ? void 0 : _q.parentEnum) {
|
|
678
|
+
parentEnumKey = (_s = this._getEnumValues((_r = (0, zod2x_metadata_1.resolveZod2xMetadata)(schema)) === null || _r === void 0 ? void 0 : _r.parentEnum).find((i) => i[1] === schema.def.values.at(0))) === null || _s === void 0 ? void 0 : _s[0];
|
|
679
|
+
parentEnum = this._zodToAST((_t = (0, zod2x_metadata_1.resolveZod2xMetadata)(schema)) === null || _t === void 0 ? void 0 : _t.parentEnum, {
|
|
579
680
|
isInjectedEnum: true,
|
|
580
681
|
});
|
|
581
682
|
}
|
|
582
683
|
return new core_1.ASTLiteral({
|
|
583
684
|
value: schema.def.values.at(0), // TODO: Support multiple values
|
|
584
|
-
description: (
|
|
685
|
+
description: (_u = schema.meta()) === null || _u === void 0 ? void 0 : _u.description,
|
|
585
686
|
parentEnum: parentEnum,
|
|
586
687
|
parentEnumKey,
|
|
587
688
|
});
|
|
@@ -591,21 +692,29 @@ class Zod2Ast {
|
|
|
591
692
|
type: zod_helpers_1.ZodHelpers.isZodRecord(schema) ? "record" : "map",
|
|
592
693
|
key: this._zodToAST(schema.keyType),
|
|
593
694
|
value: this._zodToAST(schema.valueType),
|
|
594
|
-
description: (
|
|
695
|
+
description: (_v = schema.meta()) === null || _v === void 0 ? void 0 : _v.description,
|
|
595
696
|
}));
|
|
596
697
|
}
|
|
597
698
|
else if (zod_helpers_1.ZodHelpers.isZodLazy(schema)) {
|
|
598
699
|
/** Lazy items use to be recursive schemas of its own, so the are trated as another
|
|
599
700
|
* definition */
|
|
600
|
-
|
|
701
|
+
let lazySchema = schema;
|
|
702
|
+
while (zod_helpers_1.ZodHelpers.isZodLazy(lazySchema)) {
|
|
703
|
+
// innerType is cached by Zod, so the getter is evaluated only once per instance.
|
|
704
|
+
lazySchema = lazySchema._zod.innerType;
|
|
705
|
+
}
|
|
601
706
|
const lazyPointer = this._createDefinition({ name: "pending" });
|
|
602
|
-
this.lazyPointers.push([
|
|
707
|
+
this.lazyPointers.push([
|
|
708
|
+
lazyPointer,
|
|
709
|
+
lazySchema,
|
|
710
|
+
(opt === null || opt === void 0 ? void 0 : opt.discriminantKey) ? { discriminantKey: opt.discriminantKey } : undefined,
|
|
711
|
+
]);
|
|
603
712
|
return lazyPointer;
|
|
604
713
|
}
|
|
605
714
|
else if (zod_helpers_1.ZodHelpers.isZodTuple(schema)) {
|
|
606
715
|
return this._getAliasAst(schema, new core_1.ASTTuple({
|
|
607
716
|
items: schema.def.items.map(this._zodToAST.bind(this)),
|
|
608
|
-
description: (
|
|
717
|
+
description: (_w = schema.meta()) === null || _w === void 0 ? void 0 : _w.description,
|
|
609
718
|
}));
|
|
610
719
|
/**
|
|
611
720
|
*
|
|
@@ -628,7 +737,9 @@ class Zod2Ast {
|
|
|
628
737
|
return this._getIntersectionAst(schema);
|
|
629
738
|
}
|
|
630
739
|
else {
|
|
631
|
-
logger_1.log.warn(`Unsupported Zod type: ${
|
|
740
|
+
logger_1.log.warn(`Unsupported Zod type: ${schema.def.type}`);
|
|
741
|
+
this.warnings.push(`Unsupported Zod type '${schema.def.type}' is transpiled as an any type. Avoid ` +
|
|
742
|
+
"it, or disable strict mode if not possible.");
|
|
632
743
|
return new core_1.ASTAny({
|
|
633
744
|
description: `Unsupported Zod type: ${schema.def.type}`,
|
|
634
745
|
});
|
|
@@ -640,20 +751,29 @@ class Zod2Ast {
|
|
|
640
751
|
* @returns Transpilerable nodes.
|
|
641
752
|
*/
|
|
642
753
|
build(schema) {
|
|
643
|
-
var _a, _b, _c;
|
|
754
|
+
var _a, _b, _c, _d;
|
|
644
755
|
this._zodToAST(schema, {
|
|
645
756
|
skipLayerClass: ((_a = this.opt) === null || _a === void 0 ? void 0 : _a.layer) !== undefined && ((_c = (_b = this.opt) === null || _b === void 0 ? void 0 : _b.layer) === null || _c === void 0 ? void 0 : _c.skipLayerInterface) !== false,
|
|
646
757
|
});
|
|
647
758
|
while (this.lazyPointers.length > 0) {
|
|
648
|
-
const [pointer, schema] = this.lazyPointers.shift();
|
|
649
|
-
const lazyResolve = this._zodToAST(schema);
|
|
759
|
+
const [pointer, schema, opt] = this.lazyPointers.shift();
|
|
760
|
+
const lazyResolve = this._zodToAST(schema, opt);
|
|
761
|
+
// Modifiers applied by wrappers of the lazy schema (optional, nullable, array, ...)
|
|
762
|
+
// were set on the pointer and shall be kept.
|
|
763
|
+
const { arrayDimension, isOptional, isNullable, description } = pointer;
|
|
650
764
|
/** Pointer to the pending AST node is updated with the lazy resolve */
|
|
651
765
|
Object.keys(pointer).forEach((key) => {
|
|
652
766
|
delete pointer[key];
|
|
653
767
|
});
|
|
654
|
-
Object.
|
|
655
|
-
|
|
656
|
-
|
|
768
|
+
Object.setPrototypeOf(pointer, Object.getPrototypeOf(lazyResolve));
|
|
769
|
+
Object.assign(pointer, lazyResolve);
|
|
770
|
+
const resolved = pointer;
|
|
771
|
+
if (arrayDimension) {
|
|
772
|
+
resolved.arrayDimension = ((_d = resolved.arrayDimension) !== null && _d !== void 0 ? _d : 0) + arrayDimension;
|
|
773
|
+
}
|
|
774
|
+
resolved.isOptional = isOptional !== null && isOptional !== void 0 ? isOptional : resolved.isOptional;
|
|
775
|
+
resolved.isNullable = isNullable !== null && isNullable !== void 0 ? isNullable : resolved.isNullable;
|
|
776
|
+
resolved.description = description || resolved.description;
|
|
657
777
|
}
|
|
658
778
|
if (this.opt.strict !== false && this.warnings.length > 0) {
|
|
659
779
|
throw new errors_1.AstNodeError(this.warnings.join("\n"));
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ASTAliasedTypes, ASTEnum, ASTIntersection, ASTNode, ASTNodes, ASTObject, ASTType, ASTUnion } from "../core";
|
|
1
|
+
import { ASTAliasedTypes, ASTDefinition, ASTEnum, ASTIntersection, ASTNode, ASTNodes, ASTObject, ASTType, ASTUnion } from "../core";
|
|
2
2
|
import { TIndentationLevels } from "../utils/string_utils";
|
|
3
3
|
/**
|
|
4
4
|
* Optional user settings
|
|
@@ -24,6 +24,10 @@ export interface IZodToXOpt extends Record<string, any> {
|
|
|
24
24
|
*/
|
|
25
25
|
useImports?: boolean;
|
|
26
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* For Layered Modeling. Kind of type that extends another one.
|
|
29
|
+
*/
|
|
30
|
+
export type TExtendedTypeKind = "alias" | "union" | "d-union";
|
|
27
31
|
/**
|
|
28
32
|
* Abstract base class for transpiling Zod schemas into other programming languages.
|
|
29
33
|
* Extend this class and implement the abstract methods to define how each Zod type
|
|
@@ -56,10 +60,14 @@ export declare abstract class Zod2X<T extends IZodToXOpt> {
|
|
|
56
60
|
* @param typeName
|
|
57
61
|
*/
|
|
58
62
|
protected abstract getTypeFromExternalNamespace(namespace: string, typeName: string): string;
|
|
63
|
+
/**
|
|
64
|
+
* Opening and closing brackets of generic templates in the target language.
|
|
65
|
+
*/
|
|
66
|
+
protected readonly genericTemplatesBrackets: [string, string];
|
|
59
67
|
/**
|
|
60
68
|
* Returns the translation of generic templates for a given AST node.
|
|
61
69
|
*/
|
|
62
|
-
protected
|
|
70
|
+
protected getGenericTemplatesTranslation(data: ASTNode | ASTDefinition): string | undefined;
|
|
63
71
|
/**
|
|
64
72
|
* For Layered Modeling.
|
|
65
73
|
* If a property type is an imported type, without any modification, the transpiled type will be
|
|
@@ -68,7 +76,26 @@ export declare abstract class Zod2X<T extends IZodToXOpt> {
|
|
|
68
76
|
* @param parentNamespace
|
|
69
77
|
* @param aliasOf
|
|
70
78
|
*/
|
|
71
|
-
protected abstract addExtendedType(name: string, parentNamespace: string, aliasOf: string
|
|
79
|
+
protected abstract addExtendedType(name: string, parentNamespace: string, aliasOf: string, opt?: {
|
|
80
|
+
isInternal?: boolean;
|
|
81
|
+
}): void;
|
|
82
|
+
/**
|
|
83
|
+
* For Layered Modeling.
|
|
84
|
+
* Returns the language specific options used by `addExtendedType` to declare a type that
|
|
85
|
+
* extends another one.
|
|
86
|
+
* @param data - The AST node of the type.
|
|
87
|
+
* @param type - Kind of the type.
|
|
88
|
+
*/
|
|
89
|
+
protected getExtendedTypeOptions(data: ASTNode, type?: TExtendedTypeKind): object;
|
|
90
|
+
/**
|
|
91
|
+
* For Layered Modeling.
|
|
92
|
+
* Emits the declaration of a type that extends another layered type, if the node is an alias.
|
|
93
|
+
* @param data - The AST node to transpile.
|
|
94
|
+
* @param type - Kind of the type.
|
|
95
|
+
* @returns `true` if the node shall not be transpiled as a new type: it is an alias, or a
|
|
96
|
+
* type imported from another file.
|
|
97
|
+
*/
|
|
98
|
+
protected checkExtendedTypeInclusion(data: ASTNode, type?: TExtendedTypeKind): boolean;
|
|
72
99
|
/**
|
|
73
100
|
* Returns the keyword representing a string type in the target language.
|
|
74
101
|
*/
|
|
@@ -210,7 +237,7 @@ export declare abstract class Zod2X<T extends IZodToXOpt> {
|
|
|
210
237
|
* properties of the type to evaluate.
|
|
211
238
|
* @returns `true` if the type is an external type import; otherwise, `false`.
|
|
212
239
|
*/
|
|
213
|
-
protected isExternalTypeImport(item: ASTNode): boolean;
|
|
240
|
+
protected isExternalTypeImport(item: Pick<ASTNode, "parentFile" | "parentNamespace">): boolean;
|
|
214
241
|
/**
|
|
215
242
|
* Adds an external type import to the transpiler's imports if the provided transpiled item
|
|
216
243
|
* is located into another file and namespace, and if the `useImports` option is not disabled.
|
|
@@ -219,7 +246,7 @@ export declare abstract class Zod2X<T extends IZodToXOpt> {
|
|
|
219
246
|
* about the type to be imported, including its parent file and namespace.
|
|
220
247
|
* @returns `true` if the import was successfully added, otherwise `false`.
|
|
221
248
|
*/
|
|
222
|
-
protected addExternalTypeImport(item: ASTNode): boolean;
|
|
249
|
+
protected addExternalTypeImport(item: Pick<ASTNode, "parentFile" | "parentNamespace">): boolean;
|
|
223
250
|
/**
|
|
224
251
|
* Transpiles a single item from the transpiler queue.
|
|
225
252
|
* @param item - The transpilerable type to transpile.
|
package/dist/core/transpiler.js
CHANGED
|
@@ -13,6 +13,10 @@ const string_utils_1 = __importDefault(require("../utils/string_utils"));
|
|
|
13
13
|
*/
|
|
14
14
|
class Zod2X {
|
|
15
15
|
constructor(opt) {
|
|
16
|
+
/**
|
|
17
|
+
* Opening and closing brackets of generic templates in the target language.
|
|
18
|
+
*/
|
|
19
|
+
this.genericTemplatesBrackets = ["<", ">"];
|
|
16
20
|
/**
|
|
17
21
|
* Returns a comment.
|
|
18
22
|
*/
|
|
@@ -34,6 +38,62 @@ class Zod2X {
|
|
|
34
38
|
this.indent = string_utils_1.default.getIndentationLevels(opt.indent || 4);
|
|
35
39
|
this.opt = opt;
|
|
36
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* Returns the translation of generic templates for a given AST node.
|
|
43
|
+
*/
|
|
44
|
+
getGenericTemplatesTranslation(data) {
|
|
45
|
+
if ((data instanceof core_1.ASTObject || data instanceof core_1.ASTDefinition) &&
|
|
46
|
+
data.templatesTranslation.length > 0) {
|
|
47
|
+
const [open, close] = this.genericTemplatesBrackets;
|
|
48
|
+
const templates = data.templatesTranslation.map((t) => {
|
|
49
|
+
if (t.type !== undefined) {
|
|
50
|
+
return this.getAttributeType(t.type);
|
|
51
|
+
}
|
|
52
|
+
else if (this.isExternalTypeImport(t)) {
|
|
53
|
+
this.addExternalTypeImport(t);
|
|
54
|
+
return this.getTypeFromExternalNamespace(t.parentNamespace, t.aliasOf);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
return t.aliasOf;
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
return `${open}${templates.join(", ")}${close}`;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* For Layered Modeling.
|
|
65
|
+
* Returns the language specific options used by `addExtendedType` to declare a type that
|
|
66
|
+
* extends another one.
|
|
67
|
+
* @param data - The AST node of the type.
|
|
68
|
+
* @param type - Kind of the type.
|
|
69
|
+
*/
|
|
70
|
+
getExtendedTypeOptions(data, type) {
|
|
71
|
+
return { type };
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* For Layered Modeling.
|
|
75
|
+
* Emits the declaration of a type that extends another layered type, if the node is an alias.
|
|
76
|
+
* @param data - The AST node to transpile.
|
|
77
|
+
* @param type - Kind of the type.
|
|
78
|
+
* @returns `true` if the node shall not be transpiled as a new type: it is an alias, or a
|
|
79
|
+
* type imported from another file.
|
|
80
|
+
*/
|
|
81
|
+
checkExtendedTypeInclusion(data, type) {
|
|
82
|
+
// Options are computed in advance because they can have side effects (imports, ...).
|
|
83
|
+
const options = this.getExtendedTypeOptions(data, type);
|
|
84
|
+
if (this.isExternalTypeImport(data)) {
|
|
85
|
+
if (data.aliasOf) {
|
|
86
|
+
this.addExtendedType(data.name, data.parentNamespace, data.aliasOf, options);
|
|
87
|
+
this.addExternalTypeImport(data);
|
|
88
|
+
}
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
else if (data.aliasOf) {
|
|
92
|
+
this.addExtendedType(data.name, data.parentNamespace, data.aliasOf, Object.assign(Object.assign({}, options), { isInternal: true }));
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
37
97
|
/**
|
|
38
98
|
* Determines if the given type token can be transpiled into the target language.
|
|
39
99
|
* @param token - The type token to check.
|
|
@@ -146,7 +206,7 @@ class Zod2X {
|
|
|
146
206
|
varType = token.name;
|
|
147
207
|
}
|
|
148
208
|
else {
|
|
149
|
-
console.log(" # Unknown attribute equivalent for ---> ",
|
|
209
|
+
console.log(" # Unknown attribute equivalent for ---> ", (0, core_1.getASTKind)(token));
|
|
150
210
|
}
|
|
151
211
|
return token.arrayDimension ? this.getArrayType(varType, token.arrayDimension) : varType;
|
|
152
212
|
}
|
|
@@ -198,7 +258,7 @@ class Zod2X {
|
|
|
198
258
|
this.transpileAliasedType(item);
|
|
199
259
|
}
|
|
200
260
|
else if (item instanceof core_1.ASTCommon) {
|
|
201
|
-
console.log(`Under construction: ${item
|
|
261
|
+
console.log(`Under construction: ${(0, core_1.getASTKind)(item)}`);
|
|
202
262
|
}
|
|
203
263
|
else {
|
|
204
264
|
throw new Error(`Unexpected item for transpilation: ${JSON.stringify(item)}`);
|