firebird-orm
Version:
Um ORM elegante e tipado para Firebird
263 lines (262 loc) • 10.9 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.Repository = void 0;
const decorators_1 = require("./decorators");
class Repository {
constructor(pool, entity) {
this.pool = pool;
this.entity = entity;
this.metadata = Reflect.getMetadata(decorators_1.ENTITY_METADATA_KEY, entity);
}
getColumnName(propertyKey) {
const columns = Reflect.getMetadata(decorators_1.COLUMN_METADATA_KEY, this.entity) || [];
const primaryColumns = Reflect.getMetadata(decorators_1.PRIMARY_COLUMN_METADATA_KEY, this.entity) || [];
const allColumns = [...columns, ...primaryColumns];
const column = allColumns.find(col => col.propertyKey === propertyKey);
return (column === null || column === void 0 ? void 0 : column.name) || propertyKey.toString();
}
async getNextId() {
return new Promise((resolve, reject) => {
const tableName = this.metadata.name;
const sql = `SELECT GEN_ID(GEN_${tableName}_ID, 1) AS ID FROM RDB$DATABASE`;
this.pool.get((err, db) => {
if (err) {
reject(err);
return;
}
db.query(sql, [], (err, result) => {
db.detach();
if (err) {
reject(err);
return;
}
resolve(result[0].ID);
});
});
});
}
buildWhereClause(where) {
const conditions = [];
const params = [];
Object.entries(where).forEach(([key, value]) => {
const columnName = this.getColumnName(key);
conditions.push(`${columnName} = ?`);
params.push(value);
});
return {
sql: conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '',
params
};
}
buildOrderByClause(orderBy) {
const orders = [];
Object.entries(orderBy).forEach(([key, direction]) => {
const columnName = this.getColumnName(key);
orders.push(`${columnName} ${direction}`);
});
return orders.length > 0 ? `ORDER BY ${orders.join(', ')}` : '';
}
mapResultToEntity(result) {
const entity = new this.entity();
const columns = Reflect.getMetadata(decorators_1.COLUMN_METADATA_KEY, this.entity) || [];
const primaryColumns = Reflect.getMetadata(decorators_1.PRIMARY_COLUMN_METADATA_KEY, this.entity) || [];
const allColumns = [...columns, ...primaryColumns];
allColumns.forEach(column => {
const columnName = column.name.toLowerCase();
const resultKey = Object.keys(result).find(key => key.toLowerCase() === columnName);
if (resultKey) {
entity[column.propertyKey] = result[resultKey];
}
});
return entity;
}
async findOne(id) {
return new Promise((resolve, reject) => {
const primaryColumns = Reflect.getMetadata(decorators_1.PRIMARY_COLUMN_METADATA_KEY, this.entity) || [];
if (!primaryColumns.length) {
reject(new Error('No primary key defined'));
return;
}
const primaryColumn = primaryColumns[0];
const tableName = this.metadata.name;
const sql = `SELECT * FROM ${tableName} WHERE ${primaryColumn.name} = ?`;
this.pool.get((err, db) => {
if (err) {
reject(err);
return;
}
db.query(sql, [id], (err, result) => {
db.detach();
if (err) {
reject(err);
return;
}
if (!result || result.length === 0) {
resolve(null);
return;
}
resolve(this.mapResultToEntity(result[0]));
});
});
});
}
async find(options) {
return new Promise((resolve, reject) => {
const tableName = this.metadata.name;
const whereClause = (options === null || options === void 0 ? void 0 : options.where) ? this.buildWhereClause(options.where) : { sql: '', params: [] };
const orderByClause = (options === null || options === void 0 ? void 0 : options.orderBy) ? this.buildOrderByClause(options.orderBy) : '';
const limitClause = (options === null || options === void 0 ? void 0 : options.limit) ? `ROWS ${options.limit}` : '';
const offsetClause = (options === null || options === void 0 ? void 0 : options.offset) ? `OFFSET ${options.offset}` : '';
const sql = `
SELECT * FROM ${tableName}
${whereClause.sql}
${orderByClause}
${limitClause}
${offsetClause}
`.trim().replace(/\s+/g, ' ');
this.pool.get((err, db) => {
if (err) {
reject(err);
return;
}
db.query(sql, whereClause.params, (err, result) => {
db.detach();
if (err) {
reject(err);
return;
}
if (!result) {
resolve([]);
return;
}
resolve(result.map(row => this.mapResultToEntity(row)));
});
});
});
}
async save(entity) {
return new Promise(async (resolve, reject) => {
const columns = Reflect.getMetadata(decorators_1.COLUMN_METADATA_KEY, this.entity) || [];
const primaryColumns = Reflect.getMetadata(decorators_1.PRIMARY_COLUMN_METADATA_KEY, this.entity) || [];
const tableName = this.metadata.name;
try {
// Se não tem ID e tem coluna primária, gera o próximo ID
if (primaryColumns.length) {
const primaryColumn = primaryColumns[0];
const id = entity[primaryColumn.propertyKey];
if (!id) {
const nextId = await this.getNextId();
entity[primaryColumn.propertyKey] = nextId;
}
}
// Incluir TODAS as colunas (normais + primárias)
const allColumns = [...columns, ...primaryColumns];
const columnNames = allColumns.map((col) => col.name).join(', ');
const placeholders = allColumns.map(() => '?').join(', ');
const values = allColumns.map((col) => entity[col.propertyKey]);
const sql = `INSERT INTO ${tableName} (${columnNames}) VALUES (${placeholders})`;
this.pool.get((err, db) => {
if (err) {
reject(err);
return;
}
db.query(sql, values, (err) => {
db.detach();
if (err) {
reject(err);
return;
}
if (primaryColumns.length) {
const primaryColumn = primaryColumns[0];
const id = entity[primaryColumn.propertyKey];
this.findOne(id)
.then(savedEntity => {
if (!savedEntity) {
reject(new Error('Failed to save entity'));
return;
}
resolve(savedEntity);
})
.catch(reject);
}
else {
resolve(this.mapResultToEntity(entity));
}
});
});
}
catch (error) {
reject(error);
}
});
}
async update(id, entity) {
return new Promise((resolve, reject) => {
const columns = Reflect.getMetadata(decorators_1.COLUMN_METADATA_KEY, this.entity) || [];
const primaryColumns = Reflect.getMetadata(decorators_1.PRIMARY_COLUMN_METADATA_KEY, this.entity) || [];
const tableName = this.metadata.name;
if (!primaryColumns.length) {
reject(new Error('No primary key defined'));
return;
}
const primaryColumn = primaryColumns[0];
const setClause = columns
.map((col) => `${col.name} = ?`)
.join(', ');
const values = [
...columns.map((col) => entity[col.propertyKey]),
id
];
const sql = `UPDATE ${tableName} SET ${setClause} WHERE ${primaryColumn.name} = ?`;
this.pool.get((err, db) => {
if (err) {
reject(err);
return;
}
db.query(sql, values, (err) => {
db.detach();
if (err) {
reject(err);
return;
}
this.findOne(id)
.then(updatedEntity => {
if (!updatedEntity) {
reject(new Error('Failed to update entity'));
return;
}
resolve(updatedEntity);
})
.catch(reject);
});
});
});
}
async delete(id) {
return new Promise((resolve, reject) => {
const primaryColumns = Reflect.getMetadata(decorators_1.PRIMARY_COLUMN_METADATA_KEY, this.entity) || [];
const tableName = this.metadata.name;
if (!primaryColumns.length) {
reject(new Error('No primary key defined'));
return;
}
const primaryColumn = primaryColumns[0];
const sql = `DELETE FROM ${tableName} WHERE ${primaryColumn.name} = ?`;
this.pool.get((err, db) => {
if (err) {
reject(err);
return;
}
db.query(sql, [id], (err) => {
db.detach();
if (err) {
reject(err);
return;
}
resolve();
});
});
});
}
}
exports.Repository = Repository;
;