UNPKG

zod-to-x

Version:

Multi language types generation from Zod schemas.

177 lines (176 loc) 7.56 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("../core/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) { // Only possible if `zod2xExtendable` is used. 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 && (0, zod_helpers_1.isTranspiledExtendable)(zodItem._def.typeName)) { if (metadata.layer.file !== opt.file) { // Type used from another layer. A new type is created inheriting the // original type. zodItem = (0, zod_helpers_1.cloneTranspiledExtendable)(zodItem); zodItem._zod2x = { parentLayer: metadata.layer, parentTypeName: metadata.typeName, layer: opt, typeName: name, }; } } return zodItem; }; Object.getOwnPropertyNames(this).forEach((prop) => { var _b, _c; const zodType = (_c = (_b = this[prop]) === null || _b === void 0 ? void 0 : _b._def) === null || _c === void 0 ? void 0 : _c.typeName; if ((0, zod_helpers_1.isTranspilerableZodType)(zodType)) { this[prop] = setMetadata(case_1.default.pascal(prop), this[prop], 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 })); }