feat: created_at/created_by — видно время и сервис, добавивший строку

- CREATE TABLE IF NOT EXISTS дополнена колонками:
    created_at TIMESTAMPTZ NOT NULL DEFAULT now()
    created_by TEXT NOT NULL DEFAULT ''
- ALTER TABLE ... ADD COLUMN IF NOT EXISTS досыпает колонки в уже существующую
  таблицу — данные при этом не теряются;
- INSERT пишет created_by из env SERVICE_NAME (задаётся в json_env манифеста),
  created_at ставит сама СУБД;
- список записей и UI показывают обе колонки.

Зачем: три приложения (flask / lucee / nodejs) пишут в ОДНУ таблицу — теперь
сразу видно, какое из них и когда добавило строку.
This commit is contained in:
Repinoid
2026-10-01 18:37:27 +03:00
parent 25666a977f
commit 23338cbdf5
2 changed files with 26 additions and 6 deletions
+22 -4
View File
@@ -14,6 +14,9 @@ const path = require("path");
const VERSION = "1.0.0"; const VERSION = "1.0.0";
const TABLE_NAME = process.env.TABLE_NAME || "crud_items"; const TABLE_NAME = process.env.TABLE_NAME || "crud_items";
// SERVICE_NAME — какое приложение добавило строку (колонка created_by).
// Задаётся в json_env манифеста для каждого сервиса (flask / lucee / nodejs).
const SERVICE_NAME = process.env.SERVICE_NAME || "nodejs";
const PORT = process.env.PORT || 3000; const PORT = process.env.PORT || 3000;
const pool = new Pool({ const pool = new Pool({
@@ -32,15 +35,26 @@ app.set("view engine", "ejs");
app.set("views", path.join(__dirname, "views")); app.set("views", path.join(__dirname, "views"));
// --- Инициализация БД --- // --- Инициализация БД ---
// Таблица выставочная: кроме id/value — две метки: created_at (когда добавлено)
// и created_by (какое приложение добавило). ALTER ... IF NOT EXISTS досыпает
// колонки в таблицу, созданную прошлой версией приложения, не теряя данные.
async function initDB() { async function initDB() {
const client = await pool.connect(); const client = await pool.connect();
try { try {
await client.query(` await client.query(`
CREATE TABLE IF NOT EXISTS ${TABLE_NAME} ( CREATE TABLE IF NOT EXISTS ${TABLE_NAME} (
id SERIAL PRIMARY KEY, id SERIAL PRIMARY KEY,
value TEXT NOT NULL DEFAULT '' value TEXT NOT NULL DEFAULT '',
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
created_by TEXT NOT NULL DEFAULT ''
) )
`); `);
await client.query(
`ALTER TABLE ${TABLE_NAME} ADD COLUMN IF NOT EXISTS created_at TIMESTAMPTZ NOT NULL DEFAULT now()`
);
await client.query(
`ALTER TABLE ${TABLE_NAME} ADD COLUMN IF NOT EXISTS created_by TEXT NOT NULL DEFAULT ''`
);
} finally { } finally {
client.release(); client.release();
} }
@@ -52,14 +66,14 @@ app.get("/", async (req, res) => {
let editRow = null; let editRow = null;
if (req.query.edit) { if (req.query.edit) {
const result = await pool.query( const result = await pool.query(
`SELECT id, value FROM ${TABLE_NAME} WHERE id = $1`, `SELECT id, value, created_at, created_by FROM ${TABLE_NAME} WHERE id = $1`,
[parseInt(req.query.edit)] [parseInt(req.query.edit)]
); );
if (result.rows.length > 0) editRow = result.rows[0]; if (result.rows.length > 0) editRow = result.rows[0];
} }
const result = await pool.query( const result = await pool.query(
`SELECT id, value FROM ${TABLE_NAME} ORDER BY id` `SELECT id, value, created_at, created_by FROM ${TABLE_NAME} ORDER BY id`
); );
res.render("index", { res.render("index", {
@@ -78,7 +92,11 @@ app.post("/", async (req, res) => {
const { action, value, id } = req.body; const { action, value, id } = req.body;
if (action === "create") { if (action === "create") {
await pool.query(`INSERT INTO ${TABLE_NAME} (value) VALUES ($1)`, [value || ""]); // created_at ставит СУБД (DEFAULT now()), created_by — имя этого сервиса
await pool.query(
`INSERT INTO ${TABLE_NAME} (value, created_by) VALUES ($1, $2)`,
[value || "", SERVICE_NAME]
);
} else if (action === "update") { } else if (action === "update") {
await pool.query(`UPDATE ${TABLE_NAME} SET value = $1 WHERE id = $2`, [ await pool.query(`UPDATE ${TABLE_NAME} SET value = $1 WHERE id = $2`, [
value || "", value || "",
+3 -1
View File
@@ -23,7 +23,7 @@
<table> <table>
<thead> <thead>
<tr> <tr>
<th>ID</th><th>VALUE</th> <th>ID</th><th>VALUE</th><th>ДОБАВЛЕНО</th><th>КЕМ</th>
<th style="text-align:center;"></th> <th style="text-align:center;"></th>
<th style="text-align:center;"></th> <th style="text-align:center;"></th>
</tr> </tr>
@@ -33,6 +33,8 @@
<tr> <tr>
<td><%= row.id %></td> <td><%= row.id %></td>
<td><%= row.value %></td> <td><%= row.value %></td>
<td><%= row.created_at ? new Date(row.created_at).toLocaleString('ru-RU') : '' %></td>
<td><%= row.created_by %></td>
<td style="text-align:center;"> <td style="text-align:center;">
<a href="/?edit=<%= row.id %>" class="btn btn-sm">✏️</a> <a href="/?edit=<%= row.id %>" class="btn btn-sm">✏️</a>
</td> </td>