Skip to content

Адаптер Fastify

@inferdi/fastify - это плагин для Fastify v5. В режиме со scope он выставляет root как app.di, создаёт scope запроса в onRequest, выставляет его как request.di и очищает в onResponse.

Установка

bash
pnpm add @inferdi/inferdi @inferdi/fastify fastify
ts
import Fastify, { type FastifyRequest } from 'fastify'
import { inferdiFastify } from '@inferdi/fastify'

Scope запроса

Опубликуйте конкретные типы контейнеров через расширение модуля:

ts
const root = buildRootContainer()
const app = Fastify()

type RootContainer = typeof root
type RequestContainer = ReturnType<RootContainer['createScope']>

declare module 'fastify' {
  interface FastifyInstance {
    di: RootContainer
  }

  interface FastifyRequest {
    di: RequestContainer
  }
}

await app.register(inferdiFastify, {
  container: root,
  setupScope: (scope: RequestContainer, request) => {
    const ctx = scope.get('request')
    ctx.requestId = request.id
    ctx.ip = request.ip
  },
})

app.get('/users/:id', async (request) => {
  const { id } = request.params as { id: string }
  return request.di.get('users').profile(id)
})

Fastify app.register не может глубоко вывести generics плагина для inline hooks, поэтому параметры hook лучше аннотировать явно.

Опции

ОпцияПо умолчаниюНазначение
containerобязательнаКорневой контейнер, выставленный как app.di.
scopePerRequesttruefalse для режима без scope запроса.
createScoperoot.createScope()Пользовательское создание scope запроса.
setupScopeнетНаполняет scope в onRequest.
disposeScopescope.dispose()Пользовательская очистка.
autoDisposetruefalse или предикат false передаёт владение.
disposeRootOnClosefalseОчищает root во время fastify.close().
onDisposeErrorrequest.log.errorПриёмник ошибок очистки scope запроса.

Режим без scope запроса

ts
await app.register(inferdiFastify, {
  container: root,
  scopePerRequest: false,
})

app.get('/health', async function () {
  return this.di.get('health').check()
})

В этом режиме адаптер не устанавливает request decoration и hooks жизненного цикла запроса.

Заметки о жизненном цикле

  • request.di выставляется только после успешного setup.
  • Ошибка setup очищает полусобранный scope и поднимает только исходную ошибку setup.
  • Cleanup hooks видят request.di, пока выполняются.
  • Упавший запрос игнорирует skipInferdiDispose и всё равно очищает scope, с учётом autoDispose.
  • Очистка при client abort выполняется в onRequestAbort после выставления scope.
  • Ошибки очистки root проходят через fastify.close() только с disposeRootOnClose.