typeorm-stubs
Version:
Stubs generator for Typeorm entities
334 lines • 14.3 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Parser = void 0;
const type_guards_1 = require("./type-guards");
const singleton_1 = require("./singleton");
const constants_1 = require("./constants");
const utils_1 = require("./utils");
class Parser extends singleton_1.Singleton {
constructor(generator) {
super();
this.generator = generator;
}
parseMetadata(stub, entity, metadataStorage, addedRelations, options) {
this.parseColumns(stub, entity, metadataStorage, options);
if (options.deep) {
this.parseRelations(stub, entity, metadataStorage, addedRelations, options);
}
}
parseColumns(stub, entity, metadataStorage, options) {
const columns = metadataStorage.filterColumns(entity);
for (const column of columns) {
if (Reflect.get(stub, column.propertyName) !== undefined) {
continue;
}
const designType = this.getDesignType(entity.prototype, column.propertyName);
Reflect.set(stub, column.propertyName, this.getValueByType(column, designType, options));
}
}
parseRelations(stub, entity, metadataStorage, addedRelations, options) {
const relations = metadataStorage.filterRelations(entity);
const columns = metadataStorage.filterColumns(entity);
const parent = (0, utils_1.getParentClass)(entity);
if (parent) {
columns.push(...metadataStorage.filterColumns(parent));
}
const primaryColumns = columns.filter(({ options }) => options.primary);
for (const relation of relations) {
const isArray = constants_1.ARRAY_RELATION_TYPE.includes(relation.relationType);
const relationEntity = (0, type_guards_1.isFunction)(relation.type) ? relation.type() : relation.type;
const relationName = (0, type_guards_1.isFunction)(relationEntity) ? relationEntity.name : relationEntity;
if (!(0, type_guards_1.isString)(relationName) ||
addedRelations.includes(relationName) ||
relationName === entity.name ||
!(0, type_guards_1.isConstructor)(relationEntity)) {
continue;
}
const addedRelationsWithCurrent = [...addedRelations, entity.name];
const params = [
relationEntity,
metadataStorage,
addedRelationsWithCurrent,
entity.name,
primaryColumns,
stub,
options,
];
Reflect.set(stub, relation.propertyName, isArray
? Array(this.generator.generateRandomNumber(3, 10))
.fill('')
.map(() => this.createRelation(...params))
: this.createRelation(...params));
for (const relationArgs of relations) {
const joinColumns = metadataStorage.filterJoinColumns(entity, relationArgs.propertyName);
for (let i = 0; i < joinColumns.length; i++) {
const joinColumnArgs = joinColumns[i];
if (!joinColumnArgs) {
continue;
}
const column = this.findJoinColumn(joinColumnArgs, columns);
if (!column) {
continue;
}
const relationConstructor = this.getRelationConstructor(relationArgs);
if (!relationConstructor) {
continue;
}
const primaryColumns = metadataStorage
.filterColumns(relationConstructor)
.filter(({ options }) => options.primary);
const parent = !(0, type_guards_1.isString)(relationConstructor) ? (0, utils_1.getParentClass)(relationConstructor) : null;
if (parent) {
primaryColumns.push(...metadataStorage.filterColumns(parent).filter(({ options }) => options.primary));
}
const primaryColumn = primaryColumns[i];
const relationObject = Reflect.get(stub, relationArgs.propertyName);
if (primaryColumn && (0, type_guards_1.isObject)(relationObject)) {
Reflect.set(stub, column.propertyName, Reflect.get(relationObject, primaryColumn.propertyName));
}
}
}
}
addedRelations.push(entity.name);
}
createRelation(constructor, metadataStorage, addedRelations, externalEntityName, externalPrimaryColumns, stub, options) {
const relation = new constructor();
const parent = (0, utils_1.getParentClass)(constructor);
const relationColumns = metadataStorage.filterColumns(constructor);
const deepRelations = metadataStorage.filterRelations(constructor);
const parentRelations = [];
if (parent) {
this.parseMetadata(relation, parent, metadataStorage, addedRelations, options);
relationColumns.push(...metadataStorage.filterColumns(parent));
parentRelations.push(...metadataStorage.filterRelations(parent));
}
this.parseMetadata(relation, constructor, metadataStorage, addedRelations, options);
if (parent) {
parentRelations.forEach((relationArgs) => {
this.parseDeepRelations(metadataStorage, relation, parent, relationArgs, relationColumns, externalEntityName, externalPrimaryColumns, stub);
});
}
deepRelations.forEach((relationArgs) => {
this.parseDeepRelations(metadataStorage, relation, constructor, relationArgs, relationColumns, externalEntityName, externalPrimaryColumns, stub);
});
return relation;
}
parseDeepRelations(metadataStorage, relation, constructor, relationArgs, columns, externalEntityName, externalPrimaryColumns, stub) {
const joinColumns = metadataStorage.filterJoinColumns(constructor, relationArgs.propertyName);
for (let i = 0; i < joinColumns.length; i++) {
const joinColumnArgs = joinColumns[i];
if (!joinColumnArgs) {
continue;
}
const column = this.findJoinColumn(joinColumnArgs, columns);
if (!column || !this.isJoinColumnTarget(relationArgs, externalEntityName)) {
continue;
}
const primaryColumn = externalPrimaryColumns[i];
if (!primaryColumn) {
continue;
}
Reflect.set(relation, column.propertyName, Reflect.get(stub, primaryColumn.propertyName));
}
}
isJoinColumnTarget(relationArgs, name) {
if ((0, type_guards_1.isString)(relationArgs.type)) {
return relationArgs.type === name;
}
if ((0, type_guards_1.isConstructor)(relationArgs.type) || (0, type_guards_1.isObject)(relationArgs.type)) {
return relationArgs.type.name === name;
}
if ((0, type_guards_1.isFunction)(relationArgs.type)) {
const target = relationArgs.type();
return (0, type_guards_1.isConstructor)(target) && target.name === name;
}
return false;
}
findJoinColumn(joinColumnArgs, columns) {
return columns.find((column) => {
if ((0, type_guards_1.isNotNull)(joinColumnArgs.name)) {
return joinColumnArgs.name === (column.options.name ?? column.propertyName);
}
return joinColumnArgs.propertyName === (column.options.name ?? column.propertyName);
});
}
getRelationConstructor(relationArgs) {
if ((0, type_guards_1.isString)(relationArgs.type) || (0, type_guards_1.isConstructor)(relationArgs.type)) {
return relationArgs.type;
}
if ((0, type_guards_1.isFunction)(relationArgs.type)) {
const constructor = relationArgs.type();
return (0, type_guards_1.isConstructor)(constructor) ? constructor : null;
}
return null;
}
getDesignType(entity, propertyName) {
const designType = Reflect.getMetadata('design:type', entity, propertyName);
switch (designType) {
case String:
case Number:
case Boolean:
case Array:
return designType;
case Date:
return (val) => {
if (val instanceof Date)
return val;
if ((0, type_guards_1.isString)(val) || (0, type_guards_1.isNumber)(val))
return new Date(val);
return new Date();
};
default:
return (val) => {
if ((0, type_guards_1.isConstructor)(designType))
return this.parseNested(designType);
if ((0, type_guards_1.isObject)(val))
return this.parseJson(val);
return val ?? null;
};
}
}
parseJson(obj) {
const keys = Reflect.ownKeys(obj);
const newObj = { ...obj };
for (const key of keys) {
if (!(0, type_guards_1.isNotNull)(Reflect.get(obj, key))) {
Reflect.set(newObj, key, null);
continue;
}
const designType = this.getDesignType(obj, key);
Reflect.set(newObj, key, designType(Reflect.get(obj, key)));
}
return newObj;
}
parseNested(constructor) {
const val = new constructor();
Object.keys(val).forEach((key) => {
const designType = Reflect.getMetadata('design:type', constructor.prototype, key);
const column = {
target: constructor,
propertyName: key,
mode: 'regular',
options: {},
};
Reflect.set(val, key, this.getValueByDesignType(column, designType));
});
return val;
}
getValueByDesignType(column, designType) {
switch (designType) {
case String:
return this.generator.generate(column, 'generateString', designType);
case Number:
return this.generator.generate(column, 'generateNumber', designType);
case Boolean:
return this.generator.generate(column, 'generateBoolean', designType);
case Date:
return this.generator.generate(column, 'generateDate', designType);
case Array:
return [];
}
if ((0, type_guards_1.isConstructor)(designType))
return this.parseNested(designType);
return null;
}
getValueByType(column, designType, options) {
if (column.options.nullable && options.nullDefaults) {
return null;
}
switch (column.mode) {
case 'createDate':
case 'updateDate':
return this.generator.generate(column, 'generateDate', designType);
case 'deleteDate':
return null;
}
switch (column.options.type) {
case 'uuid':
return this.generator.generate(column, 'generateUuid', designType);
case 'int':
case 'int2':
case 'int4':
case 'int8':
case 'int64':
case 'integer':
case 'unsigned big int':
case 'tinyint':
case 'smallint':
case 'mediumint':
case 'bigint':
case 'dec':
case 'decimal':
case 'smalldecimal':
case 'fixed':
case 'numeric':
case 'number':
case 'float':
case 'float4':
case 'float8':
case 'double':
case 'double precision':
case 'real':
return this.generator.generate(column, 'generateNumber', designType);
case 'character varying':
case 'varying':
case 'nvarchar':
case 'national':
case 'character':
case 'native':
case 'varchar':
case 'char':
case 'nchar':
case 'varchar2':
case 'nvarchar2':
case 'alphanum':
case 'shorttext':
case 'raw':
case 'binary':
case 'varbinary':
case 'string':
case 'tinytext':
case 'mediumtext':
case 'text':
case 'ntext':
case 'citext':
case 'longtext':
return this.generator.generate(column, 'generateString', designType);
case 'date':
case 'datetime':
case 'datetime2':
case 'datetimeoffset':
case 'time':
case 'time with time zone':
case 'time without time zone':
case 'timestamp':
case 'timestamptz':
case 'timestamp without time zone':
case 'timestamp with time zone':
case 'timestamp with local time zone':
return this.generator.generate(column, 'generateDate', designType);
case 'boolean':
case 'bool':
return this.generator.generate(column, 'generateBoolean', designType);
case 'enum':
case 'simple-enum':
return this.generator.generate(column, 'generateEnum', designType);
case 'simple-array':
case 'array':
return [];
}
switch (designType) {
case String:
return this.generator.generate(column, 'generateString', designType);
case Number:
return this.generator.generate(column, 'generateNumber', designType);
case Boolean:
return this.generator.generate(column, 'generateBoolean', designType);
case Array:
return [];
}
return designType();
}
}
exports.Parser = Parser;
//# sourceMappingURL=parser.js.map