• Stars
    star
    563
  • Rank 79,150 (Top 2 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created about 11 years ago
  • Updated almost 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Elegant dependency injection for Node.js.

Electrolyte

Build Coverage Quality Dependencies

Electrolyte is a simple, lightweight inversion of control (IoC) container for Node.js applications.

Electrolyte automatically wires together the various components and services needed by an application. It does this using a technique known as dependency injection (DI). Using Electrolyte eliminates boilerplate code and improves software quality by encouraging loose coupling between modules, resulting in greater reusability and increased test coverage.

For further details about the software architecture used for IoC and dependency injection, refer to Inversion of Control Containers and the Dependency Injection pattern by Martin Fowler.

Install

$ npm install electrolyte

Usage

There are two important terms to understand when using Electrolyte: components and annotations.

Components

Components are simply modules which return objects used within an application. For instance, a typical web application might need a place to store settings, a database connection, and a logging facility.

Here's a component that initializes settings:

exports = module.exports = function() {
  var settings = {}
    , env = process.env.NODE_ENV || 'development';

  switch (env) {
    case 'production':
      settings.dbHost = 'sql.example.com';
      settings.dbPort = 3306;
      break;
    default:
      settings.dbHost = '127.0.0.1';
      settings.dbPort = 3306;
      break;
  }

  return settings;
}

exports['@singleton'] = true;

Pretty simple. A component exports a "factory" function, which is used to create and initialize an object. In this case, it just sets a couple options depending on the environment.

What about exports['@singleton']? That's an annotation, and we'll return to that in a moment.

Here's another component that initializes a database connection (saved as 'database.js'):

var mysql = require('mysql');

exports = module.exports = function(settings) {
  var connection = mysql.createConnection({
    host: settings.dbHost,
    port: settings.dbPort
  });

  connection.connect(function(err) {
    if (err) { throw err; }
  });

  return connection;
}

exports['@singleton'] = true;
exports['@require'] = [ 'settings' ];

Also very simple. A function is exported which creates a database connection. And those annotations appear again.

Async Components

Async components are defined in an identical manner to traditional components except that the factory function should return a promise.

Let's rewrite the database component above slightly to return a promise.

var mysql = require('mysql');

exports = module.exports = function(settings) {
  return mysql.connectAsPromise({
    host: settings.dbHost,
    port: settings.dbPort
  }).then(function (conn) {
    // do something clever
    return conn;
  });
}

exports['@singleton'] = true;
exports['@require'] = [ 'settings' ];

Let's also define a users model that relies on the database component (saved as users.js).

exports = module.exports = function(database) {
  return {
    create: function (name, email, password) {
      return database.execute('INSERT INTO users ...');
    }
  };
}

exports['@singleton'] = true;
exports['@require'] = [ 'database' ];

Annotations

Annotations provide an extra bit of metadata about the component, which Electrolyte uses to automatically wire together an application.

  • @require Declares an array of dependencies needed by the component. These dependencies are automatically created and injected as arguments (in the same order as listed in the array) to the exported function.

  • @singleton Indicates that the component returns a singleton object, which should be shared by all components in the application.

Creating Components

Components are created by asking the IoC container to create them:

var IoC = require('electrolyte');

var db = IoC.create('database');

Electrolyte is smart enough to automatically traverse a component's dependencies (and dependencies of dependencies, and so on), correctly wiring together the complete object structure.

In the case of the database above, Electrolyte would first initialize the settings component, and pass the result as an argument to the database component. The database connection would then be returned from IoC.create.

This automatic instantiation and injection of components eliminates the boilerplate plumbing many application need for initialization.

Creating Async Components

Again, components are created by asking the IoC container to create them:

var IoC = require('electrolyte');

var usersPromise = IoC.createAsync('users');

usersPromise.then(function (users) {
  ...
});

Here as well electrolyte is smart enough to automatically traverse a component's dependencies, correctly wiring together the complete object structure and waiting for each promise to resolve along the way.

In the case of the users model above, Electrolyte would first initialize the settings component, and pass the result as an argument to the database component. Electrolyte would then wait for the database connection promise to resolve before passing the resulting value to the users component. IoC.createAsync then returns a promise that resolves to the object defined by the users component after the all of its dependencies resolve.

Configure the Loader

When a component is @require'd by another component, Electrolyte will automatically load and instantiate it. The loader needs to be configured with location where an application's components are found:

IoC.use(IoC.dir('app/components'));

@require vs require()

Loading components is similar in many regards to requireing a module, with one primary difference: components have the ability to return an object that is configured according to application-level or environment-specific settings. Traditional modules, in contrast, assume very little about the runtime configuration of an application and export common, reusable bundles of functionality.

Using the strengths of each approach yields a nicely layered architecture, which can be seen in the database component above. The mysql module provides reusable functionality for communicating with MySQL databases. The database component provides a configured instance created from that module that connects to a specific database.

This pattern is common: modules are require()'d, and object instances created from those modules are @require'd.

There are scenarios in which this line can blur, and it becomes desireable to inject modules themselves. This is typical with modules that provide network-related functionality that needs to be mocked out in test environments.

Electrolyte can be configured to do this automatically, by configuring the loader to inject modules:

IoC.use(IoC.node_modules());

With that in place, the database component above can be re-written as follows:

exports = module.exports = function(mysql, settings) {
  var connection = mysql.createConnection({
    host: settings.dbHost,
    port: settings.dbPort
  });

  connection.connect(function(err) {
    if (err) { throw err; }
  });

  return connection;
}

exports['@singleton'] = true;
exports['@require'] = [ 'mysql', 'settings' ];

Note that now the mysql module is injected by Electrolyte, rather than explicitly require()'d. This makes it easy to write tests for this component while mocking out network access entirely.

Examples

  • Express An example Express app using IoC to create routes, with necessary components.

  • Async Express An example Express app using IoC to create routes asynchronously, with necessary components.

Tests

$ npm install
$ npm test

Credits

License

The MIT License

Copyright (c) 2013 Jared Hanson <http://jaredhanson.net/>

More Repositories

1

passport

Simple, unobtrusive authentication for Node.js.
JavaScript
21,911
star
2

oauth2orize

OAuth 2.0 authorization server toolkit for Node.js.
JavaScript
3,417
star
3

passport-local

Username and password authentication strategy for Passport and Node.js.
JavaScript
2,669
star
4

passport-facebook

Facebook authentication strategy for Passport and Node.js.
JavaScript
1,281
star
5

connect-flash

Flash message middleware for Connect and Express.
JavaScript
1,225
star
6

passport-http-bearer

HTTP Bearer authentication strategy for Passport and Node.js.
JavaScript
946
star
7

locomotive

Powerful MVC web framework for Node.js.
JavaScript
892
star
8

passport-google-oauth2

Google authentication strategy for Passport and Node.js.
JavaScript
808
star
9

passport-google-oauth

Google authentication strategies for Passport and Node.js.
JavaScript
753
star
10

passport-oauth2

OAuth 2.0 authentication strategy for Passport and Node.js.
JavaScript
575
star
11

passport-github

GitHub authentication strategy for Passport and Node.js.
JavaScript
528
star
12

passport-twitter

Twitter authentication strategy for Passport and Node.js.
JavaScript
467
star
13

connect-ensure-login

Login session ensuring middleware for Connect and Express.
JavaScript
465
star
14

passport-http

HTTP Basic and Digest authentication strategies for Passport and Node.js.
JavaScript
265
star
15

passport-remember-me

Remember Me cookie authentication strategy for Passport and Node.js
JavaScript
217
star
16

oauthorize

OAuth service provider toolkit for Node.js.
JavaScript
200
star
17

deamdify

Browserify transform that converts AMD to CommonJS.
JavaScript
198
star
18

passport-openidconnect

OpenID Connect authentication strategy for Passport and Node.js.
JavaScript
181
star
19

passport-instagram

Instagram authentication strategy for Passport and Node.js.
JavaScript
172
star
20

passport-totp

TOTP authentication strategy for Passport and Node.js.
JavaScript
147
star
21

passport-google

Google (OpenID) authentication strategy for Passport and Node.js.
JavaScript
146
star
22

passport-linkedin

LinkedIn authentication strategy for Passport and Node.js.
JavaScript
141
star
23

passport-oauth

OAuth 1.0 and 2.0 authentication strategies for Passport and Node.js.
JavaScript
117
star
24

passport-strategy

An abstract class implementing Passport's strategy API.
Makefile
107
star
25

junction

Essential XMPP middleware for Node.js.
JavaScript
105
star
26

passport-openid

OpenID authentication strategy for Passport and Node.js.
JavaScript
100
star
27

passport-oauth2-client-password

OAuth 2.0 client password authentication strategy for Passport and Node.js.
JavaScript
96
star
28

kerouac

Poetic static site generator for Node.js.
JavaScript
82
star
29

utils-merge

merge() utility function
JavaScript
71
star
30

passport-http-oauth

HTTP OAuth authentication strategy for Passport and Node.js.
JavaScript
70
star
31

bootable

Easy application initialization for Node.js.
JavaScript
68
star
32

oauth2orize-openid

Extensions to support OpenID Connect with OAuth2orize.
JavaScript
62
star
33

passport-anonymous

Anonymous authentication strategy for Passport and Node.js.
Makefile
59
star
34

passport-browserid

BrowserID authentication strategy for Passport and Node.js.
JavaScript
53
star
35

passport-webauthn

WebAuthn authentication strategy for Passport.
JavaScript
45
star
36

passport-soundcloud

SoundCloud authentication strategy for Passport and Node.js.
JavaScript
38
star
37

passport-amazon

Amazon authentication strategy for Passport and Node.js.
JavaScript
37
star
38

node-parent-require

Require modules from parent modules.
JavaScript
35
star
39

passport-windowslive

Windows Live authentication strategy for Passport and Node.js.
JavaScript
34
star
40

chai-passport-strategy

Helpers for testing Passport strategies with the Chai assertion library.
JavaScript
33
star
41

passport-fitbit

Fitbit authentication strategy for Passport and Node.js.
JavaScript
32
star
42

passport-tumblr

Tumblr authentication strategy for Passport and Node.js.
JavaScript
30
star
43

passport-dropbox

Dropbox authentication strategy for Passport and Node.js.
JavaScript
29
star
44

passport-paypal-oauth

PayPal (OAuth) authentication strategy for Passport and Node.js.
JavaScript
28
star
45

passport-bitbucket

Bitbucket authentication strategy for Passport and Node.js.
JavaScript
26
star
46

passport-oauth1

OAuth 1.0 authentication strategy for Passport and Node.js.
JavaScript
23
star
47

passport-foursquare

Foursquare authentication strategy for Passport and Node.js.
JavaScript
22
star
48

node-notifications

A mechanism for dispatching notifications within a Node.js program.
JavaScript
22
star
49

passport-goodreads

Goodreads authentication strategy for Passport and Node.js.
JavaScript
21
star
50

passport-yahoo-oauth

Yahoo! (OAuth) authentication strategy for Passport and Node.js.
JavaScript
19
star
51

passport-persona

Mozilla Persona authentication strategy for Passport and Node.js.
JavaScript
19
star
52

locomotive-mongoose

Mongoose datastore adapter for Locomotive.
JavaScript
18
star
53

passport-runkeeper

RunKeeper authentication strategy for Passport and Node.js.
JavaScript
18
star
54

node-jsonsp

JSON stream parser for Node.js.
JavaScript
17
star
55

node-jsonrpc-tcp

JSON-RPC over TCP for Node.js.
JavaScript
16
star
56

passport-intuit-oauth

Intuit (OAuth) authentication strategy for Passport and Node.js.
JavaScript
15
star
57

passport-evernote

Evernote authentication strategy for Passport and Node.js.
JavaScript
15
star
58

passport-ethereum

Ethereum authentication strategy for Passport.
JavaScript
15
star
59

passport-meetup

Meetup authentication strategy for Passport and Node.js.
JavaScript
15
star
60

passport-google-openidconnect

Google authentication strategy for Passport and Node.js.
JavaScript
14
star
61

crane

Diligent work queue for Node.js.
JavaScript
13
star
62

rivet

Efficient build tool utilizing JavaScript and Node.js.
JavaScript
13
star
63

connect-powered-by

X-Powered-By header middleware for Connect.
JavaScript
11
star
64

passport-yammer

Yammer authentication strategy for Passport and Node.js.
JavaScript
11
star
65

passport-hotp

HOTP authentication strategy for Passport and Node.js.
JavaScript
11
star
66

passport-paypal

PayPal (OpenID) authentication strategy for Passport and Node.js.
JavaScript
10
star
67

passport-intuit

Intuit (OpenID) authentication strategy for Passport and Node.js.
JavaScript
10
star
68

js-sasl

SASL mechanism factory.
JavaScript
10
star
69

node-tokens

Encode and decode security tokens.
JavaScript
9
star
70

draft-oauth-mfa

9
star
71

passport-openstreetmap

OpenStreetMap authentication strategy for Passport and Node.js.
JavaScript
9
star
72

node-servicelocator

Central location to register and locate services within a Node.js application.
JavaScript
9
star
73

passport-dwolla

Dwolla authentication strategy for Passport and Node.js.
JavaScript
9
star
74

todos-fastify-sqlite

Todo app built with Node.js, Fastify, and SQLite.
CSS
9
star
75

passport-angellist

AngelList authentication strategy for Passport and Node.js.
JavaScript
8
star
76

make-node

Useful makefiles for developing Node.js packages.
Makefile
8
star
77

chai-connect-middleware

Helpers for testing Connect middleware with the Chai assertion library.
JavaScript
8
star
78

todos-express-sqlite

Todo app built with Node.js, Express, and SQLite.
CSS
7
star
79

passport-familysearch

FamilySearch authentication strategy for Passport and Node.js.
JavaScript
7
star
80

oauth2orize-mfa

Multi-Factor Authentication exchanges for OAuth2orize.
JavaScript
6
star
81

flowstate

Per-request state management middleware.
JavaScript
6
star
82

suitcss-utils-space

Utility classes for low-level CSS spacing traits
CSS
6
star
83

passport-fido-u2f

FIDO U2F authentication strategy for Passport and Node.js.
JavaScript
6
star
84

passport-rdio

Rdio authentication strategy for Passport and Node.js.
JavaScript
6
star
85

passport-37signals

37signals authentication strategy for Passport and Node.js.
JavaScript
6
star
86

oauth2orize-pkce

Extensions to support Proof Key for Code Exchange with OAuth2orize.
JavaScript
6
star
87

node-ffi-ipmi

wrapping various ipmi related tools and libs for node via node-ffi @ https://github.com/rbranson/node-ffi.git
C
6
star
88

node-functionpool

Provides a pool of functions that can be used to execute tasks in Node.js.
JavaScript
5
star
89

connect-lrdd

Link-based Resource Descriptor Document (LRDD) middleware for Connect.
JavaScript
5
star
90

dotfiles

$HOME
Shell
5
star
91

passport-vimeo

Vimeo authentication strategy for Passport and Node.js.
JavaScript
5
star
92

amd-resolve

A hookable AMD module resolution implementation.
JavaScript
5
star
93

passport-ssl-certificate

SSL certificate authentication strategy for Passport and Node.js.
JavaScript
5
star
94

node-nks-fs

Secure key services.
JavaScript
5
star
95

marked-engine

Express-compatible Markdown rendering powered by marked.
JavaScript
5
star
96

chai-oauth2orize-grant

Helpers for testing OAuth2orize grants with the Chai assertion library.
JavaScript
5
star
97

oauth2orize-device-code

Extensions to support device flow with OAuth2orize.
JavaScript
5
star
98

oauth2orize-redelegate

Token redelegation and chaining exchange for OAuth2orize.
JavaScript
5
star
99

passport-web3

Web3 authentication strategy for Passport.
JavaScript
5
star
100

pocket

A simple, small, file system-based data store for Node.js.
JavaScript
4
star