@tsed/schema
Version:
JsonSchema module for Ts.ED Framework
165 lines (164 loc) • 5.39 kB
JavaScript
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;
}
}
}
}