@signe/di
v2.5.2
Published
A lightweight and flexible dependency injection system for JavaScript/TypeScript applications.
Downloads
689
Readme
@signe/di
A lightweight and flexible dependency injection system for JavaScript/TypeScript applications.
Installation
npm install @signe/di
# or
yarn add @signe/di
# or
pnpm add @signe/diFeatures
- Simple and intuitive API
- Type-safe dependency injection
- Provider system with multiple configuration options
- Context-based injection
- Override capabilities for testing and customization
- Support for nested providers
- Optional injection resolution helpers
- Support for multiple named instances per token
Usage
Basic Usage
import { provide, inject, Context, Providers, injector } from '@signe/di';
const context = new Context();
class UserService {
getUser(id: string) {
return { id, name: 'John Doe' };
}
}
class AuthService {
constructor(private config: any) {}
}
const providers: Providers = [
UserService,
{
provide: 'CONFIG',
useValue: {
apiUrl: 'https://api.example.com'
}
},
{
provide: AuthService,
useFactory: (context) => {
const config = inject(context, 'CONFIG');
return new AuthService(config);
}
}
];
// Register the services
await injector(context, providers);
// Inject and use the service
const userService = inject(context, UserService);
const user = userService.getUser('123');Override Providers
import { override } from '@signe/di';
// Override existing provider
const newProviders = override(providers, {
provide: UserService,
useValue: new MockUserService()
});
// Add new provider with upsert option
const updatedProviders = override(providers, {
provide: 'NEW_SERVICE',
useValue: service
}, { upsert: true });Optional injection
import { inject } from '@signe/di';
const maybeService = inject(context, 'UNKNOWN_SERVICE', { optional: true });
if (!maybeService) {
// Handle missing service without throwing an exception
}Multiple named instances
import { provide, inject } from '@signe/di';
provide(context, UserService, new UserService('primary'), {
multi: true,
name: 'primary'
});
provide(context, UserService, new UserService('secondary'), {
multi: true,
name: 'secondary'
});
const allInstances = inject<UserService>(context, UserService, { multi: true });
const secondary = inject<UserService>(context, UserService, { name: 'secondary' });Check Injection Status
import { isInjected } from '@signe/di';
if (isInjected(context, UserService)) {
// Service is already injected
}Dependency Declaration
You can declare dependencies using the deps property. The injector will automatically sort providers to ensure dependencies are instantiated before the services that need them.
import { provide, inject, Context, Providers, injector } from '@signe/di';
const context = new Context();
class DatabaseService {
connect() {
return 'Connected to database';
}
}
class UserRepository {
constructor(context: Context) {
this.db = inject(context, DatabaseService);
}
static deps = [DatabaseService];
}
class UserService {
constructor(context: Context) {
this.repository = inject(context, UserRepository);
}
static deps = [UserRepository];
}
const providers: Providers = [
UserService,
UserRepository,
DatabaseService
];
// The injector will automatically sort: DatabaseService -> UserRepository -> UserService
await injector(context, providers);You can also declare dependencies on provider objects:
const providers: Providers = [
{
provide: 'API_CLIENT',
useFactory: (context) => {
const config = inject(context, 'CONFIG');
return new ApiClient(config);
},
deps: ['CONFIG']
},
{
provide: 'CONFIG',
useValue: { apiUrl: 'https://api.example.com' }
}
];Note: The injector will detect and throw an error if circular dependencies are found.
Find Providers
import { findProvider, findProviders } from '@signe/di';
// Find single provider
const userProvider = findProvider(providers, UserService);
// Find multiple providers by regex
const allServices = findProviders(providers, /Service$/);API Reference
provide(context, token, value, options?)
Stores a value in the context for dependency injection.
options.multi— Whentrue, allows multiple instances for the same tokenoptions.name— Registers the instance under a specific name
inject(context, token, options?)
Retrieves an injected value from the context.
options.optional— Returnsundefined/[]instead of throwing when missingoptions.multi— Returns all registered instances as an arrayoptions.name— Retrieves a specific named instance
isInjected(context, token, options?)
Checks if a value has been injected. Supports named lookups via the name option.
isProvided(context, token, options?)
Checks if a value has been registered in the context.
hasInstance(context, token, options?)
Alias of isProvided, kept for readability when checking for instance existence.
override(providers, newProvider, options?)
Overrides or adds new providers to the existing provider array.
findProvider(providers, query)
Finds a single provider by name or regex.
findProviders(providers, query)
Finds all providers matching the query.
License
MIT © Samuel Ronce
