@cheetah.js/orm
Version:
A simple ORM for Cheetah.js
158 lines (157 loc) • 6.02 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SqlColumnManager = void 0;
class SqlColumnManager {
constructor(entityStorage, statements, entity) {
this.entityStorage = entityStorage;
this.statements = statements;
this.entity = entity;
}
generateColumns(model, updatedColumns) {
const baseColumns = this.getColumnsForEntity(model, this.statements.alias);
const joinColumns = this.getJoinColumns();
const allColumns = [...baseColumns, ...joinColumns];
return [...allColumns, ...updatedColumns];
}
processUserColumns(columns) {
const aliasedColumns = this.extractAliases(columns);
return this.filterValid(aliasedColumns);
}
getColumnsForEntity(entity, alias) {
const entityOptions = this.entityStorage.get(entity);
if (!entityOptions) {
throw new Error('Entity not found');
}
const propertyColumns = this.getPropertyColumns(entityOptions, alias);
const relationColumns = this.getRelationColumns(entityOptions, alias);
return [...propertyColumns, ...relationColumns];
}
discoverAlias(column, onlyAlias = false) {
if (!this.isNestedColumn(column)) {
return this.buildSimpleColumnAlias(column, this.statements.alias, onlyAlias);
}
return this.buildNestedColumnAlias(column, onlyAlias);
}
getJoinColumns() {
if (!this.statements.join) {
return [];
}
return this.statements.join.flatMap(join => this.getColumnsForEntity(join.joinEntity, join.joinAlias));
}
getPropertyColumns(entityOptions, alias) {
return Object.keys(entityOptions.properties).map(key => {
const columnName = entityOptions.properties[key].options.columnName;
return `${alias}."${columnName}" as "${alias}_${columnName}"`;
});
}
getRelationColumns(entityOptions, alias) {
if (!entityOptions.relations) {
return [];
}
return entityOptions.relations
.filter(relation => relation.relation === 'many-to-one')
.map(relation => `${alias}."${relation.columnName}" as "${alias}_${relation.columnName}"`);
}
extractAliases(columns) {
return columns
.map(column => this.discoverAlias(column))
.flat()
.filter((col) => col !== undefined);
}
filterValid(columns) {
return columns.filter(Boolean);
}
isNestedColumn(column) {
return column.includes('.');
}
buildSimpleColumnAlias(column, alias, onlyAlias) {
const columnName = this.getColumnNameFromProperty(column);
if (onlyAlias) {
return `${alias}."${columnName}"`;
}
return `${alias}."${columnName}" as ${alias}_${columnName}`;
}
buildNestedColumnAlias(column, onlyAlias) {
this.validateJoinsExist();
const parts = column.split('.');
const aliasInfo = this.resolveNestedAlias(parts);
if (!aliasInfo) {
return undefined;
}
return this.formatColumnWithAlias(aliasInfo.alias, parts[parts.length - 1], onlyAlias);
}
validateJoinsExist() {
if (!this.statements.join && !this.statements.selectJoin) {
throw new Error('Join not found');
}
}
resolveNestedAlias(parts) {
const joinMaps = this.buildJoinMaps();
let currentAlias = this.statements.alias;
for (let i = 0; i < parts.length; i++) {
const part = parts[i];
const isLastPart = i === parts.length - 1;
if (isLastPart) {
return { alias: currentAlias };
}
const nextAlias = this.findNextAlias(part, joinMaps, i === 0);
if (!nextAlias) {
return null;
}
currentAlias = nextAlias;
}
return { alias: currentAlias };
}
buildJoinMaps() {
const relationsMap = new Map(this.entity.relations.map(rel => [rel.propertyKey, rel]));
const joinMap = new Map();
this.statements.join?.forEach(join => joinMap.set(join.joinProperty, join));
const selectJoinMap = new Map();
this.statements.selectJoin?.forEach(join => selectJoinMap.set(join.joinProperty, join));
return { joinMap, selectJoinMap, relationsMap };
}
findNextAlias(part, maps, isFirstPart) {
if (maps.joinMap.has(part)) {
return maps.joinMap.get(part).joinAlias;
}
if (maps.selectJoinMap.has(part)) {
return null;
}
return null;
}
formatColumnWithAlias(alias, propertyName, onlyAlias) {
const entity = this.getEntityFromAlias(alias);
const columnName = this.getColumnNameFromPropertyForEntity(propertyName, entity);
if (onlyAlias) {
return `${alias}."${columnName}"`;
}
return `${alias}."${columnName}" as ${alias}_${columnName}`;
}
getColumnNameFromProperty(propertyName) {
return this.getColumnNameFromPropertyForEntity(propertyName, this.entity);
}
getColumnNameFromPropertyForEntity(propertyName, entity) {
if (entity.properties[propertyName]) {
return entity.properties[propertyName].options.columnName;
}
const relation = entity.relations?.find(rel => rel.propertyKey === propertyName);
if (relation) {
return relation.columnName;
}
return propertyName;
}
getEntityFromAlias(alias) {
if (alias === this.statements.alias) {
return this.entity;
}
const join = this.statements.join?.find(j => j.joinAlias === alias);
if (join?.joinEntity) {
const entity = this.entityStorage.get(join.joinEntity);
if (entity) {
return entity;
}
}
return this.entity;
}
}
exports.SqlColumnManager = SqlColumnManager;