Forráskód Böngészése

Refactoring of CLI utils

sanex3339 5 éve
szülő
commit
0fe1c15f15

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 0 - 0
dist/index.cli.js


+ 5 - 5
package.json

@@ -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",

+ 69 - 51
src/cli/JavaScriptObfuscatorCLI.ts

@@ -21,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 {
@@ -67,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
      */
@@ -91,8 +104,6 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
         const inputFileName: string = path.basename(inputCodePath);
         const inputFilePath: string = inputCodePath;
 
-        console.log(inputFilePath, inputFileName);
-
         return {
             ...DEFAULT_PRESET,
             ...configFileOptions,
@@ -122,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());
@@ -174,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 {
@@ -185,8 +160,7 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
             return;
         }
 
-        const sourceCodeData: IFileData[] = new SourceCodeReader(this.inputCLIOptions)
-            .readSourceCode(this.inputPath);
+        const sourceCodeData: IFileData[] = this.sourceCodeReader.readSourceCode();
 
         this.processSourceCodeData(sourceCodeData);
     }
@@ -390,7 +364,7 @@ export class JavaScriptObfuscatorCLI implements IInitializable {
      */
     private processSourceCodeData (sourceCodeData: IFileData[]): void {
         sourceCodeData.forEach(({ filePath, content }: IFileData, index: number) => {
-            const outputCodePath: string = CLIUtils.getOutputCodePath(filePath, this.inputCLIOptions.output);
+            const outputCodePath: string = this.obfuscatedCodeWriter.getOutputCodePath(filePath);
 
             this.processSourceCode(content, filePath, outputCodePath, index);
         });
@@ -425,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 - 68
src/cli/utils/CLIUtils.ts

@@ -1,62 +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
-     * @param {string | null} baseOutputPath
-     * @returns {string}
-     */
-    public static getOutputCodePath (inputPath: string, baseOutputPath?: string | null): string {
-        const normalizedBaseOutputPath: string | null = baseOutputPath
-            ? path.normalize(baseOutputPath)
-            : null;
-
-        if (!normalizedBaseOutputPath) {
-            return path
-                .normalize(inputPath)
-                .split(StringSeparator.Dot)
-                .map((value: string, index: number) => {
-                    return index === 0 ? `${value}${JavaScriptObfuscatorCLI.obfuscatedFilePrefix}` : value;
-                })
-                .join(StringSeparator.Dot);
-        }
-
-        const isDirectoryPath: boolean = path.extname(normalizedBaseOutputPath) === '';
-
-        return isDirectoryPath
-            ? path.join(normalizedBaseOutputPath, inputPath)
-            : normalizedBaseOutputPath;
-    }
-
-    /**
-     * @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}
@@ -76,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
+        });
+    }
+}

+ 70 - 41
src/cli/utils/SourceCodeReader.ts

@@ -19,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;
     }
 
@@ -74,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
      */
@@ -88,16 +118,34 @@ export class SourceCodeReader {
     }
 
     /**
-     * @param {string} inputPath
+     * @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): IFileData[] {
-        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
@@ -118,46 +166,27 @@ export class SourceCodeReader {
             .forEach((fileName: string) => {
                 const filePath: string = `${directoryPath}/${fileName}`;
 
-                if (SourceCodeReader.isDirectoryPath(filePath) && this.isValidDirectory(filePath)) {
+                if (
+                    SourceCodeReader.isDirectoryPath(filePath)
+                    && SourceCodeReader.isValidDirectory(filePath, this.options.exclude)
+                ) {
                     filesData.push(...this.readDirectoryRecursive(filePath));
-                } else if (SourceCodeReader.isFilePath(filePath) && this.isValidFile(filePath)) {
-                    const fileData: IFileData = this.readFile(filePath);
 
-                    filesData.push(fileData);
+                    return;
                 }
-            });
-
-        return filesData;
-    }
 
-    /**
-     * @param {string} filePath
-     * @returns {string}
-     */
-    private readFile (filePath: string): IFileData {
-        SourceCodeReader.logFilePath(filePath);
+                if (
+                    SourceCodeReader.isFilePath(filePath)
+                    && SourceCodeReader.isValidFile(filePath, this.options.exclude)
+                ) {
+                    const fileData: IFileData = SourceCodeReader.readFile(filePath);
 
-        return {
-            filePath,
-            content: 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;
     }
 }

+ 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);
+        });
+    });
+});

+ 70 - 43
test/unit-tests/cli/utils/SourceCodeReader.spec.ts

@@ -32,7 +32,7 @@ describe('SourceCodeReader', () => {
 
                 before(() => {
                     fs.writeFileSync(inputPath, fileContent);
-                    filesData = new SourceCodeReader({}).readSourceCode(inputPath);
+                    filesData = new SourceCodeReader(inputPath, {}).readSourceCode();
                 });
 
                 it('should return valid files data', () => {
@@ -51,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', () => {
@@ -67,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', () => {
@@ -92,9 +92,12 @@ describe('SourceCodeReader', () => {
 
                     before(() => {
                         fs.writeFileSync(inputPath, fileContent);
-                        filesData = new SourceCodeReader({
-                            exclude: ['**/foo.js']
-                        }).readSourceCode(inputPath);
+                        filesData = new SourceCodeReader(
+                            inputPath,
+                            {
+                                exclude: ['**/foo.js']
+                            }
+                        ).readSourceCode();
                     });
 
                     it('should return valid files data', () => {
@@ -115,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', () => {
@@ -137,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', () => {
@@ -159,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', () => {
@@ -205,7 +217,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', () => {
@@ -226,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', () => {
@@ -276,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', () => {
@@ -322,9 +334,12 @@ describe('SourceCodeReader', () => {
                         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', () => {
@@ -368,12 +383,15 @@ describe('SourceCodeReader', () => {
                             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', () => {
@@ -416,12 +434,15 @@ describe('SourceCodeReader', () => {
                             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', () => {
@@ -464,12 +485,15 @@ describe('SourceCodeReader', () => {
                             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', () => {
@@ -501,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', () => {
@@ -535,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];

+ 38 - 33
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"
@@ -1263,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"
@@ -1750,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"
@@ -1791,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"
@@ -1811,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"
@@ -4545,6 +4545,11 @@ 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"

Nem az összes módosított fájl került megjelenítésre, mert túl sok fájl változott