فهرست منبع

Merge pull request #546 from javascript-obfuscator/file-path-in-error-messages-directory-fix

File path in error messages directory fix
Timofey Kachalov 5 سال پیش
والد
کامیت
b95455fa63

+ 4 - 0
CHANGELOG.md

@@ -1,5 +1,9 @@
 Change Log
 
+v0.24.6
+---
+* Added file path to the error message during directory obfuscation. Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/513
+
 v0.24.5
 ---
 * Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/542

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
dist/index.browser.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
dist/index.cli.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
dist/index.js


+ 6 - 6
package.json

@@ -1,6 +1,6 @@
 {
   "name": "javascript-obfuscator",
-  "version": "0.24.5",
+  "version": "0.24.6",
   "description": "JavaScript obfuscator",
   "keywords": [
     "obfuscator",
@@ -28,7 +28,7 @@
     "chalk": "3.0.0",
     "chance": "1.1.4",
     "class-validator": "0.11.0",
-    "commander": "4.1.0",
+    "commander": "4.1.1",
     "escodegen": "1.13.0",
     "eslint-scope": "5.0.0",
     "estraverse": "4.3.0",
@@ -60,16 +60,16 @@
     "@types/sinon": "7.5.1",
     "@types/string-template": "1.0.2",
     "@types/webpack-env": "1.15.1",
-    "@typescript-eslint/eslint-plugin": "2.18.0",
-    "@typescript-eslint/parser": "2.18.0",
+    "@typescript-eslint/eslint-plugin": "2.19.0",
+    "@typescript-eslint/parser": "2.19.0",
     "chai": "4.2.0",
     "coveralls": "3.0.9",
     "eslint": "6.8.0",
-    "eslint-plugin-import": "2.20.0",
+    "eslint-plugin-import": "2.20.1",
     "eslint-plugin-jsdoc": "21.0.0",
     "eslint-plugin-no-null": "1.0.2",
     "eslint-plugin-prefer-arrow": "1.1.7",
-    "eslint-plugin-unicorn": "15.0.1",
+    "eslint-plugin-unicorn": "16.0.0",
     "fork-ts-checker-notifier-webpack-plugin": "2.0.0",
     "fork-ts-checker-webpack-plugin": "4.0.3",
     "mocha": "7.0.1",

+ 105 - 88
src/cli/JavaScriptObfuscatorCLI.ts

@@ -3,7 +3,6 @@ import * as path from 'path';
 
 import { TInputCLIOptions } from '../types/options/TInputCLIOptions';
 import { TInputOptions } from '../types/options/TInputOptions';
-import { TSourceCodeData } from '../types/cli/TSourceCodeData';
 
 import { IFileData } from '../interfaces/cli/IFileData';
 import { IInitializable } from '../interfaces/IInitializable';
@@ -22,6 +21,7 @@ import { StringArrayEncodingSanitizer } from './sanitizers/StringArrayEncodingSa
 
 import { CLIUtils } from './utils/CLIUtils';
 import { JavaScriptObfuscator } from '../JavaScriptObfuscatorFacade';
+import { ObfuscatedCodeWriter } from './utils/ObfuscatedCodeWriter';
 import { SourceCodeReader } from './utils/SourceCodeReader';
 
 export class JavaScriptObfuscatorCLI implements IInitializable {
@@ -68,6 +68,18 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
     @initializable()
     private inputPath!: string;
 
+    /**
+     * @type {SourceCodeReader}
+     */
+    @initializable()
+    private sourceCodeReader!: SourceCodeReader;
+
+    /**
+     * @type {ObfuscatedCodeWriter}
+     */
+    @initializable()
+    private obfuscatedCodeWriter!: ObfuscatedCodeWriter;
+
     /**
      * @param {string[]} argv
      */
@@ -76,6 +88,31 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
         this.arguments = argv.slice(2);
     }
 
+    /**
+     * @param {TInputCLIOptions} inputOptions
+     * @param {string} inputCodePath
+     * @returns {TInputOptions}
+     */
+    private static buildOptions (
+        inputOptions: TInputCLIOptions,
+        inputCodePath: string
+    ): TInputOptions {
+        const inputCLIOptions: TInputOptions = JavaScriptObfuscatorCLI.filterOptions(inputOptions);
+        const configFilePath: string | undefined = inputOptions.config;
+        const configFileLocation: string = configFilePath ? path.resolve(configFilePath, '.') : '';
+        const configFileOptions: TInputOptions = configFileLocation ? CLIUtils.getUserConfig(configFileLocation) : {};
+        const inputFileName: string = path.basename(inputCodePath);
+        const inputFilePath: string = inputCodePath;
+
+        return {
+            ...DEFAULT_PRESET,
+            ...configFileOptions,
+            ...inputCLIOptions,
+            inputFileName,
+            inputFilePath
+        };
+    }
+
     /**
      * @param {TObject} options
      * @returns {TInputOptions}
@@ -96,50 +133,6 @@ 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 obfuscatedCode: IObfuscatedCode = JavaScriptObfuscator.obfuscate(sourceCode, options);
-
-        CLIUtils.writeFile(outputCodePath, obfuscatedCode.getObfuscatedCode());
-
-        if (options.sourceMapMode === 'separate' && obfuscatedCode.getSourceMap()) {
-            CLIUtils.writeFile(outputSourceMapPath, obfuscatedCode.getSourceMap());
-        }
-    }
-
     public initialize (): void {
         this.inputPath = path.normalize(this.arguments[0] || '');
         this.commands = <commander.CommanderStatic>(new commander.Command());
@@ -148,6 +141,14 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
         this.configureHelp();
 
         this.inputCLIOptions = this.commands.opts();
+        this.sourceCodeReader = new SourceCodeReader(
+            this.inputPath,
+            this.inputCLIOptions
+        );
+        this.obfuscatedCodeWriter = new ObfuscatedCodeWriter(
+            this.inputPath,
+            this.inputCLIOptions
+        );
     }
 
     public run (): void {
@@ -159,32 +160,11 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
             return;
         }
 
-        const sourceCodeData: TSourceCodeData = new SourceCodeReader(this.inputCLIOptions)
-            .readSourceCode(this.inputPath);
+        const sourceCodeData: IFileData[] = this.sourceCodeReader.readSourceCode();
 
         this.processSourceCodeData(sourceCodeData);
     }
 
-    /**
-     * @returns {TInputOptions}
-     */
-    private buildOptions (): TInputOptions {
-        const inputCLIOptions: TInputOptions = JavaScriptObfuscatorCLI.filterOptions(this.inputCLIOptions);
-        const configFilePath: string | undefined = this.inputCLIOptions.config;
-        const configFileLocation: string = configFilePath ? path.resolve(configFilePath, '.') : '';
-        const configFileOptions: TInputOptions = configFileLocation ? CLIUtils.getUserConfig(configFileLocation) : {};
-        const inputFileName: string = path.basename(this.inputPath);
-        const inputFilePath: string = this.inputPath;
-
-        return {
-            ...DEFAULT_PRESET,
-            ...configFileOptions,
-            ...inputCLIOptions,
-            inputFileName,
-            inputFilePath
-        };
-    }
-
     private configureCommands (): void {
         this.commands
             .usage('<inputPath> [options]')
@@ -380,39 +360,32 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
     }
 
     /**
-     * @param {TSourceCodeData} sourceCodeData
+     * @param {IFileData[]} sourceCodeData
      */
-    private processSourceCodeData (sourceCodeData: TSourceCodeData): void {
-        const outputPath: string = this.inputCLIOptions.output
-            ? path.normalize(this.inputCLIOptions.output)
-            : '';
+    private processSourceCodeData (sourceCodeData: IFileData[]): void {
+        sourceCodeData.forEach(({ filePath, content }: IFileData, index: number) => {
+            const outputCodePath: string = this.obfuscatedCodeWriter.getOutputCodePath(filePath);
 
-        if (!Array.isArray(sourceCodeData)) {
-            const outputCodePath: string = outputPath || CLIUtils.getOutputCodePath(this.inputPath);
-
-            this.processSourceCode(sourceCodeData, outputCodePath, null);
-        } else {
-            sourceCodeData.forEach(({ filePath, content }: IFileData, index: number) => {
-                const outputCodePath: string = outputPath
-                    ? path.join(outputPath, filePath)
-                    : CLIUtils.getOutputCodePath(filePath);
-
-                this.processSourceCode(content, outputCodePath, index);
-            });
-        }
+            this.processSourceCode(content, filePath, outputCodePath, index);
+        });
     }
 
     /**
      * @param {string} sourceCode
+     * @param {string} inputCodePath
      * @param {string} outputCodePath
      * @param {number | null} sourceCodeIndex
      */
     private processSourceCode (
         sourceCode: string,
+        inputCodePath: string,
         outputCodePath: string,
         sourceCodeIndex: number | null
     ): void {
-        let options: TInputOptions = this.buildOptions();
+        let options: TInputOptions = JavaScriptObfuscatorCLI.buildOptions(
+            this.inputCLIOptions,
+            inputCodePath
+        );
 
         if (sourceCodeIndex !== null) {
             const baseIdentifiersPrefix: string = this.inputCLIOptions.identifiersPrefix
@@ -426,9 +399,53 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
         }
 
         if (options.sourceMap) {
-            JavaScriptObfuscatorCLI.processSourceCodeWithSourceMap(sourceCode, outputCodePath, options);
+            this.processSourceCodeWithSourceMap(sourceCode, outputCodePath, options);
         } else {
-            JavaScriptObfuscatorCLI.processSourceCodeWithoutSourceMap(sourceCode, outputCodePath, options);
+            this.processSourceCodeWithoutSourceMap(sourceCode, outputCodePath, options);
+        }
+    }
+
+    /**
+     * @param {string} sourceCode
+     * @param {string} outputCodePath
+     * @param {TInputOptions} options
+     */
+    private processSourceCodeWithoutSourceMap (
+        sourceCode: string,
+        outputCodePath: string,
+        options: TInputOptions
+    ): void {
+        const obfuscatedCode: string = JavaScriptObfuscator.obfuscate(sourceCode, options).getObfuscatedCode();
+
+        this.obfuscatedCodeWriter.writeFile(outputCodePath, obfuscatedCode);
+    }
+
+    /**
+     * @param {string} sourceCode
+     * @param {string} outputCodePath
+     * @param {TInputOptions} options
+     */
+    private processSourceCodeWithSourceMap (
+        sourceCode: string,
+        outputCodePath: string,
+        options: TInputOptions
+    ): void {
+        const outputSourceMapPath: string = this.obfuscatedCodeWriter.getOutputSourceMapPath(
+            outputCodePath,
+            options.sourceMapFileName ?? ''
+        );
+
+        options = {
+            ...options,
+            sourceMapFileName: path.basename(outputSourceMapPath)
+        };
+
+        const obfuscatedCode: IObfuscatedCode = JavaScriptObfuscator.obfuscate(sourceCode, options);
+
+        this.obfuscatedCodeWriter.writeFile(outputCodePath, obfuscatedCode.getObfuscatedCode());
+
+        if (options.sourceMapMode === 'separate' && obfuscatedCode.getSourceMap()) {
+            this.obfuscatedCodeWriter.writeFile(outputSourceMapPath, obfuscatedCode.getSourceMap());
         }
     }
 }

+ 0 - 55
src/cli/utils/CLIUtils.ts

@@ -1,49 +1,6 @@
-import * as fs from 'fs';
-import * as mkdirp from 'mkdirp';
-import * as path from 'path';
-
 import { TObject } from '../../types/TObject';
 
-import { StringSeparator } from '../../enums/StringSeparator';
-
-import { JavaScriptObfuscatorCLI } from '../JavaScriptObfuscatorCLI';
-
 export class CLIUtils {
-    /**
-     * @param {string} inputPath
-     * @returns {string}
-     */
-    public static getOutputCodePath (inputPath: string): string {
-        return path
-            .normalize(inputPath)
-            .split(StringSeparator.Dot)
-            .map((value: string, index: number) => {
-                return index === 0 ? `${value}${JavaScriptObfuscatorCLI.obfuscatedFilePrefix}` : value;
-            })
-            .join(StringSeparator.Dot);
-    }
-
-    /**
-     * @param {string} outputCodePath
-     * @param {string} sourceMapFileName
-     * @returns {string}
-     */
-    public static getOutputSourceMapPath (outputCodePath: string, sourceMapFileName: string = ''): string {
-        if (sourceMapFileName) {
-            outputCodePath = `${outputCodePath.substring(
-                0, outputCodePath.lastIndexOf('/')
-            )}/${sourceMapFileName}`;
-        }
-
-        if (!/\.js\.map$/.test(outputCodePath)) {
-            outputCodePath = `${outputCodePath.split(StringSeparator.Dot)[0]}.js.map`;
-        } else if (/\.js$/.test(outputCodePath)) {
-            outputCodePath += '.map';
-        }
-
-        return outputCodePath;
-    }
-
     /**
      * @param {string} configPath
      * @returns {TObject}
@@ -63,16 +20,4 @@ export class CLIUtils {
 
         return config;
     }
-
-    /**
-     * @param {string} outputPath
-     * @param {string} data
-     */
-    public static writeFile (outputPath: string, data: string): void {
-        mkdirp.sync(path.dirname(outputPath));
-
-        fs.writeFileSync(outputPath, data, {
-            encoding: JavaScriptObfuscatorCLI.encoding
-        });
-    }
 }

+ 104 - 0
src/cli/utils/ObfuscatedCodeWriter.ts

@@ -0,0 +1,104 @@
+import * as fs from 'fs';
+import * as mkdirp from 'mkdirp';
+import * as path from 'path';
+
+import { TInputCLIOptions } from '../../types/options/TInputCLIOptions';
+
+import { StringSeparator } from '../../enums/StringSeparator';
+
+import { JavaScriptObfuscatorCLI } from '../JavaScriptObfuscatorCLI';
+
+export class ObfuscatedCodeWriter {
+    /**
+     * @type {string}
+     */
+    private readonly inputPath: string;
+
+    /**
+     * @type {TInputCLIOptions}
+     */
+    private readonly options: TInputCLIOptions;
+
+    /**
+     * @param {string} inputPath
+     * @param {TInputCLIOptions} options
+     */
+    public constructor (
+        inputPath: string,
+        options: TInputCLIOptions
+    ) {
+        this.inputPath = inputPath;
+        this.options = options;
+    }
+
+    /**
+     * @param {string} filePath
+     * @returns {string}
+     */
+    public getOutputCodePath (filePath: string): string {
+        const normalizedRawOutputPath: string | null = this.options.output
+            ? path.normalize(this.options.output)
+            : null;
+
+        if (!normalizedRawOutputPath) {
+            return path
+                .normalize(filePath)
+                .split(StringSeparator.Dot)
+                .map((value: string, index: number) => {
+                    return index === 0 ? `${value}${JavaScriptObfuscatorCLI.obfuscatedFilePrefix}` : value;
+                })
+                .join(StringSeparator.Dot);
+        }
+
+        const rawInputPathStats: fs.Stats = fs.lstatSync(this.inputPath);
+        const isDirectoryRawInputPath: boolean = rawInputPathStats.isDirectory();
+        const isDirectoryRawOutputPath: boolean = path.extname(normalizedRawOutputPath) === '';
+
+        if (isDirectoryRawInputPath) {
+            if (isDirectoryRawOutputPath) {
+                return path.join(normalizedRawOutputPath, filePath);
+            } else {
+                throw new Error('Output path for directory obfuscation should be a directory path');
+            }
+        } else {
+            if (isDirectoryRawOutputPath) {
+                return path.join(normalizedRawOutputPath, path.basename(filePath));
+            } else {
+                return normalizedRawOutputPath;
+            }
+        }
+    }
+
+    /**
+     * @param {string} outputCodePath
+     * @param {string} sourceMapFileName
+     * @returns {string}
+     */
+    public getOutputSourceMapPath (outputCodePath: string, sourceMapFileName: string = ''): string {
+        if (sourceMapFileName) {
+            outputCodePath = `${outputCodePath.substring(
+                0, outputCodePath.lastIndexOf('/')
+            )}/${sourceMapFileName}`;
+        }
+
+        if (!/\.js\.map$/.test(outputCodePath)) {
+            outputCodePath = `${outputCodePath.split(StringSeparator.Dot)[0]}.js.map`;
+        } else if (/\.js$/.test(outputCodePath)) {
+            outputCodePath += '.map';
+        }
+
+        return outputCodePath;
+    }
+
+    /**
+     * @param {string} outputPath
+     * @param {string} data
+     */
+    public writeFile (outputPath: string, data: string): void {
+        mkdirp.sync(path.dirname(outputPath));
+
+        fs.writeFileSync(outputPath, data, {
+            encoding: JavaScriptObfuscatorCLI.encoding
+        });
+    }
+}

+ 74 - 43
src/cli/utils/SourceCodeReader.ts

@@ -3,7 +3,6 @@ import * as path from 'path';
 import multimatch from 'multimatch';
 
 import { TInputCLIOptions } from '../../types/options/TInputCLIOptions';
-import { TSourceCodeData } from '../../types/cli/TSourceCodeData';
 
 import { IFileData } from '../../interfaces/cli/IFileData';
 
@@ -20,15 +19,25 @@ export class SourceCodeReader {
         '.js'
     ];
 
+    /**
+     * @type {string}
+     */
+    private readonly inputPath: string;
+
     /**
      * @type {TInputCLIOptions}
      */
     private readonly options: TInputCLIOptions;
 
     /**
+     * @param {string} inputPath
      * @param {TInputCLIOptions} options
      */
-    public constructor (options: TInputCLIOptions) {
+    public constructor (
+        inputPath: string,
+        options: TInputCLIOptions
+    ) {
+        this.inputPath = inputPath;
         this.options = options;
     }
 
@@ -75,6 +84,26 @@ export class SourceCodeReader {
         }
     }
 
+    /**
+     * @param {string} directoryPath
+     * @param {string[]} excludePatterns
+     * @returns {boolean}
+     */
+    private static isValidDirectory (directoryPath: string, excludePatterns: string[] = []): boolean {
+        return !SourceCodeReader.isExcludedPath(directoryPath, excludePatterns);
+    }
+
+    /**
+     * @param {string} filePath
+     * @param {string[]} excludePatterns
+     * @returns {boolean}
+     */
+    private static isValidFile (filePath: string, excludePatterns: string[] = []): boolean {
+        return SourceCodeReader.availableInputExtensions.includes(path.extname(filePath))
+            && !filePath.includes(JavaScriptObfuscatorCLI.obfuscatedFilePrefix)
+            && !SourceCodeReader.isExcludedPath(filePath, excludePatterns);
+    }
+
     /**
      * @param {string} filePath
      */
@@ -89,16 +118,34 @@ export class SourceCodeReader {
     }
 
     /**
-     * @param {string} inputPath
-     * @returns {TSourceCodeData}
+     * @param {string} filePath
+     * @returns {string}
+     */
+    private static readFile (filePath: string): IFileData {
+        SourceCodeReader.logFilePath(filePath);
+
+        return {
+            filePath,
+            content: fs.readFileSync(filePath, JavaScriptObfuscatorCLI.encoding)
+        };
+    }
+
+    /**
+     * @returns {IFileData[]}
      */
-    public readSourceCode (inputPath: string): TSourceCodeData {
-        if (SourceCodeReader.isFilePath(inputPath) && this.isValidFile(inputPath)) {
-            return this.readFile(inputPath);
+    public readSourceCode (): IFileData[] {
+        if (
+            SourceCodeReader.isFilePath(this.inputPath)
+            && SourceCodeReader.isValidFile(this.inputPath, this.options.exclude)
+        ) {
+            return [SourceCodeReader.readFile(this.inputPath)];
         }
 
-        if (SourceCodeReader.isDirectoryPath(inputPath) && this.isValidDirectory(inputPath)) {
-            return this.readDirectoryRecursive(inputPath);
+        if (
+            SourceCodeReader.isDirectoryPath(this.inputPath)
+            && SourceCodeReader.isValidDirectory(this.inputPath, this.options.exclude)
+        ) {
+            return this.readDirectoryRecursive(this.inputPath);
         }
 
         const availableFilePaths: string = SourceCodeReader
@@ -111,51 +158,35 @@ export class SourceCodeReader {
 
     /**
      * @param {string} directoryPath
-     * @param {IFileData[]} fileData
+     * @param {IFileData[]} filesData
      * @returns {IFileData[]}
      */
-    private readDirectoryRecursive (directoryPath: string, fileData: IFileData[] = []): IFileData[] {
+    private readDirectoryRecursive (directoryPath: string, filesData: IFileData[] = []): IFileData[] {
         fs.readdirSync(directoryPath, JavaScriptObfuscatorCLI.encoding)
             .forEach((fileName: string) => {
                 const filePath: string = `${directoryPath}/${fileName}`;
 
-                if (SourceCodeReader.isDirectoryPath(filePath) && this.isValidDirectory(filePath)) {
-                    fileData.push(...this.readDirectoryRecursive(filePath));
-                } else if (SourceCodeReader.isFilePath(filePath) && this.isValidFile(filePath)) {
-                    const content: string = this.readFile(filePath);
+                if (
+                    SourceCodeReader.isDirectoryPath(filePath)
+                    && SourceCodeReader.isValidDirectory(filePath, this.options.exclude)
+                ) {
+                    filesData.push(...this.readDirectoryRecursive(filePath));
 
-                    fileData.push({ filePath, content });
+                    return;
                 }
-            });
 
-        return fileData;
-    }
+                if (
+                    SourceCodeReader.isFilePath(filePath)
+                    && SourceCodeReader.isValidFile(filePath, this.options.exclude)
+                ) {
+                    const fileData: IFileData = SourceCodeReader.readFile(filePath);
 
-    /**
-     * @param {string} filePath
-     * @returns {string}
-     */
-    private readFile (filePath: string): string {
-        SourceCodeReader.logFilePath(filePath);
-
-        return fs.readFileSync(filePath, JavaScriptObfuscatorCLI.encoding);
-    }
+                    filesData.push(fileData);
 
-    /**
-     * @param {string} directoryPath
-     * @returns {boolean}
-     */
-    private isValidDirectory (directoryPath: string): boolean {
-        return !SourceCodeReader.isExcludedPath(directoryPath, this.options.exclude);
-    }
+                    return;
+                }
+            });
 
-    /**
-     * @param {string} filePath
-     * @returns {boolean}
-     */
-    private isValidFile (filePath: string): boolean {
-        return SourceCodeReader.availableInputExtensions.includes(path.extname(filePath))
-            && !filePath.includes(JavaScriptObfuscatorCLI.obfuscatedFilePrefix)
-            && !SourceCodeReader.isExcludedPath(filePath, this.options.exclude);
+        return filesData;
     }
 }

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

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

+ 1 - 0
test/index.spec.ts

@@ -16,6 +16,7 @@ import './unit-tests/cli/sanitizers/ObfuscationTargetSanitizer.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/ObfuscatedCodeWriter.spec';
 import './unit-tests/cli/utils/SourceCodeReader.spec';
 import './unit-tests/decorators/initializable/Initializable.spec';
 import './unit-tests/generators/identifier-names-generators/DictionarylIdentifierNamesGenerator.spec';

+ 0 - 29
test/unit-tests/cli/utils/CLIUtils.spec.ts

@@ -5,35 +5,6 @@ import { TInputOptions } from '../../../../src/types/options/TInputOptions';
 import { CLIUtils } from '../../../../src/cli/utils/CLIUtils';
 
 describe('CLIUtils', () => {
-    describe('getOutputCodePath', () => {
-        describe('Variant #1: base input path', () => {
-            let expectedOutputPath: string = 'test/input/test-obfuscated.js',
-                inputPath: string = 'test/input/test.js';
-
-            it('should output path based on `inputPath`', () => {
-                assert.equal(CLIUtils.getOutputCodePath(inputPath), expectedOutputPath);
-            });
-        });
-
-        describe('Variant #2: relative input path with dot', () => {
-            let expectedOutputPath: string = 'input-obfuscated.js',
-                inputPath: string = './input.js';
-
-            it('should output path based on `inputPath`', () => {
-                assert.equal(CLIUtils.getOutputCodePath(inputPath), expectedOutputPath);
-            });
-        });
-    });
-
-    describe('getOutputSourceMapPath', () => {
-        let expectedOutputSourceMapPath: string = 'test/output/test.js.map',
-            outputCodePath: string = 'test/output/test.js';
-
-        it('should return output path for source map', () => {
-            assert.equal(CLIUtils.getOutputSourceMapPath(outputCodePath), expectedOutputSourceMapPath);
-        });
-    });
-
     describe('getUserConfig', () => {
         describe('Variant #1: valid config file path', () => {
             describe('Variant #1: js file with config', () => {

+ 138 - 0
test/unit-tests/cli/utils/ObfuscatedCodeWriter.spec.ts

@@ -0,0 +1,138 @@
+import { assert } from 'chai';
+import * as mkdirp from 'mkdirp';
+import * as rimraf from 'rimraf';
+import * as fs from "fs";
+
+import { ObfuscatedCodeWriter } from '../../../../src/cli/utils/ObfuscatedCodeWriter';
+
+describe('ObfuscatedCodeWriter', () => {
+    const tmpDirectoryPath: string = 'test/tmp';
+
+    describe('getOutputCodePath', () => {
+        before(() => {
+            mkdirp.sync(`${tmpDirectoryPath}/input/`);
+            fs.writeFileSync(
+                `${tmpDirectoryPath}/input/test-input.js`,
+                'var foo = 1;'
+            );
+        });
+
+        describe('Variant #1: raw input path is a file path, raw output path is a file path', () => {
+            const inputPath: string = `${tmpDirectoryPath}/input/test-input.js`;
+            const rawInputPath: string = `${tmpDirectoryPath}/input/test-input.js`;
+            const rawOutputPath: string = `${tmpDirectoryPath}/output/test-output.js`;
+            const expectedOutputCodePath: string = `${tmpDirectoryPath}/output/test-output.js`;
+
+            let outputCodePath: string;
+
+            before(() => {
+                const obfuscatedCodeWriter: ObfuscatedCodeWriter = new ObfuscatedCodeWriter(
+                    rawInputPath,
+                    {
+                        output: rawOutputPath
+                    }
+                );
+                outputCodePath = obfuscatedCodeWriter.getOutputCodePath(inputPath);
+            });
+
+            it('should return output path that equals to passed output file path', () => {
+                assert.equal(outputCodePath, expectedOutputCodePath);
+            });
+        });
+
+        describe('Variant #2: raw input path is a file path, raw output path is a directory path', () => {
+            const inputPath: string = `${tmpDirectoryPath}/input/test-input.js`;
+            const rawInputPath: string = `${tmpDirectoryPath}/input/test-input.js`;
+            const rawOutputPath: string = `${tmpDirectoryPath}/output`;
+            const expectedOutputCodePath: string = `${tmpDirectoryPath}/output/test-input.js`;
+
+            let outputCodePath: string;
+
+            before(() => {
+                const obfuscatedCodeWriter: ObfuscatedCodeWriter = new ObfuscatedCodeWriter(
+                    rawInputPath,
+                    {
+                        output: rawOutputPath
+                    }
+                );
+                outputCodePath = obfuscatedCodeWriter.getOutputCodePath(inputPath);
+            });
+
+            it('should return output path that equals to passed output directory with file name from actual file path', () => {
+                assert.equal(outputCodePath, expectedOutputCodePath);
+            });
+        });
+
+        describe('Variant #3: raw input path is a directory path, raw output path is a file path', () => {
+            const inputPath: string = `${tmpDirectoryPath}/input/test-input.js`;
+            const rawInputPath: string = `${tmpDirectoryPath}/input`;
+            const rawOutputPath: string = `${tmpDirectoryPath}/output/test-output.js`;
+
+            let testFunc: () => string;
+
+            before(() => {
+                const obfuscatedCodeWriter: ObfuscatedCodeWriter = new ObfuscatedCodeWriter(
+                    rawInputPath,
+                    {
+                        output: rawOutputPath
+                    }
+                );
+                testFunc = () => obfuscatedCodeWriter.getOutputCodePath(inputPath);
+            });
+
+            it('should throw an error if output path is a file path', () => {
+                assert.throws(testFunc, Error);
+            });
+        });
+
+        describe('Variant #4: raw input path is a directory path, raw output path is a directory path', () => {
+            const inputPath: string = `${tmpDirectoryPath}/input/test-input.js`;
+            const rawInputPath: string = `${tmpDirectoryPath}/input`;
+            const rawOutputPath: string = `${tmpDirectoryPath}/output`;
+            const expectedOutputCodePath: string = `${tmpDirectoryPath}/output/${tmpDirectoryPath}/input/test-input.js`;
+
+            let outputCodePath: string;
+
+            before(() => {
+                const obfuscatedCodeWriter: ObfuscatedCodeWriter = new ObfuscatedCodeWriter(
+                    rawInputPath,
+                    {
+                        output: rawOutputPath
+                    }
+                );
+                outputCodePath = obfuscatedCodeWriter.getOutputCodePath(inputPath);
+            });
+
+            it('should return output path that contains raw output path and actual file input path', () => {
+                assert.equal(outputCodePath, expectedOutputCodePath);
+            });
+        });
+
+        after(() => {
+            rimraf.sync(tmpDirectoryPath);
+        });
+    });
+
+    describe('getOutputSourceMapPath', () => {
+        const rawInputPath: string = `${tmpDirectoryPath}/input/test-input.js`;
+        const rawOutputPath: string = `${tmpDirectoryPath}/output/test-output.js`;
+        const outputCodePath: string = `${tmpDirectoryPath}/output/test-output.js`;
+        const expectedOutputSourceMapPath: string = `${tmpDirectoryPath}/output/test-output.js.map`;
+
+        let outputSourceMapPath: string;
+
+        before(() => {
+            const obfuscatedCodeWriter: ObfuscatedCodeWriter = new ObfuscatedCodeWriter(
+                rawInputPath,
+                {
+                    output: rawOutputPath
+                }
+            );
+            outputSourceMapPath = obfuscatedCodeWriter.getOutputSourceMapPath(outputCodePath);
+        });
+
+        it('should return output path for source map', () => {
+            assert.equal(outputSourceMapPath, expectedOutputSourceMapPath);
+        });
+    });
+});

+ 91 - 55
test/unit-tests/cli/utils/SourceCodeReader.spec.ts

@@ -23,16 +23,20 @@ describe('SourceCodeReader', () => {
             describe('Variant #1: `inputPath` is a valid path', () => {
                 const tmpFileName: string = 'test.js';
                 const inputPath: string = `${tmpDirectoryPath}/${tmpFileName}`;
+                const expectedFilesData: IFileData[] = [{
+                    content: fileContent,
+                    filePath: inputPath
+                }];
 
-                let result: string | IFileData[];
+                let filesData: IFileData[];
 
                 before(() => {
                     fs.writeFileSync(inputPath, fileContent);
-                    result = new SourceCodeReader({}).readSourceCode(inputPath);
+                    filesData = new SourceCodeReader(inputPath, {}).readSourceCode();
                 });
 
-                it('should return content of file', () => {
-                    assert.equal(result, fileContent);
+                it('should return valid files data', () => {
+                    assert.deepEqual(filesData, expectedFilesData);
                 });
 
                 after(() => {
@@ -47,7 +51,7 @@ describe('SourceCodeReader', () => {
                 let testFunc: () => void;
 
                 before(() => {
-                    testFunc = () => new SourceCodeReader({}).readSourceCode(inputPath);
+                    testFunc = () => new SourceCodeReader(inputPath, {}).readSourceCode();
                 });
 
                 it('should throw an error if `inputPath` is not a valid path', () => {
@@ -63,7 +67,7 @@ describe('SourceCodeReader', () => {
 
                 before(() => {
                     fs.writeFileSync(inputPath, fileContent);
-                    testFunc = () => new SourceCodeReader({}).readSourceCode(inputPath);
+                    testFunc = () => new SourceCodeReader(inputPath, {}).readSourceCode();
                 });
 
                 it('should throw an error if `inputPath` has invalid extension', () => {
@@ -79,17 +83,25 @@ describe('SourceCodeReader', () => {
                 describe('Variant #1: `inputPath` isn\'t excluded path', () => {
                     const tmpFileName: string = 'test.js';
                     const inputPath: string = `${tmpDirectoryPath}/${tmpFileName}`;
+                    const expectedFilesData: IFileData[] = [{
+                        content: fileContent,
+                        filePath: inputPath
+                    }];
 
-                    let result: string | IFileData[];
+                    let filesData: IFileData[];
 
                     before(() => {
                         fs.writeFileSync(inputPath, fileContent);
-                        result = new SourceCodeReader({
-                            exclude: ['**/foo.js']
-                        }).readSourceCode(inputPath);                });
+                        filesData = new SourceCodeReader(
+                            inputPath,
+                            {
+                                exclude: ['**/foo.js']
+                            }
+                        ).readSourceCode();
+                    });
 
-                    it('should return content of file', () => {
-                        assert.equal(result, fileContent);
+                    it('should return valid files data', () => {
+                        assert.deepEqual(filesData, expectedFilesData);
                     });
 
                     after(() => {
@@ -106,9 +118,12 @@ describe('SourceCodeReader', () => {
 
                         before(() => {
                             fs.writeFileSync(inputPath, fileContent);
-                            testFunc = () => new SourceCodeReader({
-                                exclude: [`**/${tmpFileName}`]
-                            }).readSourceCode(inputPath);
+                            testFunc = () => new SourceCodeReader(
+                                inputPath,
+                                {
+                                    exclude: [`**/${tmpFileName}`]
+                                }
+                            ).readSourceCode();
                         });
 
                         it('should throw an error if `inputPath` is the excluded file path', () => {
@@ -128,9 +143,12 @@ describe('SourceCodeReader', () => {
 
                         before(() => {
                             fs.writeFileSync(inputPath, fileContent);
-                            testFunc = () => new SourceCodeReader({
-                                exclude: [tmpFileName]
-                            }).readSourceCode(inputPath);
+                            testFunc = () => new SourceCodeReader(
+                                inputPath,
+                                {
+                                    exclude: [tmpFileName]
+                                }
+                            ).readSourceCode();
                         });
 
                         it('should throw an error if `inputPath` is the excluded file path', () => {
@@ -150,9 +168,12 @@ describe('SourceCodeReader', () => {
 
                         before(() => {
                             fs.writeFileSync(inputPath, fileContent);
-                            testFunc = () => new SourceCodeReader({
-                                exclude: [inputPath]
-                            }).readSourceCode(inputPath);
+                            testFunc = () => new SourceCodeReader(
+                                inputPath,
+                                {
+                                    exclude: [inputPath]
+                                }
+                            ).readSourceCode();
                         });
 
                         it('should throw an error if `inputPath` is the excluded file path', () => {
@@ -189,14 +210,14 @@ describe('SourceCodeReader', () => {
                     }
                 ];
 
-                let result: string | IFileData[];
+                let result: IFileData[];
 
                 before(() => {
                     fs.writeFileSync(filePath1, fileContent);
                     fs.writeFileSync(filePath2, fileContent);
                     fs.writeFileSync(filePath3, fileContent);
                     fs.writeFileSync(filePath4, fileContent);
-                    result = new SourceCodeReader({}).readSourceCode(tmpDirectoryPath);
+                    result = new SourceCodeReader(tmpDirectoryPath, {}).readSourceCode();
                 });
 
                 it('should return files data', () => {
@@ -217,7 +238,7 @@ describe('SourceCodeReader', () => {
                 let testFunc: () => void;
 
                 before(() => {
-                    testFunc = () => new SourceCodeReader({}).readSourceCode(inputPath);
+                    testFunc = () => new SourceCodeReader(inputPath, {}).readSourceCode();
                 });
 
                 it('should throw an error if `inputPath` is not a valid path', () => {
@@ -258,7 +279,7 @@ describe('SourceCodeReader', () => {
                     }
                 ];
 
-                let result: string | IFileData[];
+                let result: IFileData[];
 
                 before(() => {
                     mkdirp.sync(parentDirectoryPath1);
@@ -267,7 +288,7 @@ describe('SourceCodeReader', () => {
                     fs.writeFileSync(filePath2, fileContent);
                     fs.writeFileSync(filePath3, fileContent);
                     fs.writeFileSync(filePath4, fileContent);
-                    result = new SourceCodeReader({}).readSourceCode(tmpDirectoryPath);
+                    result = new SourceCodeReader(tmpDirectoryPath, {}).readSourceCode();
                 });
 
                 it('should return files data', () => {
@@ -306,16 +327,19 @@ describe('SourceCodeReader', () => {
                         }
                     ];
 
-                    let result: string | IFileData[];
+                    let result: IFileData[];
 
                     before(() => {
                         fs.writeFileSync(filePath1, fileContent);
                         fs.writeFileSync(filePath2, fileContent);
                         fs.writeFileSync(filePath3, fileContent);
                         fs.writeFileSync(filePath4, fileContent);
-                        result = new SourceCodeReader({
-                            exclude: ['**/hawk.js']
-                        }).readSourceCode(tmpDirectoryPath);
+                        result = new SourceCodeReader(
+                            tmpDirectoryPath,
+                            {
+                                exclude: ['**/hawk.js']
+                            }
+                        ).readSourceCode();
                     });
 
                     it('should return files data', () => {
@@ -352,19 +376,22 @@ describe('SourceCodeReader', () => {
                             }
                         ];
 
-                        let result: string | IFileData[];
+                        let result: IFileData[];
 
                         before(() => {
                             fs.writeFileSync(filePath1, fileContent);
                             fs.writeFileSync(filePath2, fileContent);
                             fs.writeFileSync(filePath3, fileContent);
                             fs.writeFileSync(filePath4, fileContent);
-                            result = new SourceCodeReader({
-                                exclude: [
-                                    `**/${tmpFileName2}`,
-                                    `**/${tmpFileName4}`
-                                ]
-                            }).readSourceCode(tmpDirectoryPath);
+                            result = new SourceCodeReader(
+                                tmpDirectoryPath,
+                                {
+                                    exclude: [
+                                        `**/${tmpFileName2}`,
+                                        `**/${tmpFileName4}`
+                                    ]
+                                }
+                            ).readSourceCode();
                         });
 
                         it('should return files data', () => {
@@ -400,19 +427,22 @@ describe('SourceCodeReader', () => {
                             }
                         ];
 
-                        let result: string | IFileData[];
+                        let result: IFileData[];
 
                         before(() => {
                             fs.writeFileSync(filePath1, fileContent);
                             fs.writeFileSync(filePath2, fileContent);
                             fs.writeFileSync(filePath3, fileContent);
                             fs.writeFileSync(filePath4, fileContent);
-                            result = new SourceCodeReader({
-                                exclude: [
-                                    tmpFileName2,
-                                    tmpFileName4
-                                ]
-                            }).readSourceCode(tmpDirectoryPath);
+                            result = new SourceCodeReader(
+                                tmpDirectoryPath,
+                                {
+                                    exclude: [
+                                        tmpFileName2,
+                                        tmpFileName4
+                                    ]
+                                }
+                            ).readSourceCode();
                         });
 
                         it('should return files data', () => {
@@ -448,19 +478,22 @@ describe('SourceCodeReader', () => {
                             }
                         ];
 
-                        let result: string | IFileData[];
+                        let result: IFileData[];
 
                         before(() => {
                             fs.writeFileSync(filePath1, fileContent);
                             fs.writeFileSync(filePath2, fileContent);
                             fs.writeFileSync(filePath3, fileContent);
                             fs.writeFileSync(filePath4, fileContent);
-                            result = new SourceCodeReader({
-                                exclude: [
-                                    filePath2,
-                                    filePath4
-                                ]
-                            }).readSourceCode(tmpDirectoryPath);
+                            result = new SourceCodeReader(
+                                tmpDirectoryPath,
+                                {
+                                    exclude: [
+                                        filePath2,
+                                        filePath4
+                                    ]
+                                }
+                            ).readSourceCode();
                         });
 
                         it('should return files data', () => {
@@ -492,9 +525,12 @@ describe('SourceCodeReader', () => {
                             fs.writeFileSync(filePath2, fileContent);
                             fs.writeFileSync(filePath3, fileContent);
                             fs.writeFileSync(filePath4, fileContent);
-                            testFunc = () => new SourceCodeReader({
-                                exclude: [tmpDirectoryPath]
-                            }).readSourceCode(tmpDirectoryPath);
+                            testFunc = () => new SourceCodeReader(
+                                tmpDirectoryPath,
+                                {
+                                    exclude: [tmpDirectoryPath]
+                                }
+                            ).readSourceCode();
                         });
 
                         it('should return files data', () => {
@@ -526,7 +562,7 @@ describe('SourceCodeReader', () => {
                 consoleLogSpy = sinon.spy(console, 'log');
 
                 fs.writeFileSync(inputPath, fileContent);
-                new SourceCodeReader({}).readSourceCode(inputPath);
+                new SourceCodeReader(inputPath, {}).readSourceCode();
 
                 consoleLogCallResult = consoleLogSpy.called;
                 loggingMessageResult = consoleLogSpy.getCall(0).args[0];

+ 53 - 260
yarn.lock

@@ -323,40 +323,40 @@
   resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.15.1.tgz#c8e84705e08eed430b5e15b39c65b0944e4d1422"
   integrity sha512-eWN5ElDTeBc5lRDh95SqA8x18D0ll2pWudU3uWiyfsRmIZcmUXpEsxPU+7+BsdCrO2vfLRC629u/MmjbmF+2tA==
 
-"@typescript-eslint/[email protected]8.0":
-  version "2.18.0"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.18.0.tgz#f8cf272dfb057ecf1ea000fea1e0b3f06a32f9cb"
-  integrity sha512-kuO8WQjV+RCZvAXVRJfXWiJ8iYEtfHlKgcqqqXg9uUkIolEHuUaMmm8/lcO4xwCOtaw6mY0gStn2Lg4/eUXXYQ==
+"@typescript-eslint/[email protected]9.0":
+  version "2.19.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.19.0.tgz#bf743448a4633e4b52bee0c40148ba072ab3adbd"
+  integrity sha512-u7IcQ9qwsB6U806LupZmINRnQjC+RJyv36sV/ugaFWMHTbFm/hlLTRx3gGYJgHisxcGSTnf+I/fPDieRMhPSQQ==
   dependencies:
-    "@typescript-eslint/experimental-utils" "2.18.0"
+    "@typescript-eslint/experimental-utils" "2.19.0"
     eslint-utils "^1.4.3"
     functional-red-black-tree "^1.0.1"
     regexpp "^3.0.0"
     tsutils "^3.17.1"
 
-"@typescript-eslint/[email protected]8.0":
-  version "2.18.0"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.18.0.tgz#e4eab839082030282496c1439bbf9fdf2a4f3da8"
-  integrity sha512-J6MopKPHuJYmQUkANLip7g9I82ZLe1naCbxZZW3O2sIxTiq/9YYoOELEKY7oPg0hJ0V/AQ225h2z0Yp+RRMXhw==
+"@typescript-eslint/[email protected]9.0":
+  version "2.19.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.19.0.tgz#d5ca732f22c009e515ba09fcceb5f2127d841568"
+  integrity sha512-zwpg6zEOPbhB3+GaQfufzlMUOO6GXCNZq6skk+b2ZkZAIoBhVoanWK255BS1g5x9bMwHpLhX0Rpn5Fc3NdCZdg==
   dependencies:
     "@types/json-schema" "^7.0.3"
-    "@typescript-eslint/typescript-estree" "2.18.0"
+    "@typescript-eslint/typescript-estree" "2.19.0"
     eslint-scope "^5.0.0"
 
-"@typescript-eslint/[email protected]8.0":
-  version "2.18.0"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.18.0.tgz#d5f7fc1839abd4a985394e40e9d2454bd56aeb1f"
-  integrity sha512-SJJPxFMEYEWkM6pGfcnjLU+NJIPo+Ko1QrCBL+i0+zV30ggLD90huEmMMhKLHBpESWy9lVEeWlQibweNQzyc+A==
+"@typescript-eslint/[email protected]9.0":
+  version "2.19.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.19.0.tgz#912160d9425395d09857dcd5382352bc98be11ae"
+  integrity sha512-s0jZoxAWjHnuidbbN7aA+BFVXn4TCcxEVGPV8lWMxZglSs3NRnFFAlL+aIENNmzB2/1jUJuySi6GiM6uACPmpg==
   dependencies:
     "@types/eslint-visitor-keys" "^1.0.0"
-    "@typescript-eslint/experimental-utils" "2.18.0"
-    "@typescript-eslint/typescript-estree" "2.18.0"
+    "@typescript-eslint/experimental-utils" "2.19.0"
+    "@typescript-eslint/typescript-estree" "2.19.0"
     eslint-visitor-keys "^1.1.0"
 
-"@typescript-eslint/[email protected]8.0":
-  version "2.18.0"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.18.0.tgz#cfbd16ed1b111166617d718619c19b62764c8460"
-  integrity sha512-gVHylf7FDb8VSi2ypFuEL3hOtoC4HkZZ5dOjXvVjoyKdRrvXAOPSzpNRnKMfaUUEiSLP8UF9j9X9EDLxC0lfZg==
+"@typescript-eslint/[email protected]9.0":
+  version "2.19.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.19.0.tgz#6bd7310b9827e04756fe712909f26956aac4b196"
+  integrity sha512-n6/Xa37k0jQdwpUszffi19AlNbVCR0sdvCs3DmSKMD7wBttKY31lhD2fug5kMD91B2qW4mQldaTEc1PEzvGu8w==
   dependencies:
     debug "^4.1.1"
     eslint-visitor-keys "^1.1.0"
@@ -522,11 +522,6 @@
   resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d"
   integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==
 
-abbrev@1:
-  version "1.1.1"
-  resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
-  integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
-
 [email protected]:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/acorn-import-meta/-/acorn-import-meta-1.0.0.tgz#6cff1f01db3b60148934823d3d2dd0c08354aead"
@@ -650,7 +645,7 @@ append-transform@^2.0.0:
   dependencies:
     default-require-extensions "^3.0.0"
 
-aproba@^1.0.3, aproba@^1.1.1:
+aproba@^1.1.1:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
   integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==
@@ -660,14 +655,6 @@ archy@^1.0.0:
   resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40"
   integrity sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=
 
-are-we-there-yet@~1.1.2:
-  version "1.1.5"
-  resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21"
-  integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==
-  dependencies:
-    delegates "^1.0.0"
-    readable-stream "^2.0.6"
-
 argparse@^1.0.7:
   version "1.0.10"
   resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
@@ -1237,11 +1224,6 @@ cliui@^6.0.0:
     strip-ansi "^6.0.0"
     wrap-ansi "^6.2.0"
 
-code-point-at@^1.0.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
-  integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
-
 collection-visit@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0"
@@ -1281,10 +1263,10 @@ combined-stream@^1.0.6, combined-stream@~1.0.6:
   dependencies:
     delayed-stream "~1.0.0"
 
[email protected].0:
-  version "4.1.0"
-  resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.0.tgz#545983a0603fe425bc672d66c9e3c89c42121a83"
-  integrity sha512-NIQrwvv9V39FHgGFm36+U9SMQzbiHvU79k+iADraJTpmrFFfx7Ds0IvDoAdZsDrknlkRk14OYoWXb57uTh7/sw==
[email protected].1:
+  version "4.1.1"
+  resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068"
+  integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==
 
 commander@^2.20.0:
   version "2.20.3"
@@ -1331,11 +1313,6 @@ console-browserify@^1.1.0:
   resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336"
   integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==
 
-console-control-strings@^1.0.0, console-control-strings@~1.1.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
-  integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=
-
 constants-browserify@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75"
@@ -1480,7 +1457,7 @@ dashdash@^1.12.0:
   dependencies:
     assert-plus "^1.0.0"
 
[email protected], debug@^3.2.6:
[email protected]:
   version "3.2.6"
   resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
   integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==
@@ -1518,11 +1495,6 @@ deep-eql@^3.0.1:
   dependencies:
     type-detect "^4.0.0"
 
-deep-extend@^0.6.0:
-  version "0.6.0"
-  resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
-  integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==
-
 deep-is@~0.1.3:
   version "0.1.3"
   resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
@@ -1569,11 +1541,6 @@ delayed-stream@~1.0.0:
   resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
   integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
 
-delegates@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
-  integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=
-
 des.js@^1.0.0:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843"
@@ -1587,11 +1554,6 @@ detect-file@^1.0.0:
   resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7"
   integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=
 
-detect-libc@^1.0.2:
-  version "1.0.3"
-  resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
-  integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=
-
 [email protected], diff@^3.1.0:
   version "3.5.0"
   resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
@@ -1788,10 +1750,10 @@ eslint-module-utils@^2.4.1:
     debug "^2.6.9"
     pkg-dir "^2.0.0"
 
[email protected].0:
-  version "2.20.0"
-  resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.20.0.tgz#d749a7263fb6c29980def8e960d380a6aa6aecaa"
-  integrity sha512-NK42oA0mUc8Ngn4kONOPsPB1XhbUvNHqF+g307dPV28aknPoiNnKLFd9em4nkswwepdF5ouieqv5Th/63U7YJQ==
[email protected].1:
+  version "2.20.1"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.20.1.tgz#802423196dcb11d9ce8435a5fc02a6d3b46939b3"
+  integrity sha512-qQHgFOTjguR+LnYRoToeZWT62XM55MBVXObHM6SKFd1VzDcX/vqT1kAz8ssqigh5eMj8qXcRoXXGZpPP6RfdCw==
   dependencies:
     array-includes "^3.0.3"
     array.prototype.flat "^1.2.1"
@@ -1829,10 +1791,10 @@ [email protected]:
   resolved "https://registry.yarnpkg.com/eslint-plugin-prefer-arrow/-/eslint-plugin-prefer-arrow-1.1.7.tgz#4534dd8d2e519cd579a951f95802137365d524a2"
   integrity sha512-epsA4g804mRovlOHSbeO1xxW7REGeUjULRME9MJTJDOVscNIA01AkR66TP4cmHDfD+w72EQ9cPhf37MbZiFI2w==
 
-eslint-plugin-unicorn@15.0.1:
-  version "15.0.1"
-  resolved "https://registry.yarnpkg.com/eslint-plugin-unicorn/-/eslint-plugin-unicorn-15.0.1.tgz#8379d1d6882f9f8631bec8025ac9e8fe89e43945"
-  integrity sha512-yahqrPGFUzwH5cnmnj+iPlgPapAiBIZ/ZNSDkhTVPgPCo7/mOEjJ2gDhEclrtQVBE9olmec4N+CKDnJuZ9XpRA==
+eslint-plugin-unicorn@16.0.0:
+  version "16.0.0"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-unicorn/-/eslint-plugin-unicorn-16.0.0.tgz#5fc03d70b2944fa85099bf511c352b3d50201738"
+  integrity sha512-zqWMYzTopdixyqu0+3td4vIGmpBxwdBVeWBm3TzwnFMvHoAE6tTQ/w2Xv5RG/MklKkfQdHsRqa8CVsSpjSA4qQ==
   dependencies:
     ci-info "^2.0.0"
     clean-regexp "^1.0.0"
@@ -1849,7 +1811,7 @@ [email protected]:
     regexpp "^3.0.0"
     reserved-words "^0.1.2"
     safe-regex "^2.1.1"
-    semver "^6.3.0"
+    semver "^7.1.2"
 
 [email protected], eslint-scope@^5.0.0:
   version "5.0.0"
@@ -2280,13 +2242,6 @@ fromentries@^1.2.0:
   resolved "https://registry.yarnpkg.com/fromentries/-/fromentries-1.2.0.tgz#e6aa06f240d6267f913cea422075ef88b63e7897"
   integrity sha512-33X7H/wdfO99GdRLLgkjUrD4geAFdq/Uv0kl3HD4da6HDixd2GUg8Mw7dahLCV9r/EARkmtYBB6Tch4EEokFTQ==
 
-fs-minipass@^1.2.5:
-  version "1.2.7"
-  resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7"
-  integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==
-  dependencies:
-    minipass "^2.6.0"
-
 fs-write-stream-atomic@^1.0.8:
   version "1.0.10"
   resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9"
@@ -2325,20 +2280,6 @@ functional-red-black-tree@^1.0.1:
   resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
   integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=
 
-gauge@~2.7.3:
-  version "2.7.4"
-  resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
-  integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=
-  dependencies:
-    aproba "^1.0.3"
-    console-control-strings "^1.0.0"
-    has-unicode "^2.0.0"
-    object-assign "^4.1.0"
-    signal-exit "^3.0.0"
-    string-width "^1.0.1"
-    strip-ansi "^3.0.1"
-    wide-align "^1.1.0"
-
 gensync@^1.0.0-beta.1:
   version "1.0.0-beta.1"
   resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269"
@@ -2515,11 +2456,6 @@ has-symbols@^1.0.0, has-symbols@^1.0.1:
   resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8"
   integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==
 
-has-unicode@^2.0.0:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
-  integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=
-
 has-value@^0.3.1:
   version "0.3.1"
   resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f"
@@ -2627,7 +2563,7 @@ https-browserify@^1.0.0:
   resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73"
   integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=
 
-iconv-lite@^0.4.24, iconv-lite@^0.4.4:
+iconv-lite@^0.4.24:
   version "0.4.24"
   resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
   integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
@@ -2644,13 +2580,6 @@ iferr@^0.1.5:
   resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501"
   integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE=
 
-ignore-walk@^3.0.1:
-  version "3.0.3"
-  resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.3.tgz#017e2447184bfeade7c238e4aefdd1e8f95b1e37"
-  integrity sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==
-  dependencies:
-    minimatch "^3.0.4"
-
 ignore@^4.0.6:
   version "4.0.6"
   resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc"
@@ -2715,7 +2644,7 @@ [email protected]:
   resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
   integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
 
-ini@^1.3.4, ini@^1.3.5, ini@~1.3.0:
+ini@^1.3.4, ini@^1.3.5:
   version "1.3.5"
   resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
   integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==
@@ -2856,13 +2785,6 @@ is-extglob@^2.1.0, is-extglob@^2.1.1:
   resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
   integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
 
-is-fullwidth-code-point@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
-  integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs=
-  dependencies:
-    number-is-nan "^1.0.0"
-
 is-fullwidth-code-point@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
@@ -3501,21 +3423,6 @@ minimist@^1.2.0:
   resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
   integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=
 
-minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0:
-  version "2.9.0"
-  resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6"
-  integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==
-  dependencies:
-    safe-buffer "^5.1.2"
-    yallist "^3.0.0"
-
-minizlib@^1.2.1:
-  version "1.3.3"
-  resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d"
-  integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==
-  dependencies:
-    minipass "^2.9.0"
-
 mississippi@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022"
@@ -3540,7 +3447,7 @@ mixin-deep@^1.2.0:
     for-in "^1.0.2"
     is-extendable "^1.0.1"
 
[email protected], mkdirp@^0.5.0, mkdirp@^0.5.1:
[email protected], mkdirp@^0.5.1:
   version "0.5.1"
   resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
   integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=
@@ -3657,15 +3564,6 @@ natural-compare@^1.4.0:
   resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
   integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=
 
-needle@^2.2.1:
-  version "2.4.0"
-  resolved "https://registry.yarnpkg.com/needle/-/needle-2.4.0.tgz#6833e74975c444642590e15a750288c5f939b57c"
-  integrity sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg==
-  dependencies:
-    debug "^3.2.6"
-    iconv-lite "^0.4.4"
-    sax "^1.2.4"
-
 neo-async@^2.5.0, neo-async@^2.6.1:
   version "2.6.1"
   resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c"
@@ -3741,22 +3639,6 @@ node-notifier@^6.0.0:
     shellwords "^0.1.1"
     which "^1.3.1"
 
-node-pre-gyp@*:
-  version "0.14.0"
-  resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.14.0.tgz#9a0596533b877289bcad4e143982ca3d904ddc83"
-  integrity sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA==
-  dependencies:
-    detect-libc "^1.0.2"
-    mkdirp "^0.5.1"
-    needle "^2.2.1"
-    nopt "^4.0.1"
-    npm-packlist "^1.1.6"
-    npmlog "^4.0.2"
-    rc "^1.2.7"
-    rimraf "^2.6.1"
-    semver "^5.3.0"
-    tar "^4.4.2"
-
 node-preload@^0.2.0:
   version "0.2.1"
   resolved "https://registry.yarnpkg.com/node-preload/-/node-preload-0.2.1.tgz#c03043bb327f417a18fee7ab7ee57b408a144301"
@@ -3764,14 +3646,6 @@ node-preload@^0.2.0:
   dependencies:
     process-on-spawn "^1.0.0"
 
-nopt@^4.0.1:
-  version "4.0.1"
-  resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d"
-  integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=
-  dependencies:
-    abbrev "1"
-    osenv "^0.1.4"
-
 normalize-package-data@^2.3.2, normalize-package-data@^2.5.0:
   version "2.5.0"
   resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8"
@@ -3794,27 +3668,6 @@ normalize-path@^3.0.0, normalize-path@~3.0.0:
   resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
   integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
 
-npm-bundled@^1.0.1:
-  version "1.1.1"
-  resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.1.1.tgz#1edd570865a94cdb1bc8220775e29466c9fb234b"
-  integrity sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==
-  dependencies:
-    npm-normalize-package-bin "^1.0.1"
-
-npm-normalize-package-bin@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2"
-  integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==
-
-npm-packlist@^1.1.6:
-  version "1.4.8"
-  resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.8.tgz#56ee6cc135b9f98ad3d51c1c95da22bbb9b2ef3e"
-  integrity sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==
-  dependencies:
-    ignore-walk "^3.0.1"
-    npm-bundled "^1.0.1"
-    npm-normalize-package-bin "^1.0.1"
-
 npm-run-path@^2.0.0:
   version "2.0.2"
   resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
@@ -3822,21 +3675,6 @@ npm-run-path@^2.0.0:
   dependencies:
     path-key "^2.0.0"
 
-npmlog@^4.0.2:
-  version "4.1.2"
-  resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
-  integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==
-  dependencies:
-    are-we-there-yet "~1.1.2"
-    console-control-strings "~1.1.0"
-    gauge "~2.7.3"
-    set-blocking "~2.0.0"
-
-number-is-nan@^1.0.0:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
-  integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=
-
 [email protected]:
   version "15.0.0"
   resolved "https://registry.yarnpkg.com/nyc/-/nyc-15.0.0.tgz#eb32db2c0f29242c2414fe46357f230121cfc162"
@@ -3876,7 +3714,7 @@ oauth-sign@~0.9.0:
   resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
   integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
 
-object-assign@^4.1.0, object-assign@^4.1.1:
+object-assign@^4.1.1:
   version "4.1.1"
   resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
   integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
@@ -3978,11 +3816,6 @@ os-browserify@^0.3.0:
   resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27"
   integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=
 
-os-homedir@^1.0.0:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
-  integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M=
-
 os-locale@^3.1.0:
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a"
@@ -3997,19 +3830,11 @@ os-shim@^0.1.2:
   resolved "https://registry.yarnpkg.com/os-shim/-/os-shim-0.1.3.tgz#6b62c3791cf7909ea35ed46e17658bb417cb3917"
   integrity sha1-a2LDeRz3kJ6jXtRuF2WLtBfLORc=
 
-os-tmpdir@^1.0.0, os-tmpdir@~1.0.2:
+os-tmpdir@~1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
   integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
 
-osenv@^0.1.4:
-  version "0.1.5"
-  resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410"
-  integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==
-  dependencies:
-    os-homedir "^1.0.0"
-    os-tmpdir "^1.0.0"
-
 p-defer@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c"
@@ -4406,16 +4231,6 @@ randomfill@^1.0.3:
     randombytes "^2.0.5"
     safe-buffer "^5.1.0"
 
-rc@^1.2.7:
-  version "1.2.8"
-  resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
-  integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==
-  dependencies:
-    deep-extend "^0.6.0"
-    ini "~1.3.0"
-    minimist "^1.2.0"
-    strip-json-comments "~2.0.1"
-
 read-pkg-up@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be"
@@ -4452,7 +4267,7 @@ read-pkg@^5.2.0:
     parse-json "^5.0.0"
     type-fest "^0.6.0"
 
-"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6:
+"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6:
   version "2.3.7"
   resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
   integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
@@ -4646,7 +4461,7 @@ [email protected], rimraf@^3.0.0:
   dependencies:
     glob "^7.1.3"
 
-rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.3:
+rimraf@^2.5.4, rimraf@^2.6.3:
   version "2.7.1"
   resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
   integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
@@ -4711,11 +4526,6 @@ safe-regex@^2.1.1:
   resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
   integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
 
-sax@^1.2.4:
-  version "1.2.4"
-  resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
-  integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
-
 schema-utils@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770"
@@ -4725,7 +4535,7 @@ schema-utils@^1.0.0:
     ajv-errors "^1.0.0"
     ajv-keywords "^3.1.0"
 
-"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0, semver@^5.7.0:
+"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.6.0, semver@^5.7.0:
   version "5.7.1"
   resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
   integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
@@ -4735,12 +4545,17 @@ semver@^6.0.0, semver@^6.1.2, semver@^6.3.0:
   resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
   integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
 
+semver@^7.1.2:
+  version "7.1.2"
+  resolved "https://registry.yarnpkg.com/semver/-/semver-7.1.2.tgz#847bae5bce68c5d08889824f02667199b70e3d87"
+  integrity sha512-BJs9T/H8sEVHbeigqzIEo57Iu/3DG6c4QoqTfbQB3BPA4zgzAomh/Fk9E7QtjWQ8mx2dgA9YCfSF4y9k9bHNpQ==
+
 serialize-javascript@^2.1.2:
   version "2.1.2"
   resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-2.1.2.tgz#ecec53b0e0317bdc95ef76ab7074b7384785fa61"
   integrity sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==
 
-set-blocking@^2.0.0, 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"
   integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc=
@@ -5018,15 +4833,6 @@ [email protected]:
   resolved "https://registry.yarnpkg.com/string-template/-/string-template-1.0.0.tgz#9e9f2233dc00f218718ec379a28a5673ecca8b96"
   integrity sha1-np8iM9wA8hhxjsN5oopWc+zKi5Y=
 
-string-width@^1.0.1:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
-  integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=
-  dependencies:
-    code-point-at "^1.0.0"
-    is-fullwidth-code-point "^1.0.0"
-    strip-ansi "^3.0.0"
-
 "string-width@^1.0.2 || 2":
   version "2.1.1"
   resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
@@ -5083,7 +4889,7 @@ string_decoder@~1.1.1:
   dependencies:
     safe-buffer "~5.1.0"
 
-strip-ansi@^3.0.0, strip-ansi@^3.0.1:
+strip-ansi@^3.0.0:
   version "3.0.1"
   resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
   integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=
@@ -5126,7 +4932,7 @@ strip-eof@^1.0.0:
   resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
   integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=
 
[email protected], strip-json-comments@~2.0.1:
[email protected]:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
   integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo=
@@ -5189,19 +4995,6 @@ tapable@^1.0.0, tapable@^1.1.3:
   resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2"
   integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==
 
-tar@^4.4.2:
-  version "4.4.13"
-  resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525"
-  integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==
-  dependencies:
-    chownr "^1.1.1"
-    fs-minipass "^1.2.5"
-    minipass "^2.8.6"
-    minizlib "^1.2.1"
-    mkdirp "^0.5.0"
-    safe-buffer "^5.1.2"
-    yallist "^3.0.3"
-
 terser-webpack-plugin@^1.4.3:
   version "1.4.3"
   resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.3.tgz#5ecaf2dbdc5fb99745fd06791f46fc9ddb1c9a7c"
@@ -5645,7 +5438,7 @@ which@^2.0.1:
   dependencies:
     isexe "^2.0.0"
 
[email protected], wide-align@^1.1.0:
[email protected]:
   version "1.1.3"
   resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457"
   integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==
@@ -5726,7 +5519,7 @@ yallist@^2.1.2:
   resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
   integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=
 
-yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3:
+yallist@^3.0.2:
   version "3.1.1"
   resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
   integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است