瀏覽代碼

CLI: Added directory obfuscation

sanex3339 7 年之前
父節點
當前提交
905132d3e3

+ 1 - 0
CHANGELOG.md

@@ -4,6 +4,7 @@ v0.12.0
 ---
 * Added ability to disable and enable obfuscation for specific parts of the code by adding conditional comments. 
 * Added obfuscation of `es2015` class names.
+* CLI: added directory obfuscation.
 
 v0.11.2
 ---

+ 14 - 2
README.md

@@ -182,10 +182,13 @@ Method takes two parameters, `sourceCode` and `options` – the source code and
 For available options see [options](#options).
 
 ## CLI usage
+
+#### Obfuscate single file
+
 Usage:
 ```sh
-javascript-obfuscator in.js [options]
-javascript-obfuscator in.js --output out.js [options]
+javascript-obfuscator input_file_name.js [options]
+javascript-obfuscator input_file_name.js --output output_file_name.js [options]
 ```
 
 If the destination path is not specified with the `--output` option, obfuscated code will saved into the input file directory with name like `INPUT_FILE_NAME-obfuscated.js`
@@ -201,6 +204,15 @@ javascript-obfuscator samples/sample.js --output output/output.js --compact true
 
 See [CLI options](#cli-options).
 
+#### Obfuscate directory
+
+Usage:
+```sh
+javascript-obfuscator input_directory_name [options]
+```
+
+Obfuscated code always will saved into the input directory under `INPUT_FILE_NAME-obfuscated.js` name.
+
 ## Conditional comments
 You can disable and enable obfuscation for specific parts of the code by adding following comments: 
 * disable: `// javascript-obfuscator:disable` or `/* javascript-obfuscator:disable */`;

文件差異過大導致無法顯示
+ 0 - 0
dist/index.js


+ 10 - 10
package.json

@@ -1,6 +1,6 @@
 {
   "name": "javascript-obfuscator",
-  "version": "0.12.0-dev.1",
+  "version": "0.12.0-dev.2",
   "description": "JavaScript obfuscator",
   "keywords": [
     "obfuscator",
@@ -32,7 +32,7 @@
     "mkdirp": "0.5.1",
     "opencollective": "1.0.3",
     "reflect-metadata": "0.1.10",
-    "source-map-support": "0.4.18",
+    "source-map-support": "0.5.0",
     "string-template": "1.0.0",
     "tslib": "1.7.1"
   },
@@ -40,16 +40,16 @@
     "@types/chai": "4.0.4",
     "@types/chalk": "0.4.31",
     "@types/chance": "0.7.35",
-    "@types/commander": "2.9.2",
+    "@types/commander": "2.11.0",
     "@types/escodegen": "0.0.6",
-    "@types/esprima": "4.0.0",
+    "@types/esprima": "4.0.1",
     "@types/estraverse": "0.0.6",
     "@types/estree": "0.0.37",
     "@types/md5": "2.1.32",
     "@types/mkdirp": "0.5.1",
     "@types/mocha": "2.2.43",
-    "@types/node": "8.0.28",
-    "@types/sinon": "2.3.4",
+    "@types/node": "8.0.32",
+    "@types/sinon": "2.3.5",
     "@types/string-template": "1.0.2",
     "@types/webpack-env": "1.13.1",
     "awesome-typescript-loader": "3.2.3",
@@ -58,17 +58,17 @@
     "babel-plugin-array-includes": "2.0.3",
     "babel-preset-es2015": "6.24.1",
     "chai": "4.1.2",
-    "coveralls": "2.13.1",
+    "coveralls": "3.0.0",
     "istanbul": "1.1.0-alpha.1",
-    "mocha": "3.5.3",
+    "mocha": "4.0.1",
     "pre-commit": "1.2.2",
-    "sinon": "3.2.1",
+    "sinon": "4.0.1",
     "ts-node": "3.3.0",
     "tslint": "5.7.0",
     "tslint-eslint-rules": "4.1.1",
     "tslint-language-service": "^0.9.6",
     "tslint-webpack-plugin": "1.0.0",
-    "typescript": "2.5.2",
+    "typescript": "2.5.3",
     "webpack": "3.6.0",
     "webpack-node-externals": "1.6.0"
   },

+ 69 - 41
src/cli/JavaScriptObfuscatorCLI.ts

@@ -4,7 +4,9 @@ import * as path from 'path';
 import { TInputCLIOptions } from '../types/options/TInputCLIOptions';
 import { TInputOptions } from '../types/options/TInputOptions';
 import { TObject } from '../types/TObject';
+import { TSourceCodeData } from '../types/cli/TSourceCodeData';
 
+import { IFileData } from '../interfaces/cli/IFileData';
 import { IInitializable } from '../interfaces/IInitializable';
 import { IObfuscationResult } from '../interfaces/IObfuscationResult';
 
@@ -19,6 +21,7 @@ import { StringArrayEncodingSanitizer } from './sanitizers/StringArrayEncodingSa
 
 import { CLIUtils } from './utils/CLIUtils';
 import { JavaScriptObfuscator } from '../JavaScriptObfuscatorFacade';
+import { SourceCodeReader } from './utils/SourceCodeReader';
 
 export class JavaScriptObfuscatorCLI implements IInitializable {
     /**
@@ -49,12 +52,6 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
     @initializable()
     private inputPath: string;
 
-    /**
-     * @type {string}
-     */
-    @initializable()
-    private sourceCode: string = '';
-
     /**
      * @param {string[]} argv
      */
@@ -81,6 +78,50 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
         return filteredOptions;
     }
 
+    /**
+     * @param {string} sourceCode
+     * @param {string} outputCodePath
+     * @param {TInputOptions} options
+     */
+    private static processSourceCodeWithoutSourceMap (
+        sourceCode: string,
+        outputCodePath: string,
+        options: TInputOptions
+    ): void {
+        const obfuscatedCode: string = JavaScriptObfuscator.obfuscate(sourceCode, options).getObfuscatedCode();
+
+        CLIUtils.writeFile(outputCodePath, obfuscatedCode);
+    }
+
+    /**
+     * @param {string} sourceCode
+     * @param {string} outputCodePath
+     * @param {TInputOptions} options
+     */
+    private static processSourceCodeWithSourceMap (
+        sourceCode: string,
+        outputCodePath: string,
+        options: TInputOptions
+    ): void {
+        const outputSourceMapPath: string = CLIUtils.getOutputSourceMapPath(
+            outputCodePath,
+            options.sourceMapFileName || ''
+        );
+
+        options = {
+            ...options,
+            sourceMapFileName: path.basename(outputSourceMapPath)
+        };
+
+        const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(sourceCode, options);
+
+        CLIUtils.writeFile(outputCodePath, obfuscationResult.getObfuscatedCode());
+
+        if (options.sourceMapMode === 'separate' && obfuscationResult.getSourceMap()) {
+            CLIUtils.writeFile(outputSourceMapPath, obfuscationResult.getSourceMap());
+        }
+    }
+
     public initialize (): void {
         this.inputPath = this.arguments[0] || '';
         this.commands = <commander.CommanderStatic>(new commander.Command());
@@ -98,8 +139,9 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
             return this.commands.outputHelp();
         }
 
-        this.sourceCode = CLIUtils.readSourceCode(this.inputPath);
-        this.processSourceCode();
+        const sourceCodeData: TSourceCodeData = SourceCodeReader.readSourceCode(this.inputPath);
+
+        this.processSourceCodeData(sourceCodeData);
     }
 
     /**
@@ -259,48 +301,34 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
         });
     }
 
-    private processSourceCode (): void {
-        const options: TInputOptions = this.buildOptions();
-        const outputCodePath: string = CLIUtils.getOutputCodePath(this.inputCLIOptions.output, this.inputPath);
-
-        if (options.sourceMap) {
-            this.processSourceCodeWithSourceMap(outputCodePath, options);
-        } else {
-            this.processSourceCodeWithoutSourceMap(outputCodePath, options);
-        }
-    }
-
     /**
-     * @param {string} outputCodePath
-     * @param {TInputOptions} options
+     * @param {TSourceCodeData} sourceCodeData
      */
-    private processSourceCodeWithoutSourceMap (outputCodePath: string, options: TInputOptions): void {
-        const obfuscatedCode: string = JavaScriptObfuscator.obfuscate(this.sourceCode, options).getObfuscatedCode();
+    private processSourceCodeData (sourceCodeData: TSourceCodeData): void {
+        if (!Array.isArray(sourceCodeData)) {
+            const outputCodePath: string = this.inputCLIOptions.output || CLIUtils.getOutputCodePath(this.inputPath);
 
-        CLIUtils.writeFile(outputCodePath, obfuscatedCode);
+            this.processSourceCode(sourceCodeData, outputCodePath);
+        } else {
+            sourceCodeData.forEach(({ filePath, content }: IFileData) => {
+                const outputCodePath: string = CLIUtils.getOutputCodePath(filePath);
+
+                this.processSourceCode(content, outputCodePath);
+            });
+        }
     }
 
     /**
+     * @param {string} sourceCode
      * @param {string} outputCodePath
-     * @param {TInputOptions} options
      */
-    private processSourceCodeWithSourceMap (outputCodePath: string, options: TInputOptions): void {
-        const outputSourceMapPath: string = CLIUtils.getOutputSourceMapPath(
-            outputCodePath,
-            options.sourceMapFileName || ''
-        );
-
-        options = {
-            ...options,
-            sourceMapFileName: path.basename(outputSourceMapPath)
-        };
-
-        const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(this.sourceCode, options);
-
-        CLIUtils.writeFile(outputCodePath, obfuscationResult.getObfuscatedCode());
+    private processSourceCode (sourceCode: string, outputCodePath: string): void {
+        const options: TInputOptions = this.buildOptions();
 
-        if (options.sourceMapMode === 'separate' && obfuscationResult.getSourceMap()) {
-            CLIUtils.writeFile(outputSourceMapPath, obfuscationResult.getSourceMap());
+        if (options.sourceMap) {
+            JavaScriptObfuscatorCLI.processSourceCodeWithSourceMap(sourceCode, outputCodePath, options);
+        } else {
+            JavaScriptObfuscatorCLI.processSourceCodeWithoutSourceMap(sourceCode, outputCodePath, options);
         }
     }
 }

+ 2 - 42
src/cli/utils/CLIUtils.ts

@@ -4,31 +4,19 @@ import * as path from 'path';
 
 import { TObject } from '../../types/TObject';
 
-import { IPackageConfig } from '../../interfaces/IPackageConfig';
+import { IPackageConfig } from '../../interfaces/cli/IPackageConfig';
 
 export class CLIUtils {
-    /**
-     * @type {string[]}
-     */
-    private static readonly availableInputExtensions: string[] = [
-        '.js'
-    ];
-
     /**
      * @type {BufferEncoding}
      */
     private static readonly encoding: BufferEncoding = 'utf8';
 
     /**
-     * @param {string} outputPath
      * @param {string} inputPath
      * @returns {string}
      */
-    public static getOutputCodePath (outputPath: string | undefined, inputPath: string): string {
-        if (outputPath) {
-            return outputPath;
-        }
-
+    public static getOutputCodePath (inputPath: string): string {
         return inputPath
             .split('.')
             .map((value: string, index: number) => {
@@ -95,34 +83,6 @@ export class CLIUtils {
         return config;
     }
 
-    /**
-     * @param {string} filePath
-     * @returns {boolean}
-     */
-    public static isFilePath (filePath: string): boolean {
-        try {
-            return fs.statSync(filePath).isFile();
-        } catch (e) {
-            return false;
-        }
-    }
-
-    /**
-     * @param {string} inputPath
-     * @returns {string}
-     */
-    public static readSourceCode (inputPath: string): string {
-        if (!CLIUtils.isFilePath(inputPath)) {
-            throw new ReferenceError(`Given input path must be a valid file path`);
-        }
-
-        if (!CLIUtils.availableInputExtensions.includes(path.extname(inputPath))) {
-            throw new ReferenceError(`Input file must have .js extension`);
-        }
-
-        return fs.readFileSync(inputPath, CLIUtils.encoding);
-    }
-
     /**
      * @param {string} outputPath
      * @param {any} data

+ 95 - 0
src/cli/utils/SourceCodeReader.ts

@@ -0,0 +1,95 @@
+import * as fs from 'fs';
+import * as path from 'path';
+
+import { TSourceCodeData } from '../../types/cli/TSourceCodeData';
+
+import { IFileData } from '../../interfaces/cli/IFileData';
+
+export class SourceCodeReader {
+    /**
+     * @type {string[]}
+     */
+    private static readonly availableInputExtensions: string[] = [
+        '.js'
+    ];
+
+    /**
+     * @type {BufferEncoding}
+     */
+    private static readonly encoding: BufferEncoding = 'utf8';
+
+    /**
+     * @param {string} inputPath
+     * @returns {TSourceCodeData}
+     */
+    public static readSourceCode (inputPath: string): TSourceCodeData {
+        if (SourceCodeReader.isFilePath(inputPath)) {
+            return SourceCodeReader.readFile(inputPath);
+        }
+
+        if (SourceCodeReader.isDirectoryPath(inputPath)) {
+            return SourceCodeReader.readDirectory(inputPath);
+        }
+
+        throw new ReferenceError(`Given input path must be a valid source code file or directory path`);
+    }
+
+    /**
+     * @param {string} filePath
+     * @returns {boolean}
+     */
+    private static isDirectoryPath (filePath: string): boolean {
+        try {
+            return fs.statSync(filePath).isDirectory();
+        } catch (e) {
+            return false;
+        }
+    }
+
+    /**
+     * @param {string} filePath
+     * @returns {boolean}
+     */
+    private static isFilePath (filePath: string): boolean {
+        try {
+            return fs.statSync(filePath).isFile();
+        } catch (e) {
+            return false;
+        }
+    }
+
+    /**
+     * @param {string} directoryPath
+     * @returns {IFileData[]}
+     */
+    private static readDirectory (directoryPath: string): IFileData[] {
+        return fs.readdirSync(directoryPath, SourceCodeReader.encoding)
+            .filter(SourceCodeReader.isValidFile)
+            .map((fileName: string) => {
+                const filePath: string = `${directoryPath}/${fileName}`;
+                const content: string = fs.readFileSync(filePath, SourceCodeReader.encoding);
+
+                return { filePath, content };
+            });
+    }
+
+    /**
+     * @param {string} filePath
+     * @returns {string}
+     */
+    private static readFile (filePath: string): string {
+        if (!SourceCodeReader.isValidFile(filePath)) {
+            throw new ReferenceError(`Input file must have .js extension`);
+        }
+
+        return fs.readFileSync(filePath, SourceCodeReader.encoding);
+    }
+
+    /**
+     * @param {string} filePath
+     * @returns {boolean}
+     */
+    private static isValidFile (filePath: string): boolean {
+        return SourceCodeReader.availableInputExtensions.includes(path.extname(filePath));
+    }
+}

+ 4 - 0
src/interfaces/cli/IFileData.d.ts

@@ -0,0 +1,4 @@
+export interface IFileData {
+    filePath: string;
+    content: string;
+}

+ 0 - 0
src/interfaces/IPackageConfig.d.ts → src/interfaces/cli/IPackageConfig.d.ts


+ 3 - 0
src/types/cli/TSourceCodeData.d.ts

@@ -0,0 +1,3 @@
+import { IFileData } from '../../interfaces/cli/IFileData';
+
+export type TSourceCodeData = string | IFileData[];

+ 1 - 0
test/index.spec.ts

@@ -11,6 +11,7 @@ import './unit-tests/cli/sanitizers/BooleanSanitizer.spec';
 import './unit-tests/cli/sanitizers/SourceMapModeSanitizer.spec';
 import './unit-tests/cli/sanitizers/StringArrayEncodingSanitizer.spec';
 import './unit-tests/cli/utils/CLIUtils.spec';
+import './unit-tests/cli/utils/SourceCodeReader.spec';
 import './unit-tests/decorators/initializable/Initializable.spec';
 import './unit-tests/javascript-obfuscator/JavaScriptObfuscator.spec';
 import './unit-tests/logger/Logger.spec';

+ 4 - 80
test/unit-tests/cli/utils/CLIUtils.spec.ts

@@ -1,6 +1,3 @@
-import * as fs from 'fs';
-import * as mkdirp from 'mkdirp';
-
 import { assert } from 'chai';
 
 import { TInputOptions } from '../../../../src/types/options/TInputOptions';
@@ -8,24 +5,12 @@ import { TInputOptions } from '../../../../src/types/options/TInputOptions';
 import { CLIUtils } from '../../../../src/cli/utils/CLIUtils';
 
 describe('CLIUtils', () => {
-    const fileContent: string = 'test';
-    const tmpDir: string = 'test/tmp';
-
-    before(() => {
-        mkdirp.sync(tmpDir);
-    });
-
-    describe('getOutputCodePath (outputPath: string, inputPath: string): string', () => {
+    describe('getOutputCodePath (inputPath: string): string', () => {
         let expectedInputPath: string = 'test/input/test-obfuscated.js',
-            inputPath: string = 'test/input/test.js',
-            outputPath: string = 'test/output/test.js';
-
-        it('should return `outputPath` if this path is set', () => {
-            assert.equal(CLIUtils.getOutputCodePath(outputPath, inputPath), outputPath);
-        });
+            inputPath: string = 'test/input/test.js';
 
-        it('should output path based on `inputPath` if `outputPath` is not set', () => {
-            assert.equal(CLIUtils.getOutputCodePath('', inputPath), expectedInputPath);
+        it('should output path based on `inputPath`', () => {
+            assert.equal(CLIUtils.getOutputCodePath(inputPath), expectedInputPath);
         });
     });
 
@@ -86,65 +71,4 @@ describe('CLIUtils', () => {
             });
         });
     });
-
-    describe('readSourceCode (inputPath: string): void', () => {
-        describe('`inputPath` is a valid path', () => {
-            const tmpFileName: string = 'test.js';
-            const inputPath: string = `${tmpDir}/${tmpFileName}`;
-
-            let result: string;
-
-            before(() => {
-                fs.writeFileSync(inputPath, fileContent);
-                result = CLIUtils.readSourceCode(inputPath);
-            });
-
-            it('should return content of file', () => {
-                assert.equal(result, fileContent);
-            });
-
-            after(() => {
-                fs.unlinkSync(inputPath);
-            });
-        });
-
-        describe('`inputPath` is not a valid path', () => {
-            const tmpFileName: string = 'test.js';
-            const inputPath: string = `${tmpDir}/${tmpFileName}`;
-
-            let testFunc: () => void;
-
-            before(() => {
-                testFunc = () => CLIUtils.readSourceCode(inputPath);
-            });
-
-            it('should throw an error if `inputPath` is not a valid path', () => {
-                assert.throws(testFunc, ReferenceError);
-            });
-        });
-
-        describe('`inputPath` is a file name has invalid extension', () => {
-            const tmpFileName: string = 'test.ts';
-            const inputPath: string = `${tmpDir}/${tmpFileName}`;
-
-            let testFunc: () => void;
-
-            before(() => {
-                fs.writeFileSync(inputPath, fileContent);
-                testFunc = () => CLIUtils.readSourceCode(inputPath);
-            });
-
-            it('should throw an error if `inputPath` is a file name has invalid extension', () => {
-                assert.throws(testFunc, ReferenceError);
-            });
-
-            after(() => {
-                fs.unlinkSync(inputPath);
-            });
-        });
-    });
-
-    after(() => {
-        fs.rmdirSync(tmpDir);
-    });
 });

+ 134 - 0
test/unit-tests/cli/utils/SourceCodeReader.spec.ts

@@ -0,0 +1,134 @@
+import * as fs from 'fs';
+import * as mkdirp from 'mkdirp';
+
+import { assert } from 'chai';
+
+import { SourceCodeReader } from '../../../../src/cli/utils/SourceCodeReader';
+import { IFileData } from '../../../../src/interfaces/cli/IFileData';
+
+describe('SourceCodeReader', () => {
+    const fileContent: string = 'test';
+    const tmpDir: string = 'test/tmp';
+
+    before(() => {
+        mkdirp.sync(tmpDir);
+    });
+
+    describe('readSourceCode (inputPath: string): void', () => {
+        describe('Variant #1: input path is a file path', () => {
+            describe('`inputPath` is a valid path', () => {
+                const tmpFileName: string = 'test.js';
+                const inputPath: string = `${tmpDir}/${tmpFileName}`;
+
+                let result: string | IFileData[];
+
+                before(() => {
+                    fs.writeFileSync(inputPath, fileContent);
+                    result = SourceCodeReader.readSourceCode(inputPath);
+                });
+
+                it('should return content of file', () => {
+                    assert.equal(result, fileContent);
+                });
+
+                after(() => {
+                    fs.unlinkSync(inputPath);
+                });
+            });
+
+            describe('`inputPath` is not a valid path', () => {
+                const tmpFileName: string = 'test.js';
+                const inputPath: string = `${tmpDir}/${tmpFileName}`;
+
+                let testFunc: () => void;
+
+                before(() => {
+                    testFunc = () => SourceCodeReader.readSourceCode(inputPath);
+                });
+
+                it('should throw an error if `inputPath` is not a valid path', () => {
+                    assert.throws(testFunc, ReferenceError);
+                });
+            });
+
+            describe('`inputPath` has invalid extension', () => {
+                const tmpFileName: string = 'test.ts';
+                const inputPath: string = `${tmpDir}/${tmpFileName}`;
+
+                let testFunc: () => void;
+
+                before(() => {
+                    fs.writeFileSync(inputPath, fileContent);
+                    testFunc = () => SourceCodeReader.readSourceCode(inputPath);
+                });
+
+                it('should throw an error if `inputPath` has invalid extension', () => {
+                    assert.throws(testFunc, ReferenceError);
+                });
+
+                after(() => {
+                    fs.unlinkSync(inputPath);
+                });
+            });
+        });
+
+        describe('Variant #2: input path is a directory path', () => {
+            describe('`inputPath` is a valid path', () => {
+                const tmpFileName1: string = 'foo.js';
+                const tmpFileName2: string = 'bar.js';
+                const tmpFileName3: string = 'baz.png';
+                const filePath1: string = `${tmpDir}/${tmpFileName1}`;
+                const filePath2: string = `${tmpDir}/${tmpFileName2}`;
+                const filePath3: string = `${tmpDir}/${tmpFileName3}`;
+
+                const expectedResult: IFileData[] = [
+                    {
+                        filePath: filePath2,
+                        content: fileContent
+                    },
+                    {
+                        filePath: filePath1,
+                        content: fileContent
+                    }
+                ];
+
+                let result: string | IFileData[];
+
+                before(() => {
+                    fs.writeFileSync(filePath1, fileContent);
+                    fs.writeFileSync(filePath2, fileContent);
+                    fs.writeFileSync(filePath3, fileContent);
+                    result = SourceCodeReader.readSourceCode(tmpDir);
+                });
+
+                it('should return files data', () => {
+                    assert.deepEqual(result, expectedResult);
+                });
+
+                after(() => {
+                    fs.unlinkSync(filePath1);
+                    fs.unlinkSync(filePath2);
+                    fs.unlinkSync(filePath3);
+                });
+            });
+
+            describe('`inputPath` is not a valid path', () => {
+                const inputPath: string = 'abc';
+
+                let testFunc: () => void;
+
+                before(() => {
+                    testFunc = () => SourceCodeReader.readSourceCode(inputPath);
+                });
+
+                it('should throw an error if `inputPath` is not a valid path', () => {
+                    assert.throws(testFunc, ReferenceError);
+                });
+            });
+        });
+    });
+
+    after(() => {
+        fs.rmdirSync(tmpDir);
+    });
+});

+ 2 - 1
tsconfig.json

@@ -17,7 +17,8 @@
     "target": "es2015",
     "plugins": [
       {
-        "name": "tslint-language-service"
+        "name": "tslint-language-service",
+        "ignoreDefinitionFiles": true
       }
     ]
   },

+ 110 - 209
yarn.lock

@@ -14,9 +14,9 @@
   version "0.7.35"
   resolved "https://registry.yarnpkg.com/@types/chance/-/chance-0.7.35.tgz#e76f3441b7763476c58eb7dc32f62da3d8ea547e"
 
-"@types/commander@2.9.2":
-  version "2.9.2"
-  resolved "https://registry.yarnpkg.com/@types/commander/-/commander-2.9.2.tgz#421f0cafd94a580991662711ea61fc37a5fcfede"
+"@types/commander@2.11.0":
+  version "2.11.0"
+  resolved "https://registry.yarnpkg.com/@types/commander/-/commander-2.11.0.tgz#7fc765ccad14827e2babd6a99583359ff3e40563"
   dependencies:
     "@types/node" "*"
 
@@ -24,9 +24,9 @@
   version "0.0.6"
   resolved "https://registry.yarnpkg.com/@types/escodegen/-/escodegen-0.0.6.tgz#5230a9ce796e042cda6f086dbf19f22ea330659c"
 
-"@types/[email protected].0":
-  version "4.0.0"
-  resolved "https://registry.yarnpkg.com/@types/esprima/-/esprima-4.0.0.tgz#846e0ea76e019e1a0f93449006f742bcfc549403"
+"@types/[email protected].1":
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/@types/esprima/-/esprima-4.0.1.tgz#40f6fb3a3a50ebcaa4dfca17f41e7f10e687df03"
   dependencies:
     "@types/estree" "*"
 
@@ -56,13 +56,17 @@
   version "2.2.43"
   resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-2.2.43.tgz#03c54589c43ad048cbcbfd63999b55d0424eec27"
 
-"@types/node@*", "@types/[email protected]":
+"@types/node@*":
   version "8.0.28"
   resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.28.tgz#86206716f8d9251cf41692e384264cbd7058ad60"
 
-"@types/[email protected]":
-  version "2.3.4"
-  resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-2.3.4.tgz#2b3aa82dfc791eeff1d970b657a77eafff2899ff"
+"@types/[email protected]":
+  version "8.0.32"
+  resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.32.tgz#869a716538b6eec65ab3893f183d557be3cda206"
+
+"@types/[email protected]":
+  version "2.3.5"
+  resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-2.3.5.tgz#68f1e0ac15f2eb6cc682b7af87cd517acc77b589"
 
 "@types/[email protected]":
   version "1.0.2"
@@ -909,10 +913,6 @@ camelcase@^4.1.0:
   version "4.1.0"
   resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
 
-caseless@~0.11.0:
-  version "0.11.0"
-  resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.11.0.tgz#715b96ea9841593cc33067923f5ec60ebda4f7d7"
-
 caseless@~0.12.0:
   version "0.12.0"
   resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
@@ -935,7 +935,7 @@ [email protected]:
     pathval "^1.0.0"
     type-detect "^4.0.0"
 
[email protected], chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3:
[email protected], chalk@^1.0.0, chalk@^1.1.3:
   version "1.1.3"
   resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
   dependencies:
@@ -1069,12 +1069,6 @@ [email protected], commander@^2.11.0, commander@^2.9.0:
   version "2.11.0"
   resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563"
 
[email protected]:
-  version "2.9.0"
-  resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4"
-  dependencies:
-    graceful-readlink ">= 1.0.0"
-
 commondir@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
@@ -1125,15 +1119,15 @@ [email protected], core-util-is@~1.0.0:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
 
-coveralls@2.13.1:
-  version "2.13.1"
-  resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-2.13.1.tgz#d70bb9acc1835ec4f063ff9dac5423c17b11f178"
+coveralls@3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-3.0.0.tgz#22ef730330538080d29b8c151dc9146afde88a99"
   dependencies:
-    js-yaml "3.6.1"
-    lcov-parse "0.0.10"
-    log-driver "1.2.5"
-    minimist "1.2.0"
-    request "2.79.0"
+    js-yaml "^3.6.1"
+    lcov-parse "^0.0.10"
+    log-driver "^1.2.5"
+    minimist "^1.2.0"
+    request "^2.79.0"
 
 create-ecdh@^4.0.0:
   version "4.0.0"
@@ -1211,7 +1205,13 @@ date-now@^0.1.4:
   version "0.1.4"
   resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b"
 
[email protected], debug@^2.2.0, debug@^2.3.3, debug@^2.6.3, debug@^2.6.8:
[email protected]:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
+  dependencies:
+    ms "2.0.0"
+
+debug@^2.2.0, debug@^2.3.3, debug@^2.6.3, debug@^2.6.8:
   version "2.6.8"
   resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc"
   dependencies:
@@ -1274,7 +1274,11 @@ detect-indent@^4.0.0:
   dependencies:
     repeating "^2.0.0"
 
[email protected], diff@^3.1.0, diff@^3.2.0:
[email protected]:
+  version "3.3.1"
+  resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.1.tgz#aa8567a6eed03c531fc89d3f711cd0e5259dec75"
+
+diff@^3.1.0, diff@^3.2.0:
   version "3.2.0"
   resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9"
 
@@ -1451,6 +1455,15 @@ escope@~1.0.1:
   dependencies:
     estraverse "^2.0.0"
 
+eslint-plugin-node@^5.1.0:
+  version "5.2.0"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-5.2.0.tgz#e1efca04a385516cff3f2f04027ce8c5ae6db749"
+  dependencies:
+    ignore "^3.3.3"
+    minimatch "^3.0.4"
+    resolve "^1.3.3"
+    semver "5.3.0"
+
 [email protected]:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/esmangle/-/esmangle-1.0.1.tgz#d9bb37b8f8eafbf4e6d4ed6b7aa2956abbd3c4c2"
@@ -1468,7 +1481,7 @@ [email protected], esprima@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804"
 
-esprima@^2.6.0, esprima@^2.7.1:
+esprima@^2.7.1:
   version "2.7.3"
   resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581"
 
@@ -1758,16 +1771,6 @@ gauge@~2.7.3:
     strip-ansi "^3.0.1"
     wide-align "^1.1.0"
 
-generate-function@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74"
-
-generate-object-property@^1.1.0:
-  version "1.2.0"
-  resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0"
-  dependencies:
-    is-property "^1.0.0"
-
 get-caller-file@^1.0.1:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5"
@@ -1803,18 +1806,7 @@ glob-parent@^2.0.0:
   dependencies:
     is-glob "^2.0.0"
 
[email protected]:
-  version "7.1.1"
-  resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8"
-  dependencies:
-    fs.realpath "^1.0.0"
-    inflight "^1.0.4"
-    inherits "2"
-    minimatch "^3.0.2"
-    once "^1.3.0"
-    path-is-absolute "^1.0.0"
-
-glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2:
[email protected], glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2:
   version "7.1.2"
   resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
   dependencies:
@@ -1840,13 +1832,11 @@ graceful-fs@^4.1.2, graceful-fs@^4.1.4:
   version "4.1.11"
   resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658"
 
-"graceful-readlink@>= 1.0.0":
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725"
-
[email protected]:
-  version "1.9.2"
-  resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f"
[email protected]:
+  version "1.10.2"
+  resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.2.tgz#8f16dfcd8fb7c04cfc1f4e0012e0ea858726979a"
+  dependencies:
+    eslint-plugin-node "^5.1.0"
 
 handlebars@^4.0.3:
   version "4.0.10"
@@ -1862,15 +1852,6 @@ har-schema@^1.0.5:
   version "1.0.5"
   resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e"
 
-har-validator@~2.0.6:
-  version "2.0.6"
-  resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-2.0.6.tgz#cdcbc08188265ad119b6a5a7c8ab70eecfb5d27d"
-  dependencies:
-    chalk "^1.1.1"
-    commander "^2.9.0"
-    is-my-json-valid "^2.12.4"
-    pinkie-promise "^2.0.0"
-
 har-validator@~4.2.1:
   version "4.2.1"
   resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a"
@@ -1977,6 +1958,10 @@ ieee754@^1.1.4:
   version "1.1.8"
   resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4"
 
+ignore@^3.3.3:
+  version "3.3.5"
+  resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.5.tgz#c4e715455f6073a8d7e5dae72d2fc9d71663dba6"
+
 [email protected]:
   version "0.0.1"
   resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d"
@@ -2128,15 +2113,6 @@ is-glob@^2.0.0, is-glob@^2.0.1:
   dependencies:
     is-extglob "^1.0.0"
 
-is-my-json-valid@^2.12.4:
-  version "2.16.0"
-  resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.16.0.tgz#f079dd9bfdae65ee2038aae8acbc86ab109e3693"
-  dependencies:
-    generate-function "^2.0.0"
-    generate-object-property "^1.1.0"
-    jsonpointer "^4.0.0"
-    xtend "^4.0.0"
-
 is-number@^2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f"
@@ -2173,10 +2149,6 @@ is-promise@^2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa"
 
-is-property@^1.0.0:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84"
-
 is-stream@^1.0.1, is-stream@^1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
@@ -2295,14 +2267,7 @@ js-tokens@^3.0.0, js-tokens@^3.0.2:
   version "3.0.2"
   resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
 
[email protected], [email protected]:
-  version "3.6.1"
-  resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.6.1.tgz#6e5fe67d8b205ce4d22fad05b7781e8dadcc4b30"
-  dependencies:
-    argparse "^1.0.7"
-    esprima "^2.6.0"
-
-js-yaml@^3.7.0:
[email protected], js-yaml@^3.6.1, js-yaml@^3.7.0:
   version "3.9.1"
   resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.9.1.tgz#08775cebdfdd359209f0d2acd383c8f86a6904a0"
   dependencies:
@@ -2347,10 +2312,6 @@ json-stringify-safe@~5.0.1:
   version "5.0.1"
   resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
 
[email protected]:
-  version "3.3.2"
-  resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1"
-
 json5@^0.5.0, json5@^0.5.1:
   version "0.5.1"
   resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821"
@@ -2359,10 +2320,6 @@ jsonify@~0.0.0:
   version "0.0.0"
   resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
 
-jsonpointer@^4.0.0:
-  version "4.0.1"
-  resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9"
-
 jsprim@^1.2.2:
   version "1.4.1"
   resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
@@ -2408,7 +2365,7 @@ lcid@^1.0.0:
   dependencies:
     invert-kv "^1.0.0"
 
[email protected]:
+lcov-parse@^0.0.10:
   version "0.0.10"
   resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-0.0.10.tgz#1b0b8ff9ac9c7889250582b70b71315d9da6d9a3"
 
@@ -2454,58 +2411,15 @@ locate-path@^2.0.0:
     p-locate "^2.0.0"
     path-exists "^3.0.0"
 
-lodash._baseassign@^3.0.0:
-  version "3.2.0"
-  resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e"
-  dependencies:
-    lodash._basecopy "^3.0.0"
-    lodash.keys "^3.0.0"
-
-lodash._basecopy@^3.0.0:
-  version "3.0.1"
-  resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36"
-
-lodash._basecreate@^3.0.0:
-  version "3.0.3"
-  resolved "https://registry.yarnpkg.com/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz#1bc661614daa7fc311b7d03bf16806a0213cf821"
-
-lodash._getnative@^3.0.0:
-  version "3.9.1"
-  resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5"
-
-lodash._isiterateecall@^3.0.0:
-  version "3.0.9"
-  resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c"
-
[email protected]:
-  version "3.1.1"
-  resolved "https://registry.yarnpkg.com/lodash.create/-/lodash.create-3.1.1.tgz#d7f2849f0dbda7e04682bb8cd72ab022461debe7"
-  dependencies:
-    lodash._baseassign "^3.0.0"
-    lodash._basecreate "^3.0.0"
-    lodash._isiterateecall "^3.0.0"
-
-lodash.isarguments@^3.0.0:
-  version "3.1.0"
-  resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a"
-
-lodash.isarray@^3.0.0:
-  version "3.0.4"
-  resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55"
-
-lodash.keys@^3.0.0:
-  version "3.1.2"
-  resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a"
-  dependencies:
-    lodash._getnative "^3.0.0"
-    lodash.isarguments "^3.0.0"
-    lodash.isarray "^3.0.0"
+lodash.get@^4.4.2:
+  version "4.4.2"
+  resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
 
 lodash@^4.14.0, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0:
   version "4.17.4"
   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
 
[email protected]:
+log-driver@^1.2.5:
   version "1.2.5"
   resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.5.tgz#7ae4ec257302fd790d557cb10c97100d857b0056"
 
@@ -2674,22 +2588,20 @@ [email protected], [email protected], "mkdirp@>=0.5 0", mkdirp@^0.5.1, mkdirp@~0.5.0:
   dependencies:
     minimist "0.0.8"
 
-mocha@3.5.3:
-  version "3.5.3"
-  resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.5.3.tgz#1e0480fe36d2da5858d1eb6acc38418b26eaa20d"
+mocha@4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/mocha/-/mocha-4.0.0.tgz#3da718ccd76e93b9d82afb065e17086bdbe352bf"
   dependencies:
     browser-stdout "1.3.0"
-    commander "2.9.0"
-    debug "2.6.8"
-    diff "3.2.0"
+    commander "2.11.0"
+    debug "3.1.0"
+    diff "3.3.1"
     escape-string-regexp "1.0.5"
-    glob "7.1.1"
-    growl "1.9.2"
+    glob "7.1.2"
+    growl "1.10.2"
     he "1.1.1"
-    json3 "3.3.2"
-    lodash.create "3.1.1"
     mkdirp "0.5.1"
-    supports-color "3.1.2"
+    supports-color "4.4.0"
 
 [email protected]:
   version "2.0.0"
@@ -2724,14 +2636,15 @@ native-promise-only@^0.8.1:
   version "0.8.1"
   resolved "https://registry.yarnpkg.com/native-promise-only/-/native-promise-only-0.8.1.tgz#20a318c30cb45f71fe7adfbf7b21c99c1472ef11"
 
-nise@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/nise/-/nise-1.0.1.tgz#0da92b10a854e97c0f496f6c2845a301280b3eef"
+nise@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/nise/-/nise-1.1.0.tgz#37e41b9bf0041ccb83d1bf03e79440bbc0db10ad"
   dependencies:
     formatio "^1.2.0"
     just-extend "^1.1.22"
     lolex "^1.6.0"
     path-to-regexp "^1.7.0"
+    text-encoding "^0.6.4"
 
 [email protected]:
   version "1.6.3"
@@ -3141,10 +3054,6 @@ punycode@^1.2.4, punycode@^1.4.1:
   version "1.4.1"
   resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
 
-qs@~6.3.0:
-  version "6.3.2"
-  resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.2.tgz#e75bd5f6e268122a2a0e0bda630b2550c166502c"
-
 qs@~6.4.0:
   version "6.4.0"
   resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233"
@@ -3292,32 +3201,7 @@ repeating@^2.0.0:
   dependencies:
     is-finite "^1.0.0"
 
[email protected]:
-  version "2.79.0"
-  resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de"
-  dependencies:
-    aws-sign2 "~0.6.0"
-    aws4 "^1.2.1"
-    caseless "~0.11.0"
-    combined-stream "~1.0.5"
-    extend "~3.0.0"
-    forever-agent "~0.6.1"
-    form-data "~2.1.1"
-    har-validator "~2.0.6"
-    hawk "~3.1.3"
-    http-signature "~1.1.0"
-    is-typedarray "~1.0.0"
-    isstream "~0.1.2"
-    json-stringify-safe "~5.0.1"
-    mime-types "~2.1.7"
-    oauth-sign "~0.8.1"
-    qs "~6.3.0"
-    stringstream "~0.0.4"
-    tough-cookie "~2.3.0"
-    tunnel-agent "~0.4.1"
-    uuid "^3.0.0"
-
-request@^2.81.0:
+request@^2.79.0, request@^2.81.0:
   version "2.81.0"
   resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0"
   dependencies:
@@ -3356,7 +3240,7 @@ resolve-url@^0.2.1:
   version "0.2.1"
   resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
 
-resolve@^1.3.2:
+resolve@^1.3.2, resolve@^1.3.3:
   version "1.4.0"
   resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.4.0.tgz#a75be01c53da25d934a98ebd0e4c4a7312f92a86"
   dependencies:
@@ -3410,6 +3294,10 @@ [email protected], samsam@^1.1.3:
   version "5.4.1"
   resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e"
 
[email protected]:
+  version "5.3.0"
+  resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
+
 set-blocking@^2.0.0, set-blocking@~2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
@@ -3457,15 +3345,16 @@ signal-exit@^3.0.0, signal-exit@^3.0.2:
   version "3.0.2"
   resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
 
-sinon@3.2.1:
-  version "3.2.1"
-  resolved "https://registry.yarnpkg.com/sinon/-/sinon-3.2.1.tgz#d8adabd900730fd497788a027049c64b08be91c2"
+sinon@4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/sinon/-/sinon-4.0.0.tgz#a54a5f0237aa1dd2215e5e81c89b42b50c4fdb6b"
   dependencies:
     diff "^3.1.0"
     formatio "1.2.0"
+    lodash.get "^4.4.2"
     lolex "^2.1.2"
     native-promise-only "^0.8.1"
-    nise "^1.0.1"
+    nise "^1.1.0"
     path-to-regexp "^1.7.0"
     samsam "^1.1.3"
     text-encoding "0.6.4"
@@ -3521,7 +3410,13 @@ source-map-resolve@^0.5.0:
     source-map-url "^0.4.0"
     urix "^0.1.0"
 
[email protected], source-map-support@^0.4.0, source-map-support@^0.4.15:
[email protected]:
+  version "0.5.0"
+  resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.0.tgz#2018a7ad2bdf8faf2691e5fddab26bed5a2bacab"
+  dependencies:
+    source-map "^0.6.0"
+
+source-map-support@^0.4.0, source-map-support@^0.4.15:
   version "0.4.18"
   resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f"
   dependencies:
@@ -3541,6 +3436,10 @@ source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.1, source-map@~0.5.3:
   version "0.5.6"
   resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412"
 
+source-map@^0.6.0:
+  version "0.6.1"
+  resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
+
 source-map@~0.1.33:
   version "0.1.43"
   resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346"
@@ -3685,16 +3584,22 @@ strip-json-comments@^2.0.0, strip-json-comments@~2.0.1:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
 
-supports-color@3.1.2, supports-color@^3.1.2:
-  version "3.1.2"
-  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5"
+supports-color@4.4.0:
+  version "4.4.0"
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.4.0.tgz#883f7ddabc165142b2a61427f3352ded195d1a3e"
   dependencies:
-    has-flag "^1.0.0"
+    has-flag "^2.0.0"
 
 supports-color@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
 
+supports-color@^3.1.2:
+  version "3.1.2"
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5"
+  dependencies:
+    has-flag "^1.0.0"
+
 supports-color@^4.0.0, supports-color@^4.2.1:
   version "4.2.1"
   resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.2.1.tgz#65a4bb2631e90e02420dba5554c375a4754bb836"
@@ -3726,7 +3631,7 @@ tar@^2.2.1:
     fstream "^1.0.2"
     inherits "2"
 
[email protected]:
[email protected], text-encoding@^0.6.4:
   version "0.6.4"
   resolved "https://registry.yarnpkg.com/text-encoding/-/text-encoding-0.6.4.tgz#e399a982257a276dae428bb92845cb71bdc26d19"
 
@@ -3873,10 +3778,6 @@ tunnel-agent@^0.6.0:
   dependencies:
     safe-buffer "^5.0.1"
 
-tunnel-agent@~0.4.1:
-  version "0.4.3"
-  resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.4.3.tgz#6373db76909fe570e08d73583365ed828a74eeeb"
-
 tweetnacl@^0.14.3, tweetnacl@~0.14.0:
   version "0.14.5"
   resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
@@ -3895,9 +3796,9 @@ typedarray@^0.0.6:
   version "0.0.6"
   resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
 
[email protected].2:
-  version "2.5.2"
-  resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.5.2.tgz#038a95f7d9bbb420b1bf35ba31d4c5c1dd3ffe34"
[email protected].3:
+  version "2.5.3"
+  resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.5.3.tgz#df3dcdc38f3beb800d4bc322646b04a3f6ca7f0d"
 
 uglify-js@^2.6, uglify-js@^2.8.29:
   version "2.8.29"

部分文件因文件數量過多而無法顯示