From 60eb88dadd88179c0386348e85466386dfaf835f Mon Sep 17 00:00:00 2001 From: Timur Manyanov Date: Tue, 16 Oct 2018 18:45:24 +0200 Subject: [PATCH] Initial commit v.4.22 --- .gitignore | 25 + .npmignore | 20 + .nvmrc | 1 + .nycrc | 21 + LICENSE.txt | 11 + README.md | 147 ++ bin/marko-playground.js | 5 + browser.json | 8 + config/playground.json | 15 + marko.json | 3 + package.json | 77 + src/components.ts | 77 + src/config.ts | 71 + src/dependencies.ts | 67 + src/fixtures.ts | 33 + src/index.ts | 46 + src/logging.ts | 82 + src/meta.ts | 46 + src/playground.ts | 41 + src/routes.ts | 85 + src/server-config.ts | 32 + src/start-server.ts | 36 + src/view-model.ts | 61 + styles/comp.less | 84 + styles/const.less | 17 + styles/index.less | 90 + styles/sidebar.less | 58 + templates/mpg-comp.marko | 32 + templates/mpg-index.marko | 75 + templates/mpg-sidebar.marko | 14 + templates/mpg-site-layout.marko | 19 + test/components.spec.ts | 37 + test/config.spec.ts | 65 + test/data/combinedConfig.json | 6 + test/data/config.json | 5 + test/data/expected-comps.json | 32 + test/data/fixtures.json | 8 + test/data/localConfig.json | 3 + test/data/localConfigOverride.json | 3 + test/data/mock-comps.ts | 20 + test/data/mock-pgs.ts | 30 + test/dependencies/all-package-paths.spec.ts | 63 + test/dependencies/component-files.spec.ts | 86 + .../comp-multi-file-browser-json/browser.json | 6 + .../comp-multi-file-browser-json/component.js | 22 + .../comp-multi-file-browser-json/index.marko | 9 + .../comp-multi-file-browser-json/style.less | 17 + .../test/fixtures/default.json | 3 + .../test/fixtures/fixture2.json | 3 + .../comps/comp-multi-file-custom/component.js | 22 + .../comps/comp-multi-file-custom/index.marko | 9 + .../comps/comp-multi-file-custom/style.less | 17 + .../test/fixtures/default.json | 3 + .../test/fixtures/fixture2.json | 3 + .../test/pg/index.marko | 34 + .../comps/comp-multi-file/component.js | 22 + .../comps/comp-multi-file/index.marko | 9 + .../examples/comps/comp-multi-file/style.less | 17 + .../test/fixtures/default.json | 3 + .../test/fixtures/fixture2.json | 3 + .../browser.json | 5 + .../comp-single-file-browser-json/index.marko | 34 + .../test/fixtures/default.json | 3 + .../test/fixtures/fixture2.json | 3 + .../comp-single-file-no-fixtures/index.marko | 34 + .../comps/comp-single-file/index.marko | 34 + .../test/fixtures/default.json | 3 + .../test/fixtures/fixture2.json | 3 + test/examples/index.js | 55 + test/examples/index.marko | 21 + test/examples/marko.json | 3 + test/fixtures.spec.ts | 32 + test/mocha.opts | 8 + test/playground.spec.ts | 41 + test/routes.spec.ts | 112 + test/tslint.json | 8 + test/view-model.spec.ts | 159 ++ tsconfig.json | 23 + tslint.json | 24 + yarn.lock | 2267 +++++++++++++++++ 80 files changed, 4831 insertions(+) create mode 100644 .gitignore create mode 100644 .npmignore create mode 100644 .nvmrc create mode 100644 .nycrc create mode 100644 LICENSE.txt create mode 100644 README.md create mode 100755 bin/marko-playground.js create mode 100644 browser.json create mode 100644 config/playground.json create mode 100644 marko.json create mode 100644 package.json create mode 100644 src/components.ts create mode 100644 src/config.ts create mode 100644 src/dependencies.ts create mode 100644 src/fixtures.ts create mode 100755 src/index.ts create mode 100644 src/logging.ts create mode 100644 src/meta.ts create mode 100644 src/playground.ts create mode 100644 src/routes.ts create mode 100644 src/server-config.ts create mode 100644 src/start-server.ts create mode 100644 src/view-model.ts create mode 100644 styles/comp.less create mode 100644 styles/const.less create mode 100644 styles/index.less create mode 100644 styles/sidebar.less create mode 100644 templates/mpg-comp.marko create mode 100644 templates/mpg-index.marko create mode 100644 templates/mpg-sidebar.marko create mode 100644 templates/mpg-site-layout.marko create mode 100644 test/components.spec.ts create mode 100644 test/config.spec.ts create mode 100644 test/data/combinedConfig.json create mode 100644 test/data/config.json create mode 100644 test/data/expected-comps.json create mode 100644 test/data/fixtures.json create mode 100644 test/data/localConfig.json create mode 100644 test/data/localConfigOverride.json create mode 100644 test/data/mock-comps.ts create mode 100644 test/data/mock-pgs.ts create mode 100644 test/dependencies/all-package-paths.spec.ts create mode 100644 test/dependencies/component-files.spec.ts create mode 100644 test/examples/comps/comp-multi-file-browser-json/browser.json create mode 100644 test/examples/comps/comp-multi-file-browser-json/component.js create mode 100644 test/examples/comps/comp-multi-file-browser-json/index.marko create mode 100644 test/examples/comps/comp-multi-file-browser-json/style.less create mode 100644 test/examples/comps/comp-multi-file-browser-json/test/fixtures/default.json create mode 100644 test/examples/comps/comp-multi-file-browser-json/test/fixtures/fixture2.json create mode 100644 test/examples/comps/comp-multi-file-custom/component.js create mode 100644 test/examples/comps/comp-multi-file-custom/index.marko create mode 100644 test/examples/comps/comp-multi-file-custom/style.less create mode 100644 test/examples/comps/comp-multi-file-custom/test/fixtures/default.json create mode 100644 test/examples/comps/comp-multi-file-custom/test/fixtures/fixture2.json create mode 100644 test/examples/comps/comp-multi-file-custom/test/pg/index.marko create mode 100644 test/examples/comps/comp-multi-file/component.js create mode 100644 test/examples/comps/comp-multi-file/index.marko create mode 100644 test/examples/comps/comp-multi-file/style.less create mode 100644 test/examples/comps/comp-multi-file/test/fixtures/default.json create mode 100644 test/examples/comps/comp-multi-file/test/fixtures/fixture2.json create mode 100644 test/examples/comps/comp-single-file-browser-json/browser.json create mode 100644 test/examples/comps/comp-single-file-browser-json/index.marko create mode 100644 test/examples/comps/comp-single-file-browser-json/test/fixtures/default.json create mode 100644 test/examples/comps/comp-single-file-browser-json/test/fixtures/fixture2.json create mode 100644 test/examples/comps/comp-single-file-no-fixtures/index.marko create mode 100644 test/examples/comps/comp-single-file/index.marko create mode 100644 test/examples/comps/comp-single-file/test/fixtures/default.json create mode 100644 test/examples/comps/comp-single-file/test/fixtures/fixture2.json create mode 100644 test/examples/index.js create mode 100644 test/examples/index.marko create mode 100644 test/examples/marko.json create mode 100644 test/fixtures.spec.ts create mode 100644 test/mocha.opts create mode 100644 test/playground.spec.ts create mode 100644 test/routes.spec.ts create mode 100644 test/tslint.json create mode 100644 test/view-model.spec.ts create mode 100644 tsconfig.json create mode 100644 tslint.json create mode 100644 yarn.lock diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3d424c3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,25 @@ +# Created by .ignore support plugin (hsz.mobi) +### Node template +# Logs +logs +*.log +npm-debug.log* + +# Coverage directory used by tools like istanbul +.nyc_output/ +coverage/ + +node_modules + +### JetBrains template +.idea/ +*.iml +*.iws + +# lasso/marko/ts +static/ +.beans/ +.cache/ +*.map +*.marko.js +dist/ diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..c90aebc --- /dev/null +++ b/.npmignore @@ -0,0 +1,20 @@ +### JetBrains template +.idea/ +*.iws + +### Node template +*.log + +# Dependency directories +node_modules/ + +# lasso/marko/ts +static/ +.beans/ +.cache/ +*.map +*.marko.js + +.nycrc +.nyc_output/ +coverage/ diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..e5d3eeb --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +v6.12.1 diff --git a/.nycrc b/.nycrc new file mode 100644 index 0000000..1298cf8 --- /dev/null +++ b/.nycrc @@ -0,0 +1,21 @@ +{ + "extension": [ + ".ts" + ], + "require": [ + "ts-node/register" + ], + "include": [ + "src/**/*.ts" + ], + "exclude": [ + "**/*.d.ts", + "src/logging.ts", + "src/server-config.ts", + "src/start-server.ts" + ], + "reporter": [ + "html" + ], + "all": true +} diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..08b956e --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,11 @@ +The MIT License +SPDX short identifier: MIT + +Further resources on the MIT License +Copyright 2018 eBay Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..bda776d --- /dev/null +++ b/README.md @@ -0,0 +1,147 @@ +# marko-playground + +This project is a development utility for Marko UI components. On launch, it automatically detects all components in your Marko application and allows you to browse through them, rendering all declared use cases or states. +Scenarios can be written in fixtures that represent the backend responses or props from the parent component. +As a result, component development becomes way faster, regression testing easier and visual defects can be spotted early. + +![Marko Playground screenshot](https://user-images.githubusercontent.com/2737310/44096771-5c383430-9fdc-11e8-84fa-4d150f336bab.png) + +## Getting started + +First, add marko-playground to your project by running the following command: + +```bash +yarn add --dev marko-playground +#or +npm i --save-dev marko-playground +``` + +Now you can start the playground via + +```bash +yarn marko-playground +#or +npm run marko-playground +``` + +## Declaring states +When marko-playground detects a UI component, it reads its states from the directory `/test/fixtures`. If no state (or fixture) has been found, it falls back to an empty state and renders the component accordingly. + +Additional states can be defined with the following directory structure (which is also used by [marko-tester](https://github.com/oxala/marko-tester)): + +```json +/test/ + ⤷ fixtures/ + ⤷ default.json + ⤷ another-use-case.json +``` + +### Example of default.json +```json +{ + "viewModel": { + "title": "default title" + } +} +``` + +## Configuration + +The marko-playground tool can be configured by adding a `test/playground/config.json` to your project. +If no file is found, the following default configuration is used instead: + +```js +{ + // Playground will listen on this port, override it with environment variable PORT: + "port": 8080, + + // Widget components will be searched starting from this directory, + // override with COMPONENTS_ROOT_DIR + "componentsRootDir": "./src/components", + + // Widget playground's template will be searched in this directory relative + // to component's directory, override with PLAYGROUND_DIR: + "playgroundDir": "test/playground", + + // Lasso config, override with LASSO_CONFIG indicating local lasso config JSON file: + "lasso": { + "plugins": [ + "lasso-less", + "lasso-marko" + ], + "outputDir": "static", + "bundlingEnabled": false, + "minify": false, + "fingerprintsEnabled": false + } +} +``` + +## Lasso flags support +You can pass flags to lasso page by setting environment variable `FLAGS`, for example: `FLAGS=skin-ds6,mobile` + +## Custom playgrounds +If you don't like the standard component template used in playground, you can use your own. +Simply put it in you component's `test/playground` directory and name it `index.marko` or `template.marko`. +You can always change the location of the template by changing the config property `playgroundDir` or environment variable `PLAYGROUND_DIR`. +[Example](test/examples/comps/comp-multi-file-custom/test/pg/index.marko) + +## Components discovery + +The UI component detection is based on Marko's configuration and respect's the configuration's `tags-dir` and `/renderer` property. + +Usually, you have a `marko.json` in your project (or rely on the defaults which is the `components` directory). The marko file looks like this: +```json +{ + "tags-dir": "./components" +} +``` + +If you have a separate component project, your `marko.json` should look similar to this: +```json +{ + "": { + "renderer": "./component-dir" + } +} +``` + +That file usually resides in the root directory ([marko documentation](https://markojs.com/docs/custom-tags/#markojson-syntax).) + +## Debugging +For more diagnostic messages set environment variable `DEBUG` to truthy value like `DEBUG=1`. + +## Development +Git clone this repo, then install everything: + +```bash +yarn +#or +npm install +``` + +Then start playground with test components: +```bash +yarn start +#or +npm start +``` + +Tests can be executed via: +```bash +yarn test +#or +npm test +``` + +## CI +TBD + +## Licence + +Copyright 2018 eBay Inc. +Developer(s): Timur Manyanov + +Use of this source code is governed by an MIT-style +license that can be found in the LICENSE file or at +https://opensource.org/licenses/MIT. diff --git a/bin/marko-playground.js b/bin/marko-playground.js new file mode 100755 index 0000000..a63d2b5 --- /dev/null +++ b/bin/marko-playground.js @@ -0,0 +1,5 @@ +#!/usr/bin/env node + +'use strict'; + +require('../dist/index.js'); diff --git a/browser.json b/browser.json new file mode 100644 index 0000000..7d2dce5 --- /dev/null +++ b/browser.json @@ -0,0 +1,8 @@ +{ + "dependencies": [ + "./styles/const.less", + "./styles/sidebar.less", + "./styles/comp.less", + "./styles/index.less" + ] +} diff --git a/config/playground.json b/config/playground.json new file mode 100644 index 0000000..0a08a4f --- /dev/null +++ b/config/playground.json @@ -0,0 +1,15 @@ +{ + "port": 8080, + "componentsRootDir": "./src/components", + "playgroundDir": "test/playground", + "lassoConfig": { + "plugins": [ + "lasso-less", + "lasso-marko" + ], + "outputDir": "static", + "bundlingEnabled": false, + "minify": false, + "fingerprintsEnabled": false + } +} \ No newline at end of file diff --git a/marko.json b/marko.json new file mode 100644 index 0000000..5ba30c4 --- /dev/null +++ b/marko.json @@ -0,0 +1,3 @@ +{ + "tags-dir": "./templates" +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..8512751 --- /dev/null +++ b/package.json @@ -0,0 +1,77 @@ +{ + "name": "marko-playground", + "version": "4.22.0", + "description": "Playground for visual testing of Marko components", + "main": "dist/index.js", + "scripts": { + "clean": "rimraf dist templates/*.marko.js test/**/*.marko.js static .cache", + "start": "yarn clean && COMPONENTS_ROOT_DIR=test/examples PLAYGROUND_DIR=test/pg yarn ts-node ./src/index.ts", + "compile": "tsc", + "lint": "tslint ./src/**/*.ts -p .", + "unit-test": "mocha 'test/**/*.spec.ts'", + "test": "yarn lint && yarn unit-test", + "release": "yarn npm_release --auto --auto-fallback minor", + "custom": "yarn clean && yarn compile && git fetch && yarn release", + "precommit": "yarn lint", + "prepush": "yarn test" + }, + "keywords": [ + "marko", + "marko-widgets", + "components", + "playground", + "typescript" + ], + "author": { + "name": "Timur Manyanov", + "email": "tmanyanov@ebay.com" + }, + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/eBay/marko-playground.git" + }, + "dependencies": { + "@lasso/marko-taglib": "^1.0.8", + "chalk": "^2.3.1", + "express": "^4.14.0", + "glob": "^7.1.0", + "lasso": "^3.1.0", + "lasso-less": "^2.4.7", + "lasso-marko": "^2.4.0", + "marko": "^4.7.4" + }, + "devDependencies": { + "@types/async-writer": "^1.4.30", + "@types/chai": "^4.0.10", + "@types/express": "^4.0.39", + "@types/glob": "^5.0.34", + "@types/lasso": "^2.4.0", + "@types/lodash": "^4.14.88", + "@types/marko": "^4.6.0", + "@types/mocha": "^5.0.0", + "@types/node": "^8.0.58", + "@types/sinon": "^5.0.0", + "@types/sinon-chai": "^3.0.0", + "chai": "^4.1.2", + "chai-as-promised": "^7.1.1", + "husky": "^0.14.3", + "mocha": "^5.0.1", + "release-tools": "^2.5.2", + "rimraf": "^2.6.2", + "sinon": "^6.0.0", + "sinon-chai": "^3.0.0", + "source-map-support": "^0.5.6", + "ts-node": "^7", + "tslint": "^5.8.0", + "tslint-config-airbnb": "^5.5.0", + "typescript": "^2.7.2" + }, + "bin": { + "marko-widgets-playground": "bin/marko-playground.js", + "marko-playground": "bin/marko-playground.js" + }, + "engines": { + "node": ">=6.12.1" + } +} diff --git a/src/components.ts b/src/components.ts new file mode 100644 index 0000000..7112470 --- /dev/null +++ b/src/components.ts @@ -0,0 +1,77 @@ +/* + * Copyright 2018 eBay Inc. + * + * Use of this source code is governed by an MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT. + * + */ + +// tslint:disable:no-console + +import { resolve, dirname } from 'path'; +import { buildTaglibLookup } from 'marko/src/compiler'; +import Tag = require('marko/src/compiler/taglib-loader/Tag'); +import { existsSync } from 'fs'; + +export interface Component { + path: string; + render: Render; + tag: Tag; +} + +export type Render = (vm: object, out: any) => void; + +const tagRenderFunc = (rendererPath: string, fromTemplate: boolean = false): Render | Error => { + const renderer = existsSync(rendererPath) ? require(rendererPath) : {}; + const renderProp = fromTemplate ? '_' : 'renderer'; + + const renderFn = renderer.render && renderer.render.bind(renderer); + const rendererFn = renderer[renderProp] && renderer[renderProp].bind(renderer); + + return renderFn || rendererFn || Error(`Error: can't render from "${rendererPath}"`); +}; + +const tagTemplateRenderFunc = (templatePath: string): Render | Error => + tagRenderFunc(templatePath, true); + +const toRenderableComponent = (tag: Tag): Component | Error => { + const renderer = tag.renderer || tag.template; + + if (!renderer) { + return Error(`Error: component "${tag.name}" has neither renderer nor a template.`); + } + + const render = tag.renderer ? tagRenderFunc(tag.renderer) : tagTemplateRenderFunc(tag.template); + + if (render instanceof Error) { + return render; + } + + return { + path: dirname(renderer), + render, + tag + }; +}; + +export default function (componentsRootDir: string = ''): Component[] { + const componentsRootPath = resolve(componentsRootDir); + const notExternal = (tag: Tag): boolean => !tag.dir.includes('node_modules'); + const inSubdirs = (tag: Tag): boolean => tag.dir.includes(componentsRootPath); + const allTags: Tag[] = buildTaglibLookup(componentsRootPath).getTagsSorted(); + const tags: Tag[] = allTags.filter(notExternal).filter(inSubdirs); + + return tags.reduce(renderableComponentsReducer, []); +} + +function renderableComponentsReducer(components: Component[], tag: Tag): Component[] { + const renderableComponent: Component | Error = toRenderableComponent(tag); + + if (renderableComponent instanceof Error) { + console.error(renderableComponent); + return components; + } + + return components.concat(renderableComponent); +} diff --git a/src/config.ts b/src/config.ts new file mode 100644 index 0000000..dcc1706 --- /dev/null +++ b/src/config.ts @@ -0,0 +1,71 @@ +/* + * Copyright 2018 eBay Inc. + * + * Use of this source code is governed by an MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT. + * + */ + +import { join } from 'path'; +const root = process.cwd(); + +const pgConfigDir = process.env.CONFIG_DIR || `test/playground`; +const localConfigRelPath = process.env.CONFIG || join(pgConfigDir, 'config'); +export const app = configWithOverrides( + mergedConfig('./config/playground', localConfigRelPath), + process.env +); + +export const lasso = mergedConfig(app.lassoConfig, app.lassoLocalConfigDir); + +export function mergedConfig(mainConfigOrPath: any, localConfigRelPath: string | undefined = undefined): any { + const mainConfig = + (typeof mainConfigOrPath === 'object') ? mainConfigOrPath : safeRequire(join('..', mainConfigOrPath)); + const localConfig = localConfigRelPath && safeRequire(join(root, localConfigRelPath)); + + return { ...mainConfig, ...localConfig }; +} + +function safeRequire(filePath: string): any { + let result = {}; + + try { + if (require.resolve(filePath)) { + result = require(filePath); + } + } catch (e) { + if (e.code && e.code !== 'MODULE_NOT_FOUND') { + // tslint:disable-next-line:no-console + console.error(e.code); + } + } + + return result; +} + +export interface AppConfig { + port: number; + componentsRootDir: string; + playgroundDir: string; + playgroundConfigDir: string; + lassoLocalConfigDir: string; + lassoConfig: object; + flags: string[]; +} + +export function configWithOverrides(config: AppConfig, env: any): AppConfig { + const playgroundConfigDir = env.CONFIG_DIR || `test/playground`; + const lassoLocalConfigDir = env.LASSO_CONFIG || join(playgroundConfigDir, 'lasso'); + const flags = (env.FLAGS || '').split(','); // todo: add to config + + return { + port: env.PORT || config.port, + componentsRootDir: env.COMPONENTS_ROOT_DIR || config.componentsRootDir, + playgroundDir: env.PLAYGROUND_DIR || config.playgroundDir, + playgroundConfigDir, + lassoLocalConfigDir, + lassoConfig: config.lassoConfig, + flags + }; +} diff --git a/src/dependencies.ts b/src/dependencies.ts new file mode 100644 index 0000000..3c28265 --- /dev/null +++ b/src/dependencies.ts @@ -0,0 +1,67 @@ +import { dirname, join, relative, resolve } from 'path'; +import getComponentFiles = require('marko/src/components/taglib/TransformHelper/getComponentFiles'); +import { existsSync } from 'fs'; +import { Playground } from './playground'; +import { Meta } from './meta'; + +export interface Dependencies { + packagePaths: string[]; + dependencies: string[]; +} +export const noDeps: Dependencies = { + packagePaths: [], + dependencies: [] +}; + +export function allDepsFn(meta: Meta, playgroundConfigDir: string) { + return (playground?: Playground): Dependencies => { + const { packagePaths = [], dependencies = [] } = playground ? componentDependencies(playground) : {}; + + return { + packagePaths: allPackagePaths(meta.appRoot, playgroundConfigDir, packagePaths), + dependencies + }; + }; +} + +function componentDependencies(playground: Playground): Dependencies { + return componentFiles(playground.compRenderer || playground.compTemplate); +} + +export function componentFiles(compRendererPath: string, + getComponentFilesFn: (path: string) => any = getComponentFiles + ): Dependencies { + const resolveToComp = (f: string) => resolve(dirname(compRendererPath), f); + const compFiles: any = getComponentFilesFn(compRendererPath); + const compPackagePaths = (compFiles && compFiles.package) ? [resolveToComp(compFiles.package)] : []; + const compFileList = (compFiles && compFiles.file) ? [resolveToComp(compFiles.file)] : []; + + return { + packagePaths: compPackagePaths, + dependencies: compFiles ? compFiles.styles.map(resolveToComp).concat(compFileList) : [] + }; +} + +function pagePackagePaths(appRoot: string, existsSyncFn: (path: string) => boolean = existsSync): string[] { + const appBrowserPath = join(appRoot, 'browser.json'); + + return [ + '../browser.json', + ...(existsSyncFn(appBrowserPath) ? [ relative(__dirname, appBrowserPath) ] : '') + ]; +} + +export function allPackagePaths(appRoot: string = '', + pgConfigDir: string, + compPackagePaths: any[], + existsSyncFn: (path: string) => boolean = existsSync + ): string[] { + const appCommonPackagePath = join(appRoot, pgConfigDir, 'browser.json'); + const appPackagePaths = existsSyncFn(appCommonPackagePath) ? [ appCommonPackagePath ] : []; + + return [ + ...pagePackagePaths(appRoot, existsSyncFn), + ...appPackagePaths, + ...compPackagePaths + ]; +} diff --git a/src/fixtures.ts b/src/fixtures.ts new file mode 100644 index 0000000..094cf65 --- /dev/null +++ b/src/fixtures.ts @@ -0,0 +1,33 @@ +/* + * Copyright 2018 eBay Inc. + * + * Use of this source code is governed by an MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT. + * + */ + +import * as glob from 'glob'; +import { basename } from 'path'; + +export type Fixtures = { [name: string]: any } | {}; + +export default function (componentPath: string): Fixtures { + const fixtureFilesMask = `${componentPath}/**/fixtures/*.@(js|json)`; + const foundFixtures = findFixtures(fixtureFilesMask); + const defaultFixture = { default: {} }; + + return Object.keys(foundFixtures).length ? foundFixtures : defaultFixture; +} + +function findFixtures(fixtureMask: string): Fixtures { + const globOptions = { absolute: true }; + + return glob.sync(fixtureMask, globOptions).reduce(fixtures, {}); +} + +function fixtures(existingFixtures: Fixtures, newFixtureFilename: string): Fixtures { + const newFixtureName = basename(newFixtureFilename).split('.')[0].replace(/-/g, ' '); + + return { ...{ [newFixtureName]: require(newFixtureFilename) }, ...existingFixtures }; +} diff --git a/src/index.ts b/src/index.ts new file mode 100755 index 0000000..7662d57 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,46 @@ +/* + * Copyright 2018 eBay Inc. + * + * Use of this source code is governed by an MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT. + * + */ + +require('lasso/node-require-no-op').enable('.less', '.css'); + +import componentsInDir, { Component } from './components'; +import routes, { RouteMatch } from './routes'; +import { mergedConfig, AppConfig, app as appConfig, lasso as lassoConfig } from './config'; +import serverConfig from './server-config'; +import startServer from './start-server'; +import { Playground } from './playground'; +import { reportPlaygrounds } from './logging'; +import appMeta, { Meta } from './meta'; +import { allDepsFn } from './dependencies'; + +const { + componentsRootDir, + playgroundDir, + playgroundConfigDir, + port, + lassoLocalConfigDir, + flags }: AppConfig = appConfig; + +const lasso = mergedConfig(lassoConfig, lassoLocalConfigDir); + +const playgrounds: Playground[] = componentsInDir(componentsRootDir).map( + (c: Component) => new Playground(c, playgroundDir) +); + +const meta: Meta = appMeta(); + +const appRoutes: RouteMatch[] = routes( + playgrounds, + allDepsFn(meta, playgroundConfigDir), + meta, + flags); + +reportPlaygrounds(playgrounds, componentsRootDir); + +startServer(serverConfig(port, lasso), appRoutes); diff --git a/src/logging.ts b/src/logging.ts new file mode 100644 index 0000000..919c3fa --- /dev/null +++ b/src/logging.ts @@ -0,0 +1,82 @@ +/* + * Copyright 2018 eBay Inc. + * + * Use of this source code is governed by an MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT. + * + */ + +// tslint:disable:no-console + +import { relative } from 'path'; +import chalk from 'chalk'; +import { ComponentListPageVm, SingleComponentPageVm } from './view-model'; +import { Playground } from './playground'; +import { appRoot } from './meta'; +import { ServerConfig } from './server-config'; + +const compColor = chalk.white.bold; +const fileColor = chalk.white.bold; +const appColor = chalk.white.bold; + +console.debug = (...args: any[]): void => { + if (process.env.DEBUG) { + console.log(chalk.gray('[DEBUG]'), args.join(' ')); + } +}; + +export function reportServerStart(cfg: ServerConfig): void { + console.info(appColor(`Started Playground v${cfg.pgVersion} ` + + `for ${cfg.appName} v${cfg.appVersion} on ${cfg.url}\n`)); +} + +function isSingleComponent(vm: SingleComponentPageVm | ComponentListPageVm): vm is SingleComponentPageVm { + return (vm).componentName !== undefined; +} + +export function reportVmFiles(vm: SingleComponentPageVm | ComponentListPageVm): void { + const pageName = isSingleComponent(vm) ? vm.componentName : 'index'; + + if (vm.packagePaths.length || vm.dependencies.length) { + console.debug(`${compColor(pageName)} packages/dependencies:`); + vm.packagePaths.forEach(console.debug); + vm.dependencies.forEach(console.debug); + } +} + +export function reportPlaygrounds(playgrounds: Playground[], componentsRootDir: string): void { + if (!playgrounds.length) { + const docUrl = `https://github.com/eBay/marko-playground#components-discovery`; + console.info(`No components found in ${fileColor(componentsRootDir)}! Documentation: ${docUrl}`); + return; + } + + console.info(`Components found:`); + + playgrounds.forEach(pg => { + console.info(`${compColor(pg.compName)} @ ${relative(appRoot, pg.compPath)}:`); + + if (pg.compRenderer) { + console.debug(`- using renderer ${fileColor(`./${relative(pg.compPath, pg.compRenderer)}`)}...`); + } + + if (pg.compTemplate) { + console.debug(`- using template ${fileColor(`./${relative(pg.compPath, pg.compTemplate)}`)}...`); + } + + if (pg.customTemplate) { + const templatePath = `./${relative(pg.compPath, pg.customTemplate)}`; + console.debug(`- using custom playground template: ${fileColor(templatePath)}...`); + } + + const fixtureCount = Object.keys(pg.fixtures).length; + + if (fixtureCount) { + console.info(`- using ${fixtureCount} fixtures...`); + } else { + console.error(`Error: no fixtures found for component ` + + `${compColor(pg.compName)} in ${fileColor('test/fixtures')}.`); + } + }); +} diff --git a/src/meta.ts b/src/meta.ts new file mode 100644 index 0000000..2a283b9 --- /dev/null +++ b/src/meta.ts @@ -0,0 +1,46 @@ +/* + * Copyright 2018 eBay Inc. + * + * Use of this source code is governed by an MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT. + * + */ + +import { join } from 'path'; +import { existsSync } from 'fs'; + +export interface Meta { + appRoot?: string; + appName?: string; + appVersion?: string; + pgVersion?: string; +} + +export interface AppMeta { + name: string; + version: string; +} + +export interface PgMeta { + version: string; +} + +export const appRoot = process.cwd(); + +export const pgRoot = join(__dirname, '..'); + +const localPackagePath = join(appRoot, 'package.json'); + +export const appMeta: AppMeta = existsSync(localPackagePath) ? require(localPackagePath) : { name: '', version: '' }; + +export const pgMeta: PgMeta = require(join(pgRoot, 'package.json')); + +export default function(): Meta { + return { + appRoot, + appName: appMeta.name, + appVersion: appMeta.version, + pgVersion: pgMeta.version + }; +} diff --git a/src/playground.ts b/src/playground.ts new file mode 100644 index 0000000..5bba1d3 --- /dev/null +++ b/src/playground.ts @@ -0,0 +1,41 @@ +/* + * Copyright 2018 eBay Inc. + * + * Use of this source code is governed by an MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT. + * + */ + +import * as glob from 'glob'; +import { join } from 'path'; +import fixturesInPath, { Fixtures } from './fixtures'; +import { Component, Render } from './components'; + +export class Playground { + compName: string; + compPath: string; + compRenderer: string; + compTemplate: string; + render: Render; + fixtures: Fixtures; + customTemplate?: string; + + constructor(component: Component, playgroundDir: string = '') { + this.compName = component.tag.name; + this.compPath = component.path; + this.compRenderer = component.tag.renderer; + this.compTemplate = component.tag.template; + this.render = component.render; + this.fixtures = fixturesInPath(component.path); + this.customTemplate = customTemplateInPath(join(component.path, playgroundDir)); + } +} + +export function withFixtures(playground: Playground): boolean { + return Object.keys(playground.fixtures).length > 0; +} + +export function customTemplateInPath(playgroundPath: string = ''): string | undefined { + return glob.sync(`${playgroundPath}/?(index|template).marko`, { absolute: true })[0]; +} diff --git a/src/routes.ts b/src/routes.ts new file mode 100644 index 0000000..0d881c1 --- /dev/null +++ b/src/routes.ts @@ -0,0 +1,85 @@ +/* + * Copyright 2018 eBay Inc. + * + * Use of this source code is governed by an MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT. + * + */ + +import { Request } from 'express'; +import { RequestHandler, Response } from 'marko/express'; +import Template from 'marko/src/runtime/html/Template'; +import 'marko/node-require'; + +import { Meta } from './meta'; +import { Dependencies } from './dependencies'; +import { reportVmFiles } from './logging'; +import { compListVm, pageVm, playgroundVm } from './view-model'; +import { Playground, withFixtures } from './playground'; +import { join } from 'path'; + +export interface RouteMatch { + route: string; + handler: RequestHandler; +} + +export default function ( + playgrounds: Playground[] = [], + allDepsFn: (p?: Playground) => Dependencies, + meta: Meta = {}, + flags: string[] = [] + ): RouteMatch[] { + + const playgroundsWithFixtures: Playground[] = playgrounds.filter(withFixtures); + + const componentNames = playgroundsWithFixtures.map(p => p.compName); + + const indexRouteMatch: RouteMatch = { + route: '/', + handler: componentListHandler(componentNames, allDepsFn(), meta) + }; + + const componentRouteMatches: RouteMatch[] = playgrounds.map(playground => ({ + route: `/${playground.compName}`, + handler: componentHandler( + playground, + componentNames, + allDepsFn(playground), + meta, + flags) + })); + + return [indexRouteMatch].concat(componentRouteMatches); +} + +function componentListHandler(componentNames: string[], + allDeps: Dependencies, + meta: Meta + ): RequestHandler { + const template: Template = require('../templates/mpg-index.marko'); + const vm = pageVm(compListVm(componentNames, allDeps), meta); + + reportVmFiles(vm); + + return (req: Request, res: Response) => res.marko(template, vm); +} + +function componentHandler(playground: Playground, + componentNames: string[], + compDeps: Dependencies, + meta: Meta, + flags: string[] +): RequestHandler { + const genericPlaygroundTemplate = '../templates/mpg-comp.marko'; + const customTemplateRelPath = playground.customTemplate && join('..', playground.customTemplate); + const template: Template = require(customTemplateRelPath || genericPlaygroundTemplate); + + const pgVm = playgroundVm(playground, componentNames, compDeps, flags); + + const vm = pageVm(pgVm, meta); + + reportVmFiles(vm); + + return (req: Request, res: Response) => res.marko(template, vm); +} diff --git a/src/server-config.ts b/src/server-config.ts new file mode 100644 index 0000000..e5a06a9 --- /dev/null +++ b/src/server-config.ts @@ -0,0 +1,32 @@ +/* + * Copyright 2018 eBay Inc. + * + * Use of this source code is governed by an MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT. + * + */ + +import { LassoConfig } from 'lasso/lib/Lasso'; +import { appMeta, pgMeta } from './meta'; + +export interface ServerConfig { + url: string; + port: number; + pgVersion: string; + appVersion: string; + appName: string; + lasso: LassoConfig; +} + +export default function (port: number, lasso: LassoConfig): ServerConfig { + + return { + url: `http://localhost:${port}`, + port, + pgVersion: pgMeta.version, + appVersion: appMeta.version, + appName: appMeta.name, + lasso + }; +} diff --git a/src/start-server.ts b/src/start-server.ts new file mode 100644 index 0000000..9e6da74 --- /dev/null +++ b/src/start-server.ts @@ -0,0 +1,36 @@ +/* + * Copyright 2018 eBay Inc. + * + * Use of this source code is governed by an MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT. + * + */ + +import { reportServerStart } from './logging'; +import express = require('express'); +import markoExpress = require('marko/express'); +import 'marko/node-require'; +import * as lasso from 'lasso'; +import { serveStatic } from 'lasso/middleware'; +import { ServerConfig } from './server-config'; +import { RouteMatch } from './routes'; + +export default function(cfg: ServerConfig, routes: RouteMatch[]): void { + const app = express() as markoExpress.Application; + + lasso.configure(cfg.lasso); + app.use(serveStatic()); + app.use(markoExpress()); + + routes.forEach(({ route, handler }) => app.get(route, handler)); + + app.listen(cfg.port, () => { + reportServerStart(cfg); + + if (process.send) { + // todo: add browser-refresh support + process.send({ event: 'online', url: cfg.url }); + } + }); +} diff --git a/src/view-model.ts b/src/view-model.ts new file mode 100644 index 0000000..e80de4c --- /dev/null +++ b/src/view-model.ts @@ -0,0 +1,61 @@ +/* + * Copyright 2018 eBay Inc. + * + * Use of this source code is governed by an MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT. + * + */ + +import { Fixtures } from './fixtures'; +import { Playground } from './playground'; +import { Meta } from './meta'; +import { Render } from './components'; +import { Dependencies, noDeps } from './dependencies'; + +interface ComponentListVm extends Dependencies { + componentNames: string[]; +} + +export type SingleComponentPageVm = Meta & PlaygroundVm; + +export type ComponentListPageVm = Meta & ComponentListVm; + +export interface PlaygroundVm extends ComponentListVm { + componentName: string; + useCases: Fixtures; + render?: Render; + _?: Render; + flags: string[]; +} + +export function pageVm(additionalVm: PlaygroundVm | ComponentListVm, + meta: Meta = {}): SingleComponentPageVm | ComponentListPageVm { + return { ...meta, ...additionalVm }; +} + +export function compListVm(componentNames: string[] = [], + { packagePaths = [], dependencies = [] }: Dependencies = noDeps + ): ComponentListVm { + return { + componentNames, + packagePaths, + dependencies + }; +} + +export function playgroundVm(playground: Playground, + componentNames: string[], + { packagePaths = [], dependencies = [] }: Dependencies = noDeps, + flags: string[] = [] + ): PlaygroundVm { + return { + componentNames, + componentName: playground.compName, + useCases: playground.fixtures, + render: playground.render, + packagePaths, + dependencies, + flags + }; +} diff --git a/styles/comp.less b/styles/comp.less new file mode 100644 index 0000000..fe1b2b6 --- /dev/null +++ b/styles/comp.less @@ -0,0 +1,84 @@ +/* + * Copyright 2018 eBay Inc. + * + * Use of this source code is governed by an MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT. + * + */ + +.mpg { + padding: 20px; + background: #f0eeec; + + .card { + margin: 1rem 0.5rem; + padding: 0.0625rem 0; + background-color: #fff; + border: 1px solid #cccccc; + border-radius: 2px; + } + + .widget .card { + box-sizing: content-box; + position: relative; + margin: 0; + padding: 0; + width: 100%; + min-height: 256px; + } + + &-main { + position: absolute; + top: 0; + bottom: 0; + left: 22em; + right: 1em; + } + + &-component-use-case { + > h2 { + margin-top: 1em; + margin-bottom: 0.3em; + color: @mpg-color; + font-family: @mpg-font-family; + font-size: @mpg-font-size-h2; + font-weight: @mpg-font-weight-h2; + + &:first-letter { + text-transform: capitalize; + } + } + + > .widget-container { + > .widget { + > .card { + margin-bottom: 1em; + } + + > details { + color: @mpg-color; + font-family: @mpg-font-family; + font-size: @mpg-font-size; + + summary:hover { + cursor: pointer; + } + pre { + overflow: scroll; + max-height: 30em; + } + } + } + + > .widget-1-col { + min-width: 450px; + } + + > .widget-minimal > .card { + min-height: 0; + } + } + } + +} diff --git a/styles/const.less b/styles/const.less new file mode 100644 index 0000000..4d21d79 --- /dev/null +++ b/styles/const.less @@ -0,0 +1,17 @@ +/* + * Copyright 2018 eBay Inc. + * + * Use of this source code is governed by an MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT. + * + */ + +@mpg-color: #333; +@mpg-font-size: 0.875rem; +@mpg-font-family: "Helvetica Neue", Helvetica, Arial, Roboto, sans-serif; + +@mpg-font-weight-h1: 200; +@mpg-font-size-h1: 1.5rem; +@mpg-font-weight-h2: 400; +@mpg-font-size-h2: 1.25rem; diff --git a/styles/index.less b/styles/index.less new file mode 100644 index 0000000..fffe112 --- /dev/null +++ b/styles/index.less @@ -0,0 +1,90 @@ +/* + * Copyright 2018 eBay Inc. + * + * Use of this source code is governed by an MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT. + * + */ + +.mpg-home { + padding: 1em 0; + min-width: 35em; + color: @mpg-color; + font-family: @mpg-font-family; + font-size: @mpg-font-size; + + > .card--primary { + display: flex; + flex-direction: column; + align-items: center; + margin: 0; + } + + &-card__cell { + padding-left: 1em; + padding-bottom: 1em; + } + + section { + margin-bottom: 2em; + } + + h3 { + margin-bottom: 0.3em; + } + + h4 { + margin: 1.5em 0 0.4em; + } + + &-links { + margin: 0; + padding: 0; + list-style: none; + + li { + padding: 0.3em 0; + line-height: 1.5em; + } + + a { + vertical-align: middle; + + &.with-icon { + text-decoration: none; + + svg, + img { + position: absolute; + margin-top: 5px; + margin-left: -21px; + height: 16px; + + &.github { + width: 16px; + } + &.marko { + margin-left: -30px; + height: 14px; + } + } + + span { + text-decoration: underline; + } + } + } + } + + &-news { + margin: 0 0 0 -0.5em; + padding: 0; + + li { + padding: 0.3em 0 0.3em 0.5em; + line-height: 1.5em; + list-style-type: '\2014'; + } + } +} diff --git a/styles/sidebar.less b/styles/sidebar.less new file mode 100644 index 0000000..40f4606 --- /dev/null +++ b/styles/sidebar.less @@ -0,0 +1,58 @@ +/* + * Copyright 2018 eBay Inc. + * + * Use of this source code is governed by an MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT. + * + */ + +.mpg-sidebar { + position: fixed; + overflow: scroll; + top: 0; + bottom: 0; + left: 1em; + width: 20em; + font-family: @mpg-font-family; + font-size: @mpg-font-size; +} + +.mpg-component-list { + font-family: @mpg-font-family; + font-size: @mpg-font-size; + margin: 0; + padding-left: 0; + list-style: none; + + &-item { + padding: 0.5em 0; + font-size: @mpg-font-size; + + a, + a:visited { + text-decoration: underline; + color: blue; + } + } +} + +.mpg-home-link, +.mpg-home-link:visited { + font-family: @mpg-font-family; + font-size: @mpg-font-size; + display: inline-block; + margin-bottom: 0.8em; + color: @mpg-color; + text-decoration: none; + + &:hover { + text-decoration: underline; + } +} + +.mpg-h1 { + margin: 0.5em 0 0.3em; + font-size: @mpg-font-size-h1; + font-weight: @mpg-font-weight-h1; +} diff --git a/templates/mpg-comp.marko b/templates/mpg-comp.marko new file mode 100644 index 0000000..c33babc --- /dev/null +++ b/templates/mpg-comp.marko @@ -0,0 +1,32 @@ + + + <@sidebar> + + + + + + <@body> + + +

${caseName}

+ + + + $ input.render(caseData, out) + + +
+ Fixture +
${JSON.stringify(caseData, null, 2)}
+
+ + + + + +
diff --git a/templates/mpg-index.marko b/templates/mpg-index.marko new file mode 100644 index 0000000..16b76f5 --- /dev/null +++ b/templates/mpg-index.marko @@ -0,0 +1,75 @@ + + + <@sidebar> + + + + + + <@body> + + + + +

Marko Playground v${input.pgVersion}

+ +
+ +
  • + + + + + Sources, documentation & issues + +
  • +
  • + + + Marko 4 + +
  • + +
    + +
    +

    Changes

    + +

    v.4.22

    + +
  • Support custom playground templates
  • + + +

    v.4.19

    + +
  • Lasso flags support
  • + + +

    v.4.12

    + +
  • Auto-discover of `browser.json` on app root level by @gryshkov
  • + + +

    v.4.7

    + +
  • Use default empty fixture if none exists
  • + + +

    v.4.6.1

    + +
  • [fix] Renamed templates to avoid conflicts with apps
  • + + +

    v.4

    + +
  • Rewritten in Typescript (nothing's changed for end-users)
  • +
  • Basic Marko 4 support
  • + +
    + + + + +
    diff --git a/templates/mpg-sidebar.marko b/templates/mpg-sidebar.marko new file mode 100644 index 0000000..169e15c --- /dev/null +++ b/templates/mpg-sidebar.marko @@ -0,0 +1,14 @@ +$ const { componentNames, appName, appVersion } = input + + + Marko Playground + for ${appName} v${appVersion} + + + + + + ${componentName} + + + diff --git a/templates/mpg-site-layout.marko b/templates/mpg-site-layout.marko new file mode 100644 index 0000000..add8142 --- /dev/null +++ b/templates/mpg-site-layout.marko @@ -0,0 +1,19 @@ + + + + + + + Marko Playground + + + + + + + diff --git a/test/components.spec.ts b/test/components.spec.ts new file mode 100644 index 0000000..c57901a --- /dev/null +++ b/test/components.spec.ts @@ -0,0 +1,37 @@ +/* + * Copyright 2018 eBay Inc. + * + * Use of this source code is governed by an MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT. + * + */ + +import 'marko/node-require'; +import { expect } from 'chai'; +import { resolve } from 'path'; +import components from '../src/components'; + +const timeout = 5000; +const expectedComps: any[] = require('./data/expected-comps'); +const expectedCompNames = expectedComps.map(c => c.name); +const expectedCompPaths = expectedComps.map(c => resolve(c.dir)); + +describe('components (integration)', () => { + describe('given no root dir', () => { + it('should find all components in current dir subdirs', () => { + const foundComponents = components(); + + expect(foundComponents.length).to.equal(4); + }).timeout(timeout); + }); + + describe('given root dir', () => { + it('should find all components in subdirs', () => { + const foundComponents = components('./test/examples'); + + expect(foundComponents.map(c => c.tag.name)).to.have.same.members(expectedCompNames); + expect(foundComponents.map(c => c.path)).to.have.same.members(expectedCompPaths); + }).timeout(timeout); + }); +}); diff --git a/test/config.spec.ts b/test/config.spec.ts new file mode 100644 index 0000000..2b3597b --- /dev/null +++ b/test/config.spec.ts @@ -0,0 +1,65 @@ +/* + * Copyright 2018 eBay Inc. + * + * Use of this source code is governed by an MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT. + * + */ + +import { expect } from 'chai'; +import { mergedConfig } from '../src/config'; + +describe('mergedConfig', () => { + [ + { + should: 'should return empty object if config file not exists', + mainConfigOrPath: 'not/existing/path', + localConfigPath: undefined, + expectedConfigPath: undefined + }, + { + should: 'should return config object if config file exists', + mainConfigOrPath: './test/data/config', + localConfigPath: undefined, + expectedConfigPath: './data/config' + }, + { + should: 'should return config object if main config file exists, but not local one', + mainConfigOrPath: './test/data/config', + localConfigPath: 'not/existing', + expectedConfigPath: './data/config' + }, + { + should: 'should return local config object if only local config file exists', + mainConfigOrPath: 'not/existing/path', + localConfigPath: './test/data/localConfig', + expectedConfigPath: './data/localConfig' + }, + { + should: 'should return combined config object if both main and local config exist', + mainConfigOrPath: './test/data/config', + localConfigPath: './test/data/localConfig', + expectedConfigPath: './data/combinedConfig' + }, + { + should: 'should return combined config if main config is passed instead of path and local config exist', + mainConfigOrPath: require('./data/config'), + localConfigPath: './test/data/localConfig', + expectedConfigPath: './data/combinedConfig' + }, + { + should: 'should return overridden config object if both main and local config exist', + mainConfigOrPath: './test/data/config', + localConfigPath: './test/data/localConfigOverride', + expectedConfigPath: './data/localConfigOverride' + } + ].forEach(opts => { + it(opts.should, () => { + const config = mergedConfig(opts.mainConfigOrPath, opts.localConfigPath); + const expectedConfig = opts.expectedConfigPath ? require(opts.expectedConfigPath) : {}; + + expect(config).to.deep.equal(expectedConfig); + }); + }); +}); diff --git a/test/data/combinedConfig.json b/test/data/combinedConfig.json new file mode 100644 index 0000000..a9a72f6 --- /dev/null +++ b/test/data/combinedConfig.json @@ -0,0 +1,6 @@ +{ + "foo": { + "bar": "baz" + }, + "another": true +} diff --git a/test/data/config.json b/test/data/config.json new file mode 100644 index 0000000..faa9156 --- /dev/null +++ b/test/data/config.json @@ -0,0 +1,5 @@ +{ + "foo": { + "bar": "baz" + } +} diff --git a/test/data/expected-comps.json b/test/data/expected-comps.json new file mode 100644 index 0000000..78e209e --- /dev/null +++ b/test/data/expected-comps.json @@ -0,0 +1,32 @@ +[ + { + "name": "comp-single-file-browser-json", + "dir": "./test/examples/comps/comp-single-file-browser-json", + "pgTemplate": "./templates/mpg-comp.marko.js" + }, + { + "name": "comp-single-file", + "dir": "./test/examples/comps/comp-single-file", + "pgTemplate": "./templates/mpg-comp.marko.js" + }, + { + "name": "comp-multi-file", + "dir": "./test/examples/comps/comp-multi-file", + "pgTemplate": "./templates/mpg-comp.marko.js" + }, + { + "name": "comp-multi-file-custom", + "dir": "./test/examples/comps/comp-multi-file-custom", + "pgTemplate": "./test/examples/comps/comp-multi-file-custom/test/pg/index.marko.js" + }, + { + "name": "comp-multi-file-browser-json", + "dir": "./test/examples/comps/comp-multi-file-browser-json", + "pgTemplate": "./templates/mpg-comp.marko.js" + }, + { + "name": "comp-single-file-no-fixtures", + "dir": "./test/examples/comps/comp-single-file-no-fixtures", + "pgTemplate": "./templates/mpg-comp.marko.js" + } +] diff --git a/test/data/fixtures.json b/test/data/fixtures.json new file mode 100644 index 0000000..36328c2 --- /dev/null +++ b/test/data/fixtures.json @@ -0,0 +1,8 @@ +{ + "default": { + "name": "Frank" + }, + "fixture2": { + "foo": "bar" + } +} \ No newline at end of file diff --git a/test/data/localConfig.json b/test/data/localConfig.json new file mode 100644 index 0000000..4e8a879 --- /dev/null +++ b/test/data/localConfig.json @@ -0,0 +1,3 @@ +{ + "another": true +} diff --git a/test/data/localConfigOverride.json b/test/data/localConfigOverride.json new file mode 100644 index 0000000..c353e67 --- /dev/null +++ b/test/data/localConfigOverride.json @@ -0,0 +1,3 @@ +{ + "foo": false +} diff --git a/test/data/mock-comps.ts b/test/data/mock-comps.ts new file mode 100644 index 0000000..463c04a --- /dev/null +++ b/test/data/mock-comps.ts @@ -0,0 +1,20 @@ +/* + * Copyright 2018 eBay Inc. + * + * Use of this source code is governed by an MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT. + * + */ + +import { Component } from '../../src/components'; +import Tag = require('marko/src/compiler/taglib-loader/Tag'); + +const tag = new Tag('./some-component'); +tag.name = 'some-component'; + +export const mockComps: Component[] = [{ + path: './some-component', + render: () => {}, + tag +}]; diff --git a/test/data/mock-pgs.ts b/test/data/mock-pgs.ts new file mode 100644 index 0000000..0a74825 --- /dev/null +++ b/test/data/mock-pgs.ts @@ -0,0 +1,30 @@ +/* + * Copyright 2018 eBay Inc. + * + * Use of this source code is governed by an MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT. + * + */ + +import { Playground } from '../../src/playground'; + +export const mockPgs: Playground[] = [ + { + compName: 'some-component1', + compPath: './some-component1', + compRenderer: './some-renderer1', + render: () => {}, + compTemplate: './some-component1/template', + fixtures: require('./fixtures') + }, + { + compName: 'some-component2', + compPath: './some-component2', + compRenderer: './some-renderer2', + render: () => {}, + compTemplate: './some-component2/template', + customTemplate: './test/examples/comps/comp-multi-file-custom/test/pg/index.marko.js', + fixtures: require('./fixtures') + } +]; diff --git a/test/dependencies/all-package-paths.spec.ts b/test/dependencies/all-package-paths.spec.ts new file mode 100644 index 0000000..2c52e55 --- /dev/null +++ b/test/dependencies/all-package-paths.spec.ts @@ -0,0 +1,63 @@ +/* + * Copyright 2018 eBay Inc. + * + * Use of this source code is governed by an MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT. + * + */ + +import { expect } from 'chai'; +import { allPackagePaths } from '../../src/dependencies'; + +describe('allPackagePaths()', () => { + describe('given no additional dependencies', () => { + it('should return only playground app `browser.json`', () => { + const mockExistsSync = () => false; + const expected: string[] = [ + '../browser.json' + ]; + + expect(allPackagePaths('', '', [],mockExistsSync)).to.deep.equal(expected); + }); + }); + + describe('given additional app dependencies', () => { + it('should return them all', () => { + const appDep = 'app-root/browser.json'; + const mockExistsSync = (path: string) => path === appDep; + const expected: string[] = [ + '../browser.json', + `../${appDep}` + ]; + + expect(allPackagePaths('app-root', 'pg-config-dir', [],mockExistsSync)).to.deep.equal(expected); + }); + }); + + describe('given additional playground dependencies', () => { + it('should return them all', () => { + const pgDep = 'app-root/pg-config-dir/browser.json'; + const mockExistsSync = (path: string) => path === pgDep; + const expected: string[] = [ + '../browser.json', + pgDep + ]; + + expect(allPackagePaths('app-root', 'pg-config-dir', [],mockExistsSync)).to.deep.equal(expected); + }); + }); + + describe('given all kinds of additional dependencies', () => { + it('should return them all', () => { + const mockExistsSync = () => true; + const expected: string[] = [ + '../browser.json', + '../app-root/browser.json', + 'app-root/pg-config-dir/browser.json' + ]; + + expect(allPackagePaths('app-root', 'pg-config-dir', [],mockExistsSync)).to.deep.equal(expected); + }); + }); +}); diff --git a/test/dependencies/component-files.spec.ts b/test/dependencies/component-files.spec.ts new file mode 100644 index 0000000..cd4f4fc --- /dev/null +++ b/test/dependencies/component-files.spec.ts @@ -0,0 +1,86 @@ +/* + * Copyright 2018 eBay Inc. + * + * Use of this source code is governed by an MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT. + * + */ + +import { expect } from 'chai'; +import { componentFiles, Dependencies } from '../../src/dependencies'; +import { resolve } from 'path'; + +describe('componentFiles()', () => { + describe('given no component files found', () => { + it('should return empty dependencies', () => { + const mockGetComponentFiles = () => {}; + const expected: Dependencies = { + packagePaths: [], + dependencies: [] + }; + + expect(componentFiles('', mockGetComponentFiles)).to.deep.equal(expected); + }); + }); + + describe('given component package found', () => { + it('should return that package within dependencies', () => { + const mockGetComponentFiles = () => ({ + package: 'some-package', + styles: [] + }); + const expected: Dependencies = { + packagePaths: [ resolve('some-package') ], + dependencies: [] + }; + + expect(componentFiles('', mockGetComponentFiles)).to.deep.equal(expected); + }); + }); + + describe('given component file found', () => { + it('should return that file within dependencies', () => { + const mockGetComponentFiles = () => ({ + file: 'some-file', + styles: [] + }); + const expected: Dependencies = { + packagePaths: [], + dependencies: [ resolve('some-file') ] + }; + + expect(componentFiles('', mockGetComponentFiles)).to.deep.equal(expected); + }); + }); + + describe('given component styles found', () => { + it('should return that styles within dependencies', () => { + const mockGetComponentFiles = () => ({ + styles: [ 'some-styles' ] + }); + const expected: Dependencies = { + packagePaths: [], + dependencies: [ resolve('some-styles') ] + }; + + expect(componentFiles('', mockGetComponentFiles)).to.deep.equal(expected); + }); + }); + + describe('given component dependencies found', () => { + it('should return that dependencies', () => { + const mockGetComponentFiles = () => ({ + package: 'some-package', + file: 'some-file', + styles: [ 'some-styles' ] + }); + const expected: Dependencies = { + packagePaths: [ resolve('some-package') ], + dependencies: [ resolve('some-styles'), resolve('some-file') ] + }; + + expect(componentFiles('', mockGetComponentFiles)).to.deep.equal(expected); + }); + }); +}); diff --git a/test/examples/comps/comp-multi-file-browser-json/browser.json b/test/examples/comps/comp-multi-file-browser-json/browser.json new file mode 100644 index 0000000..8c6c785 --- /dev/null +++ b/test/examples/comps/comp-multi-file-browser-json/browser.json @@ -0,0 +1,6 @@ +{ + "dependencies": [ + "style.less", + "component.js" + ] +} diff --git a/test/examples/comps/comp-multi-file-browser-json/component.js b/test/examples/comps/comp-multi-file-browser-json/component.js new file mode 100644 index 0000000..dcbba69 --- /dev/null +++ b/test/examples/comps/comp-multi-file-browser-json/component.js @@ -0,0 +1,22 @@ +/* + * Copyright 2018 eBay Inc. + * + * Use of this source code is governed by an MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT. + * + */ + +module.exports = { + onCreate() { + this.state = { + count: 0 + } + }, + onMount() { + console.log('Mounted in the browser!'); + }, + increment() { + this.state.count++; + } +}; diff --git a/test/examples/comps/comp-multi-file-browser-json/index.marko b/test/examples/comps/comp-multi-file-browser-json/index.marko new file mode 100644 index 0000000..9f749b1 --- /dev/null +++ b/test/examples/comps/comp-multi-file-browser-json/index.marko @@ -0,0 +1,9 @@ +

    Hello ${input.name}

    + + + ${state.count} + + + + Click me + diff --git a/test/examples/comps/comp-multi-file-browser-json/style.less b/test/examples/comps/comp-multi-file-browser-json/style.less new file mode 100644 index 0000000..425b151 --- /dev/null +++ b/test/examples/comps/comp-multi-file-browser-json/style.less @@ -0,0 +1,17 @@ +/* + * Copyright 2018 eBay Inc. + * + * Use of this source code is governed by an MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT. + * + */ + +.count { + color:#09c; + font-size:3em; +} +.example-button { + font-size:1em; + padding:0.5em; +} diff --git a/test/examples/comps/comp-multi-file-browser-json/test/fixtures/default.json b/test/examples/comps/comp-multi-file-browser-json/test/fixtures/default.json new file mode 100644 index 0000000..50aeae5 --- /dev/null +++ b/test/examples/comps/comp-multi-file-browser-json/test/fixtures/default.json @@ -0,0 +1,3 @@ +{ + "name": "Frank" +} \ No newline at end of file diff --git a/test/examples/comps/comp-multi-file-browser-json/test/fixtures/fixture2.json b/test/examples/comps/comp-multi-file-browser-json/test/fixtures/fixture2.json new file mode 100644 index 0000000..b42f309 --- /dev/null +++ b/test/examples/comps/comp-multi-file-browser-json/test/fixtures/fixture2.json @@ -0,0 +1,3 @@ +{ + "foo": "bar" +} \ No newline at end of file diff --git a/test/examples/comps/comp-multi-file-custom/component.js b/test/examples/comps/comp-multi-file-custom/component.js new file mode 100644 index 0000000..dcbba69 --- /dev/null +++ b/test/examples/comps/comp-multi-file-custom/component.js @@ -0,0 +1,22 @@ +/* + * Copyright 2018 eBay Inc. + * + * Use of this source code is governed by an MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT. + * + */ + +module.exports = { + onCreate() { + this.state = { + count: 0 + } + }, + onMount() { + console.log('Mounted in the browser!'); + }, + increment() { + this.state.count++; + } +}; diff --git a/test/examples/comps/comp-multi-file-custom/index.marko b/test/examples/comps/comp-multi-file-custom/index.marko new file mode 100644 index 0000000..9f749b1 --- /dev/null +++ b/test/examples/comps/comp-multi-file-custom/index.marko @@ -0,0 +1,9 @@ +

    Hello ${input.name}

    + + + ${state.count} + + + + Click me + diff --git a/test/examples/comps/comp-multi-file-custom/style.less b/test/examples/comps/comp-multi-file-custom/style.less new file mode 100644 index 0000000..425b151 --- /dev/null +++ b/test/examples/comps/comp-multi-file-custom/style.less @@ -0,0 +1,17 @@ +/* + * Copyright 2018 eBay Inc. + * + * Use of this source code is governed by an MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT. + * + */ + +.count { + color:#09c; + font-size:3em; +} +.example-button { + font-size:1em; + padding:0.5em; +} diff --git a/test/examples/comps/comp-multi-file-custom/test/fixtures/default.json b/test/examples/comps/comp-multi-file-custom/test/fixtures/default.json new file mode 100644 index 0000000..50aeae5 --- /dev/null +++ b/test/examples/comps/comp-multi-file-custom/test/fixtures/default.json @@ -0,0 +1,3 @@ +{ + "name": "Frank" +} \ No newline at end of file diff --git a/test/examples/comps/comp-multi-file-custom/test/fixtures/fixture2.json b/test/examples/comps/comp-multi-file-custom/test/fixtures/fixture2.json new file mode 100644 index 0000000..b42f309 --- /dev/null +++ b/test/examples/comps/comp-multi-file-custom/test/fixtures/fixture2.json @@ -0,0 +1,3 @@ +{ + "foo": "bar" +} \ No newline at end of file diff --git a/test/examples/comps/comp-multi-file-custom/test/pg/index.marko b/test/examples/comps/comp-multi-file-custom/test/pg/index.marko new file mode 100644 index 0000000..8d4c900 --- /dev/null +++ b/test/examples/comps/comp-multi-file-custom/test/pg/index.marko @@ -0,0 +1,34 @@ + + + <@sidebar> + + + + + + <@body> + + +

    ${caseName} - custom playground

    + + + +

    This is a custom playground template

    + + + + +
    + Fixture +
    ${JSON.stringify(caseData, null, 2)}
    +
    + + + + + +
    diff --git a/test/examples/comps/comp-multi-file/component.js b/test/examples/comps/comp-multi-file/component.js new file mode 100644 index 0000000..dcbba69 --- /dev/null +++ b/test/examples/comps/comp-multi-file/component.js @@ -0,0 +1,22 @@ +/* + * Copyright 2018 eBay Inc. + * + * Use of this source code is governed by an MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT. + * + */ + +module.exports = { + onCreate() { + this.state = { + count: 0 + } + }, + onMount() { + console.log('Mounted in the browser!'); + }, + increment() { + this.state.count++; + } +}; diff --git a/test/examples/comps/comp-multi-file/index.marko b/test/examples/comps/comp-multi-file/index.marko new file mode 100644 index 0000000..9f749b1 --- /dev/null +++ b/test/examples/comps/comp-multi-file/index.marko @@ -0,0 +1,9 @@ +

    Hello ${input.name}

    + + + ${state.count} + + + + Click me + diff --git a/test/examples/comps/comp-multi-file/style.less b/test/examples/comps/comp-multi-file/style.less new file mode 100644 index 0000000..425b151 --- /dev/null +++ b/test/examples/comps/comp-multi-file/style.less @@ -0,0 +1,17 @@ +/* + * Copyright 2018 eBay Inc. + * + * Use of this source code is governed by an MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT. + * + */ + +.count { + color:#09c; + font-size:3em; +} +.example-button { + font-size:1em; + padding:0.5em; +} diff --git a/test/examples/comps/comp-multi-file/test/fixtures/default.json b/test/examples/comps/comp-multi-file/test/fixtures/default.json new file mode 100644 index 0000000..50aeae5 --- /dev/null +++ b/test/examples/comps/comp-multi-file/test/fixtures/default.json @@ -0,0 +1,3 @@ +{ + "name": "Frank" +} \ No newline at end of file diff --git a/test/examples/comps/comp-multi-file/test/fixtures/fixture2.json b/test/examples/comps/comp-multi-file/test/fixtures/fixture2.json new file mode 100644 index 0000000..b42f309 --- /dev/null +++ b/test/examples/comps/comp-multi-file/test/fixtures/fixture2.json @@ -0,0 +1,3 @@ +{ + "foo": "bar" +} \ No newline at end of file diff --git a/test/examples/comps/comp-single-file-browser-json/browser.json b/test/examples/comps/comp-single-file-browser-json/browser.json new file mode 100644 index 0000000..c3512df --- /dev/null +++ b/test/examples/comps/comp-single-file-browser-json/browser.json @@ -0,0 +1,5 @@ +{ + "dependencies": [ + "index.marko" + ] +} diff --git a/test/examples/comps/comp-single-file-browser-json/index.marko b/test/examples/comps/comp-single-file-browser-json/index.marko new file mode 100644 index 0000000..53df25d --- /dev/null +++ b/test/examples/comps/comp-single-file-browser-json/index.marko @@ -0,0 +1,34 @@ +class { + onCreate() { + this.state = { + count: 0 + } + } + onMount() { + console.log('Mounted in the browser!'); + } + increment() { + this.state.count++; + } +} + +style { + .count { + color:#09c; + font-size:3em; + } + .example-button { + font-size:1em; + padding:0.5em; + } +} + +

    Hello ${input.name}

    + + + ${state.count} + + + + Click me + diff --git a/test/examples/comps/comp-single-file-browser-json/test/fixtures/default.json b/test/examples/comps/comp-single-file-browser-json/test/fixtures/default.json new file mode 100644 index 0000000..50aeae5 --- /dev/null +++ b/test/examples/comps/comp-single-file-browser-json/test/fixtures/default.json @@ -0,0 +1,3 @@ +{ + "name": "Frank" +} \ No newline at end of file diff --git a/test/examples/comps/comp-single-file-browser-json/test/fixtures/fixture2.json b/test/examples/comps/comp-single-file-browser-json/test/fixtures/fixture2.json new file mode 100644 index 0000000..b42f309 --- /dev/null +++ b/test/examples/comps/comp-single-file-browser-json/test/fixtures/fixture2.json @@ -0,0 +1,3 @@ +{ + "foo": "bar" +} \ No newline at end of file diff --git a/test/examples/comps/comp-single-file-no-fixtures/index.marko b/test/examples/comps/comp-single-file-no-fixtures/index.marko new file mode 100644 index 0000000..ec1910e --- /dev/null +++ b/test/examples/comps/comp-single-file-no-fixtures/index.marko @@ -0,0 +1,34 @@ +class { + onCreate() { + this.state = { + count: 0 + } + } + onMount() { + console.log('Mounted in the browser!'); + } + increment() { + this.state.count++; + } +} + +style { + .count { + color:#09c; + font-size:3em; + } + .example-button { + font-size:1em; + padding:0.5em; + } +} + +

    Component without fixtures set up

    + + + ${state.count} + + + + Click me + diff --git a/test/examples/comps/comp-single-file/index.marko b/test/examples/comps/comp-single-file/index.marko new file mode 100644 index 0000000..53df25d --- /dev/null +++ b/test/examples/comps/comp-single-file/index.marko @@ -0,0 +1,34 @@ +class { + onCreate() { + this.state = { + count: 0 + } + } + onMount() { + console.log('Mounted in the browser!'); + } + increment() { + this.state.count++; + } +} + +style { + .count { + color:#09c; + font-size:3em; + } + .example-button { + font-size:1em; + padding:0.5em; + } +} + +

    Hello ${input.name}

    + + + ${state.count} + + + + Click me + diff --git a/test/examples/comps/comp-single-file/test/fixtures/default.json b/test/examples/comps/comp-single-file/test/fixtures/default.json new file mode 100644 index 0000000..50aeae5 --- /dev/null +++ b/test/examples/comps/comp-single-file/test/fixtures/default.json @@ -0,0 +1,3 @@ +{ + "name": "Frank" +} \ No newline at end of file diff --git a/test/examples/comps/comp-single-file/test/fixtures/fixture2.json b/test/examples/comps/comp-single-file/test/fixtures/fixture2.json new file mode 100644 index 0000000..b42f309 --- /dev/null +++ b/test/examples/comps/comp-single-file/test/fixtures/fixture2.json @@ -0,0 +1,3 @@ +{ + "foo": "bar" +} \ No newline at end of file diff --git a/test/examples/index.js b/test/examples/index.js new file mode 100644 index 0000000..7985bb2 --- /dev/null +++ b/test/examples/index.js @@ -0,0 +1,55 @@ +/* + * Copyright 2018 eBay Inc. + * + * Use of this source code is governed by an MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT. + * + */ + +require('marko/node-require'); // Allow Node.js to require and load `.marko` files + +var express = require('express'); +var markoExpress = require('marko/express'); +var template = require('./index.marko'); +var comp = require('./comps/comp-multi-file'); + +var app = express(); + +app.use(markoExpress()); //enable res.marko(template, data) + +app.use(require('lasso/middleware').serveStatic()); +require('lasso').configure({ + plugins: [ + 'lasso-marko' // Allow Marko templates to be compiled and transported to the browser + ], + outputDir: 'static', // Place all generated JS/CSS/etc. files into the "static" dir + bundlingEnabled: false, + minify: false, + fingerprintsEnabled: false +}); + +app.get('/', function (req, res) { + // comp + // .renderSync({}) + // .appendTo(document.body); + + const options = { + pageName: 'test', + packagePath: require('path').join(process.cwd(), './test/examples/comps/comp-single-file/index.marko') + }; + + require('lasso').getDefaultLasso().lassoPage(options).then(result => { + console.log('Lasso:', result.getOutputFiles()); + }); + + res.marko(template, { + name: 'Frank', + count: 30, + colors: ['red', 'green', 'blue'], + comp: comp + }); + +}); + +app.listen(8000); diff --git a/test/examples/index.marko b/test/examples/index.marko new file mode 100644 index 0000000..ca8910a --- /dev/null +++ b/test/examples/index.marko @@ -0,0 +1,21 @@ + + + + + marko-express + + +

    You have ${data.count} new messages!

    +
      +
    • ${color}
    • +
    + + $ { + //const includeTag = require('marko/src/taglibs/core/include-tag'); + data.comp.render(data, out) + //includeTag(data, out); + //includeTag({ _target: data.comp }, out); + } + + + \ No newline at end of file diff --git a/test/examples/marko.json b/test/examples/marko.json new file mode 100644 index 0000000..7729574 --- /dev/null +++ b/test/examples/marko.json @@ -0,0 +1,3 @@ +{ + "tags-dir": "./comps" +} diff --git a/test/fixtures.spec.ts b/test/fixtures.spec.ts new file mode 100644 index 0000000..fb0fe36 --- /dev/null +++ b/test/fixtures.spec.ts @@ -0,0 +1,32 @@ +/* + * Copyright 2018 eBay Inc. + * + * Use of this source code is governed by an MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT. + * + */ + +import { resolve } from 'path'; +import { expect } from 'chai'; +import fixtures from '../src/fixtures'; + +describe('fixtures()', () => { + describe('given component with fixtures', () => { + it('should find all fixtures', () => { + const compFixtures = fixtures(resolve('./test/examples/comps/comp-single-file')); + const expectedFixtures = require('./data/fixtures'); + + expect(compFixtures).to.deep.equal(expectedFixtures); + }); + }); + + describe('given component without fixtures', () => { + it('should create a default empty fixture', () => { + const compFixtures = fixtures(resolve('./test/examples/comps/comp-single-file-no-fixtures')); + const expectedFixtures = { default: {} }; + + expect(compFixtures).to.deep.equal(expectedFixtures); + }); + }); +}); diff --git a/test/mocha.opts b/test/mocha.opts new file mode 100644 index 0000000..1ad1795 --- /dev/null +++ b/test/mocha.opts @@ -0,0 +1,8 @@ +--ui bdd +--reporter spec +--timeout 1000 +--inline-diffs +--colors +--recursive +--require ts-node/register +--require source-map-support/register diff --git a/test/playground.spec.ts b/test/playground.spec.ts new file mode 100644 index 0000000..d049fbb --- /dev/null +++ b/test/playground.spec.ts @@ -0,0 +1,41 @@ +/* + * Copyright 2018 eBay Inc. + * + * Use of this source code is governed by an MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT. + * + */ + +import { resolve } from 'path'; +import { expect } from 'chai'; +import { customTemplateInPath } from '../src/playground'; + +describe('playground (integration)', () => { + describe('given component without custom playground', () => { + it('should return undefined', () => { + expect(customTemplateInPath()).to.equal(undefined); + }); + }); + + describe('given component with custom playground', () => { + describe('given no path', () => { + it('should return a custom playground template', () => { + const playground = customTemplateInPath(); + const expectedPlayground = undefined; + + expect(playground).to.equal(expectedPlayground); + }); + }); + + describe('given playground path', () => { + it('should return path to its template', () => { + const playgroundPath = resolve('./test/examples/comps/comp-multi-file-custom/test/pg'); + const playground = customTemplateInPath(playgroundPath); + const expectedPlayground = resolve('./test/examples/comps/comp-multi-file-custom/test/pg/index.marko'); + + expect(playground).to.equal(expectedPlayground); + }); + }); + }); +}); diff --git a/test/routes.spec.ts b/test/routes.spec.ts new file mode 100644 index 0000000..934c48d --- /dev/null +++ b/test/routes.spec.ts @@ -0,0 +1,112 @@ +/* + * Copyright 2018 eBay Inc. + * + * Use of this source code is governed by an MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT. + * + */ + +import { resolve } from 'path'; +import { use as chaiUse, expect } from 'chai'; +import { SinonStub as Stub, stub } from 'sinon'; +import * as sinonChai from 'sinon-chai'; +chaiUse(sinonChai); +import { Request } from 'express'; +import { Response } from 'marko/express'; + +import { PlaygroundVm } from '../src/view-model'; +import routes, { RouteMatch } from '../src/routes'; +import { mockPgs } from './data/mock-pgs'; +import { Dependencies } from '../src/dependencies'; + +const expectedRoutes = ['/some-component1', '/some-component2']; +const expectedPgNames = ['some-component1', 'some-component2']; +const expectedPgTemplates = [ + resolve('templates/mpg-comp.marko.js'), + resolve('test/examples/comps/comp-multi-file-custom/test/pg/index.marko.js') +]; +const mockDeps = (): Dependencies => ({ packagePaths: [], dependencies: [] }); +const mockMeta = undefined; +const mockFlags = ['some-flag']; + +describe('routes (integration)', () => { + let routeHandlers: RouteMatch[]; + + describe('given no playgrounds', () => { + before(() => { + routeHandlers = routes([], mockDeps); + }); + + it('should return only empty root routeHandler', () => { + expect(routeHandlers).to.have.length(1); + expect(routeHandlers[0].route).to.equal('/'); + expect(routeHandlers[0].handler).to.be.a('function'); + }); + }); + + describe('given playgrounds', () => { + beforeEach(() => { + routeHandlers = routes(mockPgs, mockDeps, mockMeta, mockFlags); + }); + + it('should return a list of all components routeHandlers', () => { + expect(routeHandlers).to.have.length(mockPgs.length + 1); + + const rootRouteHandler = routeHandlers[0]; + + expect(rootRouteHandler.route).to.equal('/'); + expect(rootRouteHandler.handler).to.be.a('function'); + + routeHandlers.slice(1).forEach(routeHandler => { + expect(expectedRoutes).to.include(routeHandler.route); + expect(routeHandler.handler).to.be.a('function'); + }); + }); + + describe('component page', () => { + let mockReq: Partial; + let mockRes: Partial; + let expectedFixtures: any; + + beforeEach(() => { + mockReq = {}; + mockRes = { marko: stub() }; + expectedFixtures = mockPgs[0].fixtures; + }); + + it('should have a list of all component names', () => { + routeHandlers.slice(1).forEach(routeHandler => { + routeHandler.handler(mockReq, mockRes); + + const calledArg = (mockRes.marko).args[0]; + const passedVm = calledArg[1]; + + expect(passedVm.componentNames).to.have.same.members(expectedPgNames); + }); + }); + + it('should have a list of all fixtures', () => { + routeHandlers.slice(1).forEach(routeHandler => { + routeHandler.handler(mockReq, mockRes); + + const calledArg = (mockRes.marko).args[0]; + const passedVm: PlaygroundVm = calledArg[1]; + const passedPgTemplate = calledArg[0]; + + const templateRelPath = resolve(passedPgTemplate.path); + expect(expectedPgTemplates).to.include(templateRelPath); + + expect(expectedPgNames).to.include(passedVm.componentName); + expect(passedVm.useCases).to.deep.equal(expectedFixtures); + expect(passedVm.flags).to.deep.equal(['some-flag']); + if ('render' in passedVm) { + expect(passedVm.render).to.be.a('function'); + } + + (mockRes.marko).reset(); + }); + }); + }); + }); +}); diff --git a/test/tslint.json b/test/tslint.json new file mode 100644 index 0000000..bdc4e62 --- /dev/null +++ b/test/tslint.json @@ -0,0 +1,8 @@ +{ + "defaultSeverity": "error", + "extends": [ "../tslint.json" ], + "jsRules": { }, + "rules": { + "no-unused-expression": false + } +} diff --git a/test/view-model.spec.ts b/test/view-model.spec.ts new file mode 100644 index 0000000..4fb1d5d --- /dev/null +++ b/test/view-model.spec.ts @@ -0,0 +1,159 @@ +/* + * Copyright 2018 eBay Inc. + * + * Use of this source code is governed by an MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT. + * + */ + +import { expect } from 'chai'; +import { compListVm, pageVm, playgroundVm } from '../src/view-model'; +import { mockPgs } from './data/mock-pgs'; +import { Dependencies } from '../src/dependencies'; +import { Meta } from '../src/meta'; + +const genericPg = mockPgs[0]; +const deps: Dependencies = { + packagePaths: ['../common/browser.json'], + dependencies: ['../styles/style.less'] +}; + +describe('viewModel', () => { + describe('playgroundVm()', () => { + describe('given no component/app dependencies', () => { + + describe('given an empty component list', () => { + it('should return a generic playground VM', () => { + const vm = playgroundVm(genericPg, []); + + expect(vm.componentName).to.equal('some-component1'); + expect(vm.componentNames).to.be.empty; + expect(vm.packagePaths).to.be.empty; + expect(vm.dependencies).to.be.empty; + expect(vm.render).to.be.a('function'); + expect(vm.useCases).to.deep.equal(require('./data/fixtures')); + }); + }); + + describe('given a component list', () => { + it('should return a generic playground VM with component list', () => { + const vm = playgroundVm(genericPg, ['another-component']); + + expect(vm.componentName).to.equal('some-component1'); + expect(vm.componentNames).to.deep.equal(['another-component']); + expect(vm.packagePaths).to.be.empty; + expect(vm.dependencies).to.be.empty; + expect(vm.render).to.be.a('function'); + expect(vm.useCases).to.deep.equal(require('./data/fixtures')); + }); + }); + }); + + describe('given additional dependencies', () => { + it('should return a VM with dependencies', () => { + const vm = playgroundVm(genericPg, [], deps); + + expect(vm.packagePaths).to.deep.equal(['../common/browser.json']); + expect(vm.dependencies).to.deep.equal(['../styles/style.less']); + }); + }); + + describe('given flags', () => { + it('should return a VM with flags', () => { + const vm = playgroundVm(genericPg, [], deps, ['some-flag']); + + expect(vm.flags).to.deep.equal(['some-flag']); + }); + }); + }); + + describe('compListVm()', () => { + describe('given empty component list', () => { + it('should return a VM with empty component list', () => { + expect(compListVm([])).to.deep.equal({ + componentNames: [], + packagePaths: [], + dependencies: [] + }); + }); + }); + describe('given non-empty component list', () => { + it('should return a VM with the same component list', () => { + expect(compListVm(['some-component'])).to.deep.equal({ + componentNames: ['some-component'], + packagePaths: [], + dependencies: [] + }); + }); + }); + describe('given additional dependencies', () => { + it('should return a VM with dependencies', () => { + expect(compListVm(['some-component'], deps)).to.deep.equal({ + componentNames: ['some-component'], + packagePaths: ['../common/browser.json'], + dependencies: ['../styles/style.less'] + }); + }); + }); + }); + + describe('pageVm()', () => { + describe('given playground', () => { + it('should return page VM merged with playground VM', () => { + const vm = pageVm(playgroundVm(genericPg, [])); + + expect(vm.packagePaths).to.be.empty; + expect(vm.dependencies).to.be.empty; + expect(vm.componentNames).to.be.empty; + expect(vm).to.have.property('componentName').which.is.equal('some-component1'); + expect(vm).to.not.have.property('appName'); + expect(vm).to.not.have.property('appVersion'); + }); + }); + + describe('given playground and component list', () => { + it('should return page VM merged with playground VM with all components', () => { + const vm = pageVm(playgroundVm(genericPg, ['some-component'])); + + expect(vm.packagePaths).to.be.empty; + expect(vm.dependencies).to.be.empty; + expect(vm.componentNames).to.deep.equal(['some-component']); + expect(vm).to.have.property('componentName').which.is.equal('some-component1'); + expect(vm).to.not.have.property('appName'); + expect(vm).to.not.have.property('appVersion'); + }); + }); + + describe('given component list', () => { + it('should return page VM with all components', () => { + const vm = pageVm(compListVm(['some-component'])); + + expect(vm.packagePaths).to.be.empty; + expect(vm.dependencies).to.be.empty; + expect(vm.componentNames).to.deep.equal(['some-component']); + expect(vm).to.not.have.property('appName'); + expect(vm).to.not.have.property('appVersion'); + expect(vm).to.not.have.property('componentName'); + }); + }); + + describe('given meta', () => { + it('should return page VM meta data', () => { + const meta: Meta = { + appName: 'app', + appVersion: '1.0' + }; + const vm = pageVm(compListVm([]), meta); + + expect(vm.appName).to.equal('app'); + expect(vm.appVersion).to.equal('1.0'); + expect(vm.packagePaths).to.be.empty; + expect(vm.dependencies).to.be.empty; + expect(vm.componentNames).to.be.empty; + expect(vm).to.not.have.property('componentName'); + }); + }); + }); + +}); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..228ee1d --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "outDir": "./dist", + "sourceMap": true, + "strictNullChecks": true, + "module": "commonjs", + "target": "es2016", + "allowJs": false, + "checkJs": false, + "strict": true, + "noImplicitAny": true, + "baseUrl": ".", + "lib": [ "dom", "es2017" ] + }, + "include": [ + "./" + ], + "exclude": [ + "node_modules", + "static", + "test" + ] +} diff --git a/tslint.json b/tslint.json new file mode 100644 index 0000000..aed77e2 --- /dev/null +++ b/tslint.json @@ -0,0 +1,24 @@ +{ + "defaultSeverity": "error", + "extends": [ "tslint-config-airbnb", "tslint-eslint-rules" ], + "jsRules": { }, + "rules": { + "max-line-length": [ true, 120 ], + "array-bracket-spacing": [ false ], + "trailing-comma": [ true, { "multiline": "never", "singleline": "never" } ], + "no-trailing-whitespace": [ true, "ignore-comments", "ignore-blank-lines" ], + //disabled until fixed: https://github.com/palantir/tslint/issues/3279 + //"strict-boolean-expressions": [ true, "allow-undefined-union", "allow-string", "allow-number" ], + "no-console": [ true ], + "object-shorthand-properties-first": [ false ], + "ter-arrow-body-style": [ true, "as-needed" ], + "ter-arrow-parens": [ true, "as-needed" ], + "no-var-keyword": true, + "import-name": [ false ], + "no-unused-variable": true, + "no-unused-expression": true, + "no-use-before-declare": true, + "space-before-function-paren": false, + "align": [true, "statements", "members", "elements"] + } +} diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..972770b --- /dev/null +++ b/yarn.lock @@ -0,0 +1,2267 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@fimbul/bifrost@^0.11.0": + version "0.11.0" + resolved "https://registry.npmjs.org/@fimbul/bifrost/-/bifrost-0.11.0.tgz#83cacc21464198b12e3cc1c2204ae6c6d7afd158" + dependencies: + "@fimbul/ymir" "^0.11.0" + get-caller-file "^1.0.2" + tslib "^1.8.1" + tsutils "^2.24.0" + +"@fimbul/ymir@^0.11.0": + version "0.11.0" + resolved "https://registry.npmjs.org/@fimbul/ymir/-/ymir-0.11.0.tgz#892a01997f1f80c7e4e437cf5ca51c95994c136f" + dependencies: + inversify "^4.10.0" + reflect-metadata "^0.1.12" + tslib "^1.8.1" + +"@lasso/marko-taglib@^1.0.8": + version "1.0.10" + resolved "https://registry.npmjs.org/@lasso/marko-taglib/-/marko-taglib-1.0.10.tgz#cc8f61353a88430d2f34f66441f5cf757aa69944" + dependencies: + lasso-resolve-from "^1.2.0" + raptor-async "^1.1.3" + raptor-logging "^1.1.3" + raptor-util "^1.1.2" + +"@sinonjs/formatio@^2.0.0": + version "2.0.0" + resolved "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz#84db7e9eb5531df18a8c5e0bfb6e449e55e654b2" + dependencies: + samsam "1.3.0" + +"@sinonjs/samsam@^2.0.0": + version "2.0.0" + resolved "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-2.0.0.tgz#9163742ac35c12d3602dece74317643b35db6a80" + +"@types/async-writer@*", "@types/async-writer@^1.4.30": + version "1.4.30" + resolved "https://registry.npmjs.org/@types/async-writer/-/async-writer-1.4.30.tgz#cf2ad7197c62bd6f8220a8822281fab9c87badce" + dependencies: + "@types/node" "*" + +"@types/body-parser@*": + version "1.17.0" + resolved "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.17.0.tgz#9f5c9d9bd04bb54be32d5eb9fc0d8c974e6cf58c" + dependencies: + "@types/connect" "*" + "@types/node" "*" + +"@types/chai@*", "@types/chai@^4.0.10": + version "4.1.4" + resolved "https://registry.npmjs.org/@types/chai/-/chai-4.1.4.tgz#5ca073b330d90b4066d6ce18f60d57f2084ce8ca" + +"@types/connect@*": + version "3.4.32" + resolved "https://registry.npmjs.org/@types/connect/-/connect-3.4.32.tgz#aa0e9616b9435ccad02bc52b5b454ffc2c70ba28" + dependencies: + "@types/node" "*" + +"@types/events@*": + version "1.2.0" + resolved "https://registry.npmjs.org/@types/events/-/events-1.2.0.tgz#81a6731ce4df43619e5c8c945383b3e62a89ea86" + +"@types/express-serve-static-core@*": + version "4.16.0" + resolved "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.16.0.tgz#fdfe777594ddc1fe8eb8eccce52e261b496e43e7" + dependencies: + "@types/events" "*" + "@types/node" "*" + "@types/range-parser" "*" + +"@types/express@*", "@types/express@^4.0.39": + version "4.16.0" + resolved "https://registry.npmjs.org/@types/express/-/express-4.16.0.tgz#6d8bc42ccaa6f35cf29a2b7c3333cb47b5a32a19" + dependencies: + "@types/body-parser" "*" + "@types/express-serve-static-core" "*" + "@types/serve-static" "*" + +"@types/glob@^5.0.34": + version "5.0.35" + resolved "https://registry.npmjs.org/@types/glob/-/glob-5.0.35.tgz#1ae151c802cece940443b5ac246925c85189f32a" + dependencies: + "@types/events" "*" + "@types/minimatch" "*" + "@types/node" "*" + +"@types/lasso@^2.4.0": + version "2.4.0" + resolved "https://registry.npmjs.org/@types/lasso/-/lasso-2.4.0.tgz#93a753f2a3b98c7c375972311556ff1edff5a0f3" + dependencies: + "@types/events" "*" + "@types/express" "*" + "@types/node" "*" + +"@types/lodash@^4.14.88": + version "4.14.112" + resolved "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.112.tgz#4a8d8e5716b97a1ac01fe1931ad1e4cba719de5a" + +"@types/marko@^4.6.0": + version "4.6.0" + resolved "https://registry.npmjs.org/@types/marko/-/marko-4.6.0.tgz#db62245800b43fa366fa9f9d963e64b9c6e6b5a2" + dependencies: + "@types/async-writer" "*" + "@types/events" "*" + "@types/express" "*" + "@types/express-serve-static-core" "*" + "@types/node" "*" + +"@types/mime@*": + version "2.0.0" + resolved "https://registry.npmjs.org/@types/mime/-/mime-2.0.0.tgz#5a7306e367c539b9f6543499de8dd519fac37a8b" + +"@types/minimatch@*": + version "3.0.3" + resolved "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" + +"@types/mocha@^5.0.0": + version "5.2.4" + resolved "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.4.tgz#2f8fbdf95c69ebf82150a7864864010f186745bf" + +"@types/node@*": + version "10.5.2" + resolved "https://registry.npmjs.org/@types/node/-/node-10.5.2.tgz#f19f05314d5421fe37e74153254201a7bf00a707" + +"@types/node@^8.0.58": + version "8.10.21" + resolved "https://registry.npmjs.org/@types/node/-/node-8.10.21.tgz#12b3f2359b27aa05a45d886c8ba1eb8d1a77e285" + +"@types/range-parser@*": + version "1.2.2" + resolved "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.2.tgz#fa8e1ad1d474688a757140c91de6dace6f4abc8d" + +"@types/serve-static@*": + version "1.13.2" + resolved "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.2.tgz#f5ac4d7a6420a99a6a45af4719f4dcd8cd907a48" + dependencies: + "@types/express-serve-static-core" "*" + "@types/mime" "*" + +"@types/sinon-chai@^3.0.0": + version "3.2.0" + resolved "https://registry.npmjs.org/@types/sinon-chai/-/sinon-chai-3.2.0.tgz#58abf70d8d002d2292ce656425431d873f2c77bc" + dependencies: + "@types/chai" "*" + "@types/sinon" "*" + +"@types/sinon@*", "@types/sinon@^5.0.0": + version "5.0.1" + resolved "https://registry.npmjs.org/@types/sinon/-/sinon-5.0.1.tgz#a15b36ec42f1f53166617491feabd1734cb03e21" + +accepts@~1.3.5: + version "1.3.5" + resolved "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2" + dependencies: + mime-types "~2.1.18" + negotiator "0.6.1" + +ajv@^4.9.1: + version "4.11.8" + resolved "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" + dependencies: + co "^4.6.0" + json-stable-stringify "^1.0.1" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + dependencies: + color-convert "^1.9.0" + +app-module-path@^2.2.0: + version "2.2.0" + resolved "https://registry.npmjs.org/app-module-path/-/app-module-path-2.2.0.tgz#641aa55dfb7d6a6f0a8141c4b9c0aa50b6c24dd5" + +app-root-dir@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/app-root-dir/-/app-root-dir-1.0.2.tgz#38187ec2dea7577fff033ffcb12172692ff6e118" + +argly@^1.0.0: + version "1.2.0" + resolved "https://registry.npmjs.org/argly/-/argly-1.2.0.tgz#2b274e4551a29ff5e7199d2ed9788eb66ed36e60" + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + dependencies: + sprintf-js "~1.0.2" + +array-find-index@^1.0.1: + version "1.0.2" + resolved "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" + +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + +arrify@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + +asap@~2.0.3: + version "2.0.6" + resolved "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" + +asn1@~0.2.3: + version "0.2.3" + resolved "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + +assert-plus@^0.2.0: + version "0.2.0" + resolved "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" + +assert@^1.4.1: + version "1.4.1" + resolved "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91" + dependencies: + util "0.10.3" + +assertion-error@^1.0.1: + version "1.1.0" + resolved "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" + +async@^0.9.0: + version "0.9.2" + resolved "https://registry.npmjs.org/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + +aws-sign2@~0.6.0: + version "0.6.0" + resolved "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" + +aws4@^1.2.1: + version "1.7.0" + resolved "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz#d4d0e9b9dbfca77bf08eeb0a8a471550fe39e289" + +babel-code-frame@^6.22.0: + version "6.26.0" + resolved "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" + dependencies: + chalk "^1.1.3" + esutils "^2.0.2" + js-tokens "^3.0.2" + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + +base64-js@^1.0.2: + version "1.3.0" + resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3" + +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + dependencies: + tweetnacl "^0.14.3" + +bl@^1.0.0: + version "1.2.2" + resolved "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c" + dependencies: + readable-stream "^2.3.5" + safe-buffer "^5.1.1" + +bluebird@^2.9.12: + version "2.11.0" + resolved "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1" + +body-parser@1.18.2: + version "1.18.2" + resolved "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz#87678a19d84b47d859b83199bd59bce222b10454" + dependencies: + bytes "3.0.0" + content-type "~1.0.4" + debug "2.6.9" + depd "~1.1.1" + http-errors "~1.6.2" + iconv-lite "0.4.19" + on-finished "~2.3.0" + qs "6.5.1" + raw-body "2.3.2" + type-is "~1.6.15" + +boom@2.x.x: + version "2.10.1" + resolved "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" + dependencies: + hoek "2.x.x" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +browser-refresh-client@^1.0.0, browser-refresh-client@^1.1.4: + version "1.1.4" + resolved "https://registry.npmjs.org/browser-refresh-client/-/browser-refresh-client-1.1.4.tgz#8e5ff8475fe1d541d2ae81f7a1aea05ae21a6217" + +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + +buffer-from@^1.0.0, buffer-from@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.0.tgz#87fcaa3a298358e0ade6e442cfce840740d1ad04" + +buffer@^5.1.0: + version "5.1.0" + resolved "https://registry.npmjs.org/buffer/-/buffer-5.1.0.tgz#c913e43678c7cb7c8bd16afbcddb6c5505e8f9fe" + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + +builtin-modules@^1.0.0, builtin-modules@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" + +bytes@3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" + +callbackify@^1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/callbackify/-/callbackify-1.1.0.tgz#d2a36986d28aa69714526c111209beeb9979d31e" + +camelcase-keys@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" + dependencies: + camelcase "^2.0.0" + map-obj "^1.0.0" + +camelcase@^2.0.0: + version "2.1.1" + resolved "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" + +camelcase@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + +chai-as-promised@^7.1.1: + version "7.1.1" + resolved "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz#08645d825deb8696ee61725dbf590c012eb00ca0" + dependencies: + check-error "^1.0.2" + +chai@^3.5.0: + version "3.5.0" + resolved "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz#4d02637b067fe958bdbfdd3a40ec56fef7373247" + dependencies: + assertion-error "^1.0.1" + deep-eql "^0.1.3" + type-detect "^1.0.0" + +chai@^4.1.2: + version "4.1.2" + resolved "https://registry.npmjs.org/chai/-/chai-4.1.2.tgz#0f64584ba642f0f2ace2806279f4f06ca23ad73c" + dependencies: + assertion-error "^1.0.1" + check-error "^1.0.1" + deep-eql "^3.0.0" + get-func-name "^2.0.0" + pathval "^1.0.0" + type-detect "^4.0.0" + +chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +chalk@^2.3.0, chalk@^2.3.1: + version "2.4.1" + resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +char-props@^0.1.5, char-props@~0.1.5: + version "0.1.5" + resolved "https://registry.npmjs.org/char-props/-/char-props-0.1.5.tgz#5b952f9e20ea21cd08ca7fe135a10f6fe91c109e" + +check-error@^1.0.1, check-error@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" + +ci-info@^1.0.0: + version "1.1.3" + resolved "https://registry.npmjs.org/ci-info/-/ci-info-1.1.3.tgz#710193264bb05c77b8c90d02f5aaf22216a667b2" + +clean-css@^4.1.11: + version "4.1.11" + resolved "https://registry.npmjs.org/clean-css/-/clean-css-4.1.11.tgz#2ecdf145aba38f54740f26cefd0ff3e03e125d6a" + dependencies: + source-map "0.5.x" + +cliui@^3.2.0: + version "3.2.0" + resolved "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + wrap-ansi "^2.0.0" + +clone@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz#d217d1e961118e3ac9a4b8bba3285553bf647cdb" + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.npmjs.org/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + +color-convert@^1.9.0: + version "1.9.2" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.2.tgz#49881b8fba67df12a96bdf3f56c0aab9e7913147" + dependencies: + color-name "1.1.1" + +color-name@1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.1.tgz#4b1415304cf50028ea81643643bd82ea05803689" + +combined-stream@^1.0.5, combined-stream@~1.0.5: + version "1.0.6" + resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" + dependencies: + delayed-stream "~1.0.0" + +commander@2.15.1: + version "2.15.1" + resolved "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" + +commander@^2.12.1, commander@~2.16.0: + version "2.16.0" + resolved "https://registry.npmjs.org/commander/-/commander-2.16.0.tgz#f16390593996ceb4f3eeb020b31d78528f7f8a50" + +complain@^1.0.0, complain@^1.2.0, complain@^1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/complain/-/complain-1.3.0.tgz#a182d5003489126c038bbf98b906866acbfa77b2" + dependencies: + error-stack-parser "^2.0.1" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + +content-disposition@0.5.2: + version "0.5.2" + resolved "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" + +content-type@~1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + +cookie@0.3.1: + version "0.3.1" + resolved "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" + +core-util-is@1.0.2, core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + +cryptiles@2.x.x: + version "2.0.5" + resolved "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" + dependencies: + boom "2.x.x" + +currently-unhandled@^0.4.1: + version "0.4.1" + resolved "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" + dependencies: + array-find-index "^1.0.1" + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + dependencies: + assert-plus "^1.0.0" + +dateformat@^1.0.11: + version "1.0.12" + resolved "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz#9f124b67594c937ff706932e4a642cca8dbbfee9" + dependencies: + get-stdin "^4.0.1" + meow "^3.3.0" + +debug@2.6.9: + version "2.6.9" + resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + dependencies: + ms "2.0.0" + +debug@3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" + dependencies: + ms "2.0.0" + +decamelize@^1.1.1, decamelize@^1.1.2: + version "1.2.0" + resolved "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + +deep-eql@^0.1.3: + version "0.1.3" + resolved "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz#ef558acab8de25206cd713906d74e56930eb69f2" + dependencies: + type-detect "0.1.1" + +deep-eql@^3.0.0: + version "3.0.1" + resolved "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" + dependencies: + type-detect "^4.0.0" + +deep-is@~0.1.3: + version "0.1.3" + resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + +depd@1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359" + +depd@~1.1.1, depd@~1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + +deresolve@^1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/deresolve/-/deresolve-1.1.2.tgz#9cf2379c8d2d631dc4b9957294b90e4a72cb6ce0" + dependencies: + lasso-package-root "^1.0.0" + raptor-polyfill "^1.0.2" + resolve-from "^1.0.1" + +destroy@~1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" + +diff@3.5.0, diff@^3.1.0, diff@^3.2.0, diff@^3.5.0: + version "3.5.0" + resolved "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" + +"dissolve@github:deoxxa/dissolve#eeb806f2bad501548138c8e38d0adcf95d4d1bdb": + version "0.3.3" + resolved "https://codeload.github.com/deoxxa/dissolve/tar.gz/eeb806f2bad501548138c8e38d0adcf95d4d1bdb" + dependencies: + bl "^1.0.0" + readable-stream "^2.0.0" + +doctrine@0.7.2: + version "0.7.2" + resolved "https://registry.npmjs.org/doctrine/-/doctrine-0.7.2.tgz#7cb860359ba3be90e040b26b729ce4bfa654c523" + dependencies: + esutils "^1.1.6" + isarray "0.0.1" + +ecc-jsbn@~0.1.1: + version "0.1.1" + resolved "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" + dependencies: + jsbn "~0.1.0" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + +errno@^0.1.1: + version "0.1.7" + resolved "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" + dependencies: + prr "~1.0.1" + +error-ex@^1.2.0: + version "1.3.2" + resolved "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + dependencies: + is-arrayish "^0.2.1" + +error-stack-parser@^2.0.1: + version "2.0.2" + resolved "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.0.2.tgz#4ae8dbaa2bf90a8b450707b9149dcabca135520d" + dependencies: + stackframe "^1.0.4" + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + +escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + +escodegen@^1.10.0, escodegen@^1.8.1: + version "1.11.0" + resolved "https://registry.npmjs.org/escodegen/-/escodegen-1.11.0.tgz#b27a9389481d5bfd5bec76f7bb1eb3f8f4556589" + dependencies: + esprima "^3.1.3" + estraverse "^4.2.0" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.6.1" + +esprima@^3.1.3: + version "3.1.3" + resolved "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + +estraverse@^4.2.0: + version "4.2.0" + resolved "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" + +esutils@^1.1.6: + version "1.1.6" + resolved "https://registry.npmjs.org/esutils/-/esutils-1.1.6.tgz#c01ccaa9ae4b897c6d0c3e210ae52f3c7a844375" + +esutils@^2.0.2: + version "2.0.2" + resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + +events-light@^1.0.0: + version "1.0.5" + resolved "https://registry.npmjs.org/events-light/-/events-light-1.0.5.tgz#964e63450ba0af4a6b022aa955b17ffef657b5ee" + dependencies: + chai "^3.5.0" + +events@^1.0.2: + version "1.1.1" + resolved "https://registry.npmjs.org/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" + +events@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/events/-/events-3.0.0.tgz#9a0a0dfaf62893d92b875b8f2698ca4114973e88" + +express@^4.14.0: + version "4.16.3" + resolved "https://registry.npmjs.org/express/-/express-4.16.3.tgz#6af8a502350db3246ecc4becf6b5a34d22f7ed53" + dependencies: + accepts "~1.3.5" + array-flatten "1.1.1" + body-parser "1.18.2" + content-disposition "0.5.2" + content-type "~1.0.4" + cookie "0.3.1" + cookie-signature "1.0.6" + debug "2.6.9" + depd "~1.1.2" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + finalhandler "1.1.1" + fresh "0.5.2" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "~2.3.0" + parseurl "~1.3.2" + path-to-regexp "0.1.7" + proxy-addr "~2.0.3" + qs "6.5.1" + range-parser "~1.2.0" + safe-buffer "5.1.1" + send "0.16.2" + serve-static "1.13.2" + setprototypeof "1.1.0" + statuses "~1.4.0" + type-is "~1.6.16" + utils-merge "1.0.1" + vary "~1.1.2" + +extend@~3.0.0: + version "3.0.1" + resolved "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + +extsprintf@^1.2.0: + version "1.4.0" + resolved "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" + +fast-levenshtein@~2.0.4: + version "2.0.6" + resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + +finalhandler@1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz#eebf4ed840079c83f4249038c9d703008301b105" + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "~2.3.0" + parseurl "~1.3.2" + statuses "~1.4.0" + unpipe "~1.0.0" + +find-up@^1.0.0: + version "1.1.2" + resolved "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" + dependencies: + path-exists "^2.0.0" + pinkie-promise "^2.0.0" + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + +form-data@~2.1.1: + version "2.1.4" + resolved "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1" + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.5" + mime-types "^2.1.12" + +forwarded@~0.1.2: + version "0.1.2" + resolved "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + +get-caller-file@^1.0.1, get-caller-file@^1.0.2: + version "1.0.3" + resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" + +get-func-name@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" + +get-stdin@^4.0.1: + version "4.0.1" + resolved "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + dependencies: + assert-plus "^1.0.0" + +glob@7.1.2, glob@^7.0.5, glob@^7.1.0, glob@^7.1.1, glob@^7.1.2: + version "7.1.2" + resolved "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +graceful-fs@^4.1.2: + version "4.1.11" + resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" + +growl@1.10.5: + version "1.10.5" + resolved "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" + +har-schema@^1.0.5: + version "1.0.5" + resolved "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e" + +har-validator@~4.2.1: + version "4.2.1" + resolved "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a" + dependencies: + ajv "^4.9.1" + har-schema "^1.0.5" + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + dependencies: + ansi-regex "^2.0.0" + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + +hawk@~3.1.3: + version "3.1.3" + resolved "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" + dependencies: + boom "2.x.x" + cryptiles "2.x.x" + hoek "2.x.x" + sntp "1.x.x" + +he@1.1.1, he@^1.1.0: + version "1.1.1" + resolved "https://registry.npmjs.org/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" + +hoek@2.x.x: + version "2.16.3" + resolved "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" + +hosted-git-info@^2.1.4: + version "2.7.1" + resolved "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" + +htmljs-parser@^2.3.2: + version "2.3.2" + resolved "https://registry.npmjs.org/htmljs-parser/-/htmljs-parser-2.3.2.tgz#1cc5bf9824a091c28820b33eaf78083a8eaa856c" + dependencies: + char-props "^0.1.5" + complain "^1.0.0" + +http-errors@1.6.2: + version "1.6.2" + resolved "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736" + dependencies: + depd "1.1.1" + inherits "2.0.3" + setprototypeof "1.0.3" + statuses ">= 1.3.1 < 2" + +http-errors@~1.6.2: + version "1.6.3" + resolved "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" + dependencies: + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.0" + statuses ">= 1.4.0 < 2" + +http-signature@~1.1.0: + version "1.1.1" + resolved "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" + dependencies: + assert-plus "^0.2.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +husky@^0.14.3: + version "0.14.3" + resolved "https://registry.npmjs.org/husky/-/husky-0.14.3.tgz#c69ed74e2d2779769a17ba8399b54ce0b63c12c3" + dependencies: + is-ci "^1.0.10" + normalize-path "^1.0.0" + strip-indent "^2.0.0" + +iconv-lite@0.4.19: + version "0.4.19" + resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" + +ieee754@^1.1.4: + version "1.1.12" + resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz#50bf24e5b9c8bb98af4964c941cdb0918da7b60b" + +image-size@^0.6.3: + version "0.6.3" + resolved "https://registry.npmjs.org/image-size/-/image-size-0.6.3.tgz#e7e5c65bb534bd7cdcedd6cb5166272a85f75fb2" + +image-size@~0.5.0: + version "0.5.5" + resolved "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz#09dfd4ab9d20e29eb1c3e80b8990378df9e3cb9c" + +indent-string@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" + dependencies: + repeating "^2.0.0" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.3, inherits@~2.0.1, inherits@~2.0.3: + version "2.0.3" + resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + +inherits@2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" + +inversify@^4.10.0: + version "4.13.0" + resolved "https://registry.npmjs.org/inversify/-/inversify-4.13.0.tgz#0ab40570bfa4474b04d5b919bbab3a4f682a72f5" + +invert-kv@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" + +ipaddr.js@1.6.0: + version "1.6.0" + resolved "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.6.0.tgz#e3fa357b773da619f26e95f049d055c72796f86b" + +is-absolute@^0.2.3: + version "0.2.6" + resolved "https://registry.npmjs.org/is-absolute/-/is-absolute-0.2.6.tgz#20de69f3db942ef2d87b9c2da36f172235b1b5eb" + dependencies: + is-relative "^0.2.1" + is-windows "^0.2.0" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + +is-builtin-module@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" + dependencies: + builtin-modules "^1.0.0" + +is-ci@^1.0.10: + version "1.1.0" + resolved "https://registry.npmjs.org/is-ci/-/is-ci-1.1.0.tgz#247e4162e7860cebbdaf30b774d6b0ac7dcfe7a5" + dependencies: + ci-info "^1.0.0" + +is-finite@^1.0.0: + version "1.0.2" + resolved "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + dependencies: + number-is-nan "^1.0.0" + +is-relative@^0.2.1: + version "0.2.1" + resolved "https://registry.npmjs.org/is-relative/-/is-relative-0.2.1.tgz#d27f4c7d516d175fb610db84bbeef23c3bc97aa5" + dependencies: + is-unc-path "^0.1.1" + +is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + +is-unc-path@^0.1.1: + version "0.1.2" + resolved "https://registry.npmjs.org/is-unc-path/-/is-unc-path-0.1.2.tgz#6ab053a72573c10250ff416a3814c35178af39b9" + dependencies: + unc-path-regex "^0.1.0" + +is-utf8@^0.2.0: + version "0.2.1" + resolved "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" + +is-windows@^0.2.0: + version "0.2.0" + resolved "https://registry.npmjs.org/is-windows/-/is-windows-0.2.0.tgz#de1aa6d63ea29dd248737b69f1ff8b8002d2108c" + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + +js-tokens@^3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" + +js-yaml@^3.7.0: + version "3.12.0" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1" + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + +json-schema@0.2.3: + version "0.2.3" + resolved "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + +json-stable-stringify@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" + dependencies: + jsonify "~0.0.0" + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + +jsonify@~0.0.0: + version "0.0.0" + resolved "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" + +jsprim@^1.2.2: + version "1.4.1" + resolved "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.2.3" + verror "1.10.0" + +just-extend@^1.1.27: + version "1.1.27" + resolved "https://registry.npmjs.org/just-extend/-/just-extend-1.1.27.tgz#ec6e79410ff914e472652abfa0e603c03d60e905" + +lasso-caching-fs@^1.0.0, lasso-caching-fs@^1.0.1, lasso-caching-fs@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/lasso-caching-fs/-/lasso-caching-fs-1.0.2.tgz#9be4eb1f06aac1260344caeaef42c2f0086eb10d" + dependencies: + raptor-async "^1.1.2" + +lasso-less@^2.4.7: + version "2.4.7" + resolved "https://registry.npmjs.org/lasso-less/-/lasso-less-2.4.7.tgz#12f36178db9bd16e4f7cdd323ceba136300e13c1" + dependencies: + async "^0.9.0" + lasso-package-root "^1.0.1" + less "^2.0.0" + raptor-async "^1.0.3" + raptor-logging "^1.0.5" + raptor-polyfill "^1.0.2" + raptor-util "^1.0.10" + resolve-from "^1.0.0" + +lasso-loader@^3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/lasso-loader/-/lasso-loader-3.0.2.tgz#dbdb55d5f72eeb3a5bae74a7e31b6bb5ff2dd093" + dependencies: + events "^1.0.2" + raptor-util "^1.0.0" + +lasso-marko@^2.4.0: + version "2.4.2" + resolved "https://registry.npmjs.org/lasso-marko/-/lasso-marko-2.4.2.tgz#7d18c0415dbe5bdfbee2ff8425cc27637fb67497" + dependencies: + callbackify "^1.1.0" + +lasso-modules-client@^2.0.4, lasso-modules-client@^2.0.5: + version "2.0.5" + resolved "https://registry.npmjs.org/lasso-modules-client/-/lasso-modules-client-2.0.5.tgz#d9a06724a900977636971667ee9c170d2fc4dd28" + dependencies: + lasso-package-root "^1.0.0" + raptor-polyfill "^1.0.2" + +lasso-package-root@^1.0.0, lasso-package-root@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/lasso-package-root/-/lasso-package-root-1.0.1.tgz#997d0e71f41d03c5f0fa09a5bc298d796f8b2c23" + dependencies: + lasso-caching-fs "^1.0.0" + +lasso-resolve-from@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/lasso-resolve-from/-/lasso-resolve-from-1.2.0.tgz#bfb234467afb69b5309f568ba459cc8320621c6e" + dependencies: + is-absolute "^0.2.3" + lasso-caching-fs "^1.0.1" + raptor-util "^1.0.10" + resolve-from "^2.0.0" + +lasso@^3.1.0: + version "3.2.1" + resolved "https://registry.npmjs.org/lasso/-/lasso-3.2.1.tgz#7c36bd1f57a46cf2a462a9a294848acec33d8f65" + dependencies: + app-root-dir "^1.0.2" + assert "^1.4.1" + browser-refresh-client "^1.1.4" + buffer "^5.1.0" + clean-css "^4.1.11" + clone "^2.1.1" + complain "^1.2.0" + escodegen "^1.10.0" + esprima "^4.0.0" + estraverse "^4.2.0" + events "^3.0.0" + glob "^7.1.2" + image-size "^0.6.3" + lasso-caching-fs "^1.0.2" + lasso-loader "^3.0.2" + lasso-modules-client "^2.0.5" + lasso-package-root "^1.0.1" + lasso-resolve-from "^1.2.0" + marko "^4.10.0" + mime "^2.3.1" + mkdirp "^0.5.1" + path-browserify "1.0.0" + pify "^3.0.0" + process "^0.11.10" + property-handlers "^1.1.1" + raptor-async "^1.1.3" + raptor-cache "^2.0.4" + raptor-css-parser "^1.1.5" + raptor-detect "^1.0.1" + raptor-logging "^1.1.3" + raptor-objects "^1.0.2" + raptor-polyfill "^1.0.2" + raptor-promises "^1.0.3" + raptor-regexp "^1.0.1" + raptor-strings "^1.0.2" + raptor-util "^3.2.0" + resolve-from "^4.0.0" + semver "^5.5.0" + send "^0.16.2" + stream-browserify "^2.0.1" + string_decoder "^1.1.1" + strip-json-comments "^2.0.1" + through "^2.3.8" + uglify-js "^3.4.0" + url "^0.11.0" + util "^0.11.0" + +lcid@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" + dependencies: + invert-kv "^1.0.0" + +less@^2.0.0: + version "2.7.3" + resolved "https://registry.npmjs.org/less/-/less-2.7.3.tgz#cc1260f51c900a9ec0d91fb6998139e02507b63b" + optionalDependencies: + errno "^0.1.1" + graceful-fs "^4.1.2" + image-size "~0.5.0" + mime "^1.2.11" + mkdirp "^0.5.0" + promise "^7.1.1" + request "2.81.0" + source-map "^0.5.3" + +levn@~0.3.0: + version "0.3.0" + resolved "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + +listener-tracker@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/listener-tracker/-/listener-tracker-2.0.0.tgz#39608b435c0901fa5510217c1452728d6bc19b5f" + +load-json-file@^1.0.0: + version "1.1.0" + resolved "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + pinkie-promise "^2.0.0" + strip-bom "^2.0.0" + +lodash.get@^4.4.2: + version "4.4.2" + resolved "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" + +lolex@^2.3.2, lolex@^2.4.2: + version "2.7.1" + resolved "https://registry.npmjs.org/lolex/-/lolex-2.7.1.tgz#e40a8c4d1f14b536aa03e42a537c7adbaf0c20be" + +loud-rejection@^1.0.0: + version "1.6.0" + resolved "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" + dependencies: + currently-unhandled "^0.4.1" + signal-exit "^3.0.0" + +make-error@^1.1.1: + version "1.3.4" + resolved "https://registry.npmjs.org/make-error/-/make-error-1.3.4.tgz#19978ed575f9e9545d2ff8c13e33b5d18a67d535" + +map-obj@^1.0.0, map-obj@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" + +marko@^4.10.0, marko@^4.7.4: + version "4.12.0" + resolved "https://registry.npmjs.org/marko/-/marko-4.12.0.tgz#3fcd01744696f4b9f199daac75185c6477cf182d" + dependencies: + app-module-path "^2.2.0" + argly "^1.0.0" + browser-refresh-client "^1.0.0" + char-props "~0.1.5" + complain "^1.3.0" + deresolve "^1.1.2" + escodegen "^1.8.1" + esprima "^4.0.0" + estraverse "^4.2.0" + events "^1.0.2" + events-light "^1.0.0" + he "^1.1.0" + htmljs-parser "^2.3.2" + lasso-caching-fs "^1.0.1" + lasso-modules-client "^2.0.4" + lasso-package-root "^1.0.1" + listener-tracker "^2.0.0" + minimatch "^3.0.2" + object-assign "^4.1.0" + property-handlers "^1.0.0" + raptor-json "^1.0.1" + raptor-polyfill "^1.0.0" + raptor-promises "^1.0.1" + raptor-regexp "^1.0.0" + raptor-util "^3.2.0" + resolve-from "^2.0.0" + shorthash "0.0.2" + simple-sha1 "^2.1.0" + strip-json-comments "^2.0.1" + try-require "^1.2.1" + warp10 "^1.0.0" + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + +meow@^3.3.0: + version "3.7.0" + resolved "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" + dependencies: + camelcase-keys "^2.0.0" + decamelize "^1.1.2" + loud-rejection "^1.0.0" + map-obj "^1.0.1" + minimist "^1.1.3" + normalize-package-data "^2.3.4" + object-assign "^4.0.1" + read-pkg-up "^1.0.1" + redent "^1.0.0" + trim-newlines "^1.0.0" + +merge-descriptors@1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + +methods@~1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + +mime-db@~1.33.0: + version "1.33.0" + resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" + +mime-types@^2.1.12, mime-types@~2.1.18, mime-types@~2.1.7: + version "2.1.18" + resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8" + dependencies: + mime-db "~1.33.0" + +mime@1.4.1: + version "1.4.1" + resolved "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" + +mime@^1.2.11: + version "1.6.0" + resolved "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + +mime@^2.3.1: + version "2.3.1" + resolved "https://registry.npmjs.org/mime/-/mime-2.3.1.tgz#b1621c54d63b97c47d3cfe7f7215f7d64517c369" + +minimatch@3.0.4, minimatch@^3.0.2, minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + dependencies: + brace-expansion "^1.1.7" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + +minimist@^1.1.3, minimist@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + +mkdirp@0.5.1, mkdirp@^0.5.0, mkdirp@^0.5.1: + version "0.5.1" + resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + dependencies: + minimist "0.0.8" + +mocha@^5.0.1: + version "5.2.0" + resolved "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6" + dependencies: + browser-stdout "1.3.1" + commander "2.15.1" + debug "3.1.0" + diff "3.5.0" + escape-string-regexp "1.0.5" + glob "7.1.2" + growl "1.10.5" + he "1.1.1" + minimatch "3.0.4" + mkdirp "0.5.1" + supports-color "5.4.0" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + +negotiator@0.6.1: + version "0.6.1" + resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" + +nise@^1.3.3: + version "1.4.2" + resolved "https://registry.npmjs.org/nise/-/nise-1.4.2.tgz#a9a3800e3994994af9e452333d549d60f72b8e8c" + dependencies: + "@sinonjs/formatio" "^2.0.0" + just-extend "^1.1.27" + lolex "^2.3.2" + path-to-regexp "^1.7.0" + text-encoding "^0.6.4" + +normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: + version "2.4.0" + resolved "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" + dependencies: + hosted-git-info "^2.1.4" + is-builtin-module "^1.0.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +normalize-path@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-1.0.0.tgz#32d0e472f91ff345701c15a8311018d3b0a90379" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + +oauth-sign@~0.8.1: + version "0.8.2" + resolved "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" + +object-assign@^4.0.1, object-assign@^4.1.0: + version "4.1.1" + resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + dependencies: + ee-first "1.1.1" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + dependencies: + wrappy "1" + +optionator@^0.8.1: + version "0.8.2" + resolved "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.4" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + wordwrap "~1.0.0" + +os-locale@^1.4.0: + version "1.4.0" + resolved "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" + dependencies: + lcid "^1.0.0" + +parse-json@^2.2.0: + version "2.2.0" + resolved "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + dependencies: + error-ex "^1.2.0" + +parseurl@~1.3.2: + version "1.3.2" + resolved "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3" + +path-browserify@1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.0.tgz#40702a97af46ae00b0ea6fa8998c0b03c0af160d" + +path-exists@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" + dependencies: + pinkie-promise "^2.0.0" + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + +path-parse@^1.0.5: + version "1.0.5" + resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" + +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + +path-to-regexp@^1.7.0: + version "1.7.0" + resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz#59fde0f435badacba103a84e9d3bc64e96b9937d" + dependencies: + isarray "0.0.1" + +path-type@^1.0.0: + version "1.1.0" + resolved "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" + dependencies: + graceful-fs "^4.1.2" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +pathval@^1.0.0: + version "1.1.0" + resolved "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0" + +performance-now@^0.2.0: + version "0.2.0" + resolved "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" + +pify@^2.0.0: + version "2.3.0" + resolved "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + +pify@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" + +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + +process-nextick-args@~2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" + +process@^0.11.10: + version "0.11.10" + resolved "https://registry.npmjs.org/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + +promise@^7.1.1: + version "7.3.1" + resolved "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" + dependencies: + asap "~2.0.3" + +property-handlers@^1.0.0, property-handlers@^1.1.1: + version "1.1.1" + resolved "http://npm.corp.ebay.com/property-handlers/-/property-handlers-1.1.1.tgz#6bc84d587ac2dac0a7d9d342e59b545b062bd0e4" + +proxy-addr@~2.0.3: + version "2.0.3" + resolved "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.3.tgz#355f262505a621646b3130a728eb647e22055341" + dependencies: + forwarded "~0.1.2" + ipaddr.js "1.6.0" + +prr@~1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" + +punycode@1.3.2: + version "1.3.2" + resolved "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" + +punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + +q@^1.0.1: + version "1.5.1" + resolved "https://registry.npmjs.org/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" + +qs@6.5.1: + version "6.5.1" + resolved "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" + +qs@~6.4.0: + version "6.4.0" + resolved "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" + +querystring@0.2.0: + version "0.2.0" + resolved "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" + +range-parser@~1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" + +raptor-async@^1.0.0, raptor-async@^1.0.3, raptor-async@^1.1.2, raptor-async@^1.1.3: + version "1.1.3" + resolved "https://registry.npmjs.org/raptor-async/-/raptor-async-1.1.3.tgz#b83c3c9b603dc985c2c3a9f78d2b4073e6f6024c" + +raptor-cache@^2.0.4: + version "2.0.4" + resolved "https://registry.npmjs.org/raptor-cache/-/raptor-cache-2.0.4.tgz#e6af0c3038ca79cb1c83bc28793de9223902d4ab" + dependencies: + dissolve "github:deoxxa/dissolve#eeb806f2bad501548138c8e38d0adcf95d4d1bdb" + mkdirp "^0.5.1" + property-handlers "^1.1.1" + raptor-async "^1.1.3" + raptor-logging "^1.1.3" + raptor-util "^1.1.2" + through "^2.3.8" + uuid "^3.2.1" + +raptor-css-parser@^1.1.5: + version "1.1.5" + resolved "https://registry.npmjs.org/raptor-css-parser/-/raptor-css-parser-1.1.5.tgz#1de018d96121c8dc1f1c34686549aff71649d037" + dependencies: + raptor-async "^1.0.0" + raptor-promises "^1.0.1" + +raptor-detect@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/raptor-detect/-/raptor-detect-1.0.1.tgz#0a54c639056ef66dfd52be3945fa22cc6d1466f3" + +raptor-json@^1.0.1: + version "1.1.0" + resolved "https://registry.npmjs.org/raptor-json/-/raptor-json-1.1.0.tgz#70bd09b14e64f7d32ec50cce8377d6029c0f0876" + dependencies: + raptor-strings "^1.0.0" + +raptor-logging@^1.0.5, raptor-logging@^1.1.3: + version "1.1.3" + resolved "https://registry.npmjs.org/raptor-logging/-/raptor-logging-1.1.3.tgz#6bd8843632882e56387aa53bcafcbebaca695ca1" + dependencies: + raptor-polyfill "^1.0.0" + raptor-stacktraces "^1.0.0" + +raptor-objects@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/raptor-objects/-/raptor-objects-1.0.2.tgz#990dce360413b079e2e4af114f2e7344a71cee11" + dependencies: + raptor-util "^1.0.0" + +raptor-polyfill@^1.0.0, raptor-polyfill@^1.0.1, raptor-polyfill@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/raptor-polyfill/-/raptor-polyfill-1.0.2.tgz#6575bce762540d844056d71cef11662488f513ed" + +raptor-promises@^1.0.1, raptor-promises@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/raptor-promises/-/raptor-promises-1.0.3.tgz#d576b110e0423654f7fdf1721e28d42e4dc3c0eb" + dependencies: + q "^1.0.1" + raptor-util "^1.0.0" + +raptor-regexp@^1.0.0, raptor-regexp@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/raptor-regexp/-/raptor-regexp-1.0.1.tgz#ecf0f66c6671c0cd9f5e48c3705026c5509995c0" + +raptor-stacktraces@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/raptor-stacktraces/-/raptor-stacktraces-1.0.1.tgz#7f9fb271a7ddcdae291c6a6b15ddeffbcc008a76" + +raptor-strings@^1.0.0, raptor-strings@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/raptor-strings/-/raptor-strings-1.0.2.tgz#92ce2cb0153afe90470d8039a0255b4cf33ab5fc" + dependencies: + raptor-polyfill "^1.0.1" + +raptor-util@^1.0.0, raptor-util@^1.0.10, raptor-util@^1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/raptor-util/-/raptor-util-1.1.2.tgz#f2ee8076a9ae3eae2e65672e46a220074fa2dff3" + +raptor-util@^3.2.0: + version "3.2.0" + resolved "https://registry.npmjs.org/raptor-util/-/raptor-util-3.2.0.tgz#23b0c803c8f1ac8a1cae67d9a6388b49161c9758" + +raw-body@2.3.2: + version "2.3.2" + resolved "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz#bcd60c77d3eb93cde0050295c3f379389bc88f89" + dependencies: + bytes "3.0.0" + http-errors "1.6.2" + iconv-lite "0.4.19" + unpipe "1.0.0" + +read-pkg-up@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" + dependencies: + find-up "^1.0.0" + read-pkg "^1.0.0" + +read-pkg@^1.0.0: + version "1.1.0" + resolved "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" + dependencies: + load-json-file "^1.0.0" + normalize-package-data "^2.3.2" + path-type "^1.0.0" + +readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.3.5: + version "2.3.6" + resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +redent@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" + dependencies: + indent-string "^2.1.0" + strip-indent "^1.0.1" + +reflect-metadata@^0.1.12: + version "0.1.12" + resolved "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.12.tgz#311bf0c6b63cd782f228a81abe146a2bfa9c56f2" + +release-tools@^2.5.2: + version "2.7.0" + resolved "http://npm.corp.ebay.com/release-tools/-/release-tools-2.7.0.tgz#23abc8acdabd09625dcaf4900278e6a4eab0c4be" + dependencies: + bluebird "^2.9.12" + dateformat "^1.0.11" + require-all "^1.0.0" + semver "^4.3.1" + xtend "^4.0.1" + yargs "^6.6.0" + +repeating@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" + dependencies: + is-finite "^1.0.0" + +request@2.81.0: + version "2.81.0" + resolved "https://registry.npmjs.org/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" + dependencies: + aws-sign2 "~0.6.0" + aws4 "^1.2.1" + caseless "~0.12.0" + combined-stream "~1.0.5" + extend "~3.0.0" + forever-agent "~0.6.1" + form-data "~2.1.1" + har-validator "~4.2.1" + hawk "~3.1.3" + http-signature "~1.1.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.7" + oauth-sign "~0.8.1" + performance-now "^0.2.0" + qs "~6.4.0" + safe-buffer "^5.0.1" + stringstream "~0.0.4" + tough-cookie "~2.3.0" + tunnel-agent "^0.6.0" + uuid "^3.0.0" + +require-all@^1.0.0: + version "1.1.0" + resolved "https://registry.npmjs.org/require-all/-/require-all-1.1.0.tgz#7d50b9c9bc4d9d79bdfcc4b33f0fa46b7718ed5e" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + +require-main-filename@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" + +resolve-from@^1.0.0, resolve-from@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" + +resolve-from@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57" + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + +resolve@^1.3.2: + version "1.8.1" + resolved "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26" + dependencies: + path-parse "^1.0.5" + +rimraf@^2.6.2: + version "2.6.2" + resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" + dependencies: + glob "^7.0.5" + +rusha@^0.8.1: + version "0.8.13" + resolved "https://registry.npmjs.org/rusha/-/rusha-0.8.13.tgz#9a084e7b860b17bff3015b92c67a6a336191513a" + +safe-buffer@5.1.1: + version "5.1.1" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" + +safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + +safer-buffer@^2.0.2: + version "2.1.2" + resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + +samsam@1.3.0: + version "1.3.0" + resolved "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz#8d1d9350e25622da30de3e44ba692b5221ab7c50" + +"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.5.0: + version "5.5.0" + resolved "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" + +semver@^4.3.1: + version "4.3.6" + resolved "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da" + +send@0.16.2, send@^0.16.2: + version "0.16.2" + resolved "https://registry.npmjs.org/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1" + dependencies: + debug "2.6.9" + depd "~1.1.2" + destroy "~1.0.4" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "~1.6.2" + mime "1.4.1" + ms "2.0.0" + on-finished "~2.3.0" + range-parser "~1.2.0" + statuses "~1.4.0" + +serve-static@1.13.2: + version "1.13.2" + resolved "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1" + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.2" + send "0.16.2" + +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + +setprototypeof@1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz#66567e37043eeb4f04d91bd658c0cbefb55b8e04" + +setprototypeof@1.1.0: + version "1.1.0" + resolved "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" + +shorthash@0.0.2: + version "0.0.2" + resolved "https://registry.npmjs.org/shorthash/-/shorthash-0.0.2.tgz#59b268eecbde59038b30da202bcfbddeb2c4a4eb" + +signal-exit@^3.0.0: + version "3.0.2" + resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + +simple-sha1@^2.1.0: + version "2.1.1" + resolved "https://registry.npmjs.org/simple-sha1/-/simple-sha1-2.1.1.tgz#93f3b7f2e8dfdc056c32793e5d47b58d311b140d" + dependencies: + rusha "^0.8.1" + +sinon-chai@^3.0.0: + version "3.2.0" + resolved "https://registry.npmjs.org/sinon-chai/-/sinon-chai-3.2.0.tgz#ed995e13a8a3cfccec18f218d9b767edc47e0715" + +sinon@^6.0.0: + version "6.1.3" + resolved "https://registry.npmjs.org/sinon/-/sinon-6.1.3.tgz#98e7d716b7b11f7f1200e9c997e74f50ae094660" + dependencies: + "@sinonjs/formatio" "^2.0.0" + "@sinonjs/samsam" "^2.0.0" + diff "^3.5.0" + lodash.get "^4.4.2" + lolex "^2.4.2" + nise "^1.3.3" + supports-color "^5.4.0" + type-detect "^4.0.8" + +sntp@1.x.x: + version "1.0.9" + resolved "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" + dependencies: + hoek "2.x.x" + +source-map-support@^0.5.6: + version "0.5.6" + resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.6.tgz#4435cee46b1aab62b8e8610ce60f788091c51c13" + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@0.5.x, source-map@^0.5.3: + version "0.5.7" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + +source-map@^0.6.0, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + +spdx-correct@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz#05a5b4d7153a195bc92c3c425b69f3b2a9524c82" + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz#2c7ae61056c714a5b9b9b2b2af7d311ef5c78fe9" + +spdx-expression-parse@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz#7a7cd28470cc6d3a1cfe6d66886f6bc430d3ac87" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + +sshpk@^1.7.0: + version "1.14.2" + resolved "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz#c6fc61648a3d9c4e764fd3fcdf4ea105e492ba98" + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + dashdash "^1.12.0" + getpass "^0.1.1" + safer-buffer "^2.0.2" + optionalDependencies: + bcrypt-pbkdf "^1.0.0" + ecc-jsbn "~0.1.1" + jsbn "~0.1.0" + tweetnacl "~0.14.0" + +stackframe@^1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/stackframe/-/stackframe-1.0.4.tgz#357b24a992f9427cba6b545d96a14ed2cbca187b" + +"statuses@>= 1.3.1 < 2", "statuses@>= 1.4.0 < 2": + version "1.5.0" + resolved "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + +statuses@~1.4.0: + version "1.4.0" + resolved "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" + +stream-browserify@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db" + dependencies: + inherits "~2.0.1" + readable-stream "^2.0.2" + +string-width@^1.0.1, string-width@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +string_decoder@^1.1.1, string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + dependencies: + safe-buffer "~5.1.0" + +stringstream@~0.0.4: + version "0.0.6" + resolved "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz#7880225b0d4ad10e30927d167a1d6f2fd3b33a72" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + dependencies: + ansi-regex "^2.0.0" + +strip-bom@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" + dependencies: + is-utf8 "^0.2.0" + +strip-indent@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" + dependencies: + get-stdin "^4.0.1" + +strip-indent@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" + +strip-json-comments@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + +supports-color@5.4.0, supports-color@^5.3.0, supports-color@^5.4.0: + version "5.4.0" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" + dependencies: + has-flag "^3.0.0" + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + +text-encoding@^0.6.4: + version "0.6.4" + resolved "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz#e399a982257a276dae428bb92845cb71bdc26d19" + +through@^2.3.8: + version "2.3.8" + resolved "https://registry.npmjs.org/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + +tough-cookie@~2.3.0: + version "2.3.4" + resolved "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655" + dependencies: + punycode "^1.4.1" + +trim-newlines@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" + +try-require@^1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/try-require/-/try-require-1.2.1.tgz#34489a2cac0c09c1cc10ed91ba011594d4333be2" + +ts-node@^7: + version "7.0.0" + resolved "https://registry.npmjs.org/ts-node/-/ts-node-7.0.0.tgz#a94a13c75e5e1aa6b82814b84c68deb339ba7bff" + dependencies: + arrify "^1.0.0" + buffer-from "^1.1.0" + diff "^3.1.0" + make-error "^1.1.1" + minimist "^1.2.0" + mkdirp "^0.5.1" + source-map-support "^0.5.6" + yn "^2.0.0" + +tslib@1.9.0: + version "1.9.0" + resolved "https://registry.npmjs.org/tslib/-/tslib-1.9.0.tgz#e37a86fda8cbbaf23a057f473c9f4dc64e5fc2e8" + +tslib@^1.7.1, tslib@^1.8.0, tslib@^1.8.1: + version "1.9.3" + resolved "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" + +tslint-config-airbnb@^5.5.0: + version "5.9.2" + resolved "https://registry.npmjs.org/tslint-config-airbnb/-/tslint-config-airbnb-5.9.2.tgz#fdb37a695ec09b663d5ee92e7852a7a9337ec44c" + dependencies: + tslint-consistent-codestyle "^1.10.0" + tslint-eslint-rules "^5.3.1" + tslint-microsoft-contrib "~5.0.1" + +tslint-consistent-codestyle@^1.10.0: + version "1.13.2" + resolved "https://registry.npmjs.org/tslint-consistent-codestyle/-/tslint-consistent-codestyle-1.13.2.tgz#c60662f08a83d62797e47e5d74737470b5e17714" + dependencies: + "@fimbul/bifrost" "^0.11.0" + tslib "^1.7.1" + tsutils "^2.27.0" + +tslint-eslint-rules@^5.3.1: + version "5.3.1" + resolved "https://registry.npmjs.org/tslint-eslint-rules/-/tslint-eslint-rules-5.3.1.tgz#10dec4361df0b3e4385d91ff8e0226bda4ec2ad4" + dependencies: + doctrine "0.7.2" + tslib "1.9.0" + tsutils "2.8.0" + +tslint-microsoft-contrib@~5.0.1: + version "5.0.3" + resolved "https://registry.npmjs.org/tslint-microsoft-contrib/-/tslint-microsoft-contrib-5.0.3.tgz#6fc3e238179cd72045c2b422e4d655f4183a8d5c" + dependencies: + tsutils "^2.12.1" + +tslint@^5.8.0: + version "5.10.0" + resolved "http://npm.corp.ebay.com/tslint/-/tslint-5.10.0.tgz#11e26bccb88afa02dd0d9956cae3d4540b5f54c3" + dependencies: + babel-code-frame "^6.22.0" + builtin-modules "^1.1.1" + chalk "^2.3.0" + commander "^2.12.1" + diff "^3.2.0" + glob "^7.1.1" + js-yaml "^3.7.0" + minimatch "^3.0.4" + resolve "^1.3.2" + semver "^5.3.0" + tslib "^1.8.0" + tsutils "^2.12.1" + +tsutils@2.8.0: + version "2.8.0" + resolved "https://registry.npmjs.org/tsutils/-/tsutils-2.8.0.tgz#0160173729b3bf138628dd14a1537e00851d814a" + dependencies: + tslib "^1.7.1" + +tsutils@^2.12.1, tsutils@^2.24.0, tsutils@^2.27.0: + version "2.27.2" + resolved "https://registry.npmjs.org/tsutils/-/tsutils-2.27.2.tgz#60ba88a23d6f785ec4b89c6e8179cac9b431f1c7" + dependencies: + tslib "^1.8.1" + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + dependencies: + safe-buffer "^5.0.1" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + dependencies: + prelude-ls "~1.1.2" + +type-detect@0.1.1: + version "0.1.1" + resolved "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz#0ba5ec2a885640e470ea4e8505971900dac58822" + +type-detect@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz#762217cc06db258ec48908a1298e8b95121e8ea2" + +type-detect@^4.0.0, type-detect@^4.0.8: + version "4.0.8" + resolved "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + +type-is@~1.6.15, type-is@~1.6.16: + version "1.6.16" + resolved "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz#f89ce341541c672b25ee7ae3c73dee3b2be50194" + dependencies: + media-typer "0.3.0" + mime-types "~2.1.18" + +typescript@^2.7.2: + version "2.9.2" + resolved "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz#1cbf61d05d6b96269244eb6a3bce4bd914e0f00c" + +uglify-js@^3.4.0: + version "3.4.4" + resolved "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.4.tgz#92e79532a3aeffd4b6c65755bdba8d5bad98d607" + dependencies: + commander "~2.16.0" + source-map "~0.6.1" + +unc-path-regex@^0.1.0: + version "0.1.2" + resolved "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + +url@^0.11.0: + version "0.11.0" + resolved "https://registry.npmjs.org/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" + dependencies: + punycode "1.3.2" + querystring "0.2.0" + +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + +util@0.10.3: + version "0.10.3" + resolved "https://registry.npmjs.org/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" + dependencies: + inherits "2.0.1" + +util@^0.11.0: + version "0.11.0" + resolved "https://registry.npmjs.org/util/-/util-0.11.0.tgz#c5f391beb244103d799b21077a926fef8769e1fb" + dependencies: + inherits "2.0.3" + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + +uuid@^3.0.0, uuid@^3.2.1: + version "3.3.2" + resolved "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" + +validate-npm-package-license@^3.0.1: + version "3.0.3" + resolved "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz#81643bcbef1bdfecd4623793dc4648948ba98338" + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + +vary@~1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +warp10@^1.0.0: + version "1.3.6" + resolved "https://registry.npmjs.org/warp10/-/warp10-1.3.6.tgz#edffff4f06382d2e469ba88ccfcb95bb81d3bda6" + +which-module@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" + +wordwrap@~1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + +wrap-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + +wrappy@1: + version "1.0.2" + resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + +xtend@^4.0.1: + version "4.0.1" + resolved "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" + +y18n@^3.2.1: + version "3.2.1" + resolved "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" + +yargs-parser@^4.2.0: + version "4.2.1" + resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz#29cceac0dc4f03c6c87b4a9f217dd18c9f74871c" + dependencies: + camelcase "^3.0.0" + +yargs@^6.6.0: + version "6.6.0" + resolved "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz#782ec21ef403345f830a808ca3d513af56065208" + dependencies: + camelcase "^3.0.0" + cliui "^3.2.0" + decamelize "^1.1.1" + get-caller-file "^1.0.1" + os-locale "^1.4.0" + read-pkg-up "^1.0.1" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^1.0.2" + which-module "^1.0.0" + y18n "^3.2.1" + yargs-parser "^4.2.0" + +yn@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz#e5adabc8acf408f6385fc76495684c88e6af689a"