fix(postgres): patch redbean-node for PostgreSQL dialect and bind handling, update service
All checks were successful
Deploy Beta (NATIVE) / deploy (push) Successful in 10s

This commit is contained in:
vickytechkey 2026-10-19 19:55:15 +05:30
parent a974249e6e
commit fbff2e3fd9
6 changed files with 130 additions and 4 deletions

View file

@ -48,7 +48,7 @@ jobs:
PORT=3002
UPTIME_KUMA_PORT=3002
UPTIME_KUMA_DB_TYPE=postgres
DB_HOST=16.113.106.152
DB_HOST=127.0.0.1
DB_PORT=5432
DB_USER=vignesh
DB_PASSWORD=vignesh_secret_pass_2026

View file

@ -20,7 +20,7 @@
"lint:prod": "node --run lint:js-prod && node --run lint:style",
"dev": "concurrently -k -r \"wait-on tcp:3000 && node --run start-server-dev \" \"node --run start-frontend-dev\"",
"start-frontend-dev": "cross-env NODE_ENV=development vite --host",
"start": "node --run start-server",
"start": "node --import=tsx server/server.js",
"start-server": "node --import=tsx server/server.js",
"start-server-dev": "cross-env NODE_ENV=development tsx server/server.js",
"start-server-dev:watch": "cross-env NODE_ENV=development tsx --watch server/server.js",

View file

@ -10,12 +10,12 @@ Environment=NODE_ENV=production
Environment=PORT=3002
Environment=UPTIME_KUMA_PORT=3002
Environment=UPTIME_KUMA_DB_TYPE=postgres
Environment=DB_HOST=16.113.106.152
Environment=DB_HOST=127.0.0.1
Environment=DB_PORT=5432
Environment=DB_USER=vignesh
Environment=DB_PASSWORD=vignesh_secret_pass_2026
Environment=DB_NAME=ResourceManagement
ExecStart=/usr/bin/npm start -- --port=3002
ExecStart=/usr/bin/node --import=tsx server/server.js --port=3002
Restart=always
RestartSec=10
StandardOutput=append:/home/ubuntu/resourcemanagement/logs/app.log

View file

@ -1,6 +1,7 @@
const fs = require("fs");
const fsAsync = fs.promises;
const { R } = require("redbean-node");
require("./utils/patch-redbean-postgres");
const { log, sleep, isDevEnv } = require("../src/util");
const knex = require("knex");
const path = require("path");

View file

@ -105,6 +105,7 @@ const express = require("express");
const expressStaticGzip = require("express-static-gzip");
log.debug("server", "Importing redbean-node");
const { R } = require("redbean-node");
require("./utils/patch-redbean-postgres");
log.debug("server", "Importing http-graceful-shutdown");
const gracefulShutdown = require("http-graceful-shutdown");
log.debug("server", "Importing prometheus-api-metrics");

View file

@ -0,0 +1,124 @@
const { R } = require("redbean-node");
function patchRedBeanPostgres() {
const RedBeanNode = R.constructor;
if (RedBeanNode.prototype._pgPatched) {
return;
}
RedBeanNode.prototype._pgPatched = true;
function cleanPgSql(sql) {
if (typeof sql === "string") {
return sql.replace(/`([^`]+)`/g, '"$1"');
}
return sql;
}
const origNormalizeRawCore = RedBeanNode.prototype.normalizeRawCore;
RedBeanNode.prototype.normalizeRawCore = function (sql, data) {
if (this.dbType === "pg") {
sql = cleanPgSql(sql);
}
return origNormalizeRawCore.call(this, sql, data);
};
const origNormalizeRaw = RedBeanNode.prototype.normalizeRaw;
RedBeanNode.prototype.normalizeRaw = async function (sql, data) {
let result = await this.normalizeRawCore(sql, data);
this.queryLog(sql);
if (this.dbType === "mysql") {
result = result[0];
} else if (this.dbType === "pg" && result && result.rows) {
result = result.rows;
}
return result;
};
RedBeanNode.prototype.getRow = async function (sql, data = [], autoLimit = false) {
if (autoLimit) {
if (this.dbType === "mssql") {
if (sql.trim().toLowerCase().startsWith("select ")) {
sql = sql.replace(/select/i, "$& TOP 1");
}
} else if (this.dbType === "pg") {
let limitTemplate = this.knex.limit(1).toSQL();
sql = cleanPgSql(sql) + limitTemplate.sql.replace("select *", "");
data = data.concat(limitTemplate.bindings);
} else {
let limitTemplate = this.knex.limit(1).toSQL().toNative();
sql = sql + limitTemplate.sql.replace("select *", "");
data = data.concat(limitTemplate.bindings);
}
}
this.queryLog(sql);
let result = await this.normalizeRaw(sql, data);
if (result && result.length > 0) {
return result[0];
} else {
return null;
}
};
const origFindCore = RedBeanNode.prototype.findCore;
RedBeanNode.prototype.findCore = function (type, clause, data = []) {
if (this.dbType === "pg") {
clause = cleanPgSql(clause);
}
return origFindCore.call(this, type, clause, data);
};
RedBeanNode.prototype.findOne = async function (type, clause = "", data = []) {
if (this.dbType === "pg") {
clause = cleanPgSql(clause);
}
let queryPromise = this.knex.table(type).whereRaw(clause, data).first();
this.queryLog(queryPromise);
let obj;
try {
obj = await queryPromise;
} catch (error) {
this.checkAllowedError(error);
}
if (!obj) {
return null;
}
return this.convertToBean(type, obj);
};
const origCount = RedBeanNode.prototype.count;
RedBeanNode.prototype.count = async function (type, clause = "", data = [], autoLimit = true) {
if (this.dbType === "pg") {
clause = cleanPgSql(clause);
}
return origCount.call(this, type, clause, data, autoLimit);
};
const origStoreCore = RedBeanNode.prototype.storeCore;
RedBeanNode.prototype.storeCore = async function (bean, changedFieldsOnly = true) {
if (this.dbType === "pg" && !bean.id) {
this.devLog("Store PG insert", bean.beanMeta.type);
await bean.storeTypeBeanList();
if (typeof bean.onUpdate === "function") {
bean.onUpdate();
}
let obj = bean.export(false);
delete obj.id;
let queryPromise = this.knex(bean.getType()).insert(obj).returning("id");
this.queryLog(queryPromise);
let result = await queryPromise;
bean.id = result && result[0] ? (typeof result[0] === "object" ? result[0].id : result[0]) : null;
await bean.storeSharedList();
await bean.storeOwnList();
bean.beanMeta.old = {};
if (typeof bean.onAfterUpdate === "function") {
bean.onAfterUpdate();
}
return bean.id;
}
return origStoreCore.call(this, bean, changedFieldsOnly);
};
}
patchRedBeanPostgres();
module.exports = { patchRedBeanPostgres };