UNPKG

zod-to-x

Version:

Multi language types generation from Zod schemas.

191 lines (190 loc) 8.42 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Layer = Layer; exports.Domain = Domain; exports.Application = Application; exports.Infrastructure = Infrastructure; exports.Presentation = Presentation; const case_1 = __importDefault(require("case")); const zod_helpers_1 = require("../lib/zod_helpers"); var EZod2XLayer; (function (EZod2XLayer) { EZod2XLayer[EZod2XLayer["DOMAIN"] = 0] = "DOMAIN"; EZod2XLayer[EZod2XLayer["APPLICATION"] = 1] = "APPLICATION"; EZod2XLayer[EZod2XLayer["INFRASTRUCTURE"] = 2] = "INFRASTRUCTURE"; EZod2XLayer[EZod2XLayer["PRESENTATION"] = 3] = "PRESENTATION"; })(EZod2XLayer || (EZod2XLayer = {})); /** * A decorator function to create a layered model by extending a class with additional metadata. * This decorator ensures that each class instance is a singleton and associates metadata with * transpilerable properties of the class. * * @param opt - The metadata options for the layer, of type `IZod2xLayerMetadata`. * * @returns A class decorator that extends the target class with the following features: * - Singleton instance management. * - Automatic assignment of metadata (`IZod2xMetadata`) to transpilerable properties. * - Layer-specific metadata association for Zod types. * * ### Usage * Apply this decorator to a class to enable layered modeling and metadata management. * * ### Example * ```typescript * @Layer({ name: "User", file: "user.ts", index: 0 }) * class ExampleClass { * // Class implementation * } * ``` * * ### Usage * It can also be used to create custom layers like Domain, Application or Infrastructure: * ```typescript * function Domain(opt: Pick<IZod2xLayerMetadata, "file" | "name">) { * return Layer({ ...opt, index: EZod2XLayer.DOMAIN }); * } * * @Domain({ name: "User", file: "user.ts" }) * class User { * // Class implementation * } * ``` */ function Layer(opt) { return function (constructor) { var _a; return _a = class extends constructor { constructor(...args) { if (constructor.instance) { return constructor.instance; } super(...args); this.modelName = constructor.name; this.layerMetadata = opt; constructor.instance = this; let metadata; /** * Set metadata for each transpilerable property of the class if not already set. * @param name * @param zodItem * @param opt */ const setMetadata = (name, zodItem, opt) => { metadata = zodItem["_zod2x"]; if (metadata === undefined) { metadata = { typeName: name, }; zodItem["_zod2x"] = metadata; } else if (!metadata.typeName) { metadata.typeName = name; } if (metadata.layer === undefined) { // Metadata is set independently because typeName could already exist if // zod2x was used before. metadata.layer = opt; } if (opt.externalInheritance !== false && (metadata.layer.file !== opt.file || name !== metadata.typeName)) { // Using an existing type. A new type is created that inherits from the // original type. zodItem = zod_helpers_1.ZodHelpers.cloneZod(zodItem); zodItem._zod2x = { parentLayer: metadata.layer, aliasOf: metadata.typeName, layer: opt, typeName: name, // Generics associated to parent, but related to current type. genericTypes: metadata.isGenericChild === false ? metadata.genericTypes : undefined, isGenericChild: true, }; } return zodItem; }; const lazyProperties = []; Object.getOwnPropertyNames(this).forEach((prop) => { const item = this[prop]; if (zod_helpers_1.ZodHelpers.isTranspilerableZodType(item) || zod_helpers_1.ZodHelpers.isTranspilerableAliasedZodType(item, opt.basicTypes === false)) { this[prop] = setMetadata(case_1.default.pascal(prop), item, opt); } else if (zod_helpers_1.ZodHelpers.isZodLazy(item)) { lazyProperties.push(prop); } }); // Process lazy properties after initial pass to ensure proper metadata assignment. lazyProperties.forEach((i) => { const lazyItem = this[i]._def.getter(); if (zod_helpers_1.ZodHelpers.isTranspilerableZodType(lazyItem) || zod_helpers_1.ZodHelpers.isTranspilerableAliasedZodType(lazyItem, opt.basicTypes === false)) { this[i] = setMetadata(case_1.default.pascal(i), lazyItem, opt); } }); } }, _a.instance = null, _a; }; } /** * The Domain layer decorator is typically used to define the core business logic or domain-specific * rules within the application. It serves as a foundational layer in the layered architecture, * encapsulating domain-related concerns. * * @param opt - An object containing the following properties: * - `file`: The file path associated with the layer. * - `name`: The name of the layer. * * @returns The configured Domain layer. */ function Domain(opt) { return Layer(Object.assign(Object.assign({}, opt), { index: EZod2XLayer.DOMAIN })); } /** * The Application layer decorator is typically used to represent the application-specific logic * or configuration in a layered architecture. It serves as a higher-level abstraction * that interacts with other layers, such as domain or infrastructure layers. * * @param opt - An object containing the following properties: * - `file`: The file associated with the layer. * - `name`: The name of the layer. * * @returns The result of invoking the `Layer` function with the provided options and * the `APPLICATION` layer index. */ function Application(opt) { return Layer(Object.assign(Object.assign({}, opt), { index: EZod2XLayer.APPLICATION })); } /** * The Infrastructure layer decorator is typically responsible for handling * low-level technical details such as database access, external APIs, * file systems, and other system-level operations. It serves as the * foundation for higher-level layers in the architecture. * * @param opt - An object containing metadata for the layer: * - `file`: The file associated with this layer. * - `name`: The name of the layer. * * @returns A configured Infrastructure layer. */ function Infrastructure(opt) { return Layer(Object.assign(Object.assign({}, opt), { index: EZod2XLayer.INFRASTRUCTURE })); } /** * The Presentation layer decorator is typically used to define the presentation or view-specific * aspects of the model, such as formatting or display-related metadata. * * @param opt - An object containing the following properties: * - `file`: The file associated with the layer. * - `name`: The name of the layer. * @returns The configured Presentation layer. */ function Presentation(opt) { return Layer(Object.assign(Object.assign({}, opt), { index: EZod2XLayer.PRESENTATION })); }