knifecycle
Advanced tools
Comparing version 2.5.2 to 2.5.3
@@ -0,1 +1,6 @@ | ||
<a name="2.5.3"></a> | ||
## [2.5.3](https://github.com/nfroidure/knifecycle/compare/v2.5.2...v2.5.3) (2018-09-16) | ||
<a name="2.5.2"></a> | ||
@@ -2,0 +7,0 @@ ## [2.5.2](https://github.com/nfroidure/knifecycle/compare/v2.5.1...v2.5.2) (2018-05-06) |
@@ -1,6 +0,6 @@ | ||
'use strict'; | ||
"use strict"; | ||
var _util = require('./util'); | ||
var _util = require("./util"); | ||
var _sequence = require('./sequence'); | ||
var _sequence = require("./sequence"); | ||
@@ -23,5 +23,3 @@ /* Architecture Note #2: Build | ||
*/ | ||
module.exports = buildInitializer; | ||
/** | ||
@@ -44,2 +42,3 @@ * Create a JavaScript module that initialize | ||
*/ | ||
function buildInitializer(constants, loader, dependencies) { | ||
@@ -53,3 +52,2 @@ return Promise.all(dependencies.map(dependency => buildDependencyTree(constants, loader, dependency))).then(dependencyTrees => { | ||
batches.pop(); | ||
return `${batches.map((batch, index) => ` | ||
@@ -73,4 +71,8 @@ // Definition batch #${index}${batch.map(name => { | ||
} | ||
return ` | ||
${name}: ${dependenciesHash[name].__initializerName}({${dependenciesHash[name].__inject ? `${dependenciesHash[name].__inject.map(_util.parseDependencyDeclaration).map(({ serviceName, mappedName }) => ` | ||
${name}: ${dependenciesHash[name].__initializerName}({${dependenciesHash[name].__inject ? `${dependenciesHash[name].__inject.map(_util.parseDependencyDeclaration).map(({ | ||
serviceName, | ||
mappedName | ||
}) => ` | ||
${serviceName}: services['${mappedName}'],`).join('')}` : ''} | ||
@@ -90,3 +92,6 @@ })${'provider' === dependenciesHash[name].__type ? '.then(provider => provider.service)' : ''},`; | ||
`).join('')} | ||
return {${dependencies.map(_util.parseDependencyDeclaration).map(({ serviceName, mappedName }) => ` | ||
return {${dependencies.map(_util.parseDependencyDeclaration).map(({ | ||
serviceName, | ||
mappedName | ||
}) => ` | ||
${serviceName}: services['${mappedName}'],`).join('')} | ||
@@ -100,3 +105,6 @@ }; | ||
function buildDependencyTree(constants, loader, dependencyDeclaration) { | ||
const { mappedName, optional } = (0, _util.parseDependencyDeclaration)(dependencyDeclaration); | ||
const { | ||
mappedName, | ||
optional | ||
} = (0, _util.parseDependencyDeclaration)(dependencyDeclaration); | ||
@@ -110,3 +118,6 @@ if (constants[mappedName]) { | ||
return loader(mappedName).then(({ path, initializer }) => { | ||
return loader(mappedName).then(({ | ||
path, | ||
initializer | ||
}) => { | ||
const node = { | ||
@@ -121,3 +132,2 @@ __name: mappedName, | ||
}; | ||
return initializer[_util.SPECIAL_PROPS.INJECT] && initializer[_util.SPECIAL_PROPS.INJECT].length ? Promise.all(initializer[_util.SPECIAL_PROPS.INJECT].map(childDependencyDeclaration => buildDependencyTree(constants, loader, childDependencyDeclaration))).then(childNodes => { | ||
@@ -131,2 +141,3 @@ node.__childNodes = childNodes.filter(identity); | ||
} | ||
throw err; | ||
@@ -142,3 +153,2 @@ }); | ||
const nodeIsALeaf = !(node.__childNodes && node.__childNodes.length); | ||
hash[node.__name] = node; | ||
@@ -145,0 +155,0 @@ |
@@ -1,17 +0,11 @@ | ||
'use strict'; | ||
"use strict"; | ||
var _assert = require('assert'); | ||
var _assert = _interopRequireDefault(require("assert")); | ||
var _assert2 = _interopRequireDefault(_assert); | ||
var _yerror = _interopRequireDefault(require("yerror")); | ||
var _yerror = require('yerror'); | ||
var _build = _interopRequireDefault(require("./build")); | ||
var _yerror2 = _interopRequireDefault(_yerror); | ||
var _util = require("./util"); | ||
var _build = require('./build'); | ||
var _build2 = _interopRequireDefault(_build); | ||
var _util = require('./util'); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
@@ -21,2 +15,3 @@ | ||
function aProvider() {} | ||
const mockedConstants = { | ||
@@ -45,2 +40,3 @@ NODE_ENV: 'development' | ||
}; | ||
function mockedLoader(name) { | ||
@@ -50,7 +46,7 @@ return mockedDepsHash[name] ? Promise.resolve({ | ||
initializer: mockedDepsHash[name] | ||
}) : Promise.reject(new _yerror2.default('E_UNMATCHED_DEPENDENCY', name)); | ||
}) : Promise.reject(new _yerror.default('E_UNMATCHED_DEPENDENCY', name)); | ||
} | ||
it('should build an initialization module', () => (0, _build2.default)(mockedConstants, mockedLoader, ['dep1', 'finalMappedDep>dep3']).then(content => { | ||
_assert2.default.equal(content, ` | ||
it('should build an initialization module', () => (0, _build.default)(mockedConstants, mockedLoader, ['dep1', 'finalMappedDep>dep3']).then(content => { | ||
_assert.default.equal(content, ` | ||
// Definition batch #0 | ||
@@ -57,0 +53,0 @@ import initDep1 from './services/dep1'; |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -6,19 +6,44 @@ Object.defineProperty(exports, "__esModule", { | ||
}); | ||
exports.options = exports.type = exports.inject = exports.name = exports.initializer = exports.Knifecycle = exports.getInstance = undefined; | ||
Object.defineProperty(exports, "initializer", { | ||
enumerable: true, | ||
get: function () { | ||
return _util.initializer; | ||
} | ||
}); | ||
Object.defineProperty(exports, "name", { | ||
enumerable: true, | ||
get: function () { | ||
return _util.name; | ||
} | ||
}); | ||
Object.defineProperty(exports, "inject", { | ||
enumerable: true, | ||
get: function () { | ||
return _util.inject; | ||
} | ||
}); | ||
Object.defineProperty(exports, "type", { | ||
enumerable: true, | ||
get: function () { | ||
return _util.type; | ||
} | ||
}); | ||
Object.defineProperty(exports, "options", { | ||
enumerable: true, | ||
get: function () { | ||
return _util.options; | ||
} | ||
}); | ||
exports.Knifecycle = exports.getInstance = exports.default = void 0; | ||
var _util = require('./util'); | ||
var _util = require("./util"); | ||
var _yerror = require('yerror'); | ||
var _yerror = _interopRequireDefault(require("yerror")); | ||
var _yerror2 = _interopRequireDefault(_yerror); | ||
var _debug = _interopRequireDefault(require("debug")); | ||
var _debug = require('debug'); | ||
var _debug2 = _interopRequireDefault(_debug); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
const debug = (0, _debug2.default)('knifecycle'); /* eslint max-len: ["warn", { "ignoreComments": true }] */ | ||
/* eslint max-len: ["warn", { "ignoreComments": true }] */ | ||
const debug = (0, _debug.default)('knifecycle'); | ||
const DISPOSE = '$dispose'; | ||
@@ -29,5 +54,3 @@ const DESTROY = '$destroy'; | ||
const FATAL_ERROR = '$fatalError'; | ||
const ALLOWED_INITIALIZER_TYPES = ['provider', 'service']; | ||
const E_BAD_ANALYZER_TYPE = 'E_BAD_ANALYZER_TYPE'; | ||
@@ -40,7 +63,5 @@ const E_UNMATCHED_DEPENDENCY = 'E_UNMATCHED_DEPENDENCY'; | ||
const E_BAD_INJECTION = 'E_BAD_INJECTION'; | ||
const E_CONSTANT_INJECTION = 'E_CONSTANT_INJECTION'; | ||
const E_CONSTANT_INJECTION = 'E_CONSTANT_INJECTION'; // Constants that should use Symbol whenever possible | ||
// Constants that should use Symbol whenever possible | ||
const INSTANCE = '__instance'; | ||
/* Architecture Note #1: Knifecycle | ||
@@ -72,2 +93,3 @@ | ||
*/ | ||
class Knifecycle { | ||
@@ -90,3 +112,5 @@ /** | ||
this._singletonsServicesShutdownsPromises = new Map(); | ||
this.provider(INJECTOR, (0, _util.inject)([SILO_CONTEXT], ({ $siloContext }) => Promise.resolve({ | ||
this.provider(INJECTOR, (0, _util.inject)([SILO_CONTEXT], ({ | ||
$siloContext | ||
}) => Promise.resolve({ | ||
service: dependenciesDeclarations => this._initializeDependencies($siloContext, $siloContext.name, dependenciesDeclarations, true) | ||
@@ -98,8 +122,5 @@ }))); | ||
const $dispose = siloContext.servicesDescriptors.get(DISPOSE).service; | ||
return $dispose(); | ||
})); | ||
debug('Shutting down Knifecycle instance.'); | ||
return this.shutdownPromise; | ||
@@ -111,3 +132,2 @@ } | ||
} | ||
/** | ||
@@ -123,2 +143,4 @@ * Returns a Knifecycle instance (always the same) | ||
*/ | ||
static getInstance() { | ||
@@ -129,3 +151,2 @@ Knifecycle[INSTANCE] = Knifecycle[INSTANCE] || new Knifecycle(); | ||
} | ||
/* Architecture Note #1.3: Declaring services | ||
@@ -174,2 +195,4 @@ The first step to use `knifecycle` is to declare | ||
*/ | ||
constant(constantName, constantValue) { | ||
@@ -179,3 +202,3 @@ const contantLooksLikeAnInitializer = constantValue instanceof Function && constantValue[_util.SPECIAL_PROPS.INJECT]; | ||
if (contantLooksLikeAnInitializer) { | ||
throw new _yerror2.default(E_CONSTANT_INJECTION, constantValue[_util.SPECIAL_PROPS.INJECT]); | ||
throw new _yerror.default(E_CONSTANT_INJECTION, constantValue[_util.SPECIAL_PROPS.INJECT]); | ||
} | ||
@@ -185,3 +208,5 @@ | ||
name: constantName, | ||
options: { singleton: true } | ||
options: { | ||
singleton: true | ||
} | ||
}, Promise.resolve.bind(Promise, { | ||
@@ -191,8 +216,5 @@ service: constantValue, | ||
}))); | ||
debug('Registered a new constant:', constantName); | ||
return this; | ||
} | ||
/** | ||
@@ -233,2 +255,4 @@ * Register a service initializer | ||
*/ | ||
service(serviceName, initializer, options) { | ||
@@ -243,3 +267,2 @@ this.register((0, _util.reuseSpecialProps)(initializer, initializer, { | ||
} | ||
/** | ||
@@ -281,2 +304,4 @@ * Register a provider initializer | ||
*/ | ||
provider(serviceName, initializer, options = {}) { | ||
@@ -295,7 +320,9 @@ this.register((0, _util.reuseSpecialProps)(initializer, initializer, { | ||
initializer[_util.SPECIAL_PROPS.TYPE] = initializer[_util.SPECIAL_PROPS.TYPE] || ALLOWED_INITIALIZER_TYPES[0]; | ||
if (!initializer[_util.SPECIAL_PROPS.NAME]) { | ||
throw new _yerror2.default(E_ANONYMOUS_ANALYZER, initializer[_util.SPECIAL_PROPS.NAME]); | ||
throw new _yerror.default(E_ANONYMOUS_ANALYZER, initializer[_util.SPECIAL_PROPS.NAME]); | ||
} | ||
if (!ALLOWED_INITIALIZER_TYPES.includes(initializer[_util.SPECIAL_PROPS.TYPE])) { | ||
throw new _yerror2.default(E_BAD_ANALYZER_TYPE, initializer[_util.SPECIAL_PROPS.TYPE], ALLOWED_INITIALIZER_TYPES); | ||
throw new _yerror.default(E_BAD_ANALYZER_TYPE, initializer[_util.SPECIAL_PROPS.TYPE], ALLOWED_INITIALIZER_TYPES); | ||
} | ||
@@ -311,3 +338,3 @@ | ||
if (initializerDependsOfItself) { | ||
throw new _yerror2.default(E_CIRCULAR_DEPENDENCY, initializer[_util.SPECIAL_PROPS.NAME]); | ||
throw new _yerror.default(E_CIRCULAR_DEPENDENCY, initializer[_util.SPECIAL_PROPS.NAME]); | ||
} | ||
@@ -320,2 +347,3 @@ | ||
this._servicesProviders.set(initializer[_util.SPECIAL_PROPS.NAME], initializer); | ||
debug('Registered a new initializer:', initializer[_util.SPECIAL_PROPS.NAME]); | ||
@@ -327,2 +355,3 @@ return this; | ||
const serviceName = _pickServiceNameFromDeclaration(dependencyDeclaration); | ||
const dependencyProvider = this._servicesProviders.get(serviceName); | ||
@@ -333,3 +362,5 @@ | ||
} | ||
declarationsStacks = declarationsStacks.concat(dependencyDeclaration); | ||
dependencyProvider[_util.SPECIAL_PROPS.INJECT].forEach(childDependencyDeclaration => { | ||
@@ -339,3 +370,3 @@ const childServiceName = _pickServiceNameFromDeclaration(childDependencyDeclaration); | ||
if (rootServiceName === childServiceName) { | ||
throw new _yerror2.default(...[E_CIRCULAR_DEPENDENCY, rootServiceName].concat(declarationsStacks).concat(childDependencyDeclaration)); | ||
throw new _yerror.default(...[E_CIRCULAR_DEPENDENCY, rootServiceName].concat(declarationsStacks).concat(childDependencyDeclaration)); | ||
} | ||
@@ -346,3 +377,2 @@ | ||
} | ||
/** | ||
@@ -373,3 +403,9 @@ * Outputs a Mermaid compatible dependency graph of the declared services. | ||
*/ | ||
toMermaidGraph({ shapes = [], styles = [], classes = {} } = {}) { | ||
toMermaidGraph({ | ||
shapes = [], | ||
styles = [], | ||
classes = {} | ||
} = {}) { | ||
const servicesProviders = this._servicesProviders; | ||
@@ -382,8 +418,13 @@ const links = Array.from(servicesProviders.keys()).filter(provider => !provider.startsWith('$')).reduce((links, serviceName) => { | ||
} | ||
return links.concat(serviceProvider[_util.SPECIAL_PROPS.INJECT].map(dependencyDeclaration => { | ||
const dependedServiceName = _pickServiceNameFromDeclaration(dependencyDeclaration); | ||
return { serviceName, dependedServiceName }; | ||
return { | ||
serviceName, | ||
dependedServiceName | ||
}; | ||
})); | ||
}, []); | ||
const classesApplications = _applyClasses(classes, styles, links); | ||
@@ -395,5 +436,7 @@ | ||
return ['graph TD'].concat(links.map(({ serviceName, dependedServiceName }) => ` ${_applyShapes(shapes, serviceName) || serviceName}-->${_applyShapes(shapes, dependedServiceName) || dependedServiceName}`)).concat(Object.keys(classes).map(className => ` classDef ${className} ${classes[className]}`)).concat(Object.keys(classesApplications).map(serviceName => ` class ${serviceName} ${classesApplications[serviceName]};`)).join('\n'); | ||
return ['graph TD'].concat(links.map(({ | ||
serviceName, | ||
dependedServiceName | ||
}) => ` ${_applyShapes(shapes, serviceName) || serviceName}-->${_applyShapes(shapes, dependedServiceName) || dependedServiceName}`)).concat(Object.keys(classes).map(className => ` classDef ${className} ${classes[className]}`)).concat(Object.keys(classesApplications).map(serviceName => ` class ${serviceName} ${classesApplications[serviceName]};`)).join('\n'); | ||
} | ||
/* Architecture Note #1.4: Execution silos | ||
@@ -426,4 +469,7 @@ Once all the services are declared, we need a way to bring | ||
*/ | ||
run(dependenciesDeclarations) { | ||
const _this = this; | ||
const internalDependencies = [...new Set(dependenciesDeclarations.concat(DISPOSE))]; | ||
@@ -439,6 +485,6 @@ const siloContext = { | ||
if (this.shutdownPromise) { | ||
throw new _yerror2.default('E_INSTANCE_DESTROYED'); | ||
} | ||
throw new _yerror.default('E_INSTANCE_DESTROYED'); | ||
} // Create a provider for the special fatal error service | ||
// Create a provider for the special fatal error service | ||
siloContext.servicesDescriptors.set(FATAL_ERROR, { | ||
@@ -453,20 +499,16 @@ service: { | ||
} | ||
}); | ||
}); // Make the siloContext available for internal injections | ||
// Make the siloContext available for internal injections | ||
siloContext.servicesDescriptors.set(SILO_CONTEXT, { | ||
service: siloContext | ||
}); | ||
// Create a provider for the shutdown special dependency | ||
}); // Create a provider for the shutdown special dependency | ||
siloContext.servicesDescriptors.set(DISPOSE, { | ||
service: () => { | ||
siloContext.shutdownPromise = siloContext.shutdownPromise || _shutdownNextServices(siloContext.servicesSequence); | ||
debug('Shutting down services'); | ||
return siloContext.shutdownPromise.then(() => { | ||
this._silosContexts.delete(siloContext); | ||
}); | ||
}); // Shutdown services in their instanciation order | ||
// Shutdown services in their instanciation order | ||
function _shutdownNextServices(reversedServiceSequence) { | ||
@@ -476,4 +518,6 @@ if (0 === reversedServiceSequence.length) { | ||
} | ||
return Promise.all(reversedServiceSequence.pop().map(serviceName => { | ||
const singletonServiceDescriptor = _this._singletonsServicesDescriptors.get(serviceName); | ||
const serviceDescriptor = singletonServiceDescriptor || siloContext.servicesDescriptors.get(serviceName); | ||
@@ -491,2 +535,3 @@ let serviceShutdownPromise = _this._singletonsServicesShutdownsPromises.get(serviceName) || siloContext.servicesShutdownsPromises.get(serviceName); | ||
} | ||
if (singletonServiceDescriptor) { | ||
@@ -496,2 +541,3 @@ const handleSet = _this._singletonsServicesHandles.get(serviceName); | ||
handleSet.delete(siloContext.name); | ||
if (handleSet.size) { | ||
@@ -501,9 +547,13 @@ debug('Singleton is used elsewhere:', serviceName, handleSet); | ||
} | ||
_this._singletonsServicesDescriptors.delete(serviceName); | ||
} | ||
debug('Shutting down a service:', serviceName); | ||
serviceShutdownPromise = serviceDescriptor.dispose ? serviceDescriptor.dispose() : Promise.resolve(); | ||
if (singletonServiceDescriptor) { | ||
_this._singletonsServicesShutdownsPromises.set(serviceName, serviceShutdownPromise); | ||
} | ||
siloContext.servicesShutdownsPromises.set(serviceName, serviceShutdownPromise); | ||
@@ -523,4 +573,6 @@ return serviceShutdownPromise; | ||
return dependenciesDeclarations.reduce((finalHash, dependencyDeclaration) => { | ||
const { serviceName, mappedName } = (0, _util.parseDependencyDeclaration)(dependencyDeclaration); | ||
const { | ||
serviceName, | ||
mappedName | ||
} = (0, _util.parseDependencyDeclaration)(dependencyDeclaration); | ||
finalHash[serviceName] = servicesHash[mappedName]; | ||
@@ -531,3 +583,2 @@ return finalHash; | ||
} | ||
/** | ||
@@ -541,2 +592,4 @@ * Initialize or return a service descriptor | ||
*/ | ||
_getServiceDescriptor(siloContext, injectOnly, serviceName) { | ||
@@ -553,9 +606,9 @@ let serviceDescriptor = this._singletonsServicesDescriptors.get(serviceName); | ||
return Promise.resolve(serviceDescriptor); | ||
} | ||
// The inject service is intended to be used as a workaround for unavoidable | ||
} // The inject service is intended to be used as a workaround for unavoidable | ||
// circular dependencies. It wouldn't make sense to instanciate new services | ||
// at this level so throwing an error | ||
if (injectOnly) { | ||
return Promise.reject(new _yerror2.default(E_BAD_INJECTION, serviceName)); | ||
return Promise.reject(new _yerror.default(E_BAD_INJECTION, serviceName)); | ||
} | ||
@@ -565,3 +618,2 @@ | ||
} | ||
/** | ||
@@ -574,6 +626,8 @@ * Initialize a service | ||
*/ | ||
_initializeServiceDescriptor(siloContext, serviceName) { | ||
const serviceProvider = this._servicesProviders.get(serviceName); | ||
let serviceDescriptorPromise; | ||
debug('Initializing a service descriptor:', serviceName); | ||
@@ -583,24 +637,25 @@ | ||
debug('No service provider:', serviceName); | ||
serviceDescriptorPromise = Promise.reject(new _yerror2.default(E_UNMATCHED_DEPENDENCY, serviceName)); | ||
serviceDescriptorPromise = Promise.reject(new _yerror.default(E_UNMATCHED_DEPENDENCY, serviceName)); | ||
siloContext.servicesDescriptors.set(serviceName, serviceDescriptorPromise); | ||
return serviceDescriptorPromise; | ||
} | ||
// A singleton service may use a reserved resource | ||
} // A singleton service may use a reserved resource | ||
// like a TCP socket. This is why we have to be aware | ||
// of singleton services full shutdown before creating | ||
// a new one | ||
serviceDescriptorPromise = (this._singletonsServicesShutdownsPromises.get(serviceName) || Promise.resolve()). | ||
// Anyway delete any shutdown promise before instanciating | ||
serviceDescriptorPromise = (this._singletonsServicesShutdownsPromises.get(serviceName) || Promise.resolve()). // Anyway delete any shutdown promise before instanciating | ||
// a new service | ||
then(() => { | ||
this._singletonsServicesShutdownsPromises.delete(serviceName); | ||
siloContext.servicesShutdownsPromises.delete(serviceName); | ||
}).then(this._initializeDependencies.bind(this, siloContext, serviceName, serviceProvider[_util.SPECIAL_PROPS.INJECT])); | ||
serviceDescriptorPromise = serviceDescriptorPromise.then(servicesHash => { | ||
debug('Successfully gathered service dependencies:', serviceName); | ||
return serviceProvider[_util.SPECIAL_PROPS.INJECT].reduce((finalHash, dependencyDeclaration) => { | ||
const { serviceName, mappedName } = (0, _util.parseDependencyDeclaration)(dependencyDeclaration); | ||
const { | ||
serviceName, | ||
mappedName | ||
} = (0, _util.parseDependencyDeclaration)(dependencyDeclaration); | ||
finalHash[serviceName] = servicesHash[mappedName]; | ||
@@ -612,5 +667,7 @@ return finalHash; | ||
debug('Provider did not return a descriptor:', serviceName); | ||
return Promise.reject(new _yerror2.default(E_BAD_SERVICE_PROVIDER, serviceName)); | ||
return Promise.reject(new _yerror.default(E_BAD_SERVICE_PROVIDER, serviceName)); | ||
} | ||
debug('Successfully initialized a service descriptor:', serviceName); | ||
if (serviceDescriptor.fatalErrorPromise) { | ||
@@ -620,2 +677,3 @@ debug('Registering service descriptor error promise:', serviceName); | ||
} | ||
siloContext.servicesDescriptors.set(serviceName, serviceDescriptor); | ||
@@ -625,12 +683,16 @@ return serviceDescriptor; | ||
debug('Error initializing a service descriptor:', serviceName, err.stack); | ||
if (E_UNMATCHED_DEPENDENCY === err.code) { | ||
throw _yerror2.default.wrap(...[err, E_UNMATCHED_DEPENDENCY, serviceName].concat(err.params)); | ||
throw _yerror.default.wrap(...[err, E_UNMATCHED_DEPENDENCY, serviceName].concat(err.params)); | ||
} | ||
throw err; | ||
}); | ||
if (serviceProvider[_util.SPECIAL_PROPS.OPTIONS].singleton) { | ||
const handlesSet = new Set(); | ||
handlesSet.add(siloContext.name); | ||
handlesSet.add(siloContext.name); | ||
this._singletonsServicesHandles.set(serviceName, handlesSet); | ||
this._singletonsServicesDescriptors.set(serviceName, serviceDescriptorPromise); | ||
@@ -640,5 +702,5 @@ } else { | ||
} | ||
return serviceDescriptorPromise; | ||
} | ||
/** | ||
@@ -652,7 +714,11 @@ * Initialize a service dependencies | ||
*/ | ||
_initializeDependencies(siloContext, serviceName, servicesDeclarations, injectOnly = false) { | ||
debug('Initializing dependencies:', serviceName, servicesDeclarations); | ||
return Promise.resolve().then(() => Promise.all(servicesDeclarations.map(serviceDeclaration => { | ||
const { mappedName, optional } = (0, _util.parseDependencyDeclaration)(serviceDeclaration); | ||
const { | ||
mappedName, | ||
optional | ||
} = (0, _util.parseDependencyDeclaration)(serviceDeclaration); | ||
return this._getServiceDescriptor(siloContext, injectOnly, mappedName).catch(err => { | ||
@@ -662,2 +728,3 @@ if (optional) { | ||
} | ||
throw err; | ||
@@ -672,2 +739,3 @@ }); | ||
} | ||
return serviceDescriptor.service; | ||
@@ -682,17 +750,15 @@ })); | ||
} | ||
} | ||
exports.default = Knifecycle; | ||
const getInstance = exports.getInstance = Knifecycle.getInstance; | ||
exports.Knifecycle = Knifecycle; | ||
exports.initializer = _util.initializer; | ||
exports.name = _util.name; | ||
exports.inject = _util.inject; | ||
exports.type = _util.type; | ||
exports.options = _util.options; | ||
var _default = Knifecycle; | ||
exports.default = _default; | ||
const getInstance = Knifecycle.getInstance; | ||
exports.getInstance = getInstance; | ||
function _pickServiceNameFromDeclaration(dependencyDeclaration) { | ||
const { serviceName } = (0, _util.parseDependencyDeclaration)(dependencyDeclaration); | ||
const { | ||
serviceName | ||
} = (0, _util.parseDependencyDeclaration)(dependencyDeclaration); | ||
return serviceName; | ||
@@ -702,4 +768,6 @@ } | ||
function _pickMappedNameFromDeclaration(dependencyDeclaration) { | ||
const { serviceName, mappedName } = (0, _util.parseDependencyDeclaration)(dependencyDeclaration); | ||
const { | ||
serviceName, | ||
mappedName | ||
} = (0, _util.parseDependencyDeclaration)(dependencyDeclaration); | ||
return mappedName || serviceName; | ||
@@ -715,6 +783,9 @@ } | ||
} | ||
matches = shape.pattern.exec(serviceName); | ||
if (!matches) { | ||
return shapedService; | ||
} | ||
return shape.template.replace(/\$([0-9])+/g, ($, $1) => matches[parseInt($1, 10)]); | ||
@@ -728,16 +799,23 @@ }, ''); | ||
function _applyStyles(classes, styles, { serviceName, dependedServiceName }) { | ||
function _applyStyles(classes, styles, { | ||
serviceName, | ||
dependedServiceName | ||
}) { | ||
return styles.reduce((classesApplications, style) => { | ||
if (style.pattern.test(serviceName) && !classesApplications[serviceName]) { | ||
if (!classes[style.className]) { | ||
throw new _yerror2.default('E_BAD_CLASS', style.className, serviceName); | ||
throw new _yerror.default('E_BAD_CLASS', style.className, serviceName); | ||
} | ||
classesApplications[serviceName] = style.className; | ||
} | ||
if (style.pattern.test(dependedServiceName) && !classesApplications[dependedServiceName]) { | ||
if (!classes[style.className]) { | ||
throw new _yerror2.default('E_BAD_CLASS', style.className, dependedServiceName); | ||
throw new _yerror.default('E_BAD_CLASS', style.className, dependedServiceName); | ||
} | ||
classesApplications[dependedServiceName] = style.className; | ||
} | ||
return classesApplications; | ||
@@ -751,4 +829,5 @@ }, {}); | ||
if (!servicePromise || !servicePromise.then) { | ||
throw new _yerror2.default(E_BAD_SERVICE_PROMISE, serviceName); | ||
throw new _yerror.default(E_BAD_SERVICE_PROMISE, serviceName); | ||
} | ||
return servicePromise.then(_service_ => Promise.resolve({ | ||
@@ -755,0 +834,0 @@ service: _service_ |
@@ -1,15 +0,12 @@ | ||
'use strict'; | ||
"use strict"; | ||
var _assert = require('assert'); | ||
var _assert = _interopRequireDefault(require("assert")); | ||
var _assert2 = _interopRequireDefault(_assert); | ||
var _sinon = _interopRequireDefault(require("sinon")); | ||
var _sinon = require('sinon'); | ||
var _index = require("./index"); | ||
var _sinon2 = _interopRequireDefault(_sinon); | ||
var _index = require('./index'); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
/* eslint max-nested-callbacks:0 */ | ||
describe('Knifecycle', () => { | ||
@@ -35,13 +32,10 @@ let $; | ||
}); | ||
describe('getInstance', () => { | ||
it('should return an instance', () => { | ||
(0, _assert2.default)(_index.Knifecycle.getInstance()); | ||
(0, _assert.default)(_index.Knifecycle.getInstance()); | ||
}); | ||
it('should always return the same instance', () => { | ||
_assert2.default.equal(_index.Knifecycle.getInstance(), _index.Knifecycle.getInstance()); | ||
_assert.default.equal(_index.Knifecycle.getInstance(), _index.Knifecycle.getInstance()); | ||
}); | ||
}); | ||
describe('constant', () => { | ||
@@ -51,9 +45,7 @@ it('should register an object', () => { | ||
}); | ||
it('should register a function', () => { | ||
$.constant('time', time); | ||
}); | ||
it('should fail with dependencies since it makes no sense', () => { | ||
_assert2.default.throws(() => { | ||
_assert.default.throws(() => { | ||
$.constant('time', (0, _index.inject)(['hash3'], time)); | ||
@@ -63,3 +55,2 @@ }, /E_CONSTANT_INJECTION/); | ||
}); | ||
describe('service', () => { | ||
@@ -70,3 +61,2 @@ it('should register service', () => { | ||
}); | ||
describe('provider', () => { | ||
@@ -76,25 +66,26 @@ it('should register provider', () => { | ||
}); | ||
it('should fail with direct circular dependencies', () => { | ||
_assert2.default.throws(() => { | ||
_assert.default.throws(() => { | ||
$.provider('hash', (0, _index.inject)(['hash'], hashProvider)); | ||
}, err => { | ||
_assert2.default.deepEqual(err.code, 'E_CIRCULAR_DEPENDENCY'); | ||
_assert2.default.deepEqual(err.params, ['hash']); | ||
_assert.default.deepEqual(err.code, 'E_CIRCULAR_DEPENDENCY'); | ||
_assert.default.deepEqual(err.params, ['hash']); | ||
return true; | ||
}); | ||
}); | ||
it('should fail with direct circular dependencies on mapped services', () => { | ||
_assert2.default.throws(() => { | ||
_assert.default.throws(() => { | ||
$.provider('hash', (0, _index.inject)(['hash>lol'], hashProvider)); | ||
}, err => { | ||
_assert2.default.deepEqual(err.code, 'E_CIRCULAR_DEPENDENCY'); | ||
_assert2.default.deepEqual(err.params, ['hash']); | ||
_assert.default.deepEqual(err.code, 'E_CIRCULAR_DEPENDENCY'); | ||
_assert.default.deepEqual(err.params, ['hash']); | ||
return true; | ||
}); | ||
}); | ||
it('should fail with circular dependencies', () => { | ||
_assert2.default.throws(() => { | ||
_assert.default.throws(() => { | ||
$.provider('hash', (0, _index.inject)(['hash3'], hashProvider)); | ||
@@ -105,10 +96,11 @@ $.provider('hash1', (0, _index.inject)(['hash'], hashProvider)); | ||
}, err => { | ||
_assert2.default.deepEqual(err.code, 'E_CIRCULAR_DEPENDENCY'); | ||
_assert2.default.deepEqual(err.params, ['hash3', 'hash', 'hash3']); | ||
_assert.default.deepEqual(err.code, 'E_CIRCULAR_DEPENDENCY'); | ||
_assert.default.deepEqual(err.params, ['hash3', 'hash', 'hash3']); | ||
return true; | ||
}); | ||
}); | ||
it('should fail with deeper circular dependencies', () => { | ||
_assert2.default.throws(() => { | ||
_assert.default.throws(() => { | ||
$.provider('hash', (0, _index.inject)(['hash1'], hashProvider)); | ||
@@ -119,10 +111,11 @@ $.provider('hash1', (0, _index.inject)(['hash2'], hashProvider)); | ||
}, err => { | ||
_assert2.default.deepEqual(err.code, 'E_CIRCULAR_DEPENDENCY'); | ||
_assert2.default.deepEqual(err.params, ['hash3', 'hash', 'hash1', 'hash2', 'hash3']); | ||
_assert.default.deepEqual(err.code, 'E_CIRCULAR_DEPENDENCY'); | ||
_assert.default.deepEqual(err.params, ['hash3', 'hash', 'hash1', 'hash2', 'hash3']); | ||
return true; | ||
}); | ||
}); | ||
it('should fail with circular dependencies on mapped services', () => { | ||
_assert2.default.throws(() => { | ||
_assert.default.throws(() => { | ||
$.provider('hash', (0, _index.inject)(['hash3>aHash3'], hashProvider)); | ||
@@ -133,4 +126,6 @@ $.provider('hash1', (0, _index.inject)(['hash>aHash'], hashProvider)); | ||
}, err => { | ||
_assert2.default.deepEqual(err.code, 'E_CIRCULAR_DEPENDENCY'); | ||
_assert2.default.deepEqual(err.params, ['hash3', 'hash>aHash', 'hash3>aHash3']); | ||
_assert.default.deepEqual(err.code, 'E_CIRCULAR_DEPENDENCY'); | ||
_assert.default.deepEqual(err.params, ['hash3', 'hash>aHash', 'hash3>aHash3']); | ||
return true; | ||
@@ -140,17 +135,15 @@ }); | ||
}); | ||
describe('run', () => { | ||
it('should work with no dependencies', done => { | ||
$.run([]).then(dependencies => { | ||
_assert2.default.deepEqual(dependencies, {}); | ||
_assert.default.deepEqual(dependencies, {}); | ||
}).then(() => done()).catch(done); | ||
}); | ||
it('should work with constant dependencies', done => { | ||
$.constant('ENV', ENV); | ||
$.constant('time', time); | ||
$.run(['time', 'ENV']).then(dependencies => { | ||
_assert.default.deepEqual(Object.keys(dependencies), ['time', 'ENV']); | ||
$.run(['time', 'ENV']).then(dependencies => { | ||
_assert2.default.deepEqual(Object.keys(dependencies), ['time', 'ENV']); | ||
_assert2.default.deepEqual(dependencies, { | ||
_assert.default.deepEqual(dependencies, { | ||
ENV, | ||
@@ -161,12 +154,13 @@ time | ||
}); | ||
it('should work with service dependencies', done => { | ||
$.service('sample', (0, _index.inject)(['time'], function sampleService({ time }) { | ||
$.service('sample', (0, _index.inject)(['time'], function sampleService({ | ||
time | ||
}) { | ||
return Promise.resolve(typeof time); | ||
})); | ||
$.constant('time', time); | ||
$.run(['sample']).then(dependencies => { | ||
_assert.default.deepEqual(Object.keys(dependencies), ['sample']); | ||
$.run(['sample']).then(dependencies => { | ||
_assert2.default.deepEqual(Object.keys(dependencies), ['sample']); | ||
_assert2.default.deepEqual(dependencies, { | ||
_assert.default.deepEqual(dependencies, { | ||
sample: 'function' | ||
@@ -176,3 +170,2 @@ }); | ||
}); | ||
it('should work with simple dependencies', done => { | ||
@@ -182,7 +175,9 @@ $.constant('ENV', ENV); | ||
$.provider('hash', (0, _index.inject)(['ENV'], hashProvider)); | ||
$.run(['time', 'hash']).then(dependencies => { | ||
_assert.default.deepEqual(Object.keys(dependencies), ['time', 'hash']); | ||
$.run(['time', 'hash']).then(dependencies => { | ||
_assert2.default.deepEqual(Object.keys(dependencies), ['time', 'hash']); | ||
_assert2.default.deepEqual(dependencies, { | ||
hash: { ENV }, | ||
_assert.default.deepEqual(dependencies, { | ||
hash: { | ||
ENV | ||
}, | ||
time | ||
@@ -192,3 +187,2 @@ }); | ||
}); | ||
it('should work with given optional dependencies', done => { | ||
@@ -199,7 +193,10 @@ $.constant('ENV', ENV); | ||
$.provider('hash', (0, _index.inject)(['ENV', '?DEBUG'], hashProvider)); | ||
$.run(['time', 'hash']).then(dependencies => { | ||
_assert.default.deepEqual(Object.keys(dependencies), ['time', 'hash']); | ||
$.run(['time', 'hash']).then(dependencies => { | ||
_assert2.default.deepEqual(Object.keys(dependencies), ['time', 'hash']); | ||
_assert2.default.deepEqual(dependencies, { | ||
hash: { ENV, DEBUG: {} }, | ||
_assert.default.deepEqual(dependencies, { | ||
hash: { | ||
ENV, | ||
DEBUG: {} | ||
}, | ||
time | ||
@@ -209,3 +206,2 @@ }); | ||
}); | ||
it('should work with lacking optional dependencies', done => { | ||
@@ -215,7 +211,10 @@ $.constant('ENV', ENV); | ||
$.provider('hash', (0, _index.inject)(['ENV', '?DEBUG'], hashProvider)); | ||
$.run(['time', 'hash']).then(dependencies => { | ||
_assert.default.deepEqual(Object.keys(dependencies), ['time', 'hash']); | ||
$.run(['time', 'hash']).then(dependencies => { | ||
_assert2.default.deepEqual(Object.keys(dependencies), ['time', 'hash']); | ||
_assert2.default.deepEqual(dependencies, { | ||
hash: { ENV, DEBUG: {}.undef }, | ||
_assert.default.deepEqual(dependencies, { | ||
hash: { | ||
ENV, | ||
DEBUG: {}.undef | ||
}, | ||
time | ||
@@ -225,3 +224,2 @@ }); | ||
}); | ||
it('should work with deeper dependencies', done => { | ||
@@ -236,10 +234,8 @@ $.constant('ENV', ENV); | ||
$.provider('hash5', (0, _index.inject)(['hash4'], hashProvider)); | ||
$.run(['hash5', 'time']).then(dependencies => { | ||
_assert2.default.deepEqual(Object.keys(dependencies), ['hash5', 'time']); | ||
_assert.default.deepEqual(Object.keys(dependencies), ['hash5', 'time']); | ||
}).then(() => done()).catch(done); | ||
}); | ||
it('should instanciate services once', done => { | ||
const timeServiceStub = _sinon2.default.spy(timeService); | ||
const timeServiceStub = _sinon.default.spy(timeService); | ||
@@ -251,14 +247,14 @@ $.constant('ENV', ENV); | ||
$.provider('hash3', (0, _index.inject)(['ENV', 'time'], hashProvider)); | ||
$.run(['hash', 'hash2', 'hash3', 'time']).then(dependencies => { | ||
_assert.default.deepEqual(Object.keys(dependencies), ['hash', 'hash2', 'hash3', 'time']); | ||
$.run(['hash', 'hash2', 'hash3', 'time']).then(dependencies => { | ||
_assert2.default.deepEqual(Object.keys(dependencies), ['hash', 'hash2', 'hash3', 'time']); | ||
_assert2.default.deepEqual(timeServiceStub.args, [[{}]]); | ||
_assert.default.deepEqual(timeServiceStub.args, [[{}]]); | ||
}).then(() => done()).catch(done); | ||
}); | ||
it('should instanciate a single mapped service', done => { | ||
const providerStub = _sinon2.default.stub().returns(Promise.resolve({ | ||
const providerStub = _sinon.default.stub().returns(Promise.resolve({ | ||
service: 'stub' | ||
})); | ||
const providerStub2 = _sinon2.default.stub().returns(Promise.resolve({ | ||
const providerStub2 = _sinon.default.stub().returns(Promise.resolve({ | ||
service: 'stub2' | ||
@@ -270,6 +266,7 @@ })); | ||
$.run(['stub>mappedStub']).then(dependencies => { | ||
_assert2.default.deepEqual(dependencies, { | ||
_assert.default.deepEqual(dependencies, { | ||
stub: 'stub' | ||
}); | ||
_assert2.default.deepEqual(providerStub.args, [[{ | ||
_assert.default.deepEqual(providerStub.args, [[{ | ||
stub2: 'stub2' | ||
@@ -279,5 +276,4 @@ }]]); | ||
}); | ||
it('should instanciate several services with mappings', done => { | ||
const timeServiceStub = _sinon2.default.spy(timeService); | ||
const timeServiceStub = _sinon.default.spy(timeService); | ||
@@ -289,9 +285,8 @@ $.constant('ENV', ENV); | ||
$.provider('aHash3', (0, _index.inject)(['ENV', 'hash>aHash'], hashProvider)); | ||
$.run(['hash2>aHash2', 'hash3>aHash3', 'time>aTime']).then(dependencies => { | ||
_assert.default.deepEqual(Object.keys(dependencies), ['hash2', 'hash3', 'time']); | ||
$.run(['hash2>aHash2', 'hash3>aHash3', 'time>aTime']).then(dependencies => { | ||
_assert2.default.deepEqual(Object.keys(dependencies), ['hash2', 'hash3', 'time']); | ||
_assert2.default.deepEqual(timeServiceStub.args, [[{}]]); | ||
_assert.default.deepEqual(timeServiceStub.args, [[{}]]); | ||
}).then(() => done()).catch(done); | ||
}); | ||
it('should fail with bad service', done => { | ||
@@ -302,7 +297,7 @@ $.service('lol', () => {}); | ||
}).catch(err => { | ||
_assert2.default.deepEqual(err.code, 'E_BAD_SERVICE_PROMISE'); | ||
_assert2.default.deepEqual(err.params, ['lol']); | ||
_assert.default.deepEqual(err.code, 'E_BAD_SERVICE_PROMISE'); | ||
_assert.default.deepEqual(err.params, ['lol']); | ||
}).then(() => done()).catch(done); | ||
}); | ||
it('should fail with bad provider', done => { | ||
@@ -313,7 +308,7 @@ $.provider('lol', () => {}); | ||
}).catch(err => { | ||
_assert2.default.deepEqual(err.code, 'E_BAD_SERVICE_PROVIDER'); | ||
_assert2.default.deepEqual(err.params, ['lol']); | ||
_assert.default.deepEqual(err.code, 'E_BAD_SERVICE_PROVIDER'); | ||
_assert.default.deepEqual(err.params, ['lol']); | ||
}).then(() => done()).catch(done); | ||
}); | ||
it('should fail with bad service in a provider', done => { | ||
@@ -324,7 +319,7 @@ $.provider('lol', () => Promise.resolve()); | ||
}).catch(err => { | ||
_assert2.default.deepEqual(err.code, 'E_BAD_SERVICE_PROVIDER'); | ||
_assert2.default.deepEqual(err.params, ['lol']); | ||
_assert.default.deepEqual(err.code, 'E_BAD_SERVICE_PROVIDER'); | ||
_assert.default.deepEqual(err.params, ['lol']); | ||
}).then(() => done()).catch(done); | ||
}); | ||
it('should fail with undeclared dependencies', done => { | ||
@@ -334,7 +329,7 @@ $.run(['lol']).then(() => { | ||
}).catch(err => { | ||
_assert2.default.deepEqual(err.code, 'E_UNMATCHED_DEPENDENCY'); | ||
_assert2.default.deepEqual(err.params, ['lol']); | ||
_assert.default.deepEqual(err.code, 'E_UNMATCHED_DEPENDENCY'); | ||
_assert.default.deepEqual(err.params, ['lol']); | ||
}).then(() => done()).catch(done); | ||
}); | ||
it('should fail with undeclared dependencies upstream', done => { | ||
@@ -345,11 +340,10 @@ $.constant('ENV', ENV); | ||
$.provider('hash2', (0, _index.inject)(['ENV', 'lol'], hashProvider)); | ||
$.run(['time', 'hash']).then(() => { | ||
throw new Error('E_UNEXPECTED_SUCCESS'); | ||
}).catch(err => { | ||
_assert2.default.deepEqual(err.code, 'E_UNMATCHED_DEPENDENCY'); | ||
_assert2.default.deepEqual(err.params, ['hash', 'hash2', 'lol']); | ||
_assert.default.deepEqual(err.code, 'E_UNMATCHED_DEPENDENCY'); | ||
_assert.default.deepEqual(err.params, ['hash', 'hash2', 'lol']); | ||
}).then(() => done()).catch(done); | ||
}); | ||
it('should provide a fatal error handler', done => { | ||
@@ -362,3 +356,5 @@ $.constant('ENV', ENV); | ||
function processProvider({ $fatalError }) { | ||
function processProvider({ | ||
$fatalError | ||
}) { | ||
return Promise.resolve({ | ||
@@ -371,3 +367,5 @@ service: { | ||
function dbProvider({ ENV }) { | ||
function dbProvider({ | ||
ENV | ||
}) { | ||
return Promise.resolve().then(() => { | ||
@@ -382,3 +380,2 @@ let service; | ||
}); | ||
return { | ||
@@ -391,7 +388,10 @@ service, | ||
$.run(['time', 'hash', 'db', 'process']).then(({ process, db }) => { | ||
$.run(['time', 'hash', 'db', 'process']).then(({ | ||
process, | ||
db | ||
}) => { | ||
process.fatalErrorPromise.then(() => { | ||
done(new Error('E_UNEXPECTED_SUCCESS')); | ||
}).catch(err => { | ||
_assert2.default.deepEqual(err.message, 'E_DB_ERROR'); | ||
_assert.default.deepEqual(err.message, 'E_DB_ERROR'); | ||
}).then(() => done()).catch(done); | ||
@@ -402,3 +402,2 @@ db.reject(new Error('E_DB_ERROR')); | ||
}); | ||
describe('inject', () => { | ||
@@ -409,12 +408,12 @@ it('should work with no dependencies', done => { | ||
$.provider('hash', (0, _index.inject)(['ENV'], hashProvider)); | ||
$.run(['time', 'hash', '$injector']).then(dependencies => { | ||
_assert.default.deepEqual(Object.keys(dependencies), ['time', 'hash', '$injector']); | ||
$.run(['time', 'hash', '$injector']).then(dependencies => { | ||
_assert2.default.deepEqual(Object.keys(dependencies), ['time', 'hash', '$injector']); | ||
return dependencies.$injector([]).then(injectDependencies => { | ||
_assert2.default.deepEqual(Object.keys(injectDependencies), []); | ||
_assert2.default.deepEqual(injectDependencies, {}); | ||
_assert.default.deepEqual(Object.keys(injectDependencies), []); | ||
_assert.default.deepEqual(injectDependencies, {}); | ||
}); | ||
}).then(() => done()).catch(done); | ||
}); | ||
it('should work with same dependencies then the running silo', done => { | ||
@@ -424,9 +423,12 @@ $.constant('ENV', ENV); | ||
$.provider('hash', (0, _index.inject)(['ENV'], hashProvider)); | ||
$.run(['time', 'hash', '$injector']).then(dependencies => { | ||
_assert.default.deepEqual(Object.keys(dependencies), ['time', 'hash', '$injector']); | ||
$.run(['time', 'hash', '$injector']).then(dependencies => { | ||
_assert2.default.deepEqual(Object.keys(dependencies), ['time', 'hash', '$injector']); | ||
return dependencies.$injector(['time', 'hash']).then(injectDependencies => { | ||
_assert2.default.deepEqual(Object.keys(injectDependencies), ['time', 'hash']); | ||
_assert2.default.deepEqual(injectDependencies, { | ||
hash: { ENV }, | ||
_assert.default.deepEqual(Object.keys(injectDependencies), ['time', 'hash']); | ||
_assert.default.deepEqual(injectDependencies, { | ||
hash: { | ||
ENV | ||
}, | ||
time | ||
@@ -437,3 +439,2 @@ }); | ||
}); | ||
it('should fail with non instanciated dependencies', done => { | ||
@@ -443,23 +444,27 @@ $.constant('ENV', ENV); | ||
$.provider('hash', (0, _index.inject)(['ENV'], hashProvider)); | ||
$.run(['time', '$injector']).then(dependencies => { | ||
_assert.default.deepEqual(Object.keys(dependencies), ['time', '$injector']); | ||
$.run(['time', '$injector']).then(dependencies => { | ||
_assert2.default.deepEqual(Object.keys(dependencies), ['time', '$injector']); | ||
return dependencies.$injector(['time', 'hash']).catch(err => { | ||
_assert2.default.equal(err.code, 'E_BAD_INJECTION'); | ||
_assert.default.equal(err.code, 'E_BAD_INJECTION'); | ||
}); | ||
}).then(() => done()).catch(done); | ||
}); | ||
it('should create dependencies when not declared as singletons', done => { | ||
$.constant('ENV', ENV); | ||
$.provider('hash', (0, _index.inject)(['ENV'], hashProvider)); | ||
Promise.all([$.run(['hash']), $.run(['hash'])]).then(([{ | ||
hash | ||
}, { | ||
hash: sameHash | ||
}]) => { | ||
_assert.default.notEqual(hash, sameHash); | ||
Promise.all([$.run(['hash']), $.run(['hash'])]).then(([{ hash }, { hash: sameHash }]) => { | ||
_assert2.default.notEqual(hash, sameHash); | ||
return $.run(['hash']).then(({ hash: yaSameHash }) => { | ||
_assert2.default.notEqual(hash, yaSameHash); | ||
return $.run(['hash']).then(({ | ||
hash: yaSameHash | ||
}) => { | ||
_assert.default.notEqual(hash, yaSameHash); | ||
}); | ||
}).then(() => done()).catch(done); | ||
}); | ||
it('should reuse dependencies when declared as singletons', done => { | ||
@@ -473,8 +478,17 @@ $.constant('ENV', ENV); | ||
}, hashProvider))); | ||
Promise.all([$.run(['hash']), $.run(['hash']), $.run(['hash2']), $.run(['hash2'])]).then(([{ | ||
hash, | ||
hash2 | ||
}, { | ||
hash: sameHash, | ||
hash2: sameHash2 | ||
}]) => { | ||
_assert.default.equal(hash, sameHash); | ||
Promise.all([$.run(['hash']), $.run(['hash']), $.run(['hash2']), $.run(['hash2'])]).then(([{ hash, hash2 }, { hash: sameHash, hash2: sameHash2 }]) => { | ||
_assert2.default.equal(hash, sameHash); | ||
_assert2.default.equal(hash2, sameHash2); | ||
return $.run(['hash']).then(({ hash: yaSameHash }) => { | ||
_assert2.default.equal(hash, yaSameHash); | ||
_assert.default.equal(hash2, sameHash2); | ||
return $.run(['hash']).then(({ | ||
hash: yaSameHash | ||
}) => { | ||
_assert.default.equal(hash, yaSameHash); | ||
}); | ||
@@ -484,7 +498,6 @@ }).then(() => done()).catch(done); | ||
}); | ||
describe('$destroy', () => { | ||
it('should work even with one silo and no dependencies', done => { | ||
$.run(['$destroy']).then(dependencies => { | ||
_assert2.default.equal(typeof dependencies.$destroy, 'function'); | ||
_assert.default.equal(typeof dependencies.$destroy, 'function'); | ||
@@ -494,12 +507,12 @@ return dependencies.$destroy(); | ||
}); | ||
it('should work with several silos and dependencies', done => { | ||
$.constant('ENV', ENV); | ||
$.constant('time', time); | ||
$.provider('hash', (0, _index.inject)(['ENV'], hashProvider), { singleton: true }); | ||
$.provider('hash', (0, _index.inject)(['ENV'], hashProvider), { | ||
singleton: true | ||
}); | ||
$.provider('hash1', (0, _index.inject)(['ENV'], hashProvider)); | ||
$.provider('hash2', (0, _index.inject)(['ENV'], hashProvider)); | ||
Promise.all([$.run(['$destroy']), $.run(['ENV', 'hash', 'hash1', 'time']), $.run(['ENV', 'hash', 'hash2'])]).then(([dependencies]) => { | ||
_assert2.default.equal(typeof dependencies.$destroy, 'function'); | ||
_assert.default.equal(typeof dependencies.$destroy, 'function'); | ||
@@ -509,3 +522,2 @@ return dependencies.$destroy(); | ||
}); | ||
it('should work when trigered from several silos simultaneously', done => { | ||
@@ -517,6 +529,4 @@ $.constant('ENV', ENV); | ||
$.provider('hash2', (0, _index.inject)(['ENV'], hashProvider)); | ||
Promise.all([$.run(['$destroy']), $.run(['$destroy', 'ENV', 'hash', 'hash1', 'time']), $.run(['$destroy', 'ENV', 'hash', 'hash2'])]).then(dependenciesBuckets => Promise.all(dependenciesBuckets.map(dependencies => dependencies.$destroy()))).then(() => done()).catch(done); | ||
}); | ||
it('should work when a silo shutdown is in progress', done => { | ||
@@ -528,6 +538,4 @@ $.constant('ENV', ENV); | ||
$.provider('hash2', (0, _index.inject)(['ENV'], hashProvider)); | ||
Promise.all([$.run(['$destroy']), $.run(['$dispose', 'ENV', 'hash', 'hash1', 'time']), $.run(['ENV', 'hash', 'hash2'])]).then(([dependencies1, dependencies2]) => Promise.all([dependencies2.$dispose(), dependencies1.$destroy()])).then(() => done()).catch(done); | ||
}); | ||
it('should disallow new runs', done => { | ||
@@ -538,10 +546,10 @@ $.constant('ENV', ENV); | ||
$.provider('hash1', (0, _index.inject)(['ENV'], hashProvider)); | ||
$.run(['$destroy']).then(dependencies => { | ||
_assert2.default.equal(typeof dependencies.$destroy, 'function'); | ||
_assert.default.equal(typeof dependencies.$destroy, 'function'); | ||
return dependencies.$destroy(); | ||
}).then(() => { | ||
_assert2.default.throws(() => $.run(['ENV', 'hash', 'hash1']), err => { | ||
_assert2.default.equal(err.code, 'E_INSTANCE_DESTROYED'); | ||
_assert.default.throws(() => $.run(['ENV', 'hash', 'hash1']), err => { | ||
_assert.default.equal(err.code, 'E_INSTANCE_DESTROYED'); | ||
return true; | ||
@@ -552,7 +560,6 @@ }); | ||
}); | ||
describe('$dispose', () => { | ||
it('should work with no dependencies', done => { | ||
$.run(['$dispose']).then(dependencies => { | ||
_assert2.default.equal(typeof dependencies.$dispose, 'function'); | ||
_assert.default.equal(typeof dependencies.$dispose, 'function'); | ||
@@ -562,9 +569,7 @@ return dependencies.$dispose(); | ||
}); | ||
it('should work with constant dependencies', done => { | ||
$.constant('ENV', ENV); | ||
$.constant('time', time); | ||
$.run(['time', 'ENV', '$dispose']).then(dependencies => { | ||
_assert2.default.deepEqual(Object.keys(dependencies), ['time', 'ENV', '$dispose']); | ||
_assert.default.deepEqual(Object.keys(dependencies), ['time', 'ENV', '$dispose']); | ||
@@ -574,3 +579,2 @@ return dependencies.$dispose(); | ||
}); | ||
it('should work with simple dependencies', done => { | ||
@@ -580,5 +584,4 @@ $.constant('ENV', ENV); | ||
$.provider('hash', (0, _index.inject)(['ENV'], hashProvider)); | ||
$.run(['time', 'hash', '$dispose']).then(dependencies => { | ||
_assert2.default.deepEqual(Object.keys(dependencies), ['time', 'hash', '$dispose']); | ||
_assert.default.deepEqual(Object.keys(dependencies), ['time', 'hash', '$dispose']); | ||
@@ -588,3 +591,2 @@ return dependencies.$dispose(); | ||
}); | ||
it('should work with deeper dependencies', done => { | ||
@@ -596,3 +598,4 @@ let shutdownCallResolve; | ||
}); | ||
const shutdownStub = _sinon2.default.spy(() => { | ||
const shutdownStub = _sinon.default.spy(() => { | ||
shutdownCallResolve(); | ||
@@ -619,15 +622,13 @@ return new Promise(resolve => { | ||
}))); | ||
$.run(['hash5', 'time', '$dispose', 'shutdownChecker']).then(dependencies => { | ||
_assert2.default.deepEqual(Object.keys(dependencies), ['hash5', 'time', '$dispose', 'shutdownChecker']); | ||
_assert.default.deepEqual(Object.keys(dependencies), ['hash5', 'time', '$dispose', 'shutdownChecker']); | ||
shutdownCallPromise.then(() => { | ||
_assert2.default.deepEqual(shutdownStub.args, [[]]); | ||
_assert.default.deepEqual(shutdownStub.args, [[]]); | ||
shutdownResolve(); | ||
}).catch(done); | ||
return dependencies.$dispose(); | ||
}).then(done).catch(done); | ||
}); | ||
it('should work with deeper multi used dependencies', done => { | ||
@@ -639,3 +640,4 @@ let shutdownCallResolve; | ||
}); | ||
const shutdownStub = _sinon2.default.spy(() => { | ||
const shutdownStub = _sinon.default.spy(() => { | ||
shutdownCallResolve(); | ||
@@ -658,17 +660,15 @@ return new Promise(resolve => { | ||
$.provider('hash2', (0, _index.inject)(['shutdownChecker'], hashProvider)); | ||
$.run(['hash1', 'hash2', '$dispose', 'shutdownChecker']).then(dependencies => { | ||
_assert2.default.deepEqual(Object.keys(dependencies), ['hash1', 'hash2', '$dispose', 'shutdownChecker']); | ||
_assert.default.deepEqual(Object.keys(dependencies), ['hash1', 'hash2', '$dispose', 'shutdownChecker']); | ||
shutdownCallPromise.then(() => { | ||
_assert2.default.deepEqual(shutdownStub.args, [[]]); | ||
_assert.default.deepEqual(shutdownStub.args, [[]]); | ||
shutdownResolve(); | ||
}).catch(done); | ||
return dependencies.$dispose(); | ||
}).then(() => done()).catch(done); | ||
}); | ||
it('should delay service shutdown to their deeper dependencies', done => { | ||
const servicesShutdownCalls = _sinon2.default.spy(() => Promise.resolve()); | ||
const servicesShutdownCalls = _sinon.default.spy(() => Promise.resolve()); | ||
@@ -687,11 +687,10 @@ $.provider('hash', () => Promise.resolve({ | ||
}))); | ||
$.run(['hash2', '$dispose']).then(dependencies => { | ||
_assert.default.deepEqual(Object.keys(dependencies), ['hash2', '$dispose']); | ||
$.run(['hash2', '$dispose']).then(dependencies => { | ||
_assert2.default.deepEqual(Object.keys(dependencies), ['hash2', '$dispose']); | ||
return dependencies.$dispose(); | ||
}).then(() => { | ||
_assert2.default.deepEqual(servicesShutdownCalls.args, [['hash2'], ['hash1'], ['hash']]); | ||
_assert.default.deepEqual(servicesShutdownCalls.args, [['hash2'], ['hash1'], ['hash']]); | ||
}).then(() => done()).catch(done); | ||
}); | ||
it('should not shutdown singleton dependencies if used elsewhere', done => { | ||
@@ -703,10 +702,11 @@ $.constant('ENV', ENV); | ||
}); | ||
$.run(['time', 'hash']).then(dependencies => { | ||
const { hash } = dependencies; | ||
const { | ||
hash | ||
} = dependencies; | ||
return $.run(['time', 'hash', '$dispose']).then(dependencies => { | ||
_assert.default.equal(dependencies.hash, hash); | ||
return $.run(['time', 'hash', '$dispose']).then(dependencies => { | ||
_assert2.default.equal(dependencies.hash, hash); | ||
return dependencies.$dispose().then(() => $.run(['time', 'hash']).then(dependencies => { | ||
_assert2.default.equal(dependencies.hash, hash); | ||
_assert.default.equal(dependencies.hash, hash); | ||
})); | ||
@@ -716,3 +716,2 @@ }); | ||
}); | ||
it('should shutdown singleton dependencies if not used elsewhere', done => { | ||
@@ -724,8 +723,8 @@ $.constant('ENV', ENV); | ||
}); | ||
$.run(['time', 'hash', '$dispose']).then(dependencies => { | ||
const { hash } = dependencies; | ||
const { | ||
hash | ||
} = dependencies; | ||
return dependencies.$dispose().then(() => $.run(['time', 'hash']).then(dependencies => { | ||
_assert2.default.notEqual(dependencies.hash, hash); | ||
_assert.default.notEqual(dependencies.hash, hash); | ||
})); | ||
@@ -735,3 +734,2 @@ }).then(() => done()).catch(done); | ||
}); | ||
describe('toMermaidGraph', () => { | ||
@@ -741,5 +739,5 @@ it('should print nothing when no dependency', () => { | ||
$.constant('time', time); | ||
_assert2.default.equal($.toMermaidGraph(), ''); | ||
_assert.default.equal($.toMermaidGraph(), ''); | ||
}); | ||
it('should print a dependency graph', () => { | ||
@@ -754,5 +752,5 @@ $.constant('ENV', ENV); | ||
$.provider('hash5', (0, _index.inject)(['hash4'], hashProvider)); | ||
_assert2.default.equal($.toMermaidGraph(), 'graph TD\n' + ' hash-->ENV\n' + ' hash1-->hash\n' + ' hash2-->hash1\n' + ' hash3-->hash2\n' + ' hash4-->hash3\n' + ' hash5-->hash4'); | ||
_assert.default.equal($.toMermaidGraph(), 'graph TD\n' + ' hash-->ENV\n' + ' hash1-->hash\n' + ' hash2-->hash1\n' + ' hash3-->hash2\n' + ' hash4-->hash3\n' + ' hash5-->hash4'); | ||
}); | ||
it('should allow custom shapes', () => { | ||
@@ -767,3 +765,4 @@ $.constant('ENV', ENV); | ||
$.provider('hash5', (0, _index.inject)(['hash4'], hashProvider)); | ||
_assert2.default.equal($.toMermaidGraph({ | ||
_assert.default.equal($.toMermaidGraph({ | ||
shapes: [{ | ||
@@ -781,3 +780,2 @@ pattern: /^hash([0-9]+)$/, | ||
}); | ||
it('should allow custom styles', () => { | ||
@@ -792,3 +790,4 @@ $.constant('ENV', ENV); | ||
$.provider('hash5', (0, _index.inject)(['hash4'], hashProvider)); | ||
_assert2.default.equal($.toMermaidGraph({ | ||
_assert.default.equal($.toMermaidGraph({ | ||
classes: { | ||
@@ -817,2 +816,2 @@ exotic: 'fill:#f9f,stroke:#333,stroke-width:4px;' | ||
}); | ||
}); /* eslint max-nested-callbacks:0 */ | ||
}); |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -6,18 +6,21 @@ Object.defineProperty(exports, "__esModule", { | ||
}); | ||
exports.$ = undefined; | ||
exports.default = exports.$ = void 0; | ||
var _index = require('./index'); | ||
var _index = require("./index"); | ||
const $ = exports.$ = (0, _index.getInstance)(); /* Architecture Note #1.2: One instance to rule them all | ||
We almost never need to use several Knifecycle instances. | ||
This is why we are providing the `knifecycle/instance` | ||
module that give a direct access to a lazy instanciated | ||
`Knifecycle` instance. | ||
At the same time, I prefer choosing when instantiating a | ||
singleton this is why I decided to not do it on the behalf | ||
of the developers by instead providing an opt-in interface | ||
to this singleton. | ||
*/ | ||
exports.default = $; | ||
/* Architecture Note #1.2: One instance to rule them all | ||
We almost never need to use several Knifecycle instances. | ||
This is why we are providing the `knifecycle/instance` | ||
module that give a direct access to a lazy instanciated | ||
`Knifecycle` instance. | ||
At the same time, I prefer choosing when instantiating a | ||
singleton this is why I decided to not do it on the behalf | ||
of the developers by instead providing an opt-in interface | ||
to this singleton. | ||
*/ | ||
const $ = (0, _index.getInstance)(); | ||
exports.$ = $; | ||
var _default = $; | ||
exports.default = _default; |
@@ -1,15 +0,9 @@ | ||
'use strict'; | ||
"use strict"; | ||
var _assert = require('assert'); | ||
var _assert = _interopRequireDefault(require("assert")); | ||
var _assert2 = _interopRequireDefault(_assert); | ||
var _index = _interopRequireDefault(require("./index")); | ||
var _index = require('./index'); | ||
var _instance = _interopRequireDefault(require("./instance")); | ||
var _index2 = _interopRequireDefault(_index); | ||
var _instance = require('./instance'); | ||
var _instance2 = _interopRequireDefault(_instance); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
@@ -19,4 +13,4 @@ | ||
it('should provide the singleton instance', () => { | ||
_assert2.default.equal(_instance2.default, _index2.default.getInstance()); | ||
_assert.default.equal(_instance.default, _index.default.getInstance()); | ||
}); | ||
}); |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -8,6 +8,4 @@ Object.defineProperty(exports, "__esModule", { | ||
var _yerror = require('yerror'); | ||
var _yerror = _interopRequireDefault(require("yerror")); | ||
var _yerror2 = _interopRequireDefault(_yerror); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
@@ -27,2 +25,3 @@ | ||
} | ||
batches.push(batch); | ||
@@ -33,3 +32,3 @@ i++; | ||
if (i === MAX_ITERATIONS) { | ||
throw new _yerror2.default('E_PROBABLE_CIRCULAR_DEPENDENCY'); | ||
throw new _yerror.default('E_PROBABLE_CIRCULAR_DEPENDENCY'); | ||
} | ||
@@ -36,0 +35,0 @@ |
@@ -1,9 +0,7 @@ | ||
'use strict'; | ||
"use strict"; | ||
var _assert = require('assert'); | ||
var _assert = _interopRequireDefault(require("assert")); | ||
var _assert2 = _interopRequireDefault(_assert); | ||
var _sequence = require("./sequence"); | ||
var _sequence = require('./sequence'); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
@@ -17,5 +15,4 @@ | ||
_assert2.default.deepEqual((0, _sequence.buildInitializationSequence)(tree), [['lol']]); | ||
_assert.default.deepEqual((0, _sequence.buildInitializationSequence)(tree), [['lol']]); | ||
}); | ||
it('should work with multi-level trees', () => { | ||
@@ -53,5 +50,4 @@ const tree = { | ||
_assert2.default.deepEqual((0, _sequence.buildInitializationSequence)(tree), [['lol 1.1.1', 'lol 1.2', 'lol 2.1', 'lol 3.1.1'], ['lol 1.1', 'lol 2', 'lol 3.1'], ['lol 1', 'lol 3'], ['lol']]); | ||
_assert.default.deepEqual((0, _sequence.buildInitializationSequence)(tree), [['lol 1.1.1', 'lol 1.2', 'lol 2.1', 'lol 3.1.1'], ['lol 1.1', 'lol 2', 'lol 3.1'], ['lol 1', 'lol 3'], ['lol']]); | ||
}); | ||
it('should work with multi-level trees and cross dependencies', () => { | ||
@@ -107,4 +103,4 @@ const tree = { | ||
_assert2.default.deepEqual((0, _sequence.buildInitializationSequence)(tree), [['lol 1.1.1', 'lol 1.2', 'lol 2.1'], ['lol 1.1', 'lol 2'], ['lol 3.1'], ['lol 3'], ['lol 1.3'], ['lol 1'], ['lol']]); | ||
_assert.default.deepEqual((0, _sequence.buildInitializationSequence)(tree), [['lol 1.1.1', 'lol 1.2', 'lol 2.1'], ['lol 1.1', 'lol 2'], ['lol 3.1'], ['lol 3'], ['lol 1.3'], ['lol 1'], ['lol']]); | ||
}); | ||
}); |
102
dist/util.js
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -6,3 +6,2 @@ Object.defineProperty(exports, "__esModule", { | ||
}); | ||
exports.OPTIONAL_FLAG = exports.DECLARATION_SEPARATOR = exports.ALLOWED_SPECIAL_PROPS = exports.SPECIAL_PROPS = exports.SPECIAL_PROPS_PREFIX = undefined; | ||
exports.reuseSpecialProps = reuseSpecialProps; | ||
@@ -18,17 +17,18 @@ exports.wrapInitializer = wrapInitializer; | ||
exports.parseDependencyDeclaration = parseDependencyDeclaration; | ||
exports.OPTIONAL_FLAG = exports.DECLARATION_SEPARATOR = exports.ALLOWED_SPECIAL_PROPS = exports.SPECIAL_PROPS = exports.SPECIAL_PROPS_PREFIX = void 0; | ||
var _yerror = require('yerror'); | ||
var _yerror = _interopRequireDefault(require("yerror")); | ||
var _yerror2 = _interopRequireDefault(_yerror); | ||
var _debug = _interopRequireDefault(require("debug")); | ||
var _debug = require('debug'); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
var _debug2 = _interopRequireDefault(_debug); | ||
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; } | ||
const debug = (0, _debug2.default)('knifecycle'); | ||
const SPECIAL_PROPS_PREFIX = exports.SPECIAL_PROPS_PREFIX = '$'; | ||
const SPECIAL_PROPS = exports.SPECIAL_PROPS = { | ||
const debug = (0, _debug.default)('knifecycle'); | ||
const SPECIAL_PROPS_PREFIX = '$'; | ||
exports.SPECIAL_PROPS_PREFIX = SPECIAL_PROPS_PREFIX; | ||
const SPECIAL_PROPS = { | ||
INJECT: `${SPECIAL_PROPS_PREFIX}inject`, | ||
@@ -40,6 +40,8 @@ OPTIONS: `${SPECIAL_PROPS_PREFIX}options`, | ||
}; | ||
const ALLOWED_SPECIAL_PROPS = exports.ALLOWED_SPECIAL_PROPS = Object.keys(SPECIAL_PROPS).map(key => SPECIAL_PROPS[key]); | ||
const DECLARATION_SEPARATOR = exports.DECLARATION_SEPARATOR = '>'; | ||
const OPTIONAL_FLAG = exports.OPTIONAL_FLAG = '?'; | ||
exports.SPECIAL_PROPS = SPECIAL_PROPS; | ||
const ALLOWED_SPECIAL_PROPS = Object.keys(SPECIAL_PROPS).map(key => SPECIAL_PROPS[key]); | ||
exports.ALLOWED_SPECIAL_PROPS = ALLOWED_SPECIAL_PROPS; | ||
const DECLARATION_SEPARATOR = '>'; | ||
exports.DECLARATION_SEPARATOR = DECLARATION_SEPARATOR; | ||
const OPTIONAL_FLAG = '?'; | ||
/** | ||
@@ -52,5 +54,9 @@ * Apply special props to the given function from another one | ||
*/ | ||
exports.OPTIONAL_FLAG = OPTIONAL_FLAG; | ||
function reuseSpecialProps(from, to, amend = {}) { | ||
return [...new Set(Object.keys(from).concat(Object.keys(amend)))].filter(prop => prop.startsWith(SPECIAL_PROPS_PREFIX)).reduce((fn, prop) => { | ||
const value = 'undefined' !== typeof amend[prop] ? amend[prop] : from[prop]; | ||
if (value instanceof Array) { | ||
@@ -63,6 +69,6 @@ fn[prop] = value.concat(); | ||
} | ||
return fn; | ||
}, to.bind()); | ||
} | ||
/** | ||
@@ -78,6 +84,7 @@ * Allows to wrap an initializer to add extra | ||
*/ | ||
function wrapInitializer(wrapper, baseInitializer) { | ||
return reuseSpecialProps(baseInitializer, services => baseInitializer(services).then(wrapper.bind(null, services))); | ||
} | ||
/** | ||
@@ -107,2 +114,4 @@ * Decorator creating a new initializer with some | ||
*/ | ||
function inject(dependenciesDeclarations, initializer, merge = false) { | ||
@@ -112,8 +121,5 @@ const uniqueInitializer = reuseSpecialProps(initializer, initializer, { | ||
}); | ||
debug('Wrapped an initializer with dependencies:', dependenciesDeclarations); | ||
return uniqueInitializer; | ||
} | ||
/** | ||
@@ -144,2 +150,4 @@ * Decorator creating a new initializer with some | ||
*/ | ||
function extra(extraInformations, initializer, merge = false) { | ||
@@ -149,8 +157,5 @@ const uniqueInitializer = reuseSpecialProps(initializer, initializer, { | ||
}); | ||
debug('Wrapped an initializer with extra informations:', extraInformations); | ||
return uniqueInitializer; | ||
} | ||
/** | ||
@@ -181,2 +186,4 @@ * Decorator to amend an initializer options. | ||
*/ | ||
function options(options, initializer, merge = false) { | ||
@@ -186,8 +193,5 @@ const uniqueInitializer = reuseSpecialProps(initializer, initializer, { | ||
}); | ||
debug('Wrapped an initializer with options:', options); | ||
return uniqueInitializer; | ||
} | ||
/** | ||
@@ -209,2 +213,4 @@ * Decorator to set an initializer name. | ||
*/ | ||
function name(name, initializer) { | ||
@@ -214,8 +220,5 @@ const uniqueInitializer = reuseSpecialProps(initializer, initializer, { | ||
}); | ||
debug('Wrapped an initializer with a name:', name); | ||
return uniqueInitializer; | ||
} | ||
/** | ||
@@ -243,2 +246,4 @@ * Decorator to set an initializer type. | ||
*/ | ||
function type(type, initializer) { | ||
@@ -248,8 +253,5 @@ const uniqueInitializer = reuseSpecialProps(initializer, initializer, { | ||
}); | ||
debug('Wrapped an initializer with a type:', type); | ||
return uniqueInitializer; | ||
} | ||
/** | ||
@@ -276,2 +278,4 @@ * Decorator to set an initializer properties. | ||
*/ | ||
function initializer(properties, initializer) { | ||
@@ -282,13 +286,11 @@ const uniqueInitializer = reuseSpecialProps(initializer, initializer, Object.keys(properties).reduce((finalProperties, property) => { | ||
if (!ALLOWED_SPECIAL_PROPS.includes(finalProperty)) { | ||
throw new _yerror2.default('E_BAD_PROPERTY', property); | ||
throw new _yerror.default('E_BAD_PROPERTY', property); | ||
} | ||
finalProperties[finalProperty] = properties[property]; | ||
return finalProperties; | ||
}, {})); | ||
debug('Wrapped an initializer with properties:', properties); | ||
return uniqueInitializer; | ||
} | ||
/** | ||
@@ -300,2 +302,4 @@ * Shortcut to create an initializer with a simple handler | ||
* The dependencies to inject in it | ||
* @param {Object} [extra] | ||
* Optional extra data to associate with the handler | ||
* @return {Function} | ||
@@ -316,13 +320,26 @@ * Returns a new initializer | ||
*/ | ||
function handler(handlerFunction, dependencies = []) { | ||
function handler(handlerFunction, dependencies = [], extra) { | ||
if (!handlerFunction.name) { | ||
throw new _yerror2.default('E_NO_HANDLER_NAME'); | ||
throw new _yerror.default('E_NO_HANDLER_NAME'); | ||
} | ||
return initializer({ | ||
name: handlerFunction.name, | ||
type: 'service', | ||
inject: dependencies | ||
}, (...args) => Promise.resolve(handlerFunction.bind(null, ...args))); | ||
inject: dependencies, | ||
extra | ||
}, | ||
/*#__PURE__*/ | ||
function () { | ||
var _ref = _asyncToGenerator(function* (...args) { | ||
return handlerFunction.bind(null, ...args); | ||
}); | ||
return function () { | ||
return _ref.apply(this, arguments); | ||
}; | ||
}()); | ||
} | ||
/* Architecture Note #1.3.1: Dependencies declaration syntax | ||
@@ -354,6 +371,7 @@ | ||
*/ | ||
function parseDependencyDeclaration(dependencyDeclaration) { | ||
const optional = dependencyDeclaration.startsWith(OPTIONAL_FLAG); | ||
const [serviceName, mappedName] = (optional ? dependencyDeclaration.slice(1) : dependencyDeclaration).split(DECLARATION_SEPARATOR); | ||
return { | ||
@@ -360,0 +378,0 @@ serviceName, |
@@ -1,13 +0,9 @@ | ||
'use strict'; | ||
"use strict"; | ||
var _assert = require('assert'); | ||
var _assert = _interopRequireDefault(require("assert")); | ||
var _assert2 = _interopRequireDefault(_assert); | ||
var _sinon = _interopRequireDefault(require("sinon")); | ||
var _sinon = require('sinon'); | ||
var _util = require("./util"); | ||
var _sinon2 = _interopRequireDefault(_sinon); | ||
var _util = require('./util'); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
@@ -21,2 +17,3 @@ | ||
// function are here just as placeholders | ||
/* istanbul ignore next */ | ||
@@ -27,2 +24,4 @@ function from() { | ||
/* istanbul ignore next */ | ||
function to() { | ||
@@ -35,17 +34,28 @@ return 'to'; | ||
from.$inject = ['ki', 'kooo', 'lol']; | ||
from.$options = { singleton: false }; | ||
from.$extra = { httpHandler: true }; | ||
from.$options = { | ||
singleton: false | ||
}; | ||
from.$extra = { | ||
httpHandler: true | ||
}; | ||
const newFn = (0, _util.reuseSpecialProps)(from, to); | ||
_assert2.default.notEqual(newFn, to); | ||
_assert2.default.equal(newFn.$name, from.$name); | ||
_assert2.default.equal(newFn.$type, from.$type); | ||
_assert2.default.notEqual(newFn.$inject, from.$inject); | ||
_assert2.default.deepEqual(newFn.$inject, from.$inject); | ||
_assert2.default.notEqual(newFn.$options, from.$options); | ||
_assert2.default.deepEqual(newFn.$options, from.$options); | ||
_assert2.default.notEqual(newFn.$extra, from.$extra); | ||
_assert2.default.deepEqual(newFn.$extra, from.$extra); | ||
_assert.default.notEqual(newFn, to); | ||
_assert.default.equal(newFn.$name, from.$name); | ||
_assert.default.equal(newFn.$type, from.$type); | ||
_assert.default.notEqual(newFn.$inject, from.$inject); | ||
_assert.default.deepEqual(newFn.$inject, from.$inject); | ||
_assert.default.notEqual(newFn.$options, from.$options); | ||
_assert.default.deepEqual(newFn.$options, from.$options); | ||
_assert.default.notEqual(newFn.$extra, from.$extra); | ||
_assert.default.deepEqual(newFn.$extra, from.$extra); | ||
const newFn2 = (0, _util.reuseSpecialProps)(from, to, { | ||
@@ -55,14 +65,21 @@ $name: 'yolo' | ||
_assert2.default.notEqual(newFn2, to); | ||
_assert2.default.equal(newFn2.$name, 'yolo'); | ||
_assert2.default.equal(newFn2.$type, from.$type); | ||
_assert2.default.notEqual(newFn2.$inject, from.$inject); | ||
_assert2.default.deepEqual(newFn2.$inject, from.$inject); | ||
_assert2.default.notEqual(newFn2.$options, from.$options); | ||
_assert2.default.deepEqual(newFn2.$options, from.$options); | ||
_assert2.default.notEqual(newFn.$extra, from.$extra); | ||
_assert2.default.deepEqual(newFn.$extra, from.$extra); | ||
_assert.default.notEqual(newFn2, to); | ||
_assert.default.equal(newFn2.$name, 'yolo'); | ||
_assert.default.equal(newFn2.$type, from.$type); | ||
_assert.default.notEqual(newFn2.$inject, from.$inject); | ||
_assert.default.deepEqual(newFn2.$inject, from.$inject); | ||
_assert.default.notEqual(newFn2.$options, from.$options); | ||
_assert.default.deepEqual(newFn2.$options, from.$options); | ||
_assert.default.notEqual(newFn.$extra, from.$extra); | ||
_assert.default.deepEqual(newFn.$extra, from.$extra); | ||
}); | ||
}); | ||
describe('wrapInitializer', done => { | ||
@@ -77,18 +94,26 @@ it('should work', () => { | ||
baseInitializer.$inject = ['log']; | ||
baseInitializer.$options = { singleton: false }; | ||
baseInitializer.$extra = { httpHandler: false }; | ||
baseInitializer.$options = { | ||
singleton: false | ||
}; | ||
baseInitializer.$extra = { | ||
httpHandler: false | ||
}; | ||
const log = _sinon2.default.stub(); | ||
const newInitializer = (0, _util.wrapInitializer)(({ log }, service) => { | ||
const log = _sinon.default.stub(); | ||
const newInitializer = (0, _util.wrapInitializer)(({ | ||
log | ||
}, service) => { | ||
log('Wrapping...'); | ||
return () => service() + '-wrapped'; | ||
}, baseInitializer); | ||
newInitializer({ | ||
log | ||
}).then(service => { | ||
_assert.default.equal(service(), 'test-wrapped'); | ||
newInitializer({ log }).then(service => { | ||
_assert2.default.equal(service(), 'test-wrapped'); | ||
_assert2.default.deepEqual(log.args, [['Wrapping...']]); | ||
_assert.default.deepEqual(log.args, [['Wrapping...']]); | ||
}).then(done).catch(done); | ||
}); | ||
}); | ||
describe('inject', () => { | ||
@@ -99,7 +124,8 @@ it('should allow to decorate an initializer with dependencies', () => { | ||
_assert2.default.notEqual(newInitializer, aProvider); | ||
_assert2.default.notEqual(newInitializer[_util.SPECIAL_PROPS.INJECT], dependencies); | ||
_assert2.default.deepEqual(newInitializer[_util.SPECIAL_PROPS.INJECT], dependencies); | ||
_assert.default.notEqual(newInitializer, aProvider); | ||
_assert.default.notEqual(newInitializer[_util.SPECIAL_PROPS.INJECT], dependencies); | ||
_assert.default.deepEqual(newInitializer[_util.SPECIAL_PROPS.INJECT], dependencies); | ||
}); | ||
it('should allow to decorate an initializer with mapped dependencies', () => { | ||
@@ -109,53 +135,70 @@ const dependencies = ['ANOTHER_ENV>ENV']; | ||
_assert2.default.notEqual(newInitializer, aProvider); | ||
_assert2.default.notEqual(newInitializer[_util.SPECIAL_PROPS.INJECT], dependencies); | ||
_assert2.default.deepEqual(newInitializer[_util.SPECIAL_PROPS.INJECT], dependencies); | ||
_assert.default.notEqual(newInitializer, aProvider); | ||
_assert.default.notEqual(newInitializer[_util.SPECIAL_PROPS.INJECT], dependencies); | ||
_assert.default.deepEqual(newInitializer[_util.SPECIAL_PROPS.INJECT], dependencies); | ||
}); | ||
}); | ||
describe('options', () => { | ||
it('should allow to decorate an initializer with options', () => { | ||
const dependencies = ['ANOTHER_ENV>ENV']; | ||
const baseOptions = { singleton: true }; | ||
const baseOptions = { | ||
singleton: true | ||
}; | ||
const newInitializer = (0, _util.inject)(dependencies, (0, _util.options)(baseOptions, aProvider)); | ||
_assert2.default.notEqual(newInitializer, aProvider); | ||
_assert2.default.notEqual(newInitializer[_util.SPECIAL_PROPS.INJECT], dependencies); | ||
_assert2.default.deepEqual(newInitializer[_util.SPECIAL_PROPS.INJECT], dependencies); | ||
_assert2.default.notEqual(newInitializer[_util.SPECIAL_PROPS.OPTIONS], baseOptions); | ||
_assert2.default.deepEqual(newInitializer[_util.SPECIAL_PROPS.OPTIONS], baseOptions); | ||
_assert.default.notEqual(newInitializer, aProvider); | ||
_assert.default.notEqual(newInitializer[_util.SPECIAL_PROPS.INJECT], dependencies); | ||
_assert.default.deepEqual(newInitializer[_util.SPECIAL_PROPS.INJECT], dependencies); | ||
_assert.default.notEqual(newInitializer[_util.SPECIAL_PROPS.OPTIONS], baseOptions); | ||
_assert.default.deepEqual(newInitializer[_util.SPECIAL_PROPS.OPTIONS], baseOptions); | ||
}); | ||
}); | ||
describe('name', () => { | ||
it('should allow to decorate an initializer with a name', () => { | ||
const dependencies = ['ANOTHER_ENV>ENV']; | ||
const baseOptions = { singleton: true }; | ||
const baseOptions = { | ||
singleton: true | ||
}; | ||
const baseName = 'hash'; | ||
const newInitializer = (0, _util.inject)(dependencies, (0, _util.options)(baseOptions, (0, _util.name)(baseName, aProvider))); | ||
_assert2.default.notEqual(newInitializer, aProvider); | ||
_assert2.default.notEqual(newInitializer[_util.SPECIAL_PROPS.INJECT], dependencies); | ||
_assert2.default.deepEqual(newInitializer[_util.SPECIAL_PROPS.INJECT], dependencies); | ||
_assert2.default.notEqual(newInitializer[_util.SPECIAL_PROPS.OPTIONS], baseOptions); | ||
_assert2.default.deepEqual(newInitializer[_util.SPECIAL_PROPS.OPTIONS], baseOptions); | ||
_assert2.default.equal(newInitializer[_util.SPECIAL_PROPS.NAME], baseName); | ||
_assert.default.notEqual(newInitializer, aProvider); | ||
_assert.default.notEqual(newInitializer[_util.SPECIAL_PROPS.INJECT], dependencies); | ||
_assert.default.deepEqual(newInitializer[_util.SPECIAL_PROPS.INJECT], dependencies); | ||
_assert.default.notEqual(newInitializer[_util.SPECIAL_PROPS.OPTIONS], baseOptions); | ||
_assert.default.deepEqual(newInitializer[_util.SPECIAL_PROPS.OPTIONS], baseOptions); | ||
_assert.default.equal(newInitializer[_util.SPECIAL_PROPS.NAME], baseName); | ||
}); | ||
}); | ||
describe('extra', () => { | ||
it('should allow to decorate an initializer with extra infos', () => { | ||
const extraInformations = { httpHandler: true }; | ||
const extraInformations = { | ||
httpHandler: true | ||
}; | ||
const newInitializer = (0, _util.extra)(extraInformations, aProvider); | ||
_assert2.default.notEqual(newInitializer, aProvider); | ||
_assert2.default.notEqual(newInitializer[_util.SPECIAL_PROPS.EXTRA], extraInformations); | ||
_assert2.default.deepEqual(newInitializer[_util.SPECIAL_PROPS.EXTRA], extraInformations); | ||
_assert.default.notEqual(newInitializer, aProvider); | ||
_assert.default.notEqual(newInitializer[_util.SPECIAL_PROPS.EXTRA], extraInformations); | ||
_assert.default.deepEqual(newInitializer[_util.SPECIAL_PROPS.EXTRA], extraInformations); | ||
}); | ||
}); | ||
describe('type', () => { | ||
it('should allow to decorate an initializer with a type', () => { | ||
const dependencies = ['ANOTHER_ENV>ENV']; | ||
const baseOptions = { singleton: true }; | ||
const baseOptions = { | ||
singleton: true | ||
}; | ||
const baseName = 'hash'; | ||
@@ -165,16 +208,23 @@ const baseType = 'service'; | ||
_assert2.default.notEqual(newInitializer, aProvider); | ||
_assert2.default.notEqual(newInitializer[_util.SPECIAL_PROPS.INJECT], dependencies); | ||
_assert2.default.deepEqual(newInitializer[_util.SPECIAL_PROPS.INJECT], dependencies); | ||
_assert2.default.notEqual(newInitializer[_util.SPECIAL_PROPS.OPTIONS], baseOptions); | ||
_assert2.default.deepEqual(newInitializer[_util.SPECIAL_PROPS.OPTIONS], baseOptions); | ||
_assert2.default.equal(newInitializer[_util.SPECIAL_PROPS.NAME], baseName); | ||
_assert2.default.equal(newInitializer[_util.SPECIAL_PROPS.TYPE], baseType); | ||
_assert.default.notEqual(newInitializer, aProvider); | ||
_assert.default.notEqual(newInitializer[_util.SPECIAL_PROPS.INJECT], dependencies); | ||
_assert.default.deepEqual(newInitializer[_util.SPECIAL_PROPS.INJECT], dependencies); | ||
_assert.default.notEqual(newInitializer[_util.SPECIAL_PROPS.OPTIONS], baseOptions); | ||
_assert.default.deepEqual(newInitializer[_util.SPECIAL_PROPS.OPTIONS], baseOptions); | ||
_assert.default.equal(newInitializer[_util.SPECIAL_PROPS.NAME], baseName); | ||
_assert.default.equal(newInitializer[_util.SPECIAL_PROPS.TYPE], baseType); | ||
}); | ||
}); | ||
describe('initializer', () => { | ||
it('should allow to decorate an initializer with every properties', () => { | ||
const dependencies = ['ANOTHER_ENV>ENV']; | ||
const baseOptions = { singleton: true }; | ||
const baseOptions = { | ||
singleton: true | ||
}; | ||
const baseName = 'hash'; | ||
@@ -189,12 +239,17 @@ const baseType = 'service'; | ||
_assert2.default.notEqual(newInitializer, aProvider); | ||
_assert2.default.notEqual(newInitializer[_util.SPECIAL_PROPS.INJECT], dependencies); | ||
_assert2.default.deepEqual(newInitializer[_util.SPECIAL_PROPS.INJECT], dependencies); | ||
_assert2.default.notEqual(newInitializer[_util.SPECIAL_PROPS.OPTIONS], baseOptions); | ||
_assert2.default.deepEqual(newInitializer[_util.SPECIAL_PROPS.OPTIONS], baseOptions); | ||
_assert2.default.equal(newInitializer[_util.SPECIAL_PROPS.NAME], baseName); | ||
_assert2.default.equal(newInitializer[_util.SPECIAL_PROPS.TYPE], baseType); | ||
_assert.default.notEqual(newInitializer, aProvider); | ||
_assert.default.notEqual(newInitializer[_util.SPECIAL_PROPS.INJECT], dependencies); | ||
_assert.default.deepEqual(newInitializer[_util.SPECIAL_PROPS.INJECT], dependencies); | ||
_assert.default.notEqual(newInitializer[_util.SPECIAL_PROPS.OPTIONS], baseOptions); | ||
_assert.default.deepEqual(newInitializer[_util.SPECIAL_PROPS.OPTIONS], baseOptions); | ||
_assert.default.equal(newInitializer[_util.SPECIAL_PROPS.NAME], baseName); | ||
_assert.default.equal(newInitializer[_util.SPECIAL_PROPS.TYPE], baseType); | ||
}); | ||
}); | ||
describe('handler', () => { | ||
@@ -209,6 +264,7 @@ it('should work', () => { | ||
_assert2.default.deepEqual(theInitializer.$name, sampleHandler.name); | ||
_assert2.default.deepEqual(theInitializer.$inject, ['kikooo', 'lol']); | ||
_assert.default.deepEqual(theInitializer.$name, sampleHandler.name); | ||
return theInitializer(services).then(theHandler => theHandler('test')).then(result => _assert2.default.deepEqual(result, { | ||
_assert.default.deepEqual(theInitializer.$inject, ['kikooo', 'lol']); | ||
return theInitializer(services).then(theHandler => theHandler('test')).then(result => _assert.default.deepEqual(result, { | ||
deps: services, | ||
@@ -219,8 +275,10 @@ args: ['test'] | ||
function sampleHandler(deps, ...args) { | ||
return Promise.resolve({ deps, args }); | ||
return Promise.resolve({ | ||
deps, | ||
args | ||
}); | ||
} | ||
}); | ||
it('should fail for anonymous functions', () => { | ||
_assert2.default.throws(() => { | ||
_assert.default.throws(() => { | ||
(0, _util.handler)(() => {}); | ||
@@ -230,6 +288,5 @@ }, /E_NO_HANDLER_NAME/); | ||
}); | ||
describe('parseDependencyDeclaration', () => { | ||
it('should work', () => { | ||
_assert2.default.deepEqual((0, _util.parseDependencyDeclaration)('pgsql>db'), { | ||
_assert.default.deepEqual((0, _util.parseDependencyDeclaration)('pgsql>db'), { | ||
serviceName: 'pgsql', | ||
@@ -236,0 +293,0 @@ mappedName: 'db', |
{ | ||
"name": "knifecycle", | ||
"version": "2.5.2", | ||
"version": "2.5.3", | ||
"description": "Manage your NodeJS processes's lifecycle.", | ||
@@ -38,4 +38,4 @@ "main": "dist/index.js", | ||
"compile": "babel src --out-dir=dist", | ||
"cover": "istanbul cover _mocha --report html -- --compilers js:babel-register src/*.mocha.js -R spec -t 5000", | ||
"coveralls": "istanbul cover _mocha --report lcovonly -- --compilers js:babel-register src/*.mocha.js -R spec -t 5000 && cat ./coverage/lcov.info | coveralls && rm -rf ./coverage", | ||
"cover": "nyc npm test && nyc report --reporter=text", | ||
"coveralls": "nyc npm test && nyc report --reporter=text-lcov | coveralls && rm -rf ./coverage", | ||
"cz": "env NODE_ENV=${NODE_ENV:-cli} git cz", | ||
@@ -46,3 +46,3 @@ "doc": "echo \"# API\" > API.md; jsdoc2md src/*.js >> API.md", | ||
"metapak": "metapak", | ||
"mocha": "mocha --compilers js:babel-register src/*.mocha.js", | ||
"mocha": "mocha --compilers js:@babel/register src/*.mocha.js", | ||
"prepublish": "npm run compile", | ||
@@ -63,34 +63,33 @@ "prettier": "prettier --write src/*.js", | ||
"devDependencies": { | ||
"babel-cli": "^6.26.0", | ||
"babel-core": "^6.26.0", | ||
"babel-eslint": "^8.2.2", | ||
"babel-plugin-transform-object-rest-spread": "^6.26.0", | ||
"babel-preset-env": "^1.6.1", | ||
"babel-register": "^6.26.0", | ||
"browserify": "^14.4.0", | ||
"commitizen": "^2.9.6", | ||
"conventional-changelog-cli": "^1.3.8", | ||
"coveralls": "^3.0.0", | ||
"@babel/cli": "^7.0.0", | ||
"@babel/core": "^7.0.1", | ||
"@babel/plugin-proposal-object-rest-spread": "^7.0.0", | ||
"@babel/preset-env": "^7.0.0", | ||
"@babel/register": "^7.0.0", | ||
"babel-eslint": "^9.0.0", | ||
"browserify": "^16.2.2", | ||
"commitizen": "^2.10.1", | ||
"conventional-changelog-cli": "^2.0.5", | ||
"coveralls": "^3.0.2", | ||
"cz-conventional-changelog": "^2.1.0", | ||
"eslint": "^4.19.0", | ||
"eslint-plugin-prettier": "^2.6.0", | ||
"istanbul": "^1.0.0-alpha.2", | ||
"eslint": "^5.6.0", | ||
"eslint-plugin-prettier": "^2.6.2", | ||
"jsarch": "^1.3.0", | ||
"jsdoc-to-markdown": "^4.0.1", | ||
"karma": "^2.0.0", | ||
"karma-browserify": "^5.1.2", | ||
"karma": "^3.0.0", | ||
"karma-browserify": "^5.3.0", | ||
"karma-chrome-launcher": "^2.2.0", | ||
"karma-firefox-launcher": "^1.1.0", | ||
"karma-mocha": "^1.3.0", | ||
"karma-sauce-launcher": "^1.1.0", | ||
"karma-sauce-launcher": "^1.2.0", | ||
"metapak": "^1.0.3", | ||
"metapak-nfroidure": "^6.1.0", | ||
"mocha": "^5.0.0", | ||
"mocha-lcov-reporter": "^1.3.0", | ||
"prettier": "^1.11.1", | ||
"sinon": "^4.4.6" | ||
"metapak-nfroidure": "^6.3.0", | ||
"mocha": "^5.2.0", | ||
"nyc": "^13.0.1", | ||
"prettier": "^1.14.2", | ||
"sinon": "^6.3.3" | ||
}, | ||
"dependencies": { | ||
"debug": "^3.1.0", | ||
"yerror": "^2.1.0" | ||
"debug": "^4.0.1", | ||
"yerror": "^2.1.3" | ||
}, | ||
@@ -108,8 +107,11 @@ "config": { | ||
"mocha", | ||
"mocha-lcov-reporter", | ||
"coveralls", | ||
"istanbul", | ||
"nyc", | ||
"eslint", | ||
"eslint-config-prettier", | ||
"prettier", | ||
"karma", | ||
"karma-chrome-launcher", | ||
"karma-firefox-launcher", | ||
"karma-mocha", | ||
"jsdoc-to-markdown", | ||
@@ -122,3 +124,3 @@ "jsarch" | ||
[ | ||
"env", | ||
"@babel/env", | ||
{ | ||
@@ -132,5 +134,5 @@ "targets": { | ||
"plugins": [ | ||
"transform-object-rest-spread" | ||
"@babel/plugin-proposal-object-rest-spread" | ||
] | ||
} | ||
} |
115
README.md
@@ -109,3 +109,3 @@ [//]: # ( ) | ||
// be set as a property of an object in first argument. | ||
}, ({ ENV }) => { | ||
}, async ({ ENV }) => { | ||
return new Promise((resolve, reject) { | ||
@@ -149,21 +149,19 @@ fs.readFile(ENV.CONFIG_PATH, function(err, data) { | ||
// handle the service unrecoverable failure. | ||
type: 'provider',, | ||
type: 'provider', | ||
options: { singleton: true }, | ||
}, ({ CONFIG, log }) { | ||
return MongoClient.connect(CONFIG.DB_URI) | ||
.then(function(db) { | ||
let fatalErrorPromise = new Promise((resolve, reject) { | ||
db.once('error', reject); | ||
}); | ||
}, async ({ CONFIG, log }) { | ||
const db = await MongoClient.connect(CONFIG.DB_URI); | ||
let fatalErrorPromise = new Promise((resolve, reject) { | ||
db.once('error', reject); | ||
}); | ||
// Logging only if the `log` service is defined | ||
log && log('info', 'db service initialized!'); | ||
// Logging only if the `log` service is defined | ||
log && log('info', 'db service initialized!'); | ||
return { | ||
service: db, | ||
dispose: db.close.bind(db, true), | ||
fatalErrorPromise, | ||
}; | ||
}); | ||
} | ||
return { | ||
service: db, | ||
dispose: db.close.bind(db, true), | ||
fatalErrorPromise, | ||
}; | ||
}); | ||
``` | ||
@@ -181,6 +179,6 @@ | ||
options: { singleton: true }, | ||
}, ({ ENV, CONFIG, log }) => { | ||
}, async ({ ENV, CONFIG, log }) => { | ||
const app = express(); | ||
return new Promise((resolve, reject) => { | ||
const server = new Promise((resolve, reject) => { | ||
const port = ENV.PORT || CONFIG.PORT; | ||
@@ -191,26 +189,26 @@ const server = app.listen(port, () => { | ||
}); | ||
}).then(function(server) { | ||
let fatalErrorPromise = new Promise((resolve, reject) { | ||
app.once('error', reject); | ||
server.once('error', reject); | ||
}); | ||
let fatalErrorPromise = new Promise((resolve, reject) { | ||
app.once('error', reject); | ||
server.once('error', reject); | ||
}); | ||
function dispose() { | ||
return new Promise((resolve, reject) => { | ||
server.close((err) => { | ||
if(err) { | ||
reject(err); | ||
return; | ||
} | ||
resolve(); | ||
}) | ||
}); | ||
} | ||
function dispose() { | ||
return new Promise((resolve, reject) => { | ||
server.close((err) => { | ||
if(err) { | ||
reject(err); | ||
return; | ||
} | ||
resolve(); | ||
}) | ||
}); | ||
} | ||
return { | ||
service: app, | ||
dispose, | ||
fatalErrorPromise, | ||
}; | ||
}); | ||
return { | ||
service: app, | ||
dispose, | ||
fatalErrorPromise, | ||
}; | ||
}); | ||
@@ -246,8 +244,8 @@ ``` | ||
// on which the `db2` service now depends on | ||
.register(name('DB2_CONFIG', inject(['CONFIG'], ({ CONFIG }) => { | ||
.register(name('DB2_CONFIG', inject(['CONFIG'], async ({ CONFIG }) => { | ||
// Let's just pick up the `db2` uri in the `CONFIG` | ||
// service | ||
return Promise.resolve({ | ||
return { | ||
DB_URI: CONFIG.DB2_URI, | ||
}); | ||
}; | ||
}))) | ||
@@ -271,11 +269,8 @@ // Add the process environment as a simple constant | ||
['server', 'now', '?log'], | ||
({ server: app, now, log }) { | ||
return Promise.resolve() | ||
.then(() => { | ||
app.get('/time', (req, res, next) => { | ||
const curTime = now(); | ||
async ({ server: app, now, log }) => { | ||
app.get('/time', (req, res, next) => { | ||
const curTime = now(); | ||
log && log('info', 'Sending the current time:', curTime); | ||
res.status(200).send(curTime); | ||
}); | ||
log && log('info', 'Sending the current time:', curTime); | ||
res.status(200).send(curTime); | ||
}); | ||
@@ -342,5 +337,12 @@ } | ||
stubs/mocks in order to let you reuse it through | ||
your projects easily. | ||
your projects easily. Here are the current projects | ||
that use this DI lib: | ||
- [common-services](https://github.com/nfroidure/common-services): | ||
contains the services I use the most in my apps. | ||
- [swagger-http-router](https://github.com/nfroidure/swagger-http-router): | ||
a complete HTTP router based on OpenAPI definitions with a few useful | ||
services compatible with Knifecycle. | ||
- [memory-kv-store](https://github.com/nfroidure/memory-kv-store): | ||
a simple in memory key-value store. | ||
[//]: # (::contents:end) | ||
@@ -393,3 +395,3 @@ | ||
</dd> | ||
<dt><a href="#handler">handler(handlerFunction, [dependencies])</a> ⇒ <code>function</code></dt> | ||
<dt><a href="#handler">handler(handlerFunction, [dependencies], [extra])</a> ⇒ <code>function</code></dt> | ||
<dd><p>Shortcut to create an initializer with a simple handler</p> | ||
@@ -855,3 +857,3 @@ </dd> | ||
## handler(handlerFunction, [dependencies]) ⇒ <code>function</code> | ||
## handler(handlerFunction, [dependencies], [extra]) ⇒ <code>function</code> | ||
Shortcut to create an initializer with a simple handler | ||
@@ -866,2 +868,3 @@ | ||
| [dependencies] | <code>Array</code> | <code>[]</code> | The dependencies to inject in it | | ||
| [extra] | <code>Object</code> | | Optional extra data to associate with the handler | | ||
@@ -868,0 +871,0 @@ **Example** |
@@ -277,2 +277,4 @@ import YError from 'yerror'; | ||
* The dependencies to inject in it | ||
* @param {Object} [extra] | ||
* Optional extra data to associate with the handler | ||
* @return {Function} | ||
@@ -293,3 +295,3 @@ * Returns a new initializer | ||
*/ | ||
export function handler(handlerFunction, dependencies = []) { | ||
export function handler(handlerFunction, dependencies = [], extra) { | ||
if (!handlerFunction.name) { | ||
@@ -303,4 +305,5 @@ throw new YError('E_NO_HANDLER_NAME'); | ||
inject: dependencies, | ||
extra, | ||
}, | ||
(...args) => Promise.resolve(handlerFunction.bind(null, ...args)), | ||
async (...args) => handlerFunction.bind(null, ...args), | ||
); | ||
@@ -307,0 +310,0 @@ } |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
228291
27
5103
900
+ Addeddebug@4.3.7(transitive)
- Removeddebug@3.2.7(transitive)
Updateddebug@^4.0.1
Updatedyerror@^2.1.3