Przeglądaj źródła

Refactoring of JavaSriptObfuscatorCLI class

sanex3339 7 lat temu
rodzic
commit
bdb5aaebd8

Plik diff jest za duży
+ 0 - 0
dist/index.js


+ 2 - 2
package.json

@@ -57,12 +57,12 @@
     "babel-loader": "7.1.1",
     "babel-plugin-array-includes": "2.0.3",
     "babel-preset-es2015": "6.24.1",
-    "chai": "4.1.0",
+    "chai": "4.1.1",
     "coveralls": "2.13.1",
     "istanbul": "1.1.0-alpha.1",
     "mocha": "3.5.0",
     "pre-commit": "1.2.2",
-    "sinon": "2.4.1",
+    "sinon": "3.0.0",
     "ts-node": "3.3.0",
     "tslint": "5.5.0",
     "tslint-eslint-rules": "4.1.1",

+ 4 - 1
src/JavaScriptObfuscator.ts

@@ -35,6 +35,9 @@ export class JavaScriptObfuscator {
      * @param {string[]} argv
      */
     public static runCLI (argv: string[]): void {
-        new JavaScriptObfuscatorCLI(argv).run();
+        const javaScriptObfuscatorCLI: JavaScriptObfuscatorCLI = new JavaScriptObfuscatorCLI(argv);
+
+        javaScriptObfuscatorCLI.initialize();
+        javaScriptObfuscatorCLI.run();
     }
 }

+ 48 - 37
src/cli/JavaScriptObfuscatorCLI.ts

@@ -1,13 +1,18 @@
 import * as commander from 'commander';
 import * as path from 'path';
 
+import { TInputCLIOptions } from '../types/options/TInputCLIOptions';
 import { TInputOptions } from '../types/options/TInputOptions';
 import { TObject } from '../types/TObject';
 
+import { IInitializable } from '../interfaces/IInitializable';
 import { IObfuscationResult } from '../interfaces/IObfuscationResult';
 
+import { initializable } from '../decorators/Initializable';
+
 import { DEFAULT_PRESET } from '../options/presets/Default';
 
+import { ArraySanitizer } from './sanitizers/ArraySanitizer';
 import { BooleanSanitizer } from './sanitizers/BooleanSanitizer';
 import { SourceMapModeSanitizer } from './sanitizers/SourceMapModeSanitizer';
 import { StringArrayEncodingSanitizer } from './sanitizers/StringArrayEncodingSanitizer';
@@ -15,7 +20,7 @@ import { StringArrayEncodingSanitizer } from './sanitizers/StringArrayEncodingSa
 import { CLIUtils } from './utils/CLIUtils';
 import { JavaScriptObfuscator } from '../JavaScriptObfuscator';
 
-export class JavaScriptObfuscatorCLI {
+export class JavaScriptObfuscatorCLI implements IInitializable {
     /**
      * @type {string[]}
      */
@@ -29,16 +34,25 @@ export class JavaScriptObfuscatorCLI {
     /**
      * @type {commander.CommanderStatic}
      */
+    @initializable()
     private commands: commander.CommanderStatic;
 
+    /**
+     * @type {TInputCLIOptions}
+     */
+    @initializable()
+    private inputCLIOptions: TInputCLIOptions;
+
     /**
      * @type {string}
      */
+    @initializable()
     private inputPath: string;
 
     /**
      * @type {string}
      */
+    @initializable()
     private sourceCode: string = '';
 
     /**
@@ -46,21 +60,18 @@ export class JavaScriptObfuscatorCLI {
      */
     constructor (argv: string[]) {
         this.rawArguments = argv;
-        this.arguments = this.rawArguments.slice(2);
-
-        this.commands = <commander.CommanderStatic>(new commander.Command());
+        this.arguments = argv.slice(2);
     }
 
     /**
      * @param {TObject} options
      * @returns {TInputOptions}
      */
-    private static sanitizeOptions (options: TObject): TInputOptions {
+    private static filterOptions (options: TObject): TInputOptions {
         const filteredOptions: TInputOptions = {};
-        const availableOptions: string[] = Object.keys(DEFAULT_PRESET);
 
         for (const option in options) {
-            if (!options.hasOwnProperty(option) || !availableOptions.includes(option)) {
+            if (!options.hasOwnProperty(option) || options[option] === undefined) {
                 continue;
             }
 
@@ -70,46 +81,50 @@ export class JavaScriptObfuscatorCLI {
         return filteredOptions;
     }
 
-    public run (): void {
+    public initialize (): void {
+        this.inputPath = this.arguments[0] || '';
+        this.commands = <commander.CommanderStatic>(new commander.Command());
+
         this.configureCommands();
         this.configureHelp();
 
-        if (!this.arguments.length || this.arguments.includes('--help')) {
-            this.commands.outputHelp();
+        this.inputCLIOptions = this.commands.opts();
+    }
 
-            return;
-        }
+    public run (): void {
+        const canShowHelp: boolean = !this.arguments.length || this.arguments.includes('--help');
 
-        this.inputPath = this.arguments[0];
-        CLIUtils.validateInputPath(this.inputPath);
+        if (canShowHelp) {
+            return this.commands.outputHelp();
+        }
 
-        this.getData();
-        this.processData();
+        this.sourceCode = CLIUtils.readSourceCode(this.inputPath);
+        this.processSourceCode();
     }
 
     /**
      * @returns {TInputOptions}
      */
     private buildOptions (): TInputOptions {
-        const inputOptions: TInputOptions = JavaScriptObfuscatorCLI.sanitizeOptions(this.commands);
-        const configFileLocation: string = this.commands.config
-            ? path.resolve(this.commands.config, '.')
-            : '';
-        const configFileOptions: TInputOptions = configFileLocation
-            ? JavaScriptObfuscatorCLI.sanitizeOptions(CLIUtils.getUserConfig(configFileLocation))
-            : {};
+        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) : {};
 
         return {
             ...DEFAULT_PRESET,
             ...configFileOptions,
-            ...inputOptions
+            ...inputCLIOptions
         };
     }
 
     private configureCommands (): void {
         this.commands
-            .version(CLIUtils.getPackageConfig().version, '-v, --version')
             .usage('<inputPath> [options]')
+            .version(
+                CLIUtils.getPackageConfig().version,
+                '-v, --version'
+            )
             .option(
                 '-o, --output <path>',
                 'Output path for obfuscated code'
@@ -161,7 +176,7 @@ export class JavaScriptObfuscatorCLI {
             .option(
                 '--domainLock <list>',
                 'Blocks the execution of the code in domains that do not match the passed RegExp patterns (comma separated)',
-                (value: string) => value.split(',')
+                ArraySanitizer
             )
             .option(
                 '--log <boolean>', 'Enables logging of the information to the console',
@@ -174,7 +189,7 @@ export class JavaScriptObfuscatorCLI {
             .option(
                 '--reservedNames <list>',
                 'Disable obfuscation of variable names, function names and names of function parameters that match the passed RegExp patterns (comma separated)',
-                (value: string) => value.split(',')
+                ArraySanitizer
             )
             .option(
                 '--renameGlobals <boolean>', 'Allows to enable obfuscation of global variable and function names with declaration.',
@@ -244,18 +259,14 @@ export class JavaScriptObfuscatorCLI {
         });
     }
 
-    private getData (): void {
-        this.sourceCode = CLIUtils.readFile(this.inputPath);
-    }
-
-    private processData (): void {
+    private processSourceCode (): void {
         const options: TInputOptions = this.buildOptions();
-        const outputCodePath: string = CLIUtils.getOutputCodePath(this.commands.output, this.inputPath);
+        const outputCodePath: string = CLIUtils.getOutputCodePath(this.inputCLIOptions.output, this.inputPath);
 
         if (options.sourceMap) {
-            this.processDataWithSourceMap(outputCodePath, options);
+            this.processSourceCodeWithSourceMap(outputCodePath, options);
         } else {
-            this.processDataWithoutSourceMap(outputCodePath, options);
+            this.processSourceCodeWithoutSourceMap(outputCodePath, options);
         }
     }
 
@@ -263,7 +274,7 @@ export class JavaScriptObfuscatorCLI {
      * @param {string} outputCodePath
      * @param {TInputOptions} options
      */
-    private processDataWithoutSourceMap (outputCodePath: string, options: TInputOptions): void {
+    private processSourceCodeWithoutSourceMap (outputCodePath: string, options: TInputOptions): void {
         const obfuscatedCode: string = JavaScriptObfuscator.obfuscate(this.sourceCode, options).getObfuscatedCode();
 
         CLIUtils.writeFile(outputCodePath, obfuscatedCode);
@@ -273,7 +284,7 @@ export class JavaScriptObfuscatorCLI {
      * @param {string} outputCodePath
      * @param {TInputOptions} options
      */
-    private processDataWithSourceMap (outputCodePath: string, options: TInputOptions): void {
+    private processSourceCodeWithSourceMap (outputCodePath: string, options: TInputOptions): void {
         const outputSourceMapPath: string = CLIUtils.getOutputSourceMapPath(
             outputCodePath,
             options.sourceMapFileName || ''

+ 9 - 0
src/cli/sanitizers/ArraySanitizer.ts

@@ -0,0 +1,9 @@
+import { TCLISanitizer } from '../../types/cli/TCLISanitizer';
+
+/**
+ * @param {string} value
+ * @returns {string[]}
+ */
+export const ArraySanitizer: TCLISanitizer = (value: string): string[] => {
+    return value.split(',').map((string: string) => string.trim());
+};

+ 2 - 2
src/cli/sanitizers/SourceMapModeSanitizer.ts

@@ -9,8 +9,8 @@ import { SourceMapMode } from '../../enums/SourceMapMode';
 export const SourceMapModeSanitizer: TCLISanitizer = (value: string): string => {
     const availableMode: boolean = Object
         .keys(SourceMapMode)
-        .some((key: string): boolean => {
-            return SourceMapMode[<any>key] === value;
+        .some((key: any): boolean => {
+            return SourceMapMode[key] === value;
         });
 
     if (!availableMode) {

+ 6 - 11
src/cli/utils/CLIUtils.ts

@@ -24,14 +24,14 @@ export class CLIUtils {
      * @param {string} inputPath
      * @returns {string}
      */
-    public static getOutputCodePath (outputPath: string, inputPath: string): string {
+    public static getOutputCodePath (outputPath: string|undefined, inputPath: string): string {
         if (outputPath) {
             return outputPath;
         }
 
         return inputPath
             .split('.')
-            .map<string>((value: string, index: number) => {
+            .map((value: string, index: number) => {
                 return index === 0 ? `${value}-obfuscated` : value;
             })
             .join('.');
@@ -62,7 +62,7 @@ export class CLIUtils {
      * @returns {IPackageConfig}
      */
     public static getPackageConfig (): IPackageConfig {
-        return <IPackageConfig>JSON.parse(
+        return JSON.parse(
             fs.readFileSync(
                 path.join(
                     path.dirname(
@@ -111,14 +111,7 @@ export class CLIUtils {
      * @param {string} inputPath
      * @returns {string}
      */
-    public static readFile (inputPath: string): string {
-        return fs.readFileSync(inputPath, CLIUtils.encoding);
-    }
-
-    /**
-     * @param {string} inputPath
-     */
-    public static validateInputPath (inputPath: string): void {
+    public static readSourceCode (inputPath: string): string {
         if (!CLIUtils.isFilePath(inputPath)) {
             throw new ReferenceError(`Given input path must be a valid file path`);
         }
@@ -126,6 +119,8 @@ export class CLIUtils {
         if (!CLIUtils.availableInputExtensions.includes(path.extname(inputPath))) {
             throw new ReferenceError(`Input file must have .js extension`);
         }
+
+        return fs.readFileSync(inputPath, CLIUtils.encoding);
     }
 
     /**

+ 7 - 0
src/interfaces/options/ICLIOptions.d.ts

@@ -0,0 +1,7 @@
+import { IOptions } from './IOptions';
+
+export interface ICLIOptions extends IOptions {
+    readonly config: string;
+    readonly output: string;
+    readonly version: string;
+}

+ 5 - 0
src/types/options/TInputCLIOptions.d.ts

@@ -0,0 +1,5 @@
+import { TObject } from '../TObject';
+
+import { ICLIOptions } from '../../interfaces/options/ICLIOptions';
+
+export type TInputCLIOptions = Partial<Pick<ICLIOptions, keyof ICLIOptions>> & TObject;

+ 1 - 0
test/index.spec.ts

@@ -5,6 +5,7 @@ require('source-map-support').install();
 /**
  * Unit tests
  */
+import './unit-tests/cli/sanitizers/ArraySanitizer.spec';
 import './unit-tests/cli/sanitizers/BooleanSanitizer.spec';
 import './unit-tests/cli/sanitizers/SourceMapModeSanitizer.spec';
 import './unit-tests/cli/sanitizers/StringArrayEncodingSanitizer.spec';

+ 38 - 0
test/unit-tests/cli/sanitizers/ArraySanitizer.spec.ts

@@ -0,0 +1,38 @@
+import { assert } from 'chai';
+
+import { ArraySanitizer } from '../../../../src/cli/sanitizers/ArraySanitizer';
+
+
+describe('ArraySanitizer', () => {
+    describe('ArraySanitizer: TCLISanitizer = (value: string): string[]', () => {
+        describe('variant #1: input value `foo`', () => {
+            const inputValue: string = 'foo';
+            const expectedValue: string[] = ['foo'];
+
+            let value: string[];
+
+            before(() => {
+                value = ArraySanitizer(inputValue);
+            });
+
+            it('should sanitize value', () => {
+                assert.deepEqual(value, expectedValue);
+            });
+        });
+
+        describe('variant #2: input value `foo, bar`', () => {
+            const inputValue: string = 'foo, bar';
+            const expectedValue: string[] = ['foo', 'bar'];
+
+            let value: string[];
+
+            before(() => {
+                value = ArraySanitizer(inputValue);
+            });
+
+            it('should sanitize value', () => {
+                assert.deepEqual(value, expectedValue);
+            });
+        });
+    });
+});

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

@@ -87,20 +87,20 @@ describe('CLIUtils', () => {
         });
     });
 
-    describe('validateInputPath (inputPath: string): void', () => {
+    describe('readSourceCode (inputPath: string): void', () => {
         describe('`inputPath` is a valid path', () => {
             const tmpFileName: string = 'test.js';
             const inputPath: string = `${tmpDir}/${tmpFileName}`;
 
-            let testFunc: () => void;
+            let result: string;
 
             before(() => {
                 fs.writeFileSync(inputPath, fileContent);
-                testFunc = () => CLIUtils.validateInputPath(inputPath);
+                result = CLIUtils.readSourceCode(inputPath);
             });
 
-            it('shouldn\'t throw an error if `inputPath` is a valid path', () => {
-                assert.doesNotThrow(testFunc, ReferenceError);
+            it('should return content of file', () => {
+                assert.equal(result, fileContent);
             });
 
             after(() => {
@@ -115,7 +115,7 @@ describe('CLIUtils', () => {
             let testFunc: () => void;
 
             before(() => {
-                testFunc = () => CLIUtils.validateInputPath(inputPath);
+                testFunc = () => CLIUtils.readSourceCode(inputPath);
             });
 
             it('should throw an error if `inputPath` is not a valid path', () => {
@@ -131,7 +131,7 @@ describe('CLIUtils', () => {
 
             before(() => {
                 fs.writeFileSync(inputPath, fileContent);
-                testFunc = () => CLIUtils.validateInputPath(inputPath);
+                testFunc = () => CLIUtils.readSourceCode(inputPath);
             });
 
             it('should throw an error if `inputPath` is a file name has invalid extension', () => {

+ 27 - 13
yarn.lock

@@ -56,11 +56,7 @@
   version "2.2.41"
   resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-2.2.41.tgz#e27cf0817153eb9f2713b2d3f6c68f1e1c3ca608"
 
-"@types/node@*":
-  version "8.0.17"
-  resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.17.tgz#677bc8c118cfb76013febb62ede1f31d2c7222a1"
-
-"@types/[email protected]":
+"@types/node@*", "@types/[email protected]":
   version "8.0.19"
   resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.19.tgz#e46e2b0243de7d03f15b26b45c59ebb84f657a4e"
 
@@ -920,9 +916,9 @@ center-align@^0.1.1:
     align-text "^0.1.3"
     lazy-cache "^1.0.3"
 
[email protected].0:
-  version "4.1.0"
-  resolved "https://registry.yarnpkg.com/chai/-/chai-4.1.0.tgz#331a0391b55c3af8740ae9c3b7458bc1c3805e6d"
[email protected].1:
+  version "4.1.1"
+  resolved "https://registry.yarnpkg.com/chai/-/chai-4.1.1.tgz#66e21279e6f3c6415ff8231878227900e2171b39"
   dependencies:
     assertion-error "^1.0.1"
     check-error "^1.0.1"
@@ -1693,7 +1689,7 @@ form-data@~2.1.1:
     combined-stream "^1.0.5"
     mime-types "^2.1.12"
 
[email protected]:
[email protected], formatio@^1.2.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/formatio/-/formatio-1.2.0.tgz#f3b2167d9068c4698a8d51f4f760a39a54d818eb"
   dependencies:
@@ -2353,6 +2349,10 @@ jsprim@^1.2.2:
     json-schema "0.2.3"
     verror "1.3.6"
 
+just-extend@^1.1.22:
+  version "1.1.22"
+  resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-1.1.22.tgz#3330af756cab6a542700c64b2e4e4aa062d52fff"
+
 kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0:
   version "3.2.2"
   resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64"
@@ -2490,6 +2490,10 @@ lolex@^1.6.0:
   version "1.6.0"
   resolved "https://registry.yarnpkg.com/lolex/-/lolex-1.6.0.tgz#3a9a0283452a47d7439e72731b9e07d7386e49f6"
 
+lolex@^2.1.2:
+  version "2.1.2"
+  resolved "https://registry.yarnpkg.com/lolex/-/lolex-2.1.2.tgz#2694b953c9ea4d013e5b8bfba891c991025b2629"
+
 longest@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097"
@@ -2690,6 +2694,15 @@ native-promise-only@^0.8.1:
   version "0.8.1"
   resolved "https://registry.yarnpkg.com/native-promise-only/-/native-promise-only-0.8.1.tgz#20a318c30cb45f71fe7adfbf7b21c99c1472ef11"
 
+nise@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/nise/-/nise-1.0.1.tgz#0da92b10a854e97c0f496f6c2845a301280b3eef"
+  dependencies:
+    formatio "^1.2.0"
+    just-extend "^1.1.22"
+    lolex "^1.6.0"
+    path-to-regexp "^1.7.0"
+
 [email protected]:
   version "1.6.3"
   resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.6.3.tgz#dc234edd6489982d58e8f0db4f695029abcd8c04"
@@ -3406,14 +3419,15 @@ signal-exit@^3.0.0, signal-exit@^3.0.2:
   version "3.0.2"
   resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
 
-sinon@2.4.1:
-  version "2.4.1"
-  resolved "https://registry.yarnpkg.com/sinon/-/sinon-2.4.1.tgz#021fd64b54cb77d9d2fb0d43cdedfae7629c3a36"
+sinon@3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/sinon/-/sinon-3.0.0.tgz#f6919755c8c705e0b4ae977e8351bbcbaf6d91de"
   dependencies:
     diff "^3.1.0"
     formatio "1.2.0"
-    lolex "^1.6.0"
+    lolex "^2.1.2"
     native-promise-only "^0.8.1"
+    nise "^1.0.1"
     path-to-regexp "^1.7.0"
     samsam "^1.1.3"
     text-encoding "0.6.4"

Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików