Comparing version 1.7.3 to 2.0.0-beta-1
# Change History | ||
## v1.7.3 (2015-11-30) | ||
## v2.0.0 (???) | ||
* Updated sack version to fix issue with nested functions | ||
* Initial v2 release | ||
## v1.7.2 (2015-11-29) | ||
## v1 Change History | ||
* Updated sack version to fix ES2015 class issue | ||
## v1.7.1 (2015-11-29) | ||
* Updated dependencies (fixes issues with ES2015 runtimes) | ||
## v1.7.0 (2014-10-12) | ||
* Added `Application#registerDefaultInstance` method | ||
* Added `Application#registerInstance` convenience method | ||
* Added `Application#registerSingleton` convenience method | ||
## v1.6.0 (2014-10-01) | ||
* Deprecate `Application#config` -- will be removing all `ConfigStore` stuff in v2 | ||
## v1.5.2 (2014-09-22) | ||
* JSDoc updates / documention generation script | ||
## v1.5.1 (2014-09-15) | ||
* Expose `ConfigStore` class on the package | ||
## v1.5.0 (2014-08-30) | ||
* `container()` method deprecated | ||
* Updated dependencies | ||
* Updated documentation | ||
## v1.4.1 (2014-06-10) | ||
* Updated dependencies | ||
* Using `bluebird` for promises now | ||
## v1.4.0 (2014-05-31) | ||
* Added `stop()` method to shutdown services in reverse order | ||
* Removed nasty deferred-style `.started` property | ||
* Expose the `Application` object directly off of module | ||
## 1.3.1 (2014-05-29) | ||
* Fixed issue with logging timing | ||
## 1.3.0 (2014-05-28) | ||
* `manifest()` is deprecated now -- semi pointless | ||
* Added debugging statements | ||
* Fixed bug with old IE | ||
## 1.2.0 (2014-05-27) | ||
* Added default implicit sets when getting a config key. | ||
## 1.1.0 (2014-05-20) | ||
* Fixed bug when accessing deep configs that are missing | ||
* Added `manifest()` method to declaratively setup services and configs | ||
## 1.0.2 (2014-05-17) | ||
* Updated NPM dependencies. | ||
## 1.0.1 (2014-05-16) | ||
* Use `~` instead of `^` in `package.json` for installing with old versions of `npm`. | ||
## 1.0.0 (2014-04-22) | ||
* First release | ||
* https://github.com/bvalosek/billy/blob/v1.7.3/HISTORY.md |
@@ -1,7 +0,1 @@ | ||
var Application = module.exports = require('./lib/Application.js'); | ||
// in case we ref it the old way ( ... ಠ_ಠ ) | ||
Application.Application = Application; | ||
// Expose config object for ref / testing | ||
module.exports.ConfigStore = require('./lib/ConfigStore.js'); | ||
module.exports = require('./lib'); |
@@ -1,324 +0,130 @@ | ||
module.exports = Application; | ||
const debug = require('debug')('billy:Application'); | ||
const Container = require('./Container.js'); | ||
var Promise = require('bluebird'); | ||
var Container = require('sack').Container; | ||
var IoCBinding = require('sack').IoCBinding; | ||
var debug = require('debug')('billy:Application'); | ||
var getName = require('typedef').getName; | ||
var ConfigStore = require('./ConfigStore.js'); | ||
/* | ||
/** | ||
* @class | ||
* Centralized application harness used to register and boot up IoC-injected | ||
* services. | ||
* | ||
* ``` | ||
* var Application = require('billy'); | ||
* | ||
* var app = new Application(); | ||
* | ||
* app.service(function() { | ||
* ... | ||
* }); | ||
* | ||
* app.service(SomeService); | ||
* app.service(SomeOtherService); | ||
* app.config('http', { | ||
* ... | ||
* }); | ||
* | ||
* app.start(); | ||
* ``` | ||
*/ | ||
function Application() | ||
Centralized application harness used to register and boot up IoC-injected | ||
services. | ||
*/ | ||
module.exports = class Application | ||
{ | ||
if (!(this instanceof Application)) | ||
return new Application(); | ||
constructor({ containerTag = 'container' } = { }) | ||
{ | ||
this._started = false; | ||
this._services = [ ]; | ||
this._running = [ ]; | ||
this._services = []; | ||
this._running = []; | ||
this._container = new Container(); | ||
this._container = new Container(); | ||
/** | ||
* The convenience function from {@link ConfigStore#getStore}. | ||
* | ||
* Also exposed in the app as the `config` dependency. | ||
* @readonly | ||
* @example | ||
* var password = app.config('http.auth.password'); | ||
* | ||
* app.service(function(config) { | ||
* | ||
* // set a new config | ||
* config('new config', 123); | ||
* | ||
* }); | ||
* @type {function} | ||
* @deprecated | ||
*/ | ||
this.config = new ConfigStore().getStore(); | ||
} | ||
if (containerTag) { | ||
this._container.registerValue(containerTag, this._container); | ||
} | ||
} | ||
/** | ||
* Add a service to the application. | ||
* | ||
* Your application entry point will register a series of services that will | ||
* power your app. Services can either be a simple closure or a class | ||
* constructor, and can optionally use promises to signal an asynchronous | ||
* startup. | ||
* @param {function} T Class constructor or closure | ||
* @example | ||
* // Use a closure as a service | ||
* app.service(function main() { | ||
* console.log('service created'); | ||
* }); | ||
* @example | ||
* // Return a Promise to signal an asynchronous startup | ||
* app.service(function main() { | ||
* console.log('service created'); | ||
* | ||
* return someAsyncTask() | ||
* .then(function() { | ||
* console.log('service started'); | ||
* }); | ||
* }); | ||
* @example | ||
* // Use a class constructor | ||
* var HttpService = require('billy-http-express'); | ||
* | ||
* app.service(HttpService); | ||
*/ | ||
Application.prototype.service = function(T) | ||
{ | ||
this._services.push(T); | ||
debug('registered service %s', getName(T)); | ||
}; | ||
get container() | ||
{ | ||
return this._container; | ||
} | ||
/** | ||
* Delegate registering things to the IoC container. | ||
* | ||
* See {@link Container#register} | ||
* @param {string} tag Tag to register a dependency under | ||
* @param {function|object} thing A class constructor or object instance | ||
* @return {IoCBinding} | ||
*/ | ||
Application.prototype.register = function(tag, thing) | ||
{ | ||
if (typeof tag !== 'string') | ||
throw new TypeError('tag'); | ||
/* | ||
debug('registering dependency with tag %s', tag); | ||
return this._container.register(tag, thing); | ||
}; | ||
Add a new service class to the application stack | ||
/** | ||
* Register a thing as a singleton dependency. | ||
* | ||
* This is a convenience method that is equivalent to: | ||
* | ||
* ``` | ||
* app.register('thing', Thing).asSingleton(); | ||
* ``` | ||
* | ||
* See {@link Container#register} | ||
* @param {string} tag Tag to register a depedency under | ||
* @param {function|object} thing A class constructor or object instance | ||
* @return {IoCBinding} | ||
*/ | ||
Application.prototype.registerSingleton = function(tag, thing) | ||
{ | ||
return this.register(tag, thing).asSingleton(); | ||
}; | ||
*/ | ||
service(T) | ||
{ | ||
if (this._started) { | ||
throw new Error('Cannot add service after application has been started'); | ||
} | ||
/** | ||
* Register an existing object instance as a dependency. | ||
* | ||
* This is a convenience method that is equivalent to: | ||
* | ||
* ``` | ||
* app.register('thing', thing).asInstance(); | ||
* ``` | ||
* | ||
* See {@link Container#register} | ||
* @param {string} tag Tag to register a depedency under | ||
* @param {object} thing An object instance | ||
* @return {IoCBinding} | ||
*/ | ||
Application.prototype.registerInstance = function(tag, thing) | ||
{ | ||
return this.register(tag, thing).asInstance(); | ||
}; | ||
if (!T) { | ||
throw new Error('Missing parameter T'); | ||
} | ||
/** | ||
* Register a weak instance dependency if there isn't already one registered. | ||
* | ||
* This effectively checks first if a dependency exists (via | ||
* {@link Container#tagExists}), and if it doesn't, will register a dependency | ||
* via the {@link IoCBinding#asWeak} and {@link IoCBinding#asInstance} | ||
* @param {string} tag | ||
* @param {object} thing | ||
*/ | ||
Application.prototype.registerDefaultInstance = function(tag, thing) | ||
{ | ||
if (this._container.tagExists(tag)) | ||
return; | ||
const type = typeof T; | ||
this._container.register(tag, thing) | ||
.asWeak() | ||
.asInstance(); | ||
}; | ||
if (type !== 'function') { | ||
throw new Error(`Invalid typeof T: ${type}, must be 'function'`); | ||
} | ||
/** | ||
* Delegate object creation to the IoC container. | ||
* | ||
* See {@link Container#make} | ||
* @param {Function|string} thing | ||
* @return {object} | ||
*/ | ||
Application.prototype.make = function(thing) | ||
{ | ||
return this._container.make(thing); | ||
}; | ||
const name = T.name; | ||
/** | ||
* Start all of the services in the ordered they were registered. | ||
* | ||
* Any service closure that returns a `Promise`, or service class that implements | ||
* a `start` method that returns a `Promise`, will cause the startup to wait | ||
* until it has resolved before moving onto the next service. | ||
* @return {Promise} This promise is resolved when all services have finished | ||
* starting, and is rejected if there was an error during service start. | ||
* @example | ||
* app.start().then(function() { | ||
* console.log('app started'); | ||
* }); | ||
*/ | ||
Application.prototype.start = function() | ||
{ | ||
debug('starting app'); | ||
if (this._services.includes(T)) { | ||
throw new Error(`Service already registered: ${name}`); | ||
} | ||
// Default stuff registered as weak so another service could override it if | ||
// needed | ||
this.register('config', this.config).asInstance().asWeak(); | ||
this.register('app', this).asInstance().asWeak(); | ||
this._services.push(T); | ||
// Instantiate all services in order -- this works equally well if a class | ||
// constructor was passed to service() or just a normal function. | ||
for (var n = 0; n < this._services.length; n++) { | ||
var T = this._services[n]; | ||
debug('creating service %s', getName(T)); | ||
var service = this.make(T); | ||
this._running.push(service); | ||
debug(`registered ${name}`); | ||
} | ||
// Start in order and async | ||
var sequence = Promise.resolve(); | ||
for (var m = 0; m < this._running.length; m++) { | ||
var s = this._running[m]; | ||
sequence = sequence.then(start(s)); | ||
} | ||
/* | ||
// Resolve the final started promise | ||
return sequence.then(function() { | ||
debug('app started successfully'); | ||
}, | ||
function(err) { | ||
debug('error starting app: %s', err); | ||
throw err; | ||
}); | ||
}; | ||
Instantiate and start each registered service | ||
/** | ||
* Stop all registered services in the reverse order they were registered. | ||
* | ||
* This allows for graceful shutdown of any services that are running. | ||
* | ||
* If a service class implements a `stop` method, it can return a `Promise` to | ||
* allow for asynchronous shutdown. | ||
* @return {Promise} This promise is resolved when all services have finished | ||
* stopping, and is rejected if there was an error during service shutdown. | ||
* @example | ||
* app.stop().then(function() { | ||
* console.log('app gracefully shutdown'); | ||
* }); | ||
*/ | ||
Application.prototype.stop = function() | ||
{ | ||
debug('stopping app'); | ||
*/ | ||
async start() | ||
{ | ||
debug('starting application'); | ||
// Loop through all services in reverse, allowing them to customize stop | ||
// behavior if needed | ||
var sequence = Promise.resolve(); | ||
for (var n = this._running.length - 1; n >= 0; n--) { | ||
var service = this._running[n]; | ||
sequence = sequence.then(stop(service)); | ||
this._started = true; | ||
for (const T of this._services) { | ||
debug(`creating ${T.name}`); | ||
const instance = this._container.new(T); | ||
this._running.push(instance); | ||
} | ||
for (const instance of this._running) { | ||
debug(`starting ${instance.constructor.name}`); | ||
if (typeof instance.start === 'function') { | ||
await instance.start(); | ||
} | ||
} | ||
debug('application started'); | ||
} | ||
return sequence.then(function() { | ||
debug('app stopped successfully'); | ||
}, | ||
function(err) { | ||
debug('error stopping app: %s', err); | ||
}); | ||
}; | ||
/* | ||
/** | ||
* Change the IoC container instance. | ||
* @deprecated | ||
* @param {{register:function}} container | ||
* @return {object} Old container. | ||
*/ | ||
Application.prototype.container = function(container) | ||
{ | ||
if (typeof container.make !== 'function') | ||
throw new TypeError('container.make'); | ||
Give each started service a chance to stop in the reverse order they were | ||
started | ||
if (typeof container.register !== 'function') | ||
throw new TypeError('container.register'); | ||
*/ | ||
async stop() | ||
{ | ||
debug('stopping application'); | ||
var old = this._container; | ||
this._container = container; | ||
return old; | ||
}; | ||
const errs = [ ]; | ||
/** | ||
* Load up application information from a manifest hash. | ||
* @deprecated | ||
* @param {{config:object, services:array<any>}} hash | ||
* @return {Application} This object. | ||
*/ | ||
Application.prototype.manifest = function(hash) | ||
{ | ||
// Add services one by one | ||
if (hash.services) { | ||
for (var n = 0; n < hash.services.length; n++) { | ||
this.service(hash.services[n]); | ||
for (const instance of this._running.reverse()) { | ||
const name = instance.constructor.name; | ||
try { | ||
debug(`stopping ${name}`); | ||
if (typeof instance.stop === 'function') { | ||
await instance.stop(); | ||
} | ||
} | ||
catch (err) { | ||
// Want to let all services get a chance to shut down, even if some | ||
// error out, so just swallow the error and continue | ||
errs.push(err); | ||
} | ||
} | ||
} | ||
// Iterate over keys | ||
if (hash.config) { | ||
for (var key in hash.config) { | ||
var value = hash.config[key]; | ||
this.config(key, value); | ||
debug('added config %s', key); | ||
// Ensure stop function throws if theres any errors while stopping | ||
if (errs.length) { | ||
throw errs[0]; | ||
} | ||
debug('application stopped'); | ||
} | ||
return this; | ||
}; | ||
function start(s) { | ||
return function() { | ||
debug('starting service %s', getName(s.constructor)); | ||
return s.start ? s.start() : s; | ||
}; | ||
} | ||
function stop(s) { | ||
return function() { | ||
debug('stopping service %s', getName(s.constructor)); | ||
return s.stop ? s.stop() : s; | ||
}; | ||
} | ||
{ | ||
"name": "billy", | ||
"version": "1.7.3", | ||
"version": "2.0.0-beta-1", | ||
"description": "A minimal application harness that stays out of your way and out of your code.", | ||
"author": { | ||
"name": "Brandon Valosek", | ||
"email": "bvalosek@gmail.com", | ||
"url": "http://bvalosek.com" | ||
}, | ||
"author": "Brandon Valosek <bvalosek@gmail.com>", | ||
"repository": "git@github.com:bvalosek/billy.git", | ||
"license": "MIT", | ||
"scripts": { | ||
"test": "tape test/*.js", | ||
"doc": "jsdoc -c ./.jsdoc.json" | ||
"test": "tape test/*.js" | ||
}, | ||
"main": "index.js", | ||
"license": "MIT", | ||
"dependencies": { | ||
"babylon": "6.17.0", | ||
"debug": "2.6.6" | ||
}, | ||
"devDependencies": { | ||
"jsdoc": "^3.3.0-alpha9", | ||
"jsdoc3-bootstrap": "^0.7.1", | ||
"tape": "^3.0.0" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git@github.com:bvalosek/billy.git" | ||
}, | ||
"testling": { | ||
"files": "test/*.js", | ||
"browsers": [ | ||
"ie/6..latest", | ||
"chrome/28..canary", | ||
"firefox/23..nightly", | ||
"safari/5.1..latest", | ||
"opera/latest", | ||
"opera/next", | ||
"iphone/latest", | ||
"ipad/latest", | ||
"android-browser/latest" | ||
] | ||
}, | ||
"dependencies": { | ||
"bluebird": "^3.0.5", | ||
"debug": "^2.0.0", | ||
"sack": "^2.2.3", | ||
"typedef": "^1.1.0" | ||
"tape": "4.6.3" | ||
} | ||
} |
207
README.md
# billy | ||
[![Build Status](https://travis-ci.org/bvalosek/billy.png?branch=master)](https://travis-ci.org/bvalosek/billy) | ||
[![NPM version](https://badge.fury.io/js/billy.png)](http://badge.fury.io/js/billy) | ||
> v2 is currently in progress and is NOT yet shipped / final. | ||
> To install it, you need to run `npm install billy@v2-beta` | ||
[![CircleCI](https://circleci.com/gh/bvalosek/billy/tree/master.svg?style=svg)](https://circleci.com/gh/bvalosek/billy/tree/master) | ||
A minimal application harness that stays out of your way and out of your code. | ||
> This is the v2 branch, which has back-compat breaking changes from v1, see | ||
> [billy v1.7.3](https://github.com/bvalosek/billy/tree/v1.7.3) for the old | ||
> version. | ||
## Installation | ||
@@ -14,150 +21,153 @@ | ||
## Usage | ||
## Overview | ||
```javascript | ||
import Application from 'billy'; | ||
The primary goal and driving philosophy of Billy is to provide a cohesive and | ||
useful set of patterns for building an application that doesn't creep its way | ||
into your business logic and domain code. | ||
let app = new Application(); | ||
It is flexible and generic enough to work great for building server apps, | ||
browser apps, Javascript games, or even CLI utilities. | ||
app.service(function main() { | ||
console.log('Hello, World!'); | ||
}); | ||
Much like [express](https://github.com/visionmedia/express), Billy strives not | ||
to be a framework that permeates all parts of your codebase, but rather the | ||
scaffolding that allows you to roll your own application architecture stack. | ||
app.start(); | ||
### The `Application` instance and the Service Stack | ||
The root of your application is a single instance of the `Application` class: | ||
```javascript | ||
const Application = require('billy'); | ||
const app = new Application(); | ||
``` | ||
## Links | ||
An application is composed of several **services**. A service is a class that | ||
sets up and starts the various dependencies in your application. Services | ||
should be free of all business logic, and should be the only parts of the | ||
aplication that are aware of Billy. | ||
* [Billy services on npm](https://www.npmjs.org/browse/keyword/billy-service) | ||
* [API documentation](http://docs.billy.technology) | ||
### The `Container` instance and Dependency Injection | ||
## Features | ||
> Philosophy behind the IoC container | ||
* [Dependency injection / inversion-of-control container](https://github.com/bvalosek/sack) | ||
* Asynchronous promise-based service stack | ||
* Extremely minimal | ||
* Service-oriented design | ||
* Compatible in all browsers and NodeJS | ||
## Usage | ||
## Overview | ||
> Code Examples | ||
The primary goal and driving philosophy of Billy is to provide a cohesive and | ||
useful set of patterns for building an application that doesn't creep its way | ||
into your business logic and domain code. | ||
### Environments | ||
It is flexible and generic enough to work great for building server apps, | ||
browser apps, javascript games, or even CLI utilities. | ||
Billy is written to run in modern Javascript environments (ES2017) that support | ||
the CommonJS module system (e.g, Node 7). | ||
Much like [express](https://github.com/visionmedia/express), Billy strives not | ||
to be a framework that permeates all parts of your codebase, but rather the | ||
scaffolding that allows you to roll your own application architecture stack. | ||
#### Older JS Runtimes | ||
## Services | ||
> Examples of requiring the transpiled versions of the lib | ||
Billy views your application as the composition of several dependency-injected | ||
Services. When the application is started via `app.start()`, all registered | ||
services will be instantiated in turn and be given a chance to startup. | ||
## API | ||
A service should be used to create various run-time objects and register them | ||
as dependencies with the IoC container via the `app` dependency for other parts | ||
of the application to use. | ||
### `Application()` | ||
Services are effectively the place where all the various pieces of your | ||
application are booted, configured, and wired together. | ||
Root application class. | ||
### Registering a service | ||
```javascript | ||
const app = new Application(); | ||
``` | ||
Your application entry point will register a series of services that will power | ||
your app. Services can either be a simple closure or a class constructor, and | ||
can optionally use promises to signal an asynchronous startup. | ||
#### `Application#service(T)` | ||
### Using closures as a Service | ||
Register a service class with the application. | ||
The simplest example of a service is a function: | ||
```javascript | ||
app.service(PostgresDatabaseService); | ||
``` | ||
#### `Application#start()` | ||
Instantiate and start all services in the order they were registered. | ||
```javascript | ||
app.service(() => { | ||
console.log('service created'); | ||
}); | ||
await app.start(); | ||
``` | ||
If our service took some time to startup, we could return a `Promise` to ensure | ||
during the service start phase, the application would wait. | ||
#### `Application#stop()` | ||
Give each service a chance to shut down in reverse order they were started. | ||
```javascript | ||
app.service(async () => { | ||
console.log('service created'); | ||
await someAsyncTask(); | ||
console.log('service started'); | ||
}); | ||
await app.stop(); | ||
``` | ||
Note that all services are first *created* all at once (by calling the provided | ||
function), synchronously. Then, all of the services are *started* (by waiting | ||
on any promises returned in the service function). | ||
#### `Application#container` | ||
#### Using Class Constructors as a Service | ||
Reference to the dependency injection container for the application. | ||
A simple class constructor can be passed to the `app.service()` method as well. | ||
### `Container` | ||
The dependency injection container. There is no need to instantiate this | ||
directly as a reference to the application's container is exposed as a property | ||
on the `Application` instance: | ||
```javascript | ||
// MyService.js | ||
const container = app.container; | ||
``` | ||
export default class MyService | ||
{ | ||
constructor() | ||
{ | ||
console.log('service created'); | ||
} | ||
} | ||
#### `Container#registerValue(tag, thing)` | ||
Store a simple value in the container. Every time the `tag` dependency is | ||
resolved, the same value is returned. | ||
```javascript | ||
app.container.registerValue('config', require('./config.json')); | ||
``` | ||
In our startup file: | ||
#### `Container#registerFactory(tag, factory)` | ||
Store a factory function in the container. Every time the `tag` dependency is | ||
resolved, the factory function will be called with its parameters injected. | ||
```javascript | ||
// main.js | ||
import Application from 'billy'; | ||
import MyService from './MyService.js'; | ||
app.container.registerFactory('currentTime', () => new Date()); | ||
``` | ||
let app = new Application(); | ||
#### `Container#registerClass(tag, T)` | ||
app.service(MyService); | ||
app.start(); | ||
Store a class in the container. Every time the `tag` dependency is resolved, a | ||
fresh instance of the class is instantiated, with its constructor parameters | ||
injected. | ||
```javascript | ||
app.container.registerClass('logger', ElasticSearchLogger); | ||
``` | ||
If this service requires some additional setup after all services have been | ||
created, or requires an asynchronous startup, we can implement a `start` | ||
method: | ||
#### `Container#registerSingleton(tag, T)` | ||
Store a **singleton** class in the container. The first time `tag` dependency | ||
is resolved, the class will be instantiated and cached. Each subsequent | ||
resolution of `tag` will return the original instance after that. | ||
```javascript | ||
export default class MyService | ||
{ | ||
async start() | ||
{ | ||
await someAsyncTask(); | ||
console.log('service started'); | ||
} | ||
} | ||
app.container.registerSingleton('db', PostgresDatabaseDriver); | ||
``` | ||
Any promise return is waited on until it resolves before attempting to start | ||
any subsequent services. | ||
#### `Container#resolve(tag)` | ||
This is useful for things like downloading external data, verifying | ||
credentials, bootstrapping external connections, etc. The application startup | ||
process will block until the service resolves, guaranteeing a deterministic | ||
boot up. | ||
Resolve a dependency from the container via its string tag. Typically this | ||
method shouldn't be used directly, but rather rely on automatic injection to | ||
get a hold of registered dependencies. | ||
## Testing | ||
```javascript | ||
const db = app.container.resolve('db'); | ||
``` | ||
$ npm test | ||
``` | ||
## Documentation | ||
## Contributors | ||
This will generate the HTML documentation under `./doc`: | ||
* [Brandon Valosek](https://github.com/bvalosek) | ||
* [Zak Angelle](https://github.com/zakangelle) | ||
* [Dillon Shook](https://github.com/dshook) | ||
## Testing | ||
``` | ||
$ npm run doc | ||
$ npm test | ||
``` | ||
@@ -167,2 +177,3 @@ | ||
MIT | ||
[MIT](https://github.com/bvalosek/billy/blob/master/LICENSE) | ||
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
2
1
178
14658
10
318
2
1
1
+ Addedbabylon@6.17.0
+ Addedbabylon@6.17.0(transitive)
+ Addeddebug@2.6.6(transitive)
+ Addedms@0.7.3(transitive)
- Removedbluebird@^3.0.5
- Removedsack@^2.2.3
- Removedtypedef@^1.1.0
- Removedbluebird@3.7.2(transitive)
- Removeddebug@2.6.9(transitive)
- Removedms@2.0.0(transitive)
- Removedsack@2.2.3(transitive)
- Removedtypedef@1.1.0(transitive)
Updateddebug@2.6.6