Skip to content

Adaptadores de frameworks

Los adaptadores de InferDI conectan tipos exactos de contenedor con los límites del lifecycle del framework. Los adaptadores HTTP crean un request scope y lo exponen en la ubicación nativa. El adaptador de React proporciona un context tipado y también puede poseer un scope secundario creado en el cliente.

Ese es todo el trabajo. Los adaptadores son una fina capa de pegamento del ciclo de vida: el mismo diseño que mantiene a @inferdi/inferdi sin dependencias también mantiene los decoradores, el escaneo de controladores, la inyección de parámetros de handlers y el descubrimiento de rutas fuera del núcleo. Optas por el ciclo de vida de las peticiones de un framework, no por la idea que ese framework tenga de la inyección de dependencias.

Paquetes

PaqueteFrameworkUbicación del scopeModo solo raíz
@inferdi/fastifyFastify v5request.di
@inferdi/honoHono v4c.var.dino
@inferdi/koaKoa v3ctx.state.dino
@inferdi/expressExpress 5req.dino
@inferdi/elysiaElysia v1context.di
@inferdi/reactReact 19React contextProvider externo

React usa el lifecycle del componente en vez del lifecycle de petición descrito abajo. Su Provider externo nunca libera el contenedor; su managed ScopeProvider crea el scope tras el commit y siempre lo libera. Consulta el adaptador de React.

Contrato común del ciclo de vida

En modo con scope, cada adaptador ejecuta los mismos pasos para cada petición:

  1. Crea el scope a partir del contenedor raíz (createScope, por defecto root.createScope()) cuando comienza la petición.
  2. Expone el scope en la ubicación nativa del framework. Hono, Koa, Express y Elysia lo exponen antes de la configuración. Fastify expone request.di después de que la configuración tenga éxito y solo lo expone de forma temporal durante la limpieza de un fallo de configuración. Los hooks de limpieza ven el slot público, mientras que los manejadores de errores nunca reciben un scope a medio construir.
  3. Configura el scope con setupScope si hace falta inicialización adicional antes de los handlers. Puede ser asíncrono.
  4. Atiende la petición: los handlers de rutas y los manejadores de errores del framework resuelven servicios desde el scope expuesto.
  5. Libera el scope en el punto de finalización seguro del framework (disposeScope, por defecto scope.dispose()), salvo que se haya transferido la propiedad.

Opciones compartidas

OpciónPor defectoPropósito
containerrequeridoContenedor raíz expuesto a la aplicación. Los adaptadores nunca lo liberan (excepto el disposeRootOnClose opcional de Fastify).
createScoperoot.createScope()Construye el scope y recibe aquí las entradas declaradas de la petición. Puede ser asíncrono.
setupScopeningunoEjecuta inicialización adicional antes de los handlers. Puede ser asíncrono.
disposeScopescope.dispose()Limpieza personalizada. Puede ser síncrona o asíncrona.
autoDisposetruefalse, o un predicado que devuelve false, cede la liberación a tu código.
onDisposeErrorsumidero por adaptadorRecibe los fallos de liberación del scope de petición: Fastify request.log.error, Koa ctx.app.emit('error'), los demás console.error.
skipInferdiDispose(...)Marca una petición como propiedad de la aplicación para streaming o trabajo en segundo plano.

Reglas de errores y de propiedad

  • Un fallo de configuración expone solo el error original. Si setupScope lanza una excepción, el adaptador libera el scope a medio construir y vuelve a lanzar ese error. Un fallo de limpieza durante esta operación va a onDisposeError (o al sumidero) y nunca se agrega al error expuesto.
  • Una petición fallida igualmente se libera. skipInferdiDispose suprime la limpieza solo en una respuesta exitosa; una ruta de error libera de todos modos. Express es la excepción: su middleware basado en callbacks no puede observar un error de ruta gestionado, por lo que una petición fallida de Express omitida permanece como propiedad de la aplicación.
  • autoDispose: false y skipInferdiDispose transfieren la propiedad. Entonces tu código pasa a ser responsable de liberar el scope en el límite correcto del framework.
  • Los errores de limpieza después de que se produce una respuesta se enrutan al sumidero y se descartan. La respuesta ya se envió, por lo que un fallo tardío de limpieza nunca podrá corromperla.

Diferencias importantes

AdaptadorDiferencia
FastifyLibera en onResponse; la limpieza por aborto usa onRequestAbort; la liberación de la raíz puede activarse con disposeRootOnClose.
HonoLibera después de await next(); los helpers de streaming pueden devolver antes de que termine el trabajo del stream, por lo que las rutas de streaming a menudo necesitan skipInferdiDispose.
KoaEspera al finish o close de la respuesta de Node, por lo que los cuerpos de stream normales no necesitan un skip.
ExpressNo puede detectar un error de ruta gestionado aguas abajo desde un middleware basado en callbacks; una petición fallida omitida permanece como propiedad de la aplicación.
ElysiaLa limpieza está vinculada a onAfterResponse; si ese hook nunca se alcanza, el adaptador no puede liberar los recursos retenidos por el scope.