batchCooking/specs/batch-cooking-architecture.md
Nicolas e9d94ff5f9 Centralize error handling (shared codes + API/client services), code quality pass
## Error handling

Requested: a centralized error-handling service on the API, custom error
codes shared across apps, and a client-side error service for i18n labels.

- packages/shared/src/errors/error-codes.ts — ErrorCode enum + ApiErrorResponse
  contract. Single source of truth: neither side hardcodes a raw error string
  the other has to guess at.
- apps/api: HttpError now carries an ErrorCode (not just a message).
  ErrorHandlerService (new) centralizes every "how do we turn a thrown error
  into an HTTP response" decision — app.ts's error middleware is now a thin
  adapter calling into it. API messages reverted to English/dev-facing (they
  were French from an earlier pass) since user-facing text is now generated
  client-side from the code.
- apps/web: ApiClient (class, singleton instance) throws ApiError carrying
  the code. ErrorMessageService (new) maps every ErrorCode to a localized
  label, structured with a Locale type from the start (only "fr" exists, but
  adding a language later is "add a locale to the map", not "hunt down every
  hardcoded string"). LoginPage/SignupPage now display
  errorMessageService.getLabel(err.code), never err.message directly.
- Tests strengthened to assert on `code`, not just HTTP status (Mocha +
  Cucumber, new "the response error code should be" step). Cypress mocks
  updated to the new {code, message} response shape.

## Code quality pass

Per explicit feedback: heavy JSDoc on every interface/type/class/function/
method/member touched in this PR, explicit public/private visibility on
every class member (ApiClient, ErrorMessageService, ErrorHandlerService,
HttpError), no HTML/logic mixing (styling extracted out of components
entirely, never inline).

ApiClient/ErrorMessageService were initially written as static-only classes;
switched to instance-based singletons (matching ErrorHandlerService's
existing pattern) after Biome's noStaticOnlyClass rule flagged the
static-only shape as an anti-pattern — same "class with visibility
modifiers" outcome, without fighting the linter.

## SCSS + theming

- apps/web/src/styles/_theme.scss — design tokens as CSS custom properties
  on :root (colors, spacing, typography), not plain Sass variables — makes
  them available at runtime, not just compile time, so a future theme
  switch (e.g. dark mode) is "redefine these variables" rather than
  rebuilding stylesheets.
- apps/web/src/styles/global.scss replaces the old single index.css:
  reset + theme import only, loaded once from main.tsx.
- Per-page/component styles colocated (HomePage.tsx + HomePage.scss);
  styles shared by multiple pages within one feature live in that feature's
  folder (features/auth/auth-form.scss, used by both Login/SignupPage) —
  not duplicated per page, not dumped in the global stylesheet either.
- Component-level .scss files intentionally don't `@use` the theme
  partial: they only consume CSS custom properties (global at runtime via
  global.scss), not Sass-level symbols, so importing it would do nothing —
  documented inline rather than left as a silently-redundant import.
- vite.config.ts opts into Sass's modern compiler API to silence a
  legacy-js-api deprecation warning on every build.

## specs/ updates

- New specs/error-handling.md — the ErrorCode/ApiErrorResponse contract,
  both services, with a flow diagram.
- New specs/frontend-architecture.md — apps/web folder structure, routing/
  auth-guard flow, SCSS/theming conventions.
- specs/batch-cooking-architecture.md links to both (original doc content
  otherwise untouched — it's the user's own hand-authored source doc).

## Verification

Full lint/mocha/cucumber/build green. Manually re-verified the whole auth
flow in a real browser against native dev servers (not just the automated
suites): signup, the EMAIL_ALREADY_IN_USE → "Cet email est déjà utilisé"
translation end-to-end (confirmed the raw API response carries the English
dev message + code, and the UI shows the French label), wrong-password
INVALID_CREDENTIALS → its label, and confirmed the theme tokens actually
apply (computed button background-color matches --color-primary, card
max-width matches the token value) rather than trusting the build succeeding.
2026-08-16 15:44:09 +02:00

2.3 KiB

Architecture technique — Projet Batch-cooking

Documentation de l'architecture serveur/client de l'application.


Vue d'ensemble

L'application repose sur une architecture client-serveur classique :

  • Un serveur exposant une API (échanges standards) et un canal websocket (communication temps réel)
  • Plusieurs clients (Client 1, Client 2, Client 3...) connectés simultanément au serveur
  • Une base de données PostgreSQL
flowchart TB
  subgraph SERVER["Server"]
    WS["Web socket"]
    API["API"]
    CALC["Calcul batch-cooking<br/><i>(TODO)</i>"]
    IMPORT["Import d'une recette"]
    IMP1["Import depuis source"]
    IMP2["Traduction en étapes"]
    IMP3["Sauvegarde"]
    DB[("Database<br/>PostgreSQL")]

    IMPORT --> IMP1 --> IMP2 --> IMP3 --> DB
    CALC --> WS
  end

  C1["Client 1"]
  C2["Client 2"]
  C3["Client 3"]

  API <--> C1
  API <--> C2
  API <--> C3
  WS --> C1
  WS --> C2
  WS --> C3

  style SERVER fill:none,stroke:#888,stroke-width:1px

Composants

API

Point d'entrée principal pour les échanges entre les clients et le serveur (requêtes classiques).

Web socket

Canal de communication temps réel entre le serveur et les clients connectés.

Module « Calcul batch-cooking »

Logique de calcul du batch-cooking (optimisation du planning/des recettes selon le planning). Statut : TODO — reste à développer.

Module « Import d'une recette »

Pipeline d'ajout d'une recette, en trois étapes :

  1. Import depuis source — récupération de la recette (via sources)
  2. Traduction en étapes — découpage en step / tech_step
  3. Sauvegarde — persistance en base de données

Database (PostgreSQL)

Stockage de l'ensemble des données de l'application (voir le modèle de données pour le détail des tables).


Notes

  • Le module de calcul batch-cooking est le principal chantier restant côté serveur (TODO).
  • Le websocket est utilisé pour la communication temps réel, en complément de l'API.

Documents liés

Documentation d'implémentation (ajoutée au fil des features, complète ce document conceptuel sans le remplacer) :