further DB infra buildout
This commit is contained in:
131
backend/db/README.md
Normal file
131
backend/db/README.md
Normal file
@@ -0,0 +1,131 @@
|
||||
# Database — kongruity backend
|
||||
|
||||
PostgreSQL database layer for the kongruity backend. All database modules live in this directory.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- PostgreSQL v14 or later
|
||||
- The `DATABASE_URL` environment variable set in `backend/.env`
|
||||
|
||||
## Configuration
|
||||
|
||||
### Environment variable
|
||||
|
||||
The connection pool reads a single env var:
|
||||
|
||||
```
|
||||
DATABASE_URL=postgresql://<user>:<password>@localhost:5432/kongruity
|
||||
```
|
||||
|
||||
This is loaded via `dotenv` from `backend/.env` (git-ignored). The pool is created once in `index.js` and shared across the application.
|
||||
|
||||
### Connection pool (`index.js`)
|
||||
|
||||
| Export | Description |
|
||||
|-------------|--------------------------------------------------|
|
||||
| `query` | Execute a parameterized SQL statement |
|
||||
| `getPool` | Return the underlying `pg.Pool` instance |
|
||||
| `close` | Gracefully shut down the pool (`pool.end()`) |
|
||||
| `default` | The pool itself (default export) |
|
||||
|
||||
## Schema
|
||||
|
||||
### `notes` table
|
||||
|
||||
Created by the migration in `migrate.js`. The DDL is idempotent (`CREATE TABLE IF NOT EXISTS`).
|
||||
|
||||
| Column | Type | Constraints / Defaults |
|
||||
|---------------|----------------|------------------------------|
|
||||
| `id` | `VARCHAR(64)` | `PRIMARY KEY` |
|
||||
| `text` | `TEXT` | `NOT NULL` |
|
||||
| `x` | `INTEGER` | `DEFAULT 0` |
|
||||
| `y` | `INTEGER` | `DEFAULT 0` |
|
||||
| `author` | `VARCHAR(128)` | |
|
||||
| `color` | `VARCHAR(32)` | `DEFAULT 'yellow'` |
|
||||
| `source_meta` | `JSONB` | `DEFAULT '{}'` |
|
||||
| `created_at` | `TIMESTAMPTZ` | `DEFAULT NOW()` |
|
||||
| `updated_at` | `TIMESTAMPTZ` | `DEFAULT NOW()` |
|
||||
|
||||
## npm scripts
|
||||
|
||||
Run these from the `backend/` directory.
|
||||
|
||||
### Migrate
|
||||
|
||||
Creates the `notes` table (safe to re-run):
|
||||
|
||||
```bash
|
||||
npm run db:migrate
|
||||
```
|
||||
|
||||
### Seed
|
||||
|
||||
Inserts 50 sample sticky notes. Uses `ON CONFLICT (id) DO NOTHING`, so re-running is safe and will not duplicate data:
|
||||
|
||||
```bash
|
||||
npm run db:seed
|
||||
```
|
||||
|
||||
## Data access layer (`notes.dao.js`)
|
||||
|
||||
| Function | Description |
|
||||
|---------------------------|--------------------------------------------------------------------|
|
||||
| `getAllNotes()` | Returns all notes ordered by `id` |
|
||||
| `getNoteById(id)` | Returns a single note by primary key, or `null` if not found |
|
||||
| `createNote(note)` | Inserts one note and returns the created row |
|
||||
| `createNotes(notes)` | Bulk-inserts an array of notes in a single query and returns rows |
|
||||
|
||||
All functions return plain objects with columns: `id`, `text`, `x`, `y`, `author`, `color`.
|
||||
|
||||
## File overview
|
||||
|
||||
```
|
||||
db/
|
||||
├── index.js # Connection pool and query helper
|
||||
├── migrate.js # Table creation (run via npm run db:migrate)
|
||||
├── notes.dao.js # Data access functions for the notes table
|
||||
├── seed.js # Sample data seeder (run via npm run db:seed)
|
||||
└── README.md # This file
|
||||
```
|
||||
|
||||
## Useful psql commands
|
||||
|
||||
Connect to the database:
|
||||
|
||||
```bash
|
||||
psql kongruity
|
||||
```
|
||||
|
||||
Quick checks:
|
||||
|
||||
```sql
|
||||
-- Row count
|
||||
SELECT count(*) FROM notes;
|
||||
|
||||
-- Preview data
|
||||
SELECT id, text, color FROM notes LIMIT 10;
|
||||
|
||||
-- Full schema info
|
||||
\d notes
|
||||
|
||||
-- Drop and re-seed (destructive)
|
||||
TRUNCATE notes;
|
||||
```
|
||||
|
||||
Then re-seed:
|
||||
|
||||
```bash
|
||||
npm run db:seed
|
||||
```
|
||||
|
||||
## Resetting the database
|
||||
|
||||
To start completely fresh:
|
||||
|
||||
```bash
|
||||
dropdb kongruity
|
||||
createdb kongruity
|
||||
cd backend
|
||||
npm run db:migrate
|
||||
npm run db:seed
|
||||
```
|
||||
@@ -1,14 +1,61 @@
|
||||
import 'dotenv/config';
|
||||
import { readFile } from 'fs/promises';
|
||||
import { query, close } from './index.js';
|
||||
|
||||
const NOTES_PATH = new URL('../data/notes.json', import.meta.url);
|
||||
const notes = [
|
||||
{ id: 'note_001', text: 'Login flow feels confusing', x: 193, y: 191, author: 'user_5', color: 'yellow' },
|
||||
{ id: 'note_002', text: 'Login flow is broken on mobile', x: 214, y: 281, author: 'user_9', color: 'yellow' },
|
||||
{ id: 'note_003', text: 'When I enter my username and password I get an unknown error', x: 189, y: 193, author: 'user_2', color: 'yellow' },
|
||||
{ id: 'note_004', text: 'Password reset email never arrives', x: 207, y: 267, author: 'user_9', color: 'yellow' },
|
||||
{ id: 'note_005', text: 'SSO login loops back to the sign-in page', x: 184, y: 124, author: 'user_7', color: 'yellow' },
|
||||
{ id: 'note_006', text: 'Two-factor code is rejected even when correct', x: 162, y: 213, author: 'user_1', color: 'yellow' },
|
||||
{ id: 'note_007', text: "I'm logged out unexpectedly after a few minutes", x: 185, y: 157, author: 'user_3', color: 'yellow' },
|
||||
{ id: 'note_008', text: 'Cannot change my password — save button does nothing', x: 244, y: 188, author: 'user_2', color: 'orange' },
|
||||
{ id: 'note_009', text: 'Account gets locked too quickly after one failed attempt', x: 280, y: 255, author: 'user_10', color: 'orange' },
|
||||
{ id: 'note_010', text: 'OAuth consent screen appears every time I sign in', x: 228, y: 124, author: 'user_9', color: 'yellow' },
|
||||
{ id: 'note_011', text: 'Need better export options (PDF quality is too low)', x: 748, y: 212, author: 'user_9', color: 'green' },
|
||||
{ id: 'note_012', text: 'Exported PDF cuts off content near the edges', x: 733, y: 159, author: 'user_6', color: 'blue' },
|
||||
{ id: 'note_013', text: 'Cannot export selected area — only full board exports', x: 696, y: 205, author: 'user_4', color: 'green' },
|
||||
{ id: 'note_014', text: 'Export takes too long and sometimes never finishes', x: 798, y: 211, author: 'user_2', color: 'green' },
|
||||
{ id: 'note_015', text: 'Sharing link permissions are confusing', x: 688, y: 290, author: 'user_6', color: 'blue' },
|
||||
{ id: 'note_016', text: 'Downloaded image is blurry compared to the canvas', x: 677, y: 245, author: 'user_5', color: 'blue' },
|
||||
{ id: 'note_017', text: 'Exported file names are inconsistent and hard to track', x: 676, y: 201, author: 'user_4', color: 'blue' },
|
||||
{ id: 'note_018', text: 'No way to schedule recurring exports for stakeholders', x: 661, y: 229, author: 'user_9', color: 'blue' },
|
||||
{ id: 'note_019', text: "Embedded exports don't update when the board changes", x: 662, y: 132, author: 'user_1', color: 'blue' },
|
||||
{ id: 'note_020', text: "Can't export comments and reactions with the content", x: 739, y: 139, author: 'user_7', color: 'green' },
|
||||
{ id: 'note_021', text: 'Board feels slow when there are many sticky notes', x: 341, y: 695, author: 'user_10', color: 'purple' },
|
||||
{ id: 'note_022', text: 'Canvas freezes for a few seconds when zooming', x: 254, y: 707, author: 'user_8', color: 'pink' },
|
||||
{ id: 'note_023', text: 'Undo/redo sometimes lags and applies late', x: 236, y: 687, author: 'user_9', color: 'purple' },
|
||||
{ id: 'note_024', text: 'App crashes when opening a large board', x: 239, y: 597, author: 'user_10', color: 'purple' },
|
||||
{ id: 'note_025', text: "Saving indicator spins but changes aren't saved", x: 129, y: 781, author: 'user_3', color: 'purple' },
|
||||
{ id: 'note_026', text: 'Search is slow on boards with lots of content', x: 253, y: 658, author: 'user_2', color: 'pink' },
|
||||
{ id: 'note_027', text: 'Scrolling stutters on older laptops', x: 178, y: 586, author: 'user_7', color: 'pink' },
|
||||
{ id: 'note_028', text: 'High CPU usage even when idle on a board', x: 190, y: 695, author: 'user_8', color: 'purple' },
|
||||
{ id: 'note_029', text: 'Offline mode loses edits when reconnecting', x: 338, y: 632, author: 'user_1', color: 'pink' },
|
||||
{ id: 'note_030', text: "I see random 'something went wrong' banners with no details", x: 214, y: 594, author: 'user_5', color: 'purple' },
|
||||
{ id: 'note_031', text: 'Hard to tell who is editing what in real time', x: 761, y: 704, author: 'user_8', color: 'yellow' },
|
||||
{ id: 'note_032', text: 'Comments get lost — no clear thread view', x: 818, y: 641, author: 'user_5', color: 'yellow' },
|
||||
{ id: 'note_033', text: "Mentions (@) don't notify the right people", x: 696, y: 669, author: 'user_5', color: 'yellow' },
|
||||
{ id: 'note_034', text: 'Too many notification emails for minor edits', x: 769, y: 739, author: 'user_9', color: 'yellow' },
|
||||
{ id: 'note_035', text: 'No notification when someone resolves my comment', x: 673, y: 636, author: 'user_2', color: 'blue' },
|
||||
{ id: 'note_036', text: 'Cursor presence is distracting and overlaps content', x: 788, y: 605, author: 'user_5', color: 'yellow' },
|
||||
{ id: 'note_037', text: "Can't easily hand off facilitation to another user", x: 816, y: 707, author: 'user_2', color: 'yellow' },
|
||||
{ id: 'note_038', text: 'Live follow mode frequently breaks', x: 710, y: 579, author: 'user_9', color: 'yellow' },
|
||||
{ id: 'note_039', text: "Guest collaborators can't see updates without refreshing", x: 759, y: 711, author: 'user_9', color: 'yellow' },
|
||||
{ id: 'note_040', text: 'Activity feed lacks context about what changed', x: 710, y: 771, author: 'user_7', color: 'yellow' },
|
||||
{ id: 'note_041', text: 'Hard to find the right template quickly', x: 536, y: 394, author: 'user_4', color: 'orange' },
|
||||
{ id: 'note_042', text: 'Template search results feel irrelevant', x: 400, y: 474, author: 'user_6', color: 'orange' },
|
||||
{ id: 'note_043', text: "Can't organize boards into folders the way I need", x: 504, y: 398, author: 'user_4', color: 'green' },
|
||||
{ id: 'note_044', text: "Naming conventions aren't enforced and things get messy", x: 469, y: 434, author: 'user_9', color: 'green' },
|
||||
{ id: 'note_045', text: 'No bulk rename for multiple sticky notes', x: 455, y: 427, author: 'user_1', color: 'green' },
|
||||
{ id: 'note_046', text: 'Tags are missing — I need better categorization', x: 472, y: 435, author: 'user_6', color: 'green' },
|
||||
{ id: 'note_047', text: 'Hard to keep consistent styles across boards', x: 420, y: 426, author: 'user_8', color: 'green' },
|
||||
{ id: 'note_048', text: 'Duplicating a board loses some formatting', x: 382, y: 410, author: 'user_10', color: 'orange' },
|
||||
{ id: 'note_049', text: 'Need better controls for aligning and distributing notes', x: 462, y: 487, author: 'user_7', color: 'green' },
|
||||
{ id: 'note_050', text: "Can't lock sections to prevent accidental edits during workshops", x: 521, y: 471, author: 'user_6', color: 'orange' },
|
||||
];
|
||||
|
||||
const run = async () => {
|
||||
try {
|
||||
const raw = await readFile(NOTES_PATH, 'utf-8');
|
||||
const notes = JSON.parse(raw);
|
||||
|
||||
const insertQuery = `
|
||||
INSERT INTO notes (id, text, x, y, author, color)
|
||||
VALUES ($1, $2, $3, $4, $5, $6)
|
||||
|
||||
Reference in New Issue
Block a user