queryforge
Version:
A powerful, type-safe SQL query builder for Node.js with support for MySQL, PostgreSQL, and SQLite. Features fluent API, transaction management, and connection pooling.
195 lines • 7.49 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.QueryForge = void 0;
const QueryBuilder_1 = require("./QueryBuilder");
const ConnectionManagerFactory_1 = require("./connections/ConnectionManagerFactory");
class QueryForge extends QueryBuilder_1.QueryBuilder {
constructor(config, options = {}) {
super(options);
this.connectionManager = ConnectionManagerFactory_1.ConnectionManagerFactory.create(config);
}
async connect() {
await this.connectionManager.connect();
}
async disconnect() {
await this.connectionManager.disconnect();
}
async beginTransaction() {
await this.connectionManager.beginTransaction();
}
async commit() {
await this.connectionManager.commit();
}
async rollback() {
await this.connectionManager.rollback();
}
buildQuery() {
switch (this.state.type) {
case 'SELECT':
return this.buildSelectQuery();
case 'INSERT':
return this.buildInsertQuery();
case 'UPDATE':
return this.buildUpdateQuery();
case 'DELETE':
return this.buildDeleteQuery();
default:
throw new Error(`Unsupported query type: ${this.state.type}`);
}
}
buildSelectQuery() {
const query = [];
// SELECT
query.push(`SELECT ${this.state.columns.join(', ')}`);
// FROM
query.push(`FROM ${this.state.table}`);
// JOINS
if (this.state.joins.length) {
const joins = this.state.joins.map(join => {
return `${join.type} JOIN ${join.table} ON ${join.on.leftColumn} ${join.on.operator} ${join.on.rightColumn}`;
});
query.push(joins.join(' '));
}
// WHERE
if (this.state.where.length) {
const conditions = this.state.where.map((condition, index) => {
const logic = index === 0 ? 'WHERE' : condition.logic;
return `${logic} ${condition.column} ${condition.operator} ?`;
});
query.push(conditions.join(' '));
}
// GROUP BY
if (this.state.groupBy.length) {
query.push(`GROUP BY ${this.state.groupBy.join(', ')}`);
}
// HAVING
if (this.state.having.length) {
const conditions = this.state.having.map((condition, index) => {
const logic = index === 0 ? 'HAVING' : condition.logic;
return `${logic} ${condition.column} ${condition.operator} ?`;
});
query.push(conditions.join(' '));
}
// ORDER BY
if (this.state.orderBy.length) {
const orderClauses = this.state.orderBy.map(order => {
return `${order.column} ${order.direction}`;
});
query.push(`ORDER BY ${orderClauses.join(', ')}`);
}
// LIMIT & OFFSET
if (this.state.limit !== undefined) {
query.push(`LIMIT ${this.state.limit}`);
}
if (this.state.offset !== undefined) {
query.push(`OFFSET ${this.state.offset}`);
}
return query.join(' ');
}
buildInsertQuery() {
if (this.state.values.length === 0) {
throw new Error('No values provided for insert');
}
const recordCount = this.state.values.length / this.state.columns.length;
if (!Number.isInteger(recordCount)) {
throw new Error('Invalid number of values for columns');
}
const singleRecordPlaceholders = `(${Array(this.state.columns.length).fill('?').join(', ')})`;
const allPlaceholders = Array(recordCount).fill(singleRecordPlaceholders).join(', ');
return `INSERT INTO ${this.state.table} (${this.state.columns.join(', ')}) VALUES ${allPlaceholders}`;
}
buildUpdateQuery() {
if (!this.state.updateValues) {
throw new Error('No update values provided');
}
const setClauses = Object.keys(this.state.updateValues)
.map(column => `${column} = ?`)
.join(', ');
const query = [`UPDATE ${this.state.table} SET ${setClauses}`];
if (this.state.where.length) {
const conditions = this.state.where.map((condition, index) => {
const logic = index === 0 ? 'WHERE' : condition.logic;
return `${logic} ${condition.column} ${condition.operator} ?`;
});
query.push(conditions.join(' '));
}
return query.join(' ');
}
buildDeleteQuery() {
const query = [`DELETE FROM ${this.state.table}`];
if (this.state.where.length) {
const conditions = this.state.where.map((condition, index) => {
const logic = index === 0 ? 'WHERE' : condition.logic;
return `${logic} ${condition.column} ${condition.operator} ?`;
});
query.push(conditions.join(' '));
}
return query.join(' ');
}
buildParameters() {
const parameters = [];
switch (this.state.type) {
case 'SELECT':
// WHERE parameters
this.state.where.forEach(condition => {
if (condition.value !== undefined) {
parameters.push(condition.value);
}
});
// HAVING parameters
this.state.having.forEach(condition => {
if (condition.value !== undefined) {
parameters.push(condition.value);
}
});
break;
case 'INSERT':
parameters.push(...this.state.values);
break;
case 'UPDATE':
// Update values
if (this.state.updateValues) {
parameters.push(...Object.values(this.state.updateValues));
}
// WHERE parameters
this.state.where.forEach(condition => {
if (condition.value !== undefined) {
parameters.push(condition.value);
}
});
break;
case 'DELETE':
// WHERE parameters
this.state.where.forEach(condition => {
if (condition.value !== undefined) {
parameters.push(condition.value);
}
});
break;
}
return parameters;
}
async execute() {
if (!this.connectionManager.isConnected()) {
await this.connect();
}
const query = this.buildQuery();
const parameters = this.buildParameters();
try {
if (this.options.logging) {
console.log('Executing query:', query);
console.log('Parameters:', parameters);
}
const result = await this.connectionManager.query(query, parameters);
return result.rows;
}
catch (error) {
if (error instanceof Error) {
throw new Error(`Query execution failed: ${error.message}`);
}
throw new Error('Query execution failed: Unknown error');
}
}
}
exports.QueryForge = QueryForge;
//# sourceMappingURL=QueryForge.js.map