diff --git a/server.js b/server.js
index 8a16906..c49853e 100644
--- a/server.js
+++ b/server.js
@@ -15,6 +15,7 @@ for (const [name, value] of Object.entries({ APP_BASE_URL, ISSUER, CLIENT_ID, CL
const pool = new Pool({ connectionString: DATABASE_URL, max: 5 });
const sessions = new Map();
+const PRIORITIES = new Set(['low', 'normal', 'high']);
function esc(value) {
return String(value ?? '').replace(/[&<>"']/g, ch => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' })[ch]);
@@ -66,14 +67,23 @@ function sessionFor(req) {
return session;
}
+function normalisePriority(value) {
+ const priority = String(value || 'normal').toLowerCase();
+ return PRIORITIES.has(priority) ? priority : 'normal';
+}
+
+function priorityOptions(current = 'normal') {
+ return ['low', 'normal', 'high'].map(value => ``).join('');
+}
+
function layout(user, content) {
return `
Arrowstack Tasks
-
Arrowstack Tasks
Keycloak + dedicated PostgreSQL CRUD demo
${esc(user.preferred_username || user.email || 'user')} Logout
+
Arrowstack Tasks schema v2
Keycloak + dedicated PostgreSQL CRUD demo
${esc(user.preferred_username || user.email || 'user')} Logout
${content}
`;
}
@@ -84,24 +94,33 @@ async function initDb() {
id BIGSERIAL PRIMARY KEY,
title TEXT NOT NULL CHECK (char_length(title) BETWEEN 1 AND 200),
completed BOOLEAN NOT NULL DEFAULT FALSE,
+ priority TEXT NOT NULL DEFAULT 'normal' CHECK (priority IN ('low', 'normal', 'high')),
created_by TEXT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
)
`);
+
+ await pool.query(`
+ ALTER TABLE tasks
+ ADD COLUMN IF NOT EXISTS priority TEXT NOT NULL DEFAULT 'normal'
+ CHECK (priority IN ('low', 'normal', 'high'))
+ `);
+
await pool.query(`CREATE INDEX IF NOT EXISTS idx_tasks_created_by_created_at ON tasks (created_by, created_at DESC)`);
+ await pool.query(`CREATE INDEX IF NOT EXISTS idx_tasks_created_by_priority_created_at ON tasks (created_by, priority, created_at DESC)`);
}
await initDb();
-console.log('database schema ready');
+console.log('database schema v2 ready');
const server = http.createServer(async (req, res) => {
try {
const url = new URL(req.url, APP_BASE_URL);
if (url.pathname === '/health') {
- await pool.query('SELECT 1');
- return send(res, 200, JSON.stringify({ ok: true, database: 'connected' }), 'application/json; charset=utf-8');
+ await pool.query('SELECT priority FROM tasks LIMIT 1');
+ return send(res, 200, JSON.stringify({ ok: true, database: 'connected', schema: 2 }), 'application/json; charset=utf-8');
}
if (url.pathname === '/login') {
@@ -161,7 +180,8 @@ const server = http.createServer(async (req, res) => {
if (req.method === 'POST' && url.pathname === '/tasks') {
const form = await readForm(req);
const title = String(form.title || '').trim().slice(0, 200);
- if (title) await pool.query('INSERT INTO tasks (title, created_by) VALUES ($1, $2)', [title, userKey]);
+ const priority = normalisePriority(form.priority);
+ if (title) await pool.query('INSERT INTO tasks (title, priority, created_by) VALUES ($1, $2, $3)', [title, priority, userKey]);
return redirect(res, '/');
}
@@ -174,7 +194,8 @@ const server = http.createServer(async (req, res) => {
} else if (action === 'update') {
const form = await readForm(req);
const title = String(form.title || '').trim().slice(0, 200);
- if (title) await pool.query('UPDATE tasks SET title = $1, updated_at = NOW() WHERE id = $2 AND created_by = $3', [title, id, userKey]);
+ const priority = normalisePriority(form.priority);
+ if (title) await pool.query('UPDATE tasks SET title = $1, priority = $2, updated_at = NOW() WHERE id = $3 AND created_by = $4', [title, priority, id, userKey]);
} else if (action === 'delete') {
await pool.query('DELETE FROM tasks WHERE id = $1 AND created_by = $2', [id, userKey]);
}
@@ -182,15 +203,15 @@ const server = http.createServer(async (req, res) => {
}
if (req.method === 'GET' && url.pathname === '/') {
- const result = await pool.query('SELECT id, title, completed, created_at FROM tasks WHERE created_by = $1 ORDER BY created_at DESC', [userKey]);
+ const result = await pool.query('SELECT id, title, completed, priority, created_at FROM tasks WHERE created_by = $1 ORDER BY created_at DESC', [userKey]);
const rows = result.rows.map(task => `
-
Created ${esc(new Date(task.created_at).toLocaleString())}
+
${esc(task.priority)}Created ${esc(new Date(task.created_at).toLocaleString())}
`).join('');
- return send(res, 200, layout(session.user, `${rows || '
No tasks yet. Add one above.
'}
`));
+ return send(res, 200, layout(session.user, `${rows || '
No tasks yet. Add one above.
'}
`));
}
return send(res, 404, 'Not found', 'text/plain; charset=utf-8');