UNPKG

@decaf-ts/decorator-validation

Version:
115 lines 3.81 kB
import { bindModelPrototype, construct } from "./construction.js"; import { ModelKeys } from "./../utils/constants.js"; import { Model } from "./Model.js"; import { metadata } from "@decaf-ts/reflection"; import { Decoration, DecorationKeys, Metadata } from "@decaf-ts/decoration"; export function modelBaseDecorator(original) { // the new constructor behaviour const newConstructor = function (...args) { const instance = construct(original, ...args); bindModelPrototype(instance); // run a builder function if defined with the first argument (The ModelArg) const builder = Model.getBuilder(); if (builder) builder(instance, args.length ? args[0] : undefined); metadata(Model.key(ModelKeys.MODEL), original.name)(instance.constructor); return instance; }; // copy prototype so instanceof operator still works newConstructor.prototype = original.prototype; metadata(Model.key(ModelKeys.MODEL), original.name)(original); Reflect.getMetadataKeys(original).forEach((key) => { Reflect.defineMetadata(key, Reflect.getMetadata(key, original), newConstructor); }); // Sets the proper constructor name for type verification Object.defineProperty(newConstructor, "name", { writable: false, enumerable: true, configurable: false, value: original.prototype.constructor.name, }); // // anchors the original constructor for future reference Object.defineProperty(newConstructor, ModelKeys.ANCHOR, { writable: false, enumerable: false, configurable: false, value: original, }); Metadata.set(newConstructor, DecorationKeys.CONSTRUCTOR, original); // // // anchors the new constructor for future reference // Object.defineProperty(original, ModelKeys.ANCHOR, { // writable: false, // enumerable: true, // configurable: false, // value: newConstructor, // }); Model.register(newConstructor, original.name); // return new constructor (will override original) return newConstructor; } /** * @summary Defines a class as a Model class * @description * * - Registers the class under the model registry so it can be easily rebuilt; * - Overrides the class constructor; * - Runs the global {@link ModelBuilderFunction} if defined; * * @function model * * @category Class Decorators */ export function model() { const key = Model.key(ModelKeys.MODEL); return Decoration.for(key).define(modelBaseDecorator).apply(); } /** * @summary Defines the hashing algorithm to use on the model * @description * * - Registers the class under the model registry so it can be easily rebuilt; * - Overrides the class constructor; * - Runs the global {@link ModelBuilderFunction} if defined; * * @param {string} algorithm the algorithm to use * * @function hashedBy * * @category Class Decorators */ export function hashedBy(algorithm, ...args) { return metadata(Model.key(ModelKeys.HASHING), { algorithm: algorithm, args: args, }); } /** * @summary Defines the serialization algorithm to use on the model * * @param {string} serializer the algorithm to use * * @function serializedBy * * @category Class Decorators */ export function serializedBy(serializer, ...args) { return metadata(Model.key(ModelKeys.SERIALIZATION), { serializer: serializer, args: args, }); } /** * @summary Applies descriptive metadata to a class, property or method * * @param {string} description the description to apply * * @function description * * @category Decorators */ export function description(description) { return metadata(Model.key(ModelKeys.DESCRIPTION), description); } //# sourceMappingURL=decorators.js.map