diff --git a/.gitignore b/.gitignore index 1f06b3d..3a4ae24 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ node_modules env.sh stash-passport-demo -data \ No newline at end of file +data +out \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..bedc202 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,18 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "attach", + "name": "Attach to Remote", + "address": localhost, + "port": 9229, + "protocol": "inspector", + //"localRoot": "${workspaceFolder}", + //"remoteRoot": "Absolute path to the remote directory containing the program" + } + ] +} \ No newline at end of file diff --git a/bin/install b/bin/install new file mode 100755 index 0000000..409446e --- /dev/null +++ b/bin/install @@ -0,0 +1,6 @@ +#! /usr/bin/env bash + +. /home/vagrant/.nvm/nvm.sh + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +eval "nvm exec 8.9.0 npm install --production --prefix ${DIR}/../ $@" \ No newline at end of file diff --git a/bin/loom b/bin/loom.ts similarity index 82% rename from bin/loom rename to bin/loom.ts index 191ad8b..dc06c8f 100755 --- a/bin/loom +++ b/bin/loom.ts @@ -1,12 +1,13 @@ #! /usr/bin/env node 'use strict'; -var loom = require('..'); -var path = require('path'); -var util = require('util'); -var Loader = require('yaml-config-loader'); -var yargs = require('yargs'); -var loader = new Loader({stopOnError: true}); +import * as loom from '../index'; +import * as path from 'path'; +import * as util from 'util'; +import * as yargs from 'yargs'; +import * as Loader from 'yaml-config-loader'; + +const loader = new Loader({stopOnError: true}); loader.on('error', function(error) { if (error.name === 'YAMLException') { @@ -15,7 +16,7 @@ loader.on('error', function(error) { throw error; }); -var argv = yargs +yargs .describe('port', 'The port to listen on.') .alias('port', 'p') .describe('config', 'A YAML config file or directory of yaml files to load, can be invoked multiple times and later files will override earlier.') @@ -23,7 +24,7 @@ var argv = yargs .describe('help', 'Display this help message.') .alias('help', 'h'); -argv = yargs.argv; +const argv = yargs.argv; if (argv.help) { yargs.showHelp(); @@ -44,7 +45,7 @@ loader.addMapping({ storageCompress: 'storage.compress', }); -var configKeys = [ +const configKeys = [ 'server', 'db', 'storage', @@ -53,17 +54,18 @@ var configKeys = [ // When you use remapping, later mappings tend to replace the entire // structure rather than overwriting the component key. -var loaderAddOptions = { - deepMerge: configKeys, +const loaderAddOptions = { + deepMerge: configKeys }; -loader.add(path.resolve(path.join(__dirname, '..', 'defaults.yaml')), loaderAddOptions); +loader.add(path.resolve(path.join(process.env.PWD, 'defaults.yaml')), loaderAddOptions); loader.addAndNormalizeObject(process.env, loaderAddOptions); if (argv.config) { if (typeof argv.config === 'string') { argv.config = [argv.config]; } + for (let filePath of argv.config) { loader.add(path.resolve(filePath), loaderAddOptions); } @@ -71,7 +73,7 @@ if (argv.config) { loader.addAndNormalizeObject(argv, loaderAddOptions); -var cachedConfig = null; +let cachedConfig = null; module.exports = { load: function(cb) { if (cachedConfig) { diff --git a/bin/mergeMigrations b/bin/mergeMigrations new file mode 100755 index 0000000..18c2a3e --- /dev/null +++ b/bin/mergeMigrations @@ -0,0 +1,61 @@ +#! /usr/bin/env node +'use strict'; + +const util = require('util'); +const fs = require('fs'); +const path = require('path'); +const Loader = require('yaml-config-loader'); +const yargs = require('yargs'); +const loader = new Loader(); + +const argv = yargs + .describe('config', 'A YAML config file or directory of yaml files to load, can be invoked multiple times and later files will override earlier.') + .alias('config', 'c') + .alias('knexfile', 'k') + .argv; + +loader.on('error', function(error) { + if (error.name === 'YAMLException') { + console.error(util.print('Error parsing YAML file `', error.filePath, '`:', error.reason)); + console.error(error); + } +}); + +loader.add(path.resolve(path.join(__dirname, '..', 'defaults.yaml'))); + +if (argv.config) { + loader.add(path.resolve(argv.config)); +} + +loader.addAndNormalizeObject({}); + +loader.load(function(error, config) { + let baseMigrationDir = path.resolve(path.join(__dirname, '..', 'baseMigrations')); + let migrationDir = path.resolve(path.join(__dirname, '..', 'migrations')); + let pluginMigrationDir = config.pluginDirectory !== null ? path.resolve(path.join(config.pluginDirectory, 'migrations')) : null; + + fs.readdir(baseMigrationDir, function(error, files) { + if (error) { + console.error(error); + process.exit(1); + } + files.forEach(function(file) { + fs.createReadStream(path.join(baseMigrationDir, file)) + .pipe(fs.createWriteStream(path.join(migrationDir, file))); + + }); + }); + + if (pluginMigrationDir) { + fs.readdir(pluginMigrationDir, function(error, files) { + if (error) { + console.error(error); + process.exit(1); + } + files.forEach(function(file) { + fs.createReadStream(path.join(pluginMigrationDir, file)) + .pipe(fs.createWriteStream(path.join(migrationDir, file))); }); + }); + } +}); + diff --git a/bin/migrate b/bin/migrate new file mode 100755 index 0000000..8451232 --- /dev/null +++ b/bin/migrate @@ -0,0 +1,68 @@ +#! /bin/bash + +MY_PATH="`dirname \"$0\"`" # relative +MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized + +while test $# -gt 0; do + case "$1" in + -h|--help) + echo "Handles merging migrations from plugins and running them." + echo " " + echo "options:" + echo "-h, --help show help" + echo "-c, specify the full path to config.yaml to use." + echo "-k, specify the full path to the knexfile to use." + echo "-e, --env specify the enviroment from the knexfile to use." + exit 0 + ;; + -c) + shift + if test $# -gt 0; then + config=$1 + else + echo "no config specified" + exit 1 + fi + shift + ;; + -k) + shift + if test $# -gt 0; then + knexfile=$1 + else + echo "no knexfile specified" + exit 1 + fi + shift + ;; + -e|--env) + shift + if test $# -gt 0; then + env=$1 + else + echo "no enviroment specified" + exit 1 + fi + shift + ;; + *) + break + ;; + esac +done + +if [[ -z $env ]]; then + enviroment="production" +else + echo "Set default enviroment as : $env" + enviroment=$env +fi + +if [[ -z $knexfile ]]; then + node_modules/.bin/knex-migrate up --env $enviroment +else + cp $knexfile $MY_PATH/../alt-knex.js + node_modules/.bin/knex-migrate up --env $enviroment --knexfile $MY_PATH/../alt-knex.js + rm $MY_PATH/../alt-knex.js +fi + diff --git a/bin/start b/bin/start new file mode 100755 index 0000000..68413e8 --- /dev/null +++ b/bin/start @@ -0,0 +1,6 @@ +#! /usr/bin/env bash + +. /home/vagrant/.nvm/nvm.sh + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +eval "nvm exec 8.9.0 npm run start --prefix ${DIR}/../ $@" \ No newline at end of file diff --git a/bin/stream b/bin/stream deleted file mode 100755 index 895765c..0000000 --- a/bin/stream +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env node - -var url = process.argv[2] -var streamid = process.argv[3] -if(!url || !streamid){ - console.error(`Reads input from stdin and streams it to the server - -usage: ${process.argv[1]} url streamid [--force]`) - process.exit(1) -} - -var client = require('../lib/client')({ - url: url - }) - -var stream = client.createWriteStream({}, { - id: streamid, - force: process.argv.indexOf('--force') > 1 -}) - -process.stdin.pipe(stream) diff --git a/bin/stream.ts b/bin/stream.ts new file mode 100755 index 0000000..86da89e --- /dev/null +++ b/bin/stream.ts @@ -0,0 +1,21 @@ +#!/usr/bin/env node +'use strict'; + +const url = process.argv[2]; +const streamid = process.argv[3]; + +if (!url || !streamid) { + console.error(`Reads input from stdin and streams it to the server + +usage: ${process.argv[1]} url streamid [--force]`); + process.exit(1); +} + +let client = require('../lib/client')({url: url}); + +let stream = client.createWriteStream({}, { + id: streamid, + force: process.argv.indexOf('--force') > 1 +}); + +process.stdin.pipe(stream); diff --git a/migrations/0001-rethink-to-file-streams.js b/dataMigration/0001-rethink-to-file-streams.js similarity index 96% rename from migrations/0001-rethink-to-file-streams.js rename to dataMigration/0001-rethink-to-file-streams.js index e9d3252..8a47b62 100644 --- a/migrations/0001-rethink-to-file-streams.js +++ b/dataMigration/0001-rethink-to-file-streams.js @@ -1,7 +1,7 @@ 'use strict'; // Run as: -// node migrations/0001-rethink-to-file-streams -c loom.yaml | bunyan +// node dataMigration/0001-rethink-to-file-streams -c loom.yaml | bunyan var loader = require('../bin/loom'); var log = require('../lib/logger').getLogger('migration 0001'); diff --git a/dataMigration/0002-rethink-to-postgre.ts b/dataMigration/0002-rethink-to-postgre.ts new file mode 100644 index 0000000..d7eab15 --- /dev/null +++ b/dataMigration/0002-rethink-to-postgre.ts @@ -0,0 +1,89 @@ +'use strict'; + +// Run as: +// node dataMigration/0001-rethink-to-file-streams -c loom.yaml | bunyan + +var loader = require("../bin/loom"); +import * as logger from "../lib/logger"; +let log = logger.getLogger('migration 0002'); +import { rethink } from "../lib/rethink"; +import { Database } from "../lib/knex"; +import * as co from 'co'; +import * as fs from 'fs'; + +import { RethinkStorage } from "../lib/models/rethink_storage"; +import { PostgreStorage } from "../lib/models/postgre_storage"; + +var listRethinkStreams = function(cb) { + var Meta = rethink.models.Meta; + Meta.run(function(err, streams) { + if (err) { return cb(err); } + + cb(null, streams.map((s)=>s)); + }); +}; + +// returns a promise that resolves to true or false +var metaRowExists = function(id, postgreStorage) { + return new Promise(function(accept, reject) { + postgreStorage.loadStream(id, (err) =>{ + accept(err); + }); + }); +}; + +// returns a promise that resoslves when src if fully written to dest +var writeStream = function(src, dest) { + return new Promise(function(accept, reject) { + src + .pipe(dest) + .on('finish', accept) + .on('error', reject); + }); +}; + + +loader.load(function(err, config) { + log.info(config, 'using config:'); + + try { + rethink.connect(config.db); + var rethinkStorage = new RethinkStorage(config.storage); + var postgreStorage = new PostgreStorage(config.storage); + + listRethinkStreams(function(err, streamIds) { + if (err) { + return log.error(err); + } + + co(function*() { + for (let meta of streamIds) { + var exists = yield metaRowExists(meta.id, postgreStorage); + + if (exists) { + log.info(`exists, skipping: ${meta.id}`); + log.info(`${exists}`); + } + else { + log.info(`writing stream to: ${meta.id}`); + + let metaData = meta.meta.metaData; + + postgreStorage.saveStream(meta.id,meta.meta); + + } + } + + setTimeout(()=> rethink.thinky.r.getPool().drain(), 1000); + }).catch(function(err) { + console.error(err.stack); + }); + }); + } + catch (e) { + console.error(e.stack); + } +}); + + + diff --git a/defaults.yaml b/defaults.yaml index 361eb34..b309353 100644 --- a/defaults.yaml +++ b/defaults.yaml @@ -1,5 +1,5 @@ # server host to listen on, defaults to localhost -host: 'localhost' +host: 0.0.0.0 # server port to listen on, defaults to 3060 port: 3060 diff --git a/dist/bin/loom.js b/dist/bin/loom.js new file mode 100755 index 0000000..d51d431 --- /dev/null +++ b/dist/bin/loom.js @@ -0,0 +1,84 @@ +#! /usr/bin/env node +'use strict'; +Object.defineProperty(exports, "__esModule", { value: true }); +const loom = require("../index"); +const path = require("path"); +const util = require("util"); +const yargs = require("yargs"); +const Loader = require("yaml-config-loader"); +const loader = new Loader({ stopOnError: true }); +loader.on('error', function (error) { + if (error.name === 'YAMLException') { + console.error({ err: error }, util.print('Error parsing YAML file `', error.filePath, '`:', error.reason)); + } + throw error; +}); +yargs + .describe('port', 'The port to listen on.') + .alias('port', 'p') + .describe('config', 'A YAML config file or directory of yaml files to load, can be invoked multiple times and later files will override earlier.') + .alias('config', 'c') + .describe('help', 'Display this help message.') + .alias('help', 'h'); +const argv = yargs.argv; +if (argv.help) { + yargs.showHelp(); + process.exit(); +} +loader.addMapping({ + host: 'server.host', + port: 'server.port', + dbHost: 'db.host', + dbPort: 'db.port', + dbName: 'db.db', + storageLogsTable: 'storage.logsTable', + storageMetaTable: 'storage.metaTable', + storageDataDir: 'storage.dataDir', + storageTailTimeout: 'storage.tailTimeout', + storageCompress: 'storage.compress', +}); +const configKeys = [ + 'server', + 'db', + 'storage', + 'tokens', +]; +const loaderAddOptions = { + deepMerge: configKeys +}; +loader.add(path.resolve(path.join(process.env.PWD, 'defaults.yaml')), loaderAddOptions); +loader.addAndNormalizeObject(process.env, loaderAddOptions); +if (argv.config) { + if (typeof argv.config === 'string') { + argv.config = [argv.config]; + } + for (let filePath of argv.config) { + loader.add(path.resolve(filePath), loaderAddOptions); + } +} +loader.addAndNormalizeObject(argv, loaderAddOptions); +let cachedConfig = null; +module.exports = { + load: function (cb) { + if (cachedConfig) { + if (typeof cb == 'function') { + cb(null, cachedConfig); + } + return cachedConfig; + } + else { + loader.load(function (err, config) { + cachedConfig = config; + cb(err, config); + }); + } + }, +}; +if (!module.parent) { + loader.load(function (error, config) { + if (error) + throw error; + loom.run(config); + }); +} +//# sourceMappingURL=loom.js.map \ No newline at end of file diff --git a/dist/bin/loom.js.map b/dist/bin/loom.js.map new file mode 100644 index 0000000..a7f18db --- /dev/null +++ b/dist/bin/loom.js.map @@ -0,0 +1 @@ +{"version":3,"file":"loom.js","sourceRoot":"","sources":["../../bin/loom.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/bin/stream.js b/dist/bin/stream.js new file mode 100644 index 0000000..aeaa128 --- /dev/null +++ b/dist/bin/stream.js @@ -0,0 +1,17 @@ +#!/usr/bin/env node +'use strict'; +const url = process.argv[2]; +const streamid = process.argv[3]; +if (!url || !streamid) { + console.error(`Reads input from stdin and streams it to the server + +usage: ${process.argv[1]} url streamid [--force]`); + process.exit(1); +} +let client = require('../lib/client')({ url: url }); +let stream = client.createWriteStream({}, { + id: streamid, + force: process.argv.indexOf('--force') > 1 +}); +process.stdin.pipe(stream); +//# sourceMappingURL=stream.js.map \ No newline at end of file diff --git a/dist/bin/stream.js.map b/dist/bin/stream.js.map new file mode 100644 index 0000000..bdfaf70 --- /dev/null +++ b/dist/bin/stream.js.map @@ -0,0 +1 @@ +{"version":3,"file":"stream.js","sourceRoot":"","sources":["../../bin/stream.ts"],"names":[],"mappings":";AACA,YAAY,CAAC;AAEb,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC5B,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAEjC,IAAI,CAAC,GAAG,IAAI,CAAC,QAAQ,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC;;SAEP,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC;IACjD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;CACjB;AAED,IAAI,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC,EAAC,GAAG,EAAE,GAAG,EAAC,CAAC,CAAC;AAElD,IAAI,MAAM,GAAG,MAAM,CAAC,iBAAiB,CAAC,EAAE,EAAE;IACxC,EAAE,EAAE,QAAQ;IACZ,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC;CAC3C,CAAC,CAAC;AAEH,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC"} \ No newline at end of file diff --git a/dist/dataMigration/0002-rethink-to-postgre.js b/dist/dataMigration/0002-rethink-to-postgre.js new file mode 100644 index 0000000..664c362 --- /dev/null +++ b/dist/dataMigration/0002-rethink-to-postgre.js @@ -0,0 +1,67 @@ +'use strict'; +Object.defineProperty(exports, "__esModule", { value: true }); +var loader = require("../bin/loom"); +const logger = require("../lib/logger"); +let log = logger.getLogger('migration 0002'); +const rethink_1 = require("../lib/rethink"); +const co = require("co"); +const rethink_storage_1 = require("../lib/models/rethink_storage"); +const postgre_storage_1 = require("../lib/models/postgre_storage"); +var listRethinkStreams = function (cb) { + var Meta = rethink_1.rethink.models.Meta; + Meta.run(function (err, streams) { + if (err) { + return cb(err); + } + cb(null, streams.map((s) => s)); + }); +}; +var metaRowExists = function (id, postgreStorage) { + return new Promise(function (accept, reject) { + postgreStorage.loadStream(id, (err) => { + accept(err); + }); + }); +}; +var writeStream = function (src, dest) { + return new Promise(function (accept, reject) { + src + .pipe(dest) + .on('finish', accept) + .on('error', reject); + }); +}; +loader.load(function (err, config) { + log.info(config, 'using config:'); + try { + rethink_1.rethink.connect(config.db); + var rethinkStorage = new rethink_storage_1.RethinkStorage(config.storage); + var postgreStorage = new postgre_storage_1.PostgreStorage(config.storage); + listRethinkStreams(function (err, streamIds) { + if (err) { + return log.error(err); + } + co(function* () { + for (let meta of streamIds) { + var exists = yield metaRowExists(meta.id, postgreStorage); + if (exists) { + log.info(`exists, skipping: ${meta.id}`); + log.info(`${exists}`); + } + else { + log.info(`writing stream to: ${meta.id}`); + let metaData = meta.meta.metaData; + postgreStorage.saveStream(meta.id, meta.meta); + } + } + setTimeout(() => rethink_1.rethink.thinky.r.getPool().drain(), 1000); + }).catch(function (err) { + console.error(err.stack); + }); + }); + } + catch (e) { + console.error(e.stack); + } +}); +//# sourceMappingURL=0002-rethink-to-postgre.js.map \ No newline at end of file diff --git a/dist/dataMigration/0002-rethink-to-postgre.js.map b/dist/dataMigration/0002-rethink-to-postgre.js.map new file mode 100644 index 0000000..c4f4d03 --- /dev/null +++ b/dist/dataMigration/0002-rethink-to-postgre.js.map @@ -0,0 +1 @@ +{"version":3,"file":"0002-rethink-to-postgre.js","sourceRoot":"","sources":["../../dataMigration/0002-rethink-to-postgre.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/index.js b/dist/index.js new file mode 100644 index 0000000..aebd370 --- /dev/null +++ b/dist/index.js @@ -0,0 +1,14 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const knex_1 = require("./lib/knex"); +const server_1 = require("./lib/api/server"); +require("./typings/TConfig"); +exports.run = (config) => { + var server = new server_1.Server(config); + server.log.info({ config: config }, "Configuration loaded"); + knex_1.Database.knex.select('id').from('meta').limit(1); + server.listen(config.server.port, config.server.host, function () { + server.log.info("%s listening at %s", server.server.name, server.server.url); + }); +}; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/index.js.map b/dist/index.js.map new file mode 100644 index 0000000..b1aa83f --- /dev/null +++ b/dist/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,qCAAsC;AACtC,6CAA0C;AAC1C,6BAA2B;AAEd,QAAA,GAAG,GAAG,CAAC,MAAe,EAAE,EAAE;IACrC,IAAI,MAAM,GAAG,IAAI,eAAM,CAAC,MAAM,CAAC,CAAC;IAChC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,sBAAsB,CAAC,CAAC;IAG5D,eAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAEjD,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE;QACpD,MAAM,CAAC,GAAG,CAAC,IAAI,CACb,oBAAoB,EACpB,MAAM,CAAC,MAAM,CAAC,IAAI,EAClB,MAAM,CAAC,MAAM,CAAC,GAAG,CAClB,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC"} \ No newline at end of file diff --git a/dist/knexfile.js b/dist/knexfile.js new file mode 100644 index 0000000..d4d1964 --- /dev/null +++ b/dist/knexfile.js @@ -0,0 +1,36 @@ +'use strict'; +module.exports = { + test: { + client: 'postgresql', + connection: { + database: 'probodb_test', + user: 'probodb_test', + password: 'password', + host: 'localhost', + }, + pool: { + min: 2, + max: 10, + }, + migrations: { + tableName: 'knex_migrations', + }, + }, + production: { + client: 'postgresql', + connection: { + database: 'log_db', + user: 'probodb', + password: 'password', + host: 'localhost', + }, + pool: { + min: 2, + max: 10, + }, + migrations: { + tableName: 'knex_migrations', + }, + }, +}; +//# sourceMappingURL=knexfile.js.map \ No newline at end of file diff --git a/dist/knexfile.js.map b/dist/knexfile.js.map new file mode 100644 index 0000000..ce9d9f8 --- /dev/null +++ b/dist/knexfile.js.map @@ -0,0 +1 @@ +{"version":3,"file":"knexfile.js","sourceRoot":"","sources":["../knexfile.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,MAAM,CAAC,OAAO,GAAG;IACf,IAAI,EAAE;QACJ,MAAM,EAAE,YAAY;QACpB,UAAU,EAAE;YACV,QAAQ,EAAE,cAAc;YACxB,IAAI,EAAE,cAAc;YACpB,QAAQ,EAAE,UAAU;YACpB,IAAI,EAAE,WAAW;SAClB;QACD,IAAI,EAAE;YACJ,GAAG,EAAE,CAAC;YACN,GAAG,EAAE,EAAE;SACR;QACD,UAAU,EAAE;YACV,SAAS,EAAE,iBAAiB;SAC7B;KACF;IAED,UAAU,EAAE;QACV,MAAM,EAAE,YAAY;QACpB,UAAU,EAAE;YACV,QAAQ,EAAE,QAAQ;YAClB,IAAI,EAAE,SAAS;YACf,QAAQ,EAAE,UAAU;YACpB,IAAI,EAAE,WAAW;SAClB;QACD,IAAI,EAAE;YACJ,GAAG,EAAE,CAAC;YACN,GAAG,EAAE,EAAE;SACR;QACD,UAAU,EAAE;YACV,SAAS,EAAE,iBAAiB;SAC7B;KACF;CACF,CAAC"} \ No newline at end of file diff --git a/dist/lib/api/auth.js b/dist/lib/api/auth.js new file mode 100644 index 0000000..59722d0 --- /dev/null +++ b/dist/lib/api/auth.js @@ -0,0 +1,44 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const passport = require("passport"); +const Strategy = require("passport-http-bearer"); +const BearerStrategy = Strategy.Strategy; +exports.Auth = function (config) { + let authlib = { + verify: function (token, done) { + process.nextTick(function () { + var user = { + token: token + }; + const found = config.tokens.indexOf(token) > -1; + if (!found) { + return done(null, false); + } + return done(null, user); + }); + }, + auth: function (req, res, next) { } + }; + passport.use(new BearerStrategy({ realm: "API Key" }, (token, done) => { + return authlib.verify(token, done); + })); + var tokenAuth = passport.authenticate("bearer", { + session: false, + failWithError: true + }); + authlib.auth = function (req, res, next) { + if (Array.isArray(config.tokens)) { + return tokenAuth(req, res, err => { + if (err) { + err.statusCode = err.status; + } + return next(err); + }); + } + else { + next(); + } + }; + return authlib; +}; +//# sourceMappingURL=auth.js.map \ No newline at end of file diff --git a/dist/lib/api/auth.js.map b/dist/lib/api/auth.js.map new file mode 100644 index 0000000..8f11b9b --- /dev/null +++ b/dist/lib/api/auth.js.map @@ -0,0 +1 @@ +{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../lib/api/auth.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,qCAAqC;AACrC,iDAAiD;AAEjD,MAAM,cAAc,GAAG,QAAQ,CAAC,QAAQ,CAAC;AAe5B,QAAA,IAAI,GAAG,UAAS,MAAkB;IAC7C,IAAI,OAAO,GAAG;QACZ,MAAM,EAAE,UACN,KAAa,EACb,IAA6D;YAE7D,OAAO,CAAC,QAAQ,CAAC;gBACf,IAAI,IAAI,GAAG;oBACT,KAAK,EAAE,KAAK;iBACb,CAAC;gBAEF,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;gBAEhD,IAAI,CAAC,KAAK,EAAE;oBACV,OAAO,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;iBAC1B;gBACD,OAAO,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YAC1B,CAAC,CAAC,CAAC;QACL,CAAC;QACD,IAAI,EAAE,UAAS,GAAG,EAAE,GAAG,EAAE,IAAI,IAAG,CAAC;KAClC,CAAC;IAEF,QAAQ,CAAC,GAAG,CACV,IAAI,cAAc,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QAEvD,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACrC,CAAC,CAAC,CACH,CAAC;IAEF,IAAI,SAAS,GAAG,QAAQ,CAAC,YAAY,CAAC,QAAQ,EAAE;QAC9C,OAAO,EAAE,KAAK;QACd,aAAa,EAAE,IAAI;KACpB,CAAC,CAAC;IAGH,OAAO,CAAC,IAAI,GAAG,UAAS,GAAG,EAAE,GAAG,EAAE,IAAI;QACpC,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE;YAChC,OAAO,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE;gBAY/B,IAAI,GAAG,EAAE;oBACP,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC,MAAM,CAAC;iBAC7B;gBAED,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;YACnB,CAAC,CAAC,CAAC;SACJ;aAAM;YACL,IAAI,EAAE,CAAC;SACR;IACH,CAAC,CAAC;IAEF,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC"} \ No newline at end of file diff --git a/dist/lib/api/controllers/index.js b/dist/lib/api/controllers/index.js new file mode 100644 index 0000000..53b363c --- /dev/null +++ b/dist/lib/api/controllers/index.js @@ -0,0 +1,188 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const co_1 = require("co"); +const postgre_stream_backend_filesystem_1 = require("../../models/postgre_stream_backend_filesystem"); +const logger_1 = require("../../logger"); +const Storage = postgre_stream_backend_filesystem_1.FileSystemStorage; +const log = logger_1.getLogger("").child({ component: "server" }); +function handleError(res, err, next) { + res.status(err.status || 500); + res.json({ error: err.message }); + next(); +} +var activeStreams = (function () { + var active = new (require("events")).EventEmitter(); + active.streams = {}; + active.on("added", function (id) { + log.info("Spy Stream added: " + id); + active.streams[id] = true; + }); + active.on("removed", function (id) { + log.info("Spy Stream removed: " + id); + delete active.streams[id]; + }); + var colorIndex = 0; + active.get_color = function (obj) { + var colors = [ + "black", + "red", + "green", + "yellow", + "blue", + "gray", + "magenta", + "cyan", + "white" + ]; + return colors[colorIndex++ % colors.length]; + }; + return active; +})(); +var streams = { + create: function (req, res, next) { + var metadata = req.header("x-stream-metadata"); + try { + if (metadata) { + metadata = JSON.parse(metadata); + } + } + catch (e) { + req.log.warn({ err: e, metadata }, "Failed to parse metadata header as JSON"); + } + co_1.default(function* () { + var id = req.params.id || + "build-" + metadata.buildId + "-task-" + metadata.task.id; + req.log = req.log.child({ sid: id }, true); + var storage = new Storage(req.loomConfig.storage); + var stream = yield storage.loadStream(id); + if (stream) { + if (req.query.force !== "true") { + var msg = `The stream with ID ${id} already exists.`; + req.log.error(msg); + res.json({ + error: msg + " Specify force=true query param to override." + }); + return next(); + } + else { + req.log.info("deleting stream..."); + yield storage.deleteStream(id); + req.log.info("stream deleted"); + res.header("x-stream-replaced", true); + } + } + storage + .saveStream(id, { + metadata: metadata + }, { + replace: req.query.force === "true" + }) + .then(function () { + var error; + var writer = storage.createWriteStream(id); + writer.on("error", err => { + req.log.error({ err }, "Failed to create writer stream for", id); + error = err; + handleError(res, err, next); + }); + setTimeout(function () { + if (!error) { + req.pipe(writer); + req.log.info({ metadata }, "created stream"); + res.writeHead(201, { + "x-stream-id": id + }); + res.flushHeaders(); + } + }, 10); + activeStreams.emit("added", id); + req.on("end", function () { + req.log.info("producer stream ended"); + res.end(); + activeStreams.emit("removed", id); + if (next) { + next(); + } + }); + }); + }).catch(next); + }, + get: function (req, res, next) { + var streamId = req.params.id; + var notail = "notail" in req.query; + req.log = req.log.child({ sid: streamId }, true); + req.log.info({ opts: { notail: notail } }, "got a consumer request"); + var storage = new Storage(req.loomConfig.storage); + storage + .loadStream(streamId) + .then(function (stream) { + if (!stream) { + res.json({ error: `The stream with ID ${streamId} does not exist` }); + return next(); + } + var reader = storage.createReadStream(streamId, { notail }); + res.header("x-stream-metadata", JSON.stringify(stream.metadata[0])); + reader.on("error", err => { + req.log.error({ err }, "Failed to create read stream for", streamId); + if (err.code === "ENOENT") { + err.status = 404; + } + handleError(res, err, next); + }); + reader.pipe(res); + res.on("finish", function () { + req.log.info("consumer stream ended"); + next(); + }); + }) + .catch(function (err) { + req.log.error({ err }, "Could not fetch stream"); + handleError(res, err, next); + }); + }, + spy: function (req, res, next) { + var colors = require("colors"); + colors.supportsColor = colors.enabled = true; + function colorize(str, color) { + if (req.query.color !== void 0) { + return colors[color](str).replace(/(^.*):/, "$&".bold); + } + return str; + } + var through2 = require("through2"); + var storage = new Storage(req.loomConfig.storage); + var lastStreamId; + function showStream(id) { + req.log.info("SHOW STREAM: " + id); + var color = activeStreams.get_color(); + res.write(colorize(`START: ${id}\n`, color)); + var readStream = storage.createReadStream(id); + readStream.on("error", err => { + req.log.error({ err }, "Failed to create spy read stream for", id); + }); + readStream + .pipe(through2(function (chunk, enc, cb) { + var header = `${id}:\n`; + if (lastStreamId === id) { + header = ""; + } + lastStreamId = id; + cb(null, colorize(`${header}${chunk.toString()}`, color)); + })) + .pipe(res, { end: false }); + readStream.on("end", function flush(cb) { + req.log.info("STREAM ENDED: " + id); + res.write(colorize(`END: ${id}\n`, color)); + }); + activeStreams.on("removed", function (removedId) { + if (id === removedId) { + setTimeout(() => readStream.end(), 200); + } + }); + } + Object.keys(activeStreams.streams).forEach(showStream); + activeStreams.on("added", showStream); + } +}; +exports.controllers = { streams }; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/lib/api/controllers/index.js.map b/dist/lib/api/controllers/index.js.map new file mode 100644 index 0000000..c0145ed --- /dev/null +++ b/dist/lib/api/controllers/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../lib/api/controllers/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/lib/api/routes.js b/dist/lib/api/routes.js new file mode 100644 index 0000000..40889c3 --- /dev/null +++ b/dist/lib/api/routes.js @@ -0,0 +1,19 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const index_1 = require("./controllers/index"); +const auth_1 = require("./auth"); +require("../../typings/TConfig"); +exports.configure = (server, config) => { + const auth = auth_1.Auth({ + tokens: config.tokens + }).auth; + const conf = function (req, res, next) { + req.loomConfig = config; + next(); + }; + server.post("/stream/", auth, conf, index_1.controllers.streams.create); + server.post("/stream/:id", auth, conf, index_1.controllers.streams.create); + server.get("/stream/:id", auth, conf, index_1.controllers.streams.get); + server.get("/spy", auth, conf, index_1.controllers.streams.spy); +}; +//# sourceMappingURL=routes.js.map \ No newline at end of file diff --git a/dist/lib/api/routes.js.map b/dist/lib/api/routes.js.map new file mode 100644 index 0000000..56cbb16 --- /dev/null +++ b/dist/lib/api/routes.js.map @@ -0,0 +1 @@ +{"version":3,"file":"routes.js","sourceRoot":"","sources":["../../../lib/api/routes.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,+CAAkD;AAClD,iCAA8B;AAC9B,iCAA+B;AAElB,QAAA,SAAS,GAAG,CAAC,MAAW,EAAE,MAAe,EAAE,EAAE;IACxD,MAAM,IAAI,GAAG,WAAI,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC,MAAM;KACtB,CAAC,CAAC,IAAI,CAAC;IAGR,MAAM,IAAI,GAAG,UAAS,GAAG,EAAE,GAAG,EAAE,IAAI;QAClC,GAAG,CAAC,UAAU,GAAG,MAAM,CAAC;QACxB,IAAI,EAAE,CAAC;IACT,CAAC,CAAC;IAEF,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,mBAAW,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAChE,MAAM,CAAC,IAAI,CAAC,aAAa,EAAE,IAAI,EAAE,IAAI,EAAE,mBAAW,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACnE,MAAM,CAAC,GAAG,CAAC,aAAa,EAAE,IAAI,EAAE,IAAI,EAAE,mBAAW,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC/D,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,mBAAW,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;AAC1D,CAAC,CAAC"} \ No newline at end of file diff --git a/dist/lib/api/server.js b/dist/lib/api/server.js new file mode 100644 index 0000000..6069c73 --- /dev/null +++ b/dist/lib/api/server.js @@ -0,0 +1,45 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const restify = require("restify"); +const logger_1 = require("../logger"); +const routes_1 = require("./routes"); +require("../../typings/TConfig"); +class Server { + constructor(config) { + this.server = restify.createServer({ + name: require(process.env.PWD + "/package.json").name, + log: logger_1.getLogger("").child({ component: "server" }) + }); + this.configure(config); + } + configure(config) { + var server = this.server; + server.use(restify.requestLogger({ + serializers: restify.bunyan.serializers + })); + server.use(function (req, res, next) { + req.log.info({ req: req }, "REQUEST"); + next(); + }); + this.log = this.server.log; + this.listen = this.server.listen; + this.close = this.server.close; + server.on("after", restify.auditLogger({ + log: server.log + })); + server.on("uncaughtException", function (req, res, route, err) { + console.log("uncaughtException", err.stack); + req.log.error({ err: err }, "uncaughtException"); + }); + server.use(function (req, res, next) { + req.connection.setTimeout(0); + res.connection.setTimeout(0); + next(); + }); + server.use(restify.queryParser({ mapParams: false })); + routes_1.configure(server, config); + server.use(restify.queryParser({ mapParams: false })); + } +} +exports.Server = Server; +//# sourceMappingURL=server.js.map \ No newline at end of file diff --git a/dist/lib/api/server.js.map b/dist/lib/api/server.js.map new file mode 100644 index 0000000..1a1ff67 --- /dev/null +++ b/dist/lib/api/server.js.map @@ -0,0 +1 @@ +{"version":3,"file":"server.js","sourceRoot":"","sources":["../../../lib/api/server.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AACb,mCAAmC;AACnC,sCAAsC;AACtC,qCAAqC;AACrC,iCAA+B;AAE/B;IAME,YAAY,MAAe;QACzB,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;YACjC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,eAAe,CAAC,CAAC,IAAI;YACrD,GAAG,EAAE,kBAAS,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC;SAClD,CAAC,CAAC;QACH,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IACzB,CAAC;IAED,SAAS,CAAC,MAAM;QACd,IAAI,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAEzB,MAAM,CAAC,GAAG,CACR,OAAO,CAAC,aAAa,CAAC;YACpB,WAAW,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW;SACxC,CAAC,CACH,CAAC;QACF,MAAM,CAAC,GAAG,CAAC,UAAS,GAAG,EAAE,GAAG,EAAE,IAAI;YAChC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,SAAS,CAAC,CAAC;YACtC,IAAI,EAAE,CAAC;QACT,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC;QAC3B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;QACjC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;QAC/B,MAAM,CAAC,EAAE,CACP,OAAO,EACP,OAAO,CAAC,WAAW,CAAC;YAClB,GAAG,EAAE,MAAM,CAAC,GAAG;SAChB,CAAC,CACH,CAAC;QACF,MAAM,CAAC,EAAE,CAAC,mBAAmB,EAAE,UAAS,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG;YAC1D,OAAO,CAAC,GAAG,CAAC,mBAAmB,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC;YAC5C,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,mBAAmB,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;QAGH,MAAM,CAAC,GAAG,CAAC,UAAS,GAAG,EAAE,GAAG,EAAE,IAAI;YAChC,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;YAC7B,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;YAC7B,IAAI,EAAE,CAAC;QACT,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;QAEtD,kBAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAE1B,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;IACxD,CAAC;CACF;AArDD,wBAqDC"} \ No newline at end of file diff --git a/dist/lib/knex.js b/dist/lib/knex.js new file mode 100644 index 0000000..5196665 --- /dev/null +++ b/dist/lib/knex.js @@ -0,0 +1,10 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const client = require("knex"); +const knexConfig = require(process.env.PWD + "/knexfile"); +process.env.NODE_ENV = process.env.NODE_ENV || "production"; +var Database; +(function (Database) { + Database.knex = client(knexConfig[process.env.NODE_ENV]); +})(Database = exports.Database || (exports.Database = {})); +//# sourceMappingURL=knex.js.map \ No newline at end of file diff --git a/dist/lib/knex.js.map b/dist/lib/knex.js.map new file mode 100644 index 0000000..632be7c --- /dev/null +++ b/dist/lib/knex.js.map @@ -0,0 +1 @@ +{"version":3,"file":"knex.js","sourceRoot":"","sources":["../../lib/knex.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAGb,+BAA+B;AAE/B,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,WAAW,CAAC,CAAC;AAE1D,OAAO,CAAC,GAAG,CAAC,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,YAAY,CAAC;AAC5D,IAAc,QAAQ,CAErB;AAFD,WAAc,QAAQ;IACP,aAAI,GAAW,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC;AACvE,CAAC,EAFa,QAAQ,GAAR,gBAAQ,KAAR,gBAAQ,QAErB"} \ No newline at end of file diff --git a/dist/lib/logger.js b/dist/lib/logger.js new file mode 100644 index 0000000..2c5ed58 --- /dev/null +++ b/dist/lib/logger.js @@ -0,0 +1,24 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const bunyan = require("bunyan"); +exports.getLogger = (component) => { + const logLevel = process.env.NODE_ENV == "test" ? bunyan.FATAL + 1 : "debug"; + const logger = bunyan.createLogger({ + name: require(process.env.PWD + "/package.json").name, + level: logLevel, + src: true, + serializers: bunyan.stdSerializers, + streams: [ + { + stream: process.stdout + } + ] + }); + if (component) { + return logger.child({ component: component }); + } + else { + return logger; + } +}; +//# sourceMappingURL=logger.js.map \ No newline at end of file diff --git a/dist/lib/logger.js.map b/dist/lib/logger.js.map new file mode 100644 index 0000000..747535d --- /dev/null +++ b/dist/lib/logger.js.map @@ -0,0 +1 @@ +{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../lib/logger.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,iCAAiC;AAEpB,QAAA,SAAS,GAAG,CAAC,SAAiB,EAAU,EAAE;IACrD,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IAC7E,MAAM,MAAM,GAAG,MAAM,CAAC,YAAY,CAAC;QACjC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,eAAe,CAAC,CAAC,IAAI;QACrD,KAAK,EAAE,QAAQ;QACf,GAAG,EAAE,IAAI;QACT,WAAW,EAAE,MAAM,CAAC,cAAc;QAClC,OAAO,EAAE;YACP;gBACE,MAAM,EAAE,OAAO,CAAC,MAAM;aACvB;SACF;KACF,CAAC,CAAC;IAEH,IAAI,SAAS,EAAE;QACb,OAAO,MAAM,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC,CAAC;KAC/C;SAAM;QACL,OAAO,MAAM,CAAC;KACf;AACH,CAAC,CAAC"} \ No newline at end of file diff --git a/dist/lib/models/postgre_storage.js b/dist/lib/models/postgre_storage.js new file mode 100644 index 0000000..c95dbd7 --- /dev/null +++ b/dist/lib/models/postgre_storage.js @@ -0,0 +1,101 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const _ = require("lodash"); +const logger_1 = require("../logger"); +require("../../typings/TConfig"); +const uuid = require("uuid/v4"); +const knex_1 = require("../knex"); +class PostgreStorage { + constructor(config) { + this.config = _.defaults({}, config, { + logsTable: "logs", + metaTable: "meta" + }); + this.log = logger_1.getLogger(""); + } + saveStream(streamId, meta, opts, cb) { + opts = opts || { replace: false }; + var conflict = opts.replace === true ? "replace" : "error"; + var stream = { + id: streamId, + meta: meta + }; + var self = this; + var metaLog = { + id: uuid(), + buildId: meta.metadata.buildId, + taskId: meta.metadata.task.id, + task: meta.metadata.task + }; + var client = knex_1.Database.knex; + return client(this.config.metaTable) + .insert(metaLog) + .then(() => { + cb(); + }) + .catch(function (er) { }); + } + loadStream(streamId, cb) { + var parsedStreamId = this.parseStreamId(streamId); + var client = knex_1.Database.knex; + var self = this; + return client + .select("buildId", "task") + .from(this.config.metaTable) + .where("buildId", parsedStreamId.build) + .andWhere("taskId", parsedStreamId.task) + .andWhere("deleted", false) + .then(function (data) { + if (data.length == 0) { + if (cb) { + cb(false); + } + else { + return false; + } + } + var meta = { + metadata: data + }; + var stream = { + id: streamId, + meta: meta + }; + self.log.debug(stream); + if (cb) { + cb(stream && stream.meta); + } + return stream && stream.meta; + }) + .catch(cb); + } + deleteStream(streamId, cb) { + var parsedStreamId = this.parseStreamId(streamId); + var client = knex_1.Database.knex(this.config.metaTable); + return client + .where("buildId", parsedStreamId.build) + .andWhere("taskId", parsedStreamId.task) + .andWhere("deleted", false) + .update({ + deleted: true + }); + } + parseStreamId(streamId) { + var poleString = streamId.split("-"); + var pole = { build: "", task: "" }; + var idName = ""; + poleString.forEach(function (element) { + if (element == "build" || element == "task") { + idName = element; + } + else { + pole[idName] += element + "-"; + } + }); + pole.build = pole.build.substr(0, pole.build.length - 1); + pole.task = pole.task.substr(0, pole.task.length - 1); + return pole; + } +} +exports.PostgreStorage = PostgreStorage; +//# sourceMappingURL=postgre_storage.js.map \ No newline at end of file diff --git a/dist/lib/models/postgre_storage.js.map b/dist/lib/models/postgre_storage.js.map new file mode 100644 index 0000000..0e39016 --- /dev/null +++ b/dist/lib/models/postgre_storage.js.map @@ -0,0 +1 @@ +{"version":3,"file":"postgre_storage.js","sourceRoot":"","sources":["../../../lib/models/postgre_storage.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/lib/models/postgre_stream_backend_filesystem.js b/dist/lib/models/postgre_stream_backend_filesystem.js new file mode 100644 index 0000000..4102f04 --- /dev/null +++ b/dist/lib/models/postgre_stream_backend_filesystem.js @@ -0,0 +1,91 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const fs = require("fs"); +const Path = require("path"); +const zlib = require("zlib"); +const ms = require("ms"); +const through2 = require("through2"); +const combine = require("bun"); +const _ = require("lodash"); +const tstream = require("tailing-stream"); +const postgre_storage_1 = require("./postgre_storage"); +require("../../typings/TConfig"); +const createTailingStream = tstream.createReadStream; +class FileSystemStorage extends postgre_storage_1.PostgreStorage { + constructor(config) { + config = _.defaults({}, config, { + dataDir: "data", + tailTimeout: 30 * 1000, + compress: true + }); + config.tailTimeout = ms(config.tailTimeout + ""); + super(config); + } + makeFileName(streamId) { + return `stream-${streamId}.log`; + } + makeStreamFilePath(streamId, makeFileName = null) { + makeFileName = makeFileName || this.makeFileName; + return Path.join(this.config.dataDir, makeFileName(streamId)); + } + createWriteStream(streamId) { + const path = this.makeStreamFilePath(streamId); + const fileStream = fs.createWriteStream(path); + if (this.config.compress) { + const zipStream = zlib.createGzip({ flush: zlib.Z_SYNC_FLUSH }); + const streams = [zipStream, fileStream]; + const stream = combine(streams); + return stream; + } + return combine([fileStream]); + } + createReadStream(streamId, opts = {}) { + let notail = opts.notail; + const path = this.makeStreamFilePath(streamId); + const stream = through2(); + this._isStreamFinished(path, (err, finished, info) => { + if (err) { + return stream.emit("error", err); + } + if (finished) { + notail = true; + } + var dataStream; + if (notail) { + dataStream = fs.createReadStream(path); + } + else { + dataStream = createTailingStream(path, { + timeout: this.config.tailTimeout + }); + } + if (this.config.compress) { + dataStream = dataStream.pipe(zlib.createGunzip()); + } + dataStream.pipe(stream); + }); + return stream; + } + deleteStream(streamId, cb) { + var newSidPrefix = `deleted_${+new Date()}_`; + var oldPath = this.makeStreamFilePath(streamId); + var newPath = this.makeStreamFilePath(streamId, sid => newSidPrefix + this.makeFileName(sid)); + fs.rename(oldPath, newPath, err => { + if (cb) { + cb(err, newPath); + } + }); + return Promise.resolve(newPath); + } + _isStreamFinished(filePath, cb) { + fs.stat(filePath, (err, stat) => { + if (err) + return cb(err); + const age = new Date().valueOf() - stat.mtime.valueOf(); + const finished = age > this.config.tailTimeout; + cb(null, finished, { age: age }); + }); + } +} +exports.FileSystemStorage = FileSystemStorage; +//# sourceMappingURL=postgre_stream_backend_filesystem.js.map \ No newline at end of file diff --git a/dist/lib/models/postgre_stream_backend_filesystem.js.map b/dist/lib/models/postgre_stream_backend_filesystem.js.map new file mode 100644 index 0000000..2654d24 --- /dev/null +++ b/dist/lib/models/postgre_stream_backend_filesystem.js.map @@ -0,0 +1 @@ +{"version":3,"file":"postgre_stream_backend_filesystem.js","sourceRoot":"","sources":["../../../lib/models/postgre_stream_backend_filesystem.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/lib/models/rethink_storage.js b/dist/lib/models/rethink_storage.js new file mode 100644 index 0000000..9a58824 --- /dev/null +++ b/dist/lib/models/rethink_storage.js @@ -0,0 +1,153 @@ +'use strict'; +Object.defineProperty(exports, "__esModule", { value: true }); +const _ = require("lodash"); +const through = require("through2"); +const rethink_1 = require("../rethink"); +const logger_1 = require("../logger"); +class RethinkStorage { + constructor(config) { + this.config = _.defaults({}, config, { + logsTable: 'logs', + metaTable: 'meta', + }); + this.log = logger_1.getLogger(''); + } + createWriteStream(streamId) { + var self = this; + var insertData = function (data, cb) { + rethink_1.rethink.r.table(self.config.logsTable).insert({ + sid: streamId, + data, + ts: new Date(), + }).run(function (err) { + cb(err); + }); + }; + var stream = through(function (data, enc, cb) { + insertData(data, cb); + }, function flush(cb) { + insertData(null, cb); + }); + return stream; + } + createReadStream(streamId, opts) { + var self = this; + const Opts = opts || {}; + var notail = opts.notail; + var stream = through.obj(); + const log = (...str) => this.log.trace('CHANGE_STREAM', ...str); + log('in createReadStream()'); + var r = rethink_1.rethink.r; + var dbStream = r.table(self.config.logsTable) + .orderBy({ index: 'sid_ts' }) + .between([streamId, r.minval], [streamId, r.maxval], { index: 'sid_ts', leftBound: 'closed', rightBound: 'closed' }) + .changes({ includeInitial: true, includeStates: true }) + .toStream(); + var createInitialDataSortingStream = function (opts) { + var buffer = []; + var initializing = true; + var log = opts.log; + return through.obj(function (obj, enc, cb) { + var self = this; + if (obj === 'ready') { + log('ready state'); + initializing = false; + buffer.sort(function (obj1, obj2) { + return obj1.ts - obj2.ts; + }).map(function (obj) { + log('sending sorted buffer object', obj); + self.push(obj); + }); + this.push(obj); + } + else if (initializing) { + log('queuing to buffer', obj); + buffer.push(obj); + } + else { + log('pushing new object through', obj); + this.push(obj); + } + cb(); + }); + }; + dbStream + .on('error', function (err) { + self.log.error({ err }, 'changes stream error:', err.message); + }) + .on('end', function () { + log('DB STREAM ended'); + }) + .pipe(through.obj(function (obj, enc, cb) { + if (obj.state) { + this.push(obj.state); + } + if (obj.new_val) { + this.push(obj.new_val); + } + cb(); + })) + .pipe(createInitialDataSortingStream({ log })) + .pipe(through.obj(function (obj, enc, cb) { + if (obj === 'initializing') { + log('initializing state'); + } + else if (obj === 'ready') { + if (notail) { + log('ready state & notail=true; closing stream'); + this.end(); + } + } + else { + this.push(obj); + } + cb(); + })) + .pipe(through.obj(function (obj, enc, cb) { + if (obj.data == null) { + log('ending stream'); + this.end(); + } + else { + this.push(obj.data); + } + cb(); + })) + .on('end', function () { + log('transform stream ended, ending db changes stream'); + dbStream.close(); + }) + .pipe(stream); + return stream; + } + saveStream(streamId, meta, opts, cb) { + opts = opts || { replace: false }; + var conflict = opts.replace === true ? 'replace' : 'error'; + var stream = { + id: streamId, + meta: meta, + }; + return rethink_1.rethink.r.table(this.config.metaTable).insert(stream, { conflict: conflict }).run(cb); + } + loadStream(streamId, cb) { + return rethink_1.rethink.r.table(this.config.metaTable).get(streamId).run() + .then(function (stream) { + if (cb) { + cb(stream && stream.meta); + } + return stream && stream.meta; + }).catch(cb); + } + deleteStream(streamId, cb) { + var newSidPostfix = '_' + +new Date(); + return rethink_1.rethink.r.table(this.config.logsTable) + .filter({ sid: streamId }) + .update({ + sid: rethink_1.rethink.r.row('sid').add(newSidPostfix), + origSid: rethink_1.rethink.r.row('sid'), + }) + .run(cb); + } +} +exports.RethinkStorage = RethinkStorage; +//# sourceMappingURL=rethink_storage.js.map \ No newline at end of file diff --git a/dist/lib/models/rethink_storage.js.map b/dist/lib/models/rethink_storage.js.map new file mode 100644 index 0000000..115421f --- /dev/null +++ b/dist/lib/models/rethink_storage.js.map @@ -0,0 +1 @@ +{"version":3,"file":"rethink_storage.js","sourceRoot":"","sources":["../../../lib/models/rethink_storage.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,4BAA4B;AAC5B,oCAAoC;AAEpC,wCAAqC;AACrC,sCAAsC;AAkBtC;IAUE,YAAY,MAAe;QACzB,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE;YACnC,SAAS,EAAE,MAAM;YACjB,SAAS,EAAE,MAAM;SAClB,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,GAAG,kBAAS,CAAC,EAAE,CAAC,CAAC;IAC3B,CAAC;IAED,iBAAiB,CAAC,QAAgB;QAChC,IAAI,IAAI,GAAG,IAAI,CAAC;QAGhB,IAAI,UAAU,GAAG,UAAS,IAAI,EAAE,EAAE;YAChC,iBAAO,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC;gBAC5C,GAAG,EAAE,QAAQ;gBACb,IAAI;gBACJ,EAAE,EAAE,IAAI,IAAI,EAAE;aACf,CAAC,CAAC,GAAG,CAAC,UAAS,GAAG;gBACjB,EAAE,CAAC,GAAG,CAAC,CAAC;YACV,CAAC,CAAC,CAAC;QACL,CAAC,CAAC;QAIF,IAAI,MAAM,GAAG,OAAO,CAAC,UAAS,IAAI,EAAE,GAAG,EAAE,EAAE;YACzC,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACvB,CAAC,EAAE,eAAe,EAAE;YAElB,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACvB,CAAC,CAAC,CAAC;QAEH,OAAO,MAAM,CAAC;IAChB,CAAC;IAGD,gBAAgB,CAAC,QAAiB,EAAE,IAAY;QAC9C,IAAI,IAAI,GAAG,IAAI,CAAC;QAChB,MAAM,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;QACxB,IAAI,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAEzB,IAAI,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;QAE3B,MAAM,GAAG,GAAG,CAAC,GAAG,GAAU,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,eAAe,EAAE,GAAG,GAAG,CAAC,CAAC;QAOvE,GAAG,CAAC,uBAAuB,CAAC,CAAC;QAE7B,IAAI,CAAC,GAAG,iBAAO,CAAC,CAAC,CAAC;QAClB,IAAI,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC;aAC1C,OAAO,CAAC,EAAC,KAAK,EAAE,QAAQ,EAAC,CAAC;aAC1B,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,EACpB,CAAC,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,EACpB,EAAC,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAC,CAAC;aACrE,OAAO,CAAC,EAAC,cAAc,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAC,CAAC;aACpD,QAAQ,EAAE,CAAC;QAEd,IAAI,8BAA8B,GAAG,UAAS,IAAsC;YAClF,IAAI,MAAM,GAAG,EAAE,CAAC;YAChB,IAAI,YAAY,GAAG,IAAI,CAAC;YAExB,IAAI,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC;YAEnB,OAAO,OAAO,CAAC,GAAG,CAAC,UAAS,GAAW,EAAE,GAAG,EAAE,EAAc;gBAC1D,IAAI,IAAI,GAAG,IAAI,CAAC;gBAChB,IAAI,GAAG,KAAK,OAAO,EAAE;oBACnB,GAAG,CAAC,aAAa,CAAC,CAAC;oBACnB,YAAY,GAAG,KAAK,CAAC;oBAGrB,MAAM,CAAC,IAAI,CAAC,UAAS,IAAI,EAAE,IAAI;wBAE7B,OAAO,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC;oBAC3B,CAAC,CAAC,CAAC,GAAG,CAAC,UAAS,GAAG;wBACjB,GAAG,CAAC,8BAA8B,EAAE,GAAG,CAAC,CAAC;wBACzC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;oBACjB,CAAC,CAAC,CAAC;oBAGH,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;iBAChB;qBACI,IAAI,YAAY,EAAE;oBAIrB,GAAG,CAAC,mBAAmB,EAAE,GAAG,CAAC,CAAC;oBAE9B,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;iBAClB;qBACI;oBAEH,GAAG,CAAC,4BAA4B,EAAE,GAAG,CAAC,CAAC;oBACvC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;iBAChB;gBAED,EAAE,EAAE,CAAC;YACP,CAAC,CAAC,CAAC;QACL,CAAC,CAAC;QAGF,QAAQ;aACL,EAAE,CAAC,OAAO,EAAE,UAAS,GAAG;YACvB,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAC,GAAG,EAAC,EAAE,uBAAuB,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;QAC9D,CAAC,CAAC;aACD,EAAE,CAAC,KAAK,EAAE;YACT,GAAG,CAAC,iBAAiB,CAAC,CAAC;QACzB,CAAC,CAAC;aAID,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAS,GAAG,EAAE,GAAG,EAAE,EAAE;YACrC,IAAI,GAAG,CAAC,KAAK,EAAE;gBACb,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;aACtB;YACD,IAAI,GAAG,CAAC,OAAO,EAAE;gBACf,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;aACxB;YACD,EAAE,EAAE,CAAC;QACP,CAAC,CAAC,CAAC;aAKF,IAAI,CAAC,8BAA8B,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;aAG7C,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAS,GAAG,EAAE,GAAG,EAAE,EAAE;YACrC,IAAI,GAAG,KAAK,cAAc,EAAE;gBAE1B,GAAG,CAAC,oBAAoB,CAAC,CAAC;aAC3B;iBACI,IAAI,GAAG,KAAK,OAAO,EAAE;gBAIxB,IAAI,MAAM,EAAE;oBACV,GAAG,CAAC,2CAA2C,CAAC,CAAC;oBACjD,IAAI,CAAC,GAAG,EAAE,CAAC;iBACZ;aACF;iBACI;gBAEH,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;aAChB;YAED,EAAE,EAAE,CAAC;QACP,CAAC,CAAC,CAAC;aAEF,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAS,GAAG,EAAE,GAAG,EAAE,EAAc;YAIjD,IAAI,GAAG,CAAC,IAAI,IAAI,IAAI,EAAE;gBACpB,GAAG,CAAC,eAAe,CAAC,CAAC;gBACrB,IAAI,CAAC,GAAG,EAAE,CAAC;aACZ;iBACI;gBACH,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;aACrB;YACD,EAAE,EAAE,CAAC;QACP,CAAC,CAAC,CAAC;aACF,EAAE,CAAC,KAAK,EAAE;YACT,GAAG,CAAC,kDAAkD,CAAC,CAAC;YAExD,QAAQ,CAAC,KAAK,EAAE,CAAC;QACnB,CAAC,CAAC;aACD,IAAI,CAAC,MAAM,CAAC,CAAC;QAEhB,OAAO,MAAM,CAAC;IAChB,CAAC;IAGD,UAAU,CAAC,QAAgB,EAAE,IAAI,EAAE,IAA2B,EAAE,EAAe;QAC7E,IAAI,GAAG,IAAI,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QAGlC,IAAI,QAAQ,GAAG,IAAI,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC;QAG3D,IAAI,MAAM,GAAG;YACX,EAAE,EAAE,QAAQ;YACZ,IAAI,EAAE,IAAI;SACX,CAAC;QACF,OAAO,iBAAO,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,EAAC,QAAQ,EAAE,QAAQ,EAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC7F,CAAC;IAGD,UAAU,CAAC,QAAgB,EAAE,EAA0B;QAErD,OAAO,iBAAO,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,GAAG,EAAE;aAC9D,IAAI,CAAC,UAAS,MAAM;YACnB,IAAI,EAAE,EAAE;gBACN,EAAE,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC;aAC3B;YAED,OAAO,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC;QAC/B,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;IAGD,YAAY,CAAC,QAAgB,EAAE,EAAc;QAI3C,IAAI,aAAa,GAAG,GAAG,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;QACtC,OAAO,iBAAO,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC;aAC1C,MAAM,CAAC,EAAC,GAAG,EAAE,QAAQ,EAAC,CAAC;aACvB,MAAM,CAAC;YACN,GAAG,EAAE,iBAAO,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC;YAC5C,OAAO,EAAE,iBAAO,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC;SAC9B,CAAC;aACD,GAAG,CAAC,EAAE,CAAC,CAAC;IACb,CAAC;CACF;AAnOD,wCAmOC"} \ No newline at end of file diff --git a/dist/lib/rethink.js b/dist/lib/rethink.js new file mode 100644 index 0000000..1558348 --- /dev/null +++ b/dist/lib/rethink.js @@ -0,0 +1,38 @@ +'use strict'; +Object.defineProperty(exports, "__esModule", { value: true }); +const _ = require("lodash"); +const logger_1 = require("./logger"); +const Thinky = require("thinky"); +const logger = logger_1.getLogger('db'); +exports.rethink = { + thinky: null, + r: null, + config: null, + models: null, + connect: function (config) { + exports.rethink.config = _.defaults(config || {}, { + logsTable: 'logs', + metaTable: 'meta', + }); + const thinky = exports.rethink.thinky = Thinky({ + host: config.host, + port: config.port, + db: config.db, + }); + const r = exports.rethink.r = thinky.r; + r.getPoolMaster().on('size', function (size) { + logger.debug({ pool_size: size }, `# of connections in pool: ${size}`); + }); + exports.rethink.models = createModels(thinky, config); + return exports.rethink; + } +}; +function createModels(thinky, config) { + var Logs = thinky.createModel(config.logsTable, {}, { enforce_extra: 'none' }); + Logs.ensureIndex('ts'); + Logs.ensureIndex('sid'); + Logs.ensureIndex('sid_ts', function (row) { return [row('sid'), row('ts')]; }); + var Meta = thinky.createModel(config.metaTable, {}, { enforce_extra: 'none' }); + return { Logs, Meta }; +} +//# sourceMappingURL=rethink.js.map \ No newline at end of file diff --git a/dist/lib/rethink.js.map b/dist/lib/rethink.js.map new file mode 100644 index 0000000..bcea26a --- /dev/null +++ b/dist/lib/rethink.js.map @@ -0,0 +1 @@ +{"version":3,"file":"rethink.js","sourceRoot":"","sources":["../../lib/rethink.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,4BAA4B;AAC5B,qCAAqC;AACrC,iCAAiC;AAEjC,MAAM,MAAM,GAAG,kBAAS,CAAC,IAAI,CAAC,CAAC;AAKlB,QAAA,OAAO,GAAG;IACrB,MAAM,EAAE,IAAI;IACZ,CAAC,EAAE,IAAI;IACP,MAAM,EAAE,IAAI;IACZ,MAAM,EAAE,IAAI;IAEZ,OAAO,EAAE,UAAS,MAAM;QACtB,eAAO,CAAC,MAAM,GAAG,CAAC,CAAC,QAAQ,CAAC,MAAM,IAAI,EAAE,EAAE;YACxC,SAAS,EAAE,MAAM;YACjB,SAAS,EAAE,MAAM;SAClB,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,eAAO,CAAC,MAAM,GAAG,MAAM,CAAC;YACrC,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,EAAE,EAAE,MAAM,CAAC,EAAE;SACd,CAAC,CAAC;QAGH,MAAM,CAAC,GAAG,eAAO,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC;QAG/B,CAAC,CAAC,aAAa,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,UAAS,IAAI;YACxC,MAAM,CAAC,KAAK,CAAC,EAAC,SAAS,EAAE,IAAI,EAAC,EAAE,6BAA6B,IAAI,EAAE,CAAC,CAAC;QACvE,CAAC,CAAC,CAAC;QAEH,eAAO,CAAC,MAAM,GAAG,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAE9C,OAAO,eAAO,CAAC;IACjB,CAAC;CACF,CAAA;AAGD,sBAAsB,MAAM,EAAE,MAAM;IAClC,IAAI,IAAI,GAAG,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,SAAS,EAAE,EAAE,EAAE,EAAC,aAAa,EAAE,MAAM,EAAC,CAAC,CAAC;IAC7E,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IACvB,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;IACxB,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,UAAS,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAE9E,IAAI,IAAI,GAAG,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,SAAS,EAAE,EAAE,EAAE,EAAC,aAAa,EAAE,MAAM,EAAC,CAAC,CAAC;IAE7E,OAAO,EAAC,IAAI,EAAE,IAAI,EAAC,CAAC;AACtB,CAAC"} \ No newline at end of file diff --git a/dist/test/__setup.js b/dist/test/__setup.js new file mode 100644 index 0000000..8f89fdd --- /dev/null +++ b/dist/test/__setup.js @@ -0,0 +1,6 @@ +"use strict"; +require("co-mocha"); +process.env.NODE_ENV = "test"; +let logger = require("../lib/logger").getLogger(); +logger._level = Number.POSITIVE_INFINITY; +//# sourceMappingURL=__setup.js.map \ No newline at end of file diff --git a/dist/test/__setup.js.map b/dist/test/__setup.js.map new file mode 100644 index 0000000..fefd8e7 --- /dev/null +++ b/dist/test/__setup.js.map @@ -0,0 +1 @@ +{"version":3,"file":"__setup.js","sourceRoot":"","sources":["../../test/__setup.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAIb,OAAO,CAAC,UAAU,CAAC,CAAC;AAEpB,OAAO,CAAC,GAAG,CAAC,QAAQ,GAAG,MAAM,CAAC;AAG9B,IAAI,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC,SAAS,EAAE,CAAC;AAClD,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,iBAAiB,CAAC"} \ No newline at end of file diff --git a/dist/test/auth.js b/dist/test/auth.js new file mode 100644 index 0000000..bf75e87 --- /dev/null +++ b/dist/test/auth.js @@ -0,0 +1,58 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +require("mocha"); +require("chai"); +const request = require("supertest"); +const server_1 = require("../lib/api/server"); +require("../typings/TConfig"); +process.env.NODE_ENV = "test"; +let server = null; +describe("auth", function () { + this.timeout(5000); + before("start server", function (done) { + var testConf = { + tokens: ["tik", "tok"], + server: { + host: "localhost", + port: 3060 + }, + db: { + host: "localhost", + port: 28015, + db: "test", + logsTable: "logs", + metaTable: "meta" + } + }; + var loom = new server_1.Server(testConf); + loom.listen(done); + server = loom.server; + }); + describe("all endpoints require auth", function () { + it("GET /spy", function (done) { + request(server) + .get("/spy") + .expect("Content-Type", /json/) + .expect(401, done); + }); + it("GET /stream/id", function (done) { + request(server) + .get("/stream/id") + .expect("Content-Type", /json/) + .expect(401, done); + }); + it("POST /stream/id", function (done) { + request(server) + .post("/stream/id") + .expect("Content-Type", /json/) + .expect(401, done); + }); + it("POST /stream/", function (done) { + request(server) + .post("/stream") + .expect("Content-Type", /json/) + .expect(401, done); + }); + }); +}); +//# sourceMappingURL=auth.js.map \ No newline at end of file diff --git a/dist/test/auth.js.map b/dist/test/auth.js.map new file mode 100644 index 0000000..d341405 --- /dev/null +++ b/dist/test/auth.js.map @@ -0,0 +1 @@ +{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../test/auth.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,iBAAe;AACf,gBAAc;AACd,qCAAqC;AACrC,8CAA2C;AAE3C,8BAA4B;AAG5B,OAAO,CAAC,GAAG,CAAC,QAAQ,GAAG,MAAM,CAAC;AAE9B,IAAI,MAAM,GAAG,IAAI,CAAC;AAElB,QAAQ,CAAC,MAAM,EAAE;IACf,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnB,MAAM,CAAC,cAAc,EAAE,UAAS,IAAI;QAClC,IAAI,QAAQ,GAAG;YACb,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC;YACtB,MAAM,EAAE;gBACN,IAAI,EAAE,WAAW;gBACjB,IAAI,EAAE,IAAI;aACX;YACD,EAAE,EAAE;gBACF,IAAI,EAAE,WAAW;gBACjB,IAAI,EAAE,KAAK;gBACX,EAAE,EAAE,MAAM;gBACV,SAAS,EAAE,MAAM;gBACjB,SAAS,EAAE,MAAM;aAClB;SACF,CAAC;QACF,IAAI,IAAI,GAAG,IAAI,eAAM,CAAC,QAAQ,CAAC,CAAC;QAChC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAElB,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IACvB,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,4BAA4B,EAAE;QACrC,EAAE,CAAC,UAAU,EAAE,UAAS,IAAI;YAC1B,OAAO,CAAC,MAAM,CAAC;iBACZ,GAAG,CAAC,MAAM,CAAC;iBACX,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC;iBAC9B,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACvB,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gBAAgB,EAAE,UAAS,IAAI;YAChC,OAAO,CAAC,MAAM,CAAC;iBACZ,GAAG,CAAC,YAAY,CAAC;iBACjB,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC;iBAC9B,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACvB,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iBAAiB,EAAE,UAAS,IAAI;YACjC,OAAO,CAAC,MAAM,CAAC;iBACZ,IAAI,CAAC,YAAY,CAAC;iBAClB,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC;iBAC9B,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACvB,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,eAAe,EAAE,UAAS,IAAI;YAC/B,OAAO,CAAC,MAAM,CAAC;iBACZ,IAAI,CAAC,SAAS,CAAC;iBACf,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC;iBAC9B,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACvB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/dist/test/file_storage.js b/dist/test/file_storage.js new file mode 100644 index 0000000..5a1b8a0 --- /dev/null +++ b/dist/test/file_storage.js @@ -0,0 +1,182 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const fs = require("fs"); +const zlib = require("zlib"); +const _ = require("lodash"); +const chai_1 = require("chai"); +require("mocha"); +const track = require("temp"); +const postgre_stream_backend_filesystem_1 = require("../lib/models/postgre_stream_backend_filesystem"); +const knex_1 = require("../lib/knex"); +chai_1.should(); +process.env.NODE_ENV = "test"; +const bl = require("bl"); +let temp = track.track(); +const config = { + dataDir: temp.mkdirSync(), + db: process.env.DB_NAME || "test", + tailTimeout: 1000, + compress: false +}; +describe("FileSystemStorage", function () { + before(function* reset() { + let config = { + db: process.env.DB_NAME || "test", + tables: { + logsTable: "logs", + metaTable: "meta" + } + }; + yield [knex_1.Database.knex(config.tables.metaTable).truncate()]; + }); + it("constructs an instance properly", function () { + let instance; + instance = new postgre_stream_backend_filesystem_1.FileSystemStorage(); + instance.config.should.contain({ + metaTable: "meta", + dataDir: "data" + }); + }); + it("generates file names properly", function () { + var instance = new postgre_stream_backend_filesystem_1.FileSystemStorage(config); + instance.makeFileName("stream-x-1").should.eql("stream-stream-x-1.log"); + instance + .makeStreamFilePath("stream-x-2") + .should.eql(`${config.dataDir}/stream-stream-x-2.log`); + }); + it("writes to a file", function (done) { + var instance = new postgre_stream_backend_filesystem_1.FileSystemStorage(config); + var writeStream = instance.createWriteStream("xyz"); + writeStream.write("line 1\n"); + writeStream.write("line 2\n"); + writeStream.end("this is the end\n"); + var filePath = `${config.dataDir}/stream-xyz.log`; + writeStream.on("finish", () => { + fs.readFileSync(filePath).toString().should.eql(`line 1 +line 2 +this is the end +`); + instance._isStreamFinished(filePath, (err, finished) => { + finished.should.eql(false); + instance.config.tailTimeout = 10; + setTimeout(() => { + instance._isStreamFinished(filePath, (err, finished, data) => { + finished.should.eql(true); + done(); + }); + }, instance.config.tailTimeout + 50); + }); + }); + }); + it("reads from a file (notail, reads to EOF)", function (done) { + var instance = new postgre_stream_backend_filesystem_1.FileSystemStorage(config); + var fileContents = `write test line 1 +write test line 2 +write test end +`; + fs.writeFileSync(`${config.dataDir}/stream-abc.log`, fileContents); + var reader = instance.createReadStream("abc", { notail: true }); + reader.pipe(bl(function (err, data) { + if (err) + return done(err); + data.toString().should.eql(fileContents); + })); + reader.on("end", () => { + done(); + }); + }); + it("reads from a file (default, tails current stream waiting for more data)", function (done) { + var instance = new postgre_stream_backend_filesystem_1.FileSystemStorage(config); + var fileContents = `write test line 1 +write test line 2 +write test end +`; + fs.writeFileSync(`${config.dataDir}/stream-tail.log`, fileContents); + setTimeout(() => fs.appendFile(`${config.dataDir}/stream-tail.log`, "new content", err => { + if (err) + throw err; + }), 200); + var reader = instance.createReadStream("tail"); + var start = +new Date(); + reader.pipe(bl(function (err, data) { + if (err) + return done(err); + data.toString().should.eql(fileContents + "new content"); + })); + reader.on("end", () => { + var end = +new Date(); + (end - start).should.approximately(1000 + 200, 20); + done(); + }); + }); + it("reads from a file (default, old stream not waiting for new data)", function (done) { + var instance = new postgre_stream_backend_filesystem_1.FileSystemStorage(config); + instance.config.tailTimeout = 50; + var streamId = "tail-old"; + var fileContents = `write test line 1 +write test line 2 +write test end +`; + fs.writeFileSync(`${config.dataDir}/stream-${streamId}.log`, fileContents); + setTimeout(() => { + var reader = instance.createReadStream(streamId); + var start = +new Date(); + reader.pipe(bl(function (err, data) { + if (err) + return done(err); + data.toString().should.eql(fileContents); + })); + reader.on("end", () => { + var end = +new Date(); + (end - start).should.approximately(0, 20); + done(); + }); + }, instance.config.tailTimeout + 10); + }); + it("writes to/from a compressed file", function (done) { + var instance = new postgre_stream_backend_filesystem_1.FileSystemStorage(_.assign({}, config, { + compress: true + })); + var writeStream = instance.createWriteStream("compressed"); + writeStream.write("line 1\n"); + writeStream.write("line 2\n"); + writeStream.end("this is the end\n"); + var filePath = `${config.dataDir}/stream-compressed.log`; + writeStream.on("finish", () => { + setTimeout(() => { + var content = fs.readFileSync(filePath); + content + .toString("base64") + .should.eql("H4sIAAAAAAAAA8rJzEtVMOQCAAAA///KAVFGXAAAAAD//yrJyCxWAKKSjFSF1LwULgAAAAD//wMAIR/aQh4AAAA="); + zlib.gunzipSync(content).toString().should.eql(`line 1 +line 2 +this is the end +`); + instance.createReadStream("compressed").pipe(bl(function (err, data) { + if (err) + return done(err); + data.toString().should.eql(`line 1 +line 2 +this is the end +`); + done(); + })); + }, 10); + }); + }); + it("deletes files", function (done) { + var instance = new postgre_stream_backend_filesystem_1.FileSystemStorage(config); + fs.writeFileSync(`${config.dataDir}/stream-deleteme.log`, "to be deleted"); + instance.deleteStream("deleteme", function (err, renamed) { + if (err) + done(err); + (function () { + fs.statSync(`${config.dataDir}/stream-deleteme.log`); + }.should.throw(/ENOENT: no such file or directory/)); + fs.statSync(renamed); + renamed.should.match(new RegExp(`${config.dataDir}/deleted_[0-9]+_stream-deleteme.log`)); + done(); + }); + }); +}); +//# sourceMappingURL=file_storage.js.map \ No newline at end of file diff --git a/dist/test/file_storage.js.map b/dist/test/file_storage.js.map new file mode 100644 index 0000000..8f31ed3 --- /dev/null +++ b/dist/test/file_storage.js.map @@ -0,0 +1 @@ +{"version":3,"file":"file_storage.js","sourceRoot":"","sources":["../../test/file_storage.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/test/models.js b/dist/test/models.js new file mode 100644 index 0000000..b465ed6 --- /dev/null +++ b/dist/test/models.js @@ -0,0 +1,149 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +require("mocha"); +const chai_1 = require("chai"); +const through = require("through2"); +const track = require("temp"); +const postgre_storage_1 = require("../lib/models/postgre_storage"); +const postgre_stream_backend_filesystem_1 = require("../lib/models/postgre_stream_backend_filesystem"); +const knex_1 = require("../lib/knex"); +chai_1.should(); +process.env.NODE_ENV = "test"; +const bl = require("bl"); +const temp = track.track(); +const tables = { + logsTable: "logs", + metaTable: "meta" +}; +function isDescendant(B, A) { + return B.prototype instanceof A || B === A; +} +function testStorage(Storage, storageConfig) { + function read(streamid, storage) { + return (storage || new Storage(storageConfig)).createReadStream(streamid); + } + function write(streamid, storage) { + return (storage || new Storage(storageConfig)).createWriteStream(streamid); + } + describe("Storage: " + Storage.name, function () { + before(function* reset() { + if (isDescendant(Storage, postgre_storage_1.PostgreStorage)) { + const config = { + db: process.env.DB_NAME || "test" + }; + yield [knex_1.Database.knex(tables.metaTable).truncate()]; + } + }); + describe("storage basics", function () { + var streams = { + "build-31aced17-67da-45fe-b447-f326f39f8a1b-task-58aa706b20c00000": { + "metadata": { + "buildId": "31aced17-67da-45fe-b447-f326f39f8a1b", + "task": { "id": "58aa706b20c00000", "name": "AssetDownloader task", "plugin": "AssetDownloader" } + } + }, + "build-31aced17-67da-45fe-b447-f326f39f8a1b-task-58aa706b21400000": { + "metadata": { + "buildId": "31aced17-67da-45fe-b447-f326f39f8a1b", + "task": { "id": "58aa706b21400000", "name": "Probo site setup", "plugin": "LAMPApp" } + } + }, + }; + it("creates streams", function* () { + var storage = new Storage(storageConfig); + for (var streamid in streams) { + yield storage.saveStream(streamid, streams[streamid]); + } + }); + it("loads streams", function* () { + var storage = new Storage(storageConfig); + var meta = yield storage.loadStream(Object.keys(streams)[0]); + meta.metadata[0].should.eql(streams[Object.keys(streams)[0]].metadata); + }); + it("stream 1 writes then reads", function (done) { + var storage = new Storage(storageConfig); + var list = bl(); + list.append("some data"); + list.append("more data"); + var streamid = "stream 1"; + var writer = write(streamid, storage); + list.duplicate().pipe(writer); + writer.on("finish", function () { + var reader = read(streamid, storage); + reader.pipe(bl(function (err, data) { + if (err) + return done(err); + data.should.eql(list.slice(), "reader on same storage as writer works"); + })); + reader.on("end", function () { + read(streamid).pipe(bl(function (err, data) { + if (err) + return done(err); + data.should.eql(list.slice(), "reader on different storage than writer works"); + done(); + })); + }); + }); + }); + it("stream 2 writes and reads async", function (done) { + var expected; + var num = 10; + var interval = 100; + var producer = makeProducer(num, interval, function finishedProducing(data) { + expected = data; + }); + producer.pipe(write("stream 2")); + var immediateFinished = false; + var delayedFinished = false; + read("stream 2").pipe(bl(function (err, data) { + data.toString().should.eql(expected.toString()); + immediateFinished = true; + if (delayedFinished && immediateFinished) { + done(); + } + })); + setTimeout(function () { + read("stream 2").pipe(bl(function (err, data) { + data.toString().should.eql(expected.toString()); + delayedFinished = true; + if (delayedFinished && immediateFinished) { + done(); + } + })); + }, num * interval / 2); + }); + }); + }); +} +testStorage(postgre_stream_backend_filesystem_1.FileSystemStorage, { + dataDir: temp.mkdirSync(), + tailTimeout: 1000, + compress: false +}); +function makeProducer(numpushes, interval, finished) { + numpushes = numpushes || 2; + interval = interval || 100; + var producer = through(); + var data = []; + var pushed = 0; + var _i = setInterval(function () { + if (pushed >= numpushes) { + clearInterval(_i); + producer.end(); + } + else { + var d = new Buffer("data " + ++pushed); + data.push(d); + producer.write(d); + } + }, interval); + if (finished) { + producer.on("finish", function () { + if (finished) { + finished(Buffer.concat(data)); + } + }); + } + return producer; +} +//# sourceMappingURL=models.js.map \ No newline at end of file diff --git a/dist/test/models.js.map b/dist/test/models.js.map new file mode 100644 index 0000000..d9b2203 --- /dev/null +++ b/dist/test/models.js.map @@ -0,0 +1 @@ +{"version":3,"file":"models.js","sourceRoot":"","sources":["../../test/models.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/test/server.js b/dist/test/server.js new file mode 100644 index 0000000..422365f --- /dev/null +++ b/dist/test/server.js @@ -0,0 +1,141 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const http = require("http"); +const url = require("url"); +const chai_1 = require("chai"); +const server_1 = require("../lib/api/server"); +const track = require("temp"); +const knex_1 = require("../lib/knex"); +chai_1.should(); +process.env.NODE_ENV = "test"; +const numChunks = 4; +const consumerWait = 2000; +let server = null; +const temp = track.track(); +var testConf = { + tokens: ["tik", "tok"], + server: { + host: "localhost", + port: 3060 + }, + db: { + host: "localhost", + port: 28015, + db: "test" + }, + storage: { + logsTable: "logs", + metaTable: "meta", + dataDir: temp.mkdirSync(), + tailTimeout: "1.5s", + compress: false + } +}; +function start(cb) { + var loom = new server_1.Server(testConf); + server = loom.server; + loom.listen(0, "127.0.0.1", function () { + server.log.info("%s listening at %s", server.name, server.url); + return cb && cb(); + }); +} +describe("Server:", function () { + before("clear database", function* () { + yield [knex_1.Database.knex(testConf.storage.metaTable).truncate()]; + }); + before("server starts", function (done) { + start(done); + }); + describe("producer", function () { + var streamId; + function startConsumer(id, cb) { + console.log("starting consumer"); + var data = []; + var consumerHandler = function (res) { + console.log("CONSUMER STATUS: " + res.statusCode); + console.log("CONSUMER HEADERS: " + JSON.stringify(res.headers)); + res.setEncoding("utf8"); + res.on("data", function (chunk) { + console.log("CONSUMER BODY: " + chunk); + data.push(chunk); + }); + res.on("end", function () { + console.log("CONSUMER has read the full stream"); + data + .join("") + .should.eql([ + "chunks written 4", + "chunks written 3", + "chunks written 2", + "chunks written 1" + ].join("")); + setTimeout(cb, 1000); + }); + res.on("error", function (err) { + console.log("CONSUMER error", err); + cb(err); + }); + }; + var consumer = http.request({ + hostname: "localhost", + port: url.parse(server.url).port, + path: "/stream/" + id, + headers: { + authorization: "bearer tik" + } + }, consumerHandler); + consumer.end(); + } + it("feeds data", function (done) { + var producerHandler = function (res) { + console.log("PRODUCER STATUS: " + res.statusCode); + console.log("PRODUCER HEADERS: " + JSON.stringify(res.headers)); + res.setEncoding("utf8"); + res.on("data", function (chunk) { + console.log("PRODUCER BODY: " + chunk); + }); + streamId = res.headers["x-stream-id"]; + setTimeout(function () { + startConsumer(streamId, done); + }, consumerWait); + console.log(` +curl -vi --no-buffer http://:::${server.address().port}/stream/${streamId} +`); + }; + var producer = http.request({ + hostname: "localhost", + port: url.parse(server.url).port, + method: "post", + path: "/stream", + headers: { + authorization: "bearer tik", + connection: "keep-alive", + "x-stream-metadata": JSON.stringify({ + buildId: "31aced17-67da-45fe-b447-f326f39f8a1b", + task: { + id: "58aa706b20c00000", + name: "AssetDownloader task", + plugin: "AssetDownloader" + } + }) + } + }, producerHandler); + var chunks = numChunks; + var i = setInterval(function () { + if (chunks > 0) { + producer.write("chunks written " + chunks); + console.log("producer sending data", chunks); + chunks--; + } + else { + clearInterval(i); + producer.end(); + } + }, 1000); + }); + it("has complete data", function (done) { + startConsumer(streamId, done); + }); + }); +}); +//# sourceMappingURL=server.js.map \ No newline at end of file diff --git a/dist/test/server.js.map b/dist/test/server.js.map new file mode 100644 index 0000000..702e401 --- /dev/null +++ b/dist/test/server.js.map @@ -0,0 +1 @@ +{"version":3,"file":"server.js","sourceRoot":"","sources":["../../test/server.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/typings/TConfig.js b/dist/typings/TConfig.js new file mode 100644 index 0000000..a92c851 --- /dev/null +++ b/dist/typings/TConfig.js @@ -0,0 +1 @@ +//# sourceMappingURL=TConfig.js.map \ No newline at end of file diff --git a/dist/typings/TConfig.js.map b/dist/typings/TConfig.js.map new file mode 100644 index 0000000..0446a0e --- /dev/null +++ b/dist/typings/TConfig.js.map @@ -0,0 +1 @@ +{"version":3,"file":"TConfig.js","sourceRoot":"","sources":["../../typings/TConfig.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/index.js b/index.js deleted file mode 100644 index 35396c4..0000000 --- a/index.js +++ /dev/null @@ -1,16 +0,0 @@ -'use strict'; -var rethink = require('./lib/rethink'); -var Server = require('./lib/api/server'); - -module.exports.run = function run(config) { - - var server = new Server(config); - server.log.info({config: config}, 'Configuration loaded'); - - // connect to the DB - rethink.connect(config.db); - - server.listen(config.server.port, config.server.host, function() { - server.log.info('%s listening at %s', server.server.name, server.server.url); - }); -}; diff --git a/index.ts b/index.ts new file mode 100644 index 0000000..a4c09fc --- /dev/null +++ b/index.ts @@ -0,0 +1,21 @@ +"use strict"; + +import { Database } from "./lib/knex"; +import { Server } from "./lib/api/server"; +import "./typings/TConfig"; + +export const run = (config: TConfig) => { + var server = new Server(config); + server.log.info({ config: config }, "Configuration loaded"); + + // connect to the DB + Database.knex.select('id').from('meta').limit(1); + + server.listen(config.server.port, config.server.host, function() { + server.log.info( + "%s listening at %s", + server.server.name, + server.server.url + ); + }); +}; diff --git a/knexfile.js b/knexfile.js new file mode 100644 index 0000000..66496f8 --- /dev/null +++ b/knexfile.js @@ -0,0 +1,37 @@ +'use strict'; + +module.exports = { + test: { + client: 'postgresql', + connection: { + database: 'probodb_test', + user: 'probodb_test', + password: 'password', + host: 'localhost', + }, + pool: { + min: 2, + max: 10, + }, + migrations: { + tableName: 'knex_migrations', + }, + }, + + production: { + client: 'postgresql', + connection: { + database: 'log_db', + user: 'probodb', + password: 'password', + host: 'localhost', + }, + pool: { + min: 2, + max: 10, + }, + migrations: { + tableName: 'knex_migrations', + }, + }, +}; diff --git a/knexfile.ts b/knexfile.ts new file mode 100644 index 0000000..66496f8 --- /dev/null +++ b/knexfile.ts @@ -0,0 +1,37 @@ +'use strict'; + +module.exports = { + test: { + client: 'postgresql', + connection: { + database: 'probodb_test', + user: 'probodb_test', + password: 'password', + host: 'localhost', + }, + pool: { + min: 2, + max: 10, + }, + migrations: { + tableName: 'knex_migrations', + }, + }, + + production: { + client: 'postgresql', + connection: { + database: 'log_db', + user: 'probodb', + password: 'password', + host: 'localhost', + }, + pool: { + min: 2, + max: 10, + }, + migrations: { + tableName: 'knex_migrations', + }, + }, +}; diff --git a/lib/api/auth.js b/lib/api/auth.ts similarity index 62% rename from lib/api/auth.js rename to lib/api/auth.ts index 3750ac4..f16c685 100644 --- a/lib/api/auth.js +++ b/lib/api/auth.ts @@ -1,7 +1,13 @@ -'use strict'; +"use strict"; -var passport = require('passport'); -var BearerStrategy = require('passport-http-bearer').Strategy; +import * as passport from "passport"; +import * as Strategy from "passport-http-bearer"; + +const BearerStrategy = Strategy.Strategy; + +type TConfigTok = { + tokens: string[]; +}; /** * Function that returns an auth lib object to use as route auth middleware @@ -12,32 +18,44 @@ var BearerStrategy = require('passport-http-bearer').Strategy; * @return {Object} - auth lib with the '.auth' function to use * as the auth middleware with routes */ -module.exports = function(config) { - var authlib = { - verify: function(token, done) { +export const Auth = function(config: TConfigTok) { + let authlib = { + verify: function( + token: string, + done: (temp: any, param: boolean | { token: string }) => void + ) { process.nextTick(function() { var user = { - token: token, + token: token }; - var found = config.tokens.indexOf(token) > -1; + const found = config.tokens.indexOf(token) > -1; - if (!found) { return done(null, false); } + if (!found) { + return done(null, false); + } return done(null, user); }); }, + auth: function(req, res, next) {} }; - passport.use(new BearerStrategy({realm: 'API Key'}, function(token, done) { - return authlib.verify(token, done); - })); + passport.use( + new BearerStrategy({ realm: "API Key" }, (token, done) => { + // Verify is not called when there is no token!! + return authlib.verify(token, done); + }) + ); - var tokenAuth = passport.authenticate('bearer', {session: false, failWithError: true}); + var tokenAuth = passport.authenticate("bearer", { + session: false, + failWithError: true + }); // auth middleware that only checks for token authentication if its configured authlib.auth = function(req, res, next) { if (Array.isArray(config.tokens)) { - return tokenAuth(req, res, function(err) { + return tokenAuth(req, res, err => { // This callback is only called when `failWithError` is // set. We need a custom callback here to call `next()` so // that Restify can log the end of the request properly (and @@ -55,8 +73,7 @@ module.exports = function(config) { return next(err); }); - } - else { + } else { next(); } }; diff --git a/lib/api/controllers/index.js b/lib/api/controllers/index.js deleted file mode 100644 index 233a557..0000000 --- a/lib/api/controllers/index.js +++ /dev/null @@ -1,228 +0,0 @@ -'use strict'; - -var co = require('co'); - -// var ArrayStreamStorage = require('../../models').ArrayStreamStorage; -// var RethinkStorage = require('../../models').RethinkStorage; -var FileSystemStorage = require('../../models').FileSystemStorage; - -// var Storage = RethinkStorage; -// var Storage = ArrayStreamStorage; -var Storage = FileSystemStorage; - - -var logger = require('../../logger'); -var log = logger.getLogger().child({component: 'server'}); - -function handleError(res, err, next) { - res.status(err.status || 500); - res.json({error: err.message}); - next(); -} - -var activeStreams = (function() { - var active = new (require('events').EventEmitter)(); - active.streams = {}; - active.on('added', function(id) { - log.info('Spy Stream added: ' + id); - active.streams[id] = true; - }); - active.on('removed', function(id) { - log.info('Spy Stream removed: ' + id); - delete active.streams[id]; - }); - - var colorIndex = 0; - active.get_color = function(obj) { - var colors = [ - 'black', 'red', 'green', 'yellow', 'blue', 'gray', 'magenta', 'cyan', 'white', - ]; - return colors[colorIndex++ % colors.length]; - }; - - return active; -})(); - -var streams = { - create: function(req, res, next) { - var metadata = req.header('x-stream-metadata'); - try { - if (metadata) { - metadata = JSON.parse(metadata); - } - } - catch (e) { - req.log.warn({err: e, metadata}, 'Failed to parse metadata header as JSON'); - } - - co(function* () { - var id = req.params.id || 'loom-' + +new Date(); - req.log = req.log.child({sid: id}, true); - - var storage = new Storage(req.loomConfig.storage); - - var stream = yield storage.loadStream(id); - if (stream) { - // stream id is already taken, see if force flag is specified - if (req.query.force !== 'true') { - var msg = `The stream with ID ${id} already exists.`; - req.log.error(msg); - res.json({error: msg + ' Specify force=true query param to override.'}); - return next(); - } - else { - // delete existing stream - req.log.info('deleting stream...'); - yield storage.deleteStream(id); - req.log.info('stream deleted'); - - res.header('x-stream-replaced', true); - } - } - - storage.saveStream(id, { - metadata: metadata, - }, { - replace: req.query.force === 'true', - }).then(function() { - var error; - - var writer = storage.createWriteStream(id); - - writer.on('error', (err) => { - req.log.error({err}, 'Failed to create writer stream for', id); - - error = err; - handleError(res, err, next); - }); - - - // allow time for spy hooks to take hold - setTimeout(function() { - if (!error) { - req.pipe(writer); - - req.log.info({metadata}, 'created stream'); - - res.writeHead(201, { - 'x-stream-id': id, - }); - res.flushHeaders(); - } - }, 10); - - activeStreams.emit('added', id); - - req.on('end', function() { - req.log.info('producer stream ended'); - res.end(); - activeStreams.emit('removed', id); - if (next) { next(); } - }); - }); - }).catch(next); - }, - - get: function(req, res, next) { - var streamId = req.params.id; - var notail = 'notail' in req.query; - - req.log = req.log.child({sid: streamId}, true); - req.log.info({opts: {notail: notail}}, 'got a consumer request'); - - var storage = new Storage(req.loomConfig.storage); - storage.loadStream(streamId).then(function(stream) { - if (!stream) { - res.json({error: `The stream with ID ${streamId} does not exist`}); - return next(); - } - - var reader = storage.createReadStream(streamId, {notail}); - res.header('x-stream-metadata', JSON.stringify(stream.metadata)); - - reader.on('error', (err) => { - req.log.error({err}, 'Failed to create read stream for', streamId); - - if (err.code === 'ENOENT') { - err.status = 404; - } - - handleError(res, err, next); - }); - - reader.pipe(res); - - res.on('finish', function() { - req.log.info('consumer stream ended'); - next(); - }); - }).catch(function(err) { - req.log.error({err}, 'Could not fetch stream'); - handleError(res, err, next); - }); - }, - - // dumps all active live streams - spy: function(req, res, next) { - var colors = require('colors'); - // force support (needed when running with npm) - colors.supportsColor = colors.enabled = true; - - function colorize(str, color) { - if (req.query.color !== void 0) { - return colors[color](str).replace(/(^.*):/, '$&'.bold); - } - return str; - } - - var through2 = require('through2'); - var storage = new Storage(req.loomConfig.storage); - - var lastStreamId; - - function showStream(id) { - req.log.info('SHOW STREAM: ' + id); - - var color = activeStreams.get_color(); - res.write(colorize(`START: ${id}\n`, color)); - - var readStream = storage.createReadStream(id); - - readStream.on('error', (err) => { - req.log.error({err}, 'Failed to create spy read stream for', id); - }); - - readStream.pipe(through2(function(chunk, enc, cb) { - // don't re-print stream ID header if the last chunk belonged to the same stream - var header = `${id}:\n`; - if (lastStreamId === id) { - header = ''; - } - lastStreamId = id; - - cb(null, colorize(`${header}${chunk.toString()}`, color)); - })).pipe(res, {end: false}); - - readStream.on('end', function flush(cb) { - req.log.info('STREAM ENDED: ' + id); - res.write(colorize(`END: ${id}\n`, color)); - }); - - activeStreams.on('removed', function(removedId) { - if (id === removedId) { - // give the stream some time to finish being written and outputted - // not the best method, but this is non-critical code - setTimeout(() => readStream.end(), 200); - } - }); - } - - // stream all in-flight streams - Object.keys(activeStreams.streams).forEach(showStream); - - // stream all new streams - activeStreams.on('added', showStream); - }, -}; - -module.exports = {streams}; diff --git a/lib/api/controllers/index.ts b/lib/api/controllers/index.ts new file mode 100644 index 0000000..4053ead --- /dev/null +++ b/lib/api/controllers/index.ts @@ -0,0 +1,249 @@ +"use strict"; + +import co from "co"; +import { FileSystemStorage } from "../../models/postgre_stream_backend_filesystem"; +import { getLogger } from "../../logger"; +import * as uuid from "uuid/v4"; + +const Storage = FileSystemStorage; +const log = getLogger("").child({ component: "server" }); + +function handleError(res, err, next) { + res.status(err.status || 500); + res.json({ error: err.message }); + next(); +} + +var activeStreams = (function() { + var active = new (require("events")).EventEmitter(); + active.streams = {}; + active.on("added", function(id) { + log.info("Spy Stream added: " + id); + active.streams[id] = true; + }); + active.on("removed", function(id) { + log.info("Spy Stream removed: " + id); + delete active.streams[id]; + }); + + var colorIndex = 0; + active.get_color = function(obj) { + var colors = [ + "black", + "red", + "green", + "yellow", + "blue", + "gray", + "magenta", + "cyan", + "white" + ]; + return colors[colorIndex++ % colors.length]; + }; + + return active; +})(); + +var streams = { + create: function(req, res, next) { + var metadata = req.header("x-stream-metadata"); + try { + if (metadata) { + metadata = JSON.parse(metadata); + } + } catch (e) { + req.log.warn( + { err: e, metadata }, + "Failed to parse metadata header as JSON" + ); + } + + co(function*() { + var id = + req.params.id || + "build-" + metadata.buildId + "-task-" + metadata.task.id; + req.log = req.log.child({ sid: id }, true); + + var storage = new Storage(req.loomConfig.storage); + + var stream = yield storage.loadStream(id); + if (stream) { + // stream id is already taken, see if force flag is specified + if (req.query.force !== "true") { + var msg = `The stream with ID ${id} already exists.`; + req.log.error(msg); + res.json({ + error: msg + " Specify force=true query param to override." + }); + return next(); + } else { + // delete existing stream + req.log.info("deleting stream..."); + yield storage.deleteStream(id); + req.log.info("stream deleted"); + + res.header("x-stream-replaced", true); + } + } + + storage + .saveStream( + id, + { + metadata: metadata + }, + { + replace: req.query.force === "true" + } + ) + .then(function() { + var error; + + var writer = storage.createWriteStream(id); + + writer.on("error", err => { + req.log.error({ err }, "Failed to create writer stream for", id); + + error = err; + handleError(res, err, next); + }); + + // allow time for spy hooks to take hold + setTimeout(function() { + if (!error) { + req.pipe(writer); + + req.log.info({ metadata }, "created stream"); + + res.writeHead(201, { + "x-stream-id": id + }); + res.flushHeaders(); + } + }, 10); + + activeStreams.emit("added", id); + + req.on("end", function() { + req.log.info("producer stream ended"); + res.end(); + activeStreams.emit("removed", id); + if (next) { + next(); + } + }); + }); + }).catch(next); + }, + + get: function(req, res, next) { + var streamId = req.params.id; + var notail = "notail" in req.query; + + req.log = req.log.child({ sid: streamId }, true); + req.log.info({ opts: { notail: notail } }, "got a consumer request"); + + var storage = new Storage(req.loomConfig.storage); + storage + .loadStream(streamId) + .then(function(stream) { + if (!stream) { + res.json({ error: `The stream with ID ${streamId} does not exist` }); + return next(); + } + + var reader = storage.createReadStream(streamId, { notail }); + res.header("x-stream-metadata", JSON.stringify(stream.metadata[0])); + + reader.on("error", err => { + req.log.error({ err }, "Failed to create read stream for", streamId); + + if (err.code === "ENOENT") { + err.status = 404; + } + + handleError(res, err, next); + }); + + reader.pipe(res); + + res.on("finish", function() { + req.log.info("consumer stream ended"); + next(); + }); + }) + .catch(function(err) { + req.log.error({ err }, "Could not fetch stream"); + handleError(res, err, next); + }); + }, + + // dumps all active live streams + spy: function(req, res, next) { + var colors = require("colors"); + // force support (needed when running with npm) + colors.supportsColor = colors.enabled = true; + + function colorize(str, color) { + if (req.query.color !== void 0) { + return colors[color](str).replace(/(^.*):/, "$&".bold); + } + return str; + } + + var through2 = require("through2"); + var storage = new Storage(req.loomConfig.storage); + + var lastStreamId; + + function showStream(id) { + req.log.info("SHOW STREAM: " + id); + + var color = activeStreams.get_color(); + res.write(colorize(`START: ${id}\n`, color)); + + var readStream = storage.createReadStream(id); + + readStream.on("error", err => { + req.log.error({ err }, "Failed to create spy read stream for", id); + }); + + readStream + .pipe( + through2(function(chunk, enc, cb) { + // don't re-print stream ID header if the last chunk belonged to the same stream + var header = `${id}:\n`; + if (lastStreamId === id) { + header = ""; + } + lastStreamId = id; + + cb(null, colorize(`${header}${chunk.toString()}`, color)); + }) + ) + .pipe(res, { end: false }); + + readStream.on("end", function flush(cb) { + req.log.info("STREAM ENDED: " + id); + res.write(colorize(`END: ${id}\n`, color)); + }); + + activeStreams.on("removed", function(removedId) { + if (id === removedId) { + // give the stream some time to finish being written and outputted + // not the best method, but this is non-critical code + setTimeout(() => readStream.end(), 200); + } + }); + } + + // stream all in-flight streams + Object.keys(activeStreams.streams).forEach(showStream); + + // stream all new streams + activeStreams.on("added", showStream); + } +}; + +export const controllers = { streams }; diff --git a/lib/api/routes.js b/lib/api/routes.js deleted file mode 100644 index 95fb544..0000000 --- a/lib/api/routes.js +++ /dev/null @@ -1,20 +0,0 @@ -'use strict'; - -var controllers = require('./controllers'); - -module.exports.configure = function(server, config) { - var auth = require('./auth')({ - tokens: config.tokens, - }).auth; - - // inject server configuration into the controllers - var conf = function(req, res, next) { - req.loomConfig = config; - next(); - }; - - server.post('/stream/', auth, conf, controllers.streams.create); - server.post('/stream/:id', auth, conf, controllers.streams.create); - server.get('/stream/:id', auth, conf, controllers.streams.get); - server.get('/spy', auth, conf, controllers.streams.spy); -}; diff --git a/lib/api/routes.ts b/lib/api/routes.ts new file mode 100644 index 0000000..b595e0a --- /dev/null +++ b/lib/api/routes.ts @@ -0,0 +1,22 @@ +"use strict"; + +import { controllers } from "./controllers/index"; +import { Auth } from "./auth"; +import "../../typings/TConfig"; + +export const configure = (server: any, config: TConfig) => { + const auth = Auth({ + tokens: config.tokens + }).auth; + + // inject server configuration into the controllers + const conf = function(req, res, next) { + req.loomConfig = config; + next(); + }; + + server.post("/stream/", auth, conf, controllers.streams.create); + server.post("/stream/:id", auth, conf, controllers.streams.create); + server.get("/stream/:id", auth, conf, controllers.streams.get); + server.get("/spy", auth, conf, controllers.streams.spy); +}; diff --git a/lib/api/server.js b/lib/api/server.js deleted file mode 100644 index 7e6ba43..0000000 --- a/lib/api/server.js +++ /dev/null @@ -1,54 +0,0 @@ -'use strict'; -var restify = require('restify'); - -var logger = require('../logger'); -var routes = require('./routes'); - -class Server { - - constructor(config) { - this.server = restify.createServer({ - name: require('../../package.json').name, - log: logger.getLogger().child({component: 'server'}), - }); - this.configure(config); - } - - configure(config) { - var server = this.server; - // Extend logger using the plugin. - server.use(restify.requestLogger({ - serializers: restify.bunyan.serializers, - })); - server.use(function(req, res, next) { - req.log.info({req: req}, 'REQUEST'); - next(); - }); - this.log = this.server.log; - this.listen = this.server.listen; - this.close = this.server.close; - server.on('after', restify.auditLogger({ - log: server.log, - })); - server.on('uncaughtException', function(req, res, route, err) { - console.log('uncaughtException', err.stack); - req.log.error({err: err}, 'uncaughtException'); - }); - - // Let requests and responses take as long as they need - server.use(function(req, res, next) { - req.connection.setTimeout(0); - res.connection.setTimeout(0); - next(); - }); - - server.use(restify.queryParser({mapParams: false})); - - routes.configure(server, config); - - server.use(restify.queryParser({mapParams: false})); - } - -} - -module.exports = Server; diff --git a/lib/api/server.ts b/lib/api/server.ts new file mode 100644 index 0000000..6d97a9b --- /dev/null +++ b/lib/api/server.ts @@ -0,0 +1,60 @@ +"use strict"; +import * as restify from "restify"; +import { getLogger } from "../logger"; +import { configure } from "./routes"; +import "../../typings/TConfig"; + +export class Server { + public server: restify.Server; + public log: any; + public listen: any; + public close: any; + + constructor(config: TConfig) { + this.server = restify.createServer({ + name: require(process.env.PWD + "/package.json").name, + log: getLogger("").child({ component: "server" }) + }); + this.configure(config); + } + + configure(config) { + var server = this.server; + // Extend logger using the plugin. + server.use( + restify.requestLogger({ + serializers: restify.bunyan.serializers + }) + ); + server.use(function(req, res, next) { + req.log.info({ req: req }, "REQUEST"); + next(); + }); + this.log = this.server.log; + this.listen = this.server.listen; + this.close = this.server.close; + server.on( + "after", + restify.auditLogger({ + log: server.log + }) + ); + server.on("uncaughtException", function(req, res, route, err) { + console.log("uncaughtException", err.stack); + req.log.error({ err: err }, "uncaughtException"); + }); + + // Let requests and responses take as long as they need + server.use(function(req, res, next) { + req.connection.setTimeout(0); + res.connection.setTimeout(0); + next(); + }); + + server.use(restify.queryParser({ mapParams: false })); + + configure(server, config); + + server.use(restify.queryParser({ mapParams: false })); + } +} diff --git a/lib/knex.ts b/lib/knex.ts new file mode 100644 index 0000000..47da2e7 --- /dev/null +++ b/lib/knex.ts @@ -0,0 +1,11 @@ +"use strict"; + +import * as _ from "lodash"; +import * as client from "knex"; + +const knexConfig = require(process.env.PWD + "/knexfile"); + +process.env.NODE_ENV = process.env.NODE_ENV || "production"; +export module Database { + export var knex: client = client(knexConfig[process.env.NODE_ENV]); +} diff --git a/lib/logger.js b/lib/logger.js deleted file mode 100644 index 07ec81d..0000000 --- a/lib/logger.js +++ /dev/null @@ -1,29 +0,0 @@ -'use strict'; - -var bunyan; -var logger; - -bunyan = require('bunyan'); - -logger = bunyan.createLogger({ - name: require('../package.json').name, - level: 'debug', - src: true, - serializers: bunyan.stdSerializers, - streams: [ - { - stream: process.stdout, - }, - ], -}); - -module.exports = { - getLogger: function(component) { - if (component) { - return logger.child({component: component}); - } - else { - return logger; - } - }, -}; diff --git a/lib/logger.ts b/lib/logger.ts new file mode 100644 index 0000000..f808f95 --- /dev/null +++ b/lib/logger.ts @@ -0,0 +1,24 @@ +"use strict"; + +import * as bunyan from "bunyan"; + +export const getLogger = (component: string): bunyan => { + const logLevel = process.env.NODE_ENV == "test" ? bunyan.FATAL + 1 : "debug"; + const logger = bunyan.createLogger({ + name: require(process.env.PWD + "/package.json").name, + level: logLevel, + src: true, + serializers: bunyan.stdSerializers, + streams: [ + { + stream: process.stdout + } + ] + }); + + if (component) { + return logger.child({ component: component }); + } else { + return logger; + } +}; diff --git a/lib/models/index.js b/lib/models/index.js index 9c1d24c..28a38f9 100644 --- a/lib/models/index.js +++ b/lib/models/index.js @@ -1,11 +1,9 @@ 'use strict'; -var ArrayStreamStorage = require('./array_stream_storage'); -var RethinkStorage = require('./rethink_storage'); -var FileSystemStorage = require('./rethink_stream_backend_filesystem'); +var PostgreStorage = require('./postgre_storage'); +var FileSystemStorage = require('./postgre_stream_backend_filesystem'); module.exports = { - ArrayStreamStorage, - RethinkStorage, + PostgreStorage, FileSystemStorage, }; diff --git a/lib/models/postgre_storage.ts b/lib/models/postgre_storage.ts new file mode 100644 index 0000000..2ab80dc --- /dev/null +++ b/lib/models/postgre_storage.ts @@ -0,0 +1,150 @@ +"use strict"; + +import * as _ from "lodash"; +import * as through from "through2"; +import { getLogger } from "../logger"; +import * as bunyan from "bunyan"; +import "../../typings/TConfig"; +import * as uuid from "uuid/v4"; +import { Database } from "../knex"; +import { QueryBuilder } from "knex"; + +type TConfigDb = TConfig["db"]; + +type TOpts = { + notail: boolean; + log: string; +}; + +export class PostgreStorage { + public config: TConfigDb; + private log: bunyan; + + /** + * @param config - Config object + * @param [config.metaTable="meta"] - table to use for metadata. Defaults to "meta" + * @param [config.logsTable="logs"] - table to use for log data. Defaults to "logs" + */ + constructor(config?: TConfigDb) { + this.config = _.defaults({}, config, { + logsTable: "logs", + metaTable: "meta" + }); + + this.log = getLogger(""); + } + + saveStream( + streamId: string, + meta, + opts?: { replace: boolean }, + cb?: () => void + ) { + opts = opts || { replace: false }; + + // no truthiness here, only the real 'true' will do + var conflict = opts.replace === true ? "replace" : "error"; + + // save the metadata of this stream + var stream = { + id: streamId, + meta: meta + }; + + var self = this; + + var metaLog = { + id: uuid(), + buildId: meta.metadata.buildId, + taskId: meta.metadata.task.id, + task: meta.metadata.task + }; + + var client = Database.knex; + + return client(this.config.metaTable) + .insert(metaLog) + .then(() => { + cb(); + }) + .catch(function(er) {}); + } + + loadStream(streamId: string, cb?: (stream: any) => void) { + var parsedStreamId = this.parseStreamId(streamId); + var client = Database.knex; + + var self = this; + + return client + .select("buildId", "task") + .from(this.config.metaTable) + .where("buildId", parsedStreamId.build) + .andWhere("taskId", parsedStreamId.task) + .andWhere("deleted", false) + .then(function(data) { + if (data.length == 0) { + if (cb) { + cb(false); + } else { + return false; + } + } + + var meta = { + metadata: data + }; + + var stream = { + id: streamId, + meta: meta + }; + + self.log.debug(stream); + if (cb) { + cb(stream && stream.meta); + } + return stream && stream.meta; + }) + .catch(cb); + } + + deleteStream( + streamId: string, + cb?: (stream: any) => void + ): QueryBuilder | Promise { + // "delete" the data for this stream + // (not the metadata - that will get overwritten on save) + + var parsedStreamId = this.parseStreamId(streamId); + + var client = Database.knex(this.config.metaTable); + + return client + .where("buildId", parsedStreamId.build) + .andWhere("taskId", parsedStreamId.task) + .andWhere("deleted", false) + .update({ + deleted: true + }); + } + + parseStreamId(streamId: string) { + var poleString = streamId.split("-"); + var pole = { build: "", task: "" }; + var idName = ""; + + poleString.forEach(function(element) { + if (element == "build" || element == "task") { + idName = element; + } else { + pole[idName] += element + "-"; + } + }); + + pole.build = pole.build.substr(0, pole.build.length - 1); + pole.task = pole.task.substr(0, pole.task.length - 1); + + return pole; + } +} diff --git a/lib/models/postgre_stream_backend_filesystem.ts b/lib/models/postgre_stream_backend_filesystem.ts new file mode 100644 index 0000000..0146b16 --- /dev/null +++ b/lib/models/postgre_stream_backend_filesystem.ts @@ -0,0 +1,146 @@ +"use strict"; + +import * as fs from "fs"; +import * as Path from "path"; +import * as zlib from "zlib"; +import * as ms from "ms"; +import * as through2 from "through2"; +import * as combine from "bun"; +import * as _ from "lodash"; +import * as tstream from "tailing-stream"; +import { PostgreStorage } from "./postgre_storage"; +import "../../typings/TConfig"; + +const createTailingStream = tstream.createReadStream; + +type TConfigDb = TConfig["db"]; + +type Tcb = (err: any, finished?: boolean, age?: { age: number }) => void; + +export class FileSystemStorage extends PostgreStorage { + /** + * @param config - Config object + * @param [config.metaTable="meta"] - table to use for metadata. Defaults to "meta" + * @param [config.dataDir="data"] - Path on file system for storing stream files. Defaults to "data" + * @param [config.tailTimeout=30000] - Timeout for tailing streams. Defaults to 30 seconds. + * @param [config.compress=true] - Boolean value for transparrent on-disk compression + */ + constructor(config?: TConfigDb) { + config = _.defaults({}, config, { + dataDir: "data", + tailTimeout: 30 * 1000, + compress: true + }); + + // convert a string representation (e.g., 30000, 30s) to a number + config.tailTimeout = ms(config.tailTimeout + ""); + + super(config); + + // this.config = config; + // this.log.debug({config}, 'FileSystemStorage config'); + } + + makeFileName(streamId: string): string { + return `stream-${streamId}.log`; + } + + makeStreamFilePath(streamId: string, makeFileName = null): string { + makeFileName = makeFileName || this.makeFileName; + return Path.join(this.config.dataDir, makeFileName(streamId)); + } + + createWriteStream(streamId: string): any { + const path = this.makeStreamFilePath(streamId); + const fileStream = fs.createWriteStream(path); + + if (this.config.compress) { + const zipStream = zlib.createGzip({ flush: zlib.Z_SYNC_FLUSH }); + const streams = [zipStream, fileStream]; + const stream = combine(streams); + return stream; + } + + return combine([fileStream]); + } + + createReadStream(streamId: string, opts: { notail?: boolean } = {}): any { + let notail = opts.notail; + + const path = this.makeStreamFilePath(streamId); + const stream = through2(); + + // a finished stream implies notail option + this._isStreamFinished(path, (err, finished, info) => { + if (err) { + return stream.emit("error", err); + } + + if (finished) { + notail = true; + } + + var dataStream; + if (notail) { + // with notail option, just read the file to the current end + dataStream = fs.createReadStream(path); + } else { + // otherwise, tail the file + // keep reading until we a timeout is hit + dataStream = createTailingStream(path, { + timeout: this.config.tailTimeout + }); + } + + if (this.config.compress) { + dataStream = dataStream.pipe(zlib.createGunzip()); + } + + dataStream.pipe(stream); + }); + + return stream; + } + + deleteStream( + streamId: string, + cb?: (err: any, newPath: string) => void + ): Promise { + // "delete" the data for this stream + // (not the metadata - that will get overwritten on save) + + var newSidPrefix = `deleted_${+new Date()}_`; + + var oldPath = this.makeStreamFilePath(streamId); + var newPath = this.makeStreamFilePath( + streamId, + sid => newSidPrefix + this.makeFileName(sid) + ); + + fs.rename(oldPath, newPath, err => { + if (cb) { + cb(err, newPath); + } + }); + + return Promise.resolve(newPath); + } + + /** + * Checks to see if the stream has finished writing. + * This is done by checking if the modified timestamp of the file is older than tailTimeout + * @param String filePath - path to the file to check + * @param Function cb - callback called with true or false, and an age in ms: function(err, boolean, {age}) + */ + + _isStreamFinished(filePath: string, cb: Tcb): void { + fs.stat(filePath, (err: any, stat) => { + if (err) return cb(err); + + const age: number = new Date().valueOf() - stat.mtime.valueOf(); + const finished: boolean = age > this.config.tailTimeout; + + cb(null, finished, { age: age }); + }); + } +} diff --git a/lib/models/rethink_storage.js b/lib/models/rethink_storage.ts similarity index 78% rename from lib/models/rethink_storage.js rename to lib/models/rethink_storage.ts index d14d990..a7f8276 100644 --- a/lib/models/rethink_storage.js +++ b/lib/models/rethink_storage.ts @@ -1,30 +1,47 @@ 'use strict'; -var _ = require('lodash'); -var through = require('through2'); - +import * as _ from 'lodash'; +import * as through from 'through2'; // connect to localhost on default port with a connection pool -var rethink = require('../rethink'); +import { rethink } from '../rethink'; +import { getLogger } from '../logger'; +import * as bunyan from 'bunyan'; + + +type TConfig = { + metaTable?: string, + logsTable?: string, + dataDir: string, + tailTimeout?: number | string, + compress?: boolean +} + +type TOpts = { + notail: boolean; + log: string; +} -var logger = require('../logger'); -class RethinkStorage { +export class RethinkStorage { + + public config: TConfig; + private log: bunyan; /** * @param config - Config object * @param [config.metaTable="meta"] - Rethinkdb table to use for metadata. Defaults to "meta" * @param [config.logsTable="logs"] - Rethinkdb table to use for log data. Defaults to "logs" */ - constructor(config) { + constructor(config: TConfig) { this.config = _.defaults({}, config, { logsTable: 'logs', metaTable: 'meta', }); - this.log = logger.getLogger(); + this.log = getLogger(''); } - createWriteStream(streamId) { + createWriteStream(streamId: string) { var self = this; // write data buffer to the DB, along with the stream id and a timestamp @@ -50,18 +67,20 @@ class RethinkStorage { return stream; } - createReadStream(streamId, opts) { + + createReadStream(streamId: string, opts?: TOpts) { var self = this; - opts = opts || {}; + const Opts = opts || {}; var notail = opts.notail; var stream = through.obj(); - function log() { - var args = Array.prototype.slice.call(arguments); - args.unshift('CHANGES STREAM:'); - self.log.trace.apply(self.log, args); - } + const log = (...str: any[]) => this.log.trace('CHANGE_STREAM', ...str); + // function log(...str: any[]) { + // var args = Array.prototype.slice.call(str); + // args.unshift('CHANGES STREAM:'); + // self.log.trace.apply(self.log, args); + // } log('in createReadStream()'); @@ -74,13 +93,13 @@ class RethinkStorage { .changes({includeInitial: true, includeStates: true}) .toStream(); - var createInitialDataSortingStream = function(opts) { + var createInitialDataSortingStream = function(opts: { log: (...str: any[]) => void }) { var buffer = []; var initializing = true; var log = opts.log; - return through.obj(function(obj, enc, cb) { + return through.obj(function(obj: string, enc, cb: () => void) { var self = this; if (obj === 'ready') { log('ready state'); @@ -140,7 +159,7 @@ class RethinkStorage { // Buffer initial data for the stream, and sort it by timestamp before // sending it out. When Rethink query does this natively, this pipe can // be removed & includeStates flag can be set to false (default). - .pipe(createInitialDataSortingStream({log})) + .pipe(createInitialDataSortingStream({ log })) // handle stream state transitions .pipe(through.obj(function(obj, enc, cb) { @@ -165,7 +184,7 @@ class RethinkStorage { cb(); })) - .pipe(through.obj(function(obj, enc, cb) { + .pipe(through.obj(function(obj, enc, cb: () => void) { // perform loom stream logic by introspecting the data and ending the stream // when it's null @@ -187,13 +206,10 @@ class RethinkStorage { return stream; } + - saveStream(streamId, meta, opts, cb) { - if (typeof opts == 'function') { - cb = opts; - opts = false; - } - opts = opts || {}; + saveStream(streamId: string, meta, opts?: { replace: boolean }, cb?: () => void) { + opts = opts || { replace: false }; // no truthiness here, only the real 'true' will do var conflict = opts.replace === true ? 'replace' : 'error'; @@ -206,16 +222,21 @@ class RethinkStorage { return rethink.r.table(this.config.metaTable).insert(stream, {conflict: conflict}).run(cb); } - loadStream(streamId, cb) { + + loadStream(streamId: string, cb?: (stream: any) => void) { // load the metadata of this stream return rethink.r.table(this.config.metaTable).get(streamId).run() .then(function(stream) { - if (cb) { cb(stream && stream.meta); } + if (cb) { + cb(stream && stream.meta); + } + return stream && stream.meta; }).catch(cb); } - deleteStream(streamId, cb) { + + deleteStream(streamId: string, cb: () => void) { // "delete" the data for this stream // (not the metadata - that will get overwritten on save) @@ -229,6 +250,3 @@ class RethinkStorage { .run(cb); } } - -module.exports = RethinkStorage; - diff --git a/lib/models/rethink_stream_backend_filesystem.js b/lib/models/rethink_stream_backend_filesystem.js deleted file mode 100644 index 6e8827b..0000000 --- a/lib/models/rethink_stream_backend_filesystem.js +++ /dev/null @@ -1,137 +0,0 @@ -'use strict'; - -var fs = require('fs'); -var path = require('path'); -var zlib = require('zlib'); -var ms = require('ms'); - -var through2 = require('through2'); -var combine = require('bun'); -var _ = require('lodash'); - -var createTailingStream = require('tailing-stream').createReadStream; - -var RethinkStorage = require('./rethink_storage'); - -class FileSystemStorage extends RethinkStorage { - - /** - * @param config - Config object - * @param [config.metaTable="meta"] - Rethinkdb table to use for metadata. Defaults to "meta" - * @param [config.dataDir="data"] - Path on file system for storing stream files. Defaults to "data" - * @param [config.tailTimeout=30000] - Timeout for tailing streams. Defaults to 30 seconds. - * @param [config.compress=true] - Boolean value for transparrent on-disk compression - */ - constructor(config) { - config = _.defaults({}, config, { - dataDir: 'data', - tailTimeout: 30 * 1000, - compress: true, - }); - - // convert a string representation (e.g., 30000, 30s) to a number - config.tailTimeout = ms(config.tailTimeout + ''); - - super(config); - - // this.log.debug({config}, 'FileSystemStorage config'); - } - - makeFileName(streamId) { - return `stream-${streamId}.log`; - } - - makeStreamFilePath(streamId, makeFileName) { - makeFileName = makeFileName || this.makeFileName; - return path.join(this.config.dataDir, makeFileName(streamId)); - } - - createWriteStream(streamId) { - var path = this.makeStreamFilePath(streamId); - var fileStream = fs.createWriteStream(path); - var streams = [fileStream]; - - if (this.config.compress) { - streams.unshift(zlib.createGzip({flush: zlib.Z_SYNC_FLUSH})); - } - - var stream = combine(streams); - return stream; - } - - createReadStream(streamId, opts) { - opts = opts || {}; - var notail = opts.notail; - - var path = this.makeStreamFilePath(streamId); - var stream = through2(); - - // a finished stream implies notail option - this._isStreamFinished(path, (err, finished, info) => { - if (err) { - return stream.emit('error', err); - } - - if (finished) { - notail = true; - } - - var dataStream; - if (notail) { - // with notail option, just read the file to the current end - dataStream = fs.createReadStream(path); - } - else { - // otherwise, tail the file - // keep reading until we a timeout is hit - dataStream = createTailingStream(path, { - timeout: this.config.tailTimeout, - }); - } - - if (this.config.compress) { - dataStream = dataStream.pipe(zlib.createGunzip()); - } - - dataStream.pipe(stream); - }); - - return stream; - } - - deleteStream(streamId, cb) { - // "delete" the data for this stream - // (not the metadata - that will get overwritten on save) - - var newSidPrefix = `deleted_${+new Date()}_`; - - var oldPath = this.makeStreamFilePath(streamId); - var newPath = this.makeStreamFilePath(streamId, (sid) => newSidPrefix + this.makeFileName(sid)); - - fs.rename(oldPath, newPath, (err) => { - if (cb) { cb(err, newPath); } - }); - return Promise.resolve(newPath); - } - - /** - * Checks to see if the stream has finished writing. - * This is done by checking if the modified timestamp of the file is older than tailTimeout - * @param String filePath - path to the file to check - * @param Function cb - callback called with true or false, and an age in ms: function(err, boolean, {age}) - */ - _isStreamFinished(filePath, cb) { - fs.stat(filePath, (err, stat) => { - if (err) return cb(err); - - var age = +new Date() - stat.mtime; - var finished = age > this.config.tailTimeout; - - cb(null, finished, {age: age}); - }); - } - -} - -module.exports = FileSystemStorage; - diff --git a/lib/rethink.js b/lib/rethink.ts similarity index 75% rename from lib/rethink.js rename to lib/rethink.ts index 6bf55bd..d150eb0 100644 --- a/lib/rethink.js +++ b/lib/rethink.ts @@ -1,12 +1,15 @@ 'use strict'; -var _ = require('lodash'); -var log = require('./logger').getLogger('db'); +import * as _ from 'lodash'; +import { getLogger } from './logger'; +import * as Thinky from 'thinky'; + +const logger = getLogger('db'); /** * .thinky, .r, .models, and .config get automatically set on connect() */ -var rethink = { +export const rethink = { thinky: null, r: null, config: null, @@ -18,25 +21,26 @@ var rethink = { metaTable: 'meta', }); - var thinky = rethink.thinky = require('thinky')({ + const thinky = rethink.thinky = Thinky({ host: config.host, port: config.port, db: config.db, }); // grab instance of the driver - var r = rethink.r = thinky.r; + const r = rethink.r = thinky.r; // log whenever the # of connections in the pool changes r.getPoolMaster().on('size', function(size) { - log.debug({pool_size: size}, `# of connections in pool: ${size}`); + logger.debug({pool_size: size}, `# of connections in pool: ${size}`); }); rethink.models = createModels(thinky, config); return rethink; - }, -}; + } +} + function createModels(thinky, config) { var Logs = thinky.createModel(config.logsTable, {}, {enforce_extra: 'none'}); @@ -48,6 +52,3 @@ function createModels(thinky, config) { return {Logs, Meta}; } - - -module.exports = rethink; diff --git a/migrations/20180301151937_create_meta.js b/migrations/20180301151937_create_meta.js new file mode 100644 index 0000000..bd32587 --- /dev/null +++ b/migrations/20180301151937_create_meta.js @@ -0,0 +1,35 @@ +'use strict'; + +exports.up = function(knex, Promise) { + return knex.schema.createTable('meta', function(table) { + table + .uuid('id') + .index() + .unique() + .notNullable(); + table + .uuid('buildId') + .index() + .notNullable(); + table + .string('taskId') + .index() + .notNullable(); + table.json('task'); + table + .boolean('deleted') + .defaultTo('false'); + table.timestamp('created_at').defaultTo(knex.fn.now()); + table.index(['buildId', 'taskId']); + }); +}; + +exports.down = function(knex, Promise) { + return knex.schema + .table('meta', function(table) { + table.dropIndex(['buildId', 'taskId']); + }) + .then(function() { + return knex.schema.dropTable('meta'); + }); +}; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..95b7dac --- /dev/null +++ b/package-lock.json @@ -0,0 +1,5408 @@ +{ + "name": "probo-loom", + "version": "2.0.1", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@types/bl": { + "version": "0.8.32", + "resolved": "https://registry.npmjs.org/@types/bl/-/bl-0.8.32.tgz", + "integrity": "sha512-t92ug7E4W/SAvcfbKcsUA5eOtDa0QoCAJ2Qx6JL3g7o48W7IZ/wthlG6WVEV1oWI7grg0PenbRx97hgO97mMOA==", + "requires": { + "@types/node": "9.6.6" + }, + "dependencies": { + "@types/node": { + "version": "9.6.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-9.6.6.tgz", + "integrity": "sha512-SJe0g5cZeGNDP5sD8mIX3scb+eq8LQQZ60FXiKZHipYSeEFZ5EKml+NNMiO76F74TY4PoMWlNxF/YRY40FOvZQ==" + } + } + }, + "@types/bluebird": { + "version": "3.5.20", + "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.20.tgz", + "integrity": "sha512-Wk41MVdF+cHBfVXj/ufUHJeO3BlIQr1McbHZANErMykaCWeDSZbH5erGjNBw2/3UlRdSxZbLfSuQTzFmPOYFsA==" + }, + "@types/chai": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.1.3.tgz", + "integrity": "sha512-f5dXGzOJycyzSMdaXVhiBhauL4dYydXwVpavfQ1mVCaGjR56a9QfklXObUxlIY9bGTmCPHEEZ04I16BZ/8w5ww==" + }, + "@types/core-js": { + "version": "0.9.46", + "resolved": "https://registry.npmjs.org/@types/core-js/-/core-js-0.9.46.tgz", + "integrity": "sha512-LooLR6XHes9V+kNYRz1Qm8w3atw9QMn7XeZUmIpUelllF9BdryeUKd/u0Wh5ErcjpWfG39NrToU9MF7ngsTFVw==", + "dev": true + }, + "@types/events": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@types/events/-/events-1.2.0.tgz", + "integrity": "sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA==" + }, + "@types/knex": { + "version": "0.14.12", + "resolved": "https://registry.npmjs.org/@types/knex/-/knex-0.14.12.tgz", + "integrity": "sha512-k5FJbl+/kP2RDRSufe7y9pYR93441MTT7YaREthsXKWeXhKZJqLrdvtgDwcaYlm0BcOeeCoZrnhQ/Uqc8jFvTw==", + "requires": { + "@types/bluebird": "3.5.20", + "@types/events": "1.2.0", + "@types/node": "9.6.6" + }, + "dependencies": { + "@types/node": { + "version": "9.6.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-9.6.6.tgz", + "integrity": "sha512-SJe0g5cZeGNDP5sD8mIX3scb+eq8LQQZ60FXiKZHipYSeEFZ5EKml+NNMiO76F74TY4PoMWlNxF/YRY40FOvZQ==" + } + } + }, + "@types/lodash": { + "version": "4.14.107", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.107.tgz", + "integrity": "sha512-afvjfP2rl3yvtv2qrCRN23zIQcDinF+munMJCoHEw2BXF22QJogTlVfNPTACQ6ieDyA6VnyKT4WLuN/wK368ng==" + }, + "@types/mocha": { + "version": "2.2.48", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-2.2.48.tgz", + "integrity": "sha512-nlK/iyETgafGli8Zh9zJVCTicvU3iajSkRwOh3Hhiva598CMqNJ4NcVCGMTGKpGpTYj/9R8RLzS9NAykSSCqGw==", + "dev": true + }, + "@types/node": { + "version": "8.10.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.9.tgz", + "integrity": "sha512-GUUTbeDaJSRaoLkqVQ5jwwKbDiLWFX3JrKLvC078q2P51Z9Dcb5F5UdnApSYqdMk4X0VrKod1gzeoX8bGl8DMg==", + "dev": true + }, + "@types/through2": { + "version": "2.0.33", + "resolved": "https://registry.npmjs.org/@types/through2/-/through2-2.0.33.tgz", + "integrity": "sha1-H/LoihAN+1sUDnu5h5HxGUQA0TE=", + "requires": { + "@types/node": "9.6.6" + }, + "dependencies": { + "@types/node": { + "version": "9.6.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-9.6.6.tgz", + "integrity": "sha512-SJe0g5cZeGNDP5sD8mIX3scb+eq8LQQZ60FXiKZHipYSeEFZ5EKml+NNMiO76F74TY4PoMWlNxF/YRY40FOvZQ==" + } + } + }, + "@types/yargs": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-11.0.0.tgz", + "integrity": "sha512-vFql3tOxs6clgh+WVoLW3nOkNGCdeKsMU6mQZkOerJpV/CR9Xc1c1lZ+kYU+hNSobrQIOcNovWfPFDJIhcG5Pw==" + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "requires": { + "kind-of": "3.2.2", + "longest": "1.0.1", + "repeat-string": "1.6.1" + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true + }, + "ansi-align": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz", + "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=", + "requires": { + "string-width": "2.1.1" + } + }, + "ansi-escapes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", + "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", + "dev": true + }, + "ansi-gray": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=" + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "requires": { + "micromatch": "3.1.10", + "normalize-path": "2.1.1" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "requires": { + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "repeat-element": "1.1.2", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "requires": { + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "requires": { + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "requires": { + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.9", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } + } + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "1.0.3" + } + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "requires": { + "arr-flatten": "1.1.0" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" + }, + "array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=" + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "1.0.3" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=" + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" + }, + "asn1": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz", + "integrity": "sha1-VZvhg3bQik7E2+gId9J4GGObLfc=" + }, + "assert-plus": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", + "integrity": "sha1-7nQAlBMALYTOxyGcasgRgS5yMWA=" + }, + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==" + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" + }, + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=" + }, + "async-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=" + }, + "atob": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.0.tgz", + "integrity": "sha512-SuiKH8vbsOyCALjA/+EINmt/Kdl+TQPrtFgW7XZZcwtryFu9e5kQoX3bjCW6mIvGH1fbeAZZuvwGR5IlBRznGw==" + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "requires": { + "core-js": "2.5.5", + "regenerator-runtime": "0.11.1" + } + }, + "backoff": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/backoff/-/backoff-2.5.0.tgz", + "integrity": "sha1-9hbtqdPktmuMp/ynn2lXIsX44m8=", + "requires": { + "precond": "0.2.3" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "requires": { + "cache-base": "1.0.1", + "class-utils": "0.3.6", + "component-emitter": "1.2.1", + "define-property": "1.0.0", + "isobject": "3.0.1", + "mixin-deep": "1.3.1", + "pascalcase": "0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "beeper": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", + "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=" + }, + "binary-extensions": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", + "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=" + }, + "bl": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", + "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", + "requires": { + "readable-stream": "2.3.6", + "safe-buffer": "5.1.1" + } + }, + "bluebird": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" + }, + "boxen": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz", + "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==", + "requires": { + "ansi-align": "2.0.0", + "camelcase": "4.1.0", + "chalk": "2.4.0", + "cli-boxes": "1.0.0", + "string-width": "2.1.1", + "term-size": "1.2.0", + "widest-line": "2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "1.9.1" + } + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" + }, + "chalk": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.0.tgz", + "integrity": "sha512-Wr/w0f4o9LuE7K53cD0qmbAMM+2XNLzR29vFn5hqko4sxGlUsyy363NvmyGIyk5tpe9cjTr9SJYbysEyPkRnFw==", + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" + } + }, + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "buffer-from": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.0.0.tgz", + "integrity": "sha512-83apNb8KK0Se60UE1+4Ukbe3HbfELJ6UlI4ldtOGs7So4KD26orJM8hIY9lxdzP+UpItH1Yh/Y8GUvNFWFFRxA==", + "dev": true + }, + "buffer-writer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-1.0.1.tgz", + "integrity": "sha1-Iqk2kB4wKa/NdUfrRIfOtpejvwg=" + }, + "bun": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/bun/-/bun-0.0.11.tgz", + "integrity": "sha1-AecS0WVri6A8mSsp6uVvn0kI4oA=", + "requires": { + "readable-stream": "1.0.34" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, + "bunyan": { + "version": "1.8.12", + "resolved": "https://registry.npmjs.org/bunyan/-/bunyan-1.8.12.tgz", + "integrity": "sha1-8VDw9nSKvdcq6uhPBEA74u8RN5c=", + "requires": { + "dtrace-provider": "0.8.6", + "moment": "2.22.1", + "mv": "2.1.1", + "safe-json-stringify": "1.1.0" + } + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "requires": { + "collection-visit": "1.0.0", + "component-emitter": "1.2.1", + "get-value": "2.0.6", + "has-value": "1.0.0", + "isobject": "3.0.1", + "set-value": "2.0.0", + "to-object-path": "0.3.0", + "union-value": "1.0.0", + "unset-value": "1.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=" + }, + "capture-stack-trace": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz", + "integrity": "sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0=" + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "requires": { + "align-text": "0.1.4", + "lazy-cache": "1.0.4" + } + }, + "chai": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.1.2.tgz", + "integrity": "sha1-D2RYS6ZC8PKs4oBiefTwbKI61zw=", + "requires": { + "assertion-error": "1.1.0", + "check-error": "1.0.2", + "deep-eql": "3.0.1", + "get-func-name": "2.0.0", + "pathval": "1.1.0", + "type-detect": "4.0.8" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=" + }, + "chokidar": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.3.tgz", + "integrity": "sha512-zW8iXYZtXMx4kux/nuZVXjkLP+CyIK5Al5FHnj1OgTKGZfp4Oy6/ymtMSKFv3GD8DviEmUPmJg9eFdJ/JzudMg==", + "requires": { + "anymatch": "2.0.0", + "async-each": "1.0.1", + "braces": "2.3.2", + "glob-parent": "3.1.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "4.0.0", + "normalize-path": "2.1.1", + "path-is-absolute": "1.0.1", + "readdirp": "2.1.0", + "upath": "1.0.4" + }, + "dependencies": { + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "requires": { + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "repeat-element": "1.1.2", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "requires": { + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "requires": { + "is-glob": "3.1.0", + "path-dirname": "1.0.2" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "requires": { + "is-extglob": "2.1.1" + } + } + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + }, + "is-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "requires": { + "is-extglob": "2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "3.2.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "ci-info": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.1.3.tgz", + "integrity": "sha512-SK/846h/Rcy8q9Z9CAwGBLfCJ6EkjJWdpelWDufQpqVDYq2Wnnv8zlSO6AMQap02jvhVruKKpEtQOufo3pFhLg==" + }, + "circular-json": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", + "dev": true + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "requires": { + "arr-union": "3.1.0", + "define-property": "0.2.5", + "isobject": "3.0.1", + "static-extend": "0.1.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "0.1.6" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "cli-boxes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", + "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=" + }, + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "dev": true, + "requires": { + "restore-cursor": "1.0.1" + } + }, + "cli-width": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-1.1.1.tgz", + "integrity": "sha1-pNKT72frt7iNSk1CwMzwDE0eNm0=", + "dev": true + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "requires": { + "center-align": "0.1.3", + "right-align": "0.1.3", + "wordwrap": "0.0.2" + } + }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=" + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "co-mocha": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/co-mocha/-/co-mocha-1.2.2.tgz", + "integrity": "sha512-ocdJRn3sxonOqpdjSU2VwTwWzjTSoatzsTqCWiC3eGvJFNs8ZNMlZwfgYolQCdfddMz4muiZl99KIV9gKoNvxg==", + "dev": true, + "requires": { + "co": "4.6.0", + "is-generator": "1.0.3" + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "requires": { + "map-visit": "1.0.0", + "object-visit": "1.0.1" + } + }, + "color-convert": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", + "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" + }, + "colors": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.2.1.tgz", + "integrity": "sha512-s8+wktIuDSLffCywiwSxQOMqtPxML11a/dtHE17tMn4B1MSWw/C22EKf7M2KGUBcDaVFEGT+S8N02geDXeuNKg==" + }, + "combined-stream": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "dev": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "commander": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==" + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "1.0.0", + "inherits": "2.0.3", + "readable-stream": "2.3.6", + "typedarray": "0.0.6" + } + }, + "configstore": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz", + "integrity": "sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw==", + "requires": { + "dot-prop": "4.2.0", + "graceful-fs": "4.1.11", + "make-dir": "1.2.0", + "unique-string": "1.0.0", + "write-file-atomic": "2.3.0", + "xdg-basedir": "3.0.0" + } + }, + "cookiejar": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.0.6.tgz", + "integrity": "sha1-Cr81atANHFohnYjURRgEbdAmrP4=", + "dev": true + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" + }, + "core-js": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.5.tgz", + "integrity": "sha1-sU3ek2xkDAV5prUMq8wTLdYSfjs=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "create-error-class": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", + "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", + "requires": { + "capture-stack-trace": "1.0.0" + } + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "requires": { + "lru-cache": "4.1.2", + "shebang-command": "1.2.0", + "which": "1.3.0" + } + }, + "crypto-random-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", + "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=" + }, + "csv": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/csv/-/csv-0.4.6.tgz", + "integrity": "sha1-jbrn3f26rmLB6ph8Pg+Kmsc3tz0=", + "requires": { + "csv-generate": "0.0.6", + "csv-parse": "1.3.3", + "csv-stringify": "0.0.8", + "stream-transform": "0.1.2" + } + }, + "csv-generate": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/csv-generate/-/csv-generate-0.0.6.tgz", + "integrity": "sha1-l+TmOuRrIZEs2UdbwxRp0m9a3mY=" + }, + "csv-parse": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/csv-parse/-/csv-parse-1.3.3.tgz", + "integrity": "sha1-0c/YdDwvhJoKuy/VRNtWaV0ZpJA=" + }, + "csv-stringify": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/csv-stringify/-/csv-stringify-0.0.8.tgz", + "integrity": "sha1-Usw7PfwZd1jFWtMlqVvoUHH55Rs=" + }, + "ctype": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz", + "integrity": "sha1-gsGMJGH3QRTvFsE1IkrQuRRMoS8=" + }, + "d": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", + "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "dev": true, + "requires": { + "es5-ext": "0.10.42" + } + }, + "dateformat": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", + "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=" + }, + "deap": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deap/-/deap-1.0.1.tgz", + "integrity": "sha512-k75KYNZMvwAwes2xIPry/QTffXIchjD8QfABvvfTr80P85jv5ZcKqcoDo+vMe71nNnVnXYe8MA28weyqcf/DKw==" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + }, + "deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "requires": { + "type-detect": "4.0.8" + } + }, + "deep-extend": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", + "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=" + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "requires": { + "is-descriptor": "1.0.2", + "isobject": "3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "dev": true, + "requires": { + "globby": "5.0.0", + "is-path-cwd": "1.0.0", + "is-path-in-cwd": "1.0.1", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "rimraf": "2.4.5" + }, + "dependencies": { + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "detect-file": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-0.1.0.tgz", + "integrity": "sha1-STXe39lIhkjgBrASlWbpOGcR6mM=", + "requires": { + "fs-exists-sync": "0.1.0" + } + }, + "detect-node": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.3.tgz", + "integrity": "sha1-ogM8CcyOFY03dI+951B4Mr1s4Sc=" + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" + }, + "doctrine": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-0.7.2.tgz", + "integrity": "sha1-fLhgNZujvpDgQLJrcpzkv6ZUxSM=", + "dev": true, + "requires": { + "esutils": "1.1.6", + "isarray": "0.0.1" + }, + "dependencies": { + "esutils": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-1.1.6.tgz", + "integrity": "sha1-wBzKqa5LiXxtDD4hCuUvPHqEQ3U=", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + } + } + }, + "dot-prop": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", + "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", + "requires": { + "is-obj": "1.0.1" + } + }, + "dtrace-provider": { + "version": "0.8.6", + "resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.8.6.tgz", + "integrity": "sha1-QooiOv4DQl0s1tY0f99AxmkDVj0=", + "optional": true, + "requires": { + "nan": "2.10.0" + } + }, + "duplexer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=" + }, + "duplexer2": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "requires": { + "readable-stream": "1.1.14" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" + }, + "es5-ext": { + "version": "0.10.42", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.42.tgz", + "integrity": "sha512-AJxO1rmPe1bDEfSR6TJ/FgMFYuTBhR5R57KW58iCkYACMyFbrkqVyzXSurYoScDGvgyMpk7uRF/lPUPPTmsRSA==", + "dev": true, + "requires": { + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1", + "next-tick": "1.0.0" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.42", + "es6-symbol": "3.1.1" + } + }, + "es6-map": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", + "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.42", + "es6-iterator": "2.0.3", + "es6-set": "0.1.5", + "es6-symbol": "3.1.1", + "event-emitter": "0.3.5" + } + }, + "es6-set": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", + "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.42", + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1", + "event-emitter": "0.3.5" + } + }, + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.42" + } + }, + "es6-weak-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", + "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.42", + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1" + } + }, + "escape-regexp-component": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/escape-regexp-component/-/escape-regexp-component-1.0.2.tgz", + "integrity": "sha1-nGO20LJf8qiMOtvRjFthrMO5+qI=" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "escope": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", + "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", + "dev": true, + "requires": { + "es6-map": "0.1.5", + "es6-weak-map": "2.0.2", + "esrecurse": "4.2.1", + "estraverse": "4.2.0" + } + }, + "eslint": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-1.10.3.tgz", + "integrity": "sha1-+xmpGxPBWAgrvKKUsX2Xm8g1Ogo=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "concat-stream": "1.6.2", + "debug": "2.6.9", + "doctrine": "0.7.2", + "escape-string-regexp": "1.0.5", + "escope": "3.6.0", + "espree": "2.2.5", + "estraverse": "4.2.0", + "estraverse-fb": "1.3.2", + "esutils": "2.0.2", + "file-entry-cache": "1.3.1", + "glob": "5.0.15", + "globals": "8.18.0", + "handlebars": "4.0.11", + "inquirer": "0.11.4", + "is-my-json-valid": "2.17.2", + "is-resolvable": "1.1.0", + "js-yaml": "3.4.5", + "json-stable-stringify": "1.0.1", + "lodash.clonedeep": "3.0.2", + "lodash.merge": "3.3.2", + "lodash.omit": "3.1.0", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "object-assign": "4.1.1", + "optionator": "0.6.0", + "path-is-absolute": "1.0.1", + "path-is-inside": "1.0.2", + "shelljs": "0.5.3", + "strip-json-comments": "1.0.4", + "text-table": "0.2.0", + "user-home": "2.0.0", + "xml-escape": "1.0.0" + }, + "dependencies": { + "espree": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/espree/-/espree-2.2.5.tgz", + "integrity": "sha1-32kbkxCIlAKuspzAZnCMVmkLhUs=", + "dev": true + }, + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "js-yaml": { + "version": "3.4.5", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.4.5.tgz", + "integrity": "sha1-w0A3l98SuRhmV08t4jZG/oyvtE0=", + "dev": true, + "requires": { + "argparse": "1.0.10", + "esprima": "2.7.3" + }, + "dependencies": { + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + } + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "strip-json-comments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", + "integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=", + "dev": true + }, + "user-home": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz", + "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", + "dev": true, + "requires": { + "os-homedir": "1.0.2" + } + } + } + }, + "eslint-config-probo": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-probo/-/eslint-config-probo-1.1.0.tgz", + "integrity": "sha1-jCGPMgHBM1Ry7+TodJ2ka+WyVuU=", + "dev": true + }, + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==" + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": true, + "requires": { + "estraverse": "4.2.0" + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + }, + "estraverse-fb": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/estraverse-fb/-/estraverse-fb-1.3.2.tgz", + "integrity": "sha1-0yOky15awzHOoDNBOpJT4WQ+B8Q=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.42" + } + }, + "event-stream": { + "version": "3.3.4", + "resolved": "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", + "requires": { + "duplexer": "0.1.1", + "from": "0.1.7", + "map-stream": "0.1.0", + "pause-stream": "0.0.11", + "split": "0.3.3", + "stream-combiner": "0.0.4", + "through": "2.3.8" + } + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "requires": { + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" + } + }, + "exit-hook": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", + "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", + "dev": true + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "requires": { + "fill-range": "2.2.3" + } + }, + "expand-tilde": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-1.2.2.tgz", + "integrity": "sha1-C4HrqJflo9MdHD0QL48BRB5VlEk=", + "requires": { + "os-homedir": "1.0.2" + } + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "requires": { + "assign-symbols": "1.0.0", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "requires": { + "is-extglob": "1.0.0" + } + }, + "extsprintf": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.2.0.tgz", + "integrity": "sha1-WtlGwi9bMrp/jNdCZxHG6KP8JSk=" + }, + "fancy-log": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", + "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", + "requires": { + "ansi-gray": "0.1.1", + "color-support": "1.1.3", + "time-stamp": "1.1.0" + } + }, + "fast-levenshtein": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.0.7.tgz", + "integrity": "sha1-AXjc3uAjuSkFGTrwlZ6KdjnP3Lk=", + "dev": true + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" + }, + "dependencies": { + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + } + } + }, + "file-entry-cache": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-1.3.1.tgz", + "integrity": "sha1-RMYepgeuS+nBQC9B9EJwy/4zT/g=", + "dev": true, + "requires": { + "flat-cache": "1.3.0", + "object-assign": "4.1.1" + }, + "dependencies": { + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + } + } + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=" + }, + "fill-range": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", + "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "1.1.7", + "repeat-element": "1.1.2", + "repeat-string": "1.6.1" + } + }, + "findup-sync": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.4.3.tgz", + "integrity": "sha1-QAQ5Kee8YK3wt/SCfExudaDeyhI=", + "requires": { + "detect-file": "0.1.0", + "is-glob": "2.0.1", + "micromatch": "2.3.11", + "resolve-dir": "0.1.1" + } + }, + "flagged-respawn": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-0.3.2.tgz", + "integrity": "sha1-/xke3c1wiKZ1smEP/8l2vpuAdLU=" + }, + "flat-cache": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", + "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", + "dev": true, + "requires": { + "circular-json": "0.3.3", + "del": "2.2.2", + "graceful-fs": "4.1.11", + "write": "0.2.1" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "requires": { + "for-in": "1.0.2" + } + }, + "form-data": { + "version": "1.0.0-rc3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-1.0.0-rc3.tgz", + "integrity": "sha1-01vGLn+8KTeuePlIqqDTjZBgdXc=", + "dev": true, + "requires": { + "async": "1.5.2", + "combined-stream": "1.0.6", + "mime-types": "2.1.18" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + } + } + }, + "formidable": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.1.tgz", + "integrity": "sha512-Fs9VRguL0gqGHkXS5GQiMCr1VhZBxz0JnJs4JmMp/2jL18Fmbzvv7vOFRU+U8TBkHEE/CX1qDXzJplVULgsLeg==" + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "requires": { + "map-cache": "0.2.2" + } + }, + "from": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", + "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=" + }, + "fs-exists-sync": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz", + "integrity": "sha1-mC1ok6+RjnLQjeyehnP/K1qNat0=" + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "g": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/g/-/g-2.0.1.tgz", + "integrity": "sha1-C1lj69DKcOO8jGdmk0oCGCHIuFc=" + }, + "generate-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", + "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", + "dev": true + }, + "generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "dev": true, + "requires": { + "is-property": "1.0.2" + } + }, + "generic-pool": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.5.4.tgz", + "integrity": "sha1-OMYYhRPhQDCUjsblz2VSPZd5KZs=" + }, + "get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=" + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" + }, + "glob": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", + "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "requires": { + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "requires": { + "is-glob": "2.0.1" + } + }, + "global-dirs": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", + "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", + "requires": { + "ini": "1.3.5" + } + }, + "global-modules": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-0.2.3.tgz", + "integrity": "sha1-6lo77ULG1s6ZWk+KEmm12uIjgo0=", + "requires": { + "global-prefix": "0.1.5", + "is-windows": "0.2.0" + } + }, + "global-prefix": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-0.1.5.tgz", + "integrity": "sha1-jTvGuNo8qBEqFg2NSW/wRiv+948=", + "requires": { + "homedir-polyfill": "1.0.1", + "ini": "1.3.5", + "is-windows": "0.2.0", + "which": "1.3.0" + } + }, + "globals": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-8.18.0.tgz", + "integrity": "sha1-k9SmK9ysOM+vr8R9awNHaMsP/LQ=", + "dev": true + }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "arrify": "1.0.1", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + }, + "dependencies": { + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "glogg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.1.tgz", + "integrity": "sha512-ynYqXLoluBKf9XGR1gA59yEJisIL7YHEH4xr3ZziHB5/yl4qWfaK8Js9jGe6gBGCSCKVqiyO30WnRZADvemUNw==", + "requires": { + "sparkles": "1.0.0" + } + }, + "got": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz", + "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", + "requires": { + "create-error-class": "3.0.2", + "duplexer3": "0.1.4", + "get-stream": "3.0.0", + "is-redirect": "1.0.0", + "is-retry-allowed": "1.1.0", + "is-stream": "1.1.0", + "lowercase-keys": "1.0.1", + "safe-buffer": "5.1.1", + "timed-out": "4.0.1", + "unzip-response": "2.0.1", + "url-parse-lax": "1.0.0" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "growl": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz", + "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==", + "dev": true + }, + "gulp-uglify": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-1.5.4.tgz", + "integrity": "sha1-UkeI2HZm0J+dDCH7IXf5ADmmWMk=", + "requires": { + "deap": "1.0.1", + "fancy-log": "1.3.2", + "gulp-util": "3.0.8", + "isobject": "2.1.0", + "through2": "2.0.3", + "uglify-js": "2.6.4", + "uglify-save-license": "0.4.1", + "vinyl-sourcemaps-apply": "0.2.1" + } + }, + "gulp-util": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", + "requires": { + "array-differ": "1.0.0", + "array-uniq": "1.0.3", + "beeper": "1.1.1", + "chalk": "1.1.3", + "dateformat": "2.2.0", + "fancy-log": "1.3.2", + "gulplog": "1.0.0", + "has-gulplog": "0.1.0", + "lodash._reescape": "3.0.0", + "lodash._reevaluate": "3.0.0", + "lodash._reinterpolate": "3.0.0", + "lodash.template": "3.6.2", + "minimist": "1.2.0", + "multipipe": "0.1.2", + "object-assign": "3.0.0", + "replace-ext": "0.0.1", + "through2": "2.0.3", + "vinyl": "0.5.3" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + } + } + }, + "gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", + "requires": { + "glogg": "1.0.1" + } + }, + "handle-thing": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz", + "integrity": "sha1-/Xqtcmvxpf0W38KbL3pmAdJxOcQ=" + }, + "handlebars": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", + "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", + "dev": true, + "requires": { + "async": "1.5.2", + "optimist": "0.6.1", + "source-map": "0.4.4", + "uglify-js": "2.6.4" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true, + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "has-gulplog": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", + "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", + "requires": { + "sparkles": "1.0.0" + } + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "requires": { + "get-value": "2.0.6", + "has-values": "1.0.0", + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "dev": true + }, + "homedir-polyfill": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", + "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", + "requires": { + "parse-passwd": "1.0.0" + } + }, + "hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", + "requires": { + "inherits": "2.0.3", + "obuf": "1.1.2", + "readable-stream": "2.3.6", + "wbuf": "1.7.3" + } + }, + "http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=" + }, + "http-signature": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.11.0.tgz", + "integrity": "sha1-F5bPZ6ABrVzWhJ3KCZFIXwkIn+Y=", + "requires": { + "asn1": "0.1.11", + "assert-plus": "0.1.5", + "ctype": "0.5.3" + } + }, + "ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=" + }, + "import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=" + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" + }, + "inquirer": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.11.4.tgz", + "integrity": "sha1-geM3ToNhvq/y2XAWIG01nQsy+k0=", + "dev": true, + "requires": { + "ansi-escapes": "1.4.0", + "ansi-regex": "2.1.1", + "chalk": "1.1.3", + "cli-cursor": "1.0.2", + "cli-width": "1.1.1", + "figures": "1.7.0", + "lodash": "3.10.1", + "readline2": "1.0.1", + "run-async": "0.1.0", + "rx-lite": "3.1.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "through": "2.3.8" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + } + } + }, + "interpret": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-0.6.6.tgz", + "integrity": "sha1-/s16GOfOXKar+5U+H4YhOknxYls=" + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "requires": { + "loose-envify": "1.3.1" + } + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "3.2.2" + } + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "requires": { + "binary-extensions": "1.11.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "is-ci": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.1.0.tgz", + "integrity": "sha512-c7TnwxLePuqIlxHgr7xtxzycJPegNHFuIrBkwbf8hc58//+Op1CqFkyS+xnIMkwn9UsJIwc174BIjkyBmSpjKg==", + "requires": { + "ci-info": "1.1.3" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "3.2.2" + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=" + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "requires": { + "is-primitive": "2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "is-generator": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-generator/-/is-generator-1.0.3.tgz", + "integrity": "sha1-wUwhBX7TbjKNuANHlmxpP4hjifM=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "requires": { + "is-extglob": "1.0.0" + } + }, + "is-installed-globally": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz", + "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=", + "requires": { + "global-dirs": "0.1.1", + "is-path-inside": "1.0.1" + } + }, + "is-my-ip-valid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz", + "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==", + "dev": true + }, + "is-my-json-valid": { + "version": "2.17.2", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.17.2.tgz", + "integrity": "sha512-IBhBslgngMQN8DDSppmgDv7RNrlFotuuDsKcrCP3+HbFaVivIBU7u9oiiErw8sH4ynx3+gOGQ3q2otkgiSi6kg==", + "dev": true, + "requires": { + "generate-function": "2.0.0", + "generate-object-property": "1.2.0", + "is-my-ip-valid": "1.0.0", + "jsonpointer": "4.0.1", + "xtend": "4.0.1" + } + }, + "is-npm": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz", + "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=" + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "requires": { + "kind-of": "3.2.2" + } + }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=" + }, + "is-odd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-2.0.0.tgz", + "integrity": "sha512-OTiixgpZAT1M4NHgS5IguFp/Vz2VI3U7Goh4/HA1adtwyLtSBrxYlcSYkhpAE07s4fKEcjrFxyvtQBND4vFQyQ==", + "requires": { + "is-number": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==" + } + } + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", + "dev": true, + "requires": { + "is-path-inside": "1.0.1" + } + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "requires": { + "path-is-inside": "1.0.2" + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=" + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=" + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", + "dev": true + }, + "is-redirect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", + "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=" + }, + "is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", + "dev": true + }, + "is-retry-allowed": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", + "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=" + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "is-windows": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-0.2.0.tgz", + "integrity": "sha1-3hqm1j6indJIc3tp8f+LgALSEIw=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "requires": { + "isarray": "1.0.0" + } + }, + "js-string-escape": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz", + "integrity": "sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8=" + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" + }, + "js-yaml": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.11.0.tgz", + "integrity": "sha512-saJstZWv7oNeOyBh3+Dx1qWzhW0+e6/8eDzo7p5rDFqxntSztloLtuKu+Ejhtq82jsilwOIZYsCz+lIjthg1Hw==", + "requires": { + "argparse": "1.0.10", + "esprima": "4.0.0" + } + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "dev": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "jsonpointer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", + "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", + "dev": true + }, + "keep-alive-agent": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/keep-alive-agent/-/keep-alive-agent-0.0.1.tgz", + "integrity": "sha1-RIR8o5TOjWtSGuhYFr1kUJlCs4U=" + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + }, + "knex": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/knex/-/knex-0.13.0.tgz", + "integrity": "sha1-CN1JT2u2SSiTTuydrDR4ehTKX6Q=", + "requires": { + "babel-runtime": "6.26.0", + "bluebird": "3.5.1", + "chalk": "1.1.3", + "commander": "2.15.1", + "debug": "2.6.9", + "generic-pool": "2.5.4", + "inherits": "2.0.3", + "interpret": "0.6.6", + "liftoff": "2.2.5", + "lodash": "4.17.5", + "minimist": "1.1.3", + "mkdirp": "0.5.1", + "pg-connection-string": "0.1.3", + "readable-stream": "1.1.14", + "safe-buffer": "5.1.1", + "tildify": "1.0.0", + "uuid": "3.2.1", + "v8flags": "2.1.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "lodash": { + "version": "4.17.5", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==" + }, + "minimist": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.1.3.tgz", + "integrity": "sha1-O+39kaktOQFvz6ocaB6Pqhoe/ag=" + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, + "knex-migrate": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/knex-migrate/-/knex-migrate-1.5.5.tgz", + "integrity": "sha512-1ymXcY0u+PrmHzxpqRAt4SZRDkHIJjzEe6FTtHkGrWm/HkJQF8yG0GbQbqogy6JhaSFY8kH9GJG2lL0OZxW8xg==", + "requires": { + "bluebird": "3.5.1", + "core-js": "2.5.5", + "invariant": "2.2.4", + "lodash": "4.17.5", + "minimist": "1.2.0", + "prettyjson": "1.2.1", + "regenerator-runtime": "0.11.1", + "req-from": "1.0.1", + "umzug": "2.1.0" + }, + "dependencies": { + "lodash": { + "version": "4.17.5", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==" + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + } + } + }, + "latest-version": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz", + "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=", + "requires": { + "package-json": "4.0.1" + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=" + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "requires": { + "invert-kv": "1.0.0" + } + }, + "levn": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.2.5.tgz", + "integrity": "sha1-uo0znQykphDjo/FFucr0iAcVUFQ=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2", + "type-check": "0.3.2" + } + }, + "liftoff": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.2.5.tgz", + "integrity": "sha1-mYwods/0hLED5EI7k9NW2kRzTJE=", + "requires": { + "extend": "3.0.1", + "findup-sync": "0.4.3", + "flagged-respawn": "0.3.2", + "rechoir": "0.6.2", + "resolve": "1.7.1" + } + }, + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" + }, + "lodash._arraycopy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._arraycopy/-/lodash._arraycopy-3.0.0.tgz", + "integrity": "sha1-due3wfH7klRzdIeKVi7Qaj5Q9uE=", + "dev": true + }, + "lodash._arrayeach": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._arrayeach/-/lodash._arrayeach-3.0.0.tgz", + "integrity": "sha1-urFWsqkNPxu9XGU0AzSeXlkz754=", + "dev": true + }, + "lodash._arraymap": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._arraymap/-/lodash._arraymap-3.0.0.tgz", + "integrity": "sha1-Go/Q9MDfS2HeoHbXF83Jfwo8PmY=", + "dev": true + }, + "lodash._baseassign": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", + "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", + "dev": true, + "requires": { + "lodash._basecopy": "3.0.1", + "lodash.keys": "3.1.2" + } + }, + "lodash._baseclone": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lodash._baseclone/-/lodash._baseclone-3.3.0.tgz", + "integrity": "sha1-MDUZv2OT/n5C802LYw73eU41Qrc=", + "dev": true, + "requires": { + "lodash._arraycopy": "3.0.0", + "lodash._arrayeach": "3.0.0", + "lodash._baseassign": "3.2.0", + "lodash._basefor": "3.0.3", + "lodash.isarray": "3.0.4", + "lodash.keys": "3.1.2" + } + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=" + }, + "lodash._basedifference": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash._basedifference/-/lodash._basedifference-3.0.3.tgz", + "integrity": "sha1-8sIEKWwqeOArOJCBtu3KyTPPYpw=", + "dev": true, + "requires": { + "lodash._baseindexof": "3.1.0", + "lodash._cacheindexof": "3.0.2", + "lodash._createcache": "3.1.2" + } + }, + "lodash._baseflatten": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/lodash._baseflatten/-/lodash._baseflatten-3.1.4.tgz", + "integrity": "sha1-B3D/gBMa9uNPO1EXlqe6UhTmX/c=", + "dev": true, + "requires": { + "lodash.isarguments": "3.1.0", + "lodash.isarray": "3.0.4" + } + }, + "lodash._basefor": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash._basefor/-/lodash._basefor-3.0.3.tgz", + "integrity": "sha1-dVC06SGO8J+tJDQ7YSAhx5tMIMI=", + "dev": true + }, + "lodash._baseindexof": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash._baseindexof/-/lodash._baseindexof-3.1.0.tgz", + "integrity": "sha1-/lK1OhxnYeQmGNZU5KJXie1hgiw=", + "dev": true + }, + "lodash._basetostring": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", + "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=" + }, + "lodash._basevalues": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", + "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=" + }, + "lodash._bindcallback": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz", + "integrity": "sha1-5THCdkTPi1epnhftlbNcdIeJOS4=", + "dev": true + }, + "lodash._cacheindexof": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/lodash._cacheindexof/-/lodash._cacheindexof-3.0.2.tgz", + "integrity": "sha1-PcaayCSY0u5ePOVgkbr9Ktx73pI=", + "dev": true + }, + "lodash._createassigner": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash._createassigner/-/lodash._createassigner-3.1.1.tgz", + "integrity": "sha1-g4pbri/aymOsIt7o4Z+k5taXCxE=", + "dev": true, + "requires": { + "lodash._bindcallback": "3.0.1", + "lodash._isiterateecall": "3.0.9", + "lodash.restparam": "3.6.1" + } + }, + "lodash._createcache": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash._createcache/-/lodash._createcache-3.1.2.tgz", + "integrity": "sha1-VtagZAF2JeeevKa4AY4XRAvc8JM=", + "dev": true, + "requires": { + "lodash._getnative": "3.9.1" + } + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=" + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=" + }, + "lodash._pickbyarray": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/lodash._pickbyarray/-/lodash._pickbyarray-3.0.2.tgz", + "integrity": "sha1-H4mNlgfrVgsOFnOEt3x8bRCKpMU=", + "dev": true + }, + "lodash._pickbycallback": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._pickbycallback/-/lodash._pickbycallback-3.0.0.tgz", + "integrity": "sha1-/2G5oBens699MObFPeKK+hm4dQo=", + "dev": true, + "requires": { + "lodash._basefor": "3.0.3", + "lodash.keysin": "3.0.8" + } + }, + "lodash._reescape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", + "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=" + }, + "lodash._reevaluate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", + "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=" + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=" + }, + "lodash._root": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", + "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=" + }, + "lodash.clonedeep": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-3.0.2.tgz", + "integrity": "sha1-oKHkDYKl6on/WxR7hETtY9koJ9s=", + "dev": true, + "requires": { + "lodash._baseclone": "3.3.0", + "lodash._bindcallback": "3.0.1" + } + }, + "lodash.escape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", + "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", + "requires": { + "lodash._root": "3.0.1" + } + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=" + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=" + }, + "lodash.isplainobject": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-3.2.0.tgz", + "integrity": "sha1-moI4rhayAEMpYM1zRlEtASP79MU=", + "dev": true, + "requires": { + "lodash._basefor": "3.0.3", + "lodash.isarguments": "3.1.0", + "lodash.keysin": "3.0.8" + } + }, + "lodash.istypedarray": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/lodash.istypedarray/-/lodash.istypedarray-3.0.6.tgz", + "integrity": "sha1-yaR3SYYHUB2OhJTSg7h8OSgc72I=", + "dev": true + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "requires": { + "lodash._getnative": "3.9.1", + "lodash.isarguments": "3.1.0", + "lodash.isarray": "3.0.4" + } + }, + "lodash.keysin": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/lodash.keysin/-/lodash.keysin-3.0.8.tgz", + "integrity": "sha1-IsRJPrvtsUJ5YqVLRFssinZ/tH8=", + "dev": true, + "requires": { + "lodash.isarguments": "3.1.0", + "lodash.isarray": "3.0.4" + } + }, + "lodash.merge": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-3.3.2.tgz", + "integrity": "sha1-DZDZPtY3sYeEN7s+IWASYNev6ZQ=", + "dev": true, + "requires": { + "lodash._arraycopy": "3.0.0", + "lodash._arrayeach": "3.0.0", + "lodash._createassigner": "3.1.1", + "lodash._getnative": "3.9.1", + "lodash.isarguments": "3.1.0", + "lodash.isarray": "3.0.4", + "lodash.isplainobject": "3.2.0", + "lodash.istypedarray": "3.0.6", + "lodash.keys": "3.1.2", + "lodash.keysin": "3.0.8", + "lodash.toplainobject": "3.0.0" + } + }, + "lodash.omit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-3.1.0.tgz", + "integrity": "sha1-iX/jguZBPZrJfGH3jtHgV6AK+fM=", + "dev": true, + "requires": { + "lodash._arraymap": "3.0.0", + "lodash._basedifference": "3.0.3", + "lodash._baseflatten": "3.1.4", + "lodash._bindcallback": "3.0.1", + "lodash._pickbyarray": "3.0.2", + "lodash._pickbycallback": "3.0.0", + "lodash.keysin": "3.0.8", + "lodash.restparam": "3.6.1" + } + }, + "lodash.restparam": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", + "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=" + }, + "lodash.template": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", + "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", + "requires": { + "lodash._basecopy": "3.0.1", + "lodash._basetostring": "3.0.1", + "lodash._basevalues": "3.0.0", + "lodash._isiterateecall": "3.0.9", + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0", + "lodash.keys": "3.1.2", + "lodash.restparam": "3.6.1", + "lodash.templatesettings": "3.1.1" + } + }, + "lodash.templatesettings": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", + "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", + "requires": { + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0" + } + }, + "lodash.toplainobject": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash.toplainobject/-/lodash.toplainobject-3.0.0.tgz", + "integrity": "sha1-KHkK2ULSk9eKpmOgfs9/UsoEGY0=", + "dev": true, + "requires": { + "lodash._basecopy": "3.0.1", + "lodash.keysin": "3.0.8" + } + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" + }, + "loose-envify": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", + "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", + "requires": { + "js-tokens": "3.0.2" + } + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" + }, + "lru-cache": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.2.tgz", + "integrity": "sha512-wgeVXhrDwAWnIF/yZARsFnMBtdFXOg1b8RIrhilp+0iDYN4mdQcNZElDZ0e4B64BhaxeQ5zN7PMyvu7we1kPeQ==", + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + }, + "dependencies": { + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + } + } + }, + "make-dir": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.2.0.tgz", + "integrity": "sha512-aNUAa4UMg/UougV25bbrU4ZaaKNjJ/3/xnvg/twpmKROPdKZPZ9wGgI0opdZzO8q/zUFawoUuixuOv33eZ61Iw==", + "requires": { + "pify": "3.0.0" + } + }, + "make-error": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.4.tgz", + "integrity": "sha512-0Dab5btKVPhibSalc9QGXb559ED7G7iLjFXBaj9Wq8O3vorueR5K5jaE3hkG6ZQINyhA/JgG6Qk4qdFQjsYV6g==" + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" + }, + "map-stream": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=" + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "requires": { + "object-visit": "1.0.1" + } + }, + "memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "dev": true + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "dev": true, + "requires": { + "mime-db": "1.33.0" + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "1.1.11" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "mixin-deep": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", + "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "requires": { + "for-in": "1.0.2", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } + }, + "mocha": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.1.1.tgz", + "integrity": "sha512-kKKs/H1KrMMQIEsWNxGmb4/BGsmj0dkeyotEvbrAuQ01FcWRLssUNXCEUZk6SZtyJBi6EE7SL0zDDtItw1rGhw==", + "dev": true, + "requires": { + "browser-stdout": "1.3.1", + "commander": "2.11.0", + "debug": "3.1.0", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "glob": "7.1.2", + "growl": "1.10.3", + "he": "1.1.1", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "supports-color": "4.4.0" + }, + "dependencies": { + "commander": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", + "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "supports-color": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", + "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "moment": { + "version": "2.22.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.22.1.tgz", + "integrity": "sha512-shJkRTSebXvsVqk56I+lkb2latjBs8I+pc2TzWc545y2iFnSjm7Wg0QMh+ZWcdSLQyGEau5jI8ocnmkyTgr9YQ==", + "optional": true + }, + "ms": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.3.tgz", + "integrity": "sha1-cIFVpeROM/X9D8U+gdDUCpG+H/8=" + }, + "multipipe": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", + "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", + "requires": { + "duplexer2": "0.0.2" + } + }, + "mute-stream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", + "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=", + "dev": true + }, + "mv": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz", + "integrity": "sha1-rmzg1vbV4KT32JN5jQPB6pVZtqI=", + "optional": true, + "requires": { + "mkdirp": "0.5.1", + "ncp": "2.0.0", + "rimraf": "2.4.5" + } + }, + "nan": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", + "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", + "optional": true + }, + "nanomatch": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.9.tgz", + "integrity": "sha512-n8R9bS8yQ6eSXaV6jHUpKzD8gLsin02w1HSFiegwrs9E098Ylhw5jdyKPaYqvHknHaSCKTPp7C8dGCQ0q9koXA==", + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "fragment-cache": "0.2.1", + "is-odd": "2.0.0", + "is-windows": "1.0.2", + "kind-of": "6.0.2", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "ncp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", + "integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=", + "optional": true + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" + }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "dev": true + }, + "nodemon": { + "version": "1.17.3", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-1.17.3.tgz", + "integrity": "sha512-8AtS+wA5u6qoE12LONjqOzUzxAI5ObzSw6U5LgqpaO/0y6wwId4l5dN0ZulYyYdpLZD1MbkBp7GjG1hqaoRqYg==", + "requires": { + "chokidar": "2.0.3", + "debug": "3.1.0", + "ignore-by-default": "1.0.1", + "minimatch": "3.0.4", + "pstree.remy": "1.1.0", + "semver": "5.5.0", + "supports-color": "5.4.0", + "touch": "3.1.0", + "undefsafe": "2.0.2", + "update-notifier": "2.5.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", + "requires": { + "abbrev": "1.1.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "requires": { + "remove-trailing-separator": "1.1.0" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "requires": { + "path-key": "2.0.1" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=" + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "requires": { + "copy-descriptor": "0.1.1", + "define-property": "0.2.5", + "kind-of": "3.2.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "0.1.6" + } + } + } + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "requires": { + "for-own": "0.1.5", + "is-extendable": "0.1.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1.0.2" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", + "dev": true + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "0.0.8", + "wordwrap": "0.0.2" + } + }, + "optionator": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.6.0.tgz", + "integrity": "sha1-tj7Lvw4xX61LyYJ7Rdx7pFKE/LY=", + "dev": true, + "requires": { + "deep-is": "0.1.3", + "fast-levenshtein": "1.0.7", + "levn": "0.2.5", + "prelude-ls": "1.1.2", + "type-check": "0.3.2", + "wordwrap": "0.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "requires": { + "lcid": "1.0.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" + }, + "package-json": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz", + "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=", + "requires": { + "got": "6.7.1", + "registry-auth-token": "3.3.2", + "registry-url": "3.1.0", + "semver": "5.5.0" + } + }, + "packet-reader": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-0.3.1.tgz", + "integrity": "sha1-zWLmCvjX/qinBexP+ZCHHEaHHyc=" + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "requires": { + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" + } + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=" + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" + }, + "passport": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.2.2.tgz", + "integrity": "sha1-nDjxe+uSnz2Br3uIOOhDDbhwPys=", + "requires": { + "passport-strategy": "1.0.0", + "pause": "0.0.1" + } + }, + "passport-http-bearer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/passport-http-bearer/-/passport-http-bearer-1.0.1.tgz", + "integrity": "sha1-FHRp6jZp4qhMYWfvmdu3fh8AmKg=", + "requires": { + "passport-strategy": "1.0.0" + } + }, + "passport-strategy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", + "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=" + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=" + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" + }, + "path-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=" + }, + "pathval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=" + }, + "pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=" + }, + "pause-stream": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", + "requires": { + "through": "2.3.8" + } + }, + "pg": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/pg/-/pg-6.4.2.tgz", + "integrity": "sha1-w2QBEGDqx6UHoq4GPrhX7OkQ4n8=", + "requires": { + "buffer-writer": "1.0.1", + "js-string-escape": "1.0.1", + "packet-reader": "0.3.1", + "pg-connection-string": "0.1.3", + "pg-pool": "1.8.0", + "pg-types": "1.13.0", + "pgpass": "1.0.2", + "semver": "4.3.2" + }, + "dependencies": { + "semver": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.2.tgz", + "integrity": "sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c=" + } + } + }, + "pg-connection-string": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-0.1.3.tgz", + "integrity": "sha1-2hhHsglA5C7hSSvq9l1J2RskXfc=" + }, + "pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==" + }, + "pg-pool": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-1.8.0.tgz", + "integrity": "sha1-9+xzgkw3oD8Hb1G/33DjQBR8Tzc=", + "requires": { + "generic-pool": "2.4.3", + "object-assign": "4.1.0" + }, + "dependencies": { + "generic-pool": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.4.3.tgz", + "integrity": "sha1-eAw29p360FpaBF3Te+etyhGk9v8=" + }, + "object-assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz", + "integrity": "sha1-ejs9DpgGPUP0wD8uiubNUahog6A=" + } + } + }, + "pg-types": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-1.13.0.tgz", + "integrity": "sha512-lfKli0Gkl/+za/+b6lzENajczwZHc7D5kiUCZfgm914jipD2kIOIvEkAhZ8GrW3/TUoP9w8FHjwpPObBye5KQQ==", + "requires": { + "pg-int8": "1.0.1", + "postgres-array": "1.0.2", + "postgres-bytea": "1.0.0", + "postgres-date": "1.0.3", + "postgres-interval": "1.1.1" + } + }, + "pgpass": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.2.tgz", + "integrity": "sha1-Knu0G2BltnkH6R2hsHwYR8h3swY=", + "requires": { + "split": "1.0.1" + }, + "dependencies": { + "split": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", + "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "requires": { + "through": "2.3.8" + } + } + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "2.0.4" + } + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" + }, + "postgres-array": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-1.0.2.tgz", + "integrity": "sha1-jgsy6wO/d6XAp4UeBEHBaaJWojg=" + }, + "postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=" + }, + "postgres-date": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.3.tgz", + "integrity": "sha1-4tiXAu/bJY/52c7g/pG9BpdSV6g=" + }, + "postgres-interval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.1.1.tgz", + "integrity": "sha512-OkuCi9t/3CZmeQreutGgx/OVNv9MKHGIT5jH8KldQ4NLYXkvmT9nDVxEuCENlNwhlGPE374oA/xMqn05G49pHA==", + "requires": { + "xtend": "4.0.1" + } + }, + "precond": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/precond/-/precond-0.2.3.tgz", + "integrity": "sha1-qpWRvKokkj8eD0hJ0kD0fvwQdaw=" + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=" + }, + "prettyjson": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prettyjson/-/prettyjson-1.2.1.tgz", + "integrity": "sha1-/P+rQdGcq0365eV15kJGYZsS0ok=", + "requires": { + "colors": "1.2.1", + "minimist": "1.2.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + } + } + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + }, + "ps-tree": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.1.0.tgz", + "integrity": "sha1-tCGyQUDWID8e08dplrRCewjowBQ=", + "requires": { + "event-stream": "3.3.4" + } + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, + "pstree.remy": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.0.tgz", + "integrity": "sha512-q5I5vLRMVtdWa8n/3UEzZX7Lfghzrg9eG2IKk2ENLSofKRCXVqMvMUHxCKgXNaqH/8ebhBxrqftHWnyTFweJ5Q==", + "requires": { + "ps-tree": "1.1.0" + } + }, + "qs": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" + }, + "randomatic": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", + "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "rc": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.6.tgz", + "integrity": "sha1-6xiYnG1PTxYsOZ953dKfODVWgJI=", + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + } + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "1.0.2", + "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.2" + } + }, + "readdirp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", + "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", + "requires": { + "graceful-fs": "4.1.11", + "minimatch": "3.0.4", + "readable-stream": "2.3.6", + "set-immediate-shim": "1.0.1" + } + }, + "readline2": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz", + "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "mute-stream": "0.0.5" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + } + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "requires": { + "resolve": "1.7.1" + } + }, + "reduce-component": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/reduce-component/-/reduce-component-1.0.1.tgz", + "integrity": "sha1-4Mk1QsV0UhvqE98PlIjtgqt3xdo=", + "dev": true + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "requires": { + "is-equal-shallow": "0.1.3" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "requires": { + "extend-shallow": "3.0.2", + "safe-regex": "1.1.0" + } + }, + "registry-auth-token": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz", + "integrity": "sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==", + "requires": { + "rc": "1.2.6", + "safe-buffer": "5.1.1" + } + }, + "registry-url": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", + "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", + "requires": { + "rc": "1.2.6" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=" + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=" + }, + "req-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/req-from/-/req-from-1.0.1.tgz", + "integrity": "sha1-v4HaUUeUfTLRO5R9wSpYrUWHNQ4=", + "requires": { + "resolve-from": "2.0.0" + } + }, + "resolve": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz", + "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==", + "requires": { + "path-parse": "1.0.5" + } + }, + "resolve-dir": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-0.1.1.tgz", + "integrity": "sha1-shklmlYC+sXFxJatiUpujMQwJh4=", + "requires": { + "expand-tilde": "1.2.2", + "global-modules": "0.2.3" + } + }, + "resolve-from": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", + "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=" + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" + }, + "restify": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/restify/-/restify-4.3.3.tgz", + "integrity": "sha512-PKYab7wZWd/wenNacGek/nkAxNNJiGF2dtOBHhczNFWn9ZNnMFOaGEDwHiHWzmNN6eDJqYQ7CtvScOcNEH5tsA==", + "requires": { + "assert-plus": "0.1.5", + "backoff": "2.5.0", + "bunyan": "1.8.12", + "csv": "0.4.6", + "dtrace-provider": "0.8.6", + "escape-regexp-component": "1.0.2", + "formidable": "1.2.1", + "http-signature": "0.11.0", + "keep-alive-agent": "0.0.1", + "lru-cache": "4.1.2", + "mime": "1.6.0", + "negotiator": "0.6.1", + "once": "1.4.0", + "qs": "6.5.1", + "semver": "4.3.6", + "spdy": "3.4.7", + "tunnel-agent": "0.4.3", + "uuid": "3.2.1", + "vasync": "1.6.3", + "verror": "1.10.0" + }, + "dependencies": { + "semver": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", + "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=" + } + } + }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "dev": true, + "requires": { + "exit-hook": "1.1.1", + "onetime": "1.1.0" + } + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" + }, + "rethinkdbdash": { + "version": "2.3.31", + "resolved": "https://registry.npmjs.org/rethinkdbdash/-/rethinkdbdash-2.3.31.tgz", + "integrity": "sha512-6nXrKFjdg2Ug0YpdmPWSvyD/2EisHnFNt4FWZ74dcXGK48ievSv+cNFTmVv+KjLi6I9CCf6w4CKZ6yCYTfMfdQ==", + "requires": { + "bluebird": "3.5.1" + } + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "requires": { + "align-text": "0.1.4" + } + }, + "rimraf": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz", + "integrity": "sha1-7nEM5dk6j9uFb7Xqj/Di11k0sto=", + "requires": { + "glob": "6.0.4" + } + }, + "run-async": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", + "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", + "dev": true, + "requires": { + "once": "1.4.0" + } + }, + "rx-lite": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", + "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=", + "dev": true + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + }, + "safe-json-stringify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-json-stringify/-/safe-json-stringify-1.1.0.tgz", + "integrity": "sha512-EzBtUaFH9bHYPc69wqjp0efJI/DPNHdFbGE3uIMn4sVbO0zx8vZ8cG4WKxQfOpUOKsQyGBiT2mTqnCw+6nLswA==", + "optional": true + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "requires": { + "ret": "0.1.15" + } + }, + "select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=" + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" + }, + "semver-diff": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", + "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", + "requires": { + "semver": "5.5.0" + } + }, + "set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=" + }, + "set-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "split-string": "3.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "requires": { + "shebang-regex": "1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" + }, + "shelljs": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.5.3.tgz", + "integrity": "sha1-xUmCuZbHbvDB5rWfvcWCX1txMRM=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "requires": { + "base": "0.11.2", + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "map-cache": "0.2.2", + "source-map": "0.5.7", + "source-map-resolve": "0.5.1", + "use": "3.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "requires": { + "define-property": "1.0.0", + "isobject": "3.0.1", + "snapdragon-util": "3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "requires": { + "kind-of": "3.2.2" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + }, + "source-map-resolve": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.1.tgz", + "integrity": "sha512-0KW2wvzfxm8NCTb30z0LMNyPqWCdDGE2viwzUaucqJdkTRXtZiSY3I+2A6nVAjmdOy0I4gU8DwnVVGsk9jvP2A==", + "requires": { + "atob": "2.1.0", + "decode-uri-component": "0.2.0", + "resolve-url": "0.2.1", + "source-map-url": "0.4.0", + "urix": "0.1.0" + } + }, + "source-map-support": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.4.tgz", + "integrity": "sha512-PETSPG6BjY1AHs2t64vS2aqAgu6dMIMXJULWFBGbh2Gr8nVLbCFDo6i/RMMvviIQ2h1Z8+5gQhVKSn2je9nmdg==", + "requires": { + "source-map": "0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" + }, + "sparkles": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz", + "integrity": "sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM=" + }, + "spdy": { + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-3.4.7.tgz", + "integrity": "sha1-Qv9B7OXMD5mjpsKKq7c/XDsDrLw=", + "requires": { + "debug": "2.6.9", + "handle-thing": "1.2.5", + "http-deceiver": "1.2.7", + "safe-buffer": "5.1.1", + "select-hose": "2.0.0", + "spdy-transport": "2.1.0" + } + }, + "spdy-transport": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-2.1.0.tgz", + "integrity": "sha512-bpUeGpZcmZ692rrTiqf9/2EUakI6/kXX1Rpe0ib/DyOzbiexVfXkw6GnvI9hVGvIwVaUhkaBojjCZwLNRGQg1g==", + "requires": { + "debug": "2.6.9", + "detect-node": "2.0.3", + "hpack.js": "2.1.6", + "obuf": "1.1.2", + "readable-stream": "2.3.6", + "safe-buffer": "5.1.1", + "wbuf": "1.7.3" + } + }, + "split": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", + "requires": { + "through": "2.3.8" + } + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "requires": { + "extend-shallow": "3.0.2" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "requires": { + "define-property": "0.2.5", + "object-copy": "0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "0.1.6" + } + } + } + }, + "stream-combiner": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", + "requires": { + "duplexer": "0.1.1" + } + }, + "stream-transform": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/stream-transform/-/stream-transform-0.1.2.tgz", + "integrity": "sha1-fY5rTgOsR4F3j4x5UXUBv7B2Kp8=" + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "3.0.0" + } + } + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "superagent": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-1.8.5.tgz", + "integrity": "sha1-HA3cOvMOgOuE68BcshItqP6UC1U=", + "dev": true, + "requires": { + "component-emitter": "1.2.1", + "cookiejar": "2.0.6", + "debug": "2.6.9", + "extend": "3.0.0", + "form-data": "1.0.0-rc3", + "formidable": "1.0.17", + "methods": "1.1.2", + "mime": "1.3.4", + "qs": "2.3.3", + "readable-stream": "1.0.27-1", + "reduce-component": "1.0.1" + }, + "dependencies": { + "extend": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz", + "integrity": "sha1-WkdDU7nzNT3dgXbf03uRyDpG8dQ=", + "dev": true + }, + "formidable": { + "version": "1.0.17", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.0.17.tgz", + "integrity": "sha1-71SRSQ+UM7cF+qdyScmQKa40hVk=", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "mime": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", + "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM=", + "dev": true + }, + "qs": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz", + "integrity": "sha1-6eha2+ddoLvkyOBHaghikPhjtAQ=", + "dev": true + }, + "readable-stream": { + "version": "1.0.27-1", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.27-1.tgz", + "integrity": "sha1-a2eYPCA1fO/QfwFlABoW1xDZEHg=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "supertest": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-1.2.0.tgz", + "integrity": "sha1-hQp5X5Bo0vrxngF5n/CZYuDOQ74=", + "dev": true, + "requires": { + "methods": "1.1.2", + "superagent": "1.8.5" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + }, + "tailing-stream": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/tailing-stream/-/tailing-stream-0.2.0.tgz", + "integrity": "sha1-SRhHFZU2nZmI/FVzmBaMkagn7Pk=" + }, + "temp": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.3.tgz", + "integrity": "sha1-4Ma8TSa5AxJEEOT+2BEDAU38H1k=", + "dev": true, + "requires": { + "os-tmpdir": "1.0.2", + "rimraf": "2.2.8" + }, + "dependencies": { + "rimraf": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", + "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=", + "dev": true + } + } + }, + "term-size": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", + "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", + "requires": { + "execa": "0.7.0" + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "thinky": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/thinky/-/thinky-2.3.9.tgz", + "integrity": "sha512-4zp4wIQdwqyHP9CVoOa0/AV3GnKprHfOOVRj1KigtVcWi1DT7Eut52DVfX9nyI59399S+N6e3J5+4+y64ruf/g==", + "requires": { + "bluebird": "2.10.2", + "rethinkdbdash": "2.3.31", + "validator": "3.34.0" + }, + "dependencies": { + "bluebird": { + "version": "2.10.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.10.2.tgz", + "integrity": "sha1-AkpVFylTCIV/FPkfEQb8O1VfRGs=" + } + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "requires": { + "readable-stream": "2.3.6", + "xtend": "4.0.1" + } + }, + "tildify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.0.0.tgz", + "integrity": "sha1-KgIdtej73gqPi03zetqo+x05190=", + "requires": { + "user-home": "1.1.1" + } + }, + "time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=" + }, + "timed-out": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=" + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "requires": { + "kind-of": "3.2.2" + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "requires": { + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "regex-not": "1.0.2", + "safe-regex": "1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "requires": { + "is-number": "3.0.0", + "repeat-string": "1.6.1" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "3.2.2" + } + } + } + }, + "touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "requires": { + "nopt": "1.0.10" + } + }, + "ts-node": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-5.0.1.tgz", + "integrity": "sha512-XK7QmDcNHVmZkVtkiwNDWiERRHPyU8nBqZB1+iv2UhOG0q3RQ9HsZ2CMqISlFbxjrYFGfG2mX7bW4dAyxBVzUw==", + "requires": { + "arrify": "1.0.1", + "chalk": "2.4.0", + "diff": "3.5.0", + "make-error": "1.3.4", + "minimist": "1.2.0", + "mkdirp": "0.5.1", + "source-map-support": "0.5.4", + "yn": "2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.0.tgz", + "integrity": "sha512-Wr/w0f4o9LuE7K53cD0qmbAMM+2XNLzR29vFn5hqko4sxGlUsyy363NvmyGIyk5tpe9cjTr9SJYbysEyPkRnFw==", + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "tunnel-agent": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=" + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2" + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "typescript": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.8.3.tgz", + "integrity": "sha512-K7g15Bb6Ra4lKf7Iq2l/I5/En+hLIHmxWZGq3D4DIRNFxMNV6j2SHSvDOqs2tGd4UvD/fJvrwopzQXjLrT7Itw==", + "dev": true + }, + "uglify-js": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.6.4.tgz", + "integrity": "sha1-ZeovswWck5RpLxX+2HwrNsFrmt8=", + "requires": { + "async": "0.2.10", + "source-map": "0.5.7", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + }, + "dependencies": { + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "requires": { + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", + "window-size": "0.1.0" + } + } + } + }, + "uglify-save-license": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/uglify-save-license/-/uglify-save-license-0.4.1.tgz", + "integrity": "sha1-lXJsF8xv0XHDYX479NjYKqjEzOE=" + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=" + }, + "umzug": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/umzug/-/umzug-2.1.0.tgz", + "integrity": "sha512-BgT+ekpItEWaG+3JjLLj6yVTxw2wIH8Cr6JyKYIzukWAx9nzGhC6BGHb/IRMjpobMM1qtIrReATwLUjKpU2iOQ==", + "requires": { + "babel-runtime": "6.26.0", + "bluebird": "3.5.1", + "lodash": "4.17.5", + "resolve": "1.7.1" + }, + "dependencies": { + "lodash": { + "version": "4.17.5", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==" + } + } + }, + "undefsafe": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.2.tgz", + "integrity": "sha1-Il9rngM3Zj4Njnz9aG/Cg2zKznY=", + "requires": { + "debug": "2.6.9" + } + }, + "union-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "requires": { + "arr-union": "3.1.0", + "get-value": "2.0.6", + "is-extendable": "0.1.1", + "set-value": "0.4.3" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + }, + "set-value": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "to-object-path": "0.3.0" + } + } + } + }, + "unique-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", + "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", + "requires": { + "crypto-random-string": "1.0.0" + } + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "requires": { + "has-value": "0.3.1", + "isobject": "3.0.1" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "requires": { + "get-value": "2.0.6", + "has-values": "0.1.4", + "isobject": "2.1.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } + } + }, + "unzip-response": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz", + "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=" + }, + "upath": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.0.4.tgz", + "integrity": "sha512-d4SJySNBXDaQp+DPrziv3xGS6w3d2Xt69FijJr86zMPBy23JEloMCEOUBBzuN7xCtjLCnmB9tI/z7SBCahHBOw==" + }, + "update-notifier": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.5.0.tgz", + "integrity": "sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==", + "requires": { + "boxen": "1.3.0", + "chalk": "2.4.0", + "configstore": "3.1.2", + "import-lazy": "2.1.0", + "is-ci": "1.1.0", + "is-installed-globally": "0.1.0", + "is-npm": "1.0.0", + "latest-version": "3.1.0", + "semver-diff": "2.1.0", + "xdg-basedir": "3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.0.tgz", + "integrity": "sha512-Wr/w0f4o9LuE7K53cD0qmbAMM+2XNLzR29vFn5hqko4sxGlUsyy363NvmyGIyk5tpe9cjTr9SJYbysEyPkRnFw==", + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" + }, + "url-parse-lax": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", + "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "requires": { + "prepend-http": "1.0.4" + } + }, + "use": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.0.tgz", + "integrity": "sha512-6UJEQM/L+mzC3ZJNM56Q4DFGLX/evKGRg15UJHGB9X5j5Z3AFbgZvjUh2yq/UJUY4U5dh7Fal++XbNg1uzpRAw==", + "requires": { + "kind-of": "6.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + } + } + }, + "user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "uuid": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", + "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==" + }, + "v8flags": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", + "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", + "requires": { + "user-home": "1.1.1" + } + }, + "validator": { + "version": "3.34.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-3.34.0.tgz", + "integrity": "sha1-Z8tBgSH4+671l9lzdtYbDbWTfMY=" + }, + "vasync": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/vasync/-/vasync-1.6.3.tgz", + "integrity": "sha1-SmnXBSpH9M6FUD12Qd8cv0BDKpQ=", + "requires": { + "verror": "1.6.0" + }, + "dependencies": { + "verror": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.6.0.tgz", + "integrity": "sha1-fROyex+swuLakEBetepuW90lLqU=", + "requires": { + "extsprintf": "1.2.0" + } + } + } + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.2.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + } + } + }, + "vinyl": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", + "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", + "requires": { + "clone": "1.0.4", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + }, + "vinyl-sourcemaps-apply": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", + "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", + "requires": { + "source-map": "0.5.7" + } + }, + "wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "requires": { + "minimalistic-assert": "1.0.1" + } + }, + "which": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", + "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "requires": { + "isexe": "2.0.0" + } + }, + "widest-line": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.0.tgz", + "integrity": "sha1-AUKk6KJD+IgsAjOqDgKBqnYVInM=", + "requires": { + "string-width": "2.1.1" + } + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=" + }, + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=" + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "1.0.1" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "dev": true, + "requires": { + "mkdirp": "0.5.1" + } + }, + "write-file-atomic": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz", + "integrity": "sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA==", + "requires": { + "graceful-fs": "4.1.11", + "imurmurhash": "0.1.4", + "signal-exit": "3.0.2" + } + }, + "xdg-basedir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", + "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=" + }, + "xml-escape": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/xml-escape/-/xml-escape-1.0.0.tgz", + "integrity": "sha1-AJY9aXsq3wwYXE4E5zF0upsojrI=", + "dev": true + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + }, + "yaml-config-loader": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/yaml-config-loader/-/yaml-config-loader-2.0.1.tgz", + "integrity": "sha1-4e+F+dFqmriHBSRZ3YSkBkZqZJk=", + "requires": { + "async": "0.6.2", + "js-yaml": "3.11.0" + }, + "dependencies": { + "async": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.6.2.tgz", + "integrity": "sha1-Qf0DijgSwKi8GELs8IumPrA5K+8=" + } + } + }, + "yargs": { + "version": "3.32.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", + "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", + "requires": { + "camelcase": "2.1.1", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "os-locale": "1.4.0", + "string-width": "1.0.2", + "window-size": "0.1.4", + "y18n": "3.2.1" + }, + "dependencies": { + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "1.0.1" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "window-size": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", + "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=" + } + } + }, + "yn": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", + "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=" + } + } +} diff --git a/package.json b/package.json index 24efcde..d213776 100644 --- a/package.json +++ b/package.json @@ -6,37 +6,60 @@ "author": "", "license": "Proprietary", "devDependencies": { - "bl": "^1.0.0", + "@types/core-js": "^0.9.34", + "@types/mocha": "^2.2.48", + "@types/node": "^8.9.4", "co-mocha": "^1.1.2", "eslint": "^1.10.3", "eslint-config-probo": "^1.0.2", - "mocha": "^2.3.4", - "should": "^7.0.4", + "mocha": "^5.1.1", "supertest": "^1.1.0", - "temp": "^0.8.3" + "temp": "^0.8.3", + "typescript": "^2.7.2" }, "scripts": { - "test": "./node_modules/.bin/mocha -t 12000 --require should --recursive", - "watch": "./node_modules/.bin/mocha -w -t 12000 --require should --recursive", - "_test": "./node_modules/.bin/mocha -w --no-timeouts --require should --recursive", - "start": "./bin/loom", - "startdev": "nodemon ./bin/loom | ./node_modules/.bin/bunyan #-o short", - "spy": "curl --no-buffer localhost:3060/spy?color" + "clean": "rm -rf dist", + "test": "./node_modules/.bin/mocha -t 12000 --require ts-node/register --recursive test/*.ts --exit", + "watch": "./node_modules/.bin/mocha -w -t 12000 --require ts-node/register --recursive test/*.ts", + "_test": "./node_modules/.bin/mocha -w --no-timeouts --require ts-node/register --recursive test/*.ts", + "start": "node ./dist/bin/loom.js -c /etc/probo/loom.yaml", + "start2": "nodemon --require ./node_modules/ts-node/register/type-check ./bin/loom.ts -c /etc/probo/loom.yaml", + "startdev": "nodemon --inspect=0.0.0.0:9229 --require ts-node/register/type-check ./bin/loom.ts -c /etc/probo/loom.yaml | ./node_modules/.bin/bunyan #-o short", + "spy": "curl --no-buffer localhost:3060/spy?color", + "tsc": "$(npm bin)/tsc", + "data-migration": "nodemon --require ts-node/register/type-check ./dataMigration/0002-rethink-to-postgre.ts -c /etc/probo/loom.yaml | ./node_modules/.bin/bunyan", + "build": "npm run clean && tsc" }, "dependencies": { + "@types/bl": "^0.8.31", + "@types/chai": "^4.1.3", + "@types/knex": "^0.14.12", + "@types/lodash": "^4.14.104", + "@types/through2": "^2.0.33", + "@types/yargs": "^11.0.0", + "bl": "^1.2.1", "bun": "0.0.11", "bunyan": "^1.4.0", + "chai": "^4.1.2", "co": "^4.6.0", "colors": "^1.1.2", + "g": "^2.0.1", + "gulp-uglify": "^1.5.4", + "knex": "^0.13.0", + "knex-migrate": "^1.3.0", "lodash": "^3.10.1", "memorystream": "^0.3.1", "ms": "^0.7.1", + "nodemon": "^1.17.3", "passport": "^0.2.2", "passport-http-bearer": "^1.0.1", + "pg": "^6.2.2", "restify": "^4.0.0", "tailing-stream": "^0.2.0", "thinky": "^2.2.4", "through2": "^2.0.0", + "ts-node": "^5.0.0", + "uuid": "^3.2.1", "yaml-config-loader": "^2.0.1", "yargs": "^3.31.0" } diff --git a/test/__setup.js b/test/__setup.ts similarity index 60% rename from test/__setup.js rename to test/__setup.ts index 9e612cd..862772a 100644 --- a/test/__setup.js +++ b/test/__setup.ts @@ -1,9 +1,11 @@ -'use strict'; +"use strict"; // This file is name __setup so that it gets loaded first // and performs initialization for tests -require('co-mocha'); +require("co-mocha"); + +process.env.NODE_ENV = "test"; // effectivley silence the logging -var logger = (require('../lib/logger')).getLogger(); +let logger = require("../lib/logger").getLogger(); logger._level = Number.POSITIVE_INFINITY; diff --git a/test/auth.js b/test/auth.js deleted file mode 100644 index 9a04d8c..0000000 --- a/test/auth.js +++ /dev/null @@ -1,61 +0,0 @@ -'use strict'; - -var request = require('supertest'); - -var Server = require('../lib/api/server'); -var server = null; - -describe('auth', function() { - this.timeout(1000); - - before('start server', function(done) { - var testConf = { - tokens: ['tik', 'tok'], - server: { - host: 'localhost', - port: 3060, - }, - db: { - host: 'localhost', - port: 28015, - db: 'test', - logsTable: 'logs', - metaTable: 'meta', - }, - }; - var loom = new Server(testConf); - loom.listen(done); - // Get a reference to the restify server. - server = loom.server; - }); - - describe('all endpoints require auth', function() { - it('GET /spy', function(done) { - request(server) - .get('/spy') - .expect('Content-Type', /json/) - .expect(401, done); - }); - - it('GET /stream/id', function(done) { - request(server) - .get('/stream/id') - .expect('Content-Type', /json/) - .expect(401, done); - }); - - it('POST /stream/id', function(done) { - request(server) - .post('/stream/id') - .expect('Content-Type', /json/) - .expect(401, done); - }); - - it('POST /stream/', function(done) { - request(server) - .post('/stream') - .expect('Content-Type', /json/) - .expect(401, done); - }); - }); -}); diff --git a/test/auth.ts b/test/auth.ts new file mode 100644 index 0000000..54ab0b2 --- /dev/null +++ b/test/auth.ts @@ -0,0 +1,68 @@ +"use strict"; + +import "mocha"; +import "chai"; +import * as request from "supertest"; +import { Server } from "../lib/api/server"; +import * as bunyan from "bunyan"; +import "../typings/TConfig"; + +// Set debug level +process.env.NODE_ENV = "test"; + +let server = null; + +describe("auth", function() { + this.timeout(5000); + + before("start server", function(done) { + var testConf = { + tokens: ["tik", "tok"], + server: { + host: "localhost", + port: 3060 + }, + db: { + host: "localhost", + port: 28015, + db: "test", + logsTable: "logs", + metaTable: "meta" + } + }; + var loom = new Server(testConf); + loom.listen(done); + // Get a reference to the restify server. + server = loom.server; + }); + + describe("all endpoints require auth", function() { + it("GET /spy", function(done) { + request(server) + .get("/spy") + .expect("Content-Type", /json/) + .expect(401, done); + }); + + it("GET /stream/id", function(done) { + request(server) + .get("/stream/id") + .expect("Content-Type", /json/) + .expect(401, done); + }); + + it("POST /stream/id", function(done) { + request(server) + .post("/stream/id") + .expect("Content-Type", /json/) + .expect(401, done); + }); + + it("POST /stream/", function(done) { + request(server) + .post("/stream") + .expect("Content-Type", /json/) + .expect(401, done); + }); + }); +}); diff --git a/test/file_storage.js b/test/file_storage.js deleted file mode 100644 index 1f983da..0000000 --- a/test/file_storage.js +++ /dev/null @@ -1,240 +0,0 @@ -'use strict'; - -/* eslint guard-for-in: 0 */ - -var fs = require('fs'); -var zlib = require('zlib'); - -var _ = require('lodash'); -var bl = require('bl'); -var temp = require('temp').track(); -var FileSystemStorage = require('../lib/models').FileSystemStorage; - -var config = { - dataDir: temp.mkdirSync(), - // keep tail timeout low so that we don't time out the test - tailTimeout: 1000, - compress: false, -}; - -describe('FileSystemStorage', function() { - before(function* reset() { - // configure and reset DB - var config = { - db: process.env.DB_NAME || 'test', - }; - var rethink = require('../lib/rethink'); - rethink.connect(config); - yield [rethink.models.Logs.delete(), rethink.models.Meta.delete()]; - }); - - it('constructs an instance properly', function() { - var instance; - instance = new FileSystemStorage(); - instance.config.should.containEql({ - metaTable: 'meta', - dataDir: 'data', - }); - - var conf = {dataDir: 'custom_dir', metaTable: 'custom table'}; - instance = new FileSystemStorage(conf); - - // ensure config argument is not modified - conf.should.eql({dataDir: 'custom_dir', metaTable: 'custom table'}); - - instance.config.should.containEql({ - metaTable: 'custom table', - dataDir: 'custom_dir', - }); - }); - - it('generates file names properly', function() { - var instance = new FileSystemStorage(config); - - instance.makeFileName('stream-x-1').should.eql('stream-stream-x-1.log'); - instance.makeStreamFilePath('stream-x-2').should.eql(`${config.dataDir}/stream-stream-x-2.log`); - }); - - it('writes to a file', function(done) { - var instance = new FileSystemStorage(config); - - var writeStream = instance.createWriteStream('xyz'); - writeStream.write('line 1\n'); - writeStream.write('line 2\n'); - writeStream.end('this is the end\n'); - - var filePath = `${config.dataDir}/stream-xyz.log`; - writeStream.on('finish', () => { - fs.readFileSync(filePath).toString() - .should.eql(`line 1 -line 2 -this is the end -`); - - // make sure we properly detect that the stream ended - instance._isStreamFinished(filePath, (err, finished)=>{ - finished.should.eql(false); - - // now make the tailTimeout value really small so that the file looks modified - // after waiting for a bit - instance.config.tailTimeout = 10; - - setTimeout(()=>{ - instance._isStreamFinished(filePath, (err, finished, data)=>{ - finished.should.eql(true); - - done(); - }); - }, instance.config.tailTimeout + 50); - }); - }); - }); - - it('reads from a file (notail, reads to EOF)', function(done) { - var instance = new FileSystemStorage(config); - - var fileContents = `write test line 1 -write test line 2 -write test end -`; - - fs.writeFileSync(`${config.dataDir}/stream-abc.log`, fileContents); - - var reader = instance.createReadStream('abc', {notail: true}); - - reader.pipe(bl(function(err, data) { - if (err) return done(err); - data.toString().should.eql(fileContents); - })); - - reader.on('end', () => { - done(); - }); - }); - - it('reads from a file (default, tails current stream waiting for more data)', function(done) { - var instance = new FileSystemStorage(config); - - var fileContents = `write test line 1 -write test line 2 -write test end -`; - - fs.writeFileSync(`${config.dataDir}/stream-tail.log`, fileContents); - setTimeout(() => fs.appendFile(`${config.dataDir}/stream-tail.log`, 'new content'), 200); - - var reader = instance.createReadStream('tail'); - - var start = +new Date(); - - reader.pipe(bl(function(err, data) { - if (err) return done(err); - data.toString().should.eql(fileContents + 'new content'); - })); - - reader.on('end', () => { - var end = +new Date(); - (end - start).should.approximately(1000 + 200, 20); - - done(); - }); - }); - - it('reads from a file (default, old stream not waiting for new data)', function(done) { - var instance = new FileSystemStorage(config); - // reset tailTimeout to a small value to make file appear old - instance.config.tailTimeout = 50; - - var streamId = 'tail-old'; - - var fileContents = `write test line 1 -write test line 2 -write test end -`; - - fs.writeFileSync(`${config.dataDir}/stream-${streamId}.log`, fileContents); - - // wait a bit for the file mtime to age - setTimeout(() => { - var reader = instance.createReadStream(streamId); - - var start = +new Date(); - - reader.pipe(bl(function(err, data) { - if (err) return done(err); - data.toString().should.eql(fileContents); - })); - - reader.on('end', () => { - var end = +new Date(); - // make sure that read returned immediately for old file, not waiting for tailTimeout - (end - start).should.approximately(0, 20); - - done(); - }); - }, instance.config.tailTimeout + 10); - }); - - it('writes to/from a compressed file', function(done) { - var instance = new FileSystemStorage(_.assign({}, config, { - compress: true, - })); - - var writeStream = instance.createWriteStream('compressed'); - writeStream.write('line 1\n'); - writeStream.write('line 2\n'); - writeStream.end('this is the end\n'); - - var filePath = `${config.dataDir}/stream-compressed.log`; - writeStream.on('finish', () => { - // in a set timeout to give fs time to flush to disk - setTimeout(()=>{ - var content = fs.readFileSync(filePath); - - // correct contents for normal gzip stream: - // content.toString('base64').should.eql('H4sIAAAAAAAAA8vJzEtVMOTKAVFGXCUZmcUKQFSSkaqQmpfCBQAhH9pCHgAAAA=='); - - // correct contents for a SYNC_FLUSH gzip stream: - content.toString('base64').should.eql('H4sIAAAAAAAAA8rJzEtVMOQCAAAA///KAVFGXAAAAAD//yrJyCxWAKKSjFSF1LwULgAAAAD//wMAIR/aQh4AAAA='); - - zlib.gunzipSync(content).toString().should.eql(`line 1 -line 2 -this is the end -`); - - instance.createReadStream('compressed').pipe(bl(function(err, data) { - if (err) return done(err); - data.toString().should.eql(`line 1 -line 2 -this is the end -`); - - done(); - })); - }, 10); - }); - }); - - it('deletes files', function(done) { - var instance = new FileSystemStorage(config); - - fs.writeFileSync(`${config.dataDir}/stream-deleteme.log`, 'to be deleted'); - - instance.deleteStream('deleteme', function(err, renamed) { - if (err) done(err); - - // make sure orignal file exists but is renamed - (function() { - fs.statSync(`${config.dataDir}/stream-deleteme.log`); - }).should.throw(/ENOENT: no such file or directory/); - - // does not throw if exists - fs.statSync(renamed); - - renamed.should.match(new RegExp(`${config.dataDir}/deleted_[0-9]+_stream-deleteme.log`)); - - done(); - }); - }); - -}); diff --git a/test/file_storage.ts b/test/file_storage.ts new file mode 100644 index 0000000..5cd295b --- /dev/null +++ b/test/file_storage.ts @@ -0,0 +1,284 @@ +"use strict"; + +/* eslint guard-for-in: 0 */ +import * as fs from "fs"; +import * as zlib from "zlib"; +import * as _ from "lodash"; +import { assert } from "chai"; // Using Assert style +import { expect } from "chai"; // Using Expect style +import { should } from "chai"; // Using Should style +import "mocha"; +import * as track from "temp"; +import { FileSystemStorage } from "../lib/models/postgre_stream_backend_filesystem"; +import { Database } from "../lib/knex"; + +should(); + +// Set debug level +process.env.NODE_ENV = "test"; + +const bl = require("bl"); + +let temp = track.track(); + +const config = { + dataDir: temp.mkdirSync(), + db: process.env.DB_NAME || "test", + // keep tail timeout low so that we don't time out the test + tailTimeout: 1000, + compress: false +}; + +describe("FileSystemStorage", function() { + before(function* reset() { + // configure and reset DB + let config = { + db: process.env.DB_NAME || "test", + tables: { + logsTable: "logs", + metaTable: "meta" + } + }; + yield [Database.knex(config.tables.metaTable).truncate()]; + }); + + it("constructs an instance properly", function() { + let instance; + instance = new FileSystemStorage(); + instance.config.should.contain({ + metaTable: "meta", + dataDir: "data" + }); + + // there is no reason to do this test in typescript + /* + let conf = { dataDir: "custom_dir", metaTable: "custom table" }; + instance = new FileSystemStorage(conf); + + // ensure config argument is not modified + // This never happend + //conf.should.eql({ dataDir: 'custom_dir', metaTable: 'custom table' }); + + instance.config.should.containEql({ + metaTable: "custom table", + dataDir: "custom_dir" + }); + */ + }); + + it("generates file names properly", function() { + var instance = new FileSystemStorage(config); + + instance.makeFileName("stream-x-1").should.eql("stream-stream-x-1.log"); + instance + .makeStreamFilePath("stream-x-2") + .should.eql(`${config.dataDir}/stream-stream-x-2.log`); + }); + + it("writes to a file", function(done) { + var instance = new FileSystemStorage(config); + + var writeStream = instance.createWriteStream("xyz"); + writeStream.write("line 1\n"); + writeStream.write("line 2\n"); + writeStream.end("this is the end\n"); + + var filePath = `${config.dataDir}/stream-xyz.log`; + writeStream.on("finish", () => { + fs.readFileSync(filePath).toString().should.eql(`line 1 +line 2 +this is the end +`); + + // make sure we properly detect that the stream ended + instance._isStreamFinished(filePath, (err, finished) => { + finished.should.eql(false); + + // now make the tailTimeout value really small so that the file looks modified + // after waiting for a bit + instance.config.tailTimeout = 10; + + setTimeout(() => { + instance._isStreamFinished(filePath, (err, finished, data) => { + finished.should.eql(true); + + done(); + }); + }, instance.config.tailTimeout + 50); + }); + }); + }); + + it("reads from a file (notail, reads to EOF)", function(done) { + var instance = new FileSystemStorage(config); + + var fileContents = `write test line 1 +write test line 2 +write test end +`; + + fs.writeFileSync(`${config.dataDir}/stream-abc.log`, fileContents); + + var reader = instance.createReadStream("abc", { notail: true }); + + reader.pipe( + bl(function(err, data) { + if (err) return done(err); + data.toString().should.eql(fileContents); + }) + ); + + reader.on("end", () => { + done(); + }); + }); + + it("reads from a file (default, tails current stream waiting for more data)", function(done) { + var instance = new FileSystemStorage(config); + + var fileContents = `write test line 1 +write test line 2 +write test end +`; + + fs.writeFileSync(`${config.dataDir}/stream-tail.log`, fileContents); + setTimeout( + () => + fs.appendFile( + `${config.dataDir}/stream-tail.log`, + "new content", + err => { + if (err) throw err; + } + ), + 200 + ); + + var reader = instance.createReadStream("tail"); + + var start = +new Date(); + + reader.pipe( + bl(function(err, data) { + if (err) return done(err); + data.toString().should.eql(fileContents + "new content"); + }) + ); + + reader.on("end", () => { + var end = +new Date(); + (end - start).should.approximately(1000 + 200, 20); + + done(); + }); + }); + + it("reads from a file (default, old stream not waiting for new data)", function(done) { + var instance = new FileSystemStorage(config); + // reset tailTimeout to a small value to make file appear old + instance.config.tailTimeout = 50; + + var streamId = "tail-old"; + + var fileContents = `write test line 1 +write test line 2 +write test end +`; + + fs.writeFileSync(`${config.dataDir}/stream-${streamId}.log`, fileContents); + + // wait a bit for the file mtime to age + setTimeout(() => { + var reader = instance.createReadStream(streamId); + + var start = +new Date(); + + reader.pipe( + bl(function(err, data) { + if (err) return done(err); + data.toString().should.eql(fileContents); + }) + ); + + reader.on("end", () => { + var end = +new Date(); + // make sure that read returned immediately for old file, not waiting for tailTimeout + (end - start).should.approximately(0, 20); + + done(); + }); + }, instance.config.tailTimeout + 10); + }); + + it("writes to/from a compressed file", function(done) { + var instance = new FileSystemStorage( + _.assign({}, config, { + compress: true + }) + ); + + var writeStream = instance.createWriteStream("compressed"); + writeStream.write("line 1\n"); + writeStream.write("line 2\n"); + writeStream.end("this is the end\n"); + + var filePath = `${config.dataDir}/stream-compressed.log`; + writeStream.on("finish", () => { + // in a set timeout to give fs time to flush to disk + setTimeout(() => { + var content = fs.readFileSync(filePath); + + // correct contents for normal gzip stream: + // content.toString('base64').should.eql('H4sIAAAAAAAAA8vJzEtVMOTKAVFGXCUZmcUKQFSSkaqQmpfCBQAhH9pCHgAAAA=='); + + // correct contents for a SYNC_FLUSH gzip stream: + content + .toString("base64") + .should.eql( + "H4sIAAAAAAAAA8rJzEtVMOQCAAAA///KAVFGXAAAAAD//yrJyCxWAKKSjFSF1LwULgAAAAD//wMAIR/aQh4AAAA=" + ); + + zlib.gunzipSync(content).toString().should.eql(`line 1 +line 2 +this is the end +`); + + instance.createReadStream("compressed").pipe( + bl(function(err, data) { + if (err) return done(err); + data.toString().should.eql(`line 1 +line 2 +this is the end +`); + + done(); + }) + ); + }, 10); + }); + }); + + it("deletes files", function(done) { + var instance = new FileSystemStorage(config); + + fs.writeFileSync(`${config.dataDir}/stream-deleteme.log`, "to be deleted"); + + instance.deleteStream("deleteme", function(err, renamed) { + if (err) done(err); + + // make sure orignal file exists but is renamed + (function() { + fs.statSync(`${config.dataDir}/stream-deleteme.log`); + }.should.throw(/ENOENT: no such file or directory/)); + + // does not throw if exists + fs.statSync(renamed); + + renamed.should.match( + new RegExp(`${config.dataDir}/deleted_[0-9]+_stream-deleteme.log`) + ); + + done(); + }); + }); +}); diff --git a/test/models.js b/test/models.js deleted file mode 100644 index db4384a..0000000 --- a/test/models.js +++ /dev/null @@ -1,169 +0,0 @@ -'use strict'; - -/* eslint guard-for-in: 0 */ - -var through = require('through2'); -var bl = require('bl'); -var temp = require('temp').track(); - -var ArrayStreamStorage = require('../lib/models').ArrayStreamStorage; -var RethinkStorage = require('../lib/models').RethinkStorage; -var FileSystemStorage = require('../lib/models').FileSystemStorage; - -function isDescendant(B, A) { - return B.prototype instanceof A || B === A; -} - -function testStorage(Storage, storageConfig) { - function read(streamid, storage) { - return (storage || new Storage(storageConfig)).createReadStream(streamid); - } - - function write(streamid, storage) { - return (storage || new Storage(storageConfig)).createWriteStream(streamid); - } - - describe('Storage: ' + Storage.name, function() { - before(function* reset() { - if (isDescendant(Storage, RethinkStorage)) { - // configure and reset DB - var config = { - db: process.env.DB_NAME || 'test', - }; - var rethink = require('../lib/rethink'); - rethink.connect(config); - yield [rethink.models.Logs.delete(), rethink.models.Meta.delete()]; - } - }); - - describe('storage basics', function() { - var streams = { - 'stream 1': {some: 'data'}, - 'stream 2': {more: 'data'}, - }; - - it('creates streams', function* () { - var storage = new Storage(storageConfig); - for (var streamid in streams) { - yield storage.saveStream(streamid, streams[streamid]); - } - }); - - it('loads streams', function* () { - var storage = new Storage(storageConfig); - var meta = yield storage.loadStream(Object.keys(streams)[0]); - meta.should.eql({some: 'data'}); - }); - - it('stream 1 writes then reads', function(done) { - var storage = new Storage(storageConfig); - var list = bl(); - list.append('some data'); - list.append('more data'); - - var streamid = 'stream 1'; - var writer = write(streamid, storage); - list.duplicate().pipe(writer); - - writer.on('finish', function() { - var reader = read(streamid, storage); - reader.pipe(bl(function(err, data) { - if (err) return done(err); - data.should.eql(list.slice(), 'reader on same storage as writer works'); - })); - - reader.on('end', function() { - read(streamid).pipe(bl(function(err, data) { - if (err) return done(err); - data.should.eql(list.slice(), 'reader on different storage than writer works'); - - done(); - })); - }); - }); - }); - - it('stream 2 writes and reads async', function(done) { - var expected; - var num = 10; - var interval = 100; - var producer = makeProducer(num, interval, function finishedProducing(data) { - expected = data; - }); - - producer.pipe(write('stream 2')); - - var immediateFinished = false; - var delayedFinished = false; - - // reader that starts reading immediately (full stream mode) - read('stream 2').pipe(bl(function(err, data) { - // console.log("expected:", expected.toString()) - // console.log("found :", data.toString()) - - data.toString().should.eql(expected.toString()); - immediateFinished = true; - - if (delayedFinished && immediateFinished) { - done(); - } - })); - - // reader that starts listenting half way (partial stream mode) - // gets existing data, then listens for changes - setTimeout(function() { - read('stream 2').pipe(bl(function(err, data) { - // console.log("expected:", expected.toString()) - // console.log("found :", data.toString()) - - data.toString().should.eql(expected.toString()); - - delayedFinished = true; - - if (delayedFinished && immediateFinished) { - done(); - } - })); - }, num * interval / 2); - }); - }); - }); -} - -testStorage(ArrayStreamStorage); -testStorage(RethinkStorage); -testStorage(FileSystemStorage, { - dataDir: temp.mkdirSync(), - // keep tail timeout low so that we don't time out the test - tailTimeout: 1000, - compress: false, -}); - -function makeProducer(numpushes, interval, finished) { - numpushes = numpushes || 2; - interval = interval || 100; - - var producer = through(); - - var data = []; - - var pushed = 0; - var _i = setInterval(function() { - if (pushed >= numpushes) { - clearInterval(_i); - producer.end(); - } - else { - var d = new Buffer('data ' + ++pushed); - data.push(d); - producer.write(d); - } - }, interval); - - if (finished) { - producer.on('finish', function() { - if (finished) { finished(Buffer.concat(data)); } - }); - } - return producer; -} diff --git a/test/models.ts b/test/models.ts new file mode 100644 index 0000000..601ded4 --- /dev/null +++ b/test/models.ts @@ -0,0 +1,206 @@ +"use strict"; + +/* eslint guard-for-in: 0 */ +import "mocha"; +import { assert } from "chai"; // Using Assert style +import { expect } from "chai"; // Using Expect style +import { should } from "chai"; // Using Should style +import * as through from "through2"; +import * as track from "temp"; +import { PostgreStorage } from "../lib/models/postgre_storage"; +import { FileSystemStorage } from "../lib/models/postgre_stream_backend_filesystem"; +import { Database } from "../lib/knex"; + +should(); + +// Set debug level +process.env.NODE_ENV = "test"; + +const bl = require("bl"); +const temp = track.track(); +const tables = { + logsTable: "logs", + metaTable: "meta" +}; + +function isDescendant(B, A) { + return B.prototype instanceof A || B === A; +} + +function testStorage(Storage, storageConfig) { + function read(streamid, storage?: any) { + return (storage || new Storage(storageConfig)).createReadStream(streamid); + } + + function write(streamid, storage?: any) { + return (storage || new Storage(storageConfig)).createWriteStream(streamid); + } + + describe("Storage: " + Storage.name, function() { + before(function* reset() { + if (isDescendant(Storage, PostgreStorage)) { + // configure and reset DB + const config = { + db: process.env.DB_NAME || "test" + }; + + yield [Database.knex(tables.metaTable).truncate()]; + } + }); + + describe("storage basics", function() { + var streams = { + "build-31aced17-67da-45fe-b447-f326f39f8a1b-task-58aa706b20c00000": { + "metadata": { + "buildId":"31aced17-67da-45fe-b447-f326f39f8a1b", + "task":{"id": "58aa706b20c00000","name": "AssetDownloader task","plugin": "AssetDownloader"}} + }, + "build-31aced17-67da-45fe-b447-f326f39f8a1b-task-58aa706b21400000": { + "metadata": { + "buildId":"31aced17-67da-45fe-b447-f326f39f8a1b", + "task":{"id": "58aa706b21400000","name": "Probo site setup","plugin": "LAMPApp"}} + }, + }; + + it("creates streams", function*() { + var storage = new Storage(storageConfig); + for (var streamid in streams) { + yield storage.saveStream(streamid, streams[streamid]); + } + }); + + it("loads streams", function*() { + var storage = new Storage(storageConfig); + var meta = yield storage.loadStream(Object.keys(streams)[0]); + meta.metadata[0].should.eql(streams[Object.keys(streams)[0]].metadata); + }); + + it("stream 1 writes then reads", function(done) { + var storage = new Storage(storageConfig); + var list = bl(); + list.append("some data"); + list.append("more data"); + + var streamid = "stream 1"; + var writer = write(streamid, storage); + list.duplicate().pipe(writer); + + writer.on("finish", function() { + var reader = read(streamid, storage); + reader.pipe( + bl(function(err, data) { + if (err) return done(err); + data.should.eql( + list.slice(), + "reader on same storage as writer works" + ); + }) + ); + + reader.on("end", function() { + read(streamid).pipe( + bl(function(err, data) { + if (err) return done(err); + data.should.eql( + list.slice(), + "reader on different storage than writer works" + ); + + done(); + }) + ); + }); + }); + }); + + it("stream 2 writes and reads async", function(done) { + var expected; + var num = 10; + var interval = 100; + var producer = makeProducer(num, interval, function finishedProducing( + data + ) { + expected = data; + }); + + producer.pipe(write("stream 2")); + + var immediateFinished = false; + var delayedFinished = false; + + // reader that starts reading immediately (full stream mode) + read("stream 2").pipe( + bl(function(err, data) { + // console.log("expected:", expected.toString()) + // console.log("found :", data.toString()) + + data.toString().should.eql(expected.toString()); + immediateFinished = true; + + if (delayedFinished && immediateFinished) { + done(); + } + }) + ); + + // reader that starts listenting half way (partial stream mode) + // gets existing data, then listens for changes + setTimeout(function() { + read("stream 2").pipe( + bl(function(err, data) { + // console.log("expected:", expected.toString()) + // console.log("found :", data.toString()) + + data.toString().should.eql(expected.toString()); + + delayedFinished = true; + + if (delayedFinished && immediateFinished) { + done(); + } + }) + ); + }, num * interval / 2); + }); + }); + }); +} + +//testStorage(ArrayStreamStorage); +//testStorage(PostgreStorage); +testStorage(FileSystemStorage, { + dataDir: temp.mkdirSync(), + // keep tail timeout low so that we don't time out the test + tailTimeout: 1000, + compress: false +}); + +function makeProducer(numpushes, interval, finished) { + numpushes = numpushes || 2; + interval = interval || 100; + + var producer = through(); + + var data = []; + + var pushed = 0; + var _i = setInterval(function() { + if (pushed >= numpushes) { + clearInterval(_i); + producer.end(); + } else { + var d = new Buffer("data " + ++pushed); + data.push(d); + producer.write(d); + } + }, interval); + + if (finished) { + producer.on("finish", function() { + if (finished) { + finished(Buffer.concat(data)); + } + }); + } + return producer; +} diff --git a/test/server.js b/test/server.js deleted file mode 100644 index 13d8496..0000000 --- a/test/server.js +++ /dev/null @@ -1,159 +0,0 @@ -'use strict'; - -var http = require('http'); -var url = require('url'); - -// var should = require('should') - -var Server = require('../lib/api/server'); -var rethink = require('../lib/rethink'); - -var numChunks = 4; -var consumerWait = 2000; -var server = null; - -var temp = require('temp').track(); - -var testConf = { - tokens: ['tik', 'tok'], - server: { - host: 'localhost', - port: 3060, - }, - db: { - host: 'localhost', - port: 28015, - db: 'test', - }, - storage: { - logsTable: 'logs', - metaTable: 'meta', - dataDir: temp.mkdirSync(), - tailTimeout: '1.5s', - compress: false, - - // compression buffers small chunks of data, which doesn't update mtime - // so to test with compression on, up time tailTimeout: - // compress: true, - // tailTimeout: '4s', - }, -}; - -function start(cb) { - var loom = new Server(testConf); - // Get a reference to the restify server. - server = loom.server; - loom.listen(0, '127.0.0.1', function() { - server.log.info('%s listening at %s', server.name, server.url); - return cb && cb(); - }); -} - -describe('Server:', function() { - before('clear database', function* () { - rethink.connect(testConf.db); - yield [rethink.models.Logs.delete(), rethink.models.Meta.delete()]; - }); - - before('server starts', function(done) { - start(done); - }); - - describe('producer', function() { - var streamId; - - function startConsumer(id, cb) { - console.log('starting consumer'); - - var data = []; - - var consumerHandler = function(res) { - console.log('CONSUMER STATUS: ' + res.statusCode); - console.log('CONSUMER HEADERS: ' + JSON.stringify(res.headers)); - res.setEncoding('utf8'); - res.on('data', function(chunk) { - console.log('CONSUMER BODY: ' + chunk); - data.push(chunk); - }); - res.on('end', function() { - console.log('CONSUMER has read the full stream'); - - data.join('').should.eql([ - 'chunks written 4', - 'chunks written 3', - 'chunks written 2', - 'chunks written 1', - ].join('')); - - setTimeout(cb, 1000); - }); - res.on('error', function(err) { - console.log('CONSUMER error', err); - cb(err); - }); - }; - - var consumer = http.request({ - hostname: 'localhost', - port: url.parse(server.url).port, - path: '/stream/' + id, - headers: { - authorization: 'bearer tik', - }, - }, consumerHandler); - consumer.end(); - } - - it('feeds data', function(done) { - var producerHandler = function(res) { - console.log('PRODUCER STATUS: ' + res.statusCode); - console.log('PRODUCER HEADERS: ' + JSON.stringify(res.headers)); - res.setEncoding('utf8'); - res.on('data', function(chunk) { - console.log('PRODUCER BODY: ' + chunk); - }); - // res.on("end", done) - - // start the consumer for our stream id - streamId = res.headers['x-stream-id']; - setTimeout(function() { - startConsumer(streamId, done); - }, consumerWait); - - console.log(` -curl -vi --no-buffer http://:::${server.address().port}/stream/${streamId} -`); - }; - - var producer = http.request({ - hostname: 'localhost', - port: url.parse(server.url).port, - method: 'post', - path: '/stream', - headers: { - 'authorization': 'bearer tik', - 'connection': 'keep-alive', - 'x-stream-metadata': JSON.stringify({test_stream: true}), - }, - }, producerHandler); - - // stream some data - var chunks = numChunks; - var i = setInterval(function() { - if (chunks > 0) { - producer.write('chunks written ' + chunks); - console.log('producer sending data', chunks); - chunks--; - } - else { - clearInterval(i); - producer.end(); - } - }, 1000); - }); - - it('has complete data', function(done) { - startConsumer(streamId, done); - }); - }); -}); diff --git a/test/server.ts b/test/server.ts new file mode 100644 index 0000000..547eb3d --- /dev/null +++ b/test/server.ts @@ -0,0 +1,181 @@ +"use strict"; + +import * as http from "http"; +import * as url from "url"; +import { assert } from "chai"; // Using Assert style +import { expect } from "chai"; // Using Expect style +import { should } from "chai"; // Using Should style +import { Server } from "../lib/api/server"; +import * as track from "temp"; +import { exists } from "fs"; +import { Database } from "../lib/knex"; + +should(); + +// Set debug level +process.env.NODE_ENV = "test"; + +const numChunks = 4; +const consumerWait = 2000; +let server = null; + +const temp = track.track(); + +var testConf = { + tokens: ["tik", "tok"], + server: { + host: "localhost", + port: 3060 + }, + db: { + host: "localhost", + port: 28015, + db: "test" + }, + storage: { + logsTable: "logs", + metaTable: "meta", + dataDir: temp.mkdirSync(), + tailTimeout: "1.5s", + compress: false + + // compression buffers small chunks of data, which doesn't update mtime + // so to test with compression on, up time tailTimeout: + // compress: true, + // tailTimeout: '4s', + } +}; + +function start(cb) { + var loom = new Server(testConf); + // Get a reference to the restify server. + server = loom.server; + loom.listen(0, "127.0.0.1", function() { + server.log.info("%s listening at %s", server.name, server.url); + return cb && cb(); + }); +} + +describe("Server:", function() { + before("clear database", function*() { + yield [Database.knex(testConf.storage.metaTable).truncate()]; + }); + + before("server starts", function(done) { + start(done); + }); + + describe("producer", function() { + var streamId; + + function startConsumer(id, cb) { + console.log("starting consumer"); + + var data = []; + + var consumerHandler = function(res) { + console.log("CONSUMER STATUS: " + res.statusCode); + console.log("CONSUMER HEADERS: " + JSON.stringify(res.headers)); + res.setEncoding("utf8"); + res.on("data", function(chunk) { + console.log("CONSUMER BODY: " + chunk); + data.push(chunk); + }); + res.on("end", function() { + console.log("CONSUMER has read the full stream"); + + data + .join("") + .should.eql( + [ + "chunks written 4", + "chunks written 3", + "chunks written 2", + "chunks written 1" + ].join("") + ); + + setTimeout(cb, 1000); + }); + res.on("error", function(err) { + console.log("CONSUMER error", err); + cb(err); + }); + }; + + var consumer = http.request( + { + hostname: "localhost", + port: url.parse(server.url).port, + path: "/stream/" + id, + headers: { + authorization: "bearer tik" + } + }, + consumerHandler + ); + consumer.end(); + } + + it("feeds data", function(done) { + var producerHandler = function(res) { + console.log("PRODUCER STATUS: " + res.statusCode); + console.log("PRODUCER HEADERS: " + JSON.stringify(res.headers)); + res.setEncoding("utf8"); + res.on("data", function(chunk) { + console.log("PRODUCER BODY: " + chunk); + }); + // res.on("end", done) + + // start the consumer for our stream id + streamId = res.headers["x-stream-id"]; + setTimeout(function() { + startConsumer(streamId, done); + }, consumerWait); + + console.log(` +curl -vi --no-buffer http://:::${server.address().port}/stream/${streamId} +`); + }; + + var producer = http.request( + { + hostname: "localhost", + port: url.parse(server.url).port, + method: "post", + path: "/stream", + headers: { + authorization: "bearer tik", + connection: "keep-alive", + "x-stream-metadata": JSON.stringify({ + buildId: "31aced17-67da-45fe-b447-f326f39f8a1b", + task: { + id: "58aa706b20c00000", + name: "AssetDownloader task", + plugin: "AssetDownloader" + } + }) + } + }, + producerHandler + ); + + // stream some data + var chunks = numChunks; + var i = setInterval(function() { + if (chunks > 0) { + producer.write("chunks written " + chunks); + console.log("producer sending data", chunks); + chunks--; + } else { + clearInterval(i); + producer.end(); + } + }, 1000); + }); + + it("has complete data", function(done) { + startConsumer(streamId, done); + }); + }); +}); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..09361a7 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "module": "commonjs", + "noImplicitAny": false, + "removeComments": true, + "preserveConstEnums": true, + "sourceMap": true, + "target": "es6", + "outDir": "./dist" + }, + "exclude": [ + "node_modules" + ] +} \ No newline at end of file diff --git a/typings/TConfig.ts b/typings/TConfig.ts new file mode 100644 index 0000000..21f012e --- /dev/null +++ b/typings/TConfig.ts @@ -0,0 +1,17 @@ +type TConfig = { + tokens: string[]; + server: { + host: string; + port: number; + }; + db: { + host?: string; + port?: number; + db: string; + metaTable?: string; + logsTable?: string; + dataDir?: string; + tailTimeout?: number | string; + compress?: boolean; + }; +};