@adinet/indigodb
Version:
ORM for PostgreSQL and MongoDB with real-time support
158 lines (157 loc) • 6.27 kB
JavaScript
;
// 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;