Product
Introducing SSO
Streamline your login process and enhance security by enabling Single Sign-On (SSO) on the Socket platform, now available for all customers on the Enterprise plan, supporting 20+ identity providers.
Readme
Dependency injection container with auto injection of module dependencies (by parameter names).
Node.js version >= 6.0
npm install sdic
const container = require('sdic').create();
or
import sdic from 'sdic';
const container = sdic.create();
load(path, opts = {})
Loads single module file or all module files in given path.
register(name, fn, opts = {})
Registers a single module.
has(name)
Checks whether container contains given module by name.
get(name, overrides)
Returns registered module from container.
getAll()
Returns all registered modules
getByTag(tag)
Returns all registered modules with given tag.
override(name, fn, opts)
Overrides registered module with new instance. Parameters: see register method
unregister(name)
Unregisters module from container.
clear()
Removes all modules from container.
module.exports = (/* no dependencies */) => {
// module instance
return {
someMethod: () => {}
}
}
or using ES6 export default syntax:
export default (/* no dependencies */) => {
// module instance
return {
someMethod: () => {}
}
}
// module depends on myDb and myNextService
module.exports = (myDb, myNextService) => {
// module instance
return {
someMethod: () => {
return myNextService.doSomething(myDb.getWhatever());
}
}
}
or using ES6 export default syntax:
// module depends on myDb and myNextService
export default (myDb, myNextService) => {
// module instance
return {
someMethod: () => {
return myNextService.doSomething(myDb.getWhatever());
}
}
}
// module without dependencies
export const firstFunctionalService = () => {
return {
method: () => ({passed: true})
}
};
// module dependds on fooService
export function secondFunctionalService (fooService) {
return {
method: () => fooService.method()
}
};
// module dependds on fooService
export class ClassService {
constructor(fooService) {
this.fooService = fooService;
}
method() {
return this.fooService.method();
}
}
ES6 note: container returns instances of modules by default (aka singletons). If you want to register a class (constructor function), you have to use option: isConstructor: true
class FooBar {}
container.register('FooBar', FooBar);
container.get('FooBar'); // --> returns an instance of FooBar (default behaviour)
class FooBar {}
container.register('FooBar', FooBar, {isConstructor: true});
container.get('FooBar'); // --> returns class FooBar
// all modules will be loaded as constructors
container.load('/path/to/constructors_folder', {isConstructor: true});
container.register('myJson', {foo: 'bar'});
container.get('myJson'); // returns {foo: 'bar'}
container.register('myPrimitive', 123);
container.get('myPrimitive'); // returns 123
container.register('myDep', (/* no dependencies */) => {
return {
doWhatever: () => {return 'whatever'}
}
});
container.register('myModule', (myJson, myPrimitive, myDep) => {
return {
getAll: () => ({myJson, myPrimitive, myDepValue: myDep.doWhatever()})
}
});
container.get('myModule'); // returns an instance of module with injected dependencies
Consider this project structure:
+ config.json
|
+ services/
+ - users.js
+ - user-roles.js
|
+ repositories/
+ - roles.js
+ - users.js
|
+ lib/
+ - validator.js
Let's load all files into SDIC.
container.load('./config'); // loads single file: config.json
container.load('./services'); // loads all files in "services" folder (basedir == "services")
container.load('./repositories'); // loads all files in "repositories" folder (basedir == "repositories")
container.load('./lib'); // loads all files in "lib" folder (basedir == "lib")
By default, all loaded modules will be named "down to up": camelCased filename + camelCased basedir. So the module names will be:
The "plurals" sounds strange. We can rename the basedirs to "singular" or tweak the loader a little bit:
container.load('./config'); // this is OK, keep it
container.load('./services', {alias: 'service'}); // alias basedir as "service"
container.load('./repositories', {alias: 'repository'}); // alias basedir as "repository"
container.load('./lib', {alias: null}); // ignore basedir name, there's no need to have explicit "Lib" postfix
Now the module names will be:
Nice :-)
Now consider more nested project structure:
+ services/
+ - users/
+ -- roles.js
+ -- users.js
|
+ repositories/
+ - users/
+ -- roles.js
+ -- index.js
We'll skip "config" file and "lib" folder (see above). Let's load all files into SDIC.
container.load('./services'); // loads all files in "services" folder (basedir == "services")
container.load('./repositories'); // loads all files in "repositories" folder (basedir == "repositories")
By default, all loaded modules will be named "camelCased, down to up": filename + subfolders + basedir. So the module names will be:
Sounds really strange. Let's set up the loading better. The "services" folder first. It'd be cool to start the name with the subfolder (if any), then the filename and the basedir at the end.
container.load('./services', {
alias: null, // disable basedir name at the beginning
reverseName: true, // name will be generated "up to down"
postfix: 'service', // instead of basedir as prefix, append it at the end
deduplicate: true // removes multiple "users" string ("users" folder + "users" file)
});
Now the modules will be:
Better, but still sounds strange because of "plurals". To fix this we need to split the loading into two steps:
container.load('./services/users', { // the basedir is now "users"
alias: 'user', // alias basedir as "user"
postfix: 'service', // append "service" at the end
ignore: [/users\.js/] // ignore users.js file for now
});
container.load('./services/users/users', {alias: 'userService'}); // append the ignored file
Finally the modules will be:
We can load the "repositories" folder the same way.
ES6 note: when loading named exports into the container, then:
SDIC supports code minification. Because module dependencies are defined using parameter names, the code minification process would damage them (to a
, b
, c
, ... etc.) and SDIC would not be able to load them properly. To prevent this situation all you need to do, is to define the list of a module dependencies in a property dependencies
:
const service = (a, b) => { // minified param names
return {
method: () => a.method() + b.method()
};
};
service.dependencies = ['fooService', 'barService']; // <--- definition of dependencies
export default service;
const service = (a, b) => { // minifies param names
return {
method: () => a.method() + b.method()
};
};
service.dependencies = ['fooService', 'barService']; // <--- definition of dependencies
module.exports = service;
export class ClassService {
constructor(a, b) { // minified param names
this.fooService = a;
this.barService = b;
}
method() {
return this.fooService.method() + this.barService.method();
}
}
ClassService.dependencies = ['fooService', 'barService']; // <--- definition of dependencies
+- users/ <- load this
+- -- foo.js
+- users.js <- as well as this
Based on the idea of: https://www.npmjs.com/package/adctd
FAQs
Simple dependency injection container
The npm package sdic receives a total of 14 weekly downloads. As such, sdic popularity was classified as not popular.
We found that sdic demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Product
Streamline your login process and enhance security by enabling Single Sign-On (SSO) on the Socket platform, now available for all customers on the Enterprise plan, supporting 20+ identity providers.
Security News
Tea.xyz, a crypto project aimed at rewarding open source contributions, is once again facing backlash due to an influx of spam packages flooding public package registries.
Security News
As cyber threats become more autonomous, AI-powered defenses are crucial for businesses to stay ahead of attackers who can exploit software vulnerabilities at scale.