├── LICENSE ├── README.md ├── pics ├── before_and_after.png ├── console.jpg └── preview.jpg └── source ├── package-lock.json ├── package.json └── wsc.js /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 DosX 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![](pics/preview.jpg) 2 | 3 | # WebSafeCompiler (WSC) 4 | **WebSafeCompiler** (WSC) is an advanced utility (websites compiler) designed for the optimization, minification, and obfuscation (if you need it) of web applications and websites using `Node.js`. It enhances your web assets by reducing file sizes or providing durable protection against reverse engineering, ensuring your code is deployment-ready and secure. 5 | 6 | > [!NOTE] 7 | > Suitable for ***.github.io** sites 8 | 9 | ## 🚀 Little about 10 | To leverage the full potential of **WebSafeCompiler**, execute the following command in your terminal: 11 | ```bash 12 | node wsc.js [--map] [--smart] [--drm] 13 | ``` 14 | 15 | ### Arguments & options: 16 | * ``: Directory containing the source files to be processed. 17 | * ``: Directory where the optimized and obfuscated files will be output. 18 | * `-m, --map`: Creates a **sitemap.xml** in the output directory for better SEO 19 | * `-s, --smart`: Automatically detects minified files and skips them. This includes JS and CSS files. 20 | * `-d, --drm`: Enables code obfuscation (DRM protection) to secure your source code against unauthorized analysis. 21 | * **🚫 disabled**: The utility focuses on optimizing your website’s files, ensuring they are lightweight and efficient. 22 | * **✅ enabled**: The utility emphasizes the protection of your intellectual property by applying rigorous obfuscation techniques to your code. 23 | * **HTML obfuscation**: HTML files are also obfuscated by adding non-functional random attributes and classes, making it difficult to reverse engineer while maintaining the visual and functional integrity of your web pages. 24 | * **JavaScript obfuscation**: Files using JavaScript will go through several stages of obfuscation, including adding unused code and encrypting strings. 25 | * `-h, --help`: Displays the help message with detailed usage instructions. 26 | * `-v, --version`: Outputs the current version of WebSafeCompiler. 27 | 28 | ### 👨🏼‍💻 Usage example: 29 | ```bash 30 | node wsc.js "/path/to/source" "/path/to/output" --drm --smart 31 | ``` 32 | 33 | This command will process all files within the specified source directory, optimize them, and, if the obfuscation flag is enabled, protect the code from unauthorized access or tampering. The output files will be ready for deployment in your web environment. 34 | 35 | ![](pics/before_and_after.png) 36 | 37 | ## 📚 Libraries used 38 | **WebSafeCompiler** uses the following libraries to work with JavaScript codes: 39 | * **[uglify-js](https://www.npmjs.com/package/uglify-js)**: Provides sophisticated JavaScript preprocessing and minification, compressing your code without sacrificing functionality. 40 | * **[javascript-obfuscator](https://www.npmjs.com/package/javascript-obfuscator)**: Applies advanced techniques to protect your JavaScript code by obfuscating it, making it significantly harder for attackers to reverse-engineer. 41 | 42 | ## 🛠️ How to install? 43 | To get started with **WebSafeCompiler**, you'll need to have [Node.js](https://nodejs.org) installed on your system. Follow these steps to install the required packages: 44 | 45 | 1. **Install Node.js**: Download and install Node.js from [Node.js official website](https://nodejs.org). Follow the installation instructions for your operating system. 46 | 47 | 2. **Clone the repository**: If you haven't already, clone the repository to your local machine: 48 | ```bash 49 | git clone 50 | cd /source 51 | ``` 52 | 53 | 3. **Install dependencies**: Navigate to the project directory and install the necessary npm packages: 54 | ```bash 55 | npm install 56 | ``` 57 | 58 | 4. **Done! You can use WSC.** 59 | 60 | ## 📜 License 61 | This project is licensed under the MIT License. For more details, please refer to the [LICENSE](./LICENSE) file. 62 | -------------------------------------------------------------------------------- /pics/before_and_after.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DosX-dev/WebSafeCompiler/a9d92896c847842923a6f1c97d99841e29d32ff5/pics/before_and_after.png -------------------------------------------------------------------------------- /pics/console.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DosX-dev/WebSafeCompiler/a9d92896c847842923a6f1c97d99841e29d32ff5/pics/console.jpg -------------------------------------------------------------------------------- /pics/preview.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DosX-dev/WebSafeCompiler/a9d92896c847842923a6f1c97d99841e29d32ff5/pics/preview.jpg -------------------------------------------------------------------------------- /source/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "WebSafeCompiler", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "WebSafeCompiler", 9 | "version": "1.0.0", 10 | "license": "MIT", 11 | "dependencies": { 12 | "javascript-obfuscator": "^4.0.0", 13 | "uglify-js": "^3.17.0" 14 | }, 15 | "bin": { 16 | "wsc": "wsc.js" 17 | }, 18 | "engines": { 19 | "node": ">=14.0.0" 20 | } 21 | }, 22 | "node_modules/@javascript-obfuscator/escodegen": { 23 | "version": "2.3.0", 24 | "resolved": "https://registry.npmjs.org/@javascript-obfuscator/escodegen/-/escodegen-2.3.0.tgz", 25 | "integrity": "sha512-QVXwMIKqYMl3KwtTirYIA6gOCiJ0ZDtptXqAv/8KWLG9uQU2fZqTVy7a/A5RvcoZhbDoFfveTxuGxJ5ibzQtkw==", 26 | "dependencies": { 27 | "@javascript-obfuscator/estraverse": "^5.3.0", 28 | "esprima": "^4.0.1", 29 | "esutils": "^2.0.2", 30 | "optionator": "^0.8.1" 31 | }, 32 | "engines": { 33 | "node": ">=6.0" 34 | }, 35 | "optionalDependencies": { 36 | "source-map": "~0.6.1" 37 | } 38 | }, 39 | "node_modules/@javascript-obfuscator/estraverse": { 40 | "version": "5.4.0", 41 | "resolved": "https://registry.npmjs.org/@javascript-obfuscator/estraverse/-/estraverse-5.4.0.tgz", 42 | "integrity": "sha512-CZFX7UZVN9VopGbjTx4UXaXsi9ewoM1buL0kY7j1ftYdSs7p2spv9opxFjHlQ/QGTgh4UqufYqJJ0WKLml7b6w==", 43 | "engines": { 44 | "node": ">=4.0" 45 | } 46 | }, 47 | "node_modules/@types/minimatch": { 48 | "version": "3.0.5", 49 | "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", 50 | "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==" 51 | }, 52 | "node_modules/@types/validator": { 53 | "version": "13.12.0", 54 | "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.12.0.tgz", 55 | "integrity": "sha512-nH45Lk7oPIJ1RVOF6JgFI6Dy0QpHEzq4QecZhvguxYPDwT8c93prCMqAtiIttm39voZ+DDR+qkNnMpJmMBRqag==" 56 | }, 57 | "node_modules/acorn": { 58 | "version": "8.8.2", 59 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", 60 | "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", 61 | "bin": { 62 | "acorn": "bin/acorn" 63 | }, 64 | "engines": { 65 | "node": ">=0.4.0" 66 | } 67 | }, 68 | "node_modules/ansi-styles": { 69 | "version": "4.3.0", 70 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 71 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 72 | "dependencies": { 73 | "color-convert": "^2.0.1" 74 | }, 75 | "engines": { 76 | "node": ">=8" 77 | }, 78 | "funding": { 79 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 80 | } 81 | }, 82 | "node_modules/array-differ": { 83 | "version": "3.0.0", 84 | "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz", 85 | "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==", 86 | "engines": { 87 | "node": ">=8" 88 | } 89 | }, 90 | "node_modules/array-union": { 91 | "version": "2.1.0", 92 | "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", 93 | "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", 94 | "engines": { 95 | "node": ">=8" 96 | } 97 | }, 98 | "node_modules/arrify": { 99 | "version": "2.0.1", 100 | "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", 101 | "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", 102 | "engines": { 103 | "node": ">=8" 104 | } 105 | }, 106 | "node_modules/assert": { 107 | "version": "2.0.0", 108 | "resolved": "https://registry.npmjs.org/assert/-/assert-2.0.0.tgz", 109 | "integrity": "sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A==", 110 | "dependencies": { 111 | "es6-object-assign": "^1.1.0", 112 | "is-nan": "^1.2.1", 113 | "object-is": "^1.0.1", 114 | "util": "^0.12.0" 115 | } 116 | }, 117 | "node_modules/available-typed-arrays": { 118 | "version": "1.0.7", 119 | "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", 120 | "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", 121 | "dependencies": { 122 | "possible-typed-array-names": "^1.0.0" 123 | }, 124 | "engines": { 125 | "node": ">= 0.4" 126 | }, 127 | "funding": { 128 | "url": "https://github.com/sponsors/ljharb" 129 | } 130 | }, 131 | "node_modules/balanced-match": { 132 | "version": "1.0.2", 133 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 134 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" 135 | }, 136 | "node_modules/brace-expansion": { 137 | "version": "1.1.11", 138 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 139 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 140 | "dependencies": { 141 | "balanced-match": "^1.0.0", 142 | "concat-map": "0.0.1" 143 | } 144 | }, 145 | "node_modules/buffer-from": { 146 | "version": "1.1.2", 147 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", 148 | "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" 149 | }, 150 | "node_modules/call-bind": { 151 | "version": "1.0.7", 152 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", 153 | "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", 154 | "dependencies": { 155 | "es-define-property": "^1.0.0", 156 | "es-errors": "^1.3.0", 157 | "function-bind": "^1.1.2", 158 | "get-intrinsic": "^1.2.4", 159 | "set-function-length": "^1.2.1" 160 | }, 161 | "engines": { 162 | "node": ">= 0.4" 163 | }, 164 | "funding": { 165 | "url": "https://github.com/sponsors/ljharb" 166 | } 167 | }, 168 | "node_modules/chalk": { 169 | "version": "4.1.2", 170 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", 171 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 172 | "dependencies": { 173 | "ansi-styles": "^4.1.0", 174 | "supports-color": "^7.1.0" 175 | }, 176 | "engines": { 177 | "node": ">=10" 178 | }, 179 | "funding": { 180 | "url": "https://github.com/chalk/chalk?sponsor=1" 181 | } 182 | }, 183 | "node_modules/chance": { 184 | "version": "1.1.9", 185 | "resolved": "https://registry.npmjs.org/chance/-/chance-1.1.9.tgz", 186 | "integrity": "sha512-TfxnA/DcZXRTA4OekA2zL9GH8qscbbl6X0ZqU4tXhGveVY/mXWvEQLt5GwZcYXTEyEFflVtj+pG8nc8EwSm1RQ==" 187 | }, 188 | "node_modules/char-regex": { 189 | "version": "1.0.2", 190 | "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", 191 | "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", 192 | "engines": { 193 | "node": ">=10" 194 | } 195 | }, 196 | "node_modules/charenc": { 197 | "version": "0.0.2", 198 | "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", 199 | "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==", 200 | "engines": { 201 | "node": "*" 202 | } 203 | }, 204 | "node_modules/class-validator": { 205 | "version": "0.14.1", 206 | "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.14.1.tgz", 207 | "integrity": "sha512-2VEG9JICxIqTpoK1eMzZqaV+u/EiwEJkMGzTrZf6sU/fwsnOITVgYJ8yojSy6CaXtO9V0Cc6ZQZ8h8m4UBuLwQ==", 208 | "dependencies": { 209 | "@types/validator": "^13.11.8", 210 | "libphonenumber-js": "^1.10.53", 211 | "validator": "^13.9.0" 212 | } 213 | }, 214 | "node_modules/color-convert": { 215 | "version": "2.0.1", 216 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 217 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 218 | "dependencies": { 219 | "color-name": "~1.1.4" 220 | }, 221 | "engines": { 222 | "node": ">=7.0.0" 223 | } 224 | }, 225 | "node_modules/color-name": { 226 | "version": "1.1.4", 227 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 228 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" 229 | }, 230 | "node_modules/commander": { 231 | "version": "10.0.0", 232 | "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.0.tgz", 233 | "integrity": "sha512-zS5PnTI22FIRM6ylNW8G4Ap0IEOyk62fhLSD0+uHRT9McRCLGpkVNvao4bjimpK/GShynyQkFFxHhwMcETmduA==", 234 | "engines": { 235 | "node": ">=14" 236 | } 237 | }, 238 | "node_modules/concat-map": { 239 | "version": "0.0.1", 240 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 241 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" 242 | }, 243 | "node_modules/crypt": { 244 | "version": "0.0.2", 245 | "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", 246 | "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==", 247 | "engines": { 248 | "node": "*" 249 | } 250 | }, 251 | "node_modules/deep-is": { 252 | "version": "0.1.4", 253 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", 254 | "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" 255 | }, 256 | "node_modules/define-data-property": { 257 | "version": "1.1.4", 258 | "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", 259 | "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", 260 | "dependencies": { 261 | "es-define-property": "^1.0.0", 262 | "es-errors": "^1.3.0", 263 | "gopd": "^1.0.1" 264 | }, 265 | "engines": { 266 | "node": ">= 0.4" 267 | }, 268 | "funding": { 269 | "url": "https://github.com/sponsors/ljharb" 270 | } 271 | }, 272 | "node_modules/define-properties": { 273 | "version": "1.2.1", 274 | "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", 275 | "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", 276 | "dependencies": { 277 | "define-data-property": "^1.0.1", 278 | "has-property-descriptors": "^1.0.0", 279 | "object-keys": "^1.1.1" 280 | }, 281 | "engines": { 282 | "node": ">= 0.4" 283 | }, 284 | "funding": { 285 | "url": "https://github.com/sponsors/ljharb" 286 | } 287 | }, 288 | "node_modules/es-define-property": { 289 | "version": "1.0.0", 290 | "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", 291 | "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", 292 | "dependencies": { 293 | "get-intrinsic": "^1.2.4" 294 | }, 295 | "engines": { 296 | "node": ">= 0.4" 297 | } 298 | }, 299 | "node_modules/es-errors": { 300 | "version": "1.3.0", 301 | "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", 302 | "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", 303 | "engines": { 304 | "node": ">= 0.4" 305 | } 306 | }, 307 | "node_modules/es6-object-assign": { 308 | "version": "1.1.0", 309 | "resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz", 310 | "integrity": "sha512-MEl9uirslVwqQU369iHNWZXsI8yaZYGg/D65aOgZkeyFJwHYSxilf7rQzXKI7DdDuBPrBXbfk3sl9hJhmd5AUw==" 311 | }, 312 | "node_modules/eslint-scope": { 313 | "version": "7.1.1", 314 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", 315 | "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", 316 | "dependencies": { 317 | "esrecurse": "^4.3.0", 318 | "estraverse": "^5.2.0" 319 | }, 320 | "engines": { 321 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 322 | } 323 | }, 324 | "node_modules/eslint-visitor-keys": { 325 | "version": "3.3.0", 326 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", 327 | "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", 328 | "engines": { 329 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0" 330 | } 331 | }, 332 | "node_modules/esprima": { 333 | "version": "4.0.1", 334 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 335 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", 336 | "bin": { 337 | "esparse": "bin/esparse.js", 338 | "esvalidate": "bin/esvalidate.js" 339 | }, 340 | "engines": { 341 | "node": ">=4" 342 | } 343 | }, 344 | "node_modules/esrecurse": { 345 | "version": "4.3.0", 346 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", 347 | "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", 348 | "dependencies": { 349 | "estraverse": "^5.2.0" 350 | }, 351 | "engines": { 352 | "node": ">=4.0" 353 | } 354 | }, 355 | "node_modules/estraverse": { 356 | "version": "5.3.0", 357 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", 358 | "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", 359 | "engines": { 360 | "node": ">=4.0" 361 | } 362 | }, 363 | "node_modules/esutils": { 364 | "version": "2.0.3", 365 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", 366 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", 367 | "engines": { 368 | "node": ">=0.10.0" 369 | } 370 | }, 371 | "node_modules/fast-deep-equal": { 372 | "version": "3.1.3", 373 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 374 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" 375 | }, 376 | "node_modules/fast-levenshtein": { 377 | "version": "2.0.6", 378 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 379 | "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" 380 | }, 381 | "node_modules/for-each": { 382 | "version": "0.3.3", 383 | "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", 384 | "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", 385 | "dependencies": { 386 | "is-callable": "^1.1.3" 387 | } 388 | }, 389 | "node_modules/function-bind": { 390 | "version": "1.1.2", 391 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", 392 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", 393 | "funding": { 394 | "url": "https://github.com/sponsors/ljharb" 395 | } 396 | }, 397 | "node_modules/get-intrinsic": { 398 | "version": "1.2.4", 399 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", 400 | "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", 401 | "dependencies": { 402 | "es-errors": "^1.3.0", 403 | "function-bind": "^1.1.2", 404 | "has-proto": "^1.0.1", 405 | "has-symbols": "^1.0.3", 406 | "hasown": "^2.0.0" 407 | }, 408 | "engines": { 409 | "node": ">= 0.4" 410 | }, 411 | "funding": { 412 | "url": "https://github.com/sponsors/ljharb" 413 | } 414 | }, 415 | "node_modules/gopd": { 416 | "version": "1.0.1", 417 | "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", 418 | "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", 419 | "dependencies": { 420 | "get-intrinsic": "^1.1.3" 421 | }, 422 | "funding": { 423 | "url": "https://github.com/sponsors/ljharb" 424 | } 425 | }, 426 | "node_modules/has-flag": { 427 | "version": "4.0.0", 428 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 429 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 430 | "engines": { 431 | "node": ">=8" 432 | } 433 | }, 434 | "node_modules/has-property-descriptors": { 435 | "version": "1.0.2", 436 | "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", 437 | "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", 438 | "dependencies": { 439 | "es-define-property": "^1.0.0" 440 | }, 441 | "funding": { 442 | "url": "https://github.com/sponsors/ljharb" 443 | } 444 | }, 445 | "node_modules/has-proto": { 446 | "version": "1.0.3", 447 | "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", 448 | "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", 449 | "engines": { 450 | "node": ">= 0.4" 451 | }, 452 | "funding": { 453 | "url": "https://github.com/sponsors/ljharb" 454 | } 455 | }, 456 | "node_modules/has-symbols": { 457 | "version": "1.0.3", 458 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 459 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", 460 | "engines": { 461 | "node": ">= 0.4" 462 | }, 463 | "funding": { 464 | "url": "https://github.com/sponsors/ljharb" 465 | } 466 | }, 467 | "node_modules/has-tostringtag": { 468 | "version": "1.0.2", 469 | "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", 470 | "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", 471 | "dependencies": { 472 | "has-symbols": "^1.0.3" 473 | }, 474 | "engines": { 475 | "node": ">= 0.4" 476 | }, 477 | "funding": { 478 | "url": "https://github.com/sponsors/ljharb" 479 | } 480 | }, 481 | "node_modules/hasown": { 482 | "version": "2.0.2", 483 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", 484 | "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", 485 | "dependencies": { 486 | "function-bind": "^1.1.2" 487 | }, 488 | "engines": { 489 | "node": ">= 0.4" 490 | } 491 | }, 492 | "node_modules/inherits": { 493 | "version": "2.0.4", 494 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 495 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 496 | }, 497 | "node_modules/inversify": { 498 | "version": "6.0.1", 499 | "resolved": "https://registry.npmjs.org/inversify/-/inversify-6.0.1.tgz", 500 | "integrity": "sha512-B3ex30927698TJENHR++8FfEaJGqoWOgI6ZY5Ht/nLUsFCwHn6akbwtnUAPCgUepAnTpe2qHxhDNjoKLyz6rgQ==" 501 | }, 502 | "node_modules/is-arguments": { 503 | "version": "1.1.1", 504 | "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", 505 | "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", 506 | "dependencies": { 507 | "call-bind": "^1.0.2", 508 | "has-tostringtag": "^1.0.0" 509 | }, 510 | "engines": { 511 | "node": ">= 0.4" 512 | }, 513 | "funding": { 514 | "url": "https://github.com/sponsors/ljharb" 515 | } 516 | }, 517 | "node_modules/is-buffer": { 518 | "version": "1.1.6", 519 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", 520 | "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" 521 | }, 522 | "node_modules/is-callable": { 523 | "version": "1.2.7", 524 | "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", 525 | "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", 526 | "engines": { 527 | "node": ">= 0.4" 528 | }, 529 | "funding": { 530 | "url": "https://github.com/sponsors/ljharb" 531 | } 532 | }, 533 | "node_modules/is-generator-function": { 534 | "version": "1.0.10", 535 | "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", 536 | "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", 537 | "dependencies": { 538 | "has-tostringtag": "^1.0.0" 539 | }, 540 | "engines": { 541 | "node": ">= 0.4" 542 | }, 543 | "funding": { 544 | "url": "https://github.com/sponsors/ljharb" 545 | } 546 | }, 547 | "node_modules/is-nan": { 548 | "version": "1.3.2", 549 | "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", 550 | "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", 551 | "dependencies": { 552 | "call-bind": "^1.0.0", 553 | "define-properties": "^1.1.3" 554 | }, 555 | "engines": { 556 | "node": ">= 0.4" 557 | }, 558 | "funding": { 559 | "url": "https://github.com/sponsors/ljharb" 560 | } 561 | }, 562 | "node_modules/is-typed-array": { 563 | "version": "1.1.13", 564 | "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", 565 | "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", 566 | "dependencies": { 567 | "which-typed-array": "^1.1.14" 568 | }, 569 | "engines": { 570 | "node": ">= 0.4" 571 | }, 572 | "funding": { 573 | "url": "https://github.com/sponsors/ljharb" 574 | } 575 | }, 576 | "node_modules/javascript-obfuscator": { 577 | "version": "4.1.1", 578 | "resolved": "https://registry.npmjs.org/javascript-obfuscator/-/javascript-obfuscator-4.1.1.tgz", 579 | "integrity": "sha512-gt+KZpIIrrxXHEQGD8xZrL8mTRwRY0U76/xz/YX0gZdPrSqQhT/c7dYLASlLlecT3r+FxE7je/+C0oLnTDCx4A==", 580 | "hasInstallScript": true, 581 | "dependencies": { 582 | "@javascript-obfuscator/escodegen": "2.3.0", 583 | "@javascript-obfuscator/estraverse": "5.4.0", 584 | "acorn": "8.8.2", 585 | "assert": "2.0.0", 586 | "chalk": "4.1.2", 587 | "chance": "1.1.9", 588 | "class-validator": "0.14.1", 589 | "commander": "10.0.0", 590 | "eslint-scope": "7.1.1", 591 | "eslint-visitor-keys": "3.3.0", 592 | "fast-deep-equal": "3.1.3", 593 | "inversify": "6.0.1", 594 | "js-string-escape": "1.0.1", 595 | "md5": "2.3.0", 596 | "mkdirp": "2.1.3", 597 | "multimatch": "5.0.0", 598 | "opencollective-postinstall": "2.0.3", 599 | "process": "0.11.10", 600 | "reflect-metadata": "0.1.13", 601 | "source-map-support": "0.5.21", 602 | "string-template": "1.0.0", 603 | "stringz": "2.1.0", 604 | "tslib": "2.5.0" 605 | }, 606 | "bin": { 607 | "javascript-obfuscator": "bin/javascript-obfuscator" 608 | }, 609 | "engines": { 610 | "node": ">=12.22.0" 611 | }, 612 | "funding": { 613 | "type": "opencollective", 614 | "url": "https://opencollective.com/javascript-obfuscator" 615 | } 616 | }, 617 | "node_modules/js-string-escape": { 618 | "version": "1.0.1", 619 | "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz", 620 | "integrity": "sha512-Smw4xcfIQ5LVjAOuJCvN/zIodzA/BBSsluuoSykP+lUvScIi4U6RJLfwHet5cxFnCswUjISV8oAXaqaJDY3chg==", 621 | "engines": { 622 | "node": ">= 0.8" 623 | } 624 | }, 625 | "node_modules/levn": { 626 | "version": "0.3.0", 627 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", 628 | "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", 629 | "dependencies": { 630 | "prelude-ls": "~1.1.2", 631 | "type-check": "~0.3.2" 632 | }, 633 | "engines": { 634 | "node": ">= 0.8.0" 635 | } 636 | }, 637 | "node_modules/libphonenumber-js": { 638 | "version": "1.11.7", 639 | "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.11.7.tgz", 640 | "integrity": "sha512-x2xON4/Qg2bRIS11KIN9yCNYUjhtiEjNyptjX0mX+pyKHecxuJVLIpfX1lq9ZD6CrC/rB+y4GBi18c6CEcUR+A==" 641 | }, 642 | "node_modules/md5": { 643 | "version": "2.3.0", 644 | "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", 645 | "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", 646 | "dependencies": { 647 | "charenc": "0.0.2", 648 | "crypt": "0.0.2", 649 | "is-buffer": "~1.1.6" 650 | } 651 | }, 652 | "node_modules/minimatch": { 653 | "version": "3.1.2", 654 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 655 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 656 | "dependencies": { 657 | "brace-expansion": "^1.1.7" 658 | }, 659 | "engines": { 660 | "node": "*" 661 | } 662 | }, 663 | "node_modules/mkdirp": { 664 | "version": "2.1.3", 665 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-2.1.3.tgz", 666 | "integrity": "sha512-sjAkg21peAG9HS+Dkx7hlG9Ztx7HLeKnvB3NQRcu/mltCVmvkF0pisbiTSfDVYTT86XEfZrTUosLdZLStquZUw==", 667 | "bin": { 668 | "mkdirp": "dist/cjs/src/bin.js" 669 | }, 670 | "engines": { 671 | "node": ">=10" 672 | }, 673 | "funding": { 674 | "url": "https://github.com/sponsors/isaacs" 675 | } 676 | }, 677 | "node_modules/multimatch": { 678 | "version": "5.0.0", 679 | "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-5.0.0.tgz", 680 | "integrity": "sha512-ypMKuglUrZUD99Tk2bUQ+xNQj43lPEfAeX2o9cTteAmShXy2VHDJpuwu1o0xqoKCt9jLVAvwyFKdLTPXKAfJyA==", 681 | "dependencies": { 682 | "@types/minimatch": "^3.0.3", 683 | "array-differ": "^3.0.0", 684 | "array-union": "^2.1.0", 685 | "arrify": "^2.0.1", 686 | "minimatch": "^3.0.4" 687 | }, 688 | "engines": { 689 | "node": ">=10" 690 | }, 691 | "funding": { 692 | "url": "https://github.com/sponsors/sindresorhus" 693 | } 694 | }, 695 | "node_modules/object-is": { 696 | "version": "1.1.6", 697 | "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", 698 | "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", 699 | "dependencies": { 700 | "call-bind": "^1.0.7", 701 | "define-properties": "^1.2.1" 702 | }, 703 | "engines": { 704 | "node": ">= 0.4" 705 | }, 706 | "funding": { 707 | "url": "https://github.com/sponsors/ljharb" 708 | } 709 | }, 710 | "node_modules/object-keys": { 711 | "version": "1.1.1", 712 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", 713 | "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", 714 | "engines": { 715 | "node": ">= 0.4" 716 | } 717 | }, 718 | "node_modules/opencollective-postinstall": { 719 | "version": "2.0.3", 720 | "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", 721 | "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==", 722 | "bin": { 723 | "opencollective-postinstall": "index.js" 724 | } 725 | }, 726 | "node_modules/optionator": { 727 | "version": "0.8.3", 728 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", 729 | "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", 730 | "dependencies": { 731 | "deep-is": "~0.1.3", 732 | "fast-levenshtein": "~2.0.6", 733 | "levn": "~0.3.0", 734 | "prelude-ls": "~1.1.2", 735 | "type-check": "~0.3.2", 736 | "word-wrap": "~1.2.3" 737 | }, 738 | "engines": { 739 | "node": ">= 0.8.0" 740 | } 741 | }, 742 | "node_modules/possible-typed-array-names": { 743 | "version": "1.0.0", 744 | "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", 745 | "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", 746 | "engines": { 747 | "node": ">= 0.4" 748 | } 749 | }, 750 | "node_modules/prelude-ls": { 751 | "version": "1.1.2", 752 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", 753 | "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", 754 | "engines": { 755 | "node": ">= 0.8.0" 756 | } 757 | }, 758 | "node_modules/process": { 759 | "version": "0.11.10", 760 | "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", 761 | "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", 762 | "engines": { 763 | "node": ">= 0.6.0" 764 | } 765 | }, 766 | "node_modules/reflect-metadata": { 767 | "version": "0.1.13", 768 | "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", 769 | "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" 770 | }, 771 | "node_modules/set-function-length": { 772 | "version": "1.2.2", 773 | "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", 774 | "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", 775 | "dependencies": { 776 | "define-data-property": "^1.1.4", 777 | "es-errors": "^1.3.0", 778 | "function-bind": "^1.1.2", 779 | "get-intrinsic": "^1.2.4", 780 | "gopd": "^1.0.1", 781 | "has-property-descriptors": "^1.0.2" 782 | }, 783 | "engines": { 784 | "node": ">= 0.4" 785 | } 786 | }, 787 | "node_modules/source-map": { 788 | "version": "0.6.1", 789 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 790 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 791 | "engines": { 792 | "node": ">=0.10.0" 793 | } 794 | }, 795 | "node_modules/source-map-support": { 796 | "version": "0.5.21", 797 | "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", 798 | "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", 799 | "dependencies": { 800 | "buffer-from": "^1.0.0", 801 | "source-map": "^0.6.0" 802 | } 803 | }, 804 | "node_modules/string-template": { 805 | "version": "1.0.0", 806 | "resolved": "https://registry.npmjs.org/string-template/-/string-template-1.0.0.tgz", 807 | "integrity": "sha512-SLqR3GBUXuoPP5MmYtD7ompvXiG87QjT6lzOszyXjTM86Uu7At7vNnt2xgyTLq5o9T4IxTYFyGxcULqpsmsfdg==" 808 | }, 809 | "node_modules/stringz": { 810 | "version": "2.1.0", 811 | "resolved": "https://registry.npmjs.org/stringz/-/stringz-2.1.0.tgz", 812 | "integrity": "sha512-KlywLT+MZ+v0IRepfMxRtnSvDCMc3nR1qqCs3m/qIbSOWkNZYT8XHQA31rS3TnKp0c5xjZu3M4GY/2aRKSi/6A==", 813 | "dependencies": { 814 | "char-regex": "^1.0.2" 815 | } 816 | }, 817 | "node_modules/supports-color": { 818 | "version": "7.2.0", 819 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 820 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 821 | "dependencies": { 822 | "has-flag": "^4.0.0" 823 | }, 824 | "engines": { 825 | "node": ">=8" 826 | } 827 | }, 828 | "node_modules/tslib": { 829 | "version": "2.5.0", 830 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", 831 | "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" 832 | }, 833 | "node_modules/type-check": { 834 | "version": "0.3.2", 835 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", 836 | "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", 837 | "dependencies": { 838 | "prelude-ls": "~1.1.2" 839 | }, 840 | "engines": { 841 | "node": ">= 0.8.0" 842 | } 843 | }, 844 | "node_modules/uglify-js": { 845 | "version": "3.19.2", 846 | "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.2.tgz", 847 | "integrity": "sha512-S8KA6DDI47nQXJSi2ctQ629YzwOVs+bQML6DAtvy0wgNdpi+0ySpQK0g2pxBq2xfF2z3YCscu7NNA8nXT9PlIQ==", 848 | "bin": { 849 | "uglifyjs": "bin/uglifyjs" 850 | }, 851 | "engines": { 852 | "node": ">=0.8.0" 853 | } 854 | }, 855 | "node_modules/util": { 856 | "version": "0.12.5", 857 | "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", 858 | "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", 859 | "dependencies": { 860 | "inherits": "^2.0.3", 861 | "is-arguments": "^1.0.4", 862 | "is-generator-function": "^1.0.7", 863 | "is-typed-array": "^1.1.3", 864 | "which-typed-array": "^1.1.2" 865 | } 866 | }, 867 | "node_modules/validator": { 868 | "version": "13.12.0", 869 | "resolved": "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz", 870 | "integrity": "sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==", 871 | "engines": { 872 | "node": ">= 0.10" 873 | } 874 | }, 875 | "node_modules/which-typed-array": { 876 | "version": "1.1.15", 877 | "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", 878 | "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", 879 | "dependencies": { 880 | "available-typed-arrays": "^1.0.7", 881 | "call-bind": "^1.0.7", 882 | "for-each": "^0.3.3", 883 | "gopd": "^1.0.1", 884 | "has-tostringtag": "^1.0.2" 885 | }, 886 | "engines": { 887 | "node": ">= 0.4" 888 | }, 889 | "funding": { 890 | "url": "https://github.com/sponsors/ljharb" 891 | } 892 | }, 893 | "node_modules/word-wrap": { 894 | "version": "1.2.5", 895 | "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", 896 | "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", 897 | "engines": { 898 | "node": ">=0.10.0" 899 | } 900 | } 901 | } 902 | } 903 | -------------------------------------------------------------------------------- /source/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "WebSafeCompiler", 3 | "version": "1.3.0", 4 | "description": "WebSafeCompiler is a utility designed to optimize web applications and websites, and obfuscate their code if necessary.", 5 | "main": "wsc.js", 6 | "bin": { 7 | "wsc": "wsc.js" 8 | }, 9 | "scripts": { 10 | "start": "node wsc.js", 11 | "test": "echo \"No tests specified\" && exit 0" 12 | }, 13 | "dependencies": { 14 | "uglify-js": "^3.17.0", 15 | "javascript-obfuscator": "^4.0.0" 16 | }, 17 | "engines": { 18 | "node": ">=14.0.0" 19 | }, 20 | "license": "MIT", 21 | "author": "DosX" 22 | } -------------------------------------------------------------------------------- /source/wsc.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const 4 | fs = require('fs'), 5 | path = require('path'), 6 | UglifyJS = require('uglify-js'), 7 | JavaScriptObfuscator = require('javascript-obfuscator'), 8 | { fileURLToPath } = require('url'); 9 | 10 | const version = { 11 | current: "v" + require('./package.json').version 12 | } 13 | 14 | const colors = { 15 | reset: "\x1b[0m", 16 | bright: "\x1b[1m", 17 | dim: "\x1b[2m", 18 | underscore: "\x1b[4m", 19 | blink: "\x1b[5m", 20 | reverse: "\x1b[7m", 21 | hidden: "\x1b[8m", 22 | 23 | fg: { 24 | black: "\x1b[30m", 25 | red: "\x1b[31m", 26 | green: "\x1b[32m", 27 | yellow: "\x1b[33m", 28 | blue: "\x1b[34m", 29 | magenta: "\x1b[35m", 30 | cyan: "\x1b[36m", 31 | white: "\x1b[37m", 32 | crimson: "\x1b[38m", 33 | 34 | brightBlack: "\x1b[90m", 35 | brightRed: "\x1b[91m", 36 | brightGreen: "\x1b[92m", 37 | brightYellow: "\x1b[93m", 38 | brightBlue: "\x1b[94m", 39 | brightMagenta: "\x1b[95m", 40 | brightCyan: "\x1b[96m", 41 | brightWhite: "\x1b[97m", 42 | 43 | color256: (code) => `\x1b[38;5;${code}m` 44 | }, 45 | bg: { 46 | black: "\x1b[40m", 47 | red: "\x1b[41m", 48 | green: "\x1b[42m", 49 | yellow: "\x1b[43m", 50 | blue: "\x1b[44m", 51 | magenta: "\x1b[45m", 52 | cyan: "\x1b[46m", 53 | white: "\x1b[47m", 54 | crimson: "\x1b[48m", 55 | 56 | brightBlack: "\x1b[100m", 57 | brightRed: "\x1b[101m", 58 | brightGreen: "\x1b[102m", 59 | brightYellow: "\x1b[103m", 60 | brightBlue: "\x1b[104m", 61 | brightMagenta: "\x1b[105m", 62 | brightCyan: "\x1b[106m", 63 | brightWhite: "\x1b[107m", 64 | 65 | color256: (code) => `\x1b[48;5;${code}m` 66 | } 67 | }; 68 | 69 | const obfuscationPreset = { 70 | compact: true, 71 | controlFlowFlattening: true, 72 | deadCodeInjection: true, 73 | debugProtection: false, 74 | renameGlobals: false, 75 | stringArray: true, 76 | stringArrayEncoding: ['base64'], 77 | stringArrayThreshold: 1, 78 | identifiersPrefix: 'wsc_', 79 | identifierNamesGenerator: 'mangled-shuffled' 80 | }, 81 | minificationPreset = { 82 | mangle: true, 83 | compress: { 84 | passes: 5, 85 | drop_console: false 86 | } 87 | }; 88 | 89 | const scriptPath = path.basename(process.argv[1]); 90 | 91 | function handleError(message) { 92 | console.error(`${colors.fg.red}Error: ${message}${colors.reset}`); 93 | process.exit(1); 94 | } 95 | 96 | function printArt() { 97 | console.log( 98 | `${colors.fg.brightBlue} 99 | ██╗ ██╗ ██╗ ███████╗ ██████╗ ██╗ 100 | ██╔╝ ██║ ██║ ██╔════╝ ██╔════╝ ╚██╗ 101 | ██╔╝ ██║ █╗ ██║ ███████╗ ██║ ╚██╗ 102 | ╚██╗ ██║███╗██║ ╚════██║ ██║ ██╔╝ 103 | ╚██╗ ╚███╔███╔╝ ███████║ ╚██████╗ ██╔╝ 104 | ╚═╝ ╚══╝╚══╝ ╚══════╝ ╚═════╝ ╚═╝${colors.fg.brightBlack} 105 | WebSafeCompiler, (C) DosX [2024]${colors.fg.brightMagenta} 106 | A utility designed to optimize web applications and websites, 107 | and obfuscate their code if necessary.${colors.reset}`); 108 | } 109 | 110 | function printHelp() { 111 | 112 | printArt(); 113 | 114 | console.log(` 115 | ${colors.fg.brightYellow}Usage:${colors.reset} 116 | node ${scriptPath} [--map] [--smart] [--drm] 117 | 118 | ${colors.fg.brightYellow}Options:${colors.reset} 119 | Directory containing the source files. 120 | Directory where processed files will be saved. 121 | -m, --map Generate sitemap.xml in the root of the site 122 | -s, --smart Skip minified JS/CSS files. 123 | ${colors.fg.red + '*' + colors.reset} -d, --drm Enable code obfuscation (DRM protection). 124 | -h, --help Show this help message. 125 | -v, --version Get the current version of WSC. 126 | 127 | ${colors.fg.brightGreen}Dependencies used:${colors.reset} 128 | * ${colors.fg.cyan}uglify-js:${colors.reset} JavaScript preprocessing and minification. 129 | * ${colors.fg.cyan}javascript-obfuscator:${colors.reset} JavaScript code protection. 130 | 131 | ${colors.fg.brightYellow}Example:${colors.reset} 132 | node ${scriptPath} "/path/to/source" "/path/to/output" --map --smart --drm 133 | 134 | ${colors.fg.brightBlack}WebSafeCompiler will process all files in the specified source directory, 135 | perform optimization, and if the obfuscation option is set, protect the 136 | code from analysis. The result will be optimized and protected files 137 | ready for deployment on your website. Current version is ${version.current}. 138 | GitHub: ${colors.bg.brightBlack + colors.fg.blue} https://github.com/DosX-dev/WebSafeCompiler ${colors.reset}`); 139 | process.exit(0); 140 | } 141 | 142 | function printVersion() { 143 | console.log("WebSafeCompiler, " + version.current); 144 | process.exit(0); 145 | } 146 | 147 | function parseArguments() { 148 | const args = process.argv.slice(2); 149 | 150 | // Check for help flags first 151 | if (args.includes('-h') || args.includes('--help')) { 152 | printHelp(); 153 | } else if (args.includes('-v') || args.includes('--version')) { 154 | printVersion(); 155 | } 156 | 157 | // Extract main arguments 158 | const 159 | inputDir = args.shift(), 160 | outputDir = args.shift(), 161 | map = args.includes('-m') || args.includes("--map"), 162 | smart = args.includes('-s') || args.includes('--smart'), 163 | obfuscate = args.includes('-d') || args.includes('--drm'); 164 | 165 | if (!inputDir || !outputDir) { 166 | console.log( 167 | `${colors.fg.brightCyan}Usage: node ${scriptPath} [--map] [--smart] [--drm]${colors.fg.brightBlack} 168 | Use --help for more detailed usage instructions.${colors.reset}`); 169 | process.exit(0); 170 | } 171 | 172 | return { inputDir, outputDir, map, smart, obfuscate }; 173 | } 174 | 175 | function validateDirectories(inputDir, outputDir) { 176 | if (!fs.existsSync(inputDir)) { 177 | handleError(`Input directory does not exist: ${inputDir}`); 178 | } 179 | 180 | if (!fs.existsSync(outputDir)) { 181 | try { 182 | fs.mkdirSync(outputDir, { recursive: true }); 183 | console.log(`${colors.fg.green}Output directory created:${colors.reset} ${outputDir}`); 184 | } catch (error) { 185 | handleError(`Failed to create output directory: ${error.message}`); 186 | } 187 | } 188 | } 189 | 190 | function validateArguments(inputDir, outputDir, args) { 191 | const allowedFlags = ['-m', '-s', '-d', '-v', '-h', '--map', '--smart', '--drm', '--version', '--help']; 192 | 193 | args.forEach(arg => { 194 | if (!allowedFlags.includes(arg) && !path.isAbsolute(arg) && !fs.existsSync(arg)) { 195 | handleError(`Invalid flag detected: ${arg}`); 196 | } 197 | }); 198 | } 199 | 200 | function getAllFiles(dir) { 201 | try { 202 | let results = []; 203 | const list = fs.readdirSync(dir); 204 | 205 | list.forEach(file => { 206 | file = path.join(dir, file); 207 | const stat = fs.statSync(file); 208 | if (stat && stat.isDirectory()) { 209 | results = results.concat(getAllFiles(file)); 210 | } else { 211 | results.push(file); 212 | } 213 | }); 214 | 215 | return results; 216 | } catch (error) { 217 | handleError(`Reading directory failed: ${error.message}`); 218 | } 219 | } 220 | 221 | function checkFilePermissions(file) { 222 | try { 223 | fs.accessSync(file, fs.constants.R_OK | fs.constants.W_OK); 224 | } catch (error) { 225 | handleError(`Insufficient permissions for file: ${file}`); 226 | } 227 | } 228 | 229 | function checkEmptyDirectory(files, inputDir) { 230 | if (files.length === 0) { 231 | handleError(`Input directory is empty: ${inputDir}`); 232 | } 233 | } 234 | 235 | function getRandomString(length) { 236 | if (length <= 0) { 237 | handleError(`Invalid string length: ${length}`); 238 | } 239 | 240 | const chars = 'abcdefghijklmnopqrstuvwxyz'; 241 | let result = ''; 242 | for (let i = 0; i < length; i++) { 243 | result += chars.charAt(Math.floor(Math.random() * chars.length)); 244 | } 245 | return result; 246 | } 247 | 248 | function getRandomNumber(min, max) { 249 | return Math.floor(Math.random() * (max - min + 1)) + min; 250 | } 251 | 252 | function obfuscateHtml(html) { 253 | try { 254 | return html.replace(/<(\w+)(\s[^>]*?)?(\s*\/)?>/g, (match, tagName, attributes, closingSlash) => { 255 | if (!attributes || ['meta', 'noscript'].includes(tagName)) { 256 | return `<${tagName}${attributes || ''}>`; 257 | } 258 | 259 | const attrArray = attributes.trim().match(/\S+="[^"]*"|\S+='[^']*'|\S+/g) || []; 260 | 261 | const obfuscatedAttrs = attrArray.map(attr => { 262 | let obfuscatedAttr = attr; 263 | 264 | if (/^class=['"]/.test(attr)) { 265 | const classNames = attr.match(/class=['"]([^'"]*)['"]/)[1].split(/\s+/); 266 | const obfuscatedClasses = classNames.map(className => className); 267 | const randomClasses = Array.from({ length: getRandomNumber(1, 3) }, () => 268 | getRandomString(getRandomNumber(6, 7)) 269 | ); 270 | 271 | obfuscatedAttr = `class="${[...obfuscatedClasses, ...randomClasses].join(' ')}"`; 272 | } 273 | 274 | const randomBefore = getRandomString(getRandomNumber(5, 7)); 275 | const randomAfter = getRandomString(getRandomNumber(5, 7)); 276 | 277 | return `${randomBefore} ${obfuscatedAttr} ${randomAfter}`; 278 | }).join(' '); 279 | 280 | return `<${tagName} ${obfuscatedAttrs}${closingSlash ? ' /' : ''}>`; 281 | }); 282 | } catch (error) { 283 | handleError(`Obfuscating HTML failed: ${error.message}`); 284 | } 285 | } 286 | 287 | 288 | // Remove HTML comments 289 | function removeHtmlComments(content) { 290 | return content.replace(//g, ''); 291 | } 292 | 293 | // Remove HTML comments and handle script/style tags 294 | function removeHtmlComments(content) { 295 | let inScript = false, 296 | inStyle = false; 297 | 298 | return content.replace(/(?:[\s\S]*?<\/script>)|(?:[\s\S]*?<\/style>)|/g, (match, offset, string) => { 299 | if (match.startsWith(']+>|[^<]+|(['"])(?:(?=(\\?))\2.)*?\1/g, (match, quote, escapeChar) => { 323 | if (quote) { 324 | if (escapeChar) return match; // Preserve quoted strings with escape characters 325 | isInSingleQuote = !isInSingleQuote && quote === "'"; 326 | isInDoubleQuote = !isInDoubleQuote && quote === '"'; 327 | return match; 328 | } 329 | 330 | if (match.startsWith('<')) { 331 | const tagName = match.replace(/[<\/>]/g, '').split(' ')[0]; 332 | if (tagsToPreserve.includes(tagName)) { 333 | isInPreservedTag = match.startsWith(' { 358 | if (quotedString) { 359 | return quotedString; // Preserve quoted strings 360 | } 361 | 362 | return String(); // Remove CSS comments 363 | }); 364 | } catch (error) { 365 | handleError(`Removing CSS comments failed: ${error.message}`); 366 | } 367 | } 368 | 369 | // Minify CSS content 370 | function minifyCss(content) { 371 | try { 372 | const patterns = [ 373 | [/\s*([{}:;,\n])\s*/g, '$1'], // Remove space around special characters 374 | [/\s+/g, ' '], // Reduce multiple spaces to single space 375 | [/;}/g, '}'] // Remove redundant semicolons before closing brace 376 | ]; 377 | 378 | content = removeCssComments(content); // Remove comments first 379 | for (const [pattern, replacement] of patterns) { 380 | content = content.replace(pattern, replacement); // Apply patterns 381 | } 382 | 383 | return content.trim(); // Trim leading and trailing spaces 384 | } catch (error) { 385 | handleError(`Minifying CSS failed: ${error.message}`); 386 | } 387 | } 388 | 389 | // Obfuscate and minify inline `; // Replace the script with minified code 405 | } 406 | throw new Error('Minification failed.'); 407 | } catch (error) { 408 | console.error(`${colors.fg.red}Error processing inline script: ${error.message}${colors.reset}`); 409 | return match; // Return original script if an error occurs 410 | } 411 | }); 412 | } catch (error) { 413 | handleError(`Obfuscating and minifying inline scripts failed: ${error.message}`); 414 | } 415 | } 416 | 417 | // Obfuscate and minify JavaScript content 418 | function obfuscateAndMinifyJs(content, obfuscate) { 419 | try { 420 | let processedContent = content; 421 | if (obfuscate) { 422 | // Obfuscate the JavaScript content if needed 423 | processedContent = JavaScriptObfuscator.obfuscate(content, obfuscationPreset).getObfuscatedCode(); 424 | } 425 | 426 | // Minify the (possibly obfuscated) JavaScript content 427 | const minifiedContent = UglifyJS.minify(processedContent, minificationPreset).code; 428 | 429 | if (minifiedContent === undefined) throw new Error("Minification failed."); 430 | return minifiedContent; 431 | } catch (error) { 432 | handleError(`Obfuscating and minifying JS failed: ${error.message}`); 433 | } 434 | } 435 | 436 | // Minify a file based on its extension and options 437 | function processFile(file, outputDir, obfuscate = false, smart = false) { 438 | try { 439 | const 440 | ext = path.extname(file), 441 | outputFilePath = path.join(outputDir, path.relative(process.argv[2], file)); 442 | 443 | fs.mkdirSync(path.dirname(outputFilePath), { recursive: true }); 444 | 445 | let content = fs.readFileSync(file, 'utf8'), 446 | minifiedContent; 447 | 448 | if (smart && (ext === '.js' || ext === '.css')) { 449 | // Skip minification for already minified files or very compact files 450 | if (path.basename(file).endsWith('min' + ext) || 451 | (content.length > 250 && !content.includes('\n'))) { 452 | console.log(`${colors.fg.brightBlack}Copied:${colors.reset} ${file} -> ${outputFilePath} ${colors.fg.brightBlack}(skipped)${colors.reset}`); 453 | fs.copyFileSync(file, outputFilePath); 454 | return; 455 | } 456 | } 457 | 458 | switch (ext) { 459 | case '.js': 460 | minifiedContent = obfuscateAndMinifyJs(content, obfuscate); 461 | break; 462 | case '.css': 463 | content = removeCssComments(content); // Remove CSS comments before minifying 464 | minifiedContent = minifyCss(content); 465 | break; 466 | case '.html': 467 | case '.htm': 468 | if (obfuscate) { 469 | content = obfuscateHtml(content); // Obfuscate HTML content if needed 470 | } 471 | content = obfuscateAndMinifyInlineScripts(content, obfuscate); // Minify inline scripts 472 | minifiedContent = minifyHtml(content); 473 | break; 474 | default: 475 | fs.copyFileSync(file, outputFilePath); // Copy non-processable files 476 | console.log(`${colors.fg.brightBlue}Copied:${colors.reset} ${file} -> ${outputFilePath}`); 477 | return; 478 | } 479 | fs.writeFileSync(outputFilePath, minifiedContent, 'utf8'); 480 | console.log(`${colors.fg.green}Compiled:${colors.reset} ${file} -> ${outputFilePath}`); 481 | } catch (error) { 482 | console.error(`${colors.fg.red}Error processing ${file}: ${error.message}${colors.reset}`); 483 | fs.copyFileSync(file, path.join(outputDir, path.relative(process.argv[2], file))); // Copy file in case of an error 484 | console.log(`${colors.fg.yellow}Copied without minification due to error:${colors.reset} ${file} -> ${path.join(outputDir, path.relative(process.argv[2], file))}`); 485 | process.exit(1); 486 | } 487 | } 488 | 489 | function removeIndex(relativePath) { 490 | const endings = ['index.html', 'index.htm', 'index.php']; 491 | for (const ending of endings) { 492 | if (relativePath.endsWith(ending)) { 493 | return relativePath.slice(0, -ending.length); 494 | } 495 | } 496 | return relativePath; 497 | } 498 | 499 | function generateSiteMap(contentPath) { 500 | const urls = []; 501 | 502 | function walkDir(currentPath) { 503 | fs.readdirSync(currentPath).forEach(file => { 504 | const 505 | fullPath = path.join(currentPath, file), 506 | stats = fs.statSync(fullPath); 507 | 508 | if (stats.isDirectory()) { 509 | walkDir(fullPath); 510 | } else if (stats.isFile() && ['.html', '.htm', '.php'].includes(path.extname(fullPath))) { 511 | let relativePath = path.relative(contentPath, fullPath).replace(/\\/g, '/'); 512 | 513 | relativePath = '/' + removeIndex(relativePath); 514 | 515 | if (relativePath) { 516 | urls.push(`${relativePath}`); 517 | } 518 | } 519 | }); 520 | } 521 | 522 | walkDir(contentPath); 523 | 524 | const xml = 525 | `\n\n` + 526 | urls.map(url => ` \n ${url}\n `).join('\n') + 527 | `\n`; 528 | 529 | const siteMapPath = path.join(contentPath, 'sitemap.xml'); 530 | 531 | fs.writeFileSync(siteMapPath, xml); 532 | 533 | console.log(`${colors.fg.brightCyan}Generated:${colors.reset} ${siteMapPath}`); 534 | } 535 | 536 | // Print statistics about the files processed 537 | function printFileStats(files, obfuscate) { 538 | try { 539 | const 540 | totalFiles = files.length, 541 | skippedFiles = files.filter(file => !['.js', '.css', '.html', '.htm'].includes(path.extname(file))).length, 542 | processedFiles = totalFiles - skippedFiles; 543 | 544 | console.log(`Source files detected: ${colors.fg.brightCyan}${processedFiles}${colors.reset}\n` + 545 | `Resource files detected: ${colors.fg.brightYellow}${skippedFiles}${colors.reset}\n`); 546 | 547 | console.log("Compilation mode: " + (obfuscate ? `${colors.bg.brightMagenta}${colors.fg.white}DRM protection${colors.reset}` : `${colors.bg.yellow}${colors.fg.black}Preprocess only${colors.reset}`) + "\n"); 548 | } catch (error) { 549 | handleError(`Printing file stats failed: ${error.message}`); 550 | } 551 | } 552 | 553 | // Check if required dependencies are installed 554 | function checkDependencies() { 555 | try { 556 | require.resolve('uglify-js'); // Ensure UglifyJS is available 557 | require.resolve('javascript-obfuscator'); // Ensure JavaScriptObfuscator is available 558 | } catch (error) { 559 | handleError(`Missing dependency: ${error.message}`); 560 | } 561 | } 562 | 563 | function main() { 564 | try { 565 | const { inputDir, outputDir, map, smart, obfuscate } = parseArguments(); 566 | 567 | validateDirectories(inputDir, outputDir); 568 | checkDependencies(); 569 | validateArguments(inputDir, outputDir, process.argv.slice(2)); 570 | 571 | const files = getAllFiles(inputDir); 572 | checkEmptyDirectory(files, inputDir); 573 | printFileStats(files, obfuscate); 574 | 575 | files.forEach(file => { 576 | checkFilePermissions(file); 577 | processFile(file, outputDir, obfuscate, smart); 578 | }); 579 | 580 | if (map) { 581 | generateSiteMap(outputDir); 582 | } 583 | 584 | console.log(`\n${colors.bg.brightGreen}${colors.fg.black}[Done!]${colors.reset} The web application files are compiled${obfuscate ? " and protected" : ""}.`); 585 | } catch (error) { 586 | handleError(`Fatal error: ${error.message}`); 587 | } 588 | } 589 | 590 | main(); 591 | --------------------------------------------------------------------------------