Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

systemic

Package Overview
Dependencies
Maintainers
4
Versions
44
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

systemic - npm Package Compare versions

Comparing version 3.3.7 to 3.3.9

.eslintrc.js

11

CHANGELOG.md
# Change Log
## [3.3.9]
- Exclude various files (including the 12M cc-test-reporter binary) from the npm package.
## [3.3.8]
- Remove lodash
- Replace mocha with zunit
- Update nyc
- Replace travis with github actions
- Replace eslint imperative with ESNext and updated syntax
- Bump dependencies
## [3.3.7]

@@ -4,0 +15,0 @@ ### Changed

447

index.js

@@ -1,256 +0,261 @@

var async = require('async')
var debug = require('debug')('systemic:index')
var format = require('util').format
var Toposort = require('toposort-class')
var getProp = require('lodash.get')
var setProp = require('lodash.set')
var hasProp = require('lodash.has')
var map = require('lodash.map')
var find = require('lodash.find')
var isFunction = require('lodash.isfunction')
var toArray = require('lodash.toarray')
var defaults = require('lodash.defaults')
var assign = require('lodash.assign')
var intersection = require('lodash.intersection')
var requireAll = require('require-all')
var Chance = require('chance')
const async = require('async');
const debug = require('debug')('systemic:index');
const format = require('util').format;
const Toposort = require('toposort-class');
const requireAll = require('require-all');
const {
randomName,
isFunction,
arraysIntersection,
hasProp,
getProp,
setProp
} = require('./utils');
module.exports = function(_params) {
var params = assign({}, { name: new Chance().first() }, _params)
var definitions = {}
var currentDefinition
var running = false
var started
var defaultComponent = {
start: function(dependencies, cb) {
cb(null, dependencies)
}
const api = {};
const params = Object.assign({}, {name: randomName()}, _params);
let definitions = {};
let currentDefinition;
let running = false;
let started;
const defaultComponent = {
start(dependencies, cb) {
cb(null, dependencies);
}
};
function bootstrap(path) {
requireAll({
dirname: path,
filter: /^(index.js)$/,
resolve: function(exported) {
var component = exported.default || exported
api.include(isFunction(component) ? component() : component)
}
})
return api
}
function bootstrap(path) {
requireAll({
dirname: path,
filter: /^(index.js)$/,
resolve(exported) {
const component = exported.default || exported;
api.include(isFunction(component) ? component() : component);
}
});
return api;
}
function configure(component) {
return add('config', component, { scoped: true })
}
function configure(component) {
return add('config', component, { scoped: true });
}
function add(name, component, options) {
debug('Adding component %s to system %s', name, params.name)
if (definitions.hasOwnProperty(name)) throw new Error(format('Duplicate component: %s', name))
if (arguments.length === 1) return add(name, defaultComponent)
return _set(name, component, options)
}
function add(...args) {
const [name, component, options] = args;
debug('Adding component %s to system %s', name, params.name);
if (definitions.hasOwnProperty(name)) throw new Error(format('Duplicate component: %s', name));
if (args.length === 1) return add(name, defaultComponent);
return _set(name, component, options);
}
function set(name, component, options) {
debug('Setting component %s on system %s', name, params.name)
return _set(name, component, options)
}
function set(name, component, options) {
debug('Setting component %s on system %s', name, params.name);
return _set(name, component, options);
}
function remove(name) {
debug('Removing component %s from system %s', name, params.name)
delete definitions[name]
return api
}
function remove(name) {
debug('Removing component %s from system %s', name, params.name);
delete definitions[name];
return api;
}
function _set(name, component, options) {
if (!component) throw new Error(format('Component %s is null or undefined', name))
definitions[name] = assign({}, options, { name: name, component: component.start ? component : wrap(component), dependencies: [] })
currentDefinition = definitions[name]
return api
}
function _set(name, component, options) {
if (!component) throw new Error(format('Component %s is null or undefined', name));
definitions[name] = Object.assign({}, options, {
name,
component: component.start ? component : wrap(component),
dependencies: []
});
currentDefinition = definitions[name];
return api;
}
function include(subSystem) {
debug('Including definitions from sub system %s into system %s', subSystem.name, params.name)
definitions = assign({}, definitions, subSystem._definitions)
return api
}
function include(subSystem) {
debug('Including definitions from sub system %s into system %s', subSystem.name, params.name);
definitions = Object.assign({}, definitions, subSystem._definitions);
return api;
}
function dependsOn() {
if (!currentDefinition) throw new Error('You must add a component before calling dependsOn')
currentDefinition.dependencies = toArray(arguments).reduce(toDependencyDefinitions, currentDefinition.dependencies)
return api
}
function dependsOn(...args) {
if (!currentDefinition) throw new Error('You must add a component before calling dependsOn');
currentDefinition.dependencies = args.reduce(toDependencyDefinitions, currentDefinition.dependencies);
return api;
}
function toDependencyDefinitions(accumulator, arg) {
var record = typeof arg === 'string' ? { component: arg, destination: arg } : defaults({}, arg, { destination: arg.component })
if (!record.component) throw new Error(format('Component %s has an invalid dependency %s', currentDefinition.name, JSON.stringify(arg)))
if (find(currentDefinition.dependencies, { destination: record.destination })) throw new Error(format('Component %s has a duplicate dependency %s', currentDefinition.name, record.destination))
return accumulator.concat(record)
function toDependencyDefinitions(accumulator, arg) {
const record = typeof arg === 'string' ? {
component: arg,
destination: arg
} : Object.assign({}, {destination: arg.component}, arg);
if (!record.component) throw new Error(format('Component %s has an invalid dependency %s', currentDefinition.name, JSON.stringify(arg)));
if (currentDefinition.dependencies.find((dep) => dep.destination === record.destination)) {
throw new Error(format('Component %s has a duplicate dependency %s', currentDefinition.name, record.destination));
}
return accumulator.concat(record);
}
function start(cb) {
debug('Starting system %s', params.name)
started = []
var p = new Promise(function(resolve, reject) {
async.seq(sortComponents, ensureComponents, function(components, cb) {
debug('System %s started', params.name)
running = components
cb(null, components)
})(function(err, components) {
if (err) return reject(err, {})
resolve(components)
})
})
return cb ? p.then(immediateCallback(cb)).catch(immediateError(cb, {})) : p
}
function start(cb) {
debug('Starting system %s', params.name);
started = [];
const p = new Promise((resolve, reject) => {
async.seq(sortComponents, ensureComponents, (components, cb) => {
debug('System %s started', params.name);
running = components;
cb(null, components);
})((err, components) => {
if (err) return reject(err, {});
resolve(components);
});
});
return cb ? p.then(immediateCallback(cb)).catch(immediateError(cb, {})) : p;
}
function ensureComponents(components, cb) {
if (running) return cb(null, running)
async.reduce(components.reverse(), {}, toSystem, cb)
}
function ensureComponents(components, cb) {
if (running) return cb(null, running);
async.reduce(components.reverse(), {}, toSystem, cb);
}
function toSystem(system, name, cb) {
debug('Inspecting compontent %s', name)
getDependencies(name, system, function(err, dependencies) {
if (err) return cb(err)
startComponent(dependencies, name, system, cb)
})
}
function toSystem(system, name, cb) {
debug('Inspecting compontent %s', name);
getDependencies(name, system, (err, dependencies) => {
if (err) return cb(err);
startComponent(dependencies, name, system, cb);
});
}
function startComponent(dependencies, name, system, cb) {
debug('Starting component %s', name)
started.push(name)
var component = definitions[name].component
var onStarted = function(err, started) {
if (err) return cb(err)
setProp(system, name, started)
debug('Component %s started', name)
setImmediate(function() {
cb(null, system)
})
}
const p = component.start(dependencies, onStarted)
if (p && p.then) {
p.then(immediateCallback(onStarted)).catch(immediateError(cb))
}
function startComponent(dependencies, name, system, cb) {
debug('Starting component %s', name);
started.push(name);
const component = definitions[name].component;
const onStarted = function(err, started) {
if (err) return cb(err);
setProp(system, name, started);
debug('Component %s started', name);
setImmediate(() => {
cb(null, system);
});
};
const p = component.start(dependencies, onStarted);
if (p && p.then) {
p.then(immediateCallback(onStarted)).catch(immediateError(cb));
}
}
function stop(cb) {
debug('Stopping system %s', params.name)
var p = new Promise(function(resolve, reject) {
async.seq(sortComponents, removeUnstarted, stopComponents, function(cb) {
debug('System %s stopped', params.name)
running = false
cb()
})(function(err) {
if (err) return reject(err)
resolve();
})
})
return cb ? p.then(immediateCallback(cb)).catch(immediateError(cb)) : p
}
function stop(cb) {
debug('Stopping system %s', params.name);
const p = new Promise((resolve, reject) => {
async.seq(sortComponents, removeUnstarted, stopComponents, (cb) => {
debug('System %s stopped', params.name);
running = false;
cb();
})((err) => {
if (err) return reject(err);
resolve();
});
});
return cb ? p.then(immediateCallback(cb)).catch(immediateError(cb)) : p;
}
function stopComponents(components, cb) {
async.eachSeries(components, stopComponent, cb)
}
function stopComponents(components, cb) {
async.eachSeries(components, stopComponent, cb);
}
function stopComponent(name, cb) {
debug('Stopping component %s', name)
var stop = definitions[name].component.stop || noop
var onStopped = function(err) {
if (err) return cb(err)
debug('Component %s stopped', name)
setImmediate(cb)
}
var p = stop(onStopped)
if (p && p.then) {
p.then(immediateCallback(onStopped)).catch(immediateError(cb))
}
function stopComponent(name, cb) {
debug('Stopping component %s', name);
const stop = definitions[name].component.stop || noop;
const onStopped = function(err) {
if (err) return cb(err);
debug('Component %s stopped', name);
setImmediate(cb);
};
const p = stop(onStopped);
if (p && p.then) {
p.then(immediateCallback(onStopped)).catch(immediateError(cb));
}
}
function sortComponents(cb) {
var result = []
try {
var graph = new Toposort()
Object.keys(definitions).forEach(function(name) {
graph.add(name, map(definitions[name].dependencies, 'component'))
})
result = intersection(graph.sort(), Object.keys(definitions))
} catch (err) {
return cb(err)
}
return cb(null, result)
function sortComponents(cb) {
let result = [];
try {
const graph = new Toposort();
Object.keys(definitions).forEach((name) => {
graph.add(name, definitions[name].dependencies.map((dep) => dep.component));
});
result = arraysIntersection(graph.sort(), Object.keys(definitions));
} catch (err) {
return cb(err);
}
return cb(null, result);
}
function removeUnstarted(components, cb) {
cb(null, intersection(components, started))
}
function removeUnstarted(components, cb) {
cb(null, arraysIntersection(components, started));
}
function getDependencies(name, system, cb) {
async.reduce(definitions[name].dependencies, {}, function(accumulator, dependency, cb) {
if (!hasProp(definitions, dependency.component)) return cb(new Error(format('Component %s has an unsatisfied dependency on %s', name, dependency.component)))
if (!dependency.hasOwnProperty('source') && definitions[dependency.component].scoped) dependency.source = name
dependency.source ? debug('Injecting dependency %s.%s as %s into %s', dependency.component, dependency.source, dependency.destination, name)
: debug('Injecting dependency %s as %s into %s', dependency.component, dependency.destination, name)
var component = getProp(system, dependency.component)
setProp(accumulator, dependency.destination, dependency.source ? getProp(component, dependency.source) : component)
cb(null, accumulator)
}, cb)
}
function getDependencies(name, system, cb) {
async.reduce(definitions[name].dependencies, {}, (accumulator, dependency, cb) => {
if (!hasProp(definitions, dependency.component)) return cb(new Error(format('Component %s has an unsatisfied dependency on %s', name, dependency.component)));
if (!dependency.hasOwnProperty('source') && definitions[dependency.component].scoped) dependency.source = name;
dependency.source ? debug('Injecting dependency %s.%s as %s into %s', dependency.component, dependency.source, dependency.destination, name)
: debug('Injecting dependency %s as %s into %s', dependency.component, dependency.destination, name);
const component = getProp(system, dependency.component);
setProp(accumulator, dependency.destination, dependency.source ? getProp(component, dependency.source) : component);
cb(null, accumulator);
}, cb);
}
function noop() {
var args = toArray(arguments)
var cb = args.pop()
cb && cb.apply(null, [null].concat(args))
}
function noop(...args) {
const cb = args.pop();
cb && cb(...[null].concat(args));
}
function wrap(component) {
return {
start: function(dependencies, cb) {
return cb(null, component)
}
}
}
function wrap(component) {
return {
start(dependencies, cb) {
return cb(null, component);
}
};
}
function restart(cb) {
var p = api.stop().then(function() {
return api.start()
})
function restart(cb) {
const p = api.stop().then(() => api.start());
return cb ? p.then(immediateCallback(cb)).catch(immediateError(cb)) : p
}
return cb ? p.then(immediateCallback(cb)).catch(immediateError(cb)) : p;
}
function immediateCallback(cb) {
return function(resolved) {
setImmediate(function() {
cb(null, resolved);
})
}
}
function immediateCallback(cb) {
return function (resolved) {
setImmediate(() => {
cb(null, resolved);
});
};
}
function immediateError(cb, resolved) {
return function(err) {
setImmediate(function() {
resolved ? cb(err, resolved) : cb(err);
})
}
}
function immediateError(cb, resolved) {
return function (err) {
setImmediate(() => {
resolved ? cb(err, resolved) : cb(err);
});
};
}
var api = {
name: params.name,
bootstrap: bootstrap,
configure: configure,
add: add,
set: set,
remove: remove,
merge: include,
include: include,
dependsOn: dependsOn,
start: start,
stop: stop,
restart: restart,
_definitions: definitions
}
Object.assign(api, {
name: params.name,
bootstrap,
configure,
add,
set,
remove,
merge: include,
include,
dependsOn,
start,
stop,
restart,
_definitions: definitions
});
return api
}
return api;
};
{
"name": "systemic",
"version": "3.3.7",
"version": "3.3.9",
"description": "A minimal dependency injection library for node",
"main": "index.js",
"scripts": {
"qa": "npm run lint && npm run test",
"qa": "npm run lint && npm test",
"lint": "eslint .",
"test": "nyc --report html --reporter lcov --reporter text-summary mocha test"
"test": "node test",
"coverage": "nyc --report html --reporter lcov --reporter text-summary node test"
},

@@ -27,22 +28,11 @@ "keywords": [

"eslint": "^6.8.0",
"eslint-config-imperative": "^3.0.0",
"eslint-plugin-imperative": "^3.0.0",
"husky": "^4.2.3",
"mocha": "^7.1.1",
"nyc": "^15.0.0"
"eslint-config-esnext": "^4.1.0",
"husky": "^4.3.6",
"nyc": "^15.1.0",
"zunit": "^3.0.0"
},
"dependencies": {
"async": "^3.2.0",
"chance": "^1.1.4",
"debug": "^4.1.1",
"lodash.assign": "^4.2.0",
"lodash.defaults": "^4.2.0",
"lodash.find": "^4.6.0",
"lodash.get": "^4.4.2",
"lodash.has": "^4.5.2",
"lodash.intersection": "^4.4.0",
"lodash.isfunction": "^3.0.9",
"lodash.map": "^4.6.0",
"lodash.set": "^4.3.2",
"lodash.toarray": "^4.4.0",
"chance": "^1.1.7",
"debug": "^4.3.1",
"require-all": "^3.0.0",

@@ -52,7 +42,6 @@ "toposort-class": "^1.0.1"

"directories": {
"example": "examples",
"test": "tests"
"example": "examples"
},
"engines": {
"node": ">6.0.0"
"node": ">=10.0.0"
},

@@ -59,0 +48,0 @@ "repository": {

@@ -5,9 +5,7 @@ # Systemic

[![Greenkeeper badge](https://badges.greenkeeper.io/guidesmiths/systemic.svg)](https://greenkeeper.io/)
[![NPM version](https://img.shields.io/npm/v/systemic.svg?style=flat-square)](https://www.npmjs.com/package/systemic)
[![NPM downloads](https://img.shields.io/npm/dm/systemic.svg?style=flat-square)](https://www.npmjs.com/package/systemic)
[![Build Status](https://img.shields.io/travis/guidesmiths/systemic/master.svg)](https://travis-ci.org/guidesmiths/systemic)
[![Node.js CI](https://github.com/guidesmiths/systemic/workflows/Node.js%20CI/badge.svg)](https://github.com/guidesmiths/systemic/actions?query=workflow%3A%22Node.js+CI%22)
[![Code Climate](https://codeclimate.com/github/guidesmiths/systemic/badges/gpa.svg)](https://codeclimate.com/github/guidesmiths/systemic)
[![Test Coverage](https://codeclimate.com/github/guidesmiths/systemic/badges/coverage.svg)](https://codeclimate.com/github/guidesmiths/systemic/coverage)
[![Code Style](https://img.shields.io/badge/code%20style-imperative-brightgreen.svg)](https://github.com/guidesmiths/eslint-config-imperative)
[![Dependency Status](https://david-dm.org/guidesmiths/systemic.svg)](https://david-dm.org/guidesmiths/systemic)

@@ -106,3 +104,3 @@ [![devDependencies Status](https://david-dm.org/guidesmiths/systemic/dev-status.svg)](https://david-dm.org/guidesmiths/systemic?type=dev)

### Runners
While not shown in the above examples we usually separate the system definition from system start. This is important for testing since you ofen want to make changes to the system definition (e.g. replacing components with stubs), before starting the system. By wrapping the system definition in a function you create a new system in each of your tests.
While not shown in the above examples we usually separate the system definition from system start. This is important for testing since you often want to make changes to the system definition (e.g. replacing components with stubs), before starting the system. By wrapping the system definition in a function you create a new system in each of your tests.

@@ -252,3 +250,3 @@ ```js

#### Including components from another system
You can simplfiy large systems by breaking them up into smaller ones, then including their component definitions into the main system.
You can simplify large systems by breaking them up into smaller ones, then including their component definitions into the main system.

@@ -299,3 +297,3 @@ ```js

#### Bootstraping components
#### Bootstrapping components
The dependency graph for a medium size project can grow quickly leading to a large system definition. To simplify this you can bootstrap components from a specified directory, where each folder in the directory includes an index.js which defines a sub system. e.g.

@@ -372,9 +370,9 @@

systemic:index Starting system server +0ms
systemic:index Inspecting compontent routes.admin +0ms
systemic:index Inspecting component routes.admin +0ms
systemic:index Starting component routes.admin +0ms
systemic:index Component routes.admin started +15ms
systemic:index Inspecting compontent routes.api +0ms
systemic:index Inspecting component routes.api +0ms
systemic:index Starting component routes.api +0ms
systemic:index Component routes.api started +15ms
systemic:index Inspecting compontent routes +0ms
systemic:index Inspecting component routes +0ms
systemic:index Injecting dependency routes.admin as routes.admin into routes +0ms

@@ -381,0 +379,0 @@ systemic:index Injecting dependency routes.api as routes.api into routes +0ms

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc