Options.ts 9.9 KB

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