Frameworks backend
Chaque exemple construit une seule fois la racine, crée un scope par requête HTTP et l’expose via l’objet de requête natif du framework. La libération suit le cycle de vie de la réponse.
Tous utilisent le même graphe. Les différences concernent les hooks de cycle de vie et les API des adaptateurs. examples/_shared/container.ts
| Exemple | Adaptateur |
|---|---|
fastify.ts | @inferdi/fastify |
hono.ts | @inferdi/hono |
koa.ts | @inferdi/koa |
express.ts | @inferdi/express |
elysia.ts | @inferdi/elysia |
Fastify
ts
import Fastify, { type FastifyInstance, type FastifyRequest } from 'fastify'
import { inferdiFastify } from '@inferdi/fastify'
import {
buildRootContainer,
createRequestScope,
type RootContainer,
type RequestContainer
} from '../_shared/container.js'
declare module 'fastify' {
interface FastifyInstance {
di: RootContainer
}
interface FastifyRequest {
di: RequestContainer
}
}
function normalizeHeader(value: string | string[] | undefined): string | undefined {
return Array.isArray(value) ? value[0] : value
}
export function buildServer(): FastifyInstance {
const root = buildRootContainer()
const app = Fastify()
app.register(inferdiFastify, {
container: root,
// Annotate hook params: `app.register` cannot infer the plugin's generics
createScope: (root: RootContainer, request: FastifyRequest) =>
createRequestScope(root, {
requestId: request.id,
ip: request.ip,
userId: normalizeHeader(request.headers['x-user-id'])
}),
disposeRootOnClose: true
})
app.get('/users/:id', async (request) => {
const { id } = request.params as { id: string }
const users = await request.di.getAsync('users')
return users.profile(id)
})
return app
}Fichier du dépôt : examples/backend/fastify.ts
Hono
ts
import { Hono } from 'hono'
import { inferdiHono, type InferdiHonoScopeEnv } from '@inferdi/hono'
import {
buildRootContainer,
createRequestScope,
type RequestContainer
} from '../_shared/container.js'
const root = buildRootContainer()
type AppEnv = InferdiHonoScopeEnv<RequestContainer>
export const app = new Hono<AppEnv>()
app.use('*', inferdiHono({
container: root,
createScope: (_root, c) => createRequestScope(root, {
requestId: crypto.randomUUID(),
userId: c.req.header('x-user-id')
})
}))
app.get('/users/:id', async (c) => {
const users = await c.var.di.getAsync('users')
const user = await users.profile(c.req.param('id'))
return c.json(user)
})Fichier du dépôt : examples/backend/hono.ts
Koa
ts
import Koa from 'koa'
import { inferdiKoa } from '@inferdi/koa'
import {
buildRootContainer,
createRequestScope,
type RequestContainer
} from '../_shared/container.js'
const root = buildRootContainer()
declare module 'koa' {
interface DefaultState {
di: RequestContainer
}
}
export const app = new Koa()
app.use(inferdiKoa({
container: root,
createScope: (root, ctx) =>
createRequestScope(root, {
requestId: crypto.randomUUID(),
ip: ctx.ip,
userId: ctx.get('x-user-id') || undefined
})
}))
app.use(async (ctx) => {
const id = ctx.path.split('/').pop() ?? ''
const users = await ctx.state.di.getAsync('users')
ctx.body = await users.profile(id)
})Fichier du dépôt : examples/backend/koa.ts
Express
ts
import express from 'express'
import { inferdiExpress } from '@inferdi/express'
import {
buildRootContainer,
createRequestScope,
type RequestContainer
} from '../_shared/container.js'
const root = buildRootContainer()
declare global {
namespace Express {
interface Request {
di: RequestContainer
}
}
}
function normalizeHeader(value: string | string[] | undefined): string | undefined {
return Array.isArray(value) ? value[0] : value
}
export const app = express()
app.use(inferdiExpress({
container: root,
createScope: (root, req) =>
createRequestScope(root, {
requestId: crypto.randomUUID(),
// req.ip is `string | undefined` in @types/express — propagate that shape
ip: req.ip,
userId: normalizeHeader(req.headers['x-user-id'])
})
}))
app.get('/users/:id', async (req, res, next) => {
try {
const users = await req.di.getAsync('users')
res.json(await users.profile(req.params.id))
} catch (error) {
next(error)
}
})Fichier du dépôt : examples/backend/express.ts
Elysia
ts
import { Elysia } from 'elysia'
import { inferdiElysia } from '@inferdi/elysia'
import {
buildRootContainer,
createRequestScope
} from '../_shared/container.js'
const root = buildRootContainer()
export const app = new Elysia()
.use(inferdiElysia({
container: root,
createScope: (root, { request }) =>
createRequestScope(root, {
requestId: crypto.randomUUID(),
userId: request.headers.get('x-user-id') ?? undefined
})
}))
.get('/users/:id', async ({ params, di }) => {
const users = await di.getAsync('users')
return users.profile(params.id)
})Fichier du dépôt : examples/backend/elysia.ts
