No description
Find a file
Nicolas fb9ef5b6c1 Fix CI: generate Prisma Client via postinstall
CI failed with "@prisma/client did not initialize yet" — pnpm install
never ran `prisma generate`, and `prisma migrate deploy` (unlike
`migrate dev`) doesn't do it either. Worked locally only because prior
`prisma migrate dev` runs had already generated the client as a side
effect.

Adding a postinstall script fixes it for CI and for anyone cloning the
repo fresh and running plain `pnpm install`.
2026-08-16 13:14:02 +02:00
.github/workflows Add signup/login (profile creation + JWT auth) 2026-08-16 13:06:31 +02:00
apps Fix CI: generate Prisma Client via postinstall 2026-08-16 13:14:02 +02:00
packages/shared Scaffold generic pnpm monorepo (api + web + shared) (#1) 2026-08-16 10:55:13 +02:00
specs Add specs + Prisma schema for the documented data model (#3) 2026-08-16 12:23:59 +02:00
.env.example Scaffold generic pnpm monorepo (api + web + shared) (#1) 2026-08-16 10:55:13 +02:00
.gitignore Add specs + Prisma schema for the documented data model (#3) 2026-08-16 12:23:59 +02:00
.nvmrc Scaffold generic pnpm monorepo (api + web + shared) (#1) 2026-08-16 10:55:13 +02:00
biome.json Scaffold generic pnpm monorepo (api + web + shared) (#1) 2026-08-16 10:55:13 +02:00
docker-compose.yml Scaffold generic pnpm monorepo (api + web + shared) (#1) 2026-08-16 10:55:13 +02:00
package.json Add signup/login (profile creation + JWT auth) 2026-08-16 13:06:31 +02:00
pnpm-lock.yaml Add signup/login (profile creation + JWT auth) 2026-08-16 13:06:31 +02:00
pnpm-workspace.yaml Scaffold generic pnpm monorepo (api + web + shared) (#1) 2026-08-16 10:55:13 +02:00
README.md Add signup/login (profile creation + JWT auth) 2026-08-16 13:06:31 +02:00
tsconfig.base.json Scaffold generic pnpm monorepo (api + web + shared) (#1) 2026-08-16 10:55:13 +02:00

batchCooking

Structure

Monorepo pnpm workspaces :

  • apps/api — backend Express/TypeScript (squelette générique : healthcheck, config env, Prisma non modélisé, tests Mocha + Cucumber/BDD)
  • apps/web — frontend React/Vite/TypeScript (squelette générique, prêt à être embarqué par Capacitor plus tard)
  • packages/shared — code partagé entre api et web (types, schémas de validation, constantes) — vide pour l'instant

Aucun module métier n'est encore implémenté : cette base ne contient que l'outillage générique (lint/format, tests, CI, DB locale).

Prérequis

  • Node.js 22 (voir .nvmrc)
  • pnpm 10 (corepack enable puis corepack use pnpm@10.12.4, ou installation manuelle)
  • Docker (pour Postgres en local)

Installation

pnpm install
cp .env.example .env
cp apps/api/.env.example apps/api/.env

Puis édite ces deux .env pour renseigner de vrais POSTGRES_USER/POSTGRES_PASSWORD (et la DATABASE_URL correspondante dans apps/api/.env) : les fichiers .env.example ne contiennent volontairement aucun identifiant réel (juste changeme), et docker-compose.yml refuse de démarrer tant que POSTGRES_USER/PASSWORD/DB ne sont pas définis dans .env — pas de valeur par défaut en dur dans les fichiers commités. Même règle pour apps/api/.env : JWT_SECRET est requis, sans défaut (génère le tien, voir le commentaire dans apps/api/.env.example).

Cypress : téléchargement du binaire

pnpm install installe le package cypress mais pas forcément son binaire (le téléchargement du .exe/binaire natif peut être ignoré selon l'environnement où pnpm install a été lancé — ex. un environnement sandboxé/CI dont le cache ne correspond pas à celui de ta machine). Si pnpm --filter web e2e échoue avec une erreur du type :

No version of Cypress is installed in: ...\AppData\Local\Cypress\Cache\...
Please reinstall Cypress by running: cypress install

lance simplement, depuis ta machine :

pnpm --filter web exec cypress install

(à faire une seule fois par machine ; le binaire est mis en cache localement, hors du repo).

Développement

# Base de données Postgres locale
docker compose up -d

# Applique le schéma (première fois / après un changement de prisma/schema.prisma)
pnpm --filter api exec prisma migrate dev

# Backend (http://localhost:3000)
pnpm dev:api

# Frontend (http://localhost:5173)
pnpm dev:web

Conflit de port possible sur 5432 : si tu as déjà un Postgres natif installé sur ta machine (service Windows, Homebrew, etc.), il peut occuper le port 5432 et intercepter les connexions à la place du conteneur Docker (symptôme : Prisma renvoie P1000: Authentication failed alors que les identifiants sont corrects). Dans ce cas, mets POSTGRES_PORT=5433 (ou autre) dans ton .env et adapte le port dans la DATABASE_URL de apps/api/.env.

Qualité / Tests

pnpm lint                  # Biome (lint + format check)
pnpm lint:fix               # Biome --write
pnpm test                   # tests unitaires/intégration (Mocha, apps/api)
pnpm --filter api test:bdd   # tests d'intégration BDD (Cucumber/Gherkin, apps/api)
pnpm --filter web e2e         # tests e2e (Cypress, démarre le serveur dev automatiquement)
pnpm build                     # build de tous les workspaces

La CI GitHub Actions (.github/workflows/ci.yml) exécute lint + tests + build sur chaque push/PR vers main, puis les tests e2e Cypress.

Cucumber (apps/api)

Tests d'intégration lisibles en Gherkin, en complément de Mocha (qui reste pour les tests unitaires purs) :

  • apps/api/features/*.feature — scénarios en Given/When/Then (health.feature sert d'exemple)
  • apps/api/features/step-definitions/*.steps.ts — implémentation des steps
  • apps/api/features/support/world.ts — contexte partagé entre les steps d'un scénario (instancie l'app Express in-process via createApp(), comme le fait déjà supertest côté Mocha — pas besoin de lancer un vrai serveur)
  • apps/api/cucumber.cjs — config (extension .cjs volontaire, voir la remarque TypeScript/ESM ci-dessous)

Pour ajouter un scénario : écrire le .feature, lancer pnpm --filter api test:bdd, implémenter les steps manquants (Cucumber affiche des snippets tout prêts pour ceux qui n'existent pas encore).

Piège TypeScript/ESM à connaître (déjà rencontré avec cypress.config.ts) : les fichiers de config d'outils tiers qui font du chargement dynamique de TS (cucumber.cjs, cypress.config.ts…) sont sensibles au "type": "module" du package.json. cucumber.cjs évite le problème pour sa propre config en étant explicitement CommonJS ; les steps/world restent en .ts ESM classique et sont chargés via tsx (NODE_OPTIONS=--import=tsx, voir le script test:bdd).

Auth (apps/api)

Inscription (création de profil + foyer) et connexion, JWT dans un cookie httpOnly.

  • POST /auth/signup{ firstName, lastName, email, password } → crée le foyer (house) et le profil (user_profiles) en une transaction, pose le cookie de session, renvoie le profil (201)
  • POST /auth/login{ email, password } → pose le cookie de session, renvoie le profil (200) ; message d'erreur volontairement générique (401) que ce soit l'email ou le mot de passe qui soit incorrect
  • POST /auth/logout — efface le cookie (204)
  • GET /auth/me — profil courant, nécessite le cookie de session (401 sinon)

Mots de passe hachés avec argon2. Le hash est indépendant du foyer : un profil crée toujours son propre foyer à l'inscription (rejoindre un foyer existant n'est pas encore implémenté).

argon2 : version pinnée à 0.31.2, pas de ^. La version 0.45.1 (dernière au moment de l'écriture) segfault au runtime sur au moins une configuration Windows — reproduit de façon stable (bash sandboxé, bash non-sandboxé, PowerShell), alors que 0.31.2 fonctionne parfaitement avec la même API. Si tu montes la version, revérifie concrètement (argon2.hash(...) dans un node -e) avant de merger, un pnpm build qui passe ne suffit pas à détecter un crash runtime.

Les tests (Mocha + Cucumber) tournent avec un coût argon2 réduit (NODE_ENV=test, voir auth.service.ts) — le coût par défaut est volontairement élevé (sécurité), ce qui rendrait la suite de tests lente/instable sinon. La CI provisionne un vrai Postgres de service (.github/workflows/ci.yml) et exécute prisma migrate deploy avant les tests.