UNPKG

@tsed/schema

Version:
165 lines (164 loc) 5.39 kB
import { ancestorsOf, classOf, decoratorTypeOf, descriptorOf, isArrayOrArrayClass, isArrowFn, isClass, isClassObject, isCollection, isDate, isObject, isPlainObject, isPrimitiveOrPrimitiveClass, nameOf, prototypeOf, Store } from "@tsed/core"; /** * @ignore */ export const JsonEntitiesContainer = new Map(); export class JsonEntityStore { constructor(options) { this.isStore = true; const { target, propertyKey, descriptor, index, decoratorType } = options; this.target = target; this.propertyKey = propertyKey; this.propertyName = propertyKey ? String(propertyKey) : propertyKey || ""; this.descriptor = descriptor; this.index = index; this.decoratorType = decoratorType; this.token = target; this.store = options.store; this.parent = this; } get collectionType() { return this._collectionType; } set collectionType(value) { this._collectionType = value; } get type() { return this._type; } /** * Get original type without transformation * @param value */ set type(value) { if (!value?.$schema?.skip) { this._type = value; } this.build(); } /** * Return the JsonSchema */ get schema() { return this._schema; } /** * Return the class name of the entity. * @returns {string} */ get targetName() { return nameOf(this.token); } get isCollection() { return !!this._collectionType; } get isArray() { return isArrayOrArrayClass(this._collectionType); } get discriminatorAncestor() { const ancestors = ancestorsOf(this.target); const ancestor = ancestors.find((ancestor) => JsonEntityStore.from(ancestor).schema.isDiscriminator); return ancestor && JsonEntityStore.from(ancestor); } get isPrimitive() { return isPrimitiveOrPrimitiveClass(this.type); } get isDate() { return isDate(this.computedType); } get isObject() { return isObject(this.computedType); } get isClass() { return isClass(this.computedType); } /** * Return the itemSchema computed type. if the type is a function used for recursive model, the function will be called to * get the right type. */ get computedType() { return this.itemSchema.class; } get itemSchema() { return this.isCollection ? this.schema.itemSchema() : this.schema; } get parentSchema() { return this.parent.schema; } get isDiscriminatorChild() { return this.schema.isDiscriminator && this.discriminatorAncestor?.schema.discriminator().base !== this.target; } get path() { return this.store.get("path"); } set path(path) { this.store.set("path", path); } static from(...args) { if (args[0].isStore) { return args[0]; } const target = args[0]; if (args.length > 1) { args[0] = prototypeOf(args[0]); } const store = Store.from(...args); if (!store.has("JsonEntityStore")) { const decoratorType = decoratorTypeOf(args); const entityStore = JsonEntitiesContainer.get(decoratorType); const jsonSchemaStore = new entityStore({ store, decoratorType, target: classOf(target), propertyKey: args[1], index: typeof args[2] === "number" ? args[2] : undefined, descriptor: typeof args[2] === "object" ? args[2] : undefined }); jsonSchemaStore.build(); store.set("JsonEntityStore", jsonSchemaStore); } return store.get("JsonEntityStore"); } static fromMethod(target, propertyKey) { return this.from(target, propertyKey, descriptorOf(target, propertyKey)); } static get(target, propertyKey, descriptor) { return JsonEntityStore.from(prototypeOf(target), propertyKey, descriptor); } isGetterOnly() { return isObject(this.descriptor) && !this.descriptor.value && this.descriptor.get && !this.descriptor.set; } get(key, defaultValue) { return this.store.get(key, defaultValue); } set(key, value) { return this.store.set(key, value); } toString() { return [this.targetName, this.propertyName, this.index].filter((o) => o !== undefined).join(":"); } getBestType() { return this.itemSchema.hasDiscriminator ? this.itemSchema.discriminator().base : isClassObject(this.type) ? this.itemSchema.getTarget() : isArrowFn(this.type) ? this.type() : this.type; } is(input) { return this.decoratorType === input; } buildType(type) { if (isCollection(type)) { this._collectionType = type; } else if (!(type && "$schema" in type && type.$schema.skip)) { this._type = type; // issue #1534: Enum metadata stored as plain object instead of String (see: https://github.com/tsedio/tsed/issues/1534) if (this._type && isPlainObject(this._type)) { this._type = String; } } } }