@elsikora/nestjs-crud-automator
Version:
A library for automating the creation of CRUD operations in NestJS.
144 lines (140 loc) • 6.18 kB
JavaScript
;
var metadataStorage_class = require('../class/metadata-storage.class.js');
var exception_utility = require('./error/exception.utility.js');
var typeorm = require('typeorm');
/**
* Generates metadata information about an entity including columns, table name, and primary key
* @param {IApiBaseEntity} entity - The entity to generate information for
* @returns {IApiEntity<E>} The generated entity information object
* @template E - The entity type
*/
function GenerateEntityInformation(entity) {
const tableName = (() => {
// eslint-disable-next-line @elsikora/typescript/no-unsafe-function-type
const table = typeorm.getMetadataArgsStorage().tables.find(({ target }) => target.name === entity.name);
if (!table) {
throw exception_utility.ErrorException(`Table for entity ${String(entity.name)} not found in metadata storage`);
}
const namingStrategy = (tableName) => new typeorm.DefaultNamingStrategy().tableName(entity.name ?? "UnknownResource", tableName);
if (!table.name && table.type === "entity-child") {
const discriminatorValue = typeorm.getMetadataArgsStorage().discriminatorValues.find(({ target }) => target == entity);
if (!discriminatorValue?.value) {
throw exception_utility.ErrorException(`Discriminator value for entity ${String(entity.name)} not found in metadata storage`);
}
else if (typeof discriminatorValue.value === "string") {
return namingStrategy(discriminatorValue.value);
}
else {
// eslint-disable-next-line @elsikora/typescript/no-unsafe-argument,@elsikora/typescript/no-unsafe-member-access
return namingStrategy(discriminatorValue.value?.name);
}
}
return namingStrategy(table.name);
})();
const storage = metadataStorage_class.MetadataStorage.getInstance();
const entityHierarchy = [];
const entityNames = [];
if (typeof entity === "function") {
let current = entity;
while (current) {
entityHierarchy.push(current);
entityNames.push(current.name);
const parentPrototype = Object.getPrototypeOf(current.prototype);
const parentConstructor = parentPrototype ? Reflect.get(parentPrototype, "constructor") : undefined;
const parent = typeof parentConstructor === "function" ? parentConstructor : undefined;
if (!parent || parent === Object) {
break;
}
current = parent;
}
}
else if (entity.name) {
entityNames.push(entity.name);
}
const columnList = typeorm.getMetadataArgsStorage().columns.filter(({ target }) => {
if (typeof target === "string") {
return entityNames.includes(target);
}
if (typeof target !== "function") {
return false;
}
const targetEntity = target;
return entityHierarchy.some((currentEntity) => currentEntity === targetEntity || currentEntity.name === targetEntity.name) || entityNames.includes(targetEntity.name);
});
const relationList = typeorm.getMetadataArgsStorage().relations.filter(({ target }) => {
if (typeof target === "string") {
return entityNames.includes(target);
}
if (typeof target !== "function") {
return false;
}
const targetEntity = target;
return entityHierarchy.some((currentEntity) => currentEntity === targetEntity || currentEntity.name === targetEntity.name) || entityNames.includes(targetEntity.name);
});
const entityColumns = [
...columnList.map(({ options, propertyName }) => {
let metadata;
for (const entityName of entityNames) {
metadata = storage.getMetadata(entityName, propertyName);
if (metadata) {
break;
}
}
return {
isPrimary: Boolean(options.primary),
metadata,
name: propertyName,
// eslint-disable-next-line @elsikora/typescript/no-non-null-assertion
type: options.type,
};
}),
...relationList.map(({ propertyName, relationType, type }) => {
let metadata;
for (const entityName of entityNames) {
metadata = storage.getMetadata(entityName, propertyName);
if (metadata) {
break;
}
}
let relationTarget;
let resolvedRelationTarget = type;
if (typeof type === "function") {
try {
resolvedRelationTarget = type();
}
catch {
resolvedRelationTarget = type;
}
}
if (typeof resolvedRelationTarget === "string") {
relationTarget = { name: resolvedRelationTarget };
}
else if (typeof resolvedRelationTarget === "function" && resolvedRelationTarget.name) {
relationTarget = resolvedRelationTarget;
}
else if (typeof resolvedRelationTarget === "object" && resolvedRelationTarget !== null && "name" in resolvedRelationTarget && typeof resolvedRelationTarget.name === "string") {
relationTarget = resolvedRelationTarget;
}
return {
isPrimary: false,
metadata,
name: propertyName,
relation: relationTarget
? {
target: relationTarget,
}
: undefined,
type: relationType,
};
}),
];
const primaryKey = entityColumns.find((column) => column.isPrimary);
return {
columns: entityColumns,
name: entity.name,
primaryKey,
tableName,
};
}
exports.GenerateEntityInformation = GenerateEntityInformation;
//# sourceMappingURL=generate-entity-information.utility.js.map