Create request scope container
Use when you need manual control over the request container lifecycle, typically in middleware. Returns a new Container instance wrapping a request-scoped child container.
Can only be called on global container (not request-scoped).
RouterContext for the current request
Request-scoped Container instance
Replace a service registration with a decorated version
Resolves the current instance, applies the decorator, and re-registers the decorated instance. This is a one-time operation at initialization time.
IMPORTANT: This method can only be used in a module's onInitialize() method.
The onInitialize() hook runs after all modules have registered their services
via the @Module decorator, ensuring all dependencies are available for resolution.
DI token of the service to extend
Function that receives the service and returns decorated version
// In your module's onInitialize() method:
import type { OnInitialize, ModuleContext } from 'stratal/module'
@Module({ providers: [...] })
export class MyModule implements OnInitialize {
onInitialize({ container }: ModuleContext): void {
container.extend(DI_TOKENS.Database, (db, c) => {
const logger = c.resolve(LOGGER_TOKENS.LoggerService)
return new LoggingDatabaseDecorator(db, logger)
})
}
}
// DI_TOKENS.Database now resolves to LoggingDatabaseDecorator
Get current request container from context store (if in request context)
Request container if in request context, undefined otherwise
Get underlying tsyringe container
Use sparingly - prefer Container methods for most operations. Useful for advanced scenarios or compatibility with existing code.
The underlying DependencyContainer
Check if currently in request context
true if in request context (inside runInRequestScope or runWithContextStore)
Check if a token is registered
DI token to check
true if token is registered
Register a service with optional explicit token and scope
Lifecycle is controlled via the scope parameter, which maps to tsyringe's Lifecycle. If no scope is provided, defaults to Transient (new instance per resolution).
register(serviceClass, scope?) - Use class as token register(token, serviceClass, scope?) - Explicit token
Optionalscope: ScopeRegister a service with optional explicit token and scope
Lifecycle is controlled via the scope parameter, which maps to tsyringe's Lifecycle. If no scope is provided, defaults to Transient (new instance per resolution).
register(serviceClass, scope?) - Use class as token register(token, serviceClass, scope?) - Explicit token
Optionalscope: ScopeRegister an alias to an existing token
Creates a redirect so that resolving the alias token returns the same instance as the target token. This is useful for:
The alias token to register
The target token to redirect to
// Register concrete implementation
container.register(UserService)
// Create alias for interface token
container.registerExisting(I_USER_SERVICE, UserService)
// Both resolve to the same instance
const a = container.resolve(UserService)
const b = container.resolve(I_USER_SERVICE)
// a === b (same instance)
Register with factory function
Use when instance creation requires custom logic or other resolved dependencies.
DI token for resolution
Factory function that receives the Container
Register a service as singleton
Passthrough to tsyringe's registerSingleton method.
registerSingleton(serviceClass) - Use class as token registerSingleton(token, serviceClass) - Explicit token
Register a service as singleton
Passthrough to tsyringe's registerSingleton method.
registerSingleton(serviceClass) - Use class as token registerSingleton(token, serviceClass) - Explicit token
Register a value (instance) directly
Use for registering pre-created instances or primitive values.
DI token for resolution
Value to register
Resolve a service from the container
DI token for the service
Resolved service instance
Run callback within request scope
Creates a child container with fresh instances for services registered with scope: Scope.Request.
Automatically handles lifecycle (setup and cleanup).
Also wraps with RequestContextStore for Zod i18n validation support.
Can only be called on global container (not request-scoped).
RouterContext for the current request
Async operation to run with request context
Result of callback execution
Run callback within request scope context store
Wraps callback with RequestContextStore (for Zod i18n validation) and automatically handles cleanup after callback completes.
Can only be called on request-scoped container (not global).
Result of callback execution
Start a conditional binding with predicate evaluation
Creates a fluent builder for registering a service that chooses between two implementations based on a predicate evaluated at resolution time.
Function that returns true/false to determine implementation.
Receives a container with resolve() method for resolving dependencies.
Optional configuration (cache: whether to cache predicate result)
Fluent builder for specifying token and implementations
Unified Container for DI management
Manages the two-tier container hierarchy:
Example: Basic registration
Example: Resolution
Example: Request scope (automatic lifecycle)
Example: Request scope (manual lifecycle)