ADR-006 : Repository pattern (Phase 2)

ADR-006 : Repository pattern (Phase 2)

Date : 2026-Q1 (Phase 2 refactoring) — Statut : accepté

Contexte

Au début du projet, les routes Hono importaient directement db et drizzle-orm :

// routes/games.ts
import { db } from '../db.js';
import { games } from '../schema.js';

app.get('/api/games', async (c) => {
  const allGames = await db.select().from(games).all();
  return c.json(allGames);
});

Au fil du temps, le même db.select().from(games) se retrouvait dans 20 fichiers (routes, services, scripts, crons). Conséquences :

Décision

Repository pattern. Tout accès DB passe par src/repositories/*.repo.ts. Aucune autre couche n'importe db, drizzle-orm ou les tables du schéma.

// repositories/games.repo.ts
import { db } from '../db.js';
import { games } from '../schema.js';

export async function getById(id: string): Promise<Game | null> {
  return db.select().from(games).where(eq(games.id, id)).get() ?? null;
}

export async function listByParent(parentId: string): Promise<Game[]> {
  return db.select().from(games).where(eq(games.parentGameId, parentId)).all();
}

// + une trentaine de fonctions par repo
// routes/games.ts
import * as gamesRepo from '../repositories/games.repo.js';

app.get('/api/games/:id', async (c) => {
  const game = await gamesRepo.getById(c.req.param('id'));
  if (!game) return c.json({ error: 'not found' }, 404);
  return c.json(game);
});

Règle stricte :

Repos actuels

Conséquences

Bonnes

Mauvaises

Vérification

# Doit retourner zéro résultat
grep -rn "from 'drizzle-orm'" src/ --include="*.ts" \
  | grep -v src/repositories/ \
  | grep -v src/db.ts \
  | grep -v src/schema.ts \
  | grep -v drizzle.config.ts

Alternative envisagée

Évolution future

Si on ajoute un cache (Redis) entre repo et consommateurs :

C'est précisément le bénéfice de l'abstraction.


Revision #1
Created 2026-05-10 15:19:54 UTC by thymon
Updated 2026-05-10 15:19:54 UTC by thymon