diff --git a/.babelrc b/.babelrc index e403556..be2ad0a 100644 --- a/.babelrc +++ b/.babelrc @@ -1,5 +1,5 @@ { - "presets": [["env", {"targets": {"node": 4}}]], + "presets": ["es2015", "flow", "stage-3"], "plugins": [ ["transform-builtin-extend", {"globals": ["Error"]}], "transform-runtime" diff --git a/.flowconfig b/.flowconfig new file mode 100644 index 0000000..8f5fbce --- /dev/null +++ b/.flowconfig @@ -0,0 +1,10 @@ +[ignore] +.*/node_modules/documentation/.* +.*/test/.* + +[include] + +[libs] + +[options] +unsafe.enable_getters_and_setters=true diff --git a/README.md b/README.md index 90ca18b..edb9630 100644 --- a/README.md +++ b/README.md @@ -2,137 +2,195 @@ [![npm](https://img.shields.io/npm/v/iab-vast-loader.svg)](https://www.npmjs.com/package/iab-vast-loader) [![Dependencies](https://img.shields.io/david/zentrick/iab-vast-loader.svg)](https://david-dm.org/zentrick/iab-vast-loader) [![Build Status](https://img.shields.io/circleci/project/github/zentrick/iab-vast-loader/master.svg)](https://circleci.com/gh/zentrick/iab-vast-loader) [![Coverage Status](https://img.shields.io/coveralls/zentrick/iab-vast-loader/master.svg)](https://coveralls.io/r/zentrick/iab-vast-loader) [![JavaScript Standard Style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com/) -Loads and parses IAB VAST tags, resolving wrapped tags along the way. +Loads IAB VAST tag trees using a preorder depth first strategy. The package is statically typed using [Flow](https://flow.org). [Observable streams](http://npmjs.com/package/rxjs) are used to update the consumer in time with new VAST documents. + +This package exposes two functions: `loadVast()` and `vastToAd()`. + +`loadVast()` is responsible for actually loading the VAST tree, it returns a stream of VAST objects, which allows you to react on failures and offers you the choice to continue listening for subsequent VAST documents in the tree. It also delivers you a new VAST document right away (preserving preorder depth first traversal semantics), instead of waiting for the whole tree to be fetched. + +It also gives you a `vastToAd()` function to map the stream of VAST objects to a stream of Ad objects (both Wrapper and InLine), also in preorder depth first order. This gives you the right abstraction on which you can easily build further upon, using the RxJS `filter()` operator to for example only return `InLine` elements. ## Usage ```js -import VASTLoader from 'iab-vast-loader' +import { loadVast } from 'iab-vast-loader' -const tagUrl = 'https://example.com/vast.xml' - -// Create the loader -const loader = new VASTLoader(tagUrl) +const vast$ = loadVast({ + url: 'https://example.com/vast.xml' +}) -// Load the tag chain and await the resulting Promise -loader.load() - .then((chain) => { - console.info('Loaded VAST tags:', chain) +// Load the VAST tree and log all the VAST tags in the tree. +vast$ + .subscribe({ + next: action => { + switch (action.type) { + case 'VAST_LOADED': + console.info('Loaded next VAST tag: ', action.vast) + break; + case 'VAST_LOADING_FAILED': + console.info('Loading next VAST tag failed: ', action.error, action.wrapper) + break; + } + }, + complete: () => { + console.info('Finished loading the complete VAST tree') + } }) - .catch((err) => { - console.error('Error loading tag:', err) + +// When interested in Ad events +const ad$ = vastToAd(vast$) + +ad$ + .subscribe({ + next: action => { + switch (action.type) { + case 'AD_LOADED': + console.info('Loaded next Ad: ', action.ad) + break; + case 'AD_LOADING_FAILED' + console.info('Loading next Ad failed: ', action.error, action.wrapper) + break; + } + }, + complete: () => { + console.info('Finished loading the complete VAST tree') + } }) ``` ## API +### `#loadVast()` + ```js -new VASTLoader(tagUrl[, options]) +type LoadVast = (config: Config) => Observable ``` -Creates a VAST loader. +`loadVast` creates a stream of `VastLoadAction` objects. In a fully reactive codebase, this stream will be composed within another stream. If this library is used at the boundary, then you need to subscribe yourself like this: ```js -loader.load() +import { loadVast } from 'iab-vast-loader' +const vast$ = loadVast(config) + +loadVast$.subscribe({ + next: value => { }, + complete: () => { } +}) ``` -Returns a `Promise` for an array of `VAST` instances. The `VAST` class is -provided by [iab-vast-model](https://www.npmjs.com/package/iab-vast-model). +#### Configuration -## Error Handling - -In addition to the default export `VASTLoader`, the main module also exports -the `VASTLoaderError` class, which maps errors to the VAST specification: +`loadVast` accepts the following `Config` object: ```js -import { default as VASTLoader, VASTLoaderError } from 'iab-vast-loader' +type Config = { + url: string, + maxDepth?: number, + timeout?: number, + retryCount?: number, + credentials: Credentials +} +``` -const loader = new VASTLoader(tagUrl) +An overview of its properties: -loader.load() - .catch((err) => { - if (err instanceof VASTLoaderError) { - console.error('VAST error: ' + err.code + ' ' + err.message) - } else { - console.error('Unknown error: ' + err) - } - }) -``` +- `url`: The url that points to the root VAST document of the VAST document tree that we need to fetch. +- `maxDepth`: The maximum number of VAST documents to load within one chain. The default is +`10`. +- `timeout`: The maximum number of milliseconds to spend per HTTP request. The default is +`10000`. +- `retryCount`: The amount of times it will retry fetching a VAST document in case of failure. The default is `0`. +- `credentials`: The credentials value defines if cookies will be sent with the request. You should pass a [`CredentialsType`](https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials) string (`'omit'`, `'same-origin'` or `'include'`) or a function which calculcates the `CredentialsType` using the passed url. You can also pass an array of these values: in this case it will try the first credentials strategy, when this call fails it will go on with the next, until a strategy succeeds. If none of the credentials strategies succeed, it will result in a `VAST_LOADING_FAILED` action. Notice that passing an empty array doesn't make sense, because it will always result in a `VAST_LOADING_FAILED` action. -As with [iab-vast-model](https://www.npmjs.com/package/iab-vast-model), if -`instanceof` doesn't work for you, you may want to inspect `error.$type` -instead. This issue can occur if you load multiple versions of iab-vast-loader, -each with their own `VASTLoaderError` class. + With Flow, we can describe this more formally: -## Options + ```js + type Credentials = CredentialsTypeOrFn | CredentialsTypeOrFn[] + type CredentialsTypeOrFn = CredentialsType | (url: string) => CredentialsType + type CredentialsType = 'omit' | 'same-origin' | 'include' + ``` -### `maxDepth` + You can use this option to control the behavior on a per-request basis. For example: -The maximum number of VAST documents to load within one chain. The default is -10. + ```js + const loadVast$ = loadVast({ + url: 'https://example.com/vast.xml', + credentials: [ + url => uri.indexOf('.doubleclick.net/') !== 0 ? 'include' : 'omit' + ] + }) + ``` -### `timeout` + The default is `'omit'`. -The maximum number of milliseconds to spend per HTTP request. The default is -10,000. +#### Output -### `credentials` +The output of loadVast is a stream of `VastLoadAction` objects: -Controls [CORS](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing) -behavior. You can either pass a string or a function. +```js +type VastLoadedAction = { + type: 'VAST_LOADED', + vast: VAST +} + +type VastLoadingFailedAction = { + type: 'VAST_LOADING_FAILED', + error: VASTLoaderError, + wrapper: ?Wrapper +} + +type VastLoadAction = VastLoadedAction | VastLoadingFailedAction +``` -If you pass a string, it will be used as the value for the `credentials` option -to every request. -[Valid values](https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials) -are `'omit'` (the default), `'same-origin'` and `'include'`. +The `VAST` and `Wrapper` types are provided by [iab-vast-model](https://www.npmjs.com/package/iab-vast-model). -To control the behavior on a per-request basis, pass a function receiving the -request URL and returning one of the accepted values. For example: +### `#vastToAd()` ```js -const loader = new VASTLoader(wrapperUrl, { - credentials (uri) { - if (uri.indexOf('.doubleclick.net/') >= 0) { - return 'include' - } else { - return 'omit' - } - } -}) +import { loadVast, vastToAd } from 'iab-vast-loader' +const vast$ = loadVast(config) +const ad$ = vastToAd(vast$) ``` -## Events +`vastToAd` maps a stream of `VastLoadAction` objects to `AdLoadAction` objects. You can subscribe on this stream directly, or indirectly using RxJS operators, just like `loadVast`. + +#### Output -A `VASTLoader` is an `EventEmitter`. To be notified about progress, you can -subscribe to the events `willFetch`, `didFetch`, `willParse`, and `didParse` -as follows: +The output of `vastToAd` is a stream of `AdLoadAction` objects: ```js -loader - .on('willFetch', ({ uri }) => { - console.info('Fetching', uri) - }) - .on('didFetch', ({ uri, body }) => { - console.info('Fetched', body.length, 'bytes from', uri) - }) - .on('willParse', ({ uri, body }) => { - console.info('Parsing', uri) - }) - .on('didParse', ({ uri, body, vast }) => { - console.info('Parsed', uri) - }) - .load() - .then((chain) => { - console.info('Loaded VAST tags:', chain) - }) - .catch((err) => { - console.error('Error loading tag:', err) - }) +type AdLoadedAction = { + type: 'AD_LOADED', + ad: Ad +} + +type AdLoadingFailedAction = { + type: 'AD_LOADING_FAILED', + error: VASTLoaderError, + wrapper: ?Wrapper +} + +type AdLoadAction = AdLoadedAction | AdLoadingFailedAction ``` -## Maintainer +The `Ad` and `Wrapper` types are provided by [iab-vast-model](https://www.npmjs.com/package/iab-vast-model). + +## Error Handling + +In case the libary fails to load the next VAST document, it will emit a `VAST_LOADING_FAILED` action. You can react to this, by unsubscribing using the `takeUntil` operator, or you can continue listening for other values of another subtree of the VAST document tree. We don't push the stream into error state, because we want to enable the consumer to use subsequent VAST documents from the tree, after one subtree failed to fetch. + +In addition to the default export `VASTLoader`, the main module also exports +the `VASTLoaderError` class, which maps errors to the VAST specification. You can get the VAST error code using its `code` property, and the cause using its `cause` property. + +As with [iab-vast-model](https://www.npmjs.com/package/iab-vast-model), if +`instanceof` doesn't work for you, you may want to inspect `error.$type` +instead. This issue can occur if you load multiple versions of iab-vast-loader, +each with their own `VASTLoaderError` class. + +## Maintainers -[Tim De Pauw](https://github.com/timdp) +- [Tim De Pauw](https://github.com/timdp) +- [Laurent De Smet](https://github.com/laurentdesmet) ## License diff --git a/flow-typed/npm/chai_v3.5.x.js b/flow-typed/npm/chai_v3.5.x.js new file mode 100644 index 0000000..b920857 --- /dev/null +++ b/flow-typed/npm/chai_v3.5.x.js @@ -0,0 +1,216 @@ +// flow-typed signature: bad3c03afed474d4fb576a7afe069701 +// flow-typed version: 731a6ee6c3/chai_v3.5.x/flow_>=v0.24.0 + +declare module "chai" { + + declare type ExpectChain = { + and: ExpectChain, + at: ExpectChain, + be: ExpectChain, + been: ExpectChain, + have: ExpectChain, + has: ExpectChain, + is: ExpectChain, + of: ExpectChain, + same: ExpectChain, + that: ExpectChain, + to: ExpectChain, + which: ExpectChain, + with: ExpectChain, + + not: ExpectChain, + deep: ExpectChain, + any: ExpectChain, + all: ExpectChain, + + a: ExpectChain & (type: string) => ExpectChain, + an: ExpectChain & (type: string) => ExpectChain, + + include: ExpectChain & (value: mixed) => ExpectChain, + includes: ExpectChain & (value: mixed) => ExpectChain, + contain: ExpectChain & (value: mixed) => ExpectChain, + contains: ExpectChain & (value: mixed) => ExpectChain, + + eql: (value: T) => ExpectChain, + equal: (value: T) => ExpectChain, + equals: (value: T) => ExpectChain, + + above: (value: T & number) => ExpectChain, + least: (value: T & number) => ExpectChain, + below: (value: T & number) => ExpectChain, + most: (value: T & number) => ExpectChain, + within: (start: T & number, finish: T & number) => ExpectChain, + + instanceof: (constructor: mixed) => ExpectChain, + property: ( +

(name: string, value?: P) => ExpectChain

+ & (name: string) => ExpectChain + ), + + length: (value: number) => ExpectChain | ExpectChain, + lengthOf: (value: number) => ExpectChain, + + match: (regex: RegExp) => ExpectChain, + string: (string: string) => ExpectChain, + + key: (key: string) => ExpectChain, + keys: (key: string | Array, ...keys: Array) => ExpectChain, + + throw: ( + err: Class | Error | RegExp | string, + errMsgMatcher?: RegExp | string, + msg?: string) => ExpectChain, + + respondTo: (method: string) => ExpectChain, + itself: ExpectChain, + + satisfy: (method: (value: T) => bool) => ExpectChain, + + closeTo: (expected: T & number, delta: number) => ExpectChain, + + members: (set: mixed) => ExpectChain, + oneOf: (list: Array) => ExpectChain, + + change: (obj: mixed, key: string) => ExpectChain, + increase: (obj: mixed, key: string) => ExpectChain, + decrease: (obj: mixed, key: string) => ExpectChain, + + // dirty-chai + ok: () => ExpectChain, + true: () => ExpectChain, + false: () => ExpectChain, + null: () => ExpectChain, + undefined: () => ExpectChain, + exist: () => ExpectChain, + empty: () => ExpectChain, + + // chai-immutable + size: (n: number) => ExpectChain, + + // sinon-chai + called: () => ExpectChain, + callCount: (n: number) => ExpectChain, + calledOnce: () => ExpectChain, + calledBefore: (spy: mixed) => ExpectChain, + calledAfter: (spy: mixed) => ExpectChain, + calledWith: (...args: Array) => ExpectChain, + calledWithMatch: (...args: Array) => ExpectChain, + calledWithExactly: (...args: Array) => ExpectChain, + + // chai-as-promised + eventually: ExpectChain, + resolvedWith: (value: mixed) => Promise & ExpectChain, + resolved: () => Promise & ExpectChain, + rejectedWith: (value: mixed) => Promise & ExpectChain, + rejected: () => Promise & ExpectChain, + notify: (callback: () => mixed) => ExpectChain, + + // chai-subset + containSubset: (obj: Object | Object[]) => ExpectChain + }; + + declare function expect(actual: T): ExpectChain; + + declare function use(plugin: (chai: Object, utils: Object) => void): void; + + declare class assert { + static(expression: mixed, message?: string): void; + static fail(actual: mixed, expected: mixed, message?: string, operator?: string): void; + + static isOk(object: mixed, message?: string): void; + static isNotOk(object: mixed, message?: string): void; + + static equal(actual: mixed, expected: mixed, message?: string): void; + static notEqual(actual: mixed, expected: mixed, message?: string): void; + + static strictEqual(act: mixed, exp: mixed, msg?: string): void; + static notStrictEqual(act: mixed, exp: mixed, msg?: string): void; + + static deepEqual(act: mixed, exp: mixed, msg?: string): void; + static notDeepEqual(act: mixed, exp: mixed, msg?: string): void; + + static ok(val: mixed, msg?: string): void; + static isTrue(val: mixed, msg?: string): void; + static isNotTrue(val: mixed, msg?: string): void; + static isFalse(val: mixed, msg?: string): void; + static isNotFalse(val: mixed, msg?: string): void; + + static isNull(val: mixed, msg?: string): void; + static isNotNull(val: mixed, msg?: string): void; + + static isUndefined(val: mixed, msg?: string): void; + static isDefined(val: mixed, msg?: string): void; + + static isNaN(val: mixed, msg?: string): void; + static isNotNaN(val: mixed, msg?: string): void; + + static isAbove(val: number, abv: number, msg?: string): void; + static isBelow(val: number, blw: number, msg?: string): void; + + static isAtMost(val: number, atmst: number, msg?: string): void; + static isAtLeast(val: number, atlst: number, msg?: string): void; + + static isFunction(val: mixed, msg?: string): void; + static isNotFunction(val: mixed, msg?: string): void; + + static isObject(val: mixed, msg?: string): void; + static isNotObject(val: mixed, msg?: string): void; + + static isArray(val: mixed, msg?: string): void; + static isNotArray(val: mixed, msg?: string): void; + + static isString(val: mixed, msg?: string): void; + static isNotString(val: mixed, msg?: string): void; + + static isNumber(val: mixed, msg?: string): void; + static isNotNumber(val: mixed, msg?: string): void; + + static isBoolean(val: mixed, msg?: string): void; + static isNotBoolean(val: mixed, msg?: string): void; + + static typeOf(val: mixed, type: string, msg?: string): void; + static notTypeOf(val: mixed, type: string, msg?: string): void; + + static instanceOf(val: mixed, constructor: Function, msg?: string): void; + static notInstanceOf(val: mixed, constructor: Function, msg?: string): void; + + static include(exp: string, inc: mixed, msg?: string): void; + static include(exp: Array, inc: T, msg?: string): void; + + static notInclude(exp: string, inc: mixed, msg?: string): void; + static notInclude(exp: Array, inc: T, msg?: string): void; + + static match(exp: mixed, re: RegExp, msg?: string): void; + static notMatch(exp: mixed, re: RegExp, msg?: string): void; + + static property(obj: Object, prop: string, msg?: string): void; + static notProperty(obj: Object, prop: string, msg?: string): void; + static deepProperty(obj: Object, prop: string, msg?: string): void; + static notDeepProperty(obj: Object, prop: string, msg?: string): void; + + static propertyVal(obj: Object, prop: string, val: mixed, msg?: string): void; + static propertyNotVal(obj: Object, prop: string, val: mixed, msg?: string): void; + + static deepPropertyVal(obj: Object, prop: string, val: mixed, msg?: string): void; + static deepPropertyNotVal(obj: Object, prop: string, val: mixed, msg?: string): void; + + static lengthOf(exp: mixed, len: number, msg?: string): void; + + static throws( + func: () => any, + err?: Class | Error | RegExp | string, + errorMsgMatcher?: string | RegExp, + msg?: string): void; + static doesNotThrow( + func: () => any, + err?: Class | Error | RegExp | string, + errorMsgMatcher?: string | RegExp, + msg?: string): void; + } + + declare var config: { + includeStack: boolean, + showDiff: boolean, + truncateThreshold: number + }; +} diff --git a/flow-typed/npm/isomorphic-fetch_v2.x.x.js b/flow-typed/npm/isomorphic-fetch_v2.x.x.js new file mode 100644 index 0000000..4d49836 --- /dev/null +++ b/flow-typed/npm/isomorphic-fetch_v2.x.x.js @@ -0,0 +1,3 @@ +declare module 'isomorphic-fetch' { + declare module.exports: (input: string | Request, init?: RequestOptions) => Promise; +} diff --git a/flow-typed/npm/rxjs_v5.0.x.js b/flow-typed/npm/rxjs_v5.0.x.js new file mode 100644 index 0000000..53d374a --- /dev/null +++ b/flow-typed/npm/rxjs_v5.0.x.js @@ -0,0 +1,825 @@ +// flow-typed signature: 8ecb01da08c708bfc429a63dd22d3cdd +// flow-typed version: 201cfddff4/rxjs_v5.0.x/flow_>=v0.34.x + +// FIXME(samgoldman) Remove top-level interface once Babel supports +// `declare interface` syntax. +// FIXME(samgoldman) Remove this once rxjs$Subject can mixin rxjs$Observer +interface rxjs$IObserver<-T> { + next(value: T): mixed; + error(error: any): mixed; + complete(): mixed; +} + +type rxjs$PartialObserver<-T> = + | { + +next: (value: T) => mixed; + +error?: (error: any) => mixed; + +complete?: () => mixed; + } + | { + +next?: (value: T) => mixed; + +error: (error: any) => mixed; + +complete?: () => mixed; + } + | { + +next?: (value: T) => mixed; + +error?: (error: any) => mixed; + +complete: () => mixed; + } + +interface rxjs$ISubscription { + unsubscribe(): void; +} + +type rxjs$TeardownLogic = rxjs$ISubscription | () => void; + +type rxjs$EventListenerOptions = { + capture?: boolean; + passive?: boolean; + once?: boolean; +} | boolean; + +type AjaxRequest = {| + url?: string; + body?: any; + user?: string; + async?: boolean; + method?: string; + headers?: Object; + timeout?: number; + password?: string; + hasContent?: boolean; + crossDomain?: boolean; + withCredentials?: boolean; + createXHR?: () => XMLHttpRequest; + // progressSubscriber?: Subscriber; + responseType?: string; +|} + +type AjaxResponse = { + status: number, + response: any, + responseText: string, + responseType: string +} + +declare class rxjs$Observable<+T> { + static bindCallback(callbackFunc: (callback: (_: void) => any) => any, selector?: void, scheduler?: rxjs$SchedulerClass): () => rxjs$Observable; + static bindCallback(callbackFunc: (callback: (result: U) => any) => any, selector?: void, scheduler?: rxjs$SchedulerClass): () => rxjs$Observable; + static bindCallback(callbackFunc: (v1: T, callback: (result: U) => any) => any, selector?: void, scheduler?: rxjs$SchedulerClass): (v1: T) => rxjs$Observable; + static bindCallback(callbackFunc: (v1: T, v2: T2, callback: (result: U) => any) => any, selector?: void, scheduler?: rxjs$SchedulerClass): (v1: T, v2: T2) => rxjs$Observable; + static bindCallback(callbackFunc: (v1: T, v2: T2, v3: T3, callback: (result: U) => any) => any, selector?: void, scheduler?: rxjs$SchedulerClass): (v1: T, v2: T2, v3: T3) => rxjs$Observable; + static bindCallback(callbackFunc: (v1: T, v2: T2, v3: T3, v4: T4, callback: (result: U) => any) => any, selector?: void, scheduler?: rxjs$SchedulerClass): (v1: T, v2: T2, v3: T3, v4: T4) => rxjs$Observable; + static bindCallback(callbackFunc: (v1: T, v2: T2, v3: T3, v4: T4, v5: T5, callback: (result: U) => any) => any, selector?: void, scheduler?: rxjs$SchedulerClass): (v1: T, v2: T2, v3: T3, v4: T4, v5: T5) => rxjs$Observable; + static bindCallback(callbackFunc: (v1: T, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6, callback: (result: U) => any) => any, selector?: void, scheduler?: rxjs$SchedulerClass): (v1: T, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6) => rxjs$Observable; + static bindCallback(callbackFunc: (callback: (...args: Array) => any) => any, selector: (...args: Array) => U, scheduler?: rxjs$SchedulerClass): () => rxjs$Observable; + static bindCallback(callbackFunc: (v1: T, callback: (...args: Array) => any) => any, selector: (...args: Array) => U, scheduler?: rxjs$SchedulerClass): (v1: T) => rxjs$Observable; + static bindCallback(callbackFunc: (v1: T, v2: T2, callback: (...args: Array) => any) => any, selector: (...args: Array) => U, scheduler?: rxjs$SchedulerClass): (v1: T, v2: T2) => rxjs$Observable; + static bindCallback(callbackFunc: (v1: T, v2: T2, v3: T3, callback: (...args: Array) => any) => any, selector: (...args: Array) => U, scheduler?: rxjs$SchedulerClass): (v1: T, v2: T2, v3: T3) => rxjs$Observable; + static bindCallback(callbackFunc: (v1: T, v2: T2, v3: T3, v4: T4, callback: (...args: Array) => any) => any, selector: (...args: Array) => U, scheduler?: rxjs$SchedulerClass): (v1: T, v2: T2, v3: T3, v4: T4) => rxjs$Observable; + static bindCallback(callbackFunc: (v1: T, v2: T2, v3: T3, v4: T4, v5: T5, callback: (...args: Array) => any) => any, selector: (...args: Array) => U, scheduler?: rxjs$SchedulerClass): (v1: T, v2: T2, v3: T3, v4: T4, v5: T5) => rxjs$Observable; + static bindCallback(callbackFunc: (v1: T, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6, callback: (...args: Array) => any) => any, selector: (...args: Array) => U, scheduler?: rxjs$SchedulerClass): (v1: T, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6) => rxjs$Observable; + static bindCallback(callbackFunc: Function, selector?: void, scheduler?: rxjs$SchedulerClass): (...args: Array) => rxjs$Observable; + static bindCallback(callbackFunc: Function, selector?: (...args: Array) => T, scheduler?: rxjs$SchedulerClass): (...args: Array) => rxjs$Observable; + + static bindNodeCallback(callbackFunc: (callback: (err: any, result: U) => any) => any, selector?: void, scheduler?: rxjs$SchedulerClass): () => rxjs$Observable; + static bindNodeCallback(callbackFunc: (v1: T, callback: (err: any, result: U) => any) => any, selector?: void, scheduler?: rxjs$SchedulerClass): (v1: T) => rxjs$Observable; + static bindNodeCallback(callbackFunc: (v1: T, v2: T2, callback: (err: any, result: U) => any) => any, selector?: void, scheduler?: rxjs$SchedulerClass): (v1: T, v2: T2) => rxjs$Observable; + static bindNodeCallback(callbackFunc: (v1: T, v2: T2, v3: T3, callback: (err: any, result: U) => any) => any, selector?: void, scheduler?: rxjs$SchedulerClass): (v1: T, v2: T2, v3: T3) => rxjs$Observable; + static bindNodeCallback(callbackFunc: (v1: T, v2: T2, v3: T3, v4: T4, callback: (err: any, result: U) => any) => any, selector?: void, scheduler?: rxjs$SchedulerClass): (v1: T, v2: T2, v3: T3, v4: T4) => rxjs$Observable; + static bindNodeCallback(callbackFunc: (v1: T, v2: T2, v3: T3, v4: T4, v5: T5, callback: (err: any, result: U) => any) => any, selector?: void, scheduler?: rxjs$SchedulerClass): (v1: T, v2: T2, v3: T3, v4: T4, v5: T5) => rxjs$Observable; + static bindNodeCallback(callbackFunc: (v1: T, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6, callback: (err: any, result: U) => any) => any, selector?: void, scheduler?: rxjs$SchedulerClass): (v1: T, v2: T2, v3: T3, v4: T4, v5: T5, v6: T6) => rxjs$Observable; + static bindNodeCallback(callbackFunc: Function, selector?: void, scheduler?: rxjs$SchedulerClass): (...args: Array) => rxjs$Observable; + static bindNodeCallback(callbackFunc: Function, selector?: (...args: Array) => T, scheduler?: rxjs$SchedulerClass): (...args: Array) => rxjs$Observable; + + static concat(...sources: rxjs$Observable[]): rxjs$Observable; + + static create( + subscribe: (observer: rxjs$Observer) => rxjs$ISubscription | Function | void + ): rxjs$Observable; + + static defer(observableFactory: () => rxjs$Observable | Promise): rxjs$Observable; + + static from(iterable: Iterable): rxjs$Observable; + + static fromEvent(element: any, eventName: string, ...none: Array): rxjs$Observable; + static fromEvent( + element: any, + eventName: string, + options: rxjs$EventListenerOptions, + ...none: Array + ): rxjs$Observable; + static fromEvent( + element: any, + eventName: string, + selector: () => T, + ...none: Array + ): rxjs$Observable; + static fromEvent( + element: any, + eventName: string, + options: rxjs$EventListenerOptions, + selector: () => T, + ): rxjs$Observable; + + static fromEventPattern( + addHandler: (handler: () => void) => void, + removeHandler: (handler: () => void) => void, + selector?: () => T, + ): rxjs$Observable; + + static fromPromise(promise: Promise): rxjs$Observable; + + static empty(): rxjs$Observable; + + static interval(period: number): rxjs$Observable; + + static timer(initialDelay: (number | Date), period?: number, scheduler?: rxjs$SchedulerClass): rxjs$Observable; + + static merge( + source0: rxjs$Observable, + source1: rxjs$Observable, + ): rxjs$Observable; + static merge( + source0: rxjs$Observable, + source1: rxjs$Observable, + source2: rxjs$Observable, + ): rxjs$Observable; + static merge(...sources: rxjs$Observable[]): rxjs$Observable; + + static never(): rxjs$Observable; + + static of(...values: T[]): rxjs$Observable; + + static throw(error: any): rxjs$Observable; + + audit(durationSelector: (value: T) => rxjs$Observable | Promise): rxjs$Observable; + + race(other: rxjs$Observable): rxjs$Observable; + + repeat(): rxjs$Observable; + + buffer(bufferBoundaries: rxjs$Observable): rxjs$Observable>; + + catch(selector: (err: any, caught: rxjs$Observable) => rxjs$Observable): rxjs$Observable; + + concat(...sources: rxjs$Observable[]): rxjs$Observable; + + concatAll(): rxjs$Observable; + + concatMap( + f: (value: T) => rxjs$Observable | Promise | Iterable + ): rxjs$Observable; + + debounceTime(dueTime: number, scheduler?: rxjs$SchedulerClass): rxjs$Observable; + + delay(dueTime: number, scheduler?: rxjs$SchedulerClass): rxjs$Observable; + + distinctUntilChanged(compare?: (x: T, y: T) => boolean): rxjs$Observable; + + distinct(keySelector?: (value: T) => U, flushes?: rxjs$Observable): rxjs$Observable; + + distinctUntilKeyChanged(key: string, compare?: (x: mixed, y: mixed) => boolean): rxjs$Observable; + + elementAt(index: number, defaultValue?: T): rxjs$Observable; + + filter(predicate: (value: T) => boolean): rxjs$Observable; + + finally(f: () => mixed): rxjs$Observable; + + first( + predicate?: (value: T, index: number, source: rxjs$Observable) => boolean, + ): rxjs$Observable; + first( + predicate: ?(value: T, index: number, source: rxjs$Observable) => boolean, + resultSelector: (value: T, index: number) => U, + ): rxjs$Observable; + first( + predicate: ?(value: T, index: number, source: rxjs$Observable) => boolean, + resultSelector: ?(value: T, index: number) => U, + defaultValue: U, + ): rxjs$Observable; + + groupBy( + keySelector: (value: T) => mixed, + elementSelector?: (value: T) => T, + compare?: (x: T, y: T) => boolean, + ): rxjs$Observable>; + + ignoreElements(): rxjs$Observable; + + let(project: (self: rxjs$Observable) => rxjs$Observable): rxjs$Observable; + + // Alias for `let` + letBind(project: (self: rxjs$Observable) => rxjs$Observable): rxjs$Observable; + + switch(): T; // assumption: T is Observable + + // Alias for `mergeMap` + flatMap( + project: (value: T) => rxjs$Observable | Promise | Iterable, + index?: number, + ): rxjs$Observable; + + flatMapTo( + innerObservable: rxjs$Observable + ): rxjs$Observable; + + flatMapTo( + innerObservable: rxjs$Observable < U >, + resultSelector: (outerValue: T, innerValue: U, outerIndex: number, innerIndex: number) => V, + concurrent ?: number + ): rxjs$Observable; + + switchMap( + project: (value: T) => rxjs$Observable | Promise | Iterable, + index?: number, + ): rxjs$Observable; + + switchMapTo( + innerObservable: rxjs$Observable, + ): rxjs$Observable; + + map(f: (value: T) => U): rxjs$Observable; + + mapTo(value: U): rxjs$Observable; + + merge(other: rxjs$Observable): rxjs$Observable; + + mergeAll(): rxjs$Observable; + + mergeMap( + project: (value: T, index?: number) => rxjs$Observable | Promise | Iterable, + index?: number, + ): rxjs$Observable; + + mergeMapTo( + innerObservable: rxjs$Observable + ): rxjs$Observable; + + mergeMapTo( + innerObservable: rxjs$Observable < U >, + resultSelector: (outerValue: T, innerValue: U, outerIndex: number, innerIndex: number) => V, + concurrent ?: number + ): rxjs$Observable; + + multicast( + subjectOrSubjectFactory: rxjs$Subject | () => rxjs$Subject, + ): rxjs$ConnectableObservable; + + observeOn(scheduler: rxjs$SchedulerClass): rxjs$Observable; + + pairwise(): rxjs$Observable<[T, T]>; + + publish(): rxjs$ConnectableObservable; + + publishLast(): rxjs$ConnectableObservable; + + reduce( + accumulator: ( + acc: U, + currentValue: T, + index: number, + source: rxjs$Observable, + ) => U, + seed: U, + ): rxjs$Observable; + + sample(notifier: rxjs$Observable): rxjs$Observable; + + sampleTime(delay: number): rxjs$Observable; + + publishReplay(bufferSize?: number, windowTime?: number, scheduler?: rxjs$SchedulerClass): rxjs$ConnectableObservable; + + retry(retryCount: number): rxjs$Observable; + + retryWhen(notifier: (errors: rxjs$Observable) => rxjs$Observable): rxjs$Observable; + + scan( + f: (acc: U, value: T) => U, + initialValue: U, + ): rxjs$Observable; + + share(): rxjs$Observable; + + skip(count: number): rxjs$Observable; + + skipUntil(other: rxjs$Observable | Promise): rxjs$Observable; + + skipWhile(predicate: (value: T) => boolean): rxjs$Observable; + + startWith(...values: Array): rxjs$Observable; + + subscribeOn(scheduler: rxjs$SchedulerClass): rxjs$Observable; + + take(count: number): rxjs$Observable; + + takeUntil(other: rxjs$Observable): rxjs$Observable; + + takeWhile(f: (value: T) => boolean): rxjs$Observable; + + do( + onNext?: (value: T) => mixed, + onError?: (error: any) => mixed, + onCompleted?: () => mixed, + ): rxjs$Observable; + do(observer: { + next?: (value: T) => mixed; + error?: (error: any) => mixed; + complete?: () => mixed; + }): rxjs$Observable; + + throttleTime(duration: number): rxjs$Observable; + + timeout(due: number | Date, _: void): rxjs$Observable; + + toArray(): rxjs$Observable; + + toPromise(): Promise; + + subscribe(observer: rxjs$PartialObserver): rxjs$Subscription; + subscribe( + onNext: ?(value: T) => mixed, + onError: ?(error: any) => mixed, + onCompleted: ?() => mixed, + ): rxjs$Subscription; + + static combineLatest( + a: rxjs$Observable, + resultSelector: (a: A) => B, + ): rxjs$Observable; + + static combineLatest( + a: rxjs$Observable, + b: rxjs$Observable, + resultSelector: (a: A, b: B) => C, + ): rxjs$Observable; + + static combineLatest( + a: rxjs$Observable, + b: rxjs$Observable, + c: rxjs$Observable, + resultSelector: (a: A, b: B, c: C) => D, + ): rxjs$Observable; + + static combineLatest( + a: rxjs$Observable, + b: rxjs$Observable, + c: rxjs$Observable, + d: rxjs$Observable, + resultSelector: (a: A, b: B, c: C, d: D) => E, + ): rxjs$Observable; + + static combineLatest( + a: rxjs$Observable, + b: rxjs$Observable, + c: rxjs$Observable, + d: rxjs$Observable, + e: rxjs$Observable, + resultSelector: (a: A, b: B, c: C, d: D, e: E) => F, + ): rxjs$Observable; + + static combineLatest( + a: rxjs$Observable, + b: rxjs$Observable, + c: rxjs$Observable, + d: rxjs$Observable, + e: rxjs$Observable, + f: rxjs$Observable, + resultSelector: (a: A, b: B, c: C, d: D, e: E, f: F) => G, + ): rxjs$Observable; + + static combineLatest( + a: rxjs$Observable, + b: rxjs$Observable, + c: rxjs$Observable, + d: rxjs$Observable, + e: rxjs$Observable, + f: rxjs$Observable, + g: rxjs$Observable, + resultSelector: (a: A, b: B, c: C, d: D, e: E, f: F, g: G) => H, + ): rxjs$Observable; + + static combineLatest( + a: rxjs$Observable, + b: rxjs$Observable, + _: void, + ): rxjs$Observable<[A, B]>; + + static combineLatest( + a: rxjs$Observable, + b: rxjs$Observable, + c: rxjs$Observable, + _: void, + ): rxjs$Observable<[A, B, C]>; + + static combineLatest( + a: rxjs$Observable, + b: rxjs$Observable, + c: rxjs$Observable, + d: rxjs$Observable, + _: void, + ): rxjs$Observable<[A, B, C, D]>; + + static combineLatest( + a: rxjs$Observable, + b: rxjs$Observable, + c: rxjs$Observable, + d: rxjs$Observable, + e: rxjs$Observable, + _: void, + ): rxjs$Observable<[A, B, C, D, E]>; + + static combineLatest( + a: rxjs$Observable, + b: rxjs$Observable, + c: rxjs$Observable, + d: rxjs$Observable, + e: rxjs$Observable, + f: rxjs$Observable, + _: void, + ): rxjs$Observable<[A, B, C, D, E, F]>; + + static combineLatest( + a: rxjs$Observable, + b: rxjs$Observable, + c: rxjs$Observable, + d: rxjs$Observable, + e: rxjs$Observable, + f: rxjs$Observable, + g: rxjs$Observable, + _: void, + ): rxjs$Observable<[A, B, C, D, E, F, G]>; + + static combineLatest( + a: rxjs$Observable, + b: rxjs$Observable, + c: rxjs$Observable, + d: rxjs$Observable, + e: rxjs$Observable, + f: rxjs$Observable, + g: rxjs$Observable, + h: rxjs$Observable, + _: void, + ): rxjs$Observable<[A, B, C, D, E, F, G, H]>; + + combineLatest( + a: rxjs$Observable, + _: void, + ): rxjs$Observable<[T, A]>; + + combineLatest( + a: rxjs$Observable, + resultSelector: (a: A) => B, + ): rxjs$Observable; + + combineLatest( + a: rxjs$Observable, + b: rxjs$Observable, + resultSelector: (a: A, b: B) => C, + ): rxjs$Observable; + + combineLatest( + a: rxjs$Observable, + b: rxjs$Observable, + c: rxjs$Observable, + resultSelector: (a: A, b: B, c: C) => D, + ): rxjs$Observable; + + combineLatest( + a: rxjs$Observable, + b: rxjs$Observable, + c: rxjs$Observable, + d: rxjs$Observable, + resultSelector: (a: A, b: B, c: C, d: D) => E, + ): rxjs$Observable; + + combineLatest( + a: rxjs$Observable, + b: rxjs$Observable, + c: rxjs$Observable, + d: rxjs$Observable, + e: rxjs$Observable, + resultSelector: (a: A, b: B, c: C, d: D, e: E) => F, + ): rxjs$Observable; + + combineLatest( + a: rxjs$Observable, + b: rxjs$Observable, + c: rxjs$Observable, + d: rxjs$Observable, + e: rxjs$Observable, + f: rxjs$Observable, + resultSelector: (a: A, b: B, c: C, d: D, e: E, f: F) => G, + ): rxjs$Observable; + + combineLatest( + a: rxjs$Observable, + b: rxjs$Observable, + c: rxjs$Observable, + d: rxjs$Observable, + e: rxjs$Observable, + f: rxjs$Observable, + g: rxjs$Observable, + resultSelector: (a: A, b: B, c: C, d: D, e: E, f: F, g: G) => H, + ): rxjs$Observable; + + static forkJoin( + a: rxjs$Observable[] + ): rxjs$Observable; + + static forkJoin( + a: rxjs$Observable, + resultSelector: (a: A) => B, + ): rxjs$Observable; + + static forkJoin( + a: rxjs$Observable, + b: rxjs$Observable, + resultSelector: (a: A, b: B) => C, + ): rxjs$Observable; + + static forkJoin( + a: rxjs$Observable, + b: rxjs$Observable, + c: rxjs$Observable, + resultSelector: (a: A, b: B, c: C) => D, + ): rxjs$Observable; + + static forkJoin( + a: rxjs$Observable, + b: rxjs$Observable, + c: rxjs$Observable, + d: rxjs$Observable, + resultSelector: (a: A, b: B, c: C, d: D) => E, + ): rxjs$Observable; + + static forkJoin( + a: rxjs$Observable, + b: rxjs$Observable, + c: rxjs$Observable, + d: rxjs$Observable, + e: rxjs$Observable, + resultSelector: (a: A, b: B, c: C, d: D, e: E) => F, + ): rxjs$Observable; + + static forkJoin( + a: rxjs$Observable, + b: rxjs$Observable, + c: rxjs$Observable, + d: rxjs$Observable, + e: rxjs$Observable, + f: rxjs$Observable, + resultSelector: (a: A, b: B, c: C, d: D, e: E, f: F) => G, + ): rxjs$Observable; + + static forkJoin( + a: rxjs$Observable, + b: rxjs$Observable, + c: rxjs$Observable, + d: rxjs$Observable, + e: rxjs$Observable, + f: rxjs$Observable, + g: rxjs$Observable, + resultSelector: (a: A, b: B, c: C, d: D, e: E, f: F, g: G) => H, + ): rxjs$Observable; + + static forkJoin( + a: rxjs$Observable, + b: rxjs$Observable, + _: void, + ): rxjs$Observable<[A, B]>; + + static forkJoin( + a: rxjs$Observable, + b: rxjs$Observable, + c: rxjs$Observable, + _: void, + ): rxjs$Observable<[A, B, C]>; + + static forkJoin( + a: rxjs$Observable, + b: rxjs$Observable, + c: rxjs$Observable, + d: rxjs$Observable, + _: void, + ): rxjs$Observable<[A, B, C, D]>; + + static forkJoin( + a: rxjs$Observable, + b: rxjs$Observable, + c: rxjs$Observable, + d: rxjs$Observable, + e: rxjs$Observable, + _: void, + ): rxjs$Observable<[A, B, C, D, E]>; + + static forkJoin( + a: rxjs$Observable, + b: rxjs$Observable, + c: rxjs$Observable, + d: rxjs$Observable, + e: rxjs$Observable, + f: rxjs$Observable, + _: void, + ): rxjs$Observable<[A, B, C, D, E, F]>; + + static forkJoin( + a: rxjs$Observable, + b: rxjs$Observable, + c: rxjs$Observable, + d: rxjs$Observable, + e: rxjs$Observable, + f: rxjs$Observable, + g: rxjs$Observable, + _: void, + ): rxjs$Observable<[A, B, C, D, E, F, G]>; + + static forkJoin( + a: rxjs$Observable, + b: rxjs$Observable, + c: rxjs$Observable, + d: rxjs$Observable, + e: rxjs$Observable, + f: rxjs$Observable, + g: rxjs$Observable, + h: rxjs$Observable, + _: void, + ): rxjs$Observable<[A, B, C, D, E, F, G, H]>; + + static ajax(urlOrRequest: string | AjaxRequest): rxjs$Observable; + + withLatestFrom( + a: rxjs$Observable, + _: void, + ): rxjs$Observable<[T, A]>; + + withLatestFrom( + a: rxjs$Observable, + resultSelector: (a: A) => B, + ): rxjs$Observable; + + withLatestFrom( + a: rxjs$Observable, + b: rxjs$Observable, + resultSelector: (a: A, b: B) => C, + ): rxjs$Observable; + + withLatestFrom( + a: rxjs$Observable, + b: rxjs$Observable, + c: rxjs$Observable, + resultSelector: (a: A, b: B, c: C) => D, + ): rxjs$Observable; + + withLatestFrom( + a: rxjs$Observable, + b: rxjs$Observable, + c: rxjs$Observable, + d: rxjs$Observable, + resultSelector: (a: A, b: B, c: C, d: D) => E, + ): rxjs$Observable; + + withLatestFrom( + a: rxjs$Observable, + b: rxjs$Observable, + c: rxjs$Observable, + d: rxjs$Observable, + e: rxjs$Observable, + resultSelector: (a: A, b: B, c: C, d: D, e: E) => F, + ): rxjs$Observable; + + withLatestFrom( + a: rxjs$Observable, + b: rxjs$Observable, + c: rxjs$Observable, + d: rxjs$Observable, + e: rxjs$Observable, + f: rxjs$Observable, + resultSelector: (a: A, b: B, c: C, d: D, e: E, f: F) => G, + ): rxjs$Observable; + + withLatestFrom( + a: rxjs$Observable, + b: rxjs$Observable, + c: rxjs$Observable, + d: rxjs$Observable, + e: rxjs$Observable, + f: rxjs$Observable, + g: rxjs$Observable, + resultSelector: (a: A, b: B, c: C, d: D, e: E, f: F, g: G) => H, + ): rxjs$Observable; + + static using( + resourceFactory: () => ?R, + observableFactory: (resource: R) => rxjs$Observable | Promise | void, + ): rxjs$Observable; +} + +declare class rxjs$ConnectableObservable extends rxjs$Observable { + connect(): rxjs$Subscription; + refCount(): rxjs$Observable; +} + +declare class rxjs$Observer { + next(value: T): mixed; + + error(error: any): mixed; + + complete(): mixed; +} + +// FIXME(samgoldman) should be `mixins rxjs$Observable, rxjs$Observer` +// once Babel parsing support exists: https://phabricator.babeljs.io/T6821 +declare class rxjs$Subject extends rxjs$Observable { + asObservable(): rxjs$Observable; + + observers: Array>; + + unsubscribe(): void; + + // Copied from rxjs$Observer + next(value: T): mixed; + error(error: any): mixed; + complete(): mixed; + + // For use in subclasses only: + _next(value: T): void; + _subscribe(observer: rxjs$PartialObserver): rxjs$Subscription; +} + +declare class rxjs$BehaviorSubject extends rxjs$Subject { + constructor(initialValue: T): void; + + getValue(): T; +} + +declare class rxjs$ReplaySubject extends rxjs$Subject { + constructor(bufferSize?: number, windowTime?: number, scheduler?: rxjs$SchedulerClass): void; +} + +declare class rxjs$Subscription { + unsubscribe(): void; + add(teardown: rxjs$TeardownLogic): rxjs$Subscription; +} + +declare class rxjs$SchedulerClass { + schedule(work: (state?: T) => void, delay?: number, state?: T): rxjs$Subscription; +} + +declare class rxjs$TimeoutError extends Error { +} + +declare module 'rxjs' { + declare module.exports: { + Observable: typeof rxjs$Observable, + ConnectableObservable: typeof rxjs$ConnectableObservable, + Subject: typeof rxjs$Subject, + BehaviorSubject: typeof rxjs$BehaviorSubject, + ReplaySubject: typeof rxjs$ReplaySubject, + Scheduler: { + asap: rxjs$SchedulerClass, + queue: rxjs$SchedulerClass, + animationFrame: rxjs$SchedulerClass, + async: rxjs$SchedulerClass, + }, + Subscription: typeof rxjs$Subscription, + TimeoutError: typeof rxjs$TimeoutError, + } +} + +declare module 'rxjs/Observable' { + declare module.exports: { + Observable: typeof rxjs$Observable + } +} + +declare module 'rxjs/Observer' { + declare module.exports: { + Observer: typeof rxjs$Observer + } +} + +declare module 'rxjs/BehaviorSubject' { + declare module.exports: { + BehaviorSubject: typeof rxjs$BehaviorSubject + } +} + +declare module 'rxjs/ReplaySubject' { + declare module.exports: { + ReplaySubject: typeof rxjs$ReplaySubject + } +} + +declare module 'rxjs/Subject' { + declare module.exports: { + Subject: typeof rxjs$Subject + } +} + +declare module 'rxjs/Subscription' { + declare module.exports: { + Subscription: typeof rxjs$Subscription + } +} diff --git a/gulpfile.babel.js b/gulpfile.babel.js index f68b615..bc38aae 100644 --- a/gulpfile.babel.js +++ b/gulpfile.babel.js @@ -29,10 +29,7 @@ gulp.task('clean', () => del('lib')) gulp.task('build', ['clean'], () => { return gulp.src('src/**/*.js') .pipe($.sourcemaps.init()) - .pipe($.babel({ - presets: ['es2015'], - babelrc: false - })) + .pipe($.babel()) .pipe($.sourcemaps.write()) .pipe(gulp.dest('lib')) }) diff --git a/index.js b/index.js deleted file mode 100644 index d1e6949..0000000 --- a/index.js +++ /dev/null @@ -1,2 +0,0 @@ -module.exports = require('./lib/').default -module.exports.VASTLoaderError = require('./lib/error') diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index cafd10f..0000000 --- a/package-lock.json +++ /dev/null @@ -1,3504 +0,0 @@ -{ - "name": "iab-vast-loader", - "version": "0.8.0", - "lockfileVersion": 1, - "dependencies": { - "@gulp-sourcemaps/identity-map": { - "version": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-1.0.1.tgz", - "integrity": "sha1-z6I7xYQPkQTOMqZedNt+epdLvuE=", - "dev": true, - "dependencies": { - "acorn": { - "version": "https://registry.npmjs.org/acorn/-/acorn-5.0.3.tgz", - "integrity": "sha1-xGDfCEkUY/AozLguqzcwvwEIez0=", - "dev": true - } - } - }, - "@gulp-sourcemaps/map-sources": { - "version": "https://registry.npmjs.org/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz", - "integrity": "sha1-iQrnxdjId/bThIYCFazp1+yUW9o=", - "dev": true - }, - "abbrev": { - "version": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", - "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", - "dev": true - }, - "accepts": { - "version": "https://registry.npmjs.org/accepts/-/accepts-1.3.3.tgz", - "integrity": "sha1-w8p0NJOGSMPg2cHjKN1otiLChMo=", - "dev": true - }, - "acorn": { - "version": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", - "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", - "dev": true - }, - "acorn-jsx": { - "version": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", - "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", - "dev": true, - "dependencies": { - "acorn": { - "version": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", - "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", - "dev": true - } - } - }, - "ajv": { - "version": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", - "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", - "dev": true - }, - "ajv-keywords": { - "version": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", - "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=", - "dev": true - }, - "align-text": { - "version": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", - "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", - "dev": true - }, - "amdefine": { - "version": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true - }, - "ansi-escapes": { - "version": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", - "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", - "dev": true - }, - "ansi-regex": { - "version": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "any-promise": { - "version": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=", - "dev": true - }, - "app-root-path": { - "version": "https://registry.npmjs.org/app-root-path/-/app-root-path-2.0.1.tgz", - "integrity": "sha1-zWLc+OT9WkF+/GZNLlsQZTxlG0Y=", - "dev": true - }, - "archy": { - "version": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true - }, - "argparse": { - "version": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", - "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", - "dev": true - }, - "arr-diff": { - "version": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "dev": true - }, - "arr-flatten": { - "version": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.0.3.tgz", - "integrity": "sha1-onTthawIhJtr14R8RYB0XcUa37E=", - "dev": true - }, - "array-differ": { - "version": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", - "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", - "dev": true - }, - "array-flatten": { - "version": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", - "dev": true - }, - "array-union": { - "version": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true - }, - "array-uniq": { - "version": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true - }, - "array-unique": { - "version": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true - }, - "array.prototype.find": { - "version": "https://registry.npmjs.org/array.prototype.find/-/array.prototype.find-2.0.4.tgz", - "integrity": "sha1-VWpcU2LAhkgyPdrrnenRS8GGTJA=", - "dev": true - }, - "arrify": { - "version": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true - }, - "asn1": { - "version": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", - "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", - "dev": true - }, - "assert-plus": { - "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", - "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", - "dev": true - }, - "assertion-error": { - "version": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.2.tgz", - "integrity": "sha1-E8pRXYYgbaC6xm6DTdOX2HWBCUw=", - "dev": true - }, - "async": { - "version": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "asynckit": { - "version": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "atob": { - "version": "https://registry.npmjs.org/atob/-/atob-1.1.3.tgz", - "integrity": "sha1-lfE2KbEsOlGl0hWr3OKqnzL4B3M=", - "dev": true - }, - "aws-sign2": { - "version": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", - "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", - "dev": true - }, - "aws4": { - "version": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", - "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", - "dev": true - }, - "babel-code-frame": { - "version": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz", - "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=", - "dev": true - }, - "babel-core": { - "version": "https://registry.npmjs.org/babel-core/-/babel-core-6.24.1.tgz", - "integrity": "sha1-jEKFZNzh4fQfszfsNPTDsCK1rYM=", - "dev": true - }, - "babel-generator": { - "version": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.24.1.tgz", - "integrity": "sha1-5xX0hsWN7SVknYiJRNUqoHxdlJc=", - "dev": true, - "dependencies": { - "jsesc": { - "version": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", - "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", - "dev": true - } - } - }, - "babel-helper-builder-binary-assignment-operator-visitor": { - "version": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", - "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", - "dev": true - }, - "babel-helper-call-delegate": { - "version": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", - "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", - "dev": true - }, - "babel-helper-define-map": { - "version": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.24.1.tgz", - "integrity": "sha1-epdH8ljYlH0y1RX2qhx70CIEoIA=", - "dev": true - }, - "babel-helper-explode-assignable-expression": { - "version": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", - "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", - "dev": true - }, - "babel-helper-function-name": { - "version": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", - "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", - "dev": true - }, - "babel-helper-get-function-arity": { - "version": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", - "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", - "dev": true - }, - "babel-helper-hoist-variables": { - "version": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", - "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", - "dev": true - }, - "babel-helper-optimise-call-expression": { - "version": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", - "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", - "dev": true - }, - "babel-helper-regex": { - "version": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.24.1.tgz", - "integrity": "sha1-024i+rEAjXnYhkjjIRaGgShFbOg=", - "dev": true - }, - "babel-helper-remap-async-to-generator": { - "version": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", - "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", - "dev": true - }, - "babel-helper-replace-supers": { - "version": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", - "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", - "dev": true - }, - "babel-helpers": { - "version": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", - "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", - "dev": true - }, - "babel-messages": { - "version": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", - "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", - "dev": true - }, - "babel-plugin-check-es2015-constants": { - "version": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", - "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", - "dev": true - }, - "babel-plugin-syntax-async-functions": { - "version": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", - "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=", - "dev": true - }, - "babel-plugin-syntax-exponentiation-operator": { - "version": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", - "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=", - "dev": true - }, - "babel-plugin-syntax-trailing-function-commas": { - "version": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", - "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=", - "dev": true - }, - "babel-plugin-transform-async-to-generator": { - "version": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", - "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", - "dev": true - }, - "babel-plugin-transform-builtin-extend": { - "version": "https://registry.npmjs.org/babel-plugin-transform-builtin-extend/-/babel-plugin-transform-builtin-extend-1.1.2.tgz", - "integrity": "sha1-Xpb+z1i4+h7XTvytiEdbKvPJEW4=", - "dev": true - }, - "babel-plugin-transform-es2015-arrow-functions": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", - "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", - "dev": true - }, - "babel-plugin-transform-es2015-block-scoped-functions": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", - "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", - "dev": true - }, - "babel-plugin-transform-es2015-block-scoping": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.24.1.tgz", - "integrity": "sha1-dsKV3DpHQbFmWt/TFnIV3P8ypXY=", - "dev": true - }, - "babel-plugin-transform-es2015-classes": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", - "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", - "dev": true - }, - "babel-plugin-transform-es2015-computed-properties": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", - "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", - "dev": true - }, - "babel-plugin-transform-es2015-destructuring": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", - "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", - "dev": true - }, - "babel-plugin-transform-es2015-duplicate-keys": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", - "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", - "dev": true - }, - "babel-plugin-transform-es2015-for-of": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", - "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", - "dev": true - }, - "babel-plugin-transform-es2015-function-name": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", - "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", - "dev": true - }, - "babel-plugin-transform-es2015-literals": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", - "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", - "dev": true - }, - "babel-plugin-transform-es2015-modules-amd": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", - "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", - "dev": true - }, - "babel-plugin-transform-es2015-modules-commonjs": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.24.1.tgz", - "integrity": "sha1-0+MQtA72ZKNmIiAAl8bUQCmPK/4=", - "dev": true - }, - "babel-plugin-transform-es2015-modules-systemjs": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", - "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", - "dev": true - }, - "babel-plugin-transform-es2015-modules-umd": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", - "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", - "dev": true - }, - "babel-plugin-transform-es2015-object-super": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", - "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", - "dev": true - }, - "babel-plugin-transform-es2015-parameters": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", - "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", - "dev": true - }, - "babel-plugin-transform-es2015-shorthand-properties": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", - "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", - "dev": true - }, - "babel-plugin-transform-es2015-spread": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", - "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", - "dev": true - }, - "babel-plugin-transform-es2015-sticky-regex": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", - "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", - "dev": true - }, - "babel-plugin-transform-es2015-template-literals": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", - "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", - "dev": true - }, - "babel-plugin-transform-es2015-typeof-symbol": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", - "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", - "dev": true - }, - "babel-plugin-transform-es2015-unicode-regex": { - "version": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", - "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", - "dev": true - }, - "babel-plugin-transform-exponentiation-operator": { - "version": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", - "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", - "dev": true - }, - "babel-plugin-transform-regenerator": { - "version": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.24.1.tgz", - "integrity": "sha1-uNowWtQ8PJm0hI5P5AN7dw0jxBg=", - "dev": true - }, - "babel-plugin-transform-runtime": { - "version": "https://registry.npmjs.org/babel-plugin-transform-runtime/-/babel-plugin-transform-runtime-6.23.0.tgz", - "integrity": "sha1-iEkNRGUC6puOfvsP4J7E2ZR5se4=", - "dev": true - }, - "babel-plugin-transform-strict-mode": { - "version": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", - "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", - "dev": true - }, - "babel-preset-env": { - "version": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.5.2.tgz", - "integrity": "sha1-zUrpCm6Utwn5c3SzPl+LmDVWre8=", - "dev": true - }, - "babel-preset-es2015": { - "version": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz", - "integrity": "sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk=", - "dev": true - }, - "babel-register": { - "version": "https://registry.npmjs.org/babel-register/-/babel-register-6.24.1.tgz", - "integrity": "sha1-fhDhOi9xBlvfrVoXh7pFvKbe118=", - "dev": true - }, - "babel-runtime": { - "version": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.23.0.tgz", - "integrity": "sha1-CpSJ8UTecO+zzkMArM2zKeL8VDs=", - "dev": true - }, - "babel-template": { - "version": "https://registry.npmjs.org/babel-template/-/babel-template-6.24.1.tgz", - "integrity": "sha1-BK5RTx+Ts6JTfyoPYKWkX7gwgzM=", - "dev": true - }, - "babel-traverse": { - "version": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.24.1.tgz", - "integrity": "sha1-qzZnP9NW+aCUhlnnszjV/q2zFpU=", - "dev": true - }, - "babel-types": { - "version": "https://registry.npmjs.org/babel-types/-/babel-types-6.24.1.tgz", - "integrity": "sha1-oTaHncFbNga9oNkMH8dDBML/CXU=", - "dev": true - }, - "babylon": { - "version": "https://registry.npmjs.org/babylon/-/babylon-6.17.2.tgz", - "integrity": "sha1-IB0l71+JLEG65JSIsI2w3Udun1w=", - "dev": true - }, - "balanced-match": { - "version": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", - "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", - "dev": true - }, - "bcrypt-pbkdf": { - "version": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", - "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", - "dev": true, - "optional": true - }, - "beeper": { - "version": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", - "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", - "dev": true - }, - "boom": { - "version": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", - "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", - "dev": true - }, - "brace-expansion": { - "version": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.7.tgz", - "integrity": "sha1-Pv/DxQ4ABTH7cg6v+A8K6O8jz1k=", - "dev": true - }, - "braces": { - "version": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "dev": true - }, - "browser-stdout": { - "version": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", - "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", - "dev": true - }, - "browserslist": { - "version": "https://registry.npmjs.org/browserslist/-/browserslist-2.1.4.tgz", - "integrity": "sha1-zFJq9KExK30uBWU+VtDIq3DA4FM=", - "dev": true - }, - "builtin-modules": { - "version": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", - "dev": true - }, - "caller-path": { - "version": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", - "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", - "dev": true - }, - "callsites": { - "version": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", - "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", - "dev": true - }, - "camelcase": { - "version": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", - "dev": true, - "optional": true - }, - "caniuse-lite": { - "version": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000680.tgz", - "integrity": "sha1-2U2BKURxYX6GUA8Kq5DxHSK8iTQ=", - "dev": true - }, - "caseless": { - "version": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", - "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", - "dev": true - }, - "center-align": { - "version": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", - "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", - "dev": true, - "optional": true - }, - "chai": { - "version": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz", - "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=", - "dev": true - }, - "chai-as-promised": { - "version": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-6.0.0.tgz", - "integrity": "sha1-GgKkM6byTa+sY7nJb6FoTbGqjaY=", - "dev": true - }, - "chalk": { - "version": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true - }, - "charenc": { - "version": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", - "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=", - "dev": true - }, - "check-error": { - "version": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", - "dev": true - }, - "circular-json": { - "version": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.1.tgz", - "integrity": "sha1-vos2rvzN6LPKeqLWr8B6NyQsDS0=", - "dev": true - }, - "cli-cursor": { - "version": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", - "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", - "dev": true - }, - "cli-width": { - "version": "https://registry.npmjs.org/cli-width/-/cli-width-2.1.0.tgz", - "integrity": "sha1-sjTKIJsp72b8UY2bmNWEewDt8Ao=", - "dev": true - }, - "cliui": { - "version": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "dev": true, - "optional": true, - "dependencies": { - "wordwrap": { - "version": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", - "dev": true, - "optional": true - } - } - }, - "clone": { - "version": "https://registry.npmjs.org/clone/-/clone-1.0.2.tgz", - "integrity": "sha1-Jgt6meux7f4kdTgXX3gyQ8sZ0Uk=", - "dev": true - }, - "clone-stats": { - "version": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", - "dev": true - }, - "co": { - "version": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true - }, - "code-point-at": { - "version": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true - }, - "colors": { - "version": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", - "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", - "dev": true - }, - "combined-stream": { - "version": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", - "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", - "dev": true - }, - "commander": { - "version": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", - "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", - "dev": true - }, - "concat-map": { - "version": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "concat-stream": { - "version": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", - "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", - "dev": true, - "dependencies": { - "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.11.tgz", - "integrity": "sha1-B5azH412iAB/8Lk6gIjTSqF8D3I=", - "dev": true - }, - "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.2.tgz", - "integrity": "sha1-sp4fThEl+pehA4K4pTNze3SR4Xk=", - "dev": true - } - } - }, - "content-disposition": { - "version": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", - "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=", - "dev": true - }, - "content-type": { - "version": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz", - "integrity": "sha1-t9ETrueo3Se9IRM8TcJSnfFyHu0=", - "dev": true - }, - "convert-source-map": { - "version": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.0.tgz", - "integrity": "sha1-ms1whRxtXf3ZPZKC5e35SgP/RrU=", - "dev": true - }, - "cookie": { - "version": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", - "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", - "dev": true - }, - "cookie-signature": { - "version": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", - "dev": true - }, - "core-js": { - "version": "https://registry.npmjs.org/core-js/-/core-js-2.4.1.tgz", - "integrity": "sha1-TekR5mew6ukSTjQlS1OupvxhjT4=", - "dev": true - }, - "core-util-is": { - "version": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "coveralls": { - "version": "https://registry.npmjs.org/coveralls/-/coveralls-2.13.1.tgz", - "integrity": "sha1-1wu5rMGDXsTwY/+drFQjwXsR8Xg=", - "dev": true, - "dependencies": { - "minimist": { - "version": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, - "crypt": { - "version": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", - "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=", - "dev": true - }, - "cryptiles": { - "version": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", - "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", - "dev": true - }, - "css": { - "version": "https://registry.npmjs.org/css/-/css-2.2.1.tgz", - "integrity": "sha1-c6TIHehdtmTU7mdPfUcIXjstVdw=", - "dev": true, - "dependencies": { - "source-map": { - "version": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", - "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", - "dev": true - } - } - }, - "d": { - "version": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", - "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", - "dev": true - }, - "dashdash": { - "version": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, - "dependencies": { - "assert-plus": { - "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } - } - }, - "dateformat": { - "version": "https://registry.npmjs.org/dateformat/-/dateformat-2.0.0.tgz", - "integrity": "sha1-J0Pjq7XD/CRi5SfcpEXgTp9N7hc=", - "dev": true - }, - "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", - "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", - "dev": true - }, - "debug-fabulous": { - "version": "https://registry.npmjs.org/debug-fabulous/-/debug-fabulous-0.1.0.tgz", - "integrity": "sha1-rQ6gel1RkyT7VYQqjzTuWcf4/2w=", - "dev": true, - "dependencies": { - "object-assign": { - "version": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz", - "integrity": "sha1-ejs9DpgGPUP0wD8uiubNUahog6A=", - "dev": true - } - } - }, - "debug-log": { - "version": "https://registry.npmjs.org/debug-log/-/debug-log-1.0.1.tgz", - "integrity": "sha1-IwdjLUwEOCuN+KMvcLiVBG1SdF8=", - "dev": true - }, - "decamelize": { - "version": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "deep-eql": { - "version": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", - "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", - "dev": true, - "dependencies": { - "type-detect": { - "version": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", - "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=", - "dev": true - } - } - }, - "deep-is": { - "version": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, - "defaults": { - "version": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", - "dev": true - }, - "define-properties": { - "version": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", - "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", - "dev": true - }, - "deglob": { - "version": "https://registry.npmjs.org/deglob/-/deglob-2.1.0.tgz", - "integrity": "sha1-TUSr4W7zLHebSXK9FBqAMlApoUo=", - "dev": true - }, - "del": { - "version": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", - "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", - "dev": true - }, - "delayed-stream": { - "version": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true - }, - "depd": { - "version": "https://registry.npmjs.org/depd/-/depd-1.1.0.tgz", - "integrity": "sha1-4b2Cxqq2ztlluXuIsX7T5SjKGMM=", - "dev": true - }, - "deprecated": { - "version": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", - "integrity": "sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=", - "dev": true - }, - "destroy": { - "version": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", - "dev": true - }, - "detect-file": { - "version": "https://registry.npmjs.org/detect-file/-/detect-file-0.1.0.tgz", - "integrity": "sha1-STXe39lIhkjgBrASlWbpOGcR6mM=", - "dev": true - }, - "detect-indent": { - "version": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", - "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", - "dev": true - }, - "detect-newline": { - "version": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", - "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", - "dev": true - }, - "diff": { - "version": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", - "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=", - "dev": true - }, - "dirty-chai": { - "version": "https://registry.npmjs.org/dirty-chai/-/dirty-chai-1.2.2.tgz", - "integrity": "sha1-eEleYZY19/5EIZqkyDeEm/GDFC4=", - "dev": true - }, - "doctrine": { - "version": "https://registry.npmjs.org/doctrine/-/doctrine-2.0.0.tgz", - "integrity": "sha1-xz2NKQnSIpHhoAejlYBNqLZl/mM=", - "dev": true, - "dependencies": { - "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - } - } - }, - "duplexer2": { - "version": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", - "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", - "dev": true - }, - "duplexify": { - "version": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.0.tgz", - "integrity": "sha1-GqdzAC4VeEV+nZ1KULDMquvL1gQ=", - "dev": true, - "dependencies": { - "end-of-stream": { - "version": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.0.0.tgz", - "integrity": "sha1-1FlucCc0qT5A6a+GQxnqvZn/Lw4=", - "dev": true - }, - "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "once": { - "version": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", - "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", - "dev": true - }, - "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.11.tgz", - "integrity": "sha1-B5azH412iAB/8Lk6gIjTSqF8D3I=", - "dev": true - }, - "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.2.tgz", - "integrity": "sha1-sp4fThEl+pehA4K4pTNze3SR4Xk=", - "dev": true - } - } - }, - "ecc-jsbn": { - "version": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", - "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", - "dev": true, - "optional": true - }, - "ee-first": { - "version": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", - "dev": true - }, - "electron-to-chromium": { - "version": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.13.tgz", - "integrity": "sha1-GzperObgh7teJXoQCwy/6Bsokfw=", - "dev": true - }, - "encodeurl": { - "version": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", - "integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA=", - "dev": true - }, - "encoding": { - "version": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", - "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=" - }, - "end-of-stream": { - "version": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", - "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", - "dev": true, - "dependencies": { - "once": { - "version": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", - "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", - "dev": true - } - } - }, - "error-ex": { - "version": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", - "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", - "dev": true - }, - "es-abstract": { - "version": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.7.0.tgz", - "integrity": "sha1-363ndOAb/Nl/lhgCmMRJyGI/uUw=", - "dev": true - }, - "es-to-primitive": { - "version": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz", - "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", - "dev": true - }, - "es5-ext": { - "version": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.23.tgz", - "integrity": "sha1-dXi1G+l0IHpUh4IbVlOMIk5Oezg=", - "dev": true - }, - "es6-iterator": { - "version": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.1.tgz", - "integrity": "sha1-jjGcnwRTv1ddN0lAplWSDlnKVRI=", - "dev": true - }, - "es6-map": { - "version": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", - "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", - "dev": true - }, - "es6-set": { - "version": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", - "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", - "dev": true - }, - "es6-symbol": { - "version": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", - "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", - "dev": true - }, - "es6-weak-map": { - "version": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", - "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", - "dev": true - }, - "escape-html": { - "version": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", - "dev": true - }, - "escape-string-regexp": { - "version": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "escodegen": { - "version": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", - "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", - "dev": true, - "dependencies": { - "source-map": { - "version": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", - "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", - "dev": true, - "optional": true - } - } - }, - "escope": { - "version": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", - "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", - "dev": true, - "dependencies": { - "estraverse": { - "version": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "dev": true - } - } - }, - "eslint": { - "version": "https://registry.npmjs.org/eslint/-/eslint-3.18.0.tgz", - "integrity": "sha1-ZH6YXErnFQLSCsYsEJ9m1RBMiks=", - "dev": true, - "dependencies": { - "estraverse": { - "version": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "dev": true - }, - "strip-bom": { - "version": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - }, - "user-home": { - "version": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz", - "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", - "dev": true - } - } - }, - "eslint-config-standard": { - "version": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-7.1.0.tgz", - "integrity": "sha1-R+dp6gc59bLVaTsaUBwhyWUPr88=", - "dev": true - }, - "eslint-config-standard-jsx": { - "version": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-3.3.0.tgz", - "integrity": "sha1-yrCAGhWjYL9j+suXqyL73YjYpeA=", - "dev": true - }, - "eslint-plugin-promise": { - "version": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.4.2.tgz", - "integrity": "sha1-G+J5Pq/i0YtbEjuBNsJp+AT+cSI=", - "dev": true - }, - "eslint-plugin-react": { - "version": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-6.9.0.tgz", - "integrity": "sha1-VMLpkGt2+dEBQgML3DTp1oQKC7I=", - "dev": true, - "dependencies": { - "doctrine": { - "version": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", - "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true - }, - "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - } - } - }, - "eslint-plugin-standard": { - "version": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-2.0.1.tgz", - "integrity": "sha1-NYlpn/nJF/LCX3apFmh/ZBw2n/M=", - "dev": true - }, - "espree": { - "version": "https://registry.npmjs.org/espree/-/espree-3.4.3.tgz", - "integrity": "sha1-KRC1zNSc6JPC//+qtP2LOjG4I3Q=", - "dev": true, - "dependencies": { - "acorn": { - "version": "https://registry.npmjs.org/acorn/-/acorn-5.0.3.tgz", - "integrity": "sha1-xGDfCEkUY/AozLguqzcwvwEIez0=", - "dev": true - } - } - }, - "esprima": { - "version": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", - "dev": true - }, - "esquery": { - "version": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz", - "integrity": "sha1-z7qLV9f7qT8XKYqKAGoEzaE9gPo=", - "dev": true, - "dependencies": { - "estraverse": { - "version": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "dev": true - } - } - }, - "esrecurse": { - "version": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.1.0.tgz", - "integrity": "sha1-RxO2U2rffyrE8yfVWed1a/9kgiA=", - "dev": true, - "dependencies": { - "estraverse": { - "version": "https://registry.npmjs.org/estraverse/-/estraverse-4.1.1.tgz", - "integrity": "sha1-9srKcokzqFDvkGYdDheYK6RxEaI=", - "dev": true - } - } - }, - "estraverse": { - "version": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", - "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", - "dev": true - }, - "esutils": { - "version": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", - "dev": true - }, - "etag": { - "version": "https://registry.npmjs.org/etag/-/etag-1.8.0.tgz", - "integrity": "sha1-b2Ma7zNtbEY2K1F2QETOIWvjwFE=", - "dev": true - }, - "event-emitter": { - "version": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", - "dev": true - }, - "eventemitter3": { - "version": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-2.0.3.tgz", - "integrity": "sha1-teEHm1n7XhuidxwKmTvgYKWMmbo=" - }, - "exit-hook": { - "version": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", - "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", - "dev": true - }, - "expand-brackets": { - "version": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", - "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "dev": true - }, - "expand-range": { - "version": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", - "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", - "dev": true - }, - "expand-tilde": { - "version": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-1.2.2.tgz", - "integrity": "sha1-C4HrqJflo9MdHD0QL48BRB5VlEk=", - "dev": true - }, - "express": { - "version": "https://registry.npmjs.org/express/-/express-4.15.3.tgz", - "integrity": "sha1-urZdDwOqgMNYQIly/HAPkWlEtmI=", - "dev": true, - "dependencies": { - "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.6.7.tgz", - "integrity": "sha1-krrR9tBbu2u6Isyoi80OyJTChh4=", - "dev": true - } - } - }, - "extend": { - "version": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", - "dev": true - }, - "extglob": { - "version": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true - }, - "extsprintf": { - "version": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz", - "integrity": "sha1-4QgOBljjALBilJkMxw4VAiNf1VA=", - "dev": true - }, - "fancy-log": { - "version": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.0.tgz", - "integrity": "sha1-Rb4X0Cu5kX1gzP/UmVyZnmyMmUg=", - "dev": true - }, - "fast-levenshtein": { - "version": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "figures": { - "version": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "dev": true - }, - "file-entry-cache": { - "version": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", - "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", - "dev": true - }, - "filename-regex": { - "version": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", - "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", - "dev": true - }, - "fill-range": { - "version": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", - "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", - "dev": true - }, - "finalhandler": { - "version": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.0.3.tgz", - "integrity": "sha1-70fneVDpmXgOhgIqVg4yF+DQzIk=", - "dev": true, - "dependencies": { - "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.6.7.tgz", - "integrity": "sha1-krrR9tBbu2u6Isyoi80OyJTChh4=", - "dev": true - } - } - }, - "find-index": { - "version": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", - "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=", - "dev": true - }, - "find-root": { - "version": "https://registry.npmjs.org/find-root/-/find-root-1.0.0.tgz", - "integrity": "sha1-li/yEaqyXGUg/u641ih/j26VgHo=", - "dev": true - }, - "find-up": { - "version": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true - }, - "findup-sync": { - "version": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.4.3.tgz", - "integrity": "sha1-QAQ5Kee8YK3wt/SCfExudaDeyhI=", - "dev": true - }, - "fined": { - "version": "https://registry.npmjs.org/fined/-/fined-1.0.2.tgz", - "integrity": "sha1-WyhCS3YNdZiWC374SA3/itNmDpc=", - "dev": true - }, - "first-chunk-stream": { - "version": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", - "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", - "dev": true - }, - "flagged-respawn": { - "version": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-0.3.2.tgz", - "integrity": "sha1-/xke3c1wiKZ1smEP/8l2vpuAdLU=", - "dev": true - }, - "flat-cache": { - "version": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.2.2.tgz", - "integrity": "sha1-+oZxTnLCHbiGAXYezy9VXRq8a5Y=", - "dev": true - }, - "for-in": { - "version": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, - "for-own": { - "version": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", - "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", - "dev": true - }, - "foreach": { - "version": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", - "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", - "dev": true - }, - "forever-agent": { - "version": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true - }, - "fork-stream": { - "version": "https://registry.npmjs.org/fork-stream/-/fork-stream-0.0.4.tgz", - "integrity": "sha1-24Sfznf2cIpfjzhq5TOgkHtUrnA=", - "dev": true - }, - "form-data": { - "version": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", - "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", - "dev": true - }, - "formatio": { - "version": "https://registry.npmjs.org/formatio/-/formatio-1.1.1.tgz", - "integrity": "sha1-XtPM1jZVEJc4NGXZlhmRAOhhYek=", - "dev": true - }, - "forwarded": { - "version": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.0.tgz", - "integrity": "sha1-Ge+YdMSuHCl7zweP3mOgm2aoQ2M=", - "dev": true - }, - "fresh": { - "version": "https://registry.npmjs.org/fresh/-/fresh-0.5.0.tgz", - "integrity": "sha1-9HTKXmqSRtb9jglTz6m5yAWvp44=", - "dev": true - }, - "fs-exists-sync": { - "version": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz", - "integrity": "sha1-mC1ok6+RjnLQjeyehnP/K1qNat0=", - "dev": true - }, - "fs-extra": { - "version": "https://registry.npmjs.org/fs-extra/-/fs-extra-2.1.2.tgz", - "integrity": "sha1-BGxwFjzvmq1GsOSn+kZ/si1x3jU=", - "dev": true - }, - "fs-promise": { - "version": "https://registry.npmjs.org/fs-promise/-/fs-promise-2.0.3.tgz", - "integrity": "sha1-9k5PhUvPaJqovdy6JokW2z20aFQ=", - "dev": true - }, - "fs.realpath": { - "version": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "function-bind": { - "version": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.0.tgz", - "integrity": "sha1-FhdnFMgBeY5Ojyz391KUZ7tKV3E=", - "dev": true - }, - "gaze": { - "version": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", - "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", - "dev": true - }, - "generate-function": { - "version": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", - "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", - "dev": true - }, - "generate-object-property": { - "version": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", - "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", - "dev": true - }, - "get-caller-file": { - "version": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", - "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", - "dev": true - }, - "get-stdin": { - "version": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz", - "integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g=", - "dev": true - }, - "getpass": { - "version": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, - "dependencies": { - "assert-plus": { - "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } - } - }, - "glob": { - "version": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", - "dev": true - }, - "glob-base": { - "version": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", - "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", - "dev": true - }, - "glob-parent": { - "version": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "dev": true - }, - "glob-stream": { - "version": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", - "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", - "dev": true, - "dependencies": { - "glob": { - "version": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", - "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", - "dev": true - }, - "minimatch": { - "version": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", - "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", - "dev": true - }, - "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true - }, - "through2": { - "version": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true - } - } - }, - "glob-watcher": { - "version": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", - "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", - "dev": true - }, - "glob2base": { - "version": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", - "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", - "dev": true - }, - "global-modules": { - "version": "https://registry.npmjs.org/global-modules/-/global-modules-0.2.3.tgz", - "integrity": "sha1-6lo77ULG1s6ZWk+KEmm12uIjgo0=", - "dev": true - }, - "global-prefix": { - "version": "https://registry.npmjs.org/global-prefix/-/global-prefix-0.1.5.tgz", - "integrity": "sha1-jTvGuNo8qBEqFg2NSW/wRiv+948=", - "dev": true - }, - "globals": { - "version": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha1-qjiWs+abSH8X4x7SFD1pqOMMLYo=", - "dev": true - }, - "globby": { - "version": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", - "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", - "dev": true - }, - "globule": { - "version": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", - "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", - "dev": true, - "dependencies": { - "glob": { - "version": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", - "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", - "dev": true - }, - "graceful-fs": { - "version": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", - "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", - "dev": true - }, - "inherits": { - "version": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", - "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", - "dev": true - }, - "lodash": { - "version": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", - "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=", - "dev": true - }, - "minimatch": { - "version": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", - "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", - "dev": true - } - } - }, - "glogg": { - "version": "https://registry.npmjs.org/glogg/-/glogg-1.0.0.tgz", - "integrity": "sha1-f+DxmfV6yQbPUS/urY+Q7kooT8U=", - "dev": true - }, - "graceful-fs": { - "version": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "graceful-readlink": { - "version": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", - "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", - "dev": true - }, - "growl": { - "version": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", - "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", - "dev": true - }, - "gulp": { - "version": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", - "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", - "dev": true, - "dependencies": { - "minimist": { - "version": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "semver": { - "version": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", - "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", - "dev": true - } - } - }, - "gulp-babel": { - "version": "https://registry.npmjs.org/gulp-babel/-/gulp-babel-6.1.2.tgz", - "integrity": "sha1-fAF25Lo/JExgWIoMSzIKRdGt784=", - "dev": true - }, - "gulp-coveralls": { - "version": "https://registry.npmjs.org/gulp-coveralls/-/gulp-coveralls-0.1.4.tgz", - "integrity": "sha1-L2IKyN9i0LhrS73mTaNnzEGhkMk=", - "dev": true, - "dependencies": { - "through2": { - "version": "https://registry.npmjs.org/through2/-/through2-1.1.1.tgz", - "integrity": "sha1-CEfLxESfNAVXTb3M2buEG4OsNUU=", - "dev": true - } - } - }, - "gulp-if": { - "version": "https://registry.npmjs.org/gulp-if/-/gulp-if-2.0.2.tgz", - "integrity": "sha1-pJe351cwBQQcqivIt92jyARE1ik=", - "dev": true - }, - "gulp-istanbul": { - "version": "https://registry.npmjs.org/gulp-istanbul/-/gulp-istanbul-1.1.2.tgz", - "integrity": "sha1-r2X6KL/bNXbaq5Xc+qcypqJ8Wgc=", - "dev": true - }, - "gulp-load-plugins": { - "version": "https://registry.npmjs.org/gulp-load-plugins/-/gulp-load-plugins-1.5.0.tgz", - "integrity": "sha1-TEGffldk2aDjMGG6uWGPgbc9QXE=", - "dev": true - }, - "gulp-match": { - "version": "https://registry.npmjs.org/gulp-match/-/gulp-match-1.0.3.tgz", - "integrity": "sha1-kcfA1/Kb7NZgbVfYCn+Hdqh6uo4=", - "dev": true - }, - "gulp-mocha": { - "version": "https://registry.npmjs.org/gulp-mocha/-/gulp-mocha-3.0.1.tgz", - "integrity": "sha1-qwyiw5QDcYF03drXUOY6Yb4X4EE=", - "dev": true - }, - "gulp-sourcemaps": { - "version": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-2.6.0.tgz", - "integrity": "sha1-fMzomaijv8oVk6M0jQ+/Qd0/UeU=", - "dev": true, - "dependencies": { - "vinyl": { - "version": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", - "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true - } - } - }, - "gulp-standard": { - "version": "https://registry.npmjs.org/gulp-standard/-/gulp-standard-9.0.0.tgz", - "integrity": "sha1-V1mdtXRJrreZIkAxW1Yx1RwHnMc=", - "dev": true - }, - "gulp-util": { - "version": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", - "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", - "dev": true, - "dependencies": { - "minimist": { - "version": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "object-assign": { - "version": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", - "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", - "dev": true - } - } - }, - "gulplog": { - "version": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", - "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "dev": true - }, - "handlebars": { - "version": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.10.tgz", - "integrity": "sha1-PTDHGLCaPZbyPqTMH0A8TTup/08=", - "dev": true, - "dependencies": { - "source-map": { - "version": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true - } - } - }, - "har-validator": { - "version": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", - "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", - "dev": true - }, - "has": { - "version": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", - "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", - "dev": true - }, - "has-ansi": { - "version": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true - }, - "has-color": { - "version": "https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz", - "integrity": "sha1-ZxRKUmDDT8PMpnfQQdr1L+e3iy8=", - "dev": true - }, - "has-flag": { - "version": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "has-gulplog": { - "version": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", - "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", - "dev": true - }, - "hawk": { - "version": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", - "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", - "dev": true - }, - "hoek": { - "version": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", - "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", - "dev": true - }, - "home-or-tmp": { - "version": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", - "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", - "dev": true - }, - "homedir-polyfill": { - "version": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", - "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", - "dev": true - }, - "hosted-git-info": { - "version": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.4.2.tgz", - "integrity": "sha1-AHa59GonBQbduq6lZJaJdGBhKmc=", - "dev": true - }, - "http-errors": { - "version": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.1.tgz", - "integrity": "sha1-X4uO2YrKVFZWv1cplzh/kEpyIlc=", - "dev": true - }, - "http-signature": { - "version": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", - "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", - "dev": true - }, - "iab-vast-model": { - "version": "https://registry.npmjs.org/iab-vast-model/-/iab-vast-model-0.4.0.tgz", - "integrity": "sha1-P5GOVzyBxtEHprwyI0JZHY4kMGg=" - }, - "iab-vast-parser": { - "version": "https://registry.npmjs.org/iab-vast-parser/-/iab-vast-parser-0.4.1.tgz", - "integrity": "sha1-QySUGbljP4aryx2w3/mo8a6Dnv8=" - }, - "iconv-lite": { - "version": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.17.tgz", - "integrity": "sha1-T9qjs4rLwsAxsEXQ7c3+HsqxjI0=" - }, - "ignore": { - "version": "https://registry.npmjs.org/ignore/-/ignore-3.3.3.tgz", - "integrity": "sha1-QyNS5XrM2HqzEQ6C0/6g5HgSFW0=", - "dev": true - }, - "imurmurhash": { - "version": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "in-publish": { - "version": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.0.tgz", - "integrity": "sha1-4g/146KvwmkDILbcVSaCqcf631E=", - "dev": true - }, - "inflight": { - "version": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true - }, - "inherits": { - "version": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "ini": { - "version": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", - "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=", - "dev": true - }, - "inquirer": { - "version": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", - "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", - "dev": true - }, - "interpret": { - "version": "https://registry.npmjs.org/interpret/-/interpret-1.0.3.tgz", - "integrity": "sha1-y8NcYu7uc/Gat7EKgBURQBr8D5A=", - "dev": true - }, - "invariant": { - "version": "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz", - "integrity": "sha1-nh9WrArNtr8wMwbzOL47IErmA2A=", - "dev": true - }, - "invert-kv": { - "version": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true - }, - "ipaddr.js": { - "version": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.3.0.tgz", - "integrity": "sha1-HgOlL9rYOou7KyXL9JmLTP/NPew=", - "dev": true - }, - "irregular-plurals": { - "version": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-1.2.0.tgz", - "integrity": "sha1-OPKZg0uowAwwvpxVThNyaXUv86w=", - "dev": true - }, - "is-absolute": { - "version": "https://registry.npmjs.org/is-absolute/-/is-absolute-0.2.6.tgz", - "integrity": "sha1-IN5p89uULvLYe5wto28XIjWxtes=", - "dev": true - }, - "is-arrayish": { - "version": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-buffer": { - "version": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", - "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=", - "dev": true - }, - "is-builtin-module": { - "version": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", - "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", - "dev": true - }, - "is-callable": { - "version": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz", - "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=", - "dev": true - }, - "is-date-object": { - "version": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", - "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", - "dev": true - }, - "is-dotfile": { - "version": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", - "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", - "dev": true - }, - "is-equal-shallow": { - "version": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", - "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", - "dev": true - }, - "is-extendable": { - "version": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "is-extglob": { - "version": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-finite": { - "version": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", - "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true - }, - "is-glob": { - "version": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true - }, - "is-my-json-valid": { - "version": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.0.tgz", - "integrity": "sha1-8Hndm/2uZe4gOKrorLyGqxCeNpM=", - "dev": true - }, - "is-number": { - "version": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", - "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", - "dev": true - }, - "is-path-cwd": { - "version": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", - "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", - "dev": true - }, - "is-path-in-cwd": { - "version": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", - "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", - "dev": true - }, - "is-path-inside": { - "version": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz", - "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=", - "dev": true - }, - "is-posix-bracket": { - "version": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", - "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", - "dev": true - }, - "is-primitive": { - "version": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", - "dev": true - }, - "is-property": { - "version": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", - "dev": true - }, - "is-regex": { - "version": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", - "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", - "dev": true - }, - "is-relative": { - "version": "https://registry.npmjs.org/is-relative/-/is-relative-0.2.1.tgz", - "integrity": "sha1-0n9MfVFtF1+2ENuEu+7yPDvJeqU=", - "dev": true - }, - "is-resolvable": { - "version": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.0.tgz", - "integrity": "sha1-jfV8YeouPFAUCNEA+wE8+NbgzGI=", - "dev": true - }, - "is-stream": { - "version": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" - }, - "is-symbol": { - "version": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", - "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=", - "dev": true - }, - "is-typedarray": { - "version": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, - "is-unc-path": { - "version": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-0.1.2.tgz", - "integrity": "sha1-arBTpyVzwQJQ/0FqOBTDUXivObk=", - "dev": true - }, - "is-utf8": { - "version": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "is-windows": { - "version": "https://registry.npmjs.org/is-windows/-/is-windows-0.2.0.tgz", - "integrity": "sha1-3hqm1j6indJIc3tp8f+LgALSEIw=", - "dev": true - }, - "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "isexe": { - "version": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "isobject": { - "version": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "dependencies": { - "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - } - } - }, - "isomorphic-fetch": { - "version": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", - "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=" - }, - "isparta": { - "version": "https://registry.npmjs.org/isparta/-/isparta-4.0.0.tgz", - "integrity": "sha1-HekZlvSAsi3LGsqFECVbrhV0RG4=", - "dev": true - }, - "isstream": { - "version": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true - }, - "istanbul": { - "version": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", - "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", - "dev": true, - "dependencies": { - "glob": { - "version": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true - }, - "resolve": { - "version": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", - "dev": true - }, - "supports-color": { - "version": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true - } - } - }, - "istanbul-threshold-checker": { - "version": "https://registry.npmjs.org/istanbul-threshold-checker/-/istanbul-threshold-checker-0.2.1.tgz", - "integrity": "sha1-xdyU6PLMXNP/0zVFL4S1U8QkgzE=", - "dev": true - }, - "js-tokens": { - "version": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.1.tgz", - "integrity": "sha1-COnxMkhKLEWjCQfp3E1VZ7fxFNc=", - "dev": true - }, - "js-yaml": { - "version": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.6.1.tgz", - "integrity": "sha1-bl/mfYsgXOTSL60Ft3geja3MSzA=", - "dev": true - }, - "jsbn": { - "version": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true, - "optional": true - }, - "jsesc": { - "version": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true - }, - "json-schema": { - "version": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true - }, - "json-stable-stringify": { - "version": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "dev": true - }, - "json-stringify-safe": { - "version": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true - }, - "json3": { - "version": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", - "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", - "dev": true - }, - "json5": { - "version": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", - "dev": true - }, - "jsonfile": { - "version": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", - "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", - "dev": true - }, - "jsonify": { - "version": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true - }, - "jsonpointer": { - "version": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", - "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", - "dev": true - }, - "jsprim": { - "version": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.0.tgz", - "integrity": "sha1-o7h+QCmNjDgFUtjMdiigu5WiKRg=", - "dev": true, - "dependencies": { - "assert-plus": { - "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } - } - }, - "jsx-ast-utils": { - "version": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-1.4.1.tgz", - "integrity": "sha1-OGchPo3Xm/Ho8jAMDPwe+xgsDfE=", - "dev": true - }, - "kind-of": { - "version": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true - }, - "lazy-cache": { - "version": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", - "dev": true, - "optional": true - }, - "lcid": { - "version": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true - }, - "lcov-parse": { - "version": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-0.0.10.tgz", - "integrity": "sha1-GwuP+ayceIklBYK3C3ExXZ2m2aM=", - "dev": true - }, - "levn": { - "version": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true - }, - "liftoff": { - "version": "https://registry.npmjs.org/liftoff/-/liftoff-2.3.0.tgz", - "integrity": "sha1-qY8v9nGD2Lp8+soQVIvX/wVQs4U=", - "dev": true - }, - "load-json-file": { - "version": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", - "dev": true, - "dependencies": { - "strip-bom": { - "version": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - } - } - }, - "locate-path": { - "version": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true - }, - "lodash": { - "version": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", - "dev": true - }, - "lodash._baseassign": { - "version": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", - "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", - "dev": true - }, - "lodash._basecopy": { - "version": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", - "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", - "dev": true - }, - "lodash._basecreate": { - "version": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", - "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=", - "dev": true - }, - "lodash._basetostring": { - "version": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", - "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=", - "dev": true - }, - "lodash._basevalues": { - "version": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", - "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=", - "dev": true - }, - "lodash._getnative": { - "version": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", - "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", - "dev": true - }, - "lodash._isiterateecall": { - "version": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", - "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", - "dev": true - }, - "lodash._reescape": { - "version": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", - "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=", - "dev": true - }, - "lodash._reevaluate": { - "version": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", - "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", - "dev": true - }, - "lodash._reinterpolate": { - "version": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", - "dev": true - }, - "lodash._root": { - "version": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", - "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", - "dev": true - }, - "lodash.assignwith": { - "version": "https://registry.npmjs.org/lodash.assignwith/-/lodash.assignwith-4.2.0.tgz", - "integrity": "sha1-EnqX8CrcQXUalU0ksN4X4QDgOOs=", - "dev": true - }, - "lodash.create": { - "version": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", - "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", - "dev": true - }, - "lodash.escape": { - "version": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", - "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", - "dev": true - }, - "lodash.isarguments": { - "version": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", - "dev": true - }, - "lodash.isarray": { - "version": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", - "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", - "dev": true - }, - "lodash.isempty": { - "version": "https://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz", - "integrity": "sha1-b4bL7di+TsmHvpqvM8loTbGzHn4=", - "dev": true - }, - "lodash.isplainobject": { - "version": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", - "dev": true - }, - "lodash.isstring": { - "version": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=", - "dev": true - }, - "lodash.keys": { - "version": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", - "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", - "dev": true - }, - "lodash.mapvalues": { - "version": "https://registry.npmjs.org/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz", - "integrity": "sha1-G6+lAF3p3W9PJmaMMMo3IwzJaJw=", - "dev": true - }, - "lodash.pick": { - "version": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", - "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=", - "dev": true - }, - "lodash.restparam": { - "version": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", - "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", - "dev": true - }, - "lodash.template": { - "version": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", - "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", - "dev": true - }, - "lodash.templatesettings": { - "version": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", - "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", - "dev": true - }, - "log-driver": { - "version": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.5.tgz", - "integrity": "sha1-euTsJXMC/XkNVXyxDJcQDYV7AFY=", - "dev": true - }, - "log-symbols": { - "version": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", - "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", - "dev": true - }, - "lolex": { - "version": "https://registry.npmjs.org/lolex/-/lolex-1.3.2.tgz", - "integrity": "sha1-fD2mL/yzDw9agKJWbKJORdigHzE=", - "dev": true - }, - "longest": { - "version": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", - "dev": true - }, - "loose-envify": { - "version": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", - "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", - "dev": true - }, - "lru-cache": { - "version": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", - "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", - "dev": true - }, - "map-cache": { - "version": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true - }, - "md5": { - "version": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz", - "integrity": "sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=", - "dev": true - }, - "media-typer": { - "version": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", - "dev": true - }, - "merge-descriptors": { - "version": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", - "dev": true - }, - "merge-stream": { - "version": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", - "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", - "dev": true, - "dependencies": { - "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.11.tgz", - "integrity": "sha1-B5azH412iAB/8Lk6gIjTSqF8D3I=", - "dev": true - }, - "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.2.tgz", - "integrity": "sha1-sp4fThEl+pehA4K4pTNze3SR4Xk=", - "dev": true - } - } - }, - "methods": { - "version": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", - "dev": true - }, - "micromatch": { - "version": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true - }, - "mime": { - "version": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", - "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM=", - "dev": true - }, - "mime-db": { - "version": "https://registry.npmjs.org/mime-db/-/mime-db-1.27.0.tgz", - "integrity": "sha1-gg9XIpa70g7CXtVeW13oaeVDbrE=", - "dev": true - }, - "mime-types": { - "version": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.15.tgz", - "integrity": "sha1-pOv1BkCUVpI3uM9wBGd20J/JKu0=", - "dev": true - }, - "minimatch": { - "version": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", - "dev": true - }, - "minimist": { - "version": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - }, - "mkdirp": { - "version": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true - }, - "mocha": { - "version": "https://registry.npmjs.org/mocha/-/mocha-3.4.2.tgz", - "integrity": "sha1-0O9NMyEm2/GNDWQMmzgt1IvpdZQ=", - "dev": true, - "dependencies": { - "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.6.0.tgz", - "integrity": "sha1-vFlryr52F/Edn6FTYe3tVgi4SZs=", - "dev": true - }, - "glob": { - "version": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", - "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", - "dev": true - }, - "ms": { - "version": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", - "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", - "dev": true - }, - "supports-color": { - "version": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", - "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", - "dev": true - } - } - }, - "mocha-junit-reporter": { - "version": "https://registry.npmjs.org/mocha-junit-reporter/-/mocha-junit-reporter-1.13.0.tgz", - "integrity": "sha1-Aw24xTCyRGZyU7A4YdTNM29+Vsg=", - "dev": true - }, - "ms": { - "version": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "multipipe": { - "version": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", - "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", - "dev": true - }, - "mute-stream": { - "version": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", - "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=", - "dev": true - }, - "mz": { - "version": "https://registry.npmjs.org/mz/-/mz-2.6.0.tgz", - "integrity": "sha1-yLhSHZWN8KTydoAl22nHGe5O8c4=", - "dev": true - }, - "natives": { - "version": "https://registry.npmjs.org/natives/-/natives-1.1.0.tgz", - "integrity": "sha1-6f+EFBimsux6SV6TmYT3jxY+bjE=", - "dev": true - }, - "natural-compare": { - "version": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "negotiator": { - "version": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", - "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", - "dev": true - }, - "node-fetch": { - "version": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.1.tgz", - "integrity": "sha1-iZyz0KPJL5UsR/G4dvTIrqvUANU=" - }, - "nomnomnomnom": { - "version": "https://registry.npmjs.org/nomnomnomnom/-/nomnomnomnom-2.0.1.tgz", - "integrity": "sha1-siOfAxyNBNpn4yg24eMZnhL3qOI=", - "dev": true, - "dependencies": { - "ansi-styles": { - "version": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.0.0.tgz", - "integrity": "sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg=", - "dev": true - }, - "chalk": { - "version": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", - "integrity": "sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=", - "dev": true - }, - "strip-ansi": { - "version": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz", - "integrity": "sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE=", - "dev": true - } - } - }, - "nopt": { - "version": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true - }, - "normalize-package-data": { - "version": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.3.8.tgz", - "integrity": "sha1-2Bntoqne29H/pWPqQHHZNngilbs=", - "dev": true - }, - "normalize-path": { - "version": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true - }, - "number-is-nan": { - "version": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, - "oauth-sign": { - "version": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", - "dev": true - }, - "object-assign": { - "version": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, - "object-keys": { - "version": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", - "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=", - "dev": true - }, - "object.omit": { - "version": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", - "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", - "dev": true - }, - "on-finished": { - "version": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dev": true - }, - "once": { - "version": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true - }, - "onetime": { - "version": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", - "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", - "dev": true - }, - "optimist": { - "version": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "dev": true, - "dependencies": { - "wordwrap": { - "version": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", - "dev": true - } - } - }, - "optionator": { - "version": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", - "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "dev": true - }, - "orchestrator": { - "version": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", - "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", - "dev": true - }, - "ordered-read-streams": { - "version": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", - "integrity": "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=", - "dev": true - }, - "os-homedir": { - "version": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true - }, - "os-locale": { - "version": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true - }, - "os-tmpdir": { - "version": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true - }, - "p-limit": { - "version": "https://registry.npmjs.org/p-limit/-/p-limit-1.1.0.tgz", - "integrity": "sha1-sH/y2aXYi+yAYDWJWiurZqJ5iLw=", - "dev": true - }, - "p-locate": { - "version": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true - }, - "parse-filepath": { - "version": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.1.tgz", - "integrity": "sha1-FZ1hVdQ5BNFsEO9piRHaHpGWm3M=", - "dev": true - }, - "parse-glob": { - "version": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", - "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", - "dev": true - }, - "parse-json": { - "version": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true - }, - "parse-passwd": { - "version": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true - }, - "parseurl": { - "version": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz", - "integrity": "sha1-yKuMkiO6NIiKpkopeyiFO+wY2lY=", - "dev": true - }, - "path": { - "version": "https://registry.npmjs.org/path/-/path-0.12.7.tgz", - "integrity": "sha1-1NwqUGxM4hl+tIHr/NWzbAFAsQ8=", - "dev": true - }, - "path-exists": { - "version": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "path-is-absolute": { - "version": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-is-inside": { - "version": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, - "path-parse": { - "version": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", - "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", - "dev": true - }, - "path-root": { - "version": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "dev": true - }, - "path-root-regex": { - "version": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", - "dev": true - }, - "path-to-regexp": { - "version": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", - "dev": true - }, - "path-type": { - "version": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true - }, - "pify": { - "version": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "pinkie": { - "version": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true - }, - "pinkie-promise": { - "version": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true - }, - "pkg-conf": { - "version": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-2.0.0.tgz", - "integrity": "sha1-BxyHZQQDvM+5xif1h1G/5HwGcnk=", - "dev": true - }, - "pkg-config": { - "version": "https://registry.npmjs.org/pkg-config/-/pkg-config-1.1.1.tgz", - "integrity": "sha1-VX7yLXPaPIg3EHdmxS6tq94pj+Q=", - "dev": true - }, - "plur": { - "version": "https://registry.npmjs.org/plur/-/plur-2.1.2.tgz", - "integrity": "sha1-dIJFLBoPUI4+NE6uwxLJHCncZVo=", - "dev": true - }, - "pluralize": { - "version": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz", - "integrity": "sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=", - "dev": true - }, - "prelude-ls": { - "version": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true - }, - "preserve": { - "version": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", - "dev": true - }, - "pretty-hrtime": { - "version": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", - "dev": true - }, - "private": { - "version": "https://registry.npmjs.org/private/-/private-0.1.7.tgz", - "integrity": "sha1-aM5eih7woju1cMwoU3tTMqumPvE=", - "dev": true - }, - "process": { - "version": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", - "dev": true - }, - "process-nextick-args": { - "version": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", - "dev": true - }, - "progress": { - "version": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", - "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", - "dev": true - }, - "proxy-addr": { - "version": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.4.tgz", - "integrity": "sha1-J+VF9pYKRKYn2bREZ+NcG2tM4vM=", - "dev": true - }, - "punycode": { - "version": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - }, - "qs": { - "version": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", - "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", - "dev": true - }, - "randomatic": { - "version": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.6.tgz", - "integrity": "sha1-EQ3Kv/OX6dz/fAeJzMCkmt8exbs=", - "dev": true - }, - "range-parser": { - "version": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", - "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", - "dev": true - }, - "read-pkg": { - "version": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "dependencies": { - "load-json-file": { - "version": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true - }, - "strip-bom": { - "version": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true - } - } - }, - "read-pkg-up": { - "version": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "dependencies": { - "find-up": { - "version": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true - }, - "path-exists": { - "version": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true - } - } - }, - "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true - }, - "readline2": { - "version": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz", - "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", - "dev": true - }, - "rechoir": { - "version": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true - }, - "regenerate": { - "version": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.2.tgz", - "integrity": "sha1-0ZQcZ7rUN+G+dkM63Vs4X5WxkmA=", - "dev": true - }, - "regenerator-runtime": { - "version": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", - "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=", - "dev": true - }, - "regenerator-transform": { - "version": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.9.11.tgz", - "integrity": "sha1-On0GdSDLe3F2dp61/4aGkb7+EoM=", - "dev": true - }, - "regex-cache": { - "version": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.3.tgz", - "integrity": "sha1-mxpsNdTQ3871cRrmUejp09cRQUU=", - "dev": true - }, - "regexpu-core": { - "version": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", - "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", - "dev": true - }, - "regjsgen": { - "version": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", - "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", - "dev": true - }, - "regjsparser": { - "version": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", - "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", - "dev": true - }, - "remove-trailing-separator": { - "version": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.0.2.tgz", - "integrity": "sha1-abBi2XhyetFNxrVrpKt3L9jXBRE=", - "dev": true - }, - "repeat-element": { - "version": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", - "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", - "dev": true - }, - "repeat-string": { - "version": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true - }, - "repeating": { - "version": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true - }, - "replace-ext": { - "version": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", - "dev": true - }, - "req-cwd": { - "version": "https://registry.npmjs.org/req-cwd/-/req-cwd-1.0.1.tgz", - "integrity": "sha1-DXOurpJm5penj3l2AZZ352rPD/8=", - "dev": true - }, - "req-from": { - "version": "https://registry.npmjs.org/req-from/-/req-from-1.0.1.tgz", - "integrity": "sha1-v4HaUUeUfTLRO5R9wSpYrUWHNQ4=", - "dev": true - }, - "request": { - "version": "https://registry.npmjs.org/request/-/request-2.79.0.tgz", - "integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=", - "dev": true, - "dependencies": { - "qs": { - "version": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz", - "integrity": "sha1-51vV9uJoEioqDgvaYwslUMFmUCw=", - "dev": true - } - } - }, - "require-directory": { - "version": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-main-filename": { - "version": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true - }, - "require-uncached": { - "version": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", - "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", - "dev": true, - "dependencies": { - "resolve-from": { - "version": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", - "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", - "dev": true - } - } - }, - "resolve": { - "version": "https://registry.npmjs.org/resolve/-/resolve-1.3.3.tgz", - "integrity": "sha1-ZVkHw0aahoDcLeOidaj91paR8OU=", - "dev": true - }, - "resolve-dir": { - "version": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-0.1.1.tgz", - "integrity": "sha1-shklmlYC+sXFxJatiUpujMQwJh4=", - "dev": true - }, - "resolve-from": { - "version": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", - "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=", - "dev": true - }, - "resolve-url": { - "version": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true - }, - "restore-cursor": { - "version": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", - "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", - "dev": true - }, - "right-align": { - "version": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", - "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", - "dev": true, - "optional": true - }, - "rimraf": { - "version": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", - "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=", - "dev": true - }, - "run-async": { - "version": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", - "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", - "dev": true - }, - "run-parallel": { - "version": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.6.tgz", - "integrity": "sha1-KQA8miFj4B4tLfyQV18sbB1hoDk=", - "dev": true - }, - "run-sequence": { - "version": "https://registry.npmjs.org/run-sequence/-/run-sequence-1.2.2.tgz", - "integrity": "sha1-UJWgvr6YczsBQL0I3YDsAw3azes=", - "dev": true - }, - "rx-lite": { - "version": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", - "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=", - "dev": true - }, - "safe-buffer": { - "version": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.0.1.tgz", - "integrity": "sha1-0mPKVGls2KMGtcplUekt5XkY++c=", - "dev": true - }, - "samsam": { - "version": "https://registry.npmjs.org/samsam/-/samsam-1.1.2.tgz", - "integrity": "sha1-vsEf3IOp/aBjQBIQ5AF2wwJNFWc=", - "dev": true - }, - "semver": { - "version": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", - "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", - "dev": true - }, - "send": { - "version": "https://registry.npmjs.org/send/-/send-0.15.3.tgz", - "integrity": "sha1-UBP5+ZAj31DRvZiSwZ4979HVMwk=", - "dev": true, - "dependencies": { - "debug": { - "version": "https://registry.npmjs.org/debug/-/debug-2.6.7.tgz", - "integrity": "sha1-krrR9tBbu2u6Isyoi80OyJTChh4=", - "dev": true - } - } - }, - "sequencify": { - "version": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", - "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=", - "dev": true - }, - "serve-static": { - "version": "https://registry.npmjs.org/serve-static/-/serve-static-1.12.3.tgz", - "integrity": "sha1-n0uhni8wMMVH+K+ZEHg47DjVseI=", - "dev": true - }, - "set-blocking": { - "version": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "setprototypeof": { - "version": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", - "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=", - "dev": true - }, - "shelljs": { - "version": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.8.tgz", - "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=", - "dev": true - }, - "sigmund": { - "version": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", - "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", - "dev": true - }, - "sinon": { - "version": "https://registry.npmjs.org/sinon/-/sinon-1.17.7.tgz", - "integrity": "sha1-RUKk9JugxFwF6y6d2dID4rjv4L8=", - "dev": true - }, - "sinon-chai": { - "version": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-2.10.0.tgz", - "integrity": "sha1-arMAi7jK6ZKedE12ZXS0zzXzS1s=", - "dev": true - }, - "slash": { - "version": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", - "dev": true - }, - "slice-ansi": { - "version": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", - "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", - "dev": true - }, - "sntp": { - "version": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", - "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", - "dev": true - }, - "source-map": { - "version": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", - "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=", - "dev": true - }, - "source-map-resolve": { - "version": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.3.1.tgz", - "integrity": "sha1-YQ9hIqRFuN1RU1oqcbeD38Ekh2E=", - "dev": true - }, - "source-map-support": { - "version": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.15.tgz", - "integrity": "sha1-AyAt9lwG0r2MfsI2KhkwVv7407E=", - "dev": true - }, - "source-map-url": { - "version": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.3.0.tgz", - "integrity": "sha1-fsrxO1e80J2opAxdJp2zN5nUqvk=", - "dev": true - }, - "sparkles": { - "version": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz", - "integrity": "sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM=", - "dev": true - }, - "spdx-correct": { - "version": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", - "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", - "dev": true - }, - "spdx-expression-parse": { - "version": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", - "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=", - "dev": true - }, - "spdx-license-ids": { - "version": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", - "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", - "dev": true - }, - "sprintf-js": { - "version": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "sshpk": { - "version": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", - "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", - "dev": true, - "dependencies": { - "assert-plus": { - "version": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } - } - }, - "standard": { - "version": "https://registry.npmjs.org/standard/-/standard-9.0.2.tgz", - "integrity": "sha1-m9O5RnSS4hKxkU14VTlD/5tI/Zk=", - "dev": true - }, - "standard-engine": { - "version": "https://registry.npmjs.org/standard-engine/-/standard-engine-5.4.0.tgz", - "integrity": "sha1-4OhpWeoHhkJdM4PkDBv3DS+YVXk=", - "dev": true, - "dependencies": { - "minimist": { - "version": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, - "statuses": { - "version": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", - "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", - "dev": true - }, - "stream-consume": { - "version": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.0.tgz", - "integrity": "sha1-pB6tGm1ggc63n2WwYZAbbY89HQ8=", - "dev": true - }, - "stream-shift": { - "version": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", - "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", - "dev": true - }, - "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "string-width": { - "version": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true - }, - "stringstream": { - "version": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", - "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", - "dev": true - }, - "strip-ansi": { - "version": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true - }, - "strip-bom": { - "version": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", - "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", - "dev": true - }, - "strip-bom-string": { - "version": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", - "integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=", - "dev": true - }, - "strip-json-comments": { - "version": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true - }, - "supports-color": { - "version": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - }, - "table": { - "version": "https://registry.npmjs.org/table/-/table-3.8.3.tgz", - "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", - "dev": true, - "dependencies": { - "is-fullwidth-code-point": { - "version": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "string-width": { - "version": "https://registry.npmjs.org/string-width/-/string-width-2.0.0.tgz", - "integrity": "sha1-Y1xUNsxypuDDh87KJ41OLuxSaH4=", - "dev": true - } - } - }, - "temp": { - "version": "https://registry.npmjs.org/temp/-/temp-0.8.3.tgz", - "integrity": "sha1-4Ma8TSa5AxJEEOT+2BEDAU38H1k=", - "dev": true, - "dependencies": { - "rimraf": { - "version": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", - "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=", - "dev": true - } - } - }, - "ternary-stream": { - "version": "https://registry.npmjs.org/ternary-stream/-/ternary-stream-2.0.1.tgz", - "integrity": "sha1-Bk5Im0tb9gumpre8fy9cJ07Pgmk=", - "dev": true - }, - "text-table": { - "version": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "thenify": { - "version": "https://registry.npmjs.org/thenify/-/thenify-3.3.0.tgz", - "integrity": "sha1-5p44obq+lpsBCCB5eLn2K4hgSDk=", - "dev": true - }, - "thenify-all": { - "version": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=", - "dev": true - }, - "through": { - "version": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "through2": { - "version": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", - "dev": true, - "dependencies": { - "isarray": { - "version": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.11.tgz", - "integrity": "sha1-B5azH412iAB/8Lk6gIjTSqF8D3I=", - "dev": true - }, - "string_decoder": { - "version": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.2.tgz", - "integrity": "sha1-sp4fThEl+pehA4K4pTNze3SR4Xk=", - "dev": true - } - } - }, - "tildify": { - "version": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", - "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", - "dev": true - }, - "time-stamp": { - "version": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", - "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", - "dev": true - }, - "to-fast-properties": { - "version": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", - "dev": true - }, - "tough-cookie": { - "version": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.2.tgz", - "integrity": "sha1-8IH3bkyFcg5sN6X6ztc3FQ2EByo=", - "dev": true - }, - "trim-right": { - "version": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", - "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", - "dev": true - }, - "tryit": { - "version": "https://registry.npmjs.org/tryit/-/tryit-1.0.3.tgz", - "integrity": "sha1-OTvnMKlEb9Hq1tpZoBQwjzbCics=", - "dev": true - }, - "tunnel-agent": { - "version": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", - "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", - "dev": true - }, - "tweetnacl": { - "version": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true, - "optional": true - }, - "type-check": { - "version": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true - }, - "type-detect": { - "version": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz", - "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=", - "dev": true - }, - "type-is": { - "version": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz", - "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=", - "dev": true - }, - "typedarray": { - "version": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "uglify-js": { - "version": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.28.tgz", - "integrity": "sha1-4zUDLfm7INy5GPFkWJ1a9H84g0o=", - "dev": true, - "optional": true, - "dependencies": { - "yargs": { - "version": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true, - "optional": true - } - } - }, - "uglify-to-browserify": { - "version": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", - "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", - "dev": true, - "optional": true - }, - "unc-path-regex": { - "version": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", - "dev": true - }, - "underscore": { - "version": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", - "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=", - "dev": true - }, - "uniq": { - "version": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", - "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", - "dev": true - }, - "unique-stream": { - "version": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", - "integrity": "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=", - "dev": true - }, - "unpipe": { - "version": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", - "dev": true - }, - "urix": { - "version": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true - }, - "user-home": { - "version": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", - "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", - "dev": true - }, - "util": { - "version": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", - "dev": true, - "dependencies": { - "inherits": { - "version": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", - "dev": true - } - } - }, - "util-deprecate": { - "version": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "utils-merge": { - "version": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", - "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=", - "dev": true - }, - "uuid": { - "version": "https://registry.npmjs.org/uuid/-/uuid-3.0.1.tgz", - "integrity": "sha1-ZUS7ot/ajBzxfmKaOjBeK7H+5sE=", - "dev": true - }, - "v8flags": { - "version": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", - "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", - "dev": true - }, - "validate-npm-package-license": { - "version": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", - "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", - "dev": true - }, - "vary": { - "version": "https://registry.npmjs.org/vary/-/vary-1.1.1.tgz", - "integrity": "sha1-Z1Neu2lMHVIldFeYRmUyP1h+jTc=", - "dev": true - }, - "verror": { - "version": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz", - "integrity": "sha1-z/XfEpRtKX0rqu+qJoniW+AcAFw=", - "dev": true - }, - "vinyl": { - "version": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", - "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", - "dev": true - }, - "vinyl-fs": { - "version": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", - "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", - "dev": true, - "dependencies": { - "clone": { - "version": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", - "dev": true - }, - "graceful-fs": { - "version": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", - "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", - "dev": true - }, - "readable-stream": { - "version": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true - }, - "through2": { - "version": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true - }, - "vinyl": { - "version": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "dev": true - } - } - }, - "vinyl-sourcemaps-apply": { - "version": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", - "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", - "dev": true - }, - "whatwg-fetch": { - "version": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz", - "integrity": "sha1-nITsLc9oGH/wC8ZOEnS0QhduHIQ=" - }, - "which": { - "version": "https://registry.npmjs.org/which/-/which-1.2.14.tgz", - "integrity": "sha1-mofEN48D6CfOyvGs31bHNsAcFOU=", - "dev": true - }, - "which-module": { - "version": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", - "dev": true - }, - "window-size": { - "version": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", - "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", - "dev": true, - "optional": true - }, - "wordwrap": { - "version": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true - }, - "wrap-ansi": { - "version": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true - }, - "wrappy": { - "version": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "write": { - "version": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", - "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", - "dev": true - }, - "xml": { - "version": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", - "integrity": "sha1-eLpyAgApxbyHuKgaPPzXS0ovweU=", - "dev": true - }, - "xmldom": { - "version": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz", - "integrity": "sha1-1QH5ezvbQDr4757MIFcxh6rawOk=", - "optional": true - }, - "xtend": { - "version": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true - }, - "y18n": { - "version": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "dev": true - }, - "yargs": { - "version": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", - "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", - "dev": true, - "dependencies": { - "camelcase": { - "version": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true - }, - "cliui": { - "version": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true - } - } - }, - "yargs-parser": { - "version": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", - "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", - "dev": true, - "dependencies": { - "camelcase": { - "version": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true - } - } - } - } -} diff --git a/package.json b/package.json index 2df00aa..353e1e6 100644 --- a/package.json +++ b/package.json @@ -2,11 +2,12 @@ "name": "iab-vast-loader", "version": "0.8.0", "description": "Loads and parses IAB VAST tags, resolving wrapped tags along the way.", - "main": "index.js", + "main": "lib/index.js", "jsnext:main": "src/index.js", "author": "Zentrick nv (https://www.zentrick.com/)", "contributors": [ - "Tim De Pauw " + "Tim De Pauw ", + "Laurent De Smet " ], "engines": { "node": ">=4" @@ -19,9 +20,10 @@ ], "scripts": { "clean": "gulp clean", - "build": "gulp build", + "build": "gulp build && flow-copy-source src lib", "prepublish": "in-publish && npm run build || not-in-publish", - "test": "gulp test" + "test": "flow check && gulp test", + "flow": "flow check" }, "repository": "zentrick/iab-vast-loader", "bugs": "https://github.com/zentrick/iab-vast-loader/issues", @@ -29,13 +31,19 @@ "eventemitter3": "^2.0.0", "iab-vast-model": "^0.4.0", "iab-vast-parser": "^0.4.1", - "isomorphic-fetch": "^2.2.1" + "invariant": "^2.2.2", + "isomorphic-fetch": "^2.2.1", + "rxjs": "^5.4.0", + "xmlhttprequest": "^1.8.0" }, "devDependencies": { + "babel-eslint": "^7.2.3", "babel-plugin-transform-builtin-extend": "^1.1.0", "babel-plugin-transform-runtime": "^6.23.0", "babel-preset-env": "^1.1.8", "babel-preset-es2015": "^6.24.1", + "babel-preset-flow": "^6.23.0", + "babel-preset-stage-3": "^6.24.1", "babel-register": "^6.24.0", "babel-runtime": "^6.23.0", "chai": "^3.5.0", @@ -44,6 +52,8 @@ "del": "^2.2.0", "dirty-chai": "^1.2.2", "express": "^4.15.2", + "flow-bin": "^0.46.0", + "flow-copy-source": "^1.1.0", "fs-promise": "^2.0.0", "gulp": "^3.9.1", "gulp-babel": "^6.1.2", @@ -56,6 +66,7 @@ "gulp-standard": "^9.0.0", "in-publish": "^2.0.0", "isparta": "^4.0.0", + "lodash": "^4.17.4", "mocha-junit-reporter": "^1.13.0", "run-sequence": "^1.1.5", "sinon": "^1.17.7", @@ -64,6 +75,7 @@ "yargs": "^7.0.2" }, "standard": { + "parser": "babel-eslint", "globals": [ "describe", "it", @@ -75,7 +87,10 @@ "sinon", "fetch", "XMLHttpRequest", - "Headers" + "$Keys", + "$PropertyType", + "RequestOptions", + "CredentialsType" ] } } diff --git a/src/atob.js b/src/atob.js deleted file mode 100644 index db6003c..0000000 --- a/src/atob.js +++ /dev/null @@ -1,22 +0,0 @@ -// Based on https://gist.github.com/stubbetje/229984 - -const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=' - -export default (string) => { - let result = '' - let i = 0 - do { - const b1 = characters.indexOf(string.charAt(i++)) - const b2 = characters.indexOf(string.charAt(i++)) - const b3 = characters.indexOf(string.charAt(i++)) - const b4 = characters.indexOf(string.charAt(i++)) - const a = ((b1 & 0x3F) << 2) | ((b2 >> 4) & 0x3) - const b = ((b2 & 0xF) << 4) | ((b3 >> 2) & 0xF) - const c = ((b3 & 0x3) << 6) | (b4 & 0x3F) - /* istanbul ignore next */ - result += String.fromCharCode(a) + - (b ? String.fromCharCode(b) : '') + - (c ? String.fromCharCode(c) : '') - } while (i < string.length) - return result -} diff --git a/src/concat-eager.js b/src/concat-eager.js new file mode 100644 index 0000000..a7f85fd --- /dev/null +++ b/src/concat-eager.js @@ -0,0 +1,76 @@ +// @flow + +import { Observable } from 'rxjs/Observable' + +export const concatEager = (observables: Observable[]): Observable => + Observable.create(subscriber => { + if (observables.length === 0) { + subscriber.complete() + return + } + + let buffer = {} + let complete = {} + let currentIndex = 0 + + const possiblyEmitBufferedValues = () => { + if (observables.length === currentIndex) { + subscriber.complete() + } + + // If the current observable has buffered values, emit them all right now. + if (buffer[currentIndex] != null) { + buffer[currentIndex].forEach(value => subscriber.next(value)) + // These values aren't needed anymore + buffer[currentIndex] = null + } + + // If the current observable is already completed, go on with the next observable. + if (complete[currentIndex]) { + currentIndex++ + possiblyEmitBufferedValues() + } + } + + // We subscribe to all the observables at once, but all events are emitted + // in order. This means we need to buffer values when a previous observable + // is not completed yet. + const subscriptions = observables.map((observable, index) => + observable.subscribe({ + next: value => { + if (index === currentIndex) { + // Currently, this observable is active so we emit immediately. + subscriber.next(value) + } else { + // A previous observable is still emitting, so we need to buffer. + if (buffer[index] == null) { + buffer[index] = [] + } + + buffer[index].push(value) + } + }, + error: err => { + subscriptions.forEach((subscription, index) => { + subscription.unsubscribe() + }) + subscriber.error(err) + }, + complete: () => { + complete[index] = true + if (index === currentIndex) { + // The currently active observable completed, so we possibly need + // to emit buffered values or complete the resulting observable. + currentIndex++ + possiblyEmitBufferedValues() + } + } + }) + ) + + const subscription = () => { + subscriptions.forEach(subscription => subscription.unsubscribe()) + } + + return subscription + }) diff --git a/src/error-codes.js b/src/error-codes.js index 3d6ed74..63d7a96 100644 --- a/src/error-codes.js +++ b/src/error-codes.js @@ -1,31 +1,33 @@ +// @flow + // https://support.google.com/dfp_premium/answer/4442429?hl=en export default { - 100: 'XML parsing error.', - 101: 'VAST schema validation error.', - 102: 'VAST version of response not supported.', - 200: 'Trafficking error.', - 201: 'Video player expecting different linearity.', - 202: 'Video player expecting different duration.', - 203: 'Video player expecting different size.', - 300: 'General Wrapper error.', - 301: 'Timeout.', - 302: 'Wrapper limit reached.', - 303: 'No Ads VAST response after one or more Wrappers.', - 400: 'General Linear error.', - 401: 'File not found.', - 402: 'Timeout of MediaFile URI.', - 403: 'No supported MediaFile found.', - 405: 'Problem displaying MediaFile.', - 500: 'General NonLinearAds error.', - 501: 'Unable to display NonLinear Ad because creative dimensions do not align with creative display area.', - 502: 'Unable to fetch NonLinearAds/NonLinear resource.', - 503: 'Couldn\'t find NonLinear resource with supported type.', - 600: 'General CompanionAds error.', - 601: 'Unable to display Companion because creative dimensions do not fit within Companion display area.', - 602: 'Unable to display Required Companion.', - 603: 'Unable to fetch CompanionAds/Companion resource.', - 604: 'Couldn\'t find Companion resource with supported type.', - 900: 'Undefined error.', - 901: 'General VPAID error.' + '100': 'XML parsing error.', + '101': 'VAST schema validation error.', + '102': 'VAST version of response not supported.', + '200': 'Trafficking error.', + '201': 'Video player expecting different linearity.', + '202': 'Video player expecting different duration.', + '203': 'Video player expecting different size.', + '300': 'General Wrapper error.', + '301': 'Timeout.', + '302': 'Wrapper limit reached.', + '303': 'No Ads VAST response after one or more Wrappers.', + '400': 'General Linear error.', + '401': 'File not found.', + '402': 'Timeout of MediaFile URI.', + '403': 'No supported MediaFile found.', + '405': 'Problem displaying MediaFile.', + '500': 'General NonLinearAds error.', + '501': 'Unable to display NonLinear Ad because creative dimensions do not align with creative display area.', + '502': 'Unable to fetch NonLinearAds/NonLinear resource.', + '503': 'Couldn\'t find NonLinear resource with supported type.', + '600': 'General CompanionAds error.', + '601': 'Unable to display Companion because creative dimensions do not fit within Companion display area.', + '602': 'Unable to display Required Companion.', + '603': 'Unable to fetch CompanionAds/Companion resource.', + '604': 'Couldn\'t find Companion resource with supported type.', + '900': 'Undefined error.', + '901': 'General VPAID error.' } diff --git a/src/error.js b/src/error.js index 28287f0..15c023b 100644 --- a/src/error.js +++ b/src/error.js @@ -1,26 +1,28 @@ +// @flow + import codeToMessage from './error-codes' -export default class VASTLoaderError extends Error { - constructor (code, cause = null, uri = null) { +type Code = $Keys + +export class VASTLoaderError extends Error { + _code: Code + _cause: any + + constructor (code: Code, cause: any) { super(codeToMessage[code]) this._code = code this._cause = cause - this._uri = uri } - get code () { + get code (): Code { return this._code } - get cause () { + get cause (): any { return this._cause } - get uri () { - return this._uri - } - - get $type () { + get $type (): 'VASTLoaderError' { return 'VASTLoaderError' } } diff --git a/src/index.js b/src/index.js index c2999e2..b72015f 100644 --- a/src/index.js +++ b/src/index.js @@ -1,139 +1,5 @@ -import EventEmitter from 'eventemitter3' -import fetch from 'isomorphic-fetch' -import parse from 'iab-vast-parser' -import { Wrapper } from 'iab-vast-model' -import VASTLoaderError from './error' -import atob from './atob' +// @flow -const RE_DATA_URI = /^data:(.*?)(;\s*base64)?,(.*)/ -const DEFAULT_OPTIONS = { - maxDepth: 10, - credentials: 'omit', - timeout: 10000 -} - -export { VASTLoaderError } - -export default class Loader extends EventEmitter { - constructor (uri, options, parent) { - super() - this._uri = uri - if (parent != null) { - this._root = parent._root - this._options = this._root._options - this._depth = parent._depth + 1 - } else { - this._root = this - this._options = Object.assign({}, DEFAULT_OPTIONS, options) - this._depth = 1 - } - this._fetchOptions = this._buildFetchOptions(uri) - } - - load () { - return this._load(this._uri) - .catch((error) => { - this._emit('error', { error }) - throw error - }) - } - - _load (uri) { - return Promise.resolve() - .then(() => { - this._emit('willFetch', { uri }) - const match = RE_DATA_URI.exec(uri) - return (match == null) ? this._fetchUri(uri) - : this._parseDataUri(match[3], match[1], (match[2] != null)) - }) - .then(({ headers, body }) => { - this._emit('didFetch', { uri, headers, body }) - this._emit('willParse', { uri, body }) - const vast = parse(body) - this._emit('didParse', { uri, body, vast }) - if (vast.ads.length > 0) { - const ad = vast.ads.get(0) - if (ad instanceof Wrapper || ad.$type === 'Wrapper') { - return this._loadWrapped(ad.vastAdTagURI, vast) - } - } else if (this._depth > 1) { - throw new VASTLoaderError(303, null, uri) - } - return [vast] - }) - } - - _parseDataUri (data, mimeType, isBase64) { - const headers = new Headers({ 'Content-Type': mimeType }) - const body = isBase64 ? atob(data) : decodeURIComponent(data) - return { headers, body } - } - - _loadWrapped (vastAdTagURI, vast) { - return Promise.resolve() - .then(() => { - const { maxDepth } = this._options - if (maxDepth > 0 && this._depth + 1 >= maxDepth) { - throw new VASTLoaderError(302, null, vastAdTagURI) - } - const childLoader = new Loader(vastAdTagURI, null, this) - return childLoader.load() - }) - .then((children) => ([vast, ...children])) - } - - _fetchUri (uri) { - const fetching = fetch(uri, this._fetchOptions) - const timingOut = this._createTimeouter(fetching, uri) - let headers - return Promise.race([fetching, timingOut]) - .then((response) => { - timingOut.cancel() - if (!response.ok) { - // TODO Convert response to HTTPError - throw new VASTLoaderError(900, response, uri) - } - headers = response.headers - return response.text() - }) - .then((body) => ({ headers, body })) - .catch((err) => { - timingOut.cancel() - if (this._depth > 1) { - throw new VASTLoaderError(301, null, uri) - } else { - throw err - } - }) - } - - _createTimeouter (fetching, uri) { - const ms = this._options.timeout - let timeout = null - const timingOut = new Promise((resolve, reject) => { - timeout = setTimeout(() => { - reject(new VASTLoaderError(301, null, uri)) - }, ms) - }) - timingOut.cancel = () => { - if (timeout != null) { - clearTimeout(timeout) - timeout = null - } - } - return timingOut - } - - _buildFetchOptions (uri) { - const { credentials } = this._options - switch (typeof credentials) { - case 'string': return { credentials } - case 'function': return { credentials: credentials(uri) } - default: throw new Error(`Invalid credentials option: ${credentials}`) - } - } - - _emit (...args) { - this._root.emit(...args) - } -} +export { loadVast } from './load-vast' +export { vastToAd } from './vast-to-ad' +export { VASTLoaderError } from './error' diff --git a/src/load-vast.js b/src/load-vast.js new file mode 100644 index 0000000..9336022 --- /dev/null +++ b/src/load-vast.js @@ -0,0 +1,179 @@ +// @flow + +import { type VAST, Wrapper } from 'iab-vast-model' +import parse from 'iab-vast-parser' +import { VASTLoaderError } from './error' +import { concatEager } from './concat-eager' +import { fx } from './rxjs-fx' + +import { Observable } from 'rxjs/Observable' + +// RxJS statics +import 'rxjs/add/observable/empty' +import 'rxjs/add/observable/of' +import 'rxjs/add/observable/from' + +// RxJS operators +import 'rxjs/add/operator/retry' +import 'rxjs/add/operator/timeout' +import 'rxjs/add/operator/catch' +import 'rxjs/add/operator/map' +import 'rxjs/add/operator/mergeMap' +import 'rxjs/add/operator/do' +import 'rxjs/add/operator/share' +import 'rxjs/add/operator/concatMap' +import 'rxjs/add/operator/toArray' +import 'rxjs/add/operator/toPromise' +import 'rxjs/add/operator/elementAt' + +type VastLoadedAction = { type: 'VAST_LOADED', vast: VAST } + +type VastLoadingFailedAction = { type: 'VAST_LOADING_FAILED', error: VASTLoaderError, wrapper: ?Wrapper } + +export type VastLoadAction = + VastLoadedAction | + VastLoadingFailedAction + +type CredentialsTypeOrFn = CredentialsType | (url: string) => CredentialsType + +type Credentials = CredentialsTypeOrFn | CredentialsTypeOrFn[] + +type Config = { + url: string, + maxDepth?: number, + timeout?: number, + retryCount?: number, + credentials: Credentials +} + +const DEFAULT_OPTIONS = { + maxDepth: 10, + timeout: 10000, + retryCount: 0, + credentials: 'omit' +} + +export const loadVast = (config: Config): Observable => + loadVastTree({ + ...DEFAULT_OPTIONS, + ...config, + parent: null + }) + +type LoadVastConfig = { + url: string, + parent: ?Wrapper, + maxDepth: number, + timeout: number, + retryCount: number, + credentials: Credentials +} + +// Traverse the tree using a preorder depth first strategy. +const loadVastTree = (config: LoadVastConfig): Observable => { + // We add share() because we want a multicast observable here, because + // loadVast$ is subscribed to in multiple places and this would result in + // multiple ajax requests for the same VAST document. + const loadVast$ = fetchVast(config).share() + + const children$ = loadVast$ + .concatMap(output => { + if (output.type === 'VAST_LOADING_FAILED') { + // When the VAST failed loading, then we can't load its children of course. + return Observable.empty() + } else { + const { vast } = output + const wrappers = getWrappers(vast) + + if (!vast.followAdditionalWrappers() || vast.depth === config.maxDepth) { + return Observable.from( + wrappers.map(wrapper => ({ + type: 'VAST_LOADING_FAILED', + wrapper, + error: new VASTLoaderError('302') + })) + ) + } else { + // We start fetching all the children. + const results = getWrappers(vast).map(wrapper => + loadVastTree({ + ...config, + url: wrapper.vastAdTagURI, + parent: wrapper + }) + ) + + // We start fetching them all at once and return the results in order. + return concatEager(results) + } + } + }) + + // We return a stream that will first emit an event for this VAST, + // and then returns all the child VASTS which comes down to a + // preorder depth first traversal. + return concatEager([loadVast$, children$]) +} + +const getWrappers = (vast: VAST): Wrapper[] => + // We cast to any here, because Flow is pessimistic and doesn't allow downcasting. + // Another approach could be to add an additional map, and perform an invariant check. + // This has however (a very minor) performance impact at runtime and it adds unnecessary complexity. + (vast.adBuffet.toArray().filter(ad => ad instanceof Wrapper): any) + +const normalizeCredentials = (credentials: Credentials): CredentialsTypeOrFn[] => Array.isArray(credentials) + ? credentials + : [credentials] + +// This function returns a stream with exact one event: a success or error event. +const fetchVast = (config: LoadVastConfig): Observable => + Observable.from(normalizeCredentials(config.credentials)) + .map(credentials => + typeof credentials === 'string' + ? credentials + : credentials(config.url) + ) + .concatMap(credentials => + fx + .http(config.url, { + method: 'GET', + credentials + }) + .retry(config.retryCount) + .timeout(config.timeout) + // Swallow errors. + .catch(() => Observable.empty()) + ) + // When there are only errors, the resulting stream will be empty, which + // will make elemetAt(0) fail, which is the expected behavior. + .elementAt(0) + .catch(() => { + if (config.parent == null) { + throw new VASTLoaderError('900') + } else { + throw new VASTLoaderError('301') + } + }) + .map(parseVast) + .do(vast => addParentToVast(vast, config.parent)) + .map(vast => ({ + type: 'VAST_LOADED', + vast: vast + })) + .catch(error => Observable.of({ + type: 'VAST_LOADING_FAILED', + error, + wrapper: config.parent + })) + +const parseVast = (res: string) => { + try { + return parse(res) + } catch (err) { + throw new VASTLoaderError('100') + } +} + +const addParentToVast = (vast: VAST, parent: ?Wrapper) => { + vast.parent = parent +} diff --git a/src/rxjs-fx.js b/src/rxjs-fx.js new file mode 100644 index 0000000..1fb0fd2 --- /dev/null +++ b/src/rxjs-fx.js @@ -0,0 +1,15 @@ +// @flow + +import fetch from 'isomorphic-fetch' +import { Observable } from 'rxjs/Observable' +import 'rxjs/add/observable/defer' +import 'rxjs/add/operator/mergeMap' +import 'rxjs/add/observable/fromPromise' + +const http = (url: string, options?: RequestOptions) => + Observable.defer(() => fetch(url, options)) + .mergeMap(res => res.ok ? Observable.fromPromise(res.text()) : Observable.throw(new Error('Http Failed'))) + +export const fx = { + http +} diff --git a/src/vast-to-ad.js b/src/vast-to-ad.js new file mode 100644 index 0000000..9252d97 --- /dev/null +++ b/src/vast-to-ad.js @@ -0,0 +1,87 @@ +// @flow + +import { Observable } from 'rxjs/Observable' +import { type VAST, type Ad, Wrapper } from 'iab-vast-model' +import { type VastLoadAction } from './load-vast' +import { type VASTLoaderError } from './error' + +type AdLoadedAction = { type: 'AD_LOADED', ad: Ad } + +type AdLoadingFailedAction = { type: 'AD_LOADING_FAILED', error: VASTLoaderError, wrapper: ?Wrapper } + +type AdLoadAction = AdLoadedAction | AdLoadingFailedAction + +// This function returns a depth first preorder stream of inline elements of the VAST chain. +export const vastToAd = (vast$: Observable): Observable => + vast$ + .concatMap(action => { + if (action.type === 'VAST_LOADED') { + // VAST_LOADED + const { vast } = action + + const ads = walkAdsUntilNextWrapper(vast, 0) + + return Observable.from(ads) + .map(ad => ({ + type: 'AD_LOADED', + ad + })) + } else { + // VAST_LOADING_FAILED + const { wrapper, error } = action + + const wrapperLoadingFailedAction = { + type: 'AD_LOADING_FAILED', + error, + wrapper + } + + const ads = wrapper == null + // There will not be a wrapper when it's the root VAST of the tree. + ? [] + // Emit the inline elements after the failed VAST. + : walkAdsUntilNextWrapper(wrapper.parent, getWrapperIndex(wrapper) + 1) + + const adLoadedActions = ads + .map(ad => ({ + type: 'AD_LOADED', + ad + })) + + return Observable.from([wrapperLoadingFailedAction, ...adLoadedActions]) + } + }) + +const getWrapperIndex = (wrapper: Wrapper): number => + wrapper.parent.adBuffet.toArray().indexOf(wrapper) + +const walkAdsUntilNextWrapper = (vast: VAST, fromIndex: number): Ad[] => { + const adBuffet = vast.adBuffet.toArray() + const adsFromIndex = adBuffet.slice(fromIndex) + const toIndex = adsFromIndex.findIndex(ad => ad instanceof Wrapper) + + const ads = toIndex === -1 + // All the inLines until the end of the array. + ? adBuffet.slice(fromIndex) + // An array of inLine ads, ending with one wrapper ad. + : adBuffet.slice(fromIndex, fromIndex + toIndex + 1) + + if (toIndex === -1) { + // This VAST file doesn't have Wrappers anymore so we can continue walking the tree upwards. + const { parent: wrapper } = vast + + if (wrapper == null) { + // We're at the top of the VAST tree so we can just return. + return ads + } else { + // We call the function recursively for our parent with the correct fromIndex. + return [ + ...ads, + ...walkAdsUntilNextWrapper(wrapper.parent, getWrapperIndex(wrapper) + 1) + ] + } + } else { + // We arrived at the next wrapper so we can end our recursion here. + return ads + } +} diff --git a/test/fixtures/invalid-ads-wrapper.xml b/test/fixtures/invalid-ads-wrapper.xml deleted file mode 100644 index 52501a2..0000000 --- a/test/fixtures/invalid-ads-wrapper.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - http://example.com/invalid-ads.xml - - - diff --git a/test/fixtures/no-ads-wrapper.xml b/test/fixtures/no-ads-wrapper.xml deleted file mode 100644 index 88302e4..0000000 --- a/test/fixtures/no-ads-wrapper.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - http://example.com/no-ads.xml - - - diff --git a/test/fixtures/no-ads.xml b/test/fixtures/no-ads.xml deleted file mode 100644 index 2134bff..0000000 --- a/test/fixtures/no-ads.xml +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/test/fixtures/tremor-video/vast2Nonlinear.xml b/test/fixtures/tremor-video/vast2Nonlinear.xml deleted file mode 100644 index 63f807c..0000000 --- a/test/fixtures/tremor-video/vast2Nonlinear.xml +++ /dev/null @@ -1,155 +0,0 @@ - - - - - 2.0 - 5750100 - - - - - - - - - - - - - - 2.0 - 5750092 - - - - - - - - - - - - - - 2.0 - 5750094 - - - - - - - - - - - - - - 2.0 - 5750091 - - - - - - - - - - - - - - 2.0 - 5748118 - - - - - - - - - - - - - - 2.0 - 5750088 - - - - - - - - - - - - - - 2.0 - 5700028 - - - - - - - - - - - - - - 2.0 - 5750098 - - - - - - - - - - - - - - 2.0 - 5750097 - - - - - - - - - - - - - - 2.0 - 5700030 - - - - - - - - - - - - - - diff --git a/test/fixtures/tremor-video/vast2RegularLinear.xml b/test/fixtures/tremor-video/vast2RegularLinear.xml deleted file mode 100644 index 056f579..0000000 --- a/test/fixtures/tremor-video/vast2RegularLinear.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - 2.0 - 5748406 - - - - - 00:00:30 - - - - - - - - - - - - - - -Click Here - - -]]> - - - - - - - - - diff --git a/test/fixtures/tremor-video/vast2VPAIDLinear.xml b/test/fixtures/tremor-video/vast2VPAIDLinear.xml deleted file mode 100644 index eca9977..0000000 --- a/test/fixtures/tremor-video/vast2VPAIDLinear.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - 2.0 - 5773100 - - - - 00:00:01 - - - - - - - - - - Click Here - - ]]> - - - - - - - - - - - diff --git a/test/fixtures/tremor-video/vast_inline_linear.xml b/test/fixtures/tremor-video/vast_inline_linear.xml deleted file mode 100644 index 149030c..0000000 --- a/test/fixtures/tremor-video/vast_inline_linear.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - Acudeo Compatible - VAST 2.0 Instream Test 1 - VAST 2.0 Instream Test 1 - http://myErrorURL/error - http://myTrackingURL/impression - - - - 00:00:30 - - http://myTrackingURL/creativeView - http://myTrackingURL/start - http://myTrackingURL/midpoint - http://myTrackingURL/firstQuartile - http://myTrackingURL/thirdQuartile - http://myTrackingURL/complete - - - http://www.tremormedia.com - http://myTrackingURL/click - - - http://cdnp.tremormedia.com/video/acudeo/Carrot_400x300_500kb.flv - - - - - - - http://demo.tremormedia.com/proddev/vast/Blistex1.jpg - - http://myTrackingURL/firstCompanionCreativeView - - - http://www.tremormedia.com - - - http://demo.tremormedia.com/proddev/vast/728x90_banner1.jpg - http://www.tremormedia.com - - - - - - - diff --git a/test/fixtures/tremor-video/vast_inline_nonlinear.xml b/test/fixtures/tremor-video/vast_inline_nonlinear.xml deleted file mode 100644 index e799cc8..0000000 --- a/test/fixtures/tremor-video/vast_inline_nonlinear.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - Acudeo Compatible - NonLinear Test Campaign 1 - NonLinear Test Campaign 1 - http://mySurveyURL/survey - http://myErrorURL/error - http://myTrackingURL/impression - - - - - http://myTrackingURL/nonlinear/creativeView - http://myTrackingURL/nonlinear/expand - http://myTrackingURL/nonlinear/collapse - http://myTrackingURL/nonlinear/acceptInvitation - http://myTrackingURL/nonlinear/close - - - - http://demo.tremormedia.com/proddev/vast/50x300_static.jpg - - http://www.tremormedia.com - - - - http://demo.tremormedia.com/proddev/vast/50x450_static.jpg - - http://www.tremormedia.com - - - - - - - http://demo.tremormedia.com/proddev/vast/300x250_companion_1.swf - - http://www.tremormedia.com - - - http://demo.tremormedia.com/proddev/vast/728x90_banner1.jpg - - http://myTrackingURL/secondCompanion - - http://www.tremormedia.com - - - - - - - diff --git a/test/fixtures/tremor-video/vast_wrapper_linear_1.xml b/test/fixtures/tremor-video/vast_wrapper_linear_1.xml deleted file mode 100644 index c7a276f..0000000 --- a/test/fixtures/tremor-video/vast_wrapper_linear_1.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - Acudeo Compatible - http://demo.tremormedia.com/proddev/vast/vast_inline_linear.xml - http://myErrorURL/wrapper/error - http://myTrackingURL/wrapper/impression - - - - - http://myTrackingURL/wrapper/creativeView - http://myTrackingURL/wrapper/start - http://myTrackingURL/wrapper/midpoint - http://myTrackingURL/wrapper/firstQuartile - http://myTrackingURL/wrapper/thirdQuartile - http://myTrackingURL/wrapper/complete - http://myTrackingURL/wrapper/mute - http://myTrackingURL/wrapper/unmute - http://myTrackingURL/wrapper/pause - http://myTrackingURL/wrapper/resume - http://myTrackingURL/wrapper/fullscreen - - - - - - - http://myTrackingURL/wrapper/click - - - - - - - - - - - - - diff --git a/test/fixtures/tremor-video/vast_wrapper_linear_2.xml b/test/fixtures/tremor-video/vast_wrapper_linear_2.xml deleted file mode 100644 index 4dae09f..0000000 --- a/test/fixtures/tremor-video/vast_wrapper_linear_2.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - Acudeo Compatible - http://demo.tremormedia.com/proddev/vast/vast_inline_linear.xml - http://myTrackingURL/wrapper/impression - - - - - - - - - - - http://demo.tremormedia.com/proddev/vast/300x250_banner1.jpg - - http://myTrackingURL/wrapper/firstCompanionCreativeView - - http://www.tremormedia.com - - - http://demo.tremormedia.com/proddev/vast/728x90_banner1.jpg - http://www.tremormedia.com - - - - - - - diff --git a/test/fixtures/tremor-video/vast_wrapper_nonlinear_1.xml b/test/fixtures/tremor-video/vast_wrapper_nonlinear_1.xml deleted file mode 100644 index 5a10db3..0000000 --- a/test/fixtures/tremor-video/vast_wrapper_nonlinear_1.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - Acudeo Compatible - http://demo.tremormedia.com/proddev/vast/vast_inline_nonlinear2.xml - http://myErrorURL/wrapper/error - http://myTrackingURL/wrapper/impression - - - - - - - - - - - http://myTrackingURL/wrapper/nonlinear/creativeView/creativeView - http://myTrackingURL/wrapper/nonlinear/creativeView/expand - http://myTrackingURL/wrapper/nonlinear/creativeView/collapse - http://myTrackingURL/wrapper/nonlinear/creativeView/acceptInvitation - http://myTrackingURL/wrapper/nonlinear/creativeView/close - - - - - - - diff --git a/test/fixtures/tremor-video/vast_wrapper_nonlinear_2.xml b/test/fixtures/tremor-video/vast_wrapper_nonlinear_2.xml deleted file mode 100644 index eabd2a4..0000000 --- a/test/fixtures/tremor-video/vast_wrapper_nonlinear_2.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - Acudeo Compatible - http://demo.tremormedia.com/proddev/vast/vast_inline_nonlinear3.xml - http://myTrackingURL/wrapper/impression - - - - - - - - - - - - - - - - - http://demo.tremormedia.com/proddev/vast/300x250_banner1.jpg - - http://myTrackingURL/wrapper/firstCompanionCreativeView - - http://www.tremormedia.com - - - http://demo.tremormedia.com/proddev/vast/728x90_banner1.jpg - http://www.tremormedia.com - - - - - - - diff --git a/test/fixtures/vast-a.xml b/test/fixtures/vast-a.xml new file mode 100644 index 0000000..6555a9f --- /dev/null +++ b/test/fixtures/vast-a.xml @@ -0,0 +1,43 @@ + + + + + Acudeo Compatible + VAST 2.0 Instream Test 1 + http://myErrorURL/error + http://myTrackingURL/impression + + + + + Acudeo Compatible + http://192.168.1.200:8080/vast-b.xml + http://myErrorURL/wrapper/error + http://myTrackingURL/wrapper/impression + + + + + Acudeo Compatible + VAST 2.0 Instream Test 1 + http://myErrorURL/error + http://myTrackingURL/impression + + + + + Acudeo Compatible + http://192.168.1.200:8080/vast-c.xml + http://myErrorURL/wrapper/error + http://myTrackingURL/wrapper/impression + + + + + Acudeo Compatible + VAST 2.0 Instream Test 1 + http://myErrorURL/error + http://myTrackingURL/impression + + + diff --git a/test/fixtures/vast-b.xml b/test/fixtures/vast-b.xml new file mode 100644 index 0000000..b81e86e --- /dev/null +++ b/test/fixtures/vast-b.xml @@ -0,0 +1,27 @@ + + + + + Acudeo Compatible + http://192.168.1.200:8080/vast-d.xml + http://myErrorURL/wrapper/error + http://myTrackingURL/wrapper/impression + + + + + Acudeo Compatible + VAST 2.0 Instream Test 1 + http://myErrorURL/error + http://myTrackingURL/impression + + + + + Acudeo Compatible + http://192.168.1.200:8080/vast-e.xml + http://myErrorURL/wrapper/error + http://myTrackingURL/wrapper/impression + + + diff --git a/test/fixtures/vast-c.xml b/test/fixtures/vast-c.xml new file mode 100644 index 0000000..caf44a1 --- /dev/null +++ b/test/fixtures/vast-c.xml @@ -0,0 +1,11 @@ + + + + + Acudeo Compatible + VAST 2.0 Instream Test 1 + http://myErrorURL/error + http://myTrackingURL/impression + + + diff --git a/test/fixtures/vast-d.xml b/test/fixtures/vast-d.xml new file mode 100644 index 0000000..caf44a1 --- /dev/null +++ b/test/fixtures/vast-d.xml @@ -0,0 +1,11 @@ + + + + + Acudeo Compatible + VAST 2.0 Instream Test 1 + http://myErrorURL/error + http://myTrackingURL/impression + + + diff --git a/test/fixtures/vast-e.xml b/test/fixtures/vast-e.xml new file mode 100644 index 0000000..caf44a1 --- /dev/null +++ b/test/fixtures/vast-e.xml @@ -0,0 +1,11 @@ + + + + + Acudeo Compatible + VAST 2.0 Instream Test 1 + http://myErrorURL/error + http://myTrackingURL/impression + + + diff --git a/test/fixtures/vast-standalone.xml b/test/fixtures/vast-standalone.xml new file mode 100644 index 0000000..caf44a1 --- /dev/null +++ b/test/fixtures/vast-standalone.xml @@ -0,0 +1,11 @@ + + + + + Acudeo Compatible + VAST 2.0 Instream Test 1 + http://myErrorURL/error + http://myTrackingURL/impression + + + diff --git a/test/lib/build-vast.js b/test/lib/build-vast.js new file mode 100644 index 0000000..40194ba --- /dev/null +++ b/test/lib/build-vast.js @@ -0,0 +1,40 @@ +import fs from 'fs' +import path from 'path' +import parseVast from 'iab-vast-parser' + +const fixturesPath = path.resolve(__dirname, '../fixtures') + +const buildVastVars = vastPath => { + const url = 'http://192.168.1.200:8080/' + vastPath + const str = fs.readFileSync(path.join(fixturesPath, vastPath), 'utf8') + const model = parseVast(str) + + return { url, str, model } +} + +export const buildVast = () => { + const a = buildVastVars('vast-a.xml') + const b = buildVastVars('vast-b.xml') + const c = buildVastVars('vast-c.xml') + const d = buildVastVars('vast-d.xml') + const e = buildVastVars('vast-e.xml') + const standalone = buildVastVars('vast-standalone.xml') + + // Setup the Wrapper => VAST links. + b.model.parent = a.model.adBuffet.toArray()[1] + c.model.parent = a.model.adBuffet.toArray()[3] + d.model.parent = b.model.adBuffet.toArray()[0] + e.model.parent = b.model.adBuffet.toArray()[2] + + return { a, b, c, d, e, standalone } +} + +export const buildAd = (vast) => { + const [p, q, r, s, t] = vast.a.model.adBuffet.toArray() + const [u, v, w] = vast.b.model.adBuffet.toArray() + const [x] = vast.c.model.adBuffet.toArray() + const [y] = vast.d.model.adBuffet.toArray() + const [z] = vast.e.model.adBuffet.toArray() + + return { p, q, r, s, t, u, v, w, x, y, z } +} diff --git a/test/lib/write-test-tree.js b/test/lib/write-test-tree.js new file mode 100644 index 0000000..9eaffa9 --- /dev/null +++ b/test/lib/write-test-tree.js @@ -0,0 +1,57 @@ +import archy from 'archy' + +// This prints the VAST tree, used to generate the comment section of test/unit/load-vast.js +const vastTree = archy({ + label: 'a: VAST', + nodes: [ + { label: 'p: InLine' }, + { + label: 'q: Wrapper', + nodes: [ + { + label: 'b: VAST', + nodes: [ + { + label: 'u: Wrapper', + nodes: [ + { + label: 'd: VAST', + nodes: [ + { label: 'y: InLine' } + ] + } + ] + }, + { label: 'v: InLine' }, + { + label: 'w: Wrapper', + nodes: [ + { + label: 'e: VAST', + nodes: [ + { label: 'z: InLine' } + ] + } + ] + } + ] + } + ] + }, + { label: 'r: InLine ' }, + { + label: 's: Wrapper', + nodes: [ + { + label: 'c: VAST', + nodes: [ + { label: 'x: InLine' } + ] + } + ] + }, + { label: 't: InLine' } + ] +}) + +console.log(vastTree) diff --git a/test/unit/load-vast.js b/test/unit/load-vast.js new file mode 100644 index 0000000..892dd4b --- /dev/null +++ b/test/unit/load-vast.js @@ -0,0 +1,372 @@ +import { loadVast } from '../../src' +import { VASTLoaderError } from '../../src/error' +import { buildVast } from '../lib/build-vast' +import { fx } from '../../src/rxjs-fx' + +import { TestScheduler } from 'rxjs/testing/TestScheduler' +import { Observable } from 'rxjs/Observable' + +import times from 'lodash/times' + +// Throughout the tests we make use of the following VAST document tree. +// This ASCII tree is generated using the test/lib/write-test-tree.js script. +// +// a: VAST +// ├── p: InLine +// ├─┬ q: Wrapper +// │ └─┬ b: VAST +// │ ├─┬ u: Wrapper +// │ │ └─┬ d: VAST +// │ │ └── y: InLine +// │ ├── v: InLine +// │ └─┬ w: Wrapper +// │ └─┬ e: VAST +// │ └── z: InLine +// ├── r: InLine +// ├─┬ s: Wrapper +// │ └─┬ c: VAST +// │ └── x: InLine +// └── t: InLine + +let originalTimeout + +const monkeyPatch = (scheduler) => { + originalTimeout = Observable.prototype.timeout + + Observable.prototype.timeout = function (due) { + return originalTimeout.call(this, due, scheduler) + } +} + +const restore = () => { + Observable.prototype.timeout = originalTimeout +} + +const fxFactory = mock => (...args) => Observable.defer(() => mock(...args)) + +const assertDeepEqual = (actual, expected) => { + expect(actual).to.deep.equal(expected) +} + +const vast = buildVast() + +describe('#loadVast()', () => { + let scheduler, cold, http + + beforeEach(() => { + scheduler = new TestScheduler(assertDeepEqual) + monkeyPatch(scheduler) + cold = scheduler.createColdObservable.bind(scheduler) + // http will be stubbed in each test so we keep a reference to the original. + http = fx.http + }) + + afterEach(() => { + restore() + // We restore the original http function. + fx.http = http + }) + + it('should load a VAST document', () => { + const httpStub = sinon.stub() + + httpStub + .onCall(0) + .returns(cold('---(a|)', { a: vast.standalone.str })) + + httpStub.throws() + + fx.http = fxFactory(httpStub) + + const actual$ = loadVast({ url: vast.standalone.url }) + + const expected = '---(a|)' + const values = { a: { type: 'VAST_LOADED', vast: vast.standalone.model } } + + scheduler.expectObservable(actual$).toBe(expected, values) + scheduler.flush() + + expect(httpStub.callCount).to.equal(1) + expect(httpStub.getCall(0).args).to.deep.equal([vast.standalone.url, { method: 'GET', credentials: 'omit' }]) + }) + + it('should load a VAST document by trying the passed credentials strategies one by one and ignoring failed requests', () => { + // ----(#|) + // ---(a|) + // -------(a|) + + const httpStub = sinon.stub() + const credentialStub = sinon.stub() + + httpStub + .onCall(0) + .returns(cold('----(#|)', null, new Error('http failed'))) + + httpStub + .onCall(1) + .returns(cold('---(a|)', { a: vast.standalone.str })) + + httpStub.throws() + + credentialStub + .onCall(0) + .returns('include') + + credentialStub.throws() + + fx.http = fxFactory(httpStub) + + const actual$ = loadVast({ + url: vast.standalone.url, + credentials: [ + 'omit', + credentialStub, + 'same-origin' + ] + }) + + const expected = '-------(a|)' + const values = { a: { type: 'VAST_LOADED', vast: vast.standalone.model } } + + scheduler.expectObservable(actual$).toBe(expected, values) + scheduler.flush() + + expect(httpStub.callCount).to.equal(2) + expect(httpStub.getCall(0).args).to.deep.equal([vast.standalone.url, { method: 'GET', credentials: 'omit' }]) + expect(httpStub.getCall(1).args).to.deep.equal([vast.standalone.url, { method: 'GET', credentials: 'include' }]) + + expect(credentialStub.callCount).to.equal(1) + expect(credentialStub.getCall(0).args).to.deep.equal([vast.standalone.url]) + }) + + it('should retry loading a VAST document', () => { + const httpStub = sinon.stub() + + httpStub + .onCall(0) + .returns(cold('---(#|)', null, new Error('http failed'))) + + httpStub + .onCall(1) + .returns(cold('---(#|)', null, new Error('http failed'))) + + httpStub + .onCall(2) + .returns(cold('---(a|)', { a: vast.standalone.str })) + + httpStub.throws() + + fx.http = fxFactory(httpStub) + + const actual$ = loadVast({ url: vast.standalone.url, retryCount: 2 }) + + const expected = '---------(a|)' + const values = { a: { type: 'VAST_LOADED', vast: vast.standalone.model } } + + scheduler.expectObservable(actual$).toBe(expected, values) + scheduler.flush() + + expect(httpStub.callCount).to.equal(3) + + times(3, i => { + expect(httpStub.getCall(i).args).to.deep.equal([vast.standalone.url, { method: 'GET', credentials: 'omit' }]) + }) + }) + + it('should load a complete VAST tree', async () => { + const httpStub = sinon.stub() + + const vastA$ = cold('--(a|)', { a: vast.a.str }) + httpStub + .onCall(0) + .returns(vastA$) + + const vastB$ = cold('-----(b|)', { b: vast.b.str }) + httpStub + .onCall(1) + .returns(vastB$) + + httpStub + .onCall(2) + .returns(cold('--(c|)', { c: vast.c.str })) + + httpStub + .onCall(3) + .returns(cold('--(d|)', { d: vast.d.str })) + + httpStub + .onCall(4) + .returns(cold('-----(e|)', { e: vast.e.str })) + + httpStub.throws() + + fx.http = fxFactory(httpStub) + + const actual$ = loadVast({ url: vast.a.url }) + const expected = '--a----b-d--(ec|)' + const values = { + a: { type: 'VAST_LOADED', vast: vast.a.model }, + b: { type: 'VAST_LOADED', vast: vast.b.model }, + c: { type: 'VAST_LOADED', vast: vast.c.model }, + d: { type: 'VAST_LOADED', vast: vast.d.model }, + e: { type: 'VAST_LOADED', vast: vast.e.model } + } + + scheduler.expectObservable(actual$).toBe(expected, values) + scheduler.expectSubscriptions(vastA$.subscriptions).toBe('^-!') + scheduler.expectSubscriptions(vastB$.subscriptions).toBe('--^----!') + scheduler.flush() + + expect(httpStub.callCount).to.equal(5) + expect(httpStub.getCall(0).args).to.deep.equal([vast.a.url, { method: 'GET', credentials: 'omit' }]) + expect(httpStub.getCall(1).args).to.deep.equal([vast.b.url, { method: 'GET', credentials: 'omit' }]) + expect(httpStub.getCall(2).args).to.deep.equal([vast.c.url, { method: 'GET', credentials: 'omit' }]) + expect(httpStub.getCall(3).args).to.deep.equal([vast.d.url, { method: 'GET', credentials: 'omit' }]) + expect(httpStub.getCall(4).args).to.deep.equal([vast.e.url, { method: 'GET', credentials: 'omit' }]) + }) + + it('should return a VAST_LOADING_FAILED action when the root VAST document timeouts', () => { + const httpStub = sinon.stub() + + httpStub + .onCall(0) + .returns(cold('---(a|)', { a: vast.standalone.str })) + + httpStub.throws() + + fx.http = fxFactory(httpStub) + + const actual$ = loadVast({ url: vast.standalone.url, timeout: 20 }) + const expected = '--(a|)' + const values = { + a: { type: 'VAST_LOADING_FAILED', error: new VASTLoaderError('900'), wrapper: null } + } + + scheduler.expectObservable(actual$).toBe(expected, values) + scheduler.flush() + + expect(httpStub.callCount).to.equal(1) + expect(httpStub.getCall(0).args).to.deep.equal([vast.standalone.url, { method: 'GET', credentials: 'omit' }]) + }) + + describe('', () => { + let vastBParent + before(() => { + // Temporarily reset the parent of vast.b + vastBParent = vast.b.model.parent + vast.b.model.parent = null + }) + + it('should return a VAST_LOADING_FAILED action when a non-root VAST document timeouts', () => { + // --(b|) + // -----(#|) + // --(e|) + // --b----(de|) + + const httpStub = sinon.stub() + + httpStub + .onCall(0) + .returns(cold('--(b|)', { b: vast.b.str })) + + httpStub + .onCall(1) + .returns(cold('-----(#|)', null, new Error('http failed'))) + + httpStub + .onCall(2) + .returns(cold('--(e|)', { e: vast.e.str })) + + httpStub.throws() + + fx.http = fxFactory(httpStub) + + const actual$ = loadVast({ url: vast.b.url }) + const expected = '--b----(de|)' + const values = { + b: { type: 'VAST_LOADED', vast: vast.b.model }, + d: { type: 'VAST_LOADING_FAILED', error: new VASTLoaderError('301'), wrapper: vast.b.model.adBuffet.toArray()[0] }, + e: { type: 'VAST_LOADED', vast: vast.e.model } + } + + scheduler.expectObservable(actual$).toBe(expected, values) + scheduler.flush() + + expect(httpStub.callCount).to.equal(3) + expect(httpStub.getCall(0).args).to.deep.equal([vast.b.url, { method: 'GET', credentials: 'omit' }]) + expect(httpStub.getCall(1).args).to.deep.equal([vast.d.url, { method: 'GET', credentials: 'omit' }]) + expect(httpStub.getCall(2).args).to.deep.equal([vast.e.url, { method: 'GET', credentials: 'omit' }]) + }) + + after(() => { + vast.b.model.parent = vastBParent + }) + }) + + it('should return a VAST_LOADING_FAILED action when the XML document is not valid', () => { + const httpStub = sinon.stub() + + httpStub + .onCall(0) + .returns(cold('---(a|)', { a: 'malformed xml' })) + + httpStub.throws() + + fx.http = fxFactory(httpStub) + + const actual$ = loadVast({ url: vast.standalone.url }) + const expected = '---(a|)' + const values = { + a: { type: 'VAST_LOADING_FAILED', error: new VASTLoaderError('100'), wrapper: null } + } + + scheduler.expectObservable(actual$).toBe(expected, values) + scheduler.flush() + + expect(httpStub.callCount).to.equal(1) + expect(httpStub.getCall(0).args).to.deep.equal([vast.standalone.url, { method: 'GET', credentials: 'omit' }]) + }) + + it('should not fetch additional documents if maxDepth is exceeded', () => { + // --(a|) + // -----(b|) + // --(c|) + // --a----(bdec|) + + const httpStub = sinon.stub() + + httpStub + .onCall(0) + .returns(cold('--(a|)', { a: vast.a.str })) + + httpStub + .onCall(1) + .returns(cold('-----(b|)', { b: vast.b.str })) + + httpStub + .onCall(2) + .returns(cold('--(c|)', { c: vast.c.str })) + + httpStub.throws() + + fx.http = fxFactory(httpStub) + const actual$ = loadVast({ url: vast.a.url, maxDepth: 1 }) + + const expected = '--a----(bdec|)' + const values = { + a: { type: 'VAST_LOADED', vast: vast.a.model }, + b: { type: 'VAST_LOADED', vast: vast.b.model }, + d: { type: 'VAST_LOADING_FAILED', wrapper: vast.b.model.adBuffet.toArray()[0], error: new VASTLoaderError('302') }, + e: { type: 'VAST_LOADING_FAILED', wrapper: vast.b.model.adBuffet.toArray()[2], error: new VASTLoaderError('302') }, + c: { type: 'VAST_LOADED', vast: vast.c.model } + } + + scheduler.expectObservable(actual$).toBe(expected, values) + scheduler.flush() + + expect(httpStub.callCount).to.equal(3) + expect(httpStub.getCall(0).args).to.deep.equal([vast.a.url, { method: 'GET', credentials: 'omit' }]) + expect(httpStub.getCall(1).args).to.deep.equal([vast.b.url, { method: 'GET', credentials: 'omit' }]) + expect(httpStub.getCall(2).args).to.deep.equal([vast.c.url, { method: 'GET', credentials: 'omit' }]) + }) +}) diff --git a/test/unit/node.js b/test/unit/node.js deleted file mode 100644 index 5d385bb..0000000 --- a/test/unit/node.js +++ /dev/null @@ -1,278 +0,0 @@ -import express from 'express' -import fsp from 'fs-promise' -import path from 'path' -import { default as VASTLoader, VASTLoaderError } from '../../src/' - -const expectLoaderError = (error, code, message, cause) => { - expect(error).to.be.an.instanceof(VASTLoaderError) - expect(error.code).to.equal(code) - expect(error.message).to.equal(message) - if (cause != null) { - expect(error.cause).to.include(cause) - } -} - -describe('VASTLoaderError', function () { - describe('#code', function () { - it('gets set from the constructor', function () { - const error = new VASTLoaderError(301) - expect(error.code).to.equal(301) - }) - }) - - describe('#message', function () { - it('resolves from the code', function () { - const error = new VASTLoaderError(301) - expect(error.message).to.equal('Timeout.') - }) - }) - - describe('#cause', function () { - it('gets set from the constructor', function () { - const cause = new Error('Foo') - const error = new VASTLoaderError(301, cause) - expect(error.cause).to.equal(cause) - }) - }) - - describe('#$type', function () { - it('is VASTLoaderError', function () { - const error = new VASTLoaderError(900) - expect(error.$type).to.equal('VASTLoaderError') - }) - }) -}) - -describe('VASTLoader', function () { - const fixturesPath = path.resolve(__dirname, '../fixtures') - const proxyPaths = { - 'http://demo.tremormedia.com/proddev/vast/vast_inline_linear.xml': 'tremor-video/vast_inline_linear.xml', - 'http://example.com/no-ads.xml': 'no-ads.xml', - 'http://example.com/invalid-ads.xml': 'invalid-ads.xml' - } - - let fetchUriImpl - let server - let baseUrl - let responseDelay - - const createLoader = (file, options) => new VASTLoader(baseUrl + file, options) - - const proxifyFetchUri = function () { - fetchUriImpl = VASTLoader.prototype._fetchUri - VASTLoader.prototype._fetchUri = async function (uri) { - const target = proxyPaths[uri] - if (target == null) { - return await fetchUriImpl.call(this, uri) - } - return await fetchUriImpl.call(this, baseUrl + target) - } - } - - const unproxifyFetchUri = function () { - VASTLoader.prototype._fetchUri = fetchUriImpl - } - - before(function (cb) { - const app = express() - app.use((req, res, next) => { - setTimeout(() => next(), responseDelay) - }) - app.use(express.static(fixturesPath)) - server = app.listen(function () { - baseUrl = 'http://localhost:' + server.address().port + '/' - proxifyFetchUri() - cb() - }) - }) - - after(function (cb) { - unproxifyFetchUri() - server.close(cb) - }) - - beforeEach(function () { - responseDelay = 0 - }) - - describe('#load()', function () { - it('loads the InLine', async function () { - const loader = createLoader('tremor-video/vast_inline_linear.xml') - const chain = await loader.load() - expect(chain).to.be.an.instanceof(Array) - expect(chain.length).to.equal(1) - }) - - it('loads the Wrapper', async function () { - const loader = createLoader('tremor-video/vast_wrapper_linear_1.xml') - const chain = await loader.load() - expect(chain).to.be.an.instanceof(Array) - expect(chain.length).to.equal(2) - }) - - it('loads the InLine as Base64', async function () { - const file = path.join(fixturesPath, 'tremor-video/vast_inline_linear.xml') - const base64 = (await fsp.readFile(file)).toString('base64') - const dataUri = 'data:text/xml;base64,' + base64 - const loader = new VASTLoader(dataUri) - const chain = await loader.load() - expect(chain).to.be.an.instanceof(Array) - expect(chain.length).to.equal(1) - }) - - it('loads the InLine as XML', async function () { - const file = path.join(fixturesPath, 'tremor-video/vast_inline_linear.xml') - const xml = (await fsp.readFile(file, 'utf8')).replace(/\r?\n/g, '') - const dataUri = 'data:text/xml,' + xml - const loader = new VASTLoader(dataUri) - const chain = await loader.load() - expect(chain).to.be.an.instanceof(Array) - expect(chain.length).to.equal(1) - }) - - it('loads the empty tag', async function () { - const loader = createLoader('no-ads.xml') - const chain = await loader.load() - expect(chain.length).to.equal(1) - expect(chain[0].ads.length).to.equal(0) - }) - - it('throws VAST 303 on empty InLine inside Wrapper', async function () { - let error - try { - const loader = createLoader('no-ads-wrapper.xml') - await loader.load() - } catch (err) { - error = err - } - expectLoaderError(error, 303, 'No Ads VAST response after one or more Wrappers.') - }) - - it('throws VAST 301 on invalid InLine inside Wrapper', async function () { - let error - try { - const loader = createLoader('invalid-ads-wrapper.xml') - await loader.load() - } catch (err) { - error = err - } - expectLoaderError(error, 301, 'Timeout.') - }) - - it('throws on HTTP errors', async function () { - let error - try { - const loader = createLoader('four-oh-four') - await loader.load() - } catch (err) { - error = err - } - expectLoaderError(error, 900, 'Undefined error.', {status: 404, statusText: 'Not Found'}) - }) - }) - - // TODO Test event data - describe('#emit()', function () { - for (const type of ['willFetch', 'didFetch', 'willParse', 'didParse']) { - it(`emits ${type}`, async function () { - const spy = sinon.spy() - const loader = createLoader('tremor-video/vast_inline_linear.xml') - loader.on(type, spy) - await loader.load() - expect(spy.called).to.be.true() - }) - } - - for (const type of ['willFetch', 'didFetch', 'willParse', 'didParse']) { - it(`emits ${type} once per tag`, async function () { - const spy = sinon.spy() - const loader = createLoader('tremor-video/vast_wrapper_linear_1.xml') - loader.on(type, spy) - await loader.load() - expect(spy.calledTwice).to.be.true() - }) - } - - it('emits error on errors', async function () { - const spy = sinon.spy() - const loader = createLoader('four-oh-four') - loader.on('error', spy) - try { - await loader.load() - } catch (err) {} - expect(spy.calledOnce).to.be.true() - }) - }) - - describe('maxDepth option', function () { - it('throws when maxDepth is reached', async function () { - let error - try { - const loader = createLoader('tremor-video/vast_wrapper_linear_1.xml', { - maxDepth: 1 - }) - await loader.load() - } catch (err) { - error = err - } - expectLoaderError(error, 302, 'Wrapper limit reached.') - }) - }) - - describe('timeout option', function () { - it('throws when timeout is reached', async function () { - responseDelay = 100 - let error - try { - const loader = createLoader('no-ads.xml', { - timeout: 10 - }) - await loader.load() - } catch (err) { - error = err - } - expectLoaderError(error, 301, 'Timeout.') - }) - }) - - describe('credentials option', function () { - // TODO Use something nicer than inspecting private _fetchOptions - - it('is "omit" by default', function () { - const loader = createLoader('tremor-video/vast_inline_linear.xml') - expect(loader._fetchOptions).to.eql({ credentials: 'omit' }) - }) - - it('overrides with a string value', function () { - const loader = createLoader('tremor-video/vast_inline_linear.xml', { - credentials: 'include' - }) - expect(loader._fetchOptions).to.eql({ credentials: 'include' }) - }) - - it('overrides with a function value', function () { - const loader = createLoader('tremor-video/vast_inline_linear.xml', { - credentials: (uri) => 'same-origin' - }) - expect(loader._fetchOptions).to.eql({ credentials: 'same-origin' }) - }) - - it('calls the function with the tag URI', function () { - const credentials = sinon.spy((uri) => 'same-origin') - const file = 'tremor-video/vast_inline_linear.xml' - const uri = baseUrl + file - createLoader(file, { - credentials - }) - expect(credentials).to.have.been.calledWith(uri) - }) - - it('throws if neither a string nor a function provided', function () { - expect(function () { - createLoader('tremor-video/vast_inline_linear.xml', { - credentials: true - }) - }).to.throw(Error, 'Invalid credentials option: true') - }) - }) -}) diff --git a/test/unit/rxjs-fx.js b/test/unit/rxjs-fx.js new file mode 100644 index 0000000..ee55278 --- /dev/null +++ b/test/unit/rxjs-fx.js @@ -0,0 +1,46 @@ +import express from 'express' +import path from 'path' +import { fx } from '../../src/rxjs-fx' +import { buildVast } from '../lib/build-vast' +import { Observable } from 'rxjs/Observable' + +const fixturesPath = path.resolve(__dirname, '../fixtures') +const vast = buildVast() + +describe('fx', () => { + describe('#http()', () => { + let baseUrl, server + + before((cb) => { + const app = express() + app.use(express.static(fixturesPath)) + server = app.listen(() => { + baseUrl = 'http://localhost:' + server.address().port + '/' + cb() + }) + }) + + after((cb) => { + server.close(cb) + }) + + it('should fetch the correct resource', async () => { + const http$ = fx.http(baseUrl + 'vast-standalone.xml') + + // First we map the Observable to an Observable with all the observed events in one array, + // which we then convert to a promise. + const actual = await http$.toArray().toPromise() + + expect(actual).to.deep.equal([vast.standalone.str]) + }) + + it('should emit an error when fetching fails', async () => { + const http$ = fx.http(baseUrl + 'non-existent.xml') + const error = new Error('http failed') + + const actual = await http$.catch(() => Observable.of(error)).toArray().toPromise() + + expect(actual).to.deep.equal([error]) + }) + }) +}) diff --git a/test/unit/vast-to-ad.js b/test/unit/vast-to-ad.js new file mode 100644 index 0000000..0cbef18 --- /dev/null +++ b/test/unit/vast-to-ad.js @@ -0,0 +1,104 @@ +import { vastToAd } from '../../src' +import { buildVast, buildAd } from '../lib/build-vast' +import { TestScheduler } from 'rxjs/testing/TestScheduler' +import { VASTLoaderError } from '../../src/error' + +const vast = buildVast() +const ad = buildAd(vast) + +const assertDeepEqual = (actual, expected) => { + expect(actual).to.deep.equal(expected) +} + +// const createInputValues = vast => +// Object.keys(vast) +// .reduce((acc, prop) => ({ +// ...acc, +// [prop]: { type: 'VAST_LOADED', vast: vast[prop].model } +// })) + +describe('#vastToAd()', () => { + let scheduler, cold + + beforeEach(() => { + scheduler = new TestScheduler(assertDeepEqual) + cold = scheduler.createColdObservable.bind(scheduler) + }) + + it('should map the vast$ to an ad$', () => { + // --a----b--d-----e------(c|) + // --(pq)-u--(yvw)-(zrs)--(xt|) + + const input$ = cold('--a----b--d-----e------(c|)', { + a: { type: 'VAST_LOADED', vast: vast.a.model }, + b: { type: 'VAST_LOADED', vast: vast.b.model }, + d: { type: 'VAST_LOADED', vast: vast.d.model }, + e: { type: 'VAST_LOADED', vast: vast.e.model }, + c: { type: 'VAST_LOADED', vast: vast.c.model } + }) + + const actual$ = vastToAd(input$) + const expected = '--(pq)-u--(yvw)-(zrs)--(xt|)' + const values = { + p: { type: 'AD_LOADED', ad: ad.p }, + q: { type: 'AD_LOADED', ad: ad.q }, + u: { type: 'AD_LOADED', ad: ad.u }, + y: { type: 'AD_LOADED', ad: ad.y }, + v: { type: 'AD_LOADED', ad: ad.v }, + w: { type: 'AD_LOADED', ad: ad.w }, + z: { type: 'AD_LOADED', ad: ad.z }, + r: { type: 'AD_LOADED', ad: ad.r }, + s: { type: 'AD_LOADED', ad: ad.s }, + x: { type: 'AD_LOADED', ad: ad.x }, + t: { type: 'AD_LOADED', ad: ad.t } + } + scheduler.expectObservable(actual$).toBe(expected, values) + scheduler.flush() + }) + + it('should correctly map VAST_LOADING_FAILED actions to AD_LOADING_FAILED actions', () => { + // --a----b--d-----e------(c|) + // --(pq)-u--(yvw)-(zrs)--(xt|) + + const input$ = cold('--a----b--d-----e------(c|)', { + a: { type: 'VAST_LOADED', vast: vast.a.model }, + b: { type: 'VAST_LOADED', vast: vast.b.model }, + d: { type: 'VAST_LOADING_FAILED', error: new VASTLoaderError('900'), wrapper: vast.b.model.adBuffet.toArray()[0] }, + e: { type: 'VAST_LOADED', vast: vast.e.model }, + c: { type: 'VAST_LOADING_FAILED', error: new VASTLoaderError('900'), wrapper: vast.a.model.adBuffet.toArray()[3] } + }) + + const actual$ = vastToAd(input$) + const expected = '--(pq)-u--(yvw)-(zrs)--(xt|)' + const values = { + p: { type: 'AD_LOADED', ad: ad.p }, + q: { type: 'AD_LOADED', ad: ad.q }, + u: { type: 'AD_LOADED', ad: ad.u }, + y: { type: 'AD_LOADING_FAILED', error: new VASTLoaderError('900'), wrapper: vast.b.model.adBuffet.toArray()[0] }, + v: { type: 'AD_LOADED', ad: ad.v }, + w: { type: 'AD_LOADED', ad: ad.w }, + z: { type: 'AD_LOADED', ad: ad.z }, + r: { type: 'AD_LOADED', ad: ad.r }, + s: { type: 'AD_LOADED', ad: ad.s }, + x: { type: 'AD_LOADING_FAILED', error: new VASTLoaderError('900'), wrapper: vast.a.model.adBuffet.toArray()[3] }, + t: { type: 'AD_LOADED', ad: ad.t } + } + scheduler.expectObservable(actual$).toBe(expected, values) + scheduler.flush() + }) + + it('should work correctly when the root VAST fails to download', () => { + const input$ = cold('--(a|)', { + a: { type: 'VAST_LOADING_FAILED', error: new VASTLoaderError('900'), wrapper: null } + }) + + const actual$ = vastToAd(input$) + const expected = '--(p|)' + const values = { + p: { type: 'AD_LOADING_FAILED', error: new VASTLoaderError('900'), wrapper: null } + } + + scheduler.expectObservable(actual$).toBe(expected, values) + scheduler.flush() + }) +})