amw

1.0.0 • Public • Published

AMW - Another Module Wiring

Smart module wiring using dependency injection container

This library can be used as a framework for your modern java script projects.

Installation

npm install amw

Importing

// Using Node.js `require()`
const {Wire} = require('amw');

Overview

Define dependencies

First, we need to define the dependencies we want in our app. create a file di.js and here is our dependencies for the app.

// di.js
const message = config => message => {
 if (config.pre_message) {
  return `${config.pre_message} ${message}`
 }
 return `${message}`
}
 
class MathOps {
 
 add(num1, num2) {
  return num1 + num2
 }
 
 sub(num1, num2) {
  return num1 - num2
 }
 
}
 
module.exports = {
 'message': {
  factory: config => message(config.message)
 },
 
 'mathOps': {
  factory: () => new MathOps()
 },
 
 'main': {
  factory: (mathOps, message) => () => {
   const result = mathOps.sub(mathOps.add(5, 4), 3)
 
   return message(result)
  },
  tags: ['main']
 }
}

each dependency should have a unique name, here we have 3 dependencies message, mathOps and main.

each dependency shall have the following attributes

1- factory: a factory function that should return a function or an object instance, and this way we can ensure only single instance per application for each dependency.

the factory arguments can be our defined services like the case of the main factory function as it expects both mathOps and message services as arguments.

there is another argument that we can access which is the config argument, and that is the configuration exported by our config.js file. check the Define Config section.

2- tags: an array of tags, we can use to group services under the same tag for fast access, the main tag is reserved for the main service only.

Define Config

The config file is where we can keep our configuration for all our services in the same place. in this file we need to export an object of service configuration.

// config.js
module.exports = {
 message: {
  pre_message: 'result is:'
 }
}

here we just have configuration for the message service, and we use it in the message factory function.

Wiring services

Next we need to wire all those services and start our application, we shall do that in main.js file

// main.js
const {Wire} = require('amw');
const DI_FILE_LOCATION = ''; // location of di.js file
const CONFIG_FILE_LOCATION = ''; // location of config.js file
 
// define new wire instance
const wireInstance = new Wire(DI_FILE_LOCATION, CONFIG_FILE_LOCATION)
 
// connect dependencies defined in di.js
const container = wire.connect()
 
// get the main service
const main = container.getMainService()
 
// call the main function
main()

next run

$ node main.js
// result is: 6

the connect function returns a container object that we used to get the main service and call it. the container has other useful functions.

Container

The container contains all services defined in di.js, and it is used internally to register the services defined when we called wire.connect(), but it can also be used externally for service registration.

Methods

container.register(name, service)

Register new service

Kind: instance method of Container

Param Type Description
name string Service name.
service number Service object
service.dependency * Whatever you want.
service.factory function factory function
[service.tags] Array.<string> tags array

Example

// register dependency
container.register('secret', {
    dependency: 'some secret'
})

Example

// register factory with tag
container.register('logger', {
    factory: (secret) => {
        return () => {
            console.log('secret is:', secret)
        }
    },
    tags: ['logger']
})

container.getService(name) ⇒ *

Get service by name

Kind: instance method of Container Returns: * - service - Registered service

Param Type Description
name string Service name.

Example

// get dependency
const secret = container.getService('secret')
// secret = 'some-secret'

Example

// get factory
const logger = container.getService('logger')
logger()
// secret is: some-secret

container.getMainService() ⇒ *

Get main service

Kind: instance method of Container Returns: * - service - Registered service with tag 'main'

container.getTaggedServices(tag) ⇒ *

Get services by tag

Kind: instance method of Container Returns: * - services - array of services

Param Type Description
tag string Service tag.

More info

If you are interested to learn more cool design patterns in node.js I recommend this book Node.js Design Patterns by Mario Casciaro and Luciano Mammino.

Package Sidebar

Install

npm i amw

Weekly Downloads

1

Version

1.0.0

License

ISC

Unpacked Size

25.1 kB

Total Files

12

Last publish

Collaborators

  • mgundour