Aller au contenu

Vue filtrée pour Administrateur Planificateur Gestionnaire de patrimoine Enseignant Étudiant Tout afficher

J3 — La carte du monorepo

Vérifié contre le produit le .

L’objectif du jour : savoir, devant n’importe quelle demande, dans quel dossier ouvrir le premier fichier.

Durée réaliste 2 heures de lecture, et une page à rouvrir pendant des mois
Prérequis J1

Un workspace Bun piloté par Turborepo : sept applications, sept paquets partagés. Le README.md racine en décrit encore cinq de chaque — il date d’avant l’atelier de données et ce site de documentation.

apps/ Ce que c’est
api l’API REST NestJS — l’autorité : authentification, permissions, règles métier, OpenAPI servie sur /docs
web le SaaS, en TanStack Start et React — la grille de planification, le référentiel, tous les écrans connectés
solver le microservice d’optimisation, en Kotlin sur JVM. Le seul module non-TypeScript, et le seul sans dépendance au reste
landing le site vitrine, en Astro statique et bilingue — aucun JavaScript expédié au visiteur
lead-function la fonction serverless qui reçoit les formulaires de la vitrine
seeder l’atelier de données de J2 — jamais déployé, purement local
docs ce site — la documentation d’usage, en Astro Starlight
packages/ Ce que c’est
schemas les schémas Zod partagés — le contrat entre l’API, le web et le solveur. Le paquet le plus consommé du dépôt
db le schéma Drizzle, les migrations et la source du RLS multi-tenant
api-client le client TypeScript généré depuis l’OpenAPI de l’API. Rien ne s’y écrit à la main
ui les composants partagés shadcn/ui, en Tailwind v4
config les configurations TypeScript communes. Le lint et le format, eux, sont à la racine (Biome)
dataset-generator le moteur de génération de jeux de données de J2
constraints-fixtures les scénarios JSON que les deux moteurs de scoring doivent évaluer à l’identique

Relevé dans les workspace:* de chaque package.json — c’est le graphe réel, pas une intention :

web → api-client, schemas, ui
api → db, schemas, dataset-generator
seeder → dataset-generator, db, schemas, ui
docs → schemas, ui, db
landing→ schemas, ui
lead-function → schemas, config
api-client → config db → config
schemas → config ui → config
dataset-generator → schemas, config
constraints-fixtures → schemas, config
solver → (rien)

Trois choses se lisent dans ce graphe :

  • schemas est au centre. Presque tout en dépend, donc presque tout casse quand il change — et c’est voulu : un contrat qui se rompt doit se voir à la compilation.
  • web ne dépend pas de api. Il passe par api-client, qui est généré. C’est le sujet de J5.
  • solver ne dépend de rien. Son contrat avec le reste du monde est du JSON, doublé côté Kotlin — voir J6.

La question du jour, pour les cinq modifications les plus courantes.

Le chemin le plus long du dépôt, et celui qu’il faut connaître par cœur :

  1. packages/schemas — le schéma Zod, source du contrat ;
  2. packages/db — la colonne dans src/schema.ts, puis la migration générée ;
  3. apps/api — le module concerné : contrôleur, service, DTO ;
  4. la chaîne de génération — openapi:emit, puis le client ;
  5. apps/web — l’écran qui l’affiche.

Le détail de l’étape 4 est en J5 : c’est là que tout le monde se fait avoir.

apps/web/src/routes/ — le routage est par fichier, et routeTree.gen.ts est généré, jamais édité. Un écran connecté vit sous _authenticated. Ajoutez ses textes dans apps/web/messages/{en,fr}.json — anglais en langue de base, conformément à la règle « le code en anglais ». Et sa page de référence sur ce site, dans la même pull request.

Le seul changement qui traverse deux langages :

  1. packages/schemas — la définition et ses paramètres, au catalogue ;
  2. apps/api/src/scoring/ — l’évaluateur TypeScript ;
  3. apps/solver/ — la contrainte Timefold équivalente, en Kotlin ;
  4. packages/constraints-fixtures — le scénario qui prouve que les deux donnent le même score.

Puis bun run test:contract, que la CI ne joue pas à votre place.

packages/ui, et l’ajout passe par l’outil plutôt que par un copier-coller :

Fenêtre de terminal
bunx shadcn@latest add <composant> --cwd packages/ui

Il s’importe ensuite depuis @beemyschool/ui/components/<composant>.

packages/db : on modifie src/schema.ts, puis on génère.

Fenêtre de terminal
bun run --filter @beemyschool/db db:generate

Le fichier SQL produit se relit avant d’être committé — c’est le sujet de J4.

  • Vous savez nommer les sept applications et les sept paquets, et dire ce que fait chacun
  • Vous savez pourquoi web ne dépend pas de api
  • Vous savez où va un nouveau champ d’API, un écran, une contrainte, un composant, une migration
  • Vous savez que routeTree.gen.ts et packages/api-client/src/generated/ ne s’éditent pas
  • Vous avez lancé un build ciblé avec --filter

J4 — Le modèle et le RLS : la couche qui explique pourquoi une requête parfaitement écrite peut ne rien renvoyer. C’est le piège n°1 du projet, et il mérite sa journée.

Documentation technique source (2)