Options.ts 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. import { inject, injectable } from 'inversify';
  2. import { ServiceIdentifiers } from '../container/ServiceIdentifiers';
  3. import {
  4. ArrayNotEmpty,
  5. ArrayUnique,
  6. IsArray,
  7. IsBoolean,
  8. IsIn,
  9. IsNumber,
  10. IsString,
  11. IsUrl,
  12. Max,
  13. Min,
  14. ValidateIf,
  15. validateSync,
  16. ValidationError,
  17. ValidatorOptions
  18. } from 'class-validator';
  19. import { TInputOptions } from '../types/options/TInputOptions';
  20. import { TOptionsPreset } from '../types/options/TOptionsPreset';
  21. import { TRenamePropertiesMode } from '../types/options/TRenamePropertiesMode';
  22. import { TStringArrayIndexesType } from '../types/options/TStringArrayIndexesType';
  23. import { TStringArrayEncoding } from '../types/options/TStringArrayEncoding';
  24. import { TStringArrayWrappersType } from '../types/options/TStringArrayWrappersType';
  25. import { TTypeFromEnum } from '../types/utils/TTypeFromEnum';
  26. import { IOptions } from '../interfaces/options/IOptions';
  27. import { IOptionsNormalizer } from '../interfaces/options/IOptionsNormalizer';
  28. import { IdentifierNamesGenerator } from '../enums/generators/identifier-names-generators/IdentifierNamesGenerator';
  29. import { ObfuscationTarget } from '../enums/ObfuscationTarget';
  30. import { OptionsPreset } from '../enums/options/presets/OptionsPreset';
  31. import { RenamePropertiesMode } from '../enums/node-transformers/rename-properties-transformers/RenamePropertiesMode';
  32. import { SourceMapMode } from '../enums/source-map/SourceMapMode';
  33. import { StringArrayIndexesType } from '../enums/node-transformers/string-array-transformers/StringArrayIndexesType';
  34. import { StringArrayEncoding } from '../enums/node-transformers/string-array-transformers/StringArrayEncoding';
  35. import { StringArrayWrappersType } from '../enums/node-transformers/string-array-transformers/StringArrayWrappersType';
  36. import { DEFAULT_PRESET } from './presets/Default';
  37. import { LOW_OBFUSCATION_PRESET } from './presets/LowObfuscation';
  38. import { MEDIUM_OBFUSCATION_PRESET } from './presets/MediumObfuscation';
  39. import { HIGH_OBFUSCATION_PRESET } from './presets/HighObfuscation';
  40. import { ValidationErrorsFormatter } from './ValidationErrorsFormatter';
  41. import { IsAllowedForObfuscationTargets } from './validators/IsAllowedForObfuscationTargets';
  42. @injectable()
  43. export class Options implements IOptions {
  44. /**
  45. * @type {Map<TOptionsPreset, TInputOptions>}
  46. */
  47. private static readonly optionPresetsMap: Map<TOptionsPreset, TInputOptions> = new Map([
  48. [OptionsPreset.Default, DEFAULT_PRESET],
  49. [OptionsPreset.LowObfuscation, LOW_OBFUSCATION_PRESET],
  50. [OptionsPreset.MediumObfuscation, MEDIUM_OBFUSCATION_PRESET],
  51. [OptionsPreset.HighObfuscation, HIGH_OBFUSCATION_PRESET]
  52. ]);
  53. /**
  54. * @type {ValidatorOptions}
  55. */
  56. private static readonly validatorOptions: ValidatorOptions = {
  57. forbidUnknownValues: true,
  58. validationError: {
  59. target: false
  60. }
  61. };
  62. /**
  63. * @type {boolean}
  64. */
  65. @IsBoolean()
  66. public readonly compact!: boolean;
  67. /**
  68. * @type {boolean}
  69. */
  70. @IsBoolean()
  71. public readonly controlFlowFlattening!: boolean;
  72. /**
  73. * @type {boolean}
  74. */
  75. @IsNumber()
  76. @Min(0)
  77. @Max(1)
  78. public readonly controlFlowFlatteningThreshold!: number;
  79. /**
  80. * @type {boolean}
  81. */
  82. @IsBoolean()
  83. public readonly deadCodeInjection!: boolean;
  84. /**
  85. * @type {number}
  86. */
  87. @IsNumber()
  88. public readonly deadCodeInjectionThreshold!: number;
  89. /**
  90. * @type {boolean}
  91. */
  92. @IsBoolean()
  93. public readonly debugProtection!: boolean;
  94. /**
  95. * @type {boolean}
  96. */
  97. @IsBoolean()
  98. public readonly debugProtectionInterval!: boolean;
  99. /**
  100. * @type {boolean}
  101. */
  102. @IsBoolean()
  103. public readonly disableConsoleOutput!: boolean;
  104. /**
  105. * @type {string[]}
  106. */
  107. @IsArray()
  108. @ArrayUnique()
  109. @IsString({
  110. each: true
  111. })
  112. @IsAllowedForObfuscationTargets([
  113. ObfuscationTarget.Browser,
  114. ObfuscationTarget.BrowserNoEval,
  115. ])
  116. public readonly domainLock!: string[];
  117. /**
  118. * @type {string[]}
  119. */
  120. @IsArray()
  121. @ArrayUnique()
  122. @IsString({
  123. each: true
  124. })
  125. public readonly forceTransformStrings!: string[];
  126. /**
  127. * @type {IdentifierNamesGenerator}
  128. */
  129. @IsIn([
  130. IdentifierNamesGenerator.DictionaryIdentifierNamesGenerator,
  131. IdentifierNamesGenerator.HexadecimalIdentifierNamesGenerator,
  132. IdentifierNamesGenerator.MangledIdentifierNamesGenerator,
  133. IdentifierNamesGenerator.MangledShuffledIdentifierNamesGenerator
  134. ])
  135. public readonly identifierNamesGenerator!: TTypeFromEnum<typeof IdentifierNamesGenerator>;
  136. /**
  137. * @type {string}
  138. */
  139. @IsString()
  140. public readonly identifiersPrefix!: string;
  141. @IsArray()
  142. @ArrayUnique()
  143. @IsString({
  144. each: true
  145. })
  146. @ValidateIf((options: IOptions) =>
  147. options.identifierNamesGenerator === IdentifierNamesGenerator.DictionaryIdentifierNamesGenerator
  148. )
  149. @ArrayNotEmpty()
  150. public readonly identifiersDictionary!: string[];
  151. /**
  152. * @type {boolean}
  153. */
  154. @IsBoolean()
  155. public readonly ignoreRequireImports!: boolean;
  156. /**
  157. * @type {string}
  158. */
  159. @IsString()
  160. public readonly inputFileName!: string;
  161. /**
  162. * @type {boolean}
  163. */
  164. @IsBoolean()
  165. public readonly log!: boolean;
  166. /**
  167. * @type {boolean}
  168. */
  169. @IsBoolean()
  170. public readonly numbersToExpressions!: boolean;
  171. /**
  172. * @type {TOptionsPreset}
  173. */
  174. @IsIn([
  175. OptionsPreset.Default,
  176. OptionsPreset.LowObfuscation,
  177. OptionsPreset.MediumObfuscation,
  178. OptionsPreset.HighObfuscation
  179. ])
  180. public readonly optionsPreset!: TOptionsPreset;
  181. /**
  182. * @type {boolean}
  183. */
  184. @IsBoolean()
  185. public readonly renameGlobals!: boolean;
  186. /**
  187. * @type {boolean}
  188. */
  189. @IsBoolean()
  190. public readonly renameProperties!: boolean;
  191. /**
  192. * @type {RenamePropertiesMode}
  193. */
  194. @IsIn([RenamePropertiesMode.Safe, RenamePropertiesMode.Unsafe])
  195. public readonly renamePropertiesMode!: TRenamePropertiesMode;
  196. /**
  197. * @type {string[]}
  198. */
  199. @IsArray()
  200. @ArrayUnique()
  201. @IsString({
  202. each: true
  203. })
  204. public readonly reservedNames!: string[];
  205. /**
  206. * @type {string[]}
  207. */
  208. @IsArray()
  209. @ArrayUnique()
  210. @IsString({
  211. each: true
  212. })
  213. public readonly reservedStrings!: string[];
  214. /**
  215. * @type {boolean}
  216. */
  217. @IsBoolean()
  218. public readonly rotateStringArray!: boolean;
  219. /**
  220. * @type {boolean}
  221. */
  222. @IsBoolean()
  223. public readonly selfDefending!: boolean;
  224. /**
  225. * @type {boolean}
  226. */
  227. @IsBoolean()
  228. public readonly shuffleStringArray!: boolean;
  229. /**
  230. * @type {boolean}
  231. */
  232. @IsBoolean()
  233. public readonly simplify!: boolean;
  234. /**
  235. * @type {boolean}
  236. */
  237. @IsBoolean()
  238. public readonly sourceMap!: boolean;
  239. /**
  240. * @type {string}
  241. */
  242. @IsString()
  243. @ValidateIf((options: IOptions) => Boolean(options.sourceMapBaseUrl))
  244. @IsUrl({
  245. require_protocol: true,
  246. require_tld: false,
  247. require_valid_protocol: true
  248. })
  249. public readonly sourceMapBaseUrl!: string;
  250. /**
  251. * @type {string}
  252. */
  253. @IsString()
  254. public readonly sourceMapFileName!: string;
  255. /**
  256. * @type {SourceMapMode}
  257. */
  258. @IsIn([SourceMapMode.Inline, SourceMapMode.Separate])
  259. public readonly sourceMapMode!: TTypeFromEnum<typeof SourceMapMode>;
  260. /**
  261. * @type {boolean}
  262. */
  263. @IsBoolean()
  264. public readonly splitStrings!: boolean;
  265. /**
  266. * @type {number}
  267. */
  268. @IsNumber()
  269. @ValidateIf((options: IOptions) => Boolean(options.splitStrings))
  270. @Min(1)
  271. public readonly splitStringsChunkLength!: number;
  272. /**
  273. * @type {boolean}
  274. */
  275. @IsBoolean()
  276. public readonly stringArray!: boolean;
  277. /**
  278. * @type {TStringArrayEncoding[]}
  279. */
  280. @IsArray()
  281. @ArrayUnique()
  282. @IsIn([StringArrayEncoding.None, StringArrayEncoding.Base64, StringArrayEncoding.Rc4], { each: true })
  283. public readonly stringArrayEncoding!: TStringArrayEncoding[];
  284. /**
  285. * @type {TStringArrayIndexesType[]}
  286. */
  287. @IsArray()
  288. @ArrayNotEmpty()
  289. @ArrayUnique()
  290. @IsIn([StringArrayIndexesType.HexadecimalNumber, StringArrayIndexesType.HexadecimalNumericString], { each: true })
  291. public readonly stringArrayIndexesType!: TStringArrayIndexesType[];
  292. /**
  293. * @type {boolean}
  294. */
  295. @IsBoolean()
  296. public readonly stringArrayIndexShift!: boolean;
  297. /**
  298. * @type {boolean}
  299. */
  300. @IsBoolean()
  301. public readonly stringArrayWrappersChainedCalls!: boolean;
  302. /**
  303. * @type {boolean}
  304. */
  305. @IsNumber()
  306. @Min(0)
  307. public readonly stringArrayWrappersCount!: number;
  308. /**
  309. * @type {boolean}
  310. */
  311. @IsNumber()
  312. @Min(2)
  313. public readonly stringArrayWrappersParametersMaxCount!: number;
  314. /**
  315. * @type {TStringArrayWrappersType}
  316. */
  317. @IsIn([StringArrayWrappersType.Variable, StringArrayWrappersType.Function])
  318. public readonly stringArrayWrappersType!: TStringArrayWrappersType;
  319. /**
  320. * @type {number}
  321. */
  322. @IsNumber()
  323. @Min(0)
  324. @Max(1)
  325. public readonly stringArrayThreshold!: number;
  326. /**
  327. * @type {ObfuscationTarget}
  328. */
  329. @IsIn([ObfuscationTarget.Browser, ObfuscationTarget.BrowserNoEval, ObfuscationTarget.Node])
  330. public readonly target!: TTypeFromEnum<typeof ObfuscationTarget>;
  331. /**
  332. * @type {boolean}
  333. */
  334. @IsBoolean()
  335. public readonly transformObjectKeys!: boolean;
  336. /**
  337. * @type {boolean}
  338. */
  339. @IsBoolean()
  340. public readonly unicodeEscapeSequence!: boolean;
  341. /**
  342. * @type {string | number}
  343. */
  344. public readonly seed!: string | number;
  345. /**
  346. * @param {TInputOptions} inputOptions
  347. * @param {IOptionsNormalizer} optionsNormalizer
  348. */
  349. public constructor (
  350. @inject(ServiceIdentifiers.TInputOptions) inputOptions: TInputOptions,
  351. @inject(ServiceIdentifiers.IOptionsNormalizer) optionsNormalizer: IOptionsNormalizer
  352. ) {
  353. const optionsPreset: TInputOptions = Options.getOptionsByPreset(
  354. inputOptions.optionsPreset ?? OptionsPreset.Default
  355. );
  356. Object.assign(this, optionsPreset, inputOptions);
  357. const errors: ValidationError[] = validateSync(this, Options.validatorOptions);
  358. if (errors.length) {
  359. throw new ReferenceError(`Validation failed. errors:\n${ValidationErrorsFormatter.format(errors)}`);
  360. }
  361. Object.assign(this, optionsNormalizer.normalize(this));
  362. }
  363. /**
  364. * @param {TOptionsPreset} optionsPreset
  365. * @returns {TInputOptions}
  366. */
  367. public static getOptionsByPreset (optionsPreset: TOptionsPreset): TInputOptions {
  368. const options: TInputOptions | null = Options.optionPresetsMap.get(optionsPreset) ?? null;
  369. if (!options) {
  370. throw new Error(`Options for preset name \`${optionsPreset}\` are not found`);
  371. }
  372. return options;
  373. }
  374. }