├── .gitignore ├── .mocharc.yml ├── .npmignore ├── .travis.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENCE ├── README.md ├── lib ├── exception │ └── ExtensionConfigurationFileNameException.js └── index.js ├── package-lock.json ├── package.json └── test ├── lib ├── DependencyInjectionMiddleware.spec.js └── FooPass.js └── resources ├── services.js ├── services.json └── services.yml /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | dist/ 3 | node_modules/ 4 | .nyc_output/ 5 | coverage/ 6 | coverage.lcov 7 | npm-debug.log -------------------------------------------------------------------------------- /.mocharc.yml: -------------------------------------------------------------------------------- 1 | require: '@babel/register' 2 | spec: test/lib/**/*.spec.js 3 | color: true 4 | ui: bdd 5 | reporter: nyan 6 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | node_modules/ 3 | test/ 4 | lib/ -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '13' 4 | - '12' 5 | - '11' 6 | - '10' 7 | - '9' 8 | - '8' 9 | script: 10 | - npm run test:standard 11 | - npm run test:coverage 12 | after_success: 13 | - npm run report:coverage 14 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | ## [1.2.0] - 2017-06-07 4 | ### Changes 5 | - Adding container arguments values 6 | 7 | ## [1.1.0] - 2017-06-07 8 | ### Changes 9 | - Fixing bugs 10 | 11 | ## [1.0.0] - 2017-06-07 12 | ### Added 13 | - Initial commit 14 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Issues 2 | Issues are always very welcome. 3 | However, there are a couple of things you can do to make the lives of the developers much easier: 4 | 5 | ### Tell us: 6 | 7 | * What you are doing? 8 | * Post a _minimal_ code sample that reproduces the issue 9 | * What do you expect to happen? 10 | * What is actually happening? 11 | * Which NodeJS version you are using? 12 | * Which Ecma Script version you are using? 13 | * Which Ecma Script presets you are using? 14 | 15 | When you post code, please use [Github flavored markdown](https://help.github.com/articles/github-flavored-markdown), 16 | in order to get proper syntax highlighting! 17 | 18 | # Pull requests 19 | 20 | We're glad to get pull request if any functionality is missing or something is buggy. 21 | However, there are a couple of things you can do to make life easier for the maintainers: 22 | 23 | * Explain the issue that your PR is solving - or link to an existing issue 24 | * Make sure that all existing tests pass 25 | * Make sure you followed [standard coding guidelines](http://standardjs.com) 26 | * Add some tests for your new functionality or a test exhibiting the bug you are solving. Ideally all new tests should not pass _without_ your changes. 27 | * If you are adding or changing the public API, remember to add this changes in to the docs/wiki. 28 | * Add an entry to the [changelog](CHANGELOG.md), following the [changelog rules](http://keepachangelog.com/) 29 | 30 | ### 1. Prepare your environment 31 | 32 | You need [Node.JS](http://nodejs.org) and [npm](https://docs.npmjs.com/getting-started/installing-node) 33 | 34 | ### 2. Install dependencies 35 | 36 | Run `npm install`, see an example below: 37 | 38 | ```console 39 | $ npm install 40 | ``` 41 | 42 | ### 3. Run tests ### 43 | 44 | All tests are located in the `test` folder (which contains the [Mocha](http://visionmedia.github.io/mocha/) tests). 45 | 46 | ```console 47 | $ npm test || test:coverage 48 | ``` 49 | 50 | ### 4. Standard Coding Guidelines ### 51 | 52 | Please, follow [Standard JS Coding Guidelines](http://standardjs.com) 53 | 54 | ```console 55 | $ npm run test:standard 56 | ``` 57 | 58 | and if you want to fix automatically some of your source code 59 | 60 | ```console 61 | $ npm run test:standard:fix 62 | ``` 63 | 64 | And then make and commit your changes 65 | 66 | ### 5. Done ### 67 | 68 | Just commit and send your pull request. 69 | Thank you for contributing. 70 | -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014-2016 node-dependency-injection-express-middleware contributors 2 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 3 | documentation files (the "Software"), to deal in the Software without restriction, including without limitation the 4 | rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit 5 | persons to whom the Software is furnished to do so, subject to the following conditions: 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the 7 | Software. 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 9 | WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 10 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 11 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Node Dependency Injection Express Middleware 2 | ============================================ 3 | 4 | ![NDI Logo](http://image.ibb.co/iGnCUn/logojoy.png) 5 | 6 | A Node Dependency Injection middleware for Express 7 | 8 | [![Npm Version](https://badge.fury.io/js/node-dependency-injection-express-middleware.svg)](https://badge.fury.io/js/node-dependency-injection-express-middleware) 9 | [![Build Status](https://travis-ci.org/zazoomauro/node-dependency-injection-express-middleware.svg?branch=master)](https://travis-ci.org/zazoomauro/node-dependency-injection-express-middleware) 10 | [![Dependencies](https://david-dm.org/zazoomauro/node-dependency-injection-express-middleware.svg)](https://david-dm.org/zazoomauro/node-dependency-injection-express-middleware) 11 | [![DevDependencies](https://david-dm.org/zazoomauro/node-dependency-injection-express-middleware/dev-status.svg)](https://david-dm.org/zazoomauro/node-dependency-injection-express-middleware#info=devDependencies) 12 | [![Code Coverage](https://codecov.io/gh/zazoomauro/node-dependency-injection-express-middleware/branch/master/graph/badge.svg)](https://codecov.io/gh/zazoomauro/node-dependency-injection-express-middleware) 13 | [![Maintainability](https://api.codeclimate.com/v1/badges/54d93c7090e693ab753c/maintainability)](https://codeclimate.com/github/zazoomauro/node-dependency-injection-express-middleware/maintainability) 14 | [![Coding Standard](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com/) 15 | [![Known Vulnerabilities](https://snyk.io/test/github/zazoomauro/node-dependency-injection-express-middleware/badge.svg)](https://snyk.io/test/github/zazoomauro/node-dependency-injection-express-middleware) 16 | [![Npm Downloads](https://img.shields.io/npm/dm/node-dependency-injection-express-middleware.svg?maxAge=2592000)](https://www.npmjs.com/package/node-dependency-injection-express-middleware) 17 | [![License](https://img.shields.io/npm/l/node-dependency-injection-express-middleware.svg?maxAge=2592000?style=plastic)](https://github.com/zazoomauro/node-dependency-injection-express-middleware/blob/master/LICENCE) 18 | 19 | Installation 20 | ------------ 21 | 22 | ```sh 23 | npm install --save node-dependency-injection-express-middleware 24 | ``` 25 | 26 | Usage 27 | ----------- 28 | 29 | #### Minimal configuration 30 | ```js 31 | import NodeInjectionMiddleware from 'node-dependency-injection-express-middleware' 32 | import express from 'express' 33 | 34 | const app = express() 35 | 36 | const options = {serviceFilePath: 'some/path/to/config.yml'} 37 | app.use(new NodeInjectionMiddleware(options).middleware()) 38 | ``` 39 | 40 | ### Options 41 | 42 | | Name | Required | Type Value | Default Value | 43 | | --------------------------- | -------- | --------------- | -------------- | 44 | | serviceFilePath | true | string | | 45 | | compile | false | boolean | false | 46 | | compilerPass | false | array | [] | 47 | | logger | false | class or object | null | 48 | | containerReferenceAsService | false | boolean | false | 49 | | defaultDir | false | string | null | 50 | 51 | ### How to use all options 52 | 53 | ```js 54 | import MyCustomPass from 'CompilerPass/MyCustomPass' 55 | import AnotherAwesomePass from 'CompilerPass/AnotherAwesomePass' 56 | import MyCustomLogger from 'MyCustomLogger' 57 | import NDIMiddleware from 'node-dependency-injection-express-middleware' 58 | import express from 'express' 59 | 60 | const app = express() 61 | 62 | const options = { 63 | serviceFilePath: 'some/path/to/config.yml', 64 | compile: true, 65 | compilerPass: [new MyCustomPass(), new AnotherAwesomePass()], 66 | logger: new MyCustomLogger(), 67 | containerReferenceAsService: true, 68 | defaultDir: '/some/cool/dir', 69 | } 70 | app.use(new NDIMiddleware(options).middleware()) 71 | ``` 72 | 73 | ### How to get the container 74 | 75 | ```js 76 | app.get('/some/action', (req, res, next) => { 77 | const container = req.container 78 | const myAwesomeService = container.get('some.awesome.service') 79 | ... 80 | }) 81 | ``` 82 | 83 | > Please, read the [FULL DOCUMENTATION](https://github.com/zazoomauro/node-dependency-injection/wiki) 84 | 85 | Resources 86 | --------- 87 | 88 | - [Documentation](https://github.com/zazoomauro/node-dependency-injection/wiki) 89 | - [Collaboration and pull requests](CONTRIBUTING.md) 90 | - [Twitter @zazoomauro](https://twitter.com/zazoomauro) 91 | - [Changelog](CHANGELOG.md) 92 | -------------------------------------------------------------------------------- /lib/exception/ExtensionConfigurationFileNameException.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Extension configuration file name exception 3 | */ 4 | export default class ExtensionConfigurationFileNameException extends Error { 5 | /** 6 | * @param {string} format 7 | */ 8 | constructor (format) { 9 | super(`${format} config file not supported`) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | import { 2 | ContainerBuilder, 3 | YamlFileLoader, 4 | JsFileLoader, 5 | JsonFileLoader 6 | } from 'node-dependency-injection' 7 | import path from 'path' 8 | import ExtensionConfigurationFileNameException from 9 | './exception/ExtensionConfigurationFileNameException' 10 | 11 | /** 12 | * Dependency Injection middleware 13 | */ 14 | export default class Index { 15 | /** 16 | * @param {string} serviceFilePath 17 | * @param {boolean} compile 18 | * @param {[]} compilerPass 19 | * @param {*} logger 20 | * @param {boolean} containerReferenceAsService 21 | * @param {String} defaultDir 22 | * @return {Index.middleware} 23 | */ 24 | constructor ({ 25 | serviceFilePath, compile = false, compilerPass = [], 26 | logger = null, containerReferenceAsService = false, defaultDir = null 27 | }) { 28 | this._container = new ContainerBuilder(containerReferenceAsService, 29 | defaultDir) 30 | this.serviceFilePath = serviceFilePath 31 | for (const pass of compilerPass) { 32 | this._container.addCompilerPass(pass) 33 | } 34 | if (logger) { 35 | this._container.logger = logger 36 | } 37 | if (compile) { 38 | this._container.compile() 39 | } 40 | } 41 | 42 | /** 43 | * @param {string} serviceFilePath 44 | */ 45 | set serviceFilePath (serviceFilePath) { 46 | const extName = path.extname(serviceFilePath).replace('.', '') 47 | const loader = this._getLoader(extName) 48 | loader.load(serviceFilePath) 49 | } 50 | 51 | /** 52 | * @param extName 53 | * @return {YamlFileLoader|JsFileLoader|JsonFileLoader|FileLoader} 54 | * @private 55 | */ 56 | _getLoader (extName) { 57 | switch (extName) { 58 | case 'yaml': 59 | case 'yml': 60 | return new YamlFileLoader(this._container) 61 | case 'js': 62 | return new JsFileLoader(this._container) 63 | case 'json': 64 | return new JsonFileLoader(this._container) 65 | } 66 | 67 | throw new ExtensionConfigurationFileNameException( 68 | `${extName} is not supported`) 69 | } 70 | 71 | /** 72 | * @return {ContainerBuilder} 73 | */ 74 | get container () { 75 | return this._container 76 | } 77 | 78 | /** 79 | * @return {function} 80 | */ 81 | middleware () { 82 | return (req, res, next) => { 83 | req.container = this._container 84 | next() 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-dependency-injection-express-middleware", 3 | "version": "1.2.2", 4 | "description": "Node Dependency Injection Express Middleware", 5 | "main": "dist/index.js", 6 | "scripts": { 7 | "test": "cross-env NODE_ENV=test mocha", 8 | "test:coverage": "cross-env NODE_ENV=test nyc --reporter=lcov --reporter=text mocha", 9 | "test:standard": "standard", 10 | "test:standard:fix": "standard --fix", 11 | "build": "rm -rf dist/* && babel lib -d dist", 12 | "report:coverage": "nyc report --reporter=text-lcov > coverage.lcov && codecov", 13 | "preversion": "npm run test:standard && npm test", 14 | "version": "npm run build", 15 | "postversion": "git push && git push --tags && npm publish" 16 | }, 17 | "repository": { 18 | "type": "git", 19 | "url": "git+https://github.com/zazoomauro/node-dependency-injection-express-middleware.git" 20 | }, 21 | "keywords": [ 22 | "express", 23 | "middleware", 24 | "node", 25 | "dependency", 26 | "injection", 27 | "service", 28 | "container", 29 | "console", 30 | "inversion-of-control", 31 | "service-locator" 32 | ], 33 | "author": "Mauro Gadaleta ", 34 | "license": "MIT", 35 | "bugs": { 36 | "url": "https://github.com/zazoomauro/node-dependency-injection-express-middleware/issues" 37 | }, 38 | "homepage": "https://github.com/zazoomauro/node-dependency-injection-express-middleware#readme", 39 | "dependencies": { 40 | "node-dependency-injection": "^2.4.5", 41 | "path": "^0.12.7" 42 | }, 43 | "devDependencies": { 44 | "@babel/cli": "^7.7.7", 45 | "@babel/core": "^7.7.7", 46 | "@babel/preset-env": "^7.7.7", 47 | "@babel/register": "^7.7.7", 48 | "babel-plugin-istanbul": "^6.0.0", 49 | "chai": "^4.1.2", 50 | "codecov": "^3.6.1", 51 | "cross-env": "^7.0.2", 52 | "eslint": "^6.8.0", 53 | "eslint-config-standard": "^14.1.0", 54 | "eslint-config-standard-jsx": "^8.1.0", 55 | "eslint-plugin-promise": "^4.2.1", 56 | "eslint-plugin-react": "^7.17.0", 57 | "eslint-plugin-standard": "^4.0.1", 58 | "express": "^4.17.1", 59 | "istanbul": "^0.4.5", 60 | "mocha": "^7.1.1", 61 | "nyc": "^15.0.0", 62 | "standard": "^14.3.1" 63 | }, 64 | "babel": { 65 | "presets": [ 66 | "@babel/preset-env" 67 | ], 68 | "env": { 69 | "test": { 70 | "plugins": [ 71 | "istanbul" 72 | ] 73 | } 74 | } 75 | }, 76 | "nyc": { 77 | "sourceMap": false, 78 | "instrument": false 79 | }, 80 | "false": {} 81 | } 82 | -------------------------------------------------------------------------------- /test/lib/DependencyInjectionMiddleware.spec.js: -------------------------------------------------------------------------------- 1 | /* global describe, beforeEach, it */ 2 | 3 | import express from 'express' 4 | import Index from '../../lib/' 5 | import path from 'path' 6 | import chai from 'chai' 7 | import FooPass from '../lib/FooPass' 8 | import { ContainerBuilder } from 'node-dependency-injection' 9 | 10 | const assert = chai.assert 11 | 12 | describe('DependencyInjectionMiddleware', () => { 13 | let app 14 | let options 15 | 16 | beforeEach(() => { 17 | app = express() 18 | options = { 19 | serviceFilePath: path.join(__dirname, '..', 'resources', 'services.yml') 20 | } 21 | }) 22 | 23 | describe('middleware', () => { 24 | it('should throw an exception if service extension file is not supported', 25 | () => { 26 | // Arrange. 27 | options.serviceFilePath = 'foo.bar' 28 | 29 | // Act. 30 | const actual = () => app.use( 31 | new Index(options).middleware()) 32 | 33 | // Assert. 34 | return assert.throw(actual, 'bar is not supported') 35 | }) 36 | 37 | it('should load a valid yaml file', () => { 38 | // Arrange. 39 | options.serviceFilePath = path.join(__dirname, '..', 'resources', 40 | 'services.yml') 41 | 42 | // Act. 43 | const actual = () => app.use( 44 | new Index(options).middleware()) 45 | 46 | // Assert. 47 | return assert.doesNotThrow(actual) 48 | }) 49 | 50 | it('should load a valid js file', () => { 51 | // Arrange. 52 | options.serviceFilePath = path.join(__dirname, '..', 'resources', 53 | 'services.js') 54 | 55 | // Act. 56 | const actual = () => app.use( 57 | new Index(options).middleware()) 58 | 59 | // Assert. 60 | return assert.doesNotThrow(actual) 61 | }) 62 | 63 | it('should load a valid json file', () => { 64 | // Arrange. 65 | options.serviceFilePath = path.join(__dirname, '..', 'resources', 66 | 'services.json') 67 | 68 | // Act. 69 | const actual = () => app.use( 70 | new Index(options).middleware()) 71 | 72 | // Assert. 73 | return assert.doesNotThrow(actual) 74 | }) 75 | 76 | it('should compile container if flag is true', () => { 77 | // Arrange. 78 | options.compile = true 79 | 80 | // Act. 81 | const actual = () => app.use( 82 | new Index(options).middleware()) 83 | 84 | // Assert. 85 | return assert.doesNotThrow(actual) 86 | }) 87 | 88 | it('should add compiler pass to container', () => { 89 | // Arrange. 90 | options.compilerPass = [new FooPass()] 91 | options.compile = true 92 | 93 | // Act. 94 | const actual = () => app.use( 95 | new Index(options).middleware()) 96 | 97 | // Assert. 98 | return assert.doesNotThrow(actual) 99 | }) 100 | 101 | it('should add logger to container', () => { 102 | // Arrange. 103 | options.logger = { 104 | warn: () => { 105 | } 106 | } 107 | 108 | // Act. 109 | const actual = () => app.use( 110 | new Index(options).middleware()) 111 | 112 | // Assert. 113 | return assert.doesNotThrow(actual) 114 | }) 115 | }) 116 | 117 | describe('container', () => { 118 | it('should get a container builder instance', () => { 119 | // Arrange not needed. 120 | 121 | // Act. 122 | const actual = new Index(options).container 123 | 124 | // Assert. 125 | return assert.instanceOf(actual, ContainerBuilder) 126 | }) 127 | }) 128 | }) 129 | -------------------------------------------------------------------------------- /test/lib/FooPass.js: -------------------------------------------------------------------------------- 1 | export default class FooPass { 2 | /** 3 | * @param {ContainerBuilder} container 4 | */ 5 | process (container) { 6 | // ... do something during the compilation 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /test/resources/services.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | services: {} 3 | } 4 | -------------------------------------------------------------------------------- /test/resources/services.json: -------------------------------------------------------------------------------- 1 | { 2 | "services": {} 3 | } -------------------------------------------------------------------------------- /test/resources/services.yml: -------------------------------------------------------------------------------- 1 | services: --------------------------------------------------------------------------------