包详细信息

knifecycle

nfroidure244.4kMIT19.1.1

Manage your NodeJS processes's lifecycle automatically with an unobtrusive dependency injection implementation.

process, lifecycle, shutdown, dependencies

自述文件

knifecycle

Manage your NodeJS processes's lifecycle automatically with an unobtrusive dependency injection implementation.

GitHub license

The Knifecycle logo

Most (maybe all) applications rely on two kinds of dependencies.

The lifecycle of most (all?) applications

The code dependencies are fully covered by JavaScript modules in a testable manner (with mockery or System directly). There is no need for another dependency management system if those libraries are pure functions (involve no global states at all).

Unfortunately, applications often rely on global states where the JavaScript module system shows its limits. This is where knifecycle enters the game.

The app lifecycle sequence graph

It is largely inspired by the Angular service system except it should not provide code but access to global states (time, filesystem, db). It also have an important additional feature to shutdown processes which is really useful for back-end servers and doesn't exists in Angular.

Last but not least, you can build your code with Knifecycle so that once in production, it do not have to resolve the dependency tree leading to better performances and reduce the bundle size (especially for tools like AWS Lambda / GCP Functions where each endpoint has its own zip).

You may want to look at the architecture notes to better handle the reasonning behind knifecycle and its implementation.

At this point you may think that a DI system is useless. My advice is that it depends. But at least, you should not make a definitive choice and allow both approaches, Knifecycle permits this, most modules made usable by Knifecycle can in fact be used without it (this is also why static build works). See this blog post for more context about this statement.

Features

  • services management: start services taking their dependencies in count and shut them down the same way for graceful exits (namely dependency injection with inverted control),
  • singleton: maintain singleton services across several running execution silos,
  • easy end to end testing: just replace your services per your own mocks and stubs while ensuring your application integrity between testing and production,
  • isolation: isolate processing in a clean manner, per concerns;
  • functional programming ready: encapsulate global states allowing the rest of your application to be purely functional,
  • no circular dependencies for services: while circular dependencies are not a problem within purely functional libraries (require allows it), it may be harmful for your services, knifecycle impeach that while providing an $injector service à la Angular to allow accessing existing services references if you really need to,
  • generate Mermaid graphs of the dependency tree,
  • auto-detect injected services names,
  • build raw initialization modules to avoid embedding Knifecycle in your builds,
  • optionally autoload services dependencies with custom logic.

You can find all Knifecycle comptabile modules on NPM with the knifecycle keyword.

Usage

Using knifecycle is all about declaring the services our application needs and running your application over it.

Let's say we are building a CLI script. Here is how we would proceed with Knifecycle:

// bin.js
import fs from 'fs';
import { YError } from 'YError';
import {
  Knifecycle,
  initializer,
  constant,
  inject,
  name
} from 'knifecycle';

// First of all we create a new Knifecycle instance
const $ = new Knifecycle();

// Some of our code with rely on the process environment
// let's inject it as a constant instead of directly
// pickking env vars in `process.env` to make our code
// easily testable
$.register(constant('ENV', process.env));

// Let's do so for CLI args with another constant
// in real world apps we would have created a service
// that would parse args in a complexer way
$.register(constant('ARGS', process.argv));

// We want our CLI tool to rely on some configuration
// Let's build an injectable service initializer that
// reads environment variables via an injected but
// optional `ENV` object
// In a real world app, you may use the
// `application-services` module services instead.
async function initConfig({ ENV = { CONFIG_PATH: '.' } }) {
  await fs.promises.readFile(
    ENV.CONFIG_PATH,
    'utf-8',
    (err, data) => {
      if (err) {
        reject(err);
        return;
      }
      try {
        resolve(JSON.parse(data));
      } catch (err) {
        reject(err);
      }
    },
  );
}

// We are using the `initializer` decorator to
// declare our service initializer specificities
// and register it with our Knifecycle instance
$.register(
  initializer(
    {
      // we have to give our final service a name
      // for further use in other services injections
      name: 'CONFIG',
      // we will need an `ENV` variable in the initializer
      // so adding it in the injected dependencies. The `?`
      // sign tells Knifecycle that the ENV dependency
      // is optional
      inject: ['?ENV'],
      // our initializer is simple so we use the `service`
      // type for the initializer which just indicate that
      // the initializer will return a promise of the actual
      // service
      type: 'service',
      // We don't want to read the config file everytime we
      // inject it so declaring it as a singleton
      singleton: true,
    },
    initConfig,
  ),
);

// Our CLI also uses a database so let's write an
// initializer for it (in a real world app you
// can use `postgresql-service` instead):
const initDB = initializer(
  {
    name: 'db',
    // Here we are injecting the previous `CONFIG` service
    // as required so that our DB cannot be connected without
    // having a proper config.
    inject: ['CONFIG', 'DB_URI', '?log'],
    // The initializer type is slightly different. Indeed,
    // we need to manage the database connection errors
    // and wait for it to flush before shutting down the
    // process.
    // A service provider returns a promise of a provider
    // descriptor exposing:
    // - a mandatory `service` property containing the
    // actual service;
    // - an optional `dispose` function allowing to
    // gracefully close the service;
    // - an optional `fatalErrorPromise` property to
    // handle the service unrecoverable failure.
    type: 'provider',
    singleton: true,
  },
  async ({ CONFIG, DB_URI, log }) => {
    const db = await MongoClient.connect(DB_URI, CONFIG.databaseOptions);
    let fatalErrorPromise = new Promise((resolve, reject) => {
      db.once('error', reject);
    });

    // Logging only if the `log` service is defined
    log && log('info', 'db service initialized!');

    return {
      service: db,
      dispose: db.close.bind(db, true),
      fatalErrorPromise,
    };
  },
);

// Here we are registering our initializer apart to
// be able to reuse it, we also declare the required
// DB_URI constant it needs
$.register(constant('DB_URI', 'posgresql://xxxx'));
$.register(initDB);

// Say we need to use two different DB server
// We can reuse our initializer by tweaking
// some of its properties
$.register(constant('DB_URI2', 'posgresql://yyyy'));
$.register(
  // First we remap the injected dependencies. It will
  // take the `DB_URI2` constant and inject it as
  // `DB_URI`
  inject(
    ['CONFIG', 'DB_URI2>DB_URI', '?log'],
    // Then we override its name to make it
    // available as a different service
    name('db2', initDB),
  ),
);

// A lot of NodeJS functions have some side effects
// declaring them as constants allows you to easily
// mock/monitor/patch it. The `common-services` NPM
// module contains a few useful ones
$.register(constant('now', Date.now.bind(Date)))
  .register(constant('log', console.log.bind(console)))
  .register(constant('exit', process.exit.bind(process)));

// Finally, let's declare an `$autoload` service
// to allow us to load only the initializers needed
// to run the given commands
$.register(
  initializer(
    {
      name: '$autoload',
      type: 'service',
      inject: ['CONFIG', 'ARGS'],
      // Note that the auto loader must be a singleton
      singleton: true,
    },
    async ({ CONFIG, ARGS }) =>
      async (serviceName) => {
        if ('command' !== serviceName) {
          // Allows to signal that the dependency is not found
          // so that optional dependencies doesn't impeach the
          // injector to resolve the dependency tree
          throw new YError('E_UNMATCHED_DEPENDENCY', serviceName);
        }
        try {
          const path = CONFIG.commands + '/' + ARGS[2];
          return {
            path,
            initializer: require(path).default,
          };
        } catch (err) {
          throw new Error(`Cannot load ${serviceName}: ${ARGS[2]}!`);
        }
      },
  ),
);

// At this point, nothing is running. To instanciate the
// services, we have to create an execution silo using
// them. Note that we required the `$instance` service
// implicitly created by `knifecycle`
$.run(['command', '$instance', 'exit', 'log'])
  // Here, command contains the initializer eventually
  // found by automatically loading a NodeJS module
  // in the above `$autoload` service. The db connection
  // will only be instanciated if that command needs it
  .then(async ({ command, $instance, exit, log }) => {
    try {
      command();

      log('It worked!');
    } catch (err) {
      log('It failed!', err);
    } finally {
      // Here we ensure every db connections are closed
      // properly. We could have use `$.destroy()` the same
      // way but this is to illustrate that the Knifecycle
      // instance can be injected in services contexts
      // (rarely done but good to know it exists)
      await $instance.destroy().catch((err) => {
        console.error('Could not exit gracefully:', err);
        exit(1);
      });
    }
  })
  .catch((err) => {
    console.error('Could not launch the app:', err);
    process.exit(1);
  });

Running the following should make the magic happen:

cat "{ commands: './commands'}" > config.json
DEBUG=knifecycle CONFIG_PATH=./config.json node -r @babel/register bin.js mycommand test
// Prints: Could not launch the app: Error: Cannot load command: mycommand!
// (...stack trace)

Or at least, we still have to create commands, let's create the mycommand one:

// commands/mycommand.js
import { initializer } from './dist';

// A simple command that prints the given args
export default initializer(
  {
    name: 'command',
    type: 'service',
    // Here we could have injected whatever we declared
    // in the previous file: db, now, exit...
    inject: ['ARGS', 'log'],
  },
  async ({ ARGS, log }) => {
    return () => log('Command args:', ARGS.slice(2));
  },
);

So now, it works:

DEBUG=knifecycle CONFIG_PATH=./config.json node -r @babel/register bin.js mycommand test
// Prints: Command args: [ 'mycommand', 'test' ]
// It worked!

This is a very simple example but you can find a complexer CLI usage with (metapak)[https://github.com/nfroidure/metapak/blob/master/bin/metapak.js].

Auto detection

Knifecycle also provide some utility function to automatically assign the initializer property declarations, the following 3 ways to declare the getUser service are equivalent:

import noop from 'noop';
import { autoInject, inject, initializer, autoService } from 'knifecycle';

initializer({
  name: 'getUser',
  inject: ['db', '?log'],
  type: 'service',
}, getUser);

service('getUser', autoInject(getUser)));

autoService(getUser);

async function getUser({ db, log = noop}) {}

That said, if you need to build your code with webpack/babel you may have to convert auto-detections to raw declarations with the babel-plugin-knifecycle plugin. You can also do this only for the performance improvements it brings.

Also, keep in mind that the auto-detection is based on a simple regular expression so you should care to keep initializer signatures simple to avoid having a E_AUTO_INJECTION_FAILURE error. As a rule of thumb, avoid setting complex default values.

// Won't work
autoInject(async ({ log = () => {} }) => {});

// Will work
function noop() {}
autoInject(async ({ log = noop }) => {});

Debugging

Simply use the DEBUG environment variable by setting it to 'knifecycle':

DEBUG=knifecycle npm t

The output is very verbose but lead to a deep understanding of mechanisms that take place under the hood.

Plans

The scope of this library won't change. However the plan is:

  • improve performances;
  • track bugs ;).

I'll also share most of my own initializers and their stubs/mocks in order to let you reuse it through your projects easily. Here are the current projects that use this DI lib:

Notice that those modules remains usable without using Knifecycle at all which is maybe the best feature of this library 😉.

API

Classes

Knifecycle

Functions

initInitializerBuilder(services)Promise.<function()>

Instantiate the initializer builder service

initDispose()

Allow to dispose the services of an initialized silo content.

constant(name, value)function

Decorator that creates an initializer for a constant value

service(serviceBuilder, [name], [dependencies], [singleton], [extra])function

Decorator that creates an initializer from a service builder

autoService(serviceBuilder)function

Decorator that creates an initializer from a service builder by automatically detecting its name and dependencies

provider(providerBuilder, [name], [dependencies], [singleton], [extra])function

Decorator that creates an initializer for a provider builder

autoProvider(providerBuilder)function

Decorator that creates an initializer from a provider builder by automatically detecting its name and dependencies

parseDependencyDeclaration(dependencyDeclaration)Object

Explode a dependency declaration an returns its parts.

stringifyDependencyDeclaration(dependencyDeclarationParts)String

Stringify a dependency declaration from its parts.

Knifecycle

Kind: global class

new Knifecycle(options)

Create a new Knifecycle instance

Returns: Knifecycle - The Knifecycle instance

Param Type Description
options Object An object with options
options.sequential boolean Allows to load dependencies sequentially (usefull for debugging)

Example

import Knifecycle from 'knifecycle'

const $ = new Knifecycle();

knifecycle.register(initializer) ⇒ Knifecycle

Register an initializer

Kind: instance method of Knifecycle
Returns: Knifecycle - The Knifecycle instance (for chaining)

Param Type Description
initializer function An initializer

knifecycle.toMermaidGraph(options) ⇒ String

Outputs a Mermaid compatible dependency graph of the declared services. See Mermaid docs

Kind: instance method of Knifecycle
Returns: String - Returns a string containing the Mermaid dependency graph

Param Type Description
options Object Options for generating the graph (destructured)
options.shapes Array.<Object> Various shapes to apply
options.styles Array.<Object> Various styles to apply
options.classes Object A hash of various classes contents

Example

import Knifecycle, { inject, constant, service } from 'knifecycle';
import appInitializer from './app';

const $ = new Knifecycle();

$.register(constant('ENV', process.env));
$.register(constant('OS', require('os')));
$.register(service('app', inject(['ENV', 'OS'], appInitializer)));
$.toMermaidGraph();

// returns
graph TD
  app-->ENV
  app-->OS

knifecycle.run(dependenciesDeclarations) ⇒ Promise

Creates a new execution silo

Kind: instance method of Knifecycle
Returns: Promise - Service descriptor promise

Param Type Description
dependenciesDeclarations Array.<String> Service name.

Example

import Knifecycle, { constant } from 'knifecycle'

const $ = new Knifecycle();

$.register(constant('ENV', process.env));
$.run(['ENV'])
.then(({ ENV }) => {
 // Here goes your code
})

knifecycle.destroy() ⇒ Promise

Destroy the Knifecycle instance

Kind: instance method of Knifecycle
Returns: Promise - Full destruction promise
Example

import Knifecycle, { constant } from 'knifecycle'

const $ = new Knifecycle();

$.register(constant('ENV', process.env));
$.run(['ENV'])
.then(({ ENV }) => {
   // Here goes your code

   // Finally destroy the instance
   $.destroy()
})

initInitializerBuilder(services) ⇒ Promise.<function()>

Instantiate the initializer builder service

Kind: global function
Returns: Promise.<function()> - A promise of the buildInitializer function

Param Type Description
services Object The services to inject
services.$autoload Object The dependencies autoloader

Example

import initInitializerBuilder from 'knifecycle/dist/build';

const buildInitializer = await initInitializerBuilder({
  $autoload: async () => {},
});

initInitializerBuilder~buildInitializer(dependencies) ⇒ Promise.<String>

Create a JavaScript module that initialize a set of dependencies with hardcoded import/awaits.

Kind: inner method of initInitializerBuilder
Returns: Promise.<String> - The JavaScript module content

Param Type Description
dependencies Array.<String> The main dependencies

Example

import initInitializerBuilder from 'knifecycle/dist/build';

const buildInitializer = await initInitializerBuilder({
  $autoload: async () => {},
});

const content = await buildInitializer(['entryPoint']);

initDispose()

Allow to dispose the services of an initialized silo content.

Kind: global function

constant(name, value) ⇒ function

Decorator that creates an initializer for a constant value

Kind: global function
Returns: function - Returns a new constant initializer

Param Type Description
name String The constant's name.
value any The constant's value

Example

import Knifecycle, { constant, service } from 'knifecycle';

const { printAnswer } = new Knifecycle()
  .register(constant('THE_NUMBER', value))
  .register(constant('log', console.log.bind(console)))
  .register(service(
    async ({ THE_NUMBER, log }) => () => log(THE_NUMBER),
    'printAnswer',
    ['THE_NUMBER', 'log'],
  ))
  .run(['printAnswer']);

printAnswer(); // 42

service(serviceBuilder, [name], [dependencies], [singleton], [extra]) ⇒ function

Decorator that creates an initializer from a service builder

Kind: global function
Returns: function - Returns a new initializer

Param Type Description
serviceBuilder function An async function to build the service
[name] String The service's name
[dependencies] Array.<String> The service's injected dependencies
[singleton] Boolean Whether the service is a singleton or not
[extra] any Eventual extra information

Example

import Knifecycle, { constant, service } from 'knifecycle';

const { printAnswer } = new Knifecycle()
  .register(constant('THE_NUMBER', value))
  .register(constant('log', console.log.bind(console)))
  .register(service(
    async ({ THE_NUMBER, log }) => () => log(THE_NUMBER),
    'printAnswer',
    ['THE_NUMBER', 'log'],
    true
  ))
  .run(['printAnswer']);

printAnswer(); // 42

autoService(serviceBuilder) ⇒ function

Decorator that creates an initializer from a service builder by automatically detecting its name and dependencies

Kind: global function
Returns: function - Returns a new initializer

Param Type Description
serviceBuilder function An async function to build the service

provider(providerBuilder, [name], [dependencies], [singleton], [extra]) ⇒ function

Decorator that creates an initializer for a provider builder

Kind: global function
Returns: function - Returns a new provider initializer

Param Type Description
providerBuilder function An async function to build the service provider
[name] String The service's name
[dependencies] Array.<String> The service's dependencies
[singleton] Boolean Whether the service is a singleton or not
[extra] any Eventual extra information

Example

import Knifecycle, { provider } from 'knifecycle'
import fs from 'fs';

const $ = new Knifecycle();

$.register(provider(configProvider, 'config'));

async function configProvider() {
  return new Promise((resolve, reject) {
    fs.readFile('config.js', function(err, data) {
      let config;

      if(err) {
        reject(err);
        return;
      }

      try {
        config = JSON.parse(data.toString);
      } catch (err) {
        reject(err);
        return;
      }

      resolve({
        service: config,
      });
    });
  });
}

autoProvider(providerBuilder) ⇒ function

Decorator that creates an initializer from a provider builder by automatically detecting its name and dependencies

Kind: global function
Returns: function - Returns a new provider initializer

Param Type Description
providerBuilder function An async function to build the service provider

parseDependencyDeclaration(dependencyDeclaration) ⇒ Object

Explode a dependency declaration an returns its parts.

Kind: global function
Returns: Object - The various parts of it

Param Type Description
dependencyDeclaration String A dependency declaration string

Example

parseDependencyDeclaration('pgsql>db');
// Returns
{
  serviceName: 'pgsql',
  mappedName: 'db',
  optional: false,
}

stringifyDependencyDeclaration(dependencyDeclarationParts) ⇒ String

Stringify a dependency declaration from its parts.

Kind: global function
Returns: String - The various parts of it

Param Type Description
dependencyDeclarationParts Object A dependency declaration string

Example

stringifyDependencyDeclaration({
  serviceName: 'pgsql',
  mappedName: 'db',
  optional: false,
});

// Returns
'pgsql>db'

Authors

License

MIT

更新日志

19.1.1 (2025-05-12)

Bug Fixes

  • types: export injector type (7a70363)

19.1.0 (2025-05-12)

Features

  • build: allow to force a service to be constant (6563f43)

19.0.0 (2025-02-12)

18.0.0 (2024-12-04)

Features

  • core: add a location special property (9dd93ae), closes #136

BREAKING CHANGES

  • core: The build will need to be adapted to match this new feature. The autoloader service signature changed. Also the utils now provide a location decorator to allow you to create modules declaring their own location.

17.3.0 (2024-12-02)

Features

17.2.1 (2024-11-14)

Bug Fixes

  • build: align the build with overrides (688e5b0)

BREAKING CHANGES

  • build: Some builds could break but in the real world no build were made in such a short time frame.

17.2.0 (2024-11-14)

Features

  • core: allow to override some services (e17daed), closes #127

17.1.0 (2024-11-07)

Features

  • utils: add a way to uninject a dependency (7f90e65)

17.0.3 (2024-07-15)

17.0.2 (2024-05-28)

17.0.1 (2023-08-20)

Features

  • build: add a banner for generated files (97327e7)

17.0.0 (2023-08-20)

Enabling the build to use fatal error promises and to gracefully exit.

16.0.1 (2023-08-16)

16.0.0 (2023-08-16)

Bug Fixes

  • build: fix deps lock file (ab9114e)

15.0.1 (2023-05-28)

15.0.0 (2023-05-28)

14.1.0 (2022-08-30)

Bug Fixes

  • types: fix types according to the last TypeScript version (0873bff)

14.0.0 (2022-06-16)

13.0.0 (2022-06-12)

12.0.4 (2022-05-25)

12.0.3 (2022-05-25)

12.0.2 (2021-11-11)

12.0.1 (2021-11-01)

Bug Fixes

  • types: less strict registering (3453508)

12.0.0 (2021-11-01)

11.1.1 (2021-04-09)

Bug Fixes

  • docs: fix the readme on singletons (5e51fe9)

11.1.0 (2021-01-11)

Features

  • build: allow to either use esm or cjs (719ba37)

11.0.1 (2020-12-06)

Bug Fixes

  • build: fix build issues with constants (2d4d597)

11.0.0 (2020-11-22)

Bug Fixes

  • types: fix generic types initializer passthrough (773a913)

10.0.3 (2020-10-18)

Bug Fixes

10.0.2 (2020-09-15)

Bug Fixes

  • utils: fix optional dependencies merge (cadac91)

10.0.1 (2020-09-14)

Bug Fixes

  • utils: reexport injections utils (a94b734)

10.0.0 (2020-09-14)

Features

  • utils: allow object rest spread in autodected injections (846fde9)
  • utils: allow to reuse initializers injections (bc6873f)

9.1.1 (2020-04-02)

Bug Fixes

  • types: fix bad type declaration (21b3c7f)

9.1.0 (2020-04-01)

Features

  • core: add support for esm (bbb3491)

9.0.0 (2020-03-20)

8.1.0 (2020-01-19)

8.0.1 (2019-12-10)

8.0.0 (2019-12-07)

Bug Fixes

  • types: fix handler types (4d975df)

7.0.3 (2019-12-02)

Bug Fixes

  • types: use literals instead of onjects for strings (89a22f9)

7.0.2 (2019-12-01)

7.0.1 (2019-12-01)

7.0.0 (2019-11-28)

Bug Fixes

  • types: Fix types and optional parameters (e49c4e7), closes #104

6.0.0 (2019-03-15)

Code Refactoring

  • Chore: Better handling of optional dependencies (539eb47)

BREAKING CHANGES

  • Chore: Autoloaders needs to throw a E_UNMATCHED_DEPENDENCY error to still work with optional dependencies

5.3.0 (2019-03-03)

Bug Fixes

  • Debug: Fix the $injector debug message format (ae8510d)
  • Knifecycle: Take in count more errors for optional failures (6b5fab3), closes #83

Features

  • alsoInject: Dedupe injections when adding some (10e9d4f)

5.2.0 (2019-02-09)

Bug Fixes

  • $injector: Fix services mapping in the $injector (ee2a2bd)

Features

  • $injector: Allow new instantiations within $injector calls (b66e10e)

5.1.6 (2019-02-02)

5.1.5 (2019-01-27)

Bug Fixes

  • autoInject: Improve the injection detection (82d3391)

5.1.4 (2019-01-26)

Bug Fixes

  • autoService/Provider: Fix auto detection for services and providers with no deps (761921e)
  • Types: Fix the provider declaration for optional properties (cf2abcc)

5.1.3 (2019-01-24)

Bug Fixes

  • Types: Set tup the good method name for service descriptors (e77f6af)

5.1.2 (2019-01-20)

Bug Fixes

  • Types: Fix register method chaining type declaration (c468a2a)

5.1.1 (2019-01-20)

Bug Fixes

  • Tests: Fix Saucelabs tests (b77dcaa)
  • Types: Fix handlers and constant types (a42a209)

5.1.0 (2019-01-19)

Features

  • TypeScript: Add types for TypeScript support (65e94a9)

5.0.4 (2019-01-12)

5.0.3 (2019-01-12)

Bug Fixes

  • autoInject: Ensure auto injection works with trailing commas (521ab18)

5.0.2 (2018-11-29)

Bug Fixes

  • Core: Fail on syntax error even for optional services (8cfcabd)

5.0.1 (2018-11-22)

Bug Fixes

  • autoInject: Remove unecessary check in the autoInject regExp (fff9a6f)

5.0.0 (2018-11-18)

Code Refactoring

  • handler: Split the handler utils in autoHandler and handler (cae9b2f), closes #80
  • Utils: Change the service/provider utils signature (84e52a6)

Features

  • auto(Service/Provider): Add a way to automatically set provider/service (d08dca7)

BREAKING CHANGES

  • Utils: service/provider utils call will need to be changed everywhere
  • handler: handler calls will need to be converted for the new handler signature or use the newly created autoHandler function.

4.3.1 (2018-11-10)

Bug Fixes

  • autoInject util: Fix autoInject for named functions (b3b8c10)

4.3.0 (2018-11-10)

Features

  • autoInject util: Allow to auto inject even with multi-args functions (bdf4e8b)

4.2.0 (2018-11-10)

Features

  • handler util: Add autodetection features for handler utils (7190028)

4.1.0 (2018-11-10)

Features

  • autoInject: Allow to detect optional injections (ff009fb), closes #79

4.0.0 (2018-11-04)

chore

  • Dependencies: Update metapak-nfroidure (dc65134)

Features

  • autoInject: Adds a utility function to autodetect dependencies (03c8527)
  • autoName: Allow to set name according to the function name (19cde56)

BREAKING CHANGES

  • Dependencies: Drop support for NodeJS < 8 versions

3.1.0 (2018-10-14)

Features

  • Knifecycle instance: Add extra errors for bad use (a43aa30)

3.0.0 (2018-10-11)

Features

  • $instance: Add a way to inject the Knifecycle instance (5321401)

2.7.0 (2018-10-08)

Features

  • Decorators: Add a service decorator (3216abf)
  • Decorators: Add the constant decorator (911898e), closes #60

2.6.2 (2018-09-30)

Bug Fixes

  • $autoload: Fix autoload disposal (f087b12)

2.6.1 (2018-09-30)

Bug Fixes

  • $autoload: Fix autoload behavior (2256be0)

2.6.0 (2018-09-30)

Features

  • $autoload: Allows to autoload missing dependencies (5b1cdb1)

2.5.4 (2018-09-22)

2.5.3 (2018-09-16)

2.5.2 (2018-05-06)

Bug Fixes

  • Tests: Fix tests for Node10 (b3511a4)

2.5.1 (2018-04-13)

2.5.0 (2018-03-21)

Bug Fixes

  • Build: Fix build for providers (2847929)

Features

  • API: Ensure existing initializer type are provided (bf880d9)

2.4.2 (2017-12-02)

2.4.1 (2017-11-07)

2.4.0 (2017-11-07)

Features

  • Build: Allow to build initialization modules (1aaca1b)

2.3.0 (2017-10-30)

Bug Fixes

  • Build: Fix frontend tests for Firefox (890227b)

Features

  • Extra: Allow to add extra informations to initializers (782bade), closes #41

2.2.2 (2017-10-24)

Bug Fixes

  • Build: Quick fix of the build (0b71c08)

2.2.1 (2017-10-24)

Bug Fixes

  • Services mapping: Fix deep service mapping (9445cc3)

Features

  • Browser: Add browser support (d268fbd)

2.2.0 (2017-07-30)

Features

  • Decorators: Add the ability to create a initializer from simple function (f9e505e), closes #37

2.1.1 (2017-06-15)

Bug Fixes

  • Mappings: Fix the mappings for the initial run (2cfdb7f)

2.1.0 (2017-06-04)

Features

  • Util: Add a function to decorate initializers (477ad14)

2.0.0 (2017-05-28)

Code Refactoring

  • Decorators: Isolated decorators code (a776ab8), closes #28 #32
  • Dependencies: Change depends to be a Knifecycle static property (a35f5ca), closes #24
  • Dependencies declarations: Change the dependencies mapping symbol fron : to >. (9744aeb), closes #26
  • Providers: Simplify the service providers signature (7f5fef3), closes #30
  • Services: Do not support services as a promise anymore (af31c0d)

Features

  • Options: Add a decorator to specify service provider options (867f427)

BREAKING CHANGES

  • Dependencies declarations: Break 1.0 mappings
  • Decorators: Every 1.0 code will break since the index.js exports were broken.
  • Dependencies: Will break almost every 1.0 things
  • Providers: Almost every providers written before will not work anymore
  • Services: It is not possible to use a promise while declaring a service.

1.4.0 (2017-05-22)

Bug Fixes

  • Providers: Allow services to have options too (75bffcf)
  • Singletons: Ensure singletons aren't shut down (1de26d6)

Features

  • Bad usage: Fail on dependencies declaration for constant (ab57c18)
  • Dependencies declarations: Allow to make some dependencies optional (0944709), closes #23
  • Providers: Allow to declare providers as singletons (dad9006), closes #3
  • Shutdown: Allow to shutdown all silos (7af87de)
  • Singletons: Shutdown singletons when not used per any silo (f953851)

1.3.1 (2017-03-14)

1.3.0 (2017-03-08)

Bug Fixes

  • mermaid: Only apply first style (d78ecd3)
  • package: update yerror to version 2.0.0 (5697a89)

Features

  • mermaid: Add the ability to generate dependencies graphs (b2ac582)
  • mermaid: Allow to add styles to graphs (520b7a1)
  • mermaid: Allow to shape Mermaid diagrams node (ced9dad)

v1.2.0 (2017/01/31 16:46 +00:00)

  • 320ee35 1.2.0 (@nfroidure)
  • 9e7bf18 Supporting services names mapping fix #5 (@nfroidure)

v1.1.3 (2016/12/28 09:12 +00:00)

  • e49a55b 1.1.3 (@nfroidure)
  • ff34afc Drop old Node versions support (@nfroidure)

v1.1.2 (2016/12/28 09:03 +00:00)

  • 8a663e0 1.1.2 (@nfroidure)
  • 2ce95e2 Regenerating docs (@nfroidure)
  • ff1bf5e Fixing linting (@nfroidure)
  • f37a5d3 Fixing shutdown order (@nfroidure)
  • #4 Update dependencies to enable Greenkeeper 🌴 (@nfroidure)
  • b767a8b chore(package): update dependencies (@greenkeeper[bot])

v1.1.1 (2016/10/30 18:11 +00:00)

v1.1.0 (2016/10/30 09:22 +00:00)

  • 4d2db29 1.1.0 (@nfroidure)
  • 8346671 Adding an helper to get a Knifecycle instance easily (@nfroidure)
  • 7b2408c Adding the service fix #2 (@nfroidure)

v1.0.5 (2016/10/30 07:31 +00:00)

  • 26d27ea 1.0.5 (@nfroidure)
  • ead7eee Fixing shutdown for multi used dependency fix #1 (@nfroidure)

v1.0.4 (2016/09/02 13:08 +00:00)

  • b64a702 1.0.4 (@nfroidure)
  • 22303b8 Better feedback when erroring (@nfroidure)

v1.0.3 (2016/09/01 12:45 +00:00)

  • 6e40f63 1.0.3 (@nfroidure)
  • 3ccc9c1 Avoid instanciating services twice (@nfroidure)

v1.0.2 (2016/08/31 09:52 +00:00)

  • 4c5104a 1.0.2 (@nfroidure)
  • 9db5519 Fixing service shutdown (@nfroidure)

v1.0.1 (2016/08/29 13:56 +00:00)

  • f6f8b81 1.0.1 (@nfroidure)
  • bfce2c9 Fixing depends for services (@nfroidure)

v1.0.0 (2016/08/27 15:17 +00:00)

  • f278cb7 1.0.0 (@nfroidure)
  • 648d7ff Adding doc (@nfroidure)
  • 160d086 Adding project files (@nfroidure)
  • 1ee0bff Adding a LICENSE (@nfroidure)
  • dff2847 Specifying node engine (@nfroidure)
  • acffe5a Adding codeclimate config (@nfroidure)
  • 97099fc Adding coveralss cfg file to git ignore (@nfroidure)
  • f32f016 Fixing the linter issues (@nfroidure)
  • 461ecf6 Adding travis build (@nfroidure)
  • 2243977 Adding badges (@nfroidure)
  • caa3e4e Adding some usage infos and future plans (@nfroidure)
  • f7081a8 Adding the fatal error handler (@nfroidure)
  • 05fa72a First draft of a service injection tool for node (@nfroidure)