Compare commits
No commits in common. "e4774ecd6a300ebc52b7e8d79d0b2e9dddbb5f64" and "5a2848ebcfdbbe1dc054b26ec4802f7e4a75ae7a" have entirely different histories.
e4774ecd6a
...
5a2848ebcf
@ -1,40 +0,0 @@
|
|||||||
---
|
|
||||||
name: fiddy-verify
|
|
||||||
description: Run and report the Fiddy repository verification loop. Use when Codex is finishing changes, checking repo health, validating docs/scripts/config updates, or deciding which lint/typecheck/test/build commands are appropriate for this Express/Vite/npm project.
|
|
||||||
---
|
|
||||||
|
|
||||||
# Fiddy Verification
|
|
||||||
|
|
||||||
Use this workflow from the repo root.
|
|
||||||
|
|
||||||
## Before Running Commands
|
|
||||||
- Read `AGENTS.md`, `PROJECT_INSTRUCTIONS.md`, and any doc related to the touched area.
|
|
||||||
- Check `git status --short --branch` so user work is not mistaken for Codex changes.
|
|
||||||
- Do not print real `.env` values. Inspect keys only if environment context is needed.
|
|
||||||
- Do not run DB migrations unless the user explicitly asked for migration execution.
|
|
||||||
|
|
||||||
## Choose Checks
|
|
||||||
- Docs-only changes: validate affected Markdown links/content where practical, then run JSON/script sanity checks if package files changed.
|
|
||||||
- Root or frontend script changes: run `npm run lint`, `npm run typecheck`, and the relevant build command.
|
|
||||||
- Backend behavior changes: run `npm test`; add focused Jest/Supertest coverage for changed API behavior.
|
|
||||||
- Frontend behavior changes: run `npm run lint`, `npm run typecheck`, and focused Playwright tests when a browser flow changed.
|
|
||||||
- Dependency or lockfile changes: run `npm run audit` after install/update commands.
|
|
||||||
- Migration changes: run `npm run db:migrate:stale:check` and `npm run db:migrate:verify` only against the intended external DB environment.
|
|
||||||
|
|
||||||
## Default Safe Loop
|
|
||||||
Run these when dependencies are already installed and the touched files justify them:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm run lint
|
|
||||||
npm run typecheck
|
|
||||||
npm run audit
|
|
||||||
npm test
|
|
||||||
npm run build:backend
|
|
||||||
npm run build:frontend
|
|
||||||
```
|
|
||||||
|
|
||||||
## Report
|
|
||||||
- List exact commands run and pass/fail.
|
|
||||||
- For failures, include the short relevant error and whether it appears caused by the current changes.
|
|
||||||
- If a check is skipped, state the concrete reason.
|
|
||||||
- End with unresolved risks and the smallest useful next step.
|
|
||||||
@ -5,7 +5,7 @@ on:
|
|||||||
branches: [ "main" ]
|
branches: [ "main" ]
|
||||||
|
|
||||||
env:
|
env:
|
||||||
REGISTRY: git.nicosaya.com/nalalangan/grocery-app
|
REGISTRY: git.nicosaya.com/nalalangan/costco-grocery-list
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
@ -125,3 +125,4 @@ jobs:
|
|||||||
curl -d "$MSG" \
|
curl -d "$MSG" \
|
||||||
https://ntfy.nicosaya.com/gitea
|
https://ntfy.nicosaya.com/gitea
|
||||||
|
|
||||||
|
|
||||||
@ -5,7 +5,7 @@ on:
|
|||||||
branches: [ "main-new" ]
|
branches: [ "main-new" ]
|
||||||
|
|
||||||
env:
|
env:
|
||||||
REGISTRY: git.nicosaya.com/nalalangan/grocery-app
|
REGISTRY: git.nicosaya.com/nalalangan/costco-grocery-list
|
||||||
# REGISTRY: grocery-app
|
# REGISTRY: grocery-app
|
||||||
IMAGE_TAG: main-new
|
IMAGE_TAG: main-new
|
||||||
|
|
||||||
@ -147,3 +147,4 @@ jobs:
|
|||||||
curl -d "$MSG" \
|
curl -d "$MSG" \
|
||||||
https://ntfy.nicosaya.com/gitea
|
https://ntfy.nicosaya.com/gitea
|
||||||
|
|
||||||
|
|
||||||
144
AGENTS.md
144
AGENTS.md
@ -1,111 +1,57 @@
|
|||||||
# AGENTS.md - Fiddy
|
# AGENTS.md - Fiddy (External DB)
|
||||||
|
|
||||||
## Authority
|
## Authority
|
||||||
- Source of truth: `PROJECT_INSTRUCTIONS.md` in the repo root.
|
- Source of truth: `PROJECT_INSTRUCTIONS.md` (repo root). If conflict, follow it.
|
||||||
- Bugfix protocol: `DEBUGGING_INSTRUCTIONS.md`.
|
- Bugfix protocol: `DEBUGGING_INSTRUCTIONS.md` (repo root).
|
||||||
- Current-stack mapping: `docs/AGENTIC_CONTRACT_MAP.md`.
|
- Do not implement features unless required to fix the bug.
|
||||||
- If files conflict, follow `PROJECT_INSTRUCTIONS.md`.
|
|
||||||
|
|
||||||
## Project Overview
|
## Non-negotiables
|
||||||
- Full-stack grocery list app with household/group behavior, RBAC, image support, and Postgres persistence.
|
- External DB: `DATABASE_URL` points to on-prem Postgres (NOT a container).
|
||||||
- Backend: Express 5 CommonJS API in `backend/`.
|
- Dev/Prod share schema via migrations in `packages/db/migrations`.
|
||||||
- Frontend: React 19 + Vite SPA in `frontend/`, with partial TypeScript.
|
- No cron/worker jobs. Fixes must work without background tasks.
|
||||||
- Database: external on-prem Postgres. Do not add or assume a DB container.
|
- Server-side RBAC only. Client checks are UX only.
|
||||||
- Canonical migrations live in `packages/db/migrations`.
|
|
||||||
|
|
||||||
## Important Directories
|
## Security / logging (hard rules)
|
||||||
- `backend/routes`, `backend/controllers`: route registration and request/response handling.
|
- Never log secrets (passwords/tokens/cookies).
|
||||||
- `backend/models`, `backend/services`, `backend/middleware`, `backend/db`: DB access, domain logic, auth, RBAC, request IDs, image handling.
|
- Never log receipt bytes.
|
||||||
- `frontend/src/api`: client API wrappers using the shared Axios instance.
|
- Never log full invite codes; logs/audit store last4 only.
|
||||||
- `frontend/src/context`, `frontend/src/hooks`, `frontend/src/components`, `frontend/src/pages`: UI state and screens.
|
|
||||||
- `frontend/tests`: Playwright e2e tests.
|
|
||||||
- `backend/tests`: Jest/Supertest backend tests.
|
|
||||||
- `scripts`: DB migration helpers.
|
|
||||||
- `docs`: practical maps, runbooks, architecture notes, and archived implementation history.
|
|
||||||
|
|
||||||
## Setup
|
## Non-regression contracts
|
||||||
- Install root tools: `npm ci`
|
- Sessions are DB-backed (`sessions` table) and cookies are HttpOnly.
|
||||||
- Install backend tools: `npm --prefix backend ci`
|
- Receipt images stored in `receipts` (`bytea`).
|
||||||
- Install frontend tools: `npm --prefix frontend ci`
|
- Entries list endpoints must NEVER return receipt bytes.
|
||||||
- Use Node.js 20.19+ or 22.12+ for frontend/Vite commands.
|
- API responses must include `request_id`; audit logs must include `request_id`.
|
||||||
- Configure backend env from `backend/.env.example`; never commit real `.env` values.
|
- Frontend actions that manipulate database state must show a toast/bubble notification with basic outcome info (action + target + success/failure).
|
||||||
- For migration scripts, set `DATABASE_URL` in the shell before running root DB commands.
|
- Progress-type notifications must reuse the existing upload toaster pattern (`UploadQueueContext` + `UploadToaster`).
|
||||||
|
|
||||||
## Run Commands
|
## Architecture boundaries (follow existing patterns; do not invent)
|
||||||
- Dev with Docker: `docker compose -f docker-compose.dev.yml up`
|
1) API routes: `app/api/**/route.ts`
|
||||||
- Backend only: `npm run dev:backend`
|
- Thin: parse/validate + call service, return JSON.
|
||||||
- Frontend only: `npm run dev:frontend`
|
2) Server services: `lib/server/*`
|
||||||
- Backend default port: `5000`
|
- Own DB + authz. Must include `import "server-only";`.
|
||||||
- Frontend Docker-mapped port: `3010`; Vite direct default is `5173` unless overridden.
|
3) Client wrappers: `lib/client/*`
|
||||||
|
- Typed fetch + error normalization; always send credentials.
|
||||||
|
4) Hooks: `hooks/use-*.ts`
|
||||||
|
- Primary UI-facing API layer; components avoid raw `fetch()`.
|
||||||
|
|
||||||
## Verification Commands
|
## Next.js dynamic route params (required)
|
||||||
- Backend unit/API tests: `npm test`
|
- In `app/api/**/[param]/route.ts`, treat `context.params` as async:
|
||||||
- Frontend lint: `npm run lint`
|
- `const { id } = await context.params;`
|
||||||
- Frontend typecheck: `npm run typecheck`
|
|
||||||
- Vulnerability audit: `npm run audit`
|
|
||||||
- Backend build: `npm run build:backend`
|
|
||||||
- Frontend build: `npm run build:frontend`
|
|
||||||
- Full build: `npm run build`
|
|
||||||
- E2E tests: `npm run test:e2e`
|
|
||||||
- Migration status: `npm run db:migrate:status`
|
|
||||||
- Migration verification: `npm run db:migrate:verify`
|
|
||||||
|
|
||||||
## Environment Notes
|
## Working style
|
||||||
- `backend/.env` is used by the backend and Docker dev service.
|
- Scan repo first; do not guess file names or patterns.
|
||||||
- `frontend/.env` may define `VITE_API_URL` and `VITE_ALLOWED_HOSTS`.
|
- Make the smallest change that resolves the issue.
|
||||||
- Do not print, log, or commit secrets, tokens, cookies, DB URLs, receipt bytes, or full invite codes.
|
- Religiously commit work in small, verified slices; prefer frequent checkpoint commits over large end-state batches.
|
||||||
- Logs/audit entries for invite codes may include last4 only.
|
- Follow the commit discipline in `PROJECT_INSTRUCTIONS.md` for every slice, including Conventional Commit messages and related-file-only scope.
|
||||||
|
- Keep touched files free of TS warnings and lint errors.
|
||||||
|
- Add/update tests when API behavior changes (include negative cases).
|
||||||
|
- Keep text encoding clean (no mojibake).
|
||||||
|
|
||||||
## Coding Conventions
|
## Response icon legend
|
||||||
- Preserve the current stack; do not migrate to Next.js or another framework.
|
Use the same status icons defined in `PROJECT_INSTRUCTIONS.md` section "Agent Response Legend (required)":
|
||||||
- Keep Express routes/controllers thin; put DB-heavy work in models/services and authz in backend layers.
|
|
||||||
- Keep frontend network calls in `frontend/src/api` wrappers and UI state in context/hooks.
|
|
||||||
- Always send credentials through the shared Axios client when touching authenticated frontend API calls.
|
|
||||||
- Enforce RBAC server-side; client guards are UX only.
|
|
||||||
- Frontend DB-mutating actions must show toast/bubble outcome notifications.
|
|
||||||
- Progress notifications must reuse `UploadQueueContext` and `UploadToaster`.
|
|
||||||
- Keep encoding clean; do not introduce mojibake.
|
|
||||||
|
|
||||||
## Dependency Rules
|
|
||||||
- npm is the package manager; do not introduce pnpm, yarn, bun, or another build tool.
|
|
||||||
- Do not add production dependencies unless the task clearly requires it and the repo has no practical existing option.
|
|
||||||
- Do not add cron, workers, polling daemons, or background job frameworks.
|
|
||||||
|
|
||||||
## Testing Expectations
|
|
||||||
- Add or update tests when API behavior changes.
|
|
||||||
- Include negative cases for authz, membership, and invalid input where applicable.
|
|
||||||
- For UI behavior changes, prefer focused Playwright tests.
|
|
||||||
- Run the narrowest relevant checks first, then broader checks when risk warrants it.
|
|
||||||
|
|
||||||
## Done Means
|
|
||||||
- Behavior is preserved unless the task explicitly requires a change.
|
|
||||||
- Relevant tests/lint/typecheck/build commands were run or the reason they could not run is documented.
|
|
||||||
- Touched files have no known TS/lint errors.
|
|
||||||
- Migrations are in `packages/db/migrations` when schema changes are required.
|
|
||||||
- Documentation is updated for changed commands, contracts, or workflows.
|
|
||||||
|
|
||||||
## Codex Must Not
|
|
||||||
- Do not read or expose real `.env` values; inspect variable names only when needed.
|
|
||||||
- Do not touch production data or run DB migrations without explicit operator intent.
|
|
||||||
- Do not log secrets, receipt bytes, or full invite codes.
|
|
||||||
- Do not delete user work or generated artifacts unless explicitly asked.
|
|
||||||
- Do not make broad refactors, file moves, or framework changes for cleanup alone.
|
|
||||||
|
|
||||||
## Deeper Docs
|
|
||||||
- `docs/PROJECT_MAP.md`: quick repo orientation.
|
|
||||||
- `docs/DEVELOPMENT.md`: setup, run, verify, and troubleshooting.
|
|
||||||
- `docs/DB_MIGRATION_WORKFLOW.md`: migration runbook.
|
|
||||||
- `docs/PLANS.md`: template for multi-step work.
|
|
||||||
- `.agents/skills/fiddy-verify/SKILL.md`: repo-specific verification workflow for Codex.
|
|
||||||
|
|
||||||
## Response Icon Legend
|
|
||||||
- `🔄` in progress
|
- `🔄` in progress
|
||||||
- `✅` completed
|
- `✅` completed
|
||||||
- `🧪` verification/test result
|
- `🧪` verification/test result
|
||||||
- `📄` documentation update
|
- `⚠️` risk/blocker/manual action
|
||||||
- `🗄️` database or migration change
|
- `❌` failure
|
||||||
- `🚀` deploy/release step
|
- `🧭` recommendation/next step
|
||||||
- `⚠️` risk, blocker, or manual operator action needed
|
|
||||||
- `❌` failed command or unsuccessful attempt
|
|
||||||
- `ℹ️` informational context
|
|
||||||
- `🧭` recommendation or next-step option
|
|
||||||
|
|||||||
10
README.md
10
README.md
@ -2,8 +2,6 @@
|
|||||||
|
|
||||||
A full-stack web application for managing grocery shopping lists with role-based access control, image support, and intelligent item classification.
|
A full-stack web application for managing grocery shopping lists with role-based access control, image support, and intelligent item classification.
|
||||||
|
|
||||||
> Current maintainer notes: `PROJECT_INSTRUCTIONS.md` is the source of truth for project constraints. For current setup, run, and verification commands, start with `docs/DEVELOPMENT.md` and `docs/PROJECT_MAP.md`; some older sections below are historical and should be checked against current code before changing behavior.
|
|
||||||
|
|
||||||

|

|
||||||

|

|
||||||

|

|
||||||
@ -326,8 +324,8 @@ router.post("/add",
|
|||||||
|
|
||||||
1. **Clone the repository**
|
1. **Clone the repository**
|
||||||
```bash
|
```bash
|
||||||
git clone https://git.nicosaya.com/nalalangan/grocery-app.git
|
git clone https://github.com/your-org/costco-grocery-list.git
|
||||||
cd grocery-app
|
cd costco-grocery-list
|
||||||
```
|
```
|
||||||
|
|
||||||
2. **Configure environment variables**
|
2. **Configure environment variables**
|
||||||
@ -423,7 +421,7 @@ Authorization: Bearer <your_jwt_token>
|
|||||||
## 📁 Project Structure
|
## 📁 Project Structure
|
||||||
|
|
||||||
```
|
```
|
||||||
grocery-app/
|
costco-grocery-list/
|
||||||
├── .gitea/
|
├── .gitea/
|
||||||
│ └── workflows/
|
│ └── workflows/
|
||||||
│ └── deploy.yml # CI/CD pipeline configuration
|
│ └── deploy.yml # CI/CD pipeline configuration
|
||||||
@ -749,7 +747,7 @@ This project is licensed under the MIT License - see the LICENSE file for detail
|
|||||||
## 👤 Author
|
## 👤 Author
|
||||||
|
|
||||||
**Nico Saya**
|
**Nico Saya**
|
||||||
- Repository: [git.nicosaya.com/nalalangan/grocery-app](https://git.nicosaya.com/nalalangan/grocery-app)
|
- Repository: [git.nicosaya.com/nalalangan/costco-grocery-list](https://git.nicosaya.com/nalalangan/costco-grocery-list)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@ -1,62 +0,0 @@
|
|||||||
"use strict";
|
|
||||||
|
|
||||||
const fs = require("fs");
|
|
||||||
const path = require("path");
|
|
||||||
|
|
||||||
const rootDir = __dirname;
|
|
||||||
const distDir = path.join(rootDir, "dist");
|
|
||||||
|
|
||||||
const directoriesToCopy = [
|
|
||||||
"config",
|
|
||||||
"constants",
|
|
||||||
"controllers",
|
|
||||||
"db",
|
|
||||||
"middleware",
|
|
||||||
"models",
|
|
||||||
"routes",
|
|
||||||
"services",
|
|
||||||
"utils",
|
|
||||||
"public",
|
|
||||||
];
|
|
||||||
|
|
||||||
const filesToCopy = ["app.js", "server.js", "package.json", "package-lock.json"];
|
|
||||||
|
|
||||||
function copyFile(sourcePath, targetPath) {
|
|
||||||
fs.mkdirSync(path.dirname(targetPath), { recursive: true });
|
|
||||||
fs.copyFileSync(sourcePath, targetPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
function copyDirectory(sourceDir, targetDir) {
|
|
||||||
if (!fs.existsSync(sourceDir)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const entry of fs.readdirSync(sourceDir, { withFileTypes: true })) {
|
|
||||||
const sourcePath = path.join(sourceDir, entry.name);
|
|
||||||
const targetPath = path.join(targetDir, entry.name);
|
|
||||||
|
|
||||||
if (entry.isDirectory()) {
|
|
||||||
copyDirectory(sourcePath, targetPath);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entry.isFile()) {
|
|
||||||
copyFile(sourcePath, targetPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fs.mkdirSync(distDir, { recursive: true });
|
|
||||||
|
|
||||||
for (const directory of directoriesToCopy) {
|
|
||||||
copyDirectory(path.join(rootDir, directory), path.join(distDir, directory));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const file of filesToCopy) {
|
|
||||||
const sourcePath = path.join(rootDir, file);
|
|
||||||
if (fs.existsSync(sourcePath)) {
|
|
||||||
copyFile(sourcePath, path.join(distDir, file));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`Backend build copied runtime files to ${path.relative(rootDir, distDir)}`);
|
|
||||||
2206
backend/package-lock.json
generated
2206
backend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -10,12 +10,13 @@
|
|||||||
"sharp": "^0.34.5"
|
"sharp": "^0.34.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"cpx": "^1.5.0",
|
||||||
"esbuild": "^0.25.5",
|
"esbuild": "^0.25.5",
|
||||||
"nodemon": "^3.1.11",
|
"nodemon": "^3.1.11",
|
||||||
"rimraf": "^6.0.1"
|
"rimraf": "^6.0.1"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "rimraf dist && node build.js",
|
"build": "rimraf dist && node build.js && cpx \"public/**/*\" dist/public",
|
||||||
"dev": "nodemon server.js"
|
"dev": "nodemon server.js"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
services:
|
services:
|
||||||
backend:
|
backend:
|
||||||
image: git.nicosaya.com/nalalangan/grocery-app/backend:main-new
|
image: git.nicosaya.com/nalalangan/costco-grocery-list/backend:main-new
|
||||||
# image: grocery-app/backend:main-new
|
# image: grocery-app/backend:main-new
|
||||||
restart: always
|
restart: always
|
||||||
env_file:
|
env_file:
|
||||||
@ -9,7 +9,7 @@ services:
|
|||||||
- "5001:5000"
|
- "5001:5000"
|
||||||
|
|
||||||
frontend:
|
frontend:
|
||||||
image: git.nicosaya.com/nalalangan/grocery-app/frontend:main-new
|
image: git.nicosaya.com/nalalangan/costco-grocery-list/frontend:main-new
|
||||||
# image: grocery-app/frontend:main-new
|
# image: grocery-app/frontend:main-new
|
||||||
restart: always
|
restart: always
|
||||||
env_file:
|
env_file:
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
services:
|
services:
|
||||||
backend:
|
backend:
|
||||||
image: git.nicosaya.com/nalalangan/grocery-app/backend:latest
|
image: git.nicosaya.com/nalalangan/costco-grocery-list/backend:latest
|
||||||
restart: always
|
restart: always
|
||||||
env_file:
|
env_file:
|
||||||
- ./backend.env
|
- ./backend.env
|
||||||
@ -8,7 +8,7 @@ services:
|
|||||||
- "5000:5000"
|
- "5000:5000"
|
||||||
|
|
||||||
frontend:
|
frontend:
|
||||||
image: git.nicosaya.com/nalalangan/grocery-app/frontend:latest
|
image: git.nicosaya.com/nalalangan/costco-grocery-list/frontend:latest
|
||||||
restart: always
|
restart: always
|
||||||
env_file:
|
env_file:
|
||||||
- ./frontend.env
|
- ./frontend.env
|
||||||
|
|||||||
@ -1,95 +0,0 @@
|
|||||||
# Development
|
|
||||||
|
|
||||||
Use this as the practical setup and verification guide. `PROJECT_INSTRUCTIONS.md` remains the source of truth for constraints.
|
|
||||||
|
|
||||||
## Prerequisites
|
|
||||||
- Node.js 20.19+ or 22.12+ for the current Vite toolchain.
|
|
||||||
- npm.
|
|
||||||
- PostgreSQL client tools if running migration scripts (`psql` must be on `PATH`).
|
|
||||||
- Access to the external Postgres database through `DATABASE_URL` or backend DB variables.
|
|
||||||
- Docker is optional for local app containers.
|
|
||||||
|
|
||||||
## Install
|
|
||||||
Run installs separately because this repo does not define npm workspaces.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm ci
|
|
||||||
npm --prefix backend ci
|
|
||||||
npm --prefix frontend ci
|
|
||||||
```
|
|
||||||
|
|
||||||
## Environment
|
|
||||||
- Copy `backend/.env.example` to `backend/.env` for backend runtime configuration.
|
|
||||||
- Copy `frontend/.env.example` to `frontend/.env` if the frontend needs non-default API or host settings.
|
|
||||||
- Do not commit real `.env` files.
|
|
||||||
- Root DB migration scripts read `DATABASE_URL` from the shell environment; they do not load `backend/.env` automatically.
|
|
||||||
|
|
||||||
Important variables:
|
|
||||||
|
|
||||||
| Variable | Used by | Notes |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| `DATABASE_URL` | backend, root migration scripts | Preferred external Postgres connection string. |
|
|
||||||
| `DB_USER`, `DB_PASS`, `DB_HOST`, `DB_PORT`, `DB_NAME` | backend fallback | Used only when `DATABASE_URL` is absent. |
|
|
||||||
| `JWT_SECRET` | backend auth | Required for token/session-compatible auth paths. |
|
|
||||||
| `ALLOWED_ORIGINS` | backend CORS | Comma-separated allowed frontend origins. |
|
|
||||||
| `SESSION_COOKIE_NAME`, `SESSION_TTL_DAYS` | backend cookies | Optional; defaults are defined in code. |
|
|
||||||
| `VITE_API_URL` | frontend | Defaults to `http://localhost:5000`. |
|
|
||||||
| `VITE_ALLOWED_HOSTS` | Vite dev server | Comma-separated host allowlist. |
|
|
||||||
| `PLAYWRIGHT_BASE_URL` | Playwright | Defaults to `http://localhost:3010`. |
|
|
||||||
|
|
||||||
## Run Locally
|
|
||||||
Docker dev stack:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker compose -f docker-compose.dev.yml up
|
|
||||||
```
|
|
||||||
|
|
||||||
Separate terminals:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm run dev:backend
|
|
||||||
npm run dev:frontend
|
|
||||||
```
|
|
||||||
|
|
||||||
Default local endpoints:
|
|
||||||
- Backend: `http://localhost:5000`
|
|
||||||
- Frontend through Docker compose port mapping: `http://localhost:3010`
|
|
||||||
- Frontend direct Vite default: `http://localhost:5173`
|
|
||||||
|
|
||||||
## Verification Commands
|
|
||||||
Root entry points:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm test
|
|
||||||
npm run lint
|
|
||||||
npm run typecheck
|
|
||||||
npm run audit
|
|
||||||
npm run build:backend
|
|
||||||
npm run build:frontend
|
|
||||||
npm run build
|
|
||||||
npm run test:e2e
|
|
||||||
```
|
|
||||||
|
|
||||||
Migration checks:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm run db:migrate:status
|
|
||||||
npm run db:migrate:verify
|
|
||||||
npm run db:migrate:stale:check
|
|
||||||
```
|
|
||||||
|
|
||||||
Do not run `npm run db:migrate` against a shared or production database unless that is the explicit operator task.
|
|
||||||
|
|
||||||
## Common Troubleshooting
|
|
||||||
- `DATABASE_URL is required`: export/set `DATABASE_URL` in the shell before root migration commands.
|
|
||||||
- `psql executable was not found in PATH`: install PostgreSQL client tools.
|
|
||||||
- Frontend cannot reach backend: confirm `VITE_API_URL`, backend port `5000`, and backend `ALLOWED_ORIGINS`.
|
|
||||||
- Playwright starts the frontend but API calls fail: start the backend separately or use the Docker dev stack.
|
|
||||||
- CORS blocked origin: add the exact frontend origin to `ALLOWED_ORIGINS`.
|
|
||||||
|
|
||||||
## Before Finishing Work
|
|
||||||
- Re-read `AGENTS.md` and any relevant deeper doc.
|
|
||||||
- Run the smallest useful checks first.
|
|
||||||
- For API behavior changes, add/update Jest tests with negative cases.
|
|
||||||
- For user-facing UI behavior changes, add/update focused Playwright coverage.
|
|
||||||
- Summarize any command that failed, whether it appears pre-existing, and the unresolved risk.
|
|
||||||
@ -1,36 +0,0 @@
|
|||||||
# Planning Template
|
|
||||||
|
|
||||||
Use this template for multi-step features, refactors, risky bugfixes, or DB work. Keep plans short and update them as evidence changes.
|
|
||||||
|
|
||||||
## Goal
|
|
||||||
- What user-visible or operator-visible outcome should be true?
|
|
||||||
|
|
||||||
## Context
|
|
||||||
- Relevant files, routes, data tables, docs, tests, and prior decisions.
|
|
||||||
- Current behavior and desired behavior.
|
|
||||||
|
|
||||||
## Constraints
|
|
||||||
- External DB only; migrations go in `packages/db/migrations`.
|
|
||||||
- No cron, workers, or background jobs.
|
|
||||||
- RBAC must be enforced server-side.
|
|
||||||
- No secrets, receipt bytes, or full invite codes in logs.
|
|
||||||
- Preserve current behavior outside the target area.
|
|
||||||
|
|
||||||
## Milestones
|
|
||||||
1. Recon and evidence.
|
|
||||||
2. Minimal design.
|
|
||||||
3. Implementation slice.
|
|
||||||
4. Tests and verification.
|
|
||||||
5. Documentation update.
|
|
||||||
|
|
||||||
## Validation
|
|
||||||
- Commands to run.
|
|
||||||
- Manual checks needed.
|
|
||||||
- Negative cases to cover.
|
|
||||||
|
|
||||||
## Rollback
|
|
||||||
- Files or migrations that would need reverting.
|
|
||||||
- Data or operator action needed, if any.
|
|
||||||
|
|
||||||
## Open Questions
|
|
||||||
- Only questions that materially affect architecture, runtime behavior, public APIs, data storage, security, deployment, package manager, or dependency footprint.
|
|
||||||
@ -1,61 +0,0 @@
|
|||||||
# Project Map
|
|
||||||
|
|
||||||
This is the fast orientation map for Fiddy.
|
|
||||||
|
|
||||||
## Stack
|
|
||||||
- Backend: Express 5 on Node 20, CommonJS modules, PostgreSQL via `pg`.
|
|
||||||
- Frontend: React 19 + Vite, mostly JSX with partial TypeScript.
|
|
||||||
- Package manager: npm.
|
|
||||||
- Database: external on-prem Postgres. Migrations are canonical in `packages/db/migrations`.
|
|
||||||
|
|
||||||
## Root
|
|
||||||
- `PROJECT_INSTRUCTIONS.md`: source-of-truth constraints and delivery contract.
|
|
||||||
- `AGENTS.md`: concise Codex/human working guide.
|
|
||||||
- `DEBUGGING_INSTRUCTIONS.md`: required bugfix workflow.
|
|
||||||
- `package.json`: root DB, test, lint, typecheck, build, and e2e command entry points.
|
|
||||||
- `docker-compose.dev.yml`: local app containers with backend env loaded from `backend/.env`.
|
|
||||||
- `.gitea/workflows`: deploy workflows for `main` and `main-new`.
|
|
||||||
- `.github/copilot-instructions.md`: compatibility shim that points back to root instructions.
|
|
||||||
|
|
||||||
## Backend
|
|
||||||
- `backend/server.js`: starts the Express app.
|
|
||||||
- `backend/app.js`: middleware, CORS, route mounting, and error handling.
|
|
||||||
- `backend/build.js`: copies runtime backend files into `backend/dist` for the existing backend build script.
|
|
||||||
- `backend/routes`: Express routers.
|
|
||||||
- `backend/controllers`: request handlers.
|
|
||||||
- `backend/models`: database query modules.
|
|
||||||
- `backend/services`: domain service logic where present.
|
|
||||||
- `backend/middleware`: auth, optional auth, RBAC, request IDs, rate limiting, and image upload processing.
|
|
||||||
- `backend/utils`: logging, HTTP response helpers, cookies, redaction.
|
|
||||||
- `backend/tests`: Jest/Supertest tests run from the root Jest config.
|
|
||||||
- `backend/migrations`: legacy/reference SQL only; do not add new canonical migrations here.
|
|
||||||
|
|
||||||
## Frontend
|
|
||||||
- `frontend/src/main.tsx`: browser entry point.
|
|
||||||
- `frontend/src/App.jsx`: top-level routing and providers.
|
|
||||||
- `frontend/src/config.ts`: API base URL.
|
|
||||||
- `frontend/src/api`: API wrappers and shared Axios client.
|
|
||||||
- `frontend/src/context`: app state providers.
|
|
||||||
- `frontend/src/hooks`: reusable UI-facing hooks.
|
|
||||||
- `frontend/src/pages`: route-level pages.
|
|
||||||
- `frontend/src/components`: shared and domain UI components.
|
|
||||||
- `frontend/src/styles`: global, page, component, and theme CSS.
|
|
||||||
- `frontend/tests`: Playwright e2e tests.
|
|
||||||
|
|
||||||
## Database and Scripts
|
|
||||||
- `packages/db/migrations`: canonical SQL migration set.
|
|
||||||
- `packages/db/migrations/stale-files.json`: known skipped/stale migration filenames.
|
|
||||||
- `scripts/db-migrate*.js`: migration apply/status/verify/new/stale helpers.
|
|
||||||
- `docs/DB_MIGRATION_WORKFLOW.md`: operator runbook for DB changes.
|
|
||||||
|
|
||||||
## Documentation
|
|
||||||
- `docs/DEVELOPMENT.md`: setup, run, verification, and troubleshooting.
|
|
||||||
- `docs/AGENTIC_CONTRACT_MAP.md`: maps Next.js-oriented architecture language to the current Express/Vite stack.
|
|
||||||
- `docs/PLANS.md`: lightweight template for multi-step work.
|
|
||||||
- `docs/architecture`, `docs/features`, `docs/guides`, `docs/migration`: deeper reference docs.
|
|
||||||
- `docs/archive`: historical implementation notes; useful context, not necessarily current.
|
|
||||||
|
|
||||||
## Known Maintainability Hotspots
|
|
||||||
- `frontend/src/pages/GroceryList.jsx` is large and should be split only during focused UI work.
|
|
||||||
- `frontend/src/components/manage/ManageHousehold.jsx`, `backend/services/group-invites.service.js`, and `backend/models/group-invites.model.js` are also large enough to review carefully before editing.
|
|
||||||
- Some older README/guides may describe pre-session or pre-household behavior; verify against current code and root instructions before relying on them.
|
|
||||||
@ -1,41 +1,77 @@
|
|||||||
# Documentation Index
|
# Documentation Index
|
||||||
|
|
||||||
This directory contains practical project documentation. Root-level rules still take precedence:
|
This directory contains all project documentation organized by category.
|
||||||
|
|
||||||
1. `../PROJECT_INSTRUCTIONS.md`
|
## 📁 Directory Structure
|
||||||
2. `../DEBUGGING_INSTRUCTIONS.md` for bugfix work
|
|
||||||
3. `../AGENTS.md` for Codex and human workflow shortcuts
|
|
||||||
|
|
||||||
## Start Here
|
### `/architecture` - System Design & Structure
|
||||||
- `PROJECT_MAP.md`: quick repo structure and ownership map.
|
- **[component-structure.md](architecture/component-structure.md)** - Frontend component organization and patterns
|
||||||
- `DEVELOPMENT.md`: install, run, test, lint, build, and troubleshooting.
|
- **[multi-household-architecture-plan.md](architecture/multi-household-architecture-plan.md)** - Multi-household system architecture design
|
||||||
- `DB_MIGRATION_WORKFLOW.md`: external Postgres migration runbook.
|
|
||||||
- `AGENTIC_CONTRACT_MAP.md`: maps source-of-truth architecture language to the current Express/Vite stack.
|
|
||||||
- `PLANS.md`: lightweight template for multi-step work.
|
|
||||||
|
|
||||||
## Architecture
|
### `/features` - Feature Implementation Details
|
||||||
- `architecture/component-structure.md`: frontend component organization and patterns.
|
- **[classification-implementation.md](features/classification-implementation.md)** - Item classification system (zones, types, groups)
|
||||||
- `architecture/multi-household-architecture-plan.md`: multi-household system planning notes.
|
- **[image-storage-implementation.md](features/image-storage-implementation.md)** - Image storage and handling (bytea, MIME types)
|
||||||
|
|
||||||
## Features
|
### `/guides` - How-To & Reference Guides
|
||||||
- `features/classification-implementation.md`: item classification notes.
|
- **[api-documentation.md](guides/api-documentation.md)** - REST API endpoints and usage
|
||||||
- `features/image-storage-implementation.md`: image storage and handling notes.
|
- **[frontend-readme.md](guides/frontend-readme.md)** - Frontend development guide
|
||||||
|
- **[MOBILE_RESPONSIVE_AUDIT.md](guides/MOBILE_RESPONSIVE_AUDIT.md)** - Mobile-first design guidelines and audit checklist
|
||||||
|
- **[setup-checklist.md](guides/setup-checklist.md)** - Development environment setup steps
|
||||||
|
|
||||||
## Guides
|
### `/migration` - Database Migrations & Updates
|
||||||
- `guides/api-documentation.md`: REST API reference. Verify against current code before changing APIs.
|
- **[MIGRATION_GUIDE.md](migration/MIGRATION_GUIDE.md)** - Multi-household migration instructions (also in `backend/migrations/`)
|
||||||
- `guides/frontend-readme.md`: frontend development notes.
|
- **[POST_MIGRATION_UPDATES.md](migration/POST_MIGRATION_UPDATES.md)** - Required updates after migration
|
||||||
- `guides/MOBILE_RESPONSIVE_AUDIT.md`: mobile design and audit checklist.
|
|
||||||
- `guides/setup-checklist.md`: older setup checklist; prefer `DEVELOPMENT.md` for current commands.
|
|
||||||
|
|
||||||
## Migration
|
### `/archive` - Completed Implementation Records
|
||||||
- `migration/MIGRATION_GUIDE.md`: historical multi-household migration instructions.
|
Historical documentation of completed features. Useful for reference but not actively maintained.
|
||||||
- `migration/POST_MIGRATION_UPDATES.md`: historical post-migration notes.
|
|
||||||
|
|
||||||
## Archive
|
- **[ACCOUNT_MANAGEMENT_IMPLEMENTATION.md](archive/ACCOUNT_MANAGEMENT_IMPLEMENTATION.md)** - Phase 4: Display name and password change
|
||||||
Files in `archive/` are historical implementation records. They are useful for context, but they are not guaranteed to describe current behavior.
|
- **[code-cleanup-guide.md](archive/code-cleanup-guide.md)** - Code cleanup checklist (completed)
|
||||||
|
- **[HOUSEHOLD_MANAGEMENT_IMPLEMENTATION.md](archive/HOUSEHOLD_MANAGEMENT_IMPLEMENTATION.md)** - Household management UI implementation
|
||||||
|
- **[IMPLEMENTATION_STATUS.md](archive/IMPLEMENTATION_STATUS.md)** - Multi-household migration sprint status
|
||||||
|
- **[settings-dark-mode.md](archive/settings-dark-mode.md)** - Dark mode implementation notes
|
||||||
|
- **[TEST_SUITE_README.md](archive/TEST_SUITE_README.md)** - Testing infrastructure documentation
|
||||||
|
|
||||||
## Documentation Rules
|
---
|
||||||
- Keep docs concise and linked to real files or commands.
|
|
||||||
- Prefer updating `PROJECT_MAP.md` and `DEVELOPMENT.md` before adding new top-level docs.
|
## 📄 Root-Level Documentation
|
||||||
- Move completed implementation narratives to `archive/` when they are no longer active runbooks.
|
|
||||||
- Keep text encoding clean.
|
These files remain at the project root for easy access:
|
||||||
|
|
||||||
|
- **[../README.md](../README.md)** - Project overview and quick start
|
||||||
|
- **[../PROJECT_INSTRUCTIONS.md](../PROJECT_INSTRUCTIONS.md)** - Canonical project constraints and delivery contract
|
||||||
|
- **[../AGENTS.md](../AGENTS.md)** - Agent behavior and guardrails
|
||||||
|
- **[../DEBUGGING_INSTRUCTIONS.md](../DEBUGGING_INSTRUCTIONS.md)** - Required bugfix workflow
|
||||||
|
- **[../.github/copilot-instructions.md](../.github/copilot-instructions.md)** - Copilot compatibility shim to root instructions
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔍 Quick Reference
|
||||||
|
|
||||||
|
**Setting up the project?** → Start with [setup-checklist.md](guides/setup-checklist.md)
|
||||||
|
|
||||||
|
**Understanding the API?** → See [api-documentation.md](guides/api-documentation.md)
|
||||||
|
|
||||||
|
**Working on mobile UI?** → Check [MOBILE_RESPONSIVE_AUDIT.md](guides/MOBILE_RESPONSIVE_AUDIT.md)
|
||||||
|
|
||||||
|
**Need architecture context?** → Read [AGENTIC_CONTRACT_MAP.md](AGENTIC_CONTRACT_MAP.md) and [../PROJECT_INSTRUCTIONS.md](../PROJECT_INSTRUCTIONS.md)
|
||||||
|
|
||||||
|
**Running migrations?** → Follow [DB_MIGRATION_WORKFLOW.md](DB_MIGRATION_WORKFLOW.md)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📝 Contributing to Documentation
|
||||||
|
|
||||||
|
When adding new documentation:
|
||||||
|
|
||||||
|
1. **Guides** (`/guides`) - General how-to, setup, reference
|
||||||
|
2. **Features** (`/features`) - Specific feature implementation details
|
||||||
|
3. **Architecture** (`/architecture`) - System design, patterns, structure
|
||||||
|
4. **Migration** (`/migration`) - Database migrations and upgrade guides
|
||||||
|
5. **Archive** (`/archive`) - Completed implementation records (for reference only)
|
||||||
|
|
||||||
|
Keep documentation:
|
||||||
|
- ✅ Up-to-date with code changes
|
||||||
|
- ✅ Concise and scannable
|
||||||
|
- ✅ Linked to relevant files (use relative paths)
|
||||||
|
- ✅ Organized by category
|
||||||
|
|||||||
@ -1,2 +0,0 @@
|
|||||||
VITE_API_URL=http://localhost:5000
|
|
||||||
VITE_ALLOWED_HOSTS=localhost,127.0.0.1
|
|
||||||
597
frontend/package-lock.json
generated
597
frontend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -5,7 +5,6 @@
|
|||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"typecheck": "tsc -b",
|
|
||||||
"build": "tsc -b && vite build",
|
"build": "tsc -b && vite build",
|
||||||
"lint": "eslint .",
|
"lint": "eslint .",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
@ -20,8 +19,8 @@
|
|||||||
"react-router-dom": "^7.9.6"
|
"react-router-dom": "^7.9.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@playwright/test": "^1.52.0",
|
||||||
"@eslint/js": "^9.39.1",
|
"@eslint/js": "^9.39.1",
|
||||||
"@playwright/test": "^1.58.2",
|
|
||||||
"@types/node": "^24.10.0",
|
"@types/node": "^24.10.0",
|
||||||
"@types/react": "^19.2.5",
|
"@types/react": "^19.2.5",
|
||||||
"@types/react-dom": "^19.2.2",
|
"@types/react-dom": "^19.2.2",
|
||||||
|
|||||||
@ -170,7 +170,7 @@ export default function ConfirmSlideModal({
|
|||||||
onPointerCancel={handlePointerCancel}
|
onPointerCancel={handlePointerCancel}
|
||||||
aria-label="Slide to confirm"
|
aria-label="Slide to confirm"
|
||||||
>
|
>
|
||||||
>
|
>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -150,8 +150,8 @@ test("manage stores opens a modal to edit and delete household store items", asy
|
|||||||
|
|
||||||
const managerModal = page.locator(".store-items-modal");
|
const managerModal = page.locator(".store-items-modal");
|
||||||
await expect(managerModal).toBeVisible();
|
await expect(managerModal).toBeVisible();
|
||||||
await expect(managerModal.getByText("milk", { exact: true })).toBeVisible();
|
await expect(managerModal.getByText("milk")).toBeVisible();
|
||||||
await expect(managerModal.getByText("apples", { exact: true })).toBeVisible();
|
await expect(managerModal.getByText("apples")).toBeVisible();
|
||||||
|
|
||||||
await managerModal.locator(".store-items-table-row").filter({ hasText: "apples" }).getByRole("button", { name: "Edit Settings" }).click();
|
await managerModal.locator(".store-items-table-row").filter({ hasText: "apples" }).getByRole("button", { name: "Edit Settings" }).click();
|
||||||
const editorModal = page.locator(".available-item-editor-modal");
|
const editorModal = page.locator(".available-item-editor-modal");
|
||||||
|
|||||||
@ -271,9 +271,7 @@ test("add-details modal validates with toasts and persists classification detail
|
|||||||
|
|
||||||
const yogurtRow = page.locator(".glist-li").filter({ hasText: "yogurt" });
|
const yogurtRow = page.locator(".glist-li").filter({ hasText: "yogurt" });
|
||||||
await expect(yogurtRow).toBeVisible();
|
await expect(yogurtRow).toBeVisible();
|
||||||
await expect(
|
await expect(page.locator(".action-toast.action-toast-success")).toContainText("Added item");
|
||||||
page.locator(".action-toast.action-toast-success").filter({ hasText: "Added item" })
|
|
||||||
).toContainText("Added item");
|
|
||||||
|
|
||||||
await openEditModal(yogurtRow, page);
|
await openEditModal(yogurtRow, page);
|
||||||
|
|
||||||
@ -304,9 +302,7 @@ test("edit modal supports zone-only updates and shows API error toasts", async (
|
|||||||
await editModal.locator(".edit-modal-select").nth(1).selectOption("Checkout Area");
|
await editModal.locator(".edit-modal-select").nth(1).selectOption("Checkout Area");
|
||||||
await editModal.getByRole("button", { name: "Save Changes" }).click();
|
await editModal.getByRole("button", { name: "Save Changes" }).click();
|
||||||
|
|
||||||
await expect(
|
await expect(page.locator(".action-toast.action-toast-success")).toContainText("Updated item");
|
||||||
page.locator(".action-toast.action-toast-success").filter({ hasText: "Updated item" })
|
|
||||||
).toContainText("Updated item");
|
|
||||||
await expect(editModal).toBeHidden();
|
await expect(editModal).toBeHidden();
|
||||||
|
|
||||||
await openEditModal(yogurtRow, page);
|
await openEditModal(yogurtRow, page);
|
||||||
|
|||||||
@ -39,14 +39,14 @@ test("new users with no households see create and join actions instead of a load
|
|||||||
|
|
||||||
await expect(page.getByRole("button", { name: "Create or Join Household" })).toBeVisible();
|
await expect(page.getByRole("button", { name: "Create or Join Household" })).toBeVisible();
|
||||||
await expect(page.getByRole("heading", { name: "No household yet" })).toBeVisible();
|
await expect(page.getByRole("heading", { name: "No household yet" })).toBeVisible();
|
||||||
await expect(page.getByRole("button", { name: "Create Household", exact: true })).toBeVisible();
|
await expect(page.getByRole("button", { name: "Create Household" })).toBeVisible();
|
||||||
await expect(page.getByRole("button", { name: "Join Household", exact: true })).toBeVisible();
|
await expect(page.getByRole("button", { name: "Join Household" })).toBeVisible();
|
||||||
|
|
||||||
await page.getByRole("button", { name: "Join Household", exact: true }).click();
|
await page.getByRole("button", { name: "Join Household" }).click();
|
||||||
await expect(page.getByLabel("Invite Code or Link")).toBeVisible();
|
await expect(page.getByLabel("Invite Code or Link")).toBeVisible();
|
||||||
await page.getByRole("button", { name: "Close household dialog" }).click();
|
await page.getByRole("button", { name: "Close household dialog" }).click();
|
||||||
|
|
||||||
await page.getByRole("button", { name: "Create Household", exact: true }).click();
|
await page.getByRole("button", { name: "Create Household" }).click();
|
||||||
await expect(page.getByLabel("Household Name")).toBeVisible();
|
await expect(page.getByLabel("Household Name")).toBeVisible();
|
||||||
await page.getByRole("button", { name: "Close household dialog" }).click();
|
await page.getByRole("button", { name: "Close household dialog" }).click();
|
||||||
|
|
||||||
@ -54,6 +54,6 @@ test("new users with no households see create and join actions instead of a load
|
|||||||
|
|
||||||
await expect(page.getByRole("heading", { name: "Manage" })).toBeVisible();
|
await expect(page.getByRole("heading", { name: "Manage" })).toBeVisible();
|
||||||
await expect(page.getByRole("heading", { name: "No household yet" })).toBeVisible();
|
await expect(page.getByRole("heading", { name: "No household yet" })).toBeVisible();
|
||||||
await expect(page.getByRole("button", { name: "Create Household", exact: true })).toBeVisible();
|
await expect(page.getByRole("button", { name: "Create Household" })).toBeVisible();
|
||||||
await expect(page.getByRole("button", { name: "Join Household", exact: true })).toBeVisible();
|
await expect(page.getByRole("button", { name: "Join Household" })).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|||||||
@ -71,7 +71,7 @@ test("join household modal accepts invite links but rejects legacy invite codes"
|
|||||||
});
|
});
|
||||||
|
|
||||||
await page.goto("/manage");
|
await page.goto("/manage");
|
||||||
await page.getByRole("button", { name: "Join Household", exact: true }).click();
|
await page.getByRole("button", { name: "Join Household" }).click();
|
||||||
await page.getByLabel("Invite Link").fill("HABC123");
|
await page.getByLabel("Invite Link").fill("HABC123");
|
||||||
await page.getByRole("button", { name: "Open Invite" }).click();
|
await page.getByRole("button", { name: "Open Invite" }).click();
|
||||||
|
|
||||||
|
|||||||
@ -38,7 +38,7 @@ test("login failure shows inline error and error toast", async ({ page }) => {
|
|||||||
await page.getByPlaceholder("Password").fill("bad-password");
|
await page.getByPlaceholder("Password").fill("bad-password");
|
||||||
await page.getByRole("button", { name: "Login" }).click();
|
await page.getByRole("button", { name: "Login" }).click();
|
||||||
|
|
||||||
await expect(page.getByText("Invalid credentials", { exact: true })).toBeVisible();
|
await expect(page.getByText("Invalid credentials")).toBeVisible();
|
||||||
await expect(page.locator(".action-toast.action-toast-error")).toContainText("Login failed");
|
await expect(page.locator(".action-toast.action-toast-error")).toContainText("Login failed");
|
||||||
await expect(page.locator(".action-toast.action-toast-error")).toContainText("Invalid credentials");
|
await expect(page.locator(".action-toast.action-toast-error")).toContainText("Invalid credentials");
|
||||||
});
|
});
|
||||||
|
|||||||
48
package-lock.json
generated
48
package-lock.json
generated
@ -1,10 +1,10 @@
|
|||||||
{
|
{
|
||||||
"name": "grocery-app",
|
"name": "Costco-Grocery-List",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "grocery-app",
|
"name": "Costco-Grocery-List",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"cross-env": "^10.1.0",
|
"cross-env": "^10.1.0",
|
||||||
"jest": "^30.2.0",
|
"jest": "^30.2.0",
|
||||||
@ -1544,9 +1544,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/brace-expansion": {
|
"node_modules/brace-expansion": {
|
||||||
"version": "2.1.1",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
|
||||||
"integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==",
|
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"balanced-match": "^1.0.0"
|
"balanced-match": "^1.0.0"
|
||||||
@ -3130,9 +3130,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/jest-util/node_modules/picomatch": {
|
"node_modules/jest-util/node_modules/picomatch": {
|
||||||
"version": "4.0.4",
|
"version": "4.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
|
||||||
"integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
|
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
@ -3421,12 +3421,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/minimatch": {
|
"node_modules/minimatch": {
|
||||||
"version": "9.0.9",
|
"version": "9.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
|
||||||
"integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==",
|
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"brace-expansion": "^2.0.2"
|
"brace-expansion": "^2.0.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16 || 14 >=14.17"
|
"node": ">=16 || 14 >=14.17"
|
||||||
@ -3671,9 +3671,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/picomatch": {
|
"node_modules/picomatch": {
|
||||||
"version": "2.3.2",
|
"version": "2.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
||||||
"integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
|
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8.6"
|
"node": ">=8.6"
|
||||||
@ -3746,9 +3746,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/qs": {
|
"node_modules/qs": {
|
||||||
"version": "6.15.2",
|
"version": "6.14.1",
|
||||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz",
|
"resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz",
|
||||||
"integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==",
|
"integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"side-channel": "^1.1.0"
|
"side-channel": "^1.1.0"
|
||||||
@ -4191,9 +4191,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/test-exclude/node_modules/brace-expansion": {
|
"node_modules/test-exclude/node_modules/brace-expansion": {
|
||||||
"version": "1.1.14",
|
"version": "1.1.12",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||||
"integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==",
|
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"balanced-match": "^1.0.0",
|
"balanced-match": "^1.0.0",
|
||||||
@ -4222,9 +4222,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/test-exclude/node_modules/minimatch": {
|
"node_modules/test-exclude/node_modules/minimatch": {
|
||||||
"version": "3.1.5",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||||
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
|
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^1.1.7"
|
||||||
|
|||||||
13
package.json
13
package.json
@ -1,18 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "grocery-app",
|
|
||||||
"private": true,
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev:backend": "npm --prefix backend run dev",
|
|
||||||
"dev:frontend": "npm --prefix frontend run dev",
|
|
||||||
"build": "npm run build:backend && npm run build:frontend",
|
|
||||||
"build:backend": "npm --prefix backend run build",
|
|
||||||
"build:frontend": "npm --prefix frontend run build",
|
|
||||||
"lint": "npm --prefix frontend run lint",
|
|
||||||
"typecheck": "npm --prefix frontend run typecheck",
|
|
||||||
"audit": "npm run audit:root && npm run audit:backend && npm run audit:frontend",
|
|
||||||
"audit:root": "npm audit",
|
|
||||||
"audit:backend": "npm --prefix backend audit",
|
|
||||||
"audit:frontend": "npm --prefix frontend audit",
|
|
||||||
"db:migrate": "node scripts/db-migrate.js",
|
"db:migrate": "node scripts/db-migrate.js",
|
||||||
"db:migrate:status": "node scripts/db-migrate-status.js",
|
"db:migrate:status": "node scripts/db-migrate-status.js",
|
||||||
"db:migrate:verify": "node scripts/db-migrate-verify.js",
|
"db:migrate:verify": "node scripts/db-migrate-verify.js",
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user