Export-DI
Dependency Injection Container for Node.js based on ES2015 Exports
Allows you to define class dependencies inside the modules themselves by exporting a "dependencies" array. Includes singleton and folder-dependency support.
Example:
/* lib/dependency.js */ ; { super this_myArg = myArg || "FooBarBaz" } { return this_myArg; } { if value this_myArg = value } /* lib/example-deps.js */ ; const dependencies = "Dependency" { super this_firstArg = firstArg this_dependency = } { return this_dependencymyArg; } /* index.js */ let di = `/lib` let exampleDeps = di console // "FooBarBaz" let exampleDeps2 = di console // "BazBarFoo"
Installation
npm install export-di
Usage
The DI constructor accepts a directory path as its argument. It will auto-require all folders in this path, injecting their dependencies and creating singletons as needed.
let di = `/dist')
Export Dependencies
Classes in the required directory should be separated to one class per file. The class should be exported as default
, and the file should also export a dependencies
array.
The dependencies
array should consist of the path of the file relative to the root library of the container (provided in the constructor), and the name of the exported class.
Example:
const dependencies = "library/ClassName" "ClassNameInRootLib" "anotherLibrary/yetAnotherLibrary/AnotherClassName" { ... }
Export Singletons
Export-DI also allows the declaration of singletons. A singleton object will be the same object wherever it is injected. Please note that for the sake of consistency, singleton classes are injected as constructors. When instantiated, the constructors will ignore all arguments passed to them and return the singleton as the created object.
Singletons can be declared by exporting a truthy singleton constant from the module file.
Example:
/* lib/my-awesome-singleton.js */... = /* some dependencies */ const singleton = true { super this_count = 0 } { return this_count } { thiscount += 1 } /* lib/my-awesome-class.js */... = "MyAwesomeSingleton" { super this_jointCounter = } { return this_jointCountercount } { this_jointCounter } /* app.js */ let di = `/lib` let myAwesome = dilet myOtherAwesome = di console // 0myOtherAwesomeconsole // 1
Folder Dpendencies
When declaring dependencies, it's possible to declare a path to a folder rather than a path to a classname. This returns an object with all the constructors in that directory recursively.
Example with the following library structure:
lib/
├── anotherlib
│ ├── anotherexample.js (classname: AnotherExample)
│ ├── example.js (classname: Example)
│ ├── singleton.js (classname: Singleton)
│ └── yetAnotherLib
│ └── yetAnotherExample.js (classname: YetAnotherExample)
├── dependency.js (classname: Dependency)
...const dependencies = "anotherLib" { super thisanotherExample = thisexample = "some" "args" "because" "why" "not?" thissingleton = thisyetAnotherExample = }
API
<modulePath>
, [...args])
di.create(Returns an instance of module at the specified path relative to the root library provided in the constructor.
In the below example, "lib" is provided as the root path:
lib/
├── anotherlib
│ ├── anotherexample.js (classname: AnotherExample)
│ ├── example.js (classname: Example)
│ ├── singleton.js (classname: Singleton)
│ └── yetAnotherLib
│ └── yetAnotherExample.js (classname: YetAnotherExample)
├── dependency.js (classname: Dependency)
To create the class exported from the "dependency.js" file:
di
To create the class exported from the yetAnotherExample.js file:
di
Any arguments provided the create function will be passed on to the module's constructor.
<modulePath>
, [...args])
di.singleton(Manually creates a singleton and returns its instance. Note that if the module created is already a singleton, this will throw.
For an explanation of modulePath
see the create method.
Contributions / Issues
This project is still very new and has not been widely tested yet. Please feel free to open an issue or a PR if something's broken, or if you'd like some specific features added.
License
MIT