@js-recon/js-recon 1.3.2 → 1.4.1-alpha.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (233) hide show
  1. package/.github/workflows/build-and-prettify.yaml +207 -14
  2. package/.github/workflows/pr_checker.yml +2 -2
  3. package/.github/workflows/promote-js-recon.yml +104 -0
  4. package/.github/workflows/publish-js-recon.yml +22 -80
  5. package/.github/workflows/rules-smoke-test.yaml +79 -0
  6. package/CHANGELOG.md +177 -4
  7. package/CLAUDE.md +350 -16
  8. package/Dockerfile.release +29 -0
  9. package/README.md +48 -19
  10. package/build/analyze/engine/csMastSEngine.js +129 -0
  11. package/build/analyze/engine/csMastSEngine.js.map +1 -0
  12. package/build/analyze/engine/index.js +15 -0
  13. package/build/analyze/engine/index.js.map +1 -1
  14. package/build/analyze/helpers/engineHelpers/findDirectAssignment.js +2 -1
  15. package/build/analyze/helpers/engineHelpers/findDirectAssignment.js.map +1 -1
  16. package/build/analyze/helpers/engineHelpers/findMemberExpressionAssignment.js +2 -1
  17. package/build/analyze/helpers/engineHelpers/findMemberExpressionAssignment.js.map +1 -1
  18. package/build/analyze/helpers/engineHelpers/resolveFunctionIdentifier.js +2 -1
  19. package/build/analyze/helpers/engineHelpers/resolveFunctionIdentifier.js.map +1 -1
  20. package/build/analyze/helpers/engineHelpers/taintFlow.js +11 -2
  21. package/build/analyze/helpers/engineHelpers/taintFlow.js.map +1 -1
  22. package/build/analyze/helpers/initRules.js.map +1 -1
  23. package/build/analyze/helpers/schemas.js +6 -2
  24. package/build/analyze/helpers/schemas.js.map +1 -1
  25. package/build/analyze/helpers/validate.js +3 -3
  26. package/build/analyze/helpers/validate.js.map +1 -1
  27. package/build/analyze/index.js +1 -0
  28. package/build/analyze/index.js.map +1 -1
  29. package/build/completion/index.js +432 -0
  30. package/build/completion/index.js.map +1 -0
  31. package/build/cs_mast/index.js +213 -0
  32. package/build/cs_mast/index.js.map +1 -0
  33. package/build/endpoints/next_js/client_jsFilesHref.js +2 -1
  34. package/build/endpoints/next_js/client_jsFilesHref.js.map +1 -1
  35. package/build/endpoints/next_js/client_jsonParse.js +2 -1
  36. package/build/endpoints/next_js/client_jsonParse.js.map +1 -1
  37. package/build/endpoints/next_js/client_mappedJsonFile.js +2 -1
  38. package/build/endpoints/next_js/client_mappedJsonFile.js.map +1 -1
  39. package/build/endpoints/next_js/client_subsequentRequests.js +2 -1
  40. package/build/endpoints/next_js/client_subsequentRequests.js.map +1 -1
  41. package/build/fingerprint/index.js +56 -33
  42. package/build/fingerprint/index.js.map +1 -1
  43. package/build/globalConfig.js +3 -3
  44. package/build/globalConfig.js.map +1 -1
  45. package/build/index.js +210 -10
  46. package/build/index.js.map +1 -1
  47. package/build/lazyLoad/angular/angular_getFromMainJs.js +2 -1
  48. package/build/lazyLoad/angular/angular_getFromMainJs.js.map +1 -1
  49. package/build/lazyLoad/downloadFilesUtil.js +6 -5
  50. package/build/lazyLoad/downloadFilesUtil.js.map +1 -1
  51. package/build/lazyLoad/downloadLoadedJsUtil.js +59 -5
  52. package/build/lazyLoad/downloadLoadedJsUtil.js.map +1 -1
  53. package/build/lazyLoad/downloadQueue.js +10 -9
  54. package/build/lazyLoad/downloadQueue.js.map +1 -1
  55. package/build/lazyLoad/index.js +127 -85
  56. package/build/lazyLoad/index.js.map +1 -1
  57. package/build/lazyLoad/methodFilter.js +50 -0
  58. package/build/lazyLoad/methodFilter.js.map +1 -0
  59. package/build/lazyLoad/next_js/NextJsCrawler.js +69 -48
  60. package/build/lazyLoad/next_js/NextJsCrawler.js.map +1 -1
  61. package/build/lazyLoad/next_js/next_GetLazyResourcesBuildManifestJs.js +36 -34
  62. package/build/lazyLoad/next_js/next_GetLazyResourcesBuildManifestJs.js.map +1 -1
  63. package/build/lazyLoad/next_js/next_GetLazyResourcesWebpackJs.js +66 -13
  64. package/build/lazyLoad/next_js/next_GetLazyResourcesWebpackJs.js.map +1 -1
  65. package/build/lazyLoad/next_js/next_parseLayoutJs.js +80 -68
  66. package/build/lazyLoad/next_js/next_parseLayoutJs.js.map +1 -1
  67. package/build/lazyLoad/next_js/next_promiseResolve.js +22 -16
  68. package/build/lazyLoad/next_js/next_promiseResolve.js.map +1 -1
  69. package/build/lazyLoad/nuxt_js/nuxt_astParse.js +49 -47
  70. package/build/lazyLoad/nuxt_js/nuxt_astParse.js.map +1 -1
  71. package/build/lazyLoad/nuxt_js/nuxt_getBuildsManifest.js +64 -0
  72. package/build/lazyLoad/nuxt_js/nuxt_getBuildsManifest.js.map +1 -0
  73. package/build/lazyLoad/nuxt_js/nuxt_getFromPageSource.js +3 -1
  74. package/build/lazyLoad/nuxt_js/nuxt_getFromPageSource.js.map +1 -1
  75. package/build/lazyLoad/nuxt_js/nuxt_stringAnalysisJSFiles.js +3 -2
  76. package/build/lazyLoad/nuxt_js/nuxt_stringAnalysisJSFiles.js.map +1 -1
  77. package/build/lazyLoad/react/react_followImports.js +16 -7
  78. package/build/lazyLoad/react/react_followImports.js.map +1 -1
  79. package/build/lazyLoad/react/react_webpackChunkPaths.js +175 -123
  80. package/build/lazyLoad/react/react_webpackChunkPaths.js.map +1 -1
  81. package/build/lazyLoad/svelte/svelte_getFromPageSource.js +16 -0
  82. package/build/lazyLoad/svelte/svelte_getFromPageSource.js.map +1 -1
  83. package/build/lazyLoad/svelte/svelte_getVersionJson.js +40 -0
  84. package/build/lazyLoad/svelte/svelte_getVersionJson.js.map +1 -0
  85. package/build/lazyLoad/svelte/svelte_stringAnalysisJSFiles.js +3 -2
  86. package/build/lazyLoad/svelte/svelte_stringAnalysisJSFiles.js.map +1 -1
  87. package/build/lazyLoad/techDetect/checkAngularJS.js +27 -6
  88. package/build/lazyLoad/techDetect/checkAngularJS.js.map +1 -1
  89. package/build/lazyLoad/techDetect/checkNextJS.js +24 -15
  90. package/build/lazyLoad/techDetect/checkNextJS.js.map +1 -1
  91. package/build/lazyLoad/techDetect/checkReact.js +8 -0
  92. package/build/lazyLoad/techDetect/checkReact.js.map +1 -1
  93. package/build/lazyLoad/techDetect/checkSvelte.js +17 -0
  94. package/build/lazyLoad/techDetect/checkSvelte.js.map +1 -1
  95. package/build/lazyLoad/techDetect/index.js +33 -5
  96. package/build/lazyLoad/techDetect/index.js.map +1 -1
  97. package/build/lazyLoad/vue/vue_RuntimeJs.js +2 -1
  98. package/build/lazyLoad/vue/vue_RuntimeJs.js.map +1 -1
  99. package/build/lazyLoad/vue/vue_SingleJsFileOnHome.js +2 -1
  100. package/build/lazyLoad/vue/vue_SingleJsFileOnHome.js.map +1 -1
  101. package/build/lazyLoad/vue/vue_discoverJsFiles.js +59 -25
  102. package/build/lazyLoad/vue/vue_discoverJsFiles.js.map +1 -1
  103. package/build/lazyLoad/vue/vue_getClientSidePaths.js +2 -1
  104. package/build/lazyLoad/vue/vue_getClientSidePaths.js.map +1 -1
  105. package/build/lazyLoad/vue/vue_jsImports.js +2 -1
  106. package/build/lazyLoad/vue/vue_jsImports.js.map +1 -1
  107. package/build/lazyLoad/vue/vue_recursiveClientSidePathDownload.js +2 -2
  108. package/build/lazyLoad/vue/vue_recursiveClientSidePathDownload.js.map +1 -1
  109. package/build/lazyLoad/vue/vue_viteMapDeps.js +62 -54
  110. package/build/lazyLoad/vue/vue_viteMapDeps.js.map +1 -1
  111. package/build/map/angular_js/getAngularConnections.js +88 -0
  112. package/build/map/angular_js/getAngularConnections.js.map +1 -0
  113. package/build/map/angular_js/interactive.js +4 -0
  114. package/build/map/angular_js/interactive.js.map +1 -0
  115. package/build/map/graphql/resolveGraphql.js +2 -1
  116. package/build/map/graphql/resolveGraphql.js.map +1 -1
  117. package/build/map/index.js +38 -0
  118. package/build/map/index.js.map +1 -1
  119. package/build/map/next_js/getExports.js +2 -1
  120. package/build/map/next_js/getExports.js.map +1 -1
  121. package/build/map/next_js/getFetchInstances.js +2 -1
  122. package/build/map/next_js/getFetchInstances.js.map +1 -1
  123. package/build/map/next_js/getTurbopackConnections.js +2 -1
  124. package/build/map/next_js/getTurbopackConnections.js.map +1 -1
  125. package/build/map/next_js/getWebpackConnections.js +2 -1
  126. package/build/map/next_js/getWebpackConnections.js.map +1 -1
  127. package/build/map/next_js/resolveAxios.js +2 -1
  128. package/build/map/next_js/resolveAxios.js.map +1 -1
  129. package/build/map/next_js/resolveAxiosHelpers/directCallsWithoutAssignment.js +2 -1
  130. package/build/map/next_js/resolveAxiosHelpers/directCallsWithoutAssignment.js.map +1 -1
  131. package/build/map/next_js/resolveAxiosHelpers/findAxiosInstance.js +2 -1
  132. package/build/map/next_js/resolveAxiosHelpers/findAxiosInstance.js.map +1 -1
  133. package/build/map/next_js/resolveAxiosHelpers/findCrossChunkParams.js +2 -1
  134. package/build/map/next_js/resolveAxiosHelpers/findCrossChunkParams.js.map +1 -1
  135. package/build/map/next_js/resolveAxiosHelpers/handleAxiosCreate.js +2 -1
  136. package/build/map/next_js/resolveAxiosHelpers/handleAxiosCreate.js.map +1 -1
  137. package/build/map/next_js/resolveAxiosHelpers/handleZDotCreate.js +2 -1
  138. package/build/map/next_js/resolveAxiosHelpers/handleZDotCreate.js.map +1 -1
  139. package/build/map/next_js/resolveAxiosHelpers/interceptorHeaders.js +2 -1
  140. package/build/map/next_js/resolveAxiosHelpers/interceptorHeaders.js.map +1 -1
  141. package/build/map/next_js/resolveAxiosHelpers/processExportedEndpoints.js +2 -1
  142. package/build/map/next_js/resolveAxiosHelpers/processExportedEndpoints.js.map +1 -1
  143. package/build/map/next_js/resolveAxiosHelpers/traceAxiosInstanceExports.js +2 -1
  144. package/build/map/next_js/resolveAxiosHelpers/traceAxiosInstanceExports.js.map +1 -1
  145. package/build/map/next_js/resolveAxiosHelpers/traceBody.js +2 -1
  146. package/build/map/next_js/resolveAxiosHelpers/traceBody.js.map +1 -1
  147. package/build/map/next_js/resolveFetch.js +2 -1
  148. package/build/map/next_js/resolveFetch.js.map +1 -1
  149. package/build/map/next_js/resolveNewRequest.js +2 -1
  150. package/build/map/next_js/resolveNewRequest.js.map +1 -1
  151. package/build/map/next_js/resolveServerActions.js +2 -1
  152. package/build/map/next_js/resolveServerActions.js.map +1 -1
  153. package/build/map/next_js/utils.js +2 -1
  154. package/build/map/next_js/utils.js.map +1 -1
  155. package/build/map/react_js/getReactConnections.js +5 -4
  156. package/build/map/react_js/getReactConnections.js.map +1 -1
  157. package/build/map/vue_js/crossFileResolver.js +3 -2
  158. package/build/map/vue_js/crossFileResolver.js.map +1 -1
  159. package/build/map/vue_js/getViteConnections.js +5 -4
  160. package/build/map/vue_js/getViteConnections.js.map +1 -1
  161. package/build/map/vue_js/taint_utils.js +2 -1
  162. package/build/map/vue_js/taint_utils.js.map +1 -1
  163. package/build/map/vue_js/vue_resolveFetch.js +3 -2
  164. package/build/map/vue_js/vue_resolveFetch.js.map +1 -1
  165. package/build/map/vue_js/vue_resolveHttpClient.js +5 -3
  166. package/build/map/vue_js/vue_resolveHttpClient.js.map +1 -1
  167. package/build/map/vue_js/vue_resolveXhr.js +5 -3
  168. package/build/map/vue_js/vue_resolveXhr.js.map +1 -1
  169. package/build/mcp/cli.js.map +1 -1
  170. package/build/refactor/index.js +973 -27
  171. package/build/refactor/index.js.map +1 -1
  172. package/build/refactor/next/helpers.js +395 -0
  173. package/build/refactor/next/helpers.js.map +1 -0
  174. package/build/refactor/next/index.js +261 -71
  175. package/build/refactor/next/index.js.map +1 -1
  176. package/build/refactor/next/transform.js +1027 -0
  177. package/build/refactor/next/transform.js.map +1 -0
  178. package/build/refactor/next/validator.js +119 -0
  179. package/build/refactor/next/validator.js.map +1 -0
  180. package/build/refactor/react/helpers.js +106 -0
  181. package/build/refactor/react/helpers.js.map +1 -0
  182. package/build/refactor/react/index.js +290 -585
  183. package/build/refactor/react/index.js.map +1 -1
  184. package/build/refactor/react/library-classify.js +397 -0
  185. package/build/refactor/react/library-classify.js.map +1 -0
  186. package/build/refactor/react/transform.js +1852 -0
  187. package/build/refactor/react/transform.js.map +1 -0
  188. package/build/refactor/react/validator.js +123 -0
  189. package/build/refactor/react/validator.js.map +1 -0
  190. package/build/refactor/react-vite/index.js +652 -0
  191. package/build/refactor/react-vite/index.js.map +1 -0
  192. package/build/refactor/react-vite/vendor-analyze.js +336 -0
  193. package/build/refactor/react-vite/vendor-analyze.js.map +1 -0
  194. package/build/refactor/remote/cache.js +250 -0
  195. package/build/refactor/remote/cache.js.map +1 -0
  196. package/build/refactor/remote/config.js +63 -0
  197. package/build/refactor/remote/config.js.map +1 -0
  198. package/build/refactor/remote/hf-client.js +202 -0
  199. package/build/refactor/remote/hf-client.js.map +1 -0
  200. package/build/refactor/remote/version-detect.js +355 -0
  201. package/build/refactor/remote/version-detect.js.map +1 -0
  202. package/build/refactor/vue/index.js +176 -0
  203. package/build/refactor/vue/index.js.map +1 -0
  204. package/build/refactor/vue/vendor-analyze-vue.js +271 -0
  205. package/build/refactor/vue/vendor-analyze-vue.js.map +1 -0
  206. package/build/refactor/vue/vite.js +216 -0
  207. package/build/refactor/vue/vite.js.map +1 -0
  208. package/build/report/utility/genHtml.js +15 -4
  209. package/build/report/utility/genHtml.js.map +1 -1
  210. package/build/run/bundler-detect.js +154 -0
  211. package/build/run/bundler-detect.js.map +1 -0
  212. package/build/run/index.js +208 -16
  213. package/build/run/index.js.map +1 -1
  214. package/build/sourcemaps/index.js +89 -0
  215. package/build/sourcemaps/index.js.map +1 -0
  216. package/build/strings/index.js +6 -2
  217. package/build/strings/index.js.map +1 -1
  218. package/build/strings/trufflehog.js +71 -0
  219. package/build/strings/trufflehog.js.map +1 -0
  220. package/build/utility/banner.js +68 -0
  221. package/build/utility/banner.js.map +1 -0
  222. package/build/utility/getChromiumPath.js +40 -0
  223. package/build/utility/getChromiumPath.js.map +1 -0
  224. package/build/utility/globals.js +7 -0
  225. package/build/utility/globals.js.map +1 -1
  226. package/build/utility/makeReq.js +21 -11
  227. package/build/utility/makeReq.js.map +1 -1
  228. package/build/utility/postmanGenerator.js +2 -2
  229. package/build/utility/postmanGenerator.js.map +1 -1
  230. package/build/utility/puppeteerInstance.js +7 -1
  231. package/build/utility/puppeteerInstance.js.map +1 -1
  232. package/package.json +14 -8
  233. package/scripts/smoke-test.js +74 -0
@@ -0,0 +1,652 @@
1
+ // Refactor module for Vite-bundled React apps.
2
+ //
3
+ // Vite (with rolldown) produces already-split ESM files. Each chunk:
4
+ // - imports rolldown interop helpers from rolldown-runtime-*.js
5
+ // - imports from a vendor chunk (vendor-react-*.js)
6
+ // - uses CJS-interop wrappers: var X = __toESM(getter(), 1)
7
+ // - calls library APIs via (0, X.prop)(args)
8
+ //
9
+ // This module:
10
+ // 1. Analyzes the vendor chunk to classify exports
11
+ // 2. For each app chunk, rewrites (0, X.prop)(args) → prop(args)
12
+ // 3. Applies Passes E/F/G via applyModuleCleanupPasses
13
+ // 4. Rewrites direct vendor imports using vendor export map
14
+ // 5. Cleans up rolldown boilerplate
15
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
16
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
17
+ return new (P || (P = Promise))(function (resolve, reject) {
18
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
19
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
20
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
21
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
22
+ });
23
+ };
24
+ var _a, _b;
25
+ import chalk from "chalk";
26
+ import { parse } from "@babel/parser";
27
+ import _traverse from "@babel/traverse";
28
+ import * as t from "@babel/types";
29
+ import _generator from "@babel/generator";
30
+ import path from "path";
31
+ const traverse = ((_a = _traverse.default) !== null && _a !== void 0 ? _a : _traverse);
32
+ import { cs_mast_init } from "@shriyanss/cs-mast";
33
+ import { applyModuleCleanupPasses } from "../react/transform.js";
34
+ import { REACT_CANONICAL, JSX_RUNTIME_CANONICAL, REACT_DOM_CLIENT_CANONICAL, REACT_ROUTER_DOM_CANONICAL, librarySource, } from "../react/library-classify.js";
35
+ import { analyzeVendorChunk } from "./vendor-analyze.js";
36
+ const generate = (_b = _generator.default) !== null && _b !== void 0 ? _b : _generator;
37
+ // ---------------------------------------------------------------------------
38
+ // Vite chunk classification helpers
39
+ // ---------------------------------------------------------------------------
40
+ /**
41
+ * Identifies the rolldown-runtime chunk. It always has a single import (from itself)
42
+ * and exports __toESM (as 'n') and __commonJS (as 't').
43
+ */
44
+ function isRolldownRuntimeChunk(filename) {
45
+ return /rolldown[-_]runtime/i.test(path.basename(filename));
46
+ }
47
+ /**
48
+ * Identifies the vendor chunk. Typically vendor-react-*.js
49
+ */
50
+ function isVendorChunk(filename) {
51
+ return /vendor[-_]react/i.test(path.basename(filename));
52
+ }
53
+ /**
54
+ * Builds a map of chunk-local var name → VendorExportInfo by scanning import
55
+ * declarations against all known vendor chunk export maps.
56
+ */
57
+ function buildLocalVarToVendorExport(statements, vendorExportMaps) {
58
+ const result = new Map();
59
+ for (const stmt of statements) {
60
+ if (!t.isImportDeclaration(stmt))
61
+ continue;
62
+ const sourceBase = path.basename(stmt.source.value);
63
+ for (const [vendorBasename, exportMap] of vendorExportMaps) {
64
+ if (!sourceBase.includes(vendorBasename.replace(/\.js$/, "")))
65
+ continue;
66
+ for (const spec of stmt.specifiers) {
67
+ if (!t.isImportSpecifier(spec))
68
+ continue;
69
+ const importedName = t.isIdentifier(spec.imported)
70
+ ? spec.imported.name
71
+ : spec.imported.value;
72
+ const localName = spec.local.name;
73
+ const exportInfo = exportMap.get(importedName);
74
+ if (exportInfo)
75
+ result.set(localName, exportInfo);
76
+ }
77
+ break;
78
+ }
79
+ }
80
+ return result;
81
+ }
82
+ /**
83
+ * Finds interop vars and classifies them using vendor export map info.
84
+ *
85
+ * Handles two rolldown patterns:
86
+ * - `var X = toESM(getter(), 1)` — wrapped CJS interop
87
+ * - `var X = getter()` — direct CJS call (no toESM)
88
+ *
89
+ * Returns interopVarNames (set of vars to remove) and varToLib (for Pass D).
90
+ */
91
+ function detectInteropVars(statements, toEsmLocalName, localVarToVendorExport) {
92
+ const interopVarNames = new Set();
93
+ const varToLib = new Map();
94
+ for (const stmt of statements) {
95
+ if (!t.isVariableDeclaration(stmt))
96
+ continue;
97
+ for (const decl of stmt.declarations) {
98
+ if (!t.isIdentifier(decl.id) || !decl.init)
99
+ continue;
100
+ if (!t.isCallExpression(decl.init))
101
+ continue;
102
+ const callee = decl.init.callee;
103
+ const args = decl.init.arguments;
104
+ const varName = decl.id.name;
105
+ let getterExportInfo;
106
+ // Pattern 1: toESM(getter(), 1)
107
+ if (toEsmLocalName &&
108
+ t.isIdentifier(callee, { name: toEsmLocalName }) &&
109
+ args.length >= 1 &&
110
+ t.isCallExpression(args[0]) &&
111
+ t.isIdentifier(args[0].callee)) {
112
+ const getterName = args[0].callee.name;
113
+ const info = localVarToVendorExport.get(getterName);
114
+ if (info === null || info === void 0 ? void 0 : info.isCjsGetter)
115
+ getterExportInfo = info;
116
+ }
117
+ // Pattern 2: getter() — direct CJS call without toESM wrapper
118
+ if (!getterExportInfo && t.isIdentifier(callee)) {
119
+ const info = localVarToVendorExport.get(callee.name);
120
+ if (info === null || info === void 0 ? void 0 : info.isCjsGetter)
121
+ getterExportInfo = info;
122
+ }
123
+ if (!getterExportInfo)
124
+ continue;
125
+ interopVarNames.add(varName);
126
+ let libType = "unknown";
127
+ if (getterExportInfo.library === "react")
128
+ libType = "react";
129
+ else if (getterExportInfo.library === "react/jsx-runtime")
130
+ libType = "react-jsx-runtime";
131
+ else if (getterExportInfo.library === "react-dom/client")
132
+ libType = "react-dom-client";
133
+ if (libType !== "unknown") {
134
+ varToLib.set(varName, { varName, libType, exportMap: new Map() });
135
+ }
136
+ }
137
+ }
138
+ return { interopVarNames, varToLib };
139
+ }
140
+ // ---------------------------------------------------------------------------
141
+ // Vite Pass D — rewrite (0, X.prop)(args) → prop(args)
142
+ // ---------------------------------------------------------------------------
143
+ /**
144
+ * Rewrites `(0, X.prop)(args)` → `prop(args)` for known library vars.
145
+ * Also rewrites bare `X.prop` member accesses in non-call positions.
146
+ * Returns a Map from library source path → set of used canonical names.
147
+ */
148
+ function rewriteViteLibraryCalls(statements, varToLib) {
149
+ const usedExports = new Map();
150
+ const record = (libType, name) => {
151
+ const src = librarySource(libType);
152
+ if (!src)
153
+ return;
154
+ if (!usedExports.has(src))
155
+ usedExports.set(src, new Set());
156
+ usedExports.get(src).add(name);
157
+ };
158
+ const resolveViteProp = (varName, prop) => {
159
+ const info = varToLib.get(varName);
160
+ if (!info || info.libType === "unknown")
161
+ return null;
162
+ const isCanonical = (name) => {
163
+ if (info.libType === "react")
164
+ return REACT_CANONICAL.has(name);
165
+ if (info.libType === "react-jsx-runtime")
166
+ return JSX_RUNTIME_CANONICAL.has(name) || name === "Fragment";
167
+ if (info.libType === "react-dom-client")
168
+ return REACT_DOM_CLIENT_CANONICAL.has(name);
169
+ if (info.libType === "react-router-dom")
170
+ return REACT_ROUTER_DOM_CANONICAL.has(name);
171
+ return false;
172
+ };
173
+ if (isCanonical(prop))
174
+ return { canonical: prop, libType: info.libType };
175
+ return null;
176
+ };
177
+ const syntheticFile = t.file(t.program(statements, [], "module"));
178
+ traverse(syntheticFile, {
179
+ CallExpression(p) {
180
+ const callee = p.node.callee;
181
+ // (0, X.prop) form
182
+ if (t.isSequenceExpression(callee) && callee.expressions.length === 2) {
183
+ const [first, second] = callee.expressions;
184
+ if (t.isNumericLiteral(first) &&
185
+ first.value === 0 &&
186
+ t.isMemberExpression(second) &&
187
+ !second.computed &&
188
+ t.isIdentifier(second.object) &&
189
+ t.isIdentifier(second.property)) {
190
+ const varName = second.object.name;
191
+ const prop = second.property.name;
192
+ const resolved = resolveViteProp(varName, prop);
193
+ if (resolved) {
194
+ record(resolved.libType, resolved.canonical);
195
+ p.node.callee = t.identifier(resolved.canonical);
196
+ }
197
+ }
198
+ return;
199
+ }
200
+ // X.prop form
201
+ if (t.isMemberExpression(callee) &&
202
+ !callee.computed &&
203
+ t.isIdentifier(callee.object) &&
204
+ t.isIdentifier(callee.property)) {
205
+ const varName = callee.object.name;
206
+ const prop = callee.property.name;
207
+ const resolved = resolveViteProp(varName, prop);
208
+ if (resolved) {
209
+ record(resolved.libType, resolved.canonical);
210
+ p.node.callee = t.identifier(resolved.canonical);
211
+ }
212
+ }
213
+ },
214
+ MemberExpression(p) {
215
+ // Non-call positions
216
+ if (t.isCallExpression(p.parent) && p.parent.callee === p.node)
217
+ return;
218
+ if (p.node.computed)
219
+ return;
220
+ if (!t.isIdentifier(p.node.object) || !t.isIdentifier(p.node.property))
221
+ return;
222
+ const varName = p.node.object.name;
223
+ const prop = p.node.property.name;
224
+ const resolved = resolveViteProp(varName, prop);
225
+ if (resolved) {
226
+ record(resolved.libType, resolved.canonical);
227
+ p.replaceWith(t.identifier(resolved.canonical));
228
+ p.skip();
229
+ }
230
+ },
231
+ });
232
+ return usedExports;
233
+ }
234
+ // ---------------------------------------------------------------------------
235
+ // Boilerplate removal
236
+ // ---------------------------------------------------------------------------
237
+ /**
238
+ * Removes the `__vite__mapDeps` const declaration.
239
+ * Pattern: const __vite__mapDeps = (i, m=__vite__mapDeps, d=(m.f||(m.f=[...]))) => ...
240
+ */
241
+ function removeViteMapDeps(statements) {
242
+ return statements.filter((stmt) => {
243
+ if (!t.isVariableDeclaration(stmt))
244
+ return true;
245
+ return !stmt.declarations.some((d) => t.isIdentifier(d.id) && d.id.name === "__vite__mapDeps");
246
+ });
247
+ }
248
+ /**
249
+ * Removes modulepreload setup IIFEs.
250
+ * Pattern: (function(){let e=document.createElement(`link`).relList;...})()
251
+ */
252
+ function removeModulepreloadIIFE(statements) {
253
+ return statements.filter((stmt) => {
254
+ if (!t.isExpressionStatement(stmt))
255
+ return true;
256
+ const expr = stmt.expression;
257
+ if (!t.isCallExpression(expr))
258
+ return true;
259
+ const callee = expr.callee;
260
+ if (!t.isFunctionExpression(callee) && !t.isArrowFunctionExpression(callee))
261
+ return true;
262
+ // Detect modulepreload setup by looking for `relList` or `modulepreload` in body
263
+ try {
264
+ const bodyCode = generate(callee).code;
265
+ if (bodyCode.includes("relList") ||
266
+ bodyCode.includes("modulepreload") ||
267
+ (bodyCode.includes("createElement") && bodyCode.includes("link"))) {
268
+ return false;
269
+ }
270
+ }
271
+ catch (_a) {
272
+ // skip
273
+ }
274
+ return true;
275
+ });
276
+ }
277
+ /**
278
+ * Simplifies dynamic imports wrapped with __vite__mapDeps preloading helper.
279
+ * Pattern: (0, o.lazy)(() => o(()=>import('./X.js'), __vite__mapDeps([0,1,2])))
280
+ * After Pass D, becomes: lazy(() => o(()=>import('./X.js'), __vite__mapDeps([0,1,2])))
281
+ * We simplify the inner call: lazy(() => import('./X.js'))
282
+ */
283
+ function simplifyViteMapDepsImports(statements) {
284
+ const syntheticFile = t.file(t.program(statements, [], "module"));
285
+ traverse(syntheticFile, {
286
+ CallExpression(p) {
287
+ // Look for: lazy(() => someWrapper(()=>import('./X.js'), __vite__mapDeps(...)))
288
+ const callee = p.node.callee;
289
+ if (!t.isIdentifier(callee, { name: "lazy" }))
290
+ return;
291
+ if (p.node.arguments.length !== 1)
292
+ return;
293
+ const arg = p.node.arguments[0];
294
+ if (!t.isArrowFunctionExpression(arg))
295
+ return;
296
+ const body = arg.body;
297
+ if (!t.isCallExpression(body))
298
+ return;
299
+ // The inner call has 2 args: ()=>import('./X.js'), __vite__mapDeps(...)
300
+ const innerArgs = body.arguments;
301
+ if (innerArgs.length < 2)
302
+ return;
303
+ const firstInnerArg = innerArgs[0];
304
+ if (!t.isArrowFunctionExpression(firstInnerArg))
305
+ return;
306
+ const innerBody = firstInnerArg.body;
307
+ if (!t.isCallExpression(innerBody))
308
+ return;
309
+ if (!t.isImport(innerBody.callee))
310
+ return;
311
+ // We found: lazy(() => wrapper(() => import('./X.js'), __vite__mapDeps(...)))
312
+ // Simplify to: lazy(() => import('./X.js'))
313
+ p.node.arguments = [t.arrowFunctionExpression([], innerBody)];
314
+ },
315
+ });
316
+ }
317
+ // ---------------------------------------------------------------------------
318
+ // Import rewriting for direct vendor imports
319
+ // ---------------------------------------------------------------------------
320
+ /**
321
+ * Rewrites vendor imports using all known vendor export maps.
322
+ * Removes all vendor chunk imports and replaces direct (non-CJS-getter) exports
323
+ * with proper library imports. Returns new statement list and rename map.
324
+ */
325
+ function rewriteVendorImports(statements, vendorExportMaps) {
326
+ const renames = new Map(); // localSpecifier → canonicalName
327
+ const newLibImports = new Map(); // libraryPath → set of canonical names
328
+ const vendorSources = new Set(); // exact source values to remove
329
+ for (const stmt of statements) {
330
+ if (!t.isImportDeclaration(stmt))
331
+ continue;
332
+ const source = stmt.source.value;
333
+ const sourceBase = path.basename(source);
334
+ let exportMap;
335
+ for (const [vendorBasename, map] of vendorExportMaps) {
336
+ if (sourceBase.includes(vendorBasename.replace(/\.js$/, ""))) {
337
+ exportMap = map;
338
+ vendorSources.add(source);
339
+ break;
340
+ }
341
+ }
342
+ if (!exportMap)
343
+ continue;
344
+ for (const spec of stmt.specifiers) {
345
+ if (!t.isImportSpecifier(spec))
346
+ continue;
347
+ const importedName = t.isIdentifier(spec.imported)
348
+ ? spec.imported.name
349
+ : spec.imported.value;
350
+ const localName = spec.local.name;
351
+ const exportInfo = exportMap.get(importedName);
352
+ if (!exportInfo || exportInfo.isCjsGetter)
353
+ continue;
354
+ // Direct export (react-router-dom component or similar)
355
+ const libPath = exportInfo.library;
356
+ if (!newLibImports.has(libPath))
357
+ newLibImports.set(libPath, new Set());
358
+ newLibImports.get(libPath).add(exportInfo.canonicalName);
359
+ if (localName !== exportInfo.canonicalName) {
360
+ renames.set(localName, exportInfo.canonicalName);
361
+ }
362
+ }
363
+ }
364
+ // Remove all vendor import statements (identified by exact source value)
365
+ const filtered = statements.filter((stmt) => {
366
+ if (!t.isImportDeclaration(stmt))
367
+ return true;
368
+ return !vendorSources.has(stmt.source.value);
369
+ });
370
+ // Build new import declarations for direct exports
371
+ const libImportStmts = [];
372
+ for (const [libPath, canonicalNames] of newLibImports) {
373
+ if (canonicalNames.size === 0)
374
+ continue;
375
+ const specifiers = Array.from(canonicalNames).map((name) => t.importSpecifier(t.identifier(name), t.identifier(name)));
376
+ libImportStmts.push(t.importDeclaration(specifiers, t.stringLiteral(libPath)));
377
+ }
378
+ return {
379
+ newStatements: [...libImportStmts, ...filtered],
380
+ renames,
381
+ };
382
+ }
383
+ /**
384
+ * Renames usages of old identifier names to new names throughout statements.
385
+ */
386
+ function applyRenames(statements, renames) {
387
+ if (renames.size === 0)
388
+ return;
389
+ const syntheticFile = t.file(t.program(statements, [], "module"));
390
+ traverse(syntheticFile, {
391
+ Identifier(p) {
392
+ var _a, _b;
393
+ const newName = renames.get(p.node.name);
394
+ if (!newName)
395
+ return;
396
+ // Skip binding declarations and import specifiers
397
+ if ((_a = p.parentPath) === null || _a === void 0 ? void 0 : _a.isImportSpecifier())
398
+ return;
399
+ if ((_b = p.parentPath) === null || _b === void 0 ? void 0 : _b.isImportDefaultSpecifier())
400
+ return;
401
+ p.node.name = newName;
402
+ },
403
+ JSXIdentifier(p) {
404
+ const newName = renames.get(p.node.name);
405
+ if (!newName)
406
+ return;
407
+ p.node.name = newName;
408
+ },
409
+ });
410
+ }
411
+ // ---------------------------------------------------------------------------
412
+ // Build new library import declarations from usedExports
413
+ // ---------------------------------------------------------------------------
414
+ function buildLibImportStatements(usedExports) {
415
+ const decls = [];
416
+ for (const [libPath, names] of usedExports) {
417
+ if (names.size === 0)
418
+ continue;
419
+ const specifiers = Array.from(names).map((name) => t.importSpecifier(t.identifier(name), t.identifier(name)));
420
+ decls.push(t.importDeclaration(specifiers, t.stringLiteral(libPath)));
421
+ }
422
+ return decls;
423
+ }
424
+ // ---------------------------------------------------------------------------
425
+ // Prune unused named imports (Pass H equivalent)
426
+ // ---------------------------------------------------------------------------
427
+ function collectReferencedNames(stmts) {
428
+ const names = new Set();
429
+ const syntheticFile = t.file(t.program(stmts, [], "module"));
430
+ traverse(syntheticFile, {
431
+ Identifier(p) {
432
+ var _a, _b, _c, _d, _e, _f, _g, _h;
433
+ if ((_a = p.parentPath) === null || _a === void 0 ? void 0 : _a.isImportSpecifier())
434
+ return;
435
+ if ((_b = p.parentPath) === null || _b === void 0 ? void 0 : _b.isImportDefaultSpecifier())
436
+ return;
437
+ if ((_c = p.parentPath) === null || _c === void 0 ? void 0 : _c.isImportNamespaceSpecifier())
438
+ return;
439
+ if (((_d = p.parentPath) === null || _d === void 0 ? void 0 : _d.isMemberExpression()) &&
440
+ !p.parent.computed &&
441
+ p.parentPath.get("property") === p)
442
+ return;
443
+ if (((_e = p.parentPath) === null || _e === void 0 ? void 0 : _e.isObjectProperty()) &&
444
+ !p.parent.computed &&
445
+ p.parentPath.get("key") === p)
446
+ return;
447
+ if ((_f = p.parentPath) === null || _f === void 0 ? void 0 : _f.isJSXAttribute())
448
+ return;
449
+ if (((_g = p.parentPath) === null || _g === void 0 ? void 0 : _g.isJSXOpeningElement()) || ((_h = p.parentPath) === null || _h === void 0 ? void 0 : _h.isJSXClosingElement()))
450
+ return;
451
+ names.add(p.node.name);
452
+ },
453
+ JSXIdentifier(p) {
454
+ names.add(p.node.name);
455
+ },
456
+ });
457
+ return names;
458
+ }
459
+ function pruneUnusedNamedImports(importStmts, bodyStmts) {
460
+ const refs = collectReferencedNames(bodyStmts);
461
+ return importStmts
462
+ .map((stmt) => {
463
+ if (!t.isImportDeclaration(stmt))
464
+ return stmt;
465
+ const prunedSpecifiers = stmt.specifiers.filter((spec) => {
466
+ if (t.isImportNamespaceSpecifier(spec))
467
+ return true;
468
+ if (t.isImportDefaultSpecifier(spec))
469
+ return true;
470
+ if (t.isImportSpecifier(spec)) {
471
+ const localName = t.isIdentifier(spec.local) ? spec.local.name : null;
472
+ return localName ? refs.has(localName) : true;
473
+ }
474
+ return true;
475
+ });
476
+ if (prunedSpecifiers.length === 0)
477
+ return null;
478
+ if (prunedSpecifiers.length === stmt.specifiers.length)
479
+ return stmt;
480
+ return t.importDeclaration(prunedSpecifiers, stmt.source);
481
+ })
482
+ .filter(Boolean);
483
+ }
484
+ // ---------------------------------------------------------------------------
485
+ // CS-MAST library detection (file-level)
486
+ // ---------------------------------------------------------------------------
487
+ const LIB_SIG_SCAT = ["lit", "decl", "loop", "cond"];
488
+ const LIB_FILE_CLASSIFICATION_THRESHOLD = 0.51;
489
+ const fileIsLibrary = (code, libSigs, scatOverride) => {
490
+ if (libSigs.size === 0)
491
+ return false;
492
+ try {
493
+ const tree = cs_mast_init(code, {
494
+ hash: "sha256",
495
+ scat: scatOverride !== null && scatOverride !== void 0 ? scatOverride : LIB_SIG_SCAT,
496
+ sinc: [],
497
+ lang: "js",
498
+ prsr: "@babel/parser",
499
+ });
500
+ const sigs = [...tree._signatureMap.keys()];
501
+ if (sigs.length === 0)
502
+ return false;
503
+ const matchCount = sigs.filter((s) => libSigs.has(s)).length;
504
+ return matchCount / sigs.length >= LIB_FILE_CLASSIFICATION_THRESHOLD;
505
+ }
506
+ catch (_a) {
507
+ return false;
508
+ }
509
+ };
510
+ // ---------------------------------------------------------------------------
511
+ // Main refactor function
512
+ // ---------------------------------------------------------------------------
513
+ /**
514
+ * Refactors Vite-bundled React app chunks.
515
+ *
516
+ * @param chunks - Mapped chunks from the Vite app (vendor + app chunks)
517
+ * @param libSigs - Optional set of library signatures for CS-MAST-based chunk filtering
518
+ * @param scatOverride - Optional scat category override (defaults to lit-decl-loop-cond)
519
+ * @returns Record<filename, refactoredCode>
520
+ */
521
+ export default function refactorVite(chunks, libSigs, scatOverride) {
522
+ return __awaiter(this, void 0, void 0, function* () {
523
+ var _a, _b, _c, _d, _e;
524
+ const result = {};
525
+ // Step 1: Collect all vendor chunks and detect the rolldown runtime chunk
526
+ const vendorChunks = new Map(); // basename → code
527
+ for (const [, chunk] of Object.entries(chunks)) {
528
+ const filename = (_b = (_a = chunk.file) !== null && _a !== void 0 ? _a : chunk.id) !== null && _b !== void 0 ? _b : "";
529
+ const basename = path.basename(filename);
530
+ if (isVendorChunk(basename)) {
531
+ vendorChunks.set(basename, (_c = chunk.code) !== null && _c !== void 0 ? _c : "");
532
+ }
533
+ }
534
+ // Step 2: Analyze all vendor chunks
535
+ const vendorExportMaps = new Map();
536
+ for (const [basename, code] of vendorChunks) {
537
+ vendorExportMaps.set(basename, analyzeVendorChunk(code));
538
+ }
539
+ // Step 3: Process each non-vendor, non-runtime chunk
540
+ for (const [chunkKey, chunk] of Object.entries(chunks)) {
541
+ const filename = (_e = (_d = chunk.file) !== null && _d !== void 0 ? _d : chunk.id) !== null && _e !== void 0 ? _e : chunkKey;
542
+ const basename = path.basename(filename);
543
+ // Skip vendor and runtime chunks (they're not app code)
544
+ if (isVendorChunk(basename))
545
+ continue;
546
+ if (isRolldownRuntimeChunk(basename))
547
+ continue;
548
+ const code = chunk.code;
549
+ if (!code || code.trim().length === 0)
550
+ continue;
551
+ // CS-MAST library detection: skip chunks whose signature set matches the baseline
552
+ if (libSigs && libSigs.size > 0 && fileIsLibrary(code, libSigs, scatOverride)) {
553
+ console.log(chalk.gray(`[-] Chunk ${basename} matches library baseline — skipping`));
554
+ continue;
555
+ }
556
+ let ast;
557
+ try {
558
+ ast = parse(code, {
559
+ sourceType: "module",
560
+ plugins: ["jsx"],
561
+ errorRecovery: true,
562
+ });
563
+ }
564
+ catch (_f) {
565
+ // If parsing fails, keep the original code
566
+ result[chunkKey] = code;
567
+ continue;
568
+ }
569
+ let statements = ast.program.body;
570
+ // Step 3a: Find rolldown-runtime import to identify __toESM local name
571
+ let toEsmLocalName = null;
572
+ for (const stmt of statements) {
573
+ if (!t.isImportDeclaration(stmt))
574
+ continue;
575
+ if (!stmt.source.value.includes("rolldown-runtime"))
576
+ continue;
577
+ for (const spec of stmt.specifiers) {
578
+ if (!t.isImportSpecifier(spec))
579
+ continue;
580
+ const imported = t.isIdentifier(spec.imported)
581
+ ? spec.imported.name
582
+ : spec.imported.value;
583
+ // rolldown exports __toESM as 'n'
584
+ if (imported === "n") {
585
+ toEsmLocalName = spec.local.name;
586
+ }
587
+ }
588
+ }
589
+ // Step 3b: Build local var → vendor export info from import statements
590
+ const localVarToVendorExport = buildLocalVarToVendorExport(statements, vendorExportMaps);
591
+ // Step 3c: Detect interop vars and classify them using vendor export info
592
+ const { interopVarNames, varToLib } = detectInteropVars(statements, toEsmLocalName, localVarToVendorExport);
593
+ // Step 3d: Vite Pass D — rewrite (0, X.prop)(args) → prop(args)
594
+ const usedExports = rewriteViteLibraryCalls(statements, varToLib);
595
+ // Step 3e: Build new library import declarations from usedExports
596
+ const libImportDecls = buildLibImportStatements(usedExports);
597
+ // Step 3f: Apply cleanup passes E/F/G
598
+ const bodyStatements = statements.filter((s) => !t.isImportDeclaration(s));
599
+ const cleanedBody = applyModuleCleanupPasses(bodyStatements);
600
+ // Step 3g: Apply Pass H (prune unused imports)
601
+ const prunedLibImports = pruneUnusedNamedImports(libImportDecls, cleanedBody);
602
+ // Step 3h: Simplify __vite__mapDeps lazy imports
603
+ simplifyViteMapDepsImports(cleanedBody);
604
+ // Step 3i: Remove Vite boilerplate from body
605
+ const cleanedBodyNoBoilerplate = removeViteMapDeps(removeModulepreloadIIFE(cleanedBody));
606
+ // Step 3j: Rewrite direct vendor imports using all vendor export maps
607
+ const vendorImportStmts = statements.filter((s) => t.isImportDeclaration(s));
608
+ const vendorResult = vendorExportMaps.size > 0
609
+ ? rewriteVendorImports(vendorImportStmts, vendorExportMaps)
610
+ : { newStatements: vendorImportStmts, renames: new Map() };
611
+ // Remove rolldown-runtime imports from the resulting statement list
612
+ const filteredNonVendorImports = vendorResult.newStatements.filter((s) => {
613
+ if (!t.isImportDeclaration(s))
614
+ return true;
615
+ return !s.source.value.includes("rolldown-runtime");
616
+ });
617
+ const vendorRenames = vendorResult.renames;
618
+ // Remove interop var declarators from body.
619
+ // When a declaration mixes interop and non-interop declarators, keep non-interop ones.
620
+ const bodyWithoutInteropVars = cleanedBodyNoBoilerplate
621
+ .map((stmt) => {
622
+ if (!t.isVariableDeclaration(stmt))
623
+ return stmt;
624
+ const keptDeclarators = stmt.declarations.filter((d) => !(t.isIdentifier(d.id) && interopVarNames.has(d.id.name)));
625
+ if (keptDeclarators.length === 0)
626
+ return null; // all interop — drop statement
627
+ if (keptDeclarators.length === stmt.declarations.length)
628
+ return stmt; // unchanged
629
+ return t.variableDeclaration(stmt.kind, keptDeclarators);
630
+ })
631
+ .filter(Boolean);
632
+ // Apply vendor renames to the body
633
+ applyRenames(bodyWithoutInteropVars, vendorRenames);
634
+ // Step 3k: Assemble final statement list
635
+ const finalStatements = [
636
+ ...filteredNonVendorImports,
637
+ ...prunedLibImports,
638
+ ...bodyWithoutInteropVars,
639
+ ];
640
+ // Step 3l: Generate code
641
+ try {
642
+ const generated = generate(t.file(t.program(finalStatements, [], "module"))).code;
643
+ result[chunkKey] = generated;
644
+ }
645
+ catch (_g) {
646
+ result[chunkKey] = code; // fallback to original
647
+ }
648
+ }
649
+ return result;
650
+ });
651
+ }
652
+ //# sourceMappingURL=index.js.map