Skip to content

Адаптер Elysia

@inferdi/elysia - это плагин для Elysia v1. В режиме со scope он создаёт один scope запроса, выставляет его в контекст Elysia, оставляет доступным для пользовательских обработчиков ошибок и очищает из onAfterResponse.

Установка

bash
pnpm add @inferdi/inferdi @inferdi/elysia elysia
ts
import { Elysia } from 'elysia'
import { inferdiElysia } from '@inferdi/elysia'

Scope запроса

ts
const root = buildRootContainer()

const app = new Elysia()
  .use(inferdiElysia({
    container: root,
    setupScope: (scope, { request }) => {
      const ctx = scope.get('request')
      ctx.requestId = crypto.randomUUID()
      ctx.userId = request.headers.get('x-user-id') ?? undefined
    },
  }))
  .get('/users/:id', ({ di, params }) =>
    di.get('users').profile(params.id),
  )

Собственный ключ контекста:

ts
const app = new Elysia()
  .use(inferdiElysia({ container: root, key: 'container' }))
  .get('/users/:id', ({ container, params }) =>
    container.get('users').profile(params.id),
  )

Routes должны регистрироваться после .use(inferdiElysia(...)) в типизированной цепочке Elysia.

Опции

ОпцияПо умолчаниюНазначение
containerобязательнаКорневой контейнер.
key'di'Ключ контекста Elysia.
scopePerRequesttruefalse для режима без scope запроса.
createScoperoot.createScope()Пользовательское создание scope запроса.
setupScopeнетНаполняет scope до validation и обработчиков маршрутов.
setupValidatedScopeнетНаполняет scope после validation Elysia.
disposeScopescope.dispose()Пользовательская очистка.
autoDisposetruefalse или предикат false передаёт владение.
onDisposeErrorconsole.errorПриёмник ошибок очистки.

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

ts
const app = new Elysia()
  .use(inferdiElysia({
    container: root,
    scopePerRequest: false,
  }))
  .get('/health', ({ di }) => di.get('health').check())

В этом режиме адаптер выставляет корневой контейнер и не устанавливает hooks жизненного цикла scope запроса. Опции, допустимые только для scoped mode, отклоняются статически.

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

Очистка привязана к onAfterResponse. Если Elysia не доходит до этого hook, адаптер не может освободить ресурсы, удерживаемые scope запроса. Учёт на каждый запрос хранится через weak-ссылки, но для dispose ресурсов всё равно нужен hook жизненного цикла.

setupScope подходит для значений до validation. setupValidatedScope подходит для данных из проверенных body, query, params, headers или cookies.

Стриминг

Elysia может вернуть streaming Response до завершения stream. Если scoped-сервисы используются после возврата route, вызывайте skipInferdiDispose(context) и очищайте scope самостоятельно.

ts
import { skipInferdiDispose } from '@inferdi/elysia'

app.get('/events', (context) => {
  skipInferdiDispose(context)

  const scope = context.di
  const events = scope.get('events')

  return new Response(new ReadableStream({
    async start(controller) {
      const encoder = new TextEncoder()

      try {
        for await (const event of events.subscribe()) {
          controller.enqueue(encoder.encode(`data: ${JSON.stringify(event)}\n\n`))
        }
      } finally {
        await scope.dispose()
      }
    },
  }))
})

skipInferdiDispose подавляет только очистку успешного ответа. Пути с ошибкой всё равно очищают scope.