From 0b56d0d6c47bae07142fcbbf3d6192f1ac9d291a Mon Sep 17 00:00:00 2001 From: KS Jannette Date: Tue, 24 Feb 2026 19:38:35 -0500 Subject: [PATCH] further DB infra buildout --- backend/data/notes.json | 402 ---------------------------------------- backend/db/README.md | 131 +++++++++++++ backend/db/seed.js | 57 +++++- 3 files changed, 183 insertions(+), 407 deletions(-) delete mode 100644 backend/data/notes.json create mode 100644 backend/db/README.md diff --git a/backend/data/notes.json b/backend/data/notes.json deleted file mode 100644 index 6e65768..0000000 --- a/backend/data/notes.json +++ /dev/null @@ -1,402 +0,0 @@ -[ - { - "id": "note_038", - "text": "Live follow mode frequently breaks", - "x": 710, - "y": 579, - "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_023", - "text": "Undo/redo sometimes lags and applies late", - "x": 236, - "y": 687, - "author": "user_9", - "color": "purple" - }, - { - "id": "note_017", - "text": "Exported file names are inconsistent and hard to track", - "x": 676, - "y": 201, - "author": "user_4", - "color": "blue" - }, - { - "id": "note_049", - "text": "Need better controls for aligning and distributing notes", - "x": 462, - "y": 487, - "author": "user_7", - "color": "green" - }, - { - "id": "note_010", - "text": "OAuth consent screen appears every time I sign in", - "x": 228, - "y": 124, - "author": "user_9", - "color": "yellow" - }, - { - "id": "note_036", - "text": "Cursor presence is distracting and overlaps content", - "x": 788, - "y": 605, - "author": "user_5", - "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_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_039", - "text": "Guest collaborators can’t see updates without refreshing", - "x": 759, - "y": 711, - "author": "user_9", - "color": "yellow" - }, - { - "id": "note_024", - "text": "App crashes when opening a large board", - "x": 239, - "y": 597, - "author": "user_10", - "color": "purple" - }, - { - "id": "note_041", - "text": "Hard to find the right template quickly", - "x": 536, - "y": 394, - "author": "user_4", - "color": "orange" - }, - { - "id": "note_040", - "text": "Activity feed lacks context about what changed", - "x": 710, - "y": 771, - "author": "user_7", - "color": "yellow" - }, - { - "id": "note_014", - "text": "Export takes too long and sometimes never finishes", - "x": 798, - "y": 211, - "author": "user_2", - "color": "green" - }, - { - "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_050", - "text": "Can’t lock sections to prevent accidental edits during workshops", - "x": 521, - "y": 471, - "author": "user_6", - "color": "orange" - }, - { - "id": "note_001", - "text": "Login flow feels confusing", - "x": 193, - "y": 191, - "author": "user_5", - "color": "yellow" - }, - { - "id": "note_025", - "text": "Saving indicator spins but changes aren’t saved", - "x": 129, - "y": 781, - "author": "user_3", - "color": "purple" - }, - { - "id": "note_021", - "text": "Board feels slow when there are many sticky notes", - "x": 341, - "y": 695, - "author": "user_10", - "color": "purple" - }, - { - "id": "note_002", - "text": "Login flow is broken on mobile", - "x": 214, - "y": 281, - "author": "user_9", - "color": "yellow" - }, - { - "id": "note_046", - "text": "Tags are missing — I need better categorization", - "x": 472, - "y": 435, - "author": "user_6", - "color": "green" - }, - { - "id": "note_018", - "text": "No way to schedule recurring exports for stakeholders", - "x": 661, - "y": 229, - "author": "user_9", - "color": "blue" - }, - { - "id": "note_034", - "text": "Too many notification emails for minor edits", - "x": 769, - "y": 739, - "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_008", - "text": "Cannot change my password — save button does nothing", - "x": 244, - "y": 188, - "author": "user_2", - "color": "orange" - }, - { - "id": "note_015", - "text": "Sharing link permissions are confusing", - "x": 688, - "y": 290, - "author": "user_6", - "color": "blue" - }, - { - "id": "note_033", - "text": "Mentions (@) don’t notify the right people", - "x": 696, - "y": 669, - "author": "user_5", - "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_028", - "text": "High CPU usage even when idle on a board", - "x": 190, - "y": 695, - "author": "user_8", - "color": "purple" - }, - { - "id": "note_009", - "text": "Account gets locked too quickly after one failed attempt", - "x": 280, - "y": 255, - "author": "user_10", - "color": "orange" - }, - { - "id": "note_029", - "text": "Offline mode loses edits when reconnecting", - "x": 338, - "y": 632, - "author": "user_1", - "color": "pink" - }, - { - "id": "note_035", - "text": "No notification when someone resolves my comment", - "x": 673, - "y": 636, - "author": "user_2", - "color": "blue" - }, - { - "id": "note_037", - "text": "Can’t easily hand off facilitation to another user", - "x": 816, - "y": 707, - "author": "user_2", - "color": "yellow" - }, - { - "id": "note_013", - "text": "Cannot export selected area — only full board exports", - "x": 696, - "y": 205, - "author": "user_4", - "color": "green" - }, - { - "id": "note_016", - "text": "Downloaded image is blurry compared to the canvas", - "x": 677, - "y": 245, - "author": "user_5", - "color": "blue" - }, - { - "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_022", - "text": "Canvas freezes for a few seconds when zooming", - "x": 254, - "y": 707, - "author": "user_8", - "color": "pink" - }, - { - "id": "note_026", - "text": "Search is slow on boards with lots of content", - "x": 253, - "y": 658, - "author": "user_2", - "color": "pink" - }, - { - "id": "note_048", - "text": "Duplicating a board loses some formatting", - "x": 382, - "y": 410, - "author": "user_10", - "color": "orange" - }, - { - "id": "note_007", - "text": "I’m logged out unexpectedly after a few minutes", - "x": 185, - "y": 157, - "author": "user_3", - "color": "yellow" - }, - { - "id": "note_045", - "text": "No bulk rename for multiple sticky notes", - "x": 455, - "y": 427, - "author": "user_1", - "color": "green" - }, - { - "id": "note_042", - "text": "Template search results feel irrelevant", - "x": 400, - "y": 474, - "author": "user_6", - "color": "orange" - }, - { - "id": "note_044", - "text": "Naming conventions aren’t enforced and things get messy", - "x": 469, - "y": 434, - "author": "user_9", - "color": "green" - }, - { - "id": "note_004", - "text": "Password reset email never arrives", - "x": 207, - "y": 267, - "author": "user_9", - "color": "yellow" - }, - { - "id": "note_047", - "text": "Hard to keep consistent styles across boards", - "x": 420, - "y": 426, - "author": "user_8", - "color": "green" - }, - { - "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_027", - "text": "Scrolling stutters on older laptops", - "x": 178, - "y": 586, - "author": "user_7", - "color": "pink" - } -] \ No newline at end of file diff --git a/backend/db/README.md b/backend/db/README.md new file mode 100644 index 0000000..7998e20 --- /dev/null +++ b/backend/db/README.md @@ -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://:@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 +``` diff --git a/backend/db/seed.js b/backend/db/seed.js index 84935fb..c7cf7e4 100644 --- a/backend/db/seed.js +++ b/backend/db/seed.js @@ -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)