Dependable Dependency Injection Framework
Dependable is a minimalist dependency injection (DI) framework specifically designed for Node.js environments. It currently stands at version 1.1.0, a stable release, but exhibits a very low release cadence, with the last significant update being a number of years ago, despite minor recent commits on its GitHub repository. Its core functionality revolves around automatic dependency resolution through function argument introspection, allowing for lazy loading of dependencies. Key differentiators include its simple API for registering and resolving dependencies, support for re-registering components (useful for configuration or mocking), and the ability to override dependencies at resolve time. Unlike more comprehensive modern DI containers like InversifyJS or Awilix, Dependable focuses purely on a lightweight, convention-based approach, omitting features such as explicit type binding, decorator-based configuration, or native asynchronous dependency resolution. This makes it suitable for projects prioritizing simplicity and minimal overhead.
Common errors
-
Error: Dependency 'someDependency' not found
cause Attempting to resolve a dependency that has not been registered in the container.fixEnsure `container.register('someDependency', valueOrFunction)` is called before `container.resolve()` or `container.get()` attempts to use it. -
TypeError: dependable.container is not a function
cause The `dependable` module was imported incorrectly, or Node.js's CommonJS/ESM interop failed to expose the default export as expected.fixAlways use `const dependable = require('dependable');` for this CommonJS-first package. Avoid `import dependable from 'dependable';` unless your build pipeline or Node.js environment is configured to handle CJS default exports in ESM. -
ERR_REQUIRE_ESM
cause This error typically occurs in a CommonJS module when attempting to `require()` an npm package that has switched to being ESM-only.fixWhile `dependable` itself is CJS, if one of your dependencies registered with `dependable` is ESM-only and you're trying to `require` it, this error might appear. Ensure all modules directly or indirectly `require`d in your CJS application are also CJS, or migrate your application to ESM if possible to leverage native ESM imports for ESM-only packages.
Warnings
- gotcha This package is primarily designed for CommonJS (`require()`) environments. While Node.js offers some interoperability, using native ESM `import` statements directly with `dependable` may require specific configurations or lead to unexpected behavior, especially when dealing with other ESM-only dependencies.
- gotcha The `container.load(fileOrFolder)` method explicitly states it 'Does not traverse subdirectories.' This means it will only load files directly within the specified folder, which can be a limitation for larger applications with nested dependency structures, requiring manual registration or a custom loading mechanism for such cases.
- gotcha Dependable's minimalist design does not natively support asynchronous dependency resolution. If your dependencies require asynchronous initialization (e.g., fetching configuration, connecting to a database), you'll need to handle the asynchronous logic externally before registering the resolved dependency or design your functions to accept promises and resolve them manually outside the container's direct control.
- gotcha As with any dependency injection system, introducing circular dependencies can lead to unexpected behavior or runtime errors, even with lazy resolution. Dependable doesn't provide explicit mechanisms for detecting or breaking circular dependencies, which might complicate debugging in complex applications.
- gotcha The package has seen very limited active development since its initial release, with its core version remaining at 1.1.0 for a long period, despite minor recent commits on GitHub. This indicates minimal ongoing maintenance, which could pose a risk for long-term project viability, security updates, or compatibility with newer Node.js versions or ecosystem changes.
Install
-
npm install dependable -
yarn add dependable -
pnpm add dependable
Imports
- dependable
import dependable from 'dependable';
const dependable = require('dependable'); - container
import { container } from 'dependable';const container = dependable.container();
- register
container.register('myService', myServiceFunction); - resolve
container.resolve(function (myService) { /* ... */ });
Quickstart
const dependable = require('dependable');
const container = dependable.container();
// Register simple dependencies
container.register('occupation', 'tax attorney');
container.register('transport', {
type: 'station wagon',
material: 'wood-paneled'
});
// Register a dependency that has other dependencies
container.register('song', function (occupation, transport, legalStatus) {
const song = {};
song.chorus = function chorus() {
return [
'I\'m a ' + occupation,
'On a ' + transport.material + ' ' + transport.type + ' I ride',
'And I\'m ' + legalStatus.message
].join('\n');
};
return song;
});
// Register a dependency out-of-order (lazy resolution)
container.register('legalStatus', {
warrants: [],
message: 'without outstanding warrants'
});
// Resolve and use a dependency
container.resolve(function (song) {
console.log('Original song:\n' + song.chorus());
});
// Re-register dependencies for updated behavior (e.g., for testing)
container.register('occupation', 'cowboy');
container.register('legalStatus', {
warrants: [
{
for: 'shooting the sheriff',
notes: 'did not shoot the deputy'
}
],
message: 'wanted: dead or alive'
});
// Resolve with updated dependencies (empty override to force re-evaluation)
container.resolve({}, function (song) {
console.log('\nUpdated song:\n' + song.chorus());
});
// Override dependencies at resolve time
const horse = {
type: 'horse',
material: 'steel'
};
container.resolve({ transport: horse }, function (song) {
console.log('\nOverride transport song:\n' + song.chorus());
});