UNPKG

@adinet/indigodb

Version:

ORM for PostgreSQL and MongoDB with real-time support

158 lines (157 loc) 6.27 kB
"use strict"; // src/models/postgresModel.ts var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); class PostgresModel { constructor(name, schema, orm) { this.name = name; this.schema = schema; this.orm = orm; this.client = orm.client; this.init(); } init() { return __awaiter(this, void 0, void 0, function* () { yield this.createTable(); yield this.setupTriggers(); }); } createTable() { return __awaiter(this, void 0, void 0, function* () { const columns = []; for (const [columnName, columnProps] of Object.entries(this.schema)) { let columnDef = `${columnName} ${this.mapDataType(columnProps.type)}`; if (columnProps.primaryKey) columnDef += " PRIMARY KEY"; if (columnProps.autoIncrement) columnDef += " GENERATED ALWAYS AS IDENTITY"; if (columnProps.unique) columnDef += " UNIQUE"; columns.push(columnDef); } const createTableQuery = ` CREATE TABLE IF NOT EXISTS ${this.name} ( ${columns.join(", ")} ); `; yield this.client.query(createTableQuery); }); } setupTriggers() { return __awaiter(this, void 0, void 0, function* () { const functionName = `notify_${this.name}_change`; const triggerName = `${this.name}_change_trigger`; const createFunctionQuery = ` CREATE OR REPLACE FUNCTION ${functionName}() RETURNS trigger AS $$ DECLARE record RECORD; payload TEXT; BEGIN IF TG_OP = 'DELETE' THEN record := OLD; ELSE record := NEW; END IF; payload := json_build_object( 'model', '${this.name}', 'operation', TG_OP, 'data', row_to_json(record) )::text; PERFORM pg_notify('realtime_updates', payload); RETURN NULL; END; $$ LANGUAGE plpgsql; `; const createTriggerQuery = ` DROP TRIGGER IF EXISTS ${triggerName} ON ${this.name}; CREATE TRIGGER ${triggerName} AFTER INSERT OR UPDATE OR DELETE ON ${this.name} FOR EACH ROW EXECUTE FUNCTION ${functionName}(); `; yield this.client.query(createFunctionQuery); yield this.client.query(createTriggerQuery); }); } create(data) { return __awaiter(this, void 0, void 0, function* () { const columns = Object.keys(data).join(", "); const values = Object.values(data); const placeholders = values.map((_, index) => `$${index + 1}`).join(", "); const insertQuery = `INSERT INTO ${this.name} (${columns}) VALUES (${placeholders}) RETURNING *;`; const result = yield this.client.query(insertQuery, values); return result.rows[0]; }); } findAll(criteria = {}) { return __awaiter(this, void 0, void 0, function* () { let query = `SELECT * FROM ${this.name}`; const whereClauses = []; const values = []; Object.entries(criteria).forEach(([key, value], index) => { whereClauses.push(`${key} = $${index + 1}`); values.push(value); }); if (whereClauses.length > 0) { query += ` WHERE ${whereClauses.join(" AND ")}`; } const result = yield this.client.query(query, values); return result.rows; }); } findById(id) { return __awaiter(this, void 0, void 0, function* () { const query = `SELECT * FROM ${this.name} WHERE _id = $1;`; const result = yield this.client.query(query, [id]); return result.rows[0] ? result.rows[0] : null; }); } update(id, data) { return __awaiter(this, void 0, void 0, function* () { const updates = []; const values = []; let index = 1; for (const [key, value] of Object.entries(data)) { updates.push(`${key} = $${index++}`); values.push(value); } values.push(id); const updateQuery = `UPDATE ${this.name} SET ${updates.join(", ")} WHERE _id = $${index} RETURNING *;`; const result = yield this.client.query(updateQuery, values); return result.rows[0] ? result.rows[0] : null; }); } delete(id) { return __awaiter(this, void 0, void 0, function* () { const deleteQuery = `DELETE FROM ${this.name} WHERE _id = $1 RETURNING *;`; const result = yield this.client.query(deleteQuery, [id]); return result.rows[0] ? result.rows[0] : null; }); } mapDataType(type) { switch (type) { case "INTEGER": return "INTEGER"; case "STRING": return "VARCHAR(255)"; case "FLOAT": return "REAL"; case "BOOLEAN": return "BOOLEAN"; case "DATE": return "TIMESTAMP"; case "TEXT": return "TEXT"; default: throw new Error(`Unsupported data type: ${type}`); } } } exports.default = PostgresModel;