Backend-Frameworks
Jedes Beispiel baut den Root-Container einmal auf, erstellt einen Scope je HTTP-Anfrage und stellt ihn über das native Request-Objekt bereit. Die Freigabe folgt dem Lebenszyklus der Antwort.
Alle verwenden denselben Graphen. Die Unterschiede liegen in den Lebenszyklushooks und Adapter-APIs. examples/_shared/container.ts
| Beispiel | Adapter |
|---|---|
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
}Datei im Repository: 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)
})Datei im Repository: 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)
})Datei im Repository: 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)
}
})Datei im Repository: 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)
})Datei im Repository: examples/backend/elysia.ts
