From ec2bb7eec9d8e130ce6f0938d3589ab304b7380e Mon Sep 17 00:00:00 2001 From: Bas van Rossem Date: Wed, 17 Jun 2026 17:05:56 +0200 Subject: [PATCH] feat(api): seed a dev login account (worker@solelog.local) for testing db:seed now also creates a ready-made dev account via better-auth (properly hashed), idempotent, and SKIPPED when NODE_ENV=production so no known-password account ships to prod. Credentials: worker@solelog.local / werkplaats123. Documented in the worker README. API tests 37/37 green; verified live (sign-in returns a bearer token; /api/me returns the user). --- apps/api/src/db/seed.ts | 20 +++++++++++++++++++- apps/api/test/seed.test.ts | 12 +++++++++++- apps/worker/README.md | 6 ++++-- 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/apps/api/src/db/seed.ts b/apps/api/src/db/seed.ts index fbfd814..a20239d 100644 --- a/apps/api/src/db/seed.ts +++ b/apps/api/src/db/seed.ts @@ -1,7 +1,13 @@ import { pathToFileURL } from 'node:url'; import { eq } from 'drizzle-orm'; import { db } from './client'; -import { activities } from './schema'; +import { activities, user } from './schema'; +import { auth } from '../auth'; + +// Dev-only test account so `db:seed` yields ready-made login credentials for local +// testing / phone demos. Created through better-auth (password is properly hashed). +// NEVER seeded when NODE_ENV=production — see seedDevUser(). +const DEV_USER = { email: 'worker@solelog.local', password: 'werkplaats123', name: 'Test Werker' }; // Reference activities (realistic Dutch handeling names) — see // docs/reference/legacy-mobile-app.md §6.2 and the Phase 1 plan. @@ -14,6 +20,17 @@ const REFERENCE_ACTIVITIES: { name: string; insoleTypes: string[] }[] = [ { name: 'Printen', insoleTypes: ['3D'] }, ]; +// Idempotent: create the dev account once, and only outside production (it has a +// known password). Uses better-auth's server API so the user + hashed-password +// account rows are created exactly as a real sign-up would. +async function seedDevUser(): Promise { + if (process.env.NODE_ENV === 'production') return; + const existing = await db.select().from(user).where(eq(user.email, DEV_USER.email)); + if (existing.length > 0) return; + await auth.api.signUpEmail({ body: DEV_USER }); + console.log(`Seeded dev account: ${DEV_USER.email} / ${DEV_USER.password}`); +} + // Idempotent: insert each reference activity only if no activity with that name exists. export async function seed(): Promise { for (const activity of REFERENCE_ACTIVITIES) { @@ -28,6 +45,7 @@ export async function seed(): Promise { }); } } + await seedDevUser(); } // Allow running directly: `tsx src/db/seed.ts` (cross-platform — pathToFileURL diff --git a/apps/api/test/seed.test.ts b/apps/api/test/seed.test.ts index 637b017..e29b457 100644 --- a/apps/api/test/seed.test.ts +++ b/apps/api/test/seed.test.ts @@ -2,7 +2,7 @@ import { describe, it, expect } from 'vitest'; import { inArray, eq } from 'drizzle-orm'; import { seed } from '../src/db/seed'; import { db } from '../src/db/client'; -import { activities } from '../src/db/schema'; +import { activities, user } from '../src/db/schema'; const SEED_NAMES = ['Leerrand', 'Frezen', 'Slijpen', 'Bekleden', 'Afwerken', 'Printen']; @@ -31,4 +31,14 @@ describe('seed', () => { expect(printen).toHaveLength(1); expect(printen[0]?.insoleTypes).toEqual(['3D']); }); + + it('seeds the dev test account idempotently (and only once)', async () => { + await seed(); + const first = await db.select().from(user).where(eq(user.email, 'worker@solelog.local')); + expect(first).toHaveLength(1); + + await seed(); + const second = await db.select().from(user).where(eq(user.email, 'worker@solelog.local')); + expect(second).toHaveLength(1); + }); }); diff --git a/apps/worker/README.md b/apps/worker/README.md index 530a3d3..c55a5ca 100644 --- a/apps/worker/README.md +++ b/apps/worker/README.md @@ -39,8 +39,10 @@ From the repo root: yarn workspace @solelog/worker dev # Vite dev server on http://localhost:5173 ``` -Open **http://localhost:5173** in any browser. There is a sign-up affordance on the login screen for -creating a test account; after signing in you land on the Stopwatch tab. +Open **http://localhost:5173** in any browser. `db:seed` creates a ready-made **dev login**: +**`worker@solelog.local`** / **`werkplaats123`** (dev-only — skipped when `NODE_ENV=production`). +Or use the sign-up affordance on the login screen to create your own account. After signing in you +land on the Stopwatch tab. The API base URL comes from `VITE_API_URL` (default `http://localhost:3000`).