@atlaspack/inspector 0.0.19-canary.3998

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 (235) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +126 -0
  3. package/bin/atlaspack-inspector.js +2 -0
  4. package/lib/backend/cli.js +4 -0
  5. package/lib/backend/config/logger.js +16 -0
  6. package/lib/backend/config/middleware/cacheDataMiddleware.js +60 -0
  7. package/lib/backend/config/middleware/errorHandlingMiddleware.js +17 -0
  8. package/lib/backend/config/middleware/errorHandlingMiddleware.test.js +44 -0
  9. package/lib/backend/config/middleware/loggingMiddleware.js +22 -0
  10. package/lib/backend/controllers/BundleGraphController.js +42 -0
  11. package/lib/backend/controllers/CacheDataController.js +143 -0
  12. package/lib/backend/controllers/FrontendAssetsController.js +61 -0
  13. package/lib/backend/controllers/TreeMapController.js +108 -0
  14. package/lib/backend/controllers/mcp/InspectorMCP.js +231 -0
  15. package/lib/backend/controllers/mcp/InspectorMCPController.js +16 -0
  16. package/lib/backend/errors/HTTPError.js +16 -0
  17. package/lib/backend/errors/HTTPError.test.js +21 -0
  18. package/lib/backend/index.js +177 -0
  19. package/lib/backend/services/AnalyticsService.js +86 -0
  20. package/lib/backend/services/LazyValue.js +33 -0
  21. package/lib/backend/services/LazyValue.test.js +12 -0
  22. package/lib/backend/services/buildJsonGraph.js +86 -0
  23. package/lib/backend/services/buildTreemap.js +140 -0
  24. package/lib/backend/services/buildTreemapBundle.test.js +298 -0
  25. package/lib/backend/services/findSourceCodeUrl.js +107 -0
  26. package/lib/backend/services/findSourceCodeUrl.test.js +216 -0
  27. package/lib/backend/services/getCacheStats.js +36 -0
  28. package/lib/backend/services/getCacheStats.test.js +162 -0
  29. package/lib/backend/services/getDisplayName.js +18 -0
  30. package/lib/backend/services/getDisplayName.test.js +71 -0
  31. package/lib/backend/services/loadCacheData.js +209 -0
  32. package/lib/backend/services/loadCacheData.test.js +79 -0
  33. package/lib/backend/testing/TemporaryDirectory.js +46 -0
  34. package/lib/frontend/node_modules/@atlaspack/packager-js/lib/dev-prelude.js +145 -0
  35. package/lib/frontend/node_modules/@atlaspack/packager-js/src/dev-prelude.js +145 -0
  36. package/package.json +75 -0
  37. package/screenshots/bottom-up.png +0 -0
  38. package/screenshots/cache-inspector.png +0 -0
  39. package/screenshots/treemap.png +0 -0
  40. package/src/backend/README.md +14 -0
  41. package/src/backend/cli.ts +3 -0
  42. package/src/backend/config/logger.ts +14 -0
  43. package/src/backend/config/middleware/cacheDataMiddleware.ts +94 -0
  44. package/src/backend/config/middleware/errorHandlingMiddleware.test.ts +52 -0
  45. package/src/backend/config/middleware/errorHandlingMiddleware.ts +20 -0
  46. package/src/backend/config/middleware/loggingMiddleware.ts +24 -0
  47. package/src/backend/controllers/BundleGraphController.ts +73 -0
  48. package/src/backend/controllers/CacheDataController.ts +187 -0
  49. package/src/backend/controllers/FrontendAssetsController.ts +28 -0
  50. package/src/backend/controllers/TreeMapController.ts +143 -0
  51. package/src/backend/controllers/mcp/InspectorMCP.ts +311 -0
  52. package/src/backend/controllers/mcp/InspectorMCPController.ts +17 -0
  53. package/src/backend/errors/HTTPError.test.ts +19 -0
  54. package/src/backend/errors/HTTPError.ts +14 -0
  55. package/src/backend/globals.d.ts +9 -0
  56. package/src/backend/index.ts +271 -0
  57. package/src/backend/services/AnalyticsService.ts +118 -0
  58. package/src/backend/services/LazyValue.test.ts +13 -0
  59. package/src/backend/services/LazyValue.ts +29 -0
  60. package/src/backend/services/buildJsonGraph.ts +124 -0
  61. package/src/backend/services/buildTreemap.ts +273 -0
  62. package/src/backend/services/buildTreemapBundle.test.ts +348 -0
  63. package/src/backend/services/findSourceCodeUrl.test.ts +228 -0
  64. package/src/backend/services/findSourceCodeUrl.ts +146 -0
  65. package/src/backend/services/getCacheStats.test.ts +169 -0
  66. package/src/backend/services/getCacheStats.ts +46 -0
  67. package/src/backend/services/getDisplayName.test.ts +84 -0
  68. package/src/backend/services/getDisplayName.ts +20 -0
  69. package/src/backend/services/loadCacheData.test.ts +101 -0
  70. package/src/backend/services/loadCacheData.ts +294 -0
  71. package/src/backend/testing/TemporaryDirectory.ts +50 -0
  72. package/src/frontend/.atlaspackrc +4 -0
  73. package/src/frontend/.eslintrc.json +19 -0
  74. package/src/frontend/dist/atlassian-dark-brand-refresh.91b786da.js +2 -0
  75. package/src/frontend/dist/atlassian-dark-brand-refresh.91b786da.js.map +1 -0
  76. package/src/frontend/dist/atlassian-dark-future.59ebadca.js +2 -0
  77. package/src/frontend/dist/atlassian-dark-future.59ebadca.js.map +1 -0
  78. package/src/frontend/dist/atlassian-dark-increased-contrast.ff6775f2.js +2 -0
  79. package/src/frontend/dist/atlassian-dark-increased-contrast.ff6775f2.js.map +1 -0
  80. package/src/frontend/dist/atlassian-dark.ad679134.js +2 -0
  81. package/src/frontend/dist/atlassian-dark.ad679134.js.map +1 -0
  82. package/src/frontend/dist/atlassian-legacy-dark.8aa27f7f.js +2 -0
  83. package/src/frontend/dist/atlassian-legacy-dark.8aa27f7f.js.map +1 -0
  84. package/src/frontend/dist/atlassian-legacy-light.2eb372ce.js +2 -0
  85. package/src/frontend/dist/atlassian-legacy-light.2eb372ce.js.map +1 -0
  86. package/src/frontend/dist/atlassian-light-brand-refresh.fadcab0a.js +2 -0
  87. package/src/frontend/dist/atlassian-light-brand-refresh.fadcab0a.js.map +1 -0
  88. package/src/frontend/dist/atlassian-light-future.612afe8a.js +2 -0
  89. package/src/frontend/dist/atlassian-light-future.612afe8a.js.map +1 -0
  90. package/src/frontend/dist/atlassian-light-increased-contrast.7161cd79.js +2 -0
  91. package/src/frontend/dist/atlassian-light-increased-contrast.7161cd79.js.map +1 -0
  92. package/src/frontend/dist/atlassian-light.bc343d4c.js +2 -0
  93. package/src/frontend/dist/atlassian-light.bc343d4c.js.map +1 -0
  94. package/src/frontend/dist/atlassian-shape.b92d69c0.js +2 -0
  95. package/src/frontend/dist/atlassian-shape.b92d69c0.js.map +1 -0
  96. package/src/frontend/dist/atlassian-spacing.60ddd8e7.js +2 -0
  97. package/src/frontend/dist/atlassian-spacing.60ddd8e7.js.map +1 -0
  98. package/src/frontend/dist/atlassian-typography-adg3.f88947f6.js +2 -0
  99. package/src/frontend/dist/atlassian-typography-adg3.f88947f6.js.map +1 -0
  100. package/src/frontend/dist/atlassian-typography-modernized.42016c51.js +2 -0
  101. package/src/frontend/dist/atlassian-typography-modernized.42016c51.js.map +1 -0
  102. package/src/frontend/dist/atlassian-typography-refreshed.ec0d111b.js +2 -0
  103. package/src/frontend/dist/atlassian-typography-refreshed.ec0d111b.js.map +1 -0
  104. package/src/frontend/dist/atlassian-typography.66d7e8f4.js +2 -0
  105. package/src/frontend/dist/atlassian-typography.66d7e8f4.js.map +1 -0
  106. package/src/frontend/dist/badge-light.7e55986a.png +0 -0
  107. package/src/frontend/dist/custom-theme.4680282a.js +2 -0
  108. package/src/frontend/dist/custom-theme.4680282a.js.map +1 -0
  109. package/src/frontend/dist/drag-handle.136830d3.js +2 -0
  110. package/src/frontend/dist/drag-handle.136830d3.js.map +1 -0
  111. package/src/frontend/dist/drag-handle.63bdb345.css +2 -0
  112. package/src/frontend/dist/drag-handle.63bdb345.css.map +1 -0
  113. package/src/frontend/dist/index.a41fafce.css +2 -0
  114. package/src/frontend/dist/index.a41fafce.css.map +1 -0
  115. package/src/frontend/dist/index.a4ce2b12.js +28 -0
  116. package/src/frontend/dist/index.a4ce2b12.js.map +1 -0
  117. package/src/frontend/dist/index.html +1 -0
  118. package/src/frontend/dist/index.runtime.a729d997.js +2 -0
  119. package/src/frontend/dist/index.runtime.a729d997.js.map +1 -0
  120. package/src/frontend/dist/refractor.2c1fd9a1.js +2 -0
  121. package/src/frontend/dist/refractor.2c1fd9a1.js.map +1 -0
  122. package/src/frontend/index.html +11 -0
  123. package/src/frontend/jest.config.js +16 -0
  124. package/src/frontend/package.json +64 -0
  125. package/src/frontend/src/APIError.test.ts +72 -0
  126. package/src/frontend/src/APIError.tsx +29 -0
  127. package/src/frontend/src/AppRoutes.tsx +56 -0
  128. package/src/frontend/src/hack-feature-flags.ts +6 -0
  129. package/src/frontend/src/main.tsx +50 -0
  130. package/src/frontend/src/test/stubCssModule.js +1 -0
  131. package/src/frontend/src/ui/App.module.css +122 -0
  132. package/src/frontend/src/ui/App.module.css.d.ts +8 -0
  133. package/src/frontend/src/ui/AppLayout/AppLayout.tsx +26 -0
  134. package/src/frontend/src/ui/AppLayout/SidebarNavigation/LinkItem.tsx +26 -0
  135. package/src/frontend/src/ui/AppLayout/SidebarNavigation/SidebarNavigation.tsx +45 -0
  136. package/src/frontend/src/ui/AppLayout/TopNavigation/Logo.module.css +12 -0
  137. package/src/frontend/src/ui/AppLayout/TopNavigation/Logo.module.css.d.ts +4 -0
  138. package/src/frontend/src/ui/AppLayout/TopNavigation/Logo.tsx +11 -0
  139. package/src/frontend/src/ui/AppLayout/TopNavigation/TopNavigation.module.css +14 -0
  140. package/src/frontend/src/ui/AppLayout/TopNavigation/TopNavigation.module.css.d.ts +3 -0
  141. package/src/frontend/src/ui/AppLayout/TopNavigation/TopNavigation.tsx +45 -0
  142. package/src/frontend/src/ui/AppLayout/TopNavigation/badge-light.png +0 -0
  143. package/src/frontend/src/ui/AppLayout/TopNavigation/logo-light.png +0 -0
  144. package/src/frontend/src/ui/DefaultLoadingIndicator/DefaultLoadingIndicator.module.css +9 -0
  145. package/src/frontend/src/ui/DefaultLoadingIndicator/DefaultLoadingIndicator.module.css.d.ts +3 -0
  146. package/src/frontend/src/ui/DefaultLoadingIndicator/DefaultLoadingIndicator.test.tsx +15 -0
  147. package/src/frontend/src/ui/DefaultLoadingIndicator/DefaultLoadingIndicator.tsx +14 -0
  148. package/src/frontend/src/ui/app/StatsPage.tsx +77 -0
  149. package/src/frontend/src/ui/app/cache/CacheKeysIndexPage.tsx +13 -0
  150. package/src/frontend/src/ui/app/cache/CacheKeysPage.module.css +11 -0
  151. package/src/frontend/src/ui/app/cache/CacheKeysPage.module.css.d.ts +4 -0
  152. package/src/frontend/src/ui/app/cache/CacheKeysPage.tsx +23 -0
  153. package/src/frontend/src/ui/app/cache/[key]/CacheValuePage.tsx +40 -0
  154. package/src/frontend/src/ui/app/cache/ui/CacheKeyList.module.css +40 -0
  155. package/src/frontend/src/ui/app/cache/ui/CacheKeyList.module.css.d.ts +7 -0
  156. package/src/frontend/src/ui/app/cache/ui/CacheKeyList.tsx +187 -0
  157. package/src/frontend/src/ui/app/cache-invalidation/CacheInvalidationPage.tsx +22 -0
  158. package/src/frontend/src/ui/app/cache-invalidation/[fileId]/CacheInvalidationFilePage.tsx +22 -0
  159. package/src/frontend/src/ui/app/cache-invalidation/ui/CacheFileList.module.css +40 -0
  160. package/src/frontend/src/ui/app/cache-invalidation/ui/CacheFileList.module.css.d.ts +7 -0
  161. package/src/frontend/src/ui/app/cache-invalidation/ui/CacheFileList.tsx +185 -0
  162. package/src/frontend/src/ui/app/treemap/BottomPanelResizeState.test.ts +25 -0
  163. package/src/frontend/src/ui/app/treemap/BottomPanelResizeState.tsx +48 -0
  164. package/src/frontend/src/ui/app/treemap/FoamTreemapPage.module.css +24 -0
  165. package/src/frontend/src/ui/app/treemap/FoamTreemapPage.module.css.d.ts +6 -0
  166. package/src/frontend/src/ui/app/treemap/FoamTreemapPage.tsx +47 -0
  167. package/src/frontend/src/ui/app/treemap/controllers/RelatedBundlesController.tsx +41 -0
  168. package/src/frontend/src/ui/app/treemap/controllers/UrlFocusController.tsx +33 -0
  169. package/src/frontend/src/ui/app/treemap/ui/BottomPanel/BottomPanel.module.css +24 -0
  170. package/src/frontend/src/ui/app/treemap/ui/BottomPanel/BottomPanel.module.css.d.ts +5 -0
  171. package/src/frontend/src/ui/app/treemap/ui/BottomPanel/BottomPanel.tsx +24 -0
  172. package/src/frontend/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/AdvancedSettings.module.css +13 -0
  173. package/src/frontend/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/AdvancedSettings.module.css.d.ts +5 -0
  174. package/src/frontend/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/AdvancedSettings.tsx +53 -0
  175. package/src/frontend/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/AssetTable/AssetTable.tsx +135 -0
  176. package/src/frontend/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/AssetTable/CollapsibleTable/CollapsibleTable.module.css +7 -0
  177. package/src/frontend/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/AssetTable/CollapsibleTable/CollapsibleTable.module.css.d.ts +3 -0
  178. package/src/frontend/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/AssetTable/CollapsibleTable/CollapsibleTable.tsx +123 -0
  179. package/src/frontend/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/AssetTable/CollapsibleTable/CollapsibleTableModel.tsx +18 -0
  180. package/src/frontend/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/AssetTable/CollapsibleTable/CollapsibleTableRow.module.css +20 -0
  181. package/src/frontend/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/AssetTable/CollapsibleTable/CollapsibleTableRow.module.css.d.ts +6 -0
  182. package/src/frontend/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/AssetTable/CollapsibleTable/CollapsibleTableRow.tsx +79 -0
  183. package/src/frontend/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/AssetTable/getFileURL.test.ts +19 -0
  184. package/src/frontend/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/AssetTable/getFileURL.ts +24 -0
  185. package/src/frontend/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/FocusedGroupInfo.module.css +20 -0
  186. package/src/frontend/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/FocusedGroupInfo.module.css.d.ts +5 -0
  187. package/src/frontend/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/FocusedGroupInfo.tsx +42 -0
  188. package/src/frontend/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/FocusedGroupInfoInner.module.css +29 -0
  189. package/src/frontend/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/FocusedGroupInfoInner.module.css.d.ts +6 -0
  190. package/src/frontend/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/FocusedGroupInfoInner.tsx +107 -0
  191. package/src/frontend/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/GraphContainer.module.css +7 -0
  192. package/src/frontend/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/GraphContainer.module.css.d.ts +3 -0
  193. package/src/frontend/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/GraphContainer.tsx +20 -0
  194. package/src/frontend/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/SourceCodeURL.tsx +5 -0
  195. package/src/frontend/src/ui/app/treemap/ui/BundleGraphRenderer.module.css +13 -0
  196. package/src/frontend/src/ui/app/treemap/ui/BundleGraphRenderer.module.css.d.ts +4 -0
  197. package/src/frontend/src/ui/app/treemap/ui/BundleGraphRenderer.tsx +95 -0
  198. package/src/frontend/src/ui/app/treemap/ui/FocusBreadcrumbs/FocusBreadcrumbs.module.css +6 -0
  199. package/src/frontend/src/ui/app/treemap/ui/FocusBreadcrumbs/FocusBreadcrumbs.module.css.d.ts +3 -0
  200. package/src/frontend/src/ui/app/treemap/ui/FocusBreadcrumbs/FocusBreadcrumbs.tsx +49 -0
  201. package/src/frontend/src/ui/app/treemap/ui/SigmaGraph.module.css +5 -0
  202. package/src/frontend/src/ui/app/treemap/ui/SigmaGraph.module.css.d.ts +3 -0
  203. package/src/frontend/src/ui/app/treemap/ui/SigmaGraph.tsx +80 -0
  204. package/src/frontend/src/ui/app/treemap/ui/Treemap.tsx +14 -0
  205. package/src/frontend/src/ui/app/treemap/ui/TreemapRenderer/ImpactScore.module.css +32 -0
  206. package/src/frontend/src/ui/app/treemap/ui/TreemapRenderer/ImpactScore.module.css.d.ts +5 -0
  207. package/src/frontend/src/ui/app/treemap/ui/TreemapRenderer/ImpactScore.tsx +24 -0
  208. package/src/frontend/src/ui/app/treemap/ui/TreemapRenderer/TreemapRenderer.module.css +14 -0
  209. package/src/frontend/src/ui/app/treemap/ui/TreemapRenderer/TreemapRenderer.module.css.d.ts +4 -0
  210. package/src/frontend/src/ui/app/treemap/ui/TreemapRenderer/TreemapRenderer.tsx +271 -0
  211. package/src/frontend/src/ui/app/treemap/ui/TreemapRenderer/TreemapTooltip.module.css +15 -0
  212. package/src/frontend/src/ui/app/treemap/ui/TreemapRenderer/TreemapTooltip.module.css.d.ts +4 -0
  213. package/src/frontend/src/ui/app/treemap/ui/TreemapRenderer/TreemapTooltip.tsx +111 -0
  214. package/src/frontend/src/ui/app/treemap/ui/TreemapRenderer/controllers/useStableCallback.test.ts +27 -0
  215. package/src/frontend/src/ui/app/treemap/ui/TreemapRenderer/controllers/useStableCallback.ts +21 -0
  216. package/src/frontend/src/ui/app/treemap/ui/TreemapRenderer/useMouseMoveController.ts +20 -0
  217. package/src/frontend/src/ui/globals.css +26 -0
  218. package/src/frontend/src/ui/globals.css.d.ts +1 -0
  219. package/src/frontend/src/ui/globals.d.ts +9 -0
  220. package/src/frontend/src/ui/model/ViewModel.test.ts +31 -0
  221. package/src/frontend/src/ui/model/ViewModel.ts +62 -0
  222. package/src/frontend/src/ui/not-found/NotFoundPage.module.css +7 -0
  223. package/src/frontend/src/ui/not-found/NotFoundPage.module.css.d.ts +3 -0
  224. package/src/frontend/src/ui/not-found/NotFoundPage.tsx +9 -0
  225. package/src/frontend/src/ui/types/Graph.tsx +12 -0
  226. package/src/frontend/src/ui/util/ErrorBoundary.module.css +3 -0
  227. package/src/frontend/src/ui/util/ErrorBoundary.module.css.d.ts +3 -0
  228. package/src/frontend/src/ui/util/ErrorBoundary.test.tsx +65 -0
  229. package/src/frontend/src/ui/util/ErrorBoundary.tsx +75 -0
  230. package/src/frontend/src/ui/util/colorPalette.tsx +122 -0
  231. package/src/frontend/src/ui/util/formatBytes.test.ts +13 -0
  232. package/src/frontend/src/ui/util/formatBytes.tsx +9 -0
  233. package/src/frontend/src/ui/util/getRandomDarkerColor.tsx +31 -0
  234. package/src/frontend/tsconfig.json +12 -0
  235. package/src/frontend/yarn.lock +0 -0
@@ -0,0 +1,162 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ const assert_1 = __importDefault(require("assert"));
40
+ const sinon = __importStar(require("sinon"));
41
+ const getCacheStats_1 = require("./getCacheStats");
42
+ describe('getCacheStats', function () {
43
+ let sandbox;
44
+ let mockCache;
45
+ beforeEach(() => {
46
+ sandbox = sinon.createSandbox();
47
+ mockCache = {
48
+ keys: sandbox.stub(),
49
+ getBlobSync: sandbox.stub(),
50
+ };
51
+ });
52
+ afterEach(() => {
53
+ sandbox.restore();
54
+ });
55
+ it('should return empty stats for empty cache', function () {
56
+ mockCache.keys.returns([]);
57
+ const result = (0, getCacheStats_1.getCacheStats)(mockCache);
58
+ assert_1.default.deepEqual(result, {
59
+ size: 0,
60
+ count: 0,
61
+ keySize: 0,
62
+ assetContentCount: 0,
63
+ assetContentSize: 0,
64
+ assetMapCount: 0,
65
+ assetMapSize: 0,
66
+ });
67
+ });
68
+ it('should calculate stats for cache with regular keys', function () {
69
+ const mockKeys = ['key1', 'key2', 'key3'];
70
+ const mockValues = [
71
+ Buffer.from('value1'),
72
+ Buffer.from('value2'),
73
+ Buffer.from('value3'),
74
+ ];
75
+ mockCache.keys.returns(mockKeys);
76
+ mockCache.getBlobSync.onCall(0).returns(mockValues[0]);
77
+ mockCache.getBlobSync.onCall(1).returns(mockValues[1]);
78
+ mockCache.getBlobSync.onCall(2).returns(mockValues[2]);
79
+ const result = (0, getCacheStats_1.getCacheStats)(mockCache);
80
+ const expectedSize = mockValues[0].length + mockValues[1].length + mockValues[2].length;
81
+ const expectedKeySize = Buffer.from('key1').length +
82
+ Buffer.from('key2').length +
83
+ Buffer.from('key3').length;
84
+ assert_1.default.equal(result.size, expectedSize);
85
+ assert_1.default.equal(result.count, 3);
86
+ assert_1.default.equal(result.keySize, expectedKeySize);
87
+ assert_1.default.equal(result.assetContentCount, 0);
88
+ assert_1.default.equal(result.assetContentSize, 0);
89
+ assert_1.default.equal(result.assetMapCount, 0);
90
+ assert_1.default.equal(result.assetMapSize, 0);
91
+ });
92
+ it('should count asset content keys correctly', function () {
93
+ const mockKeys = ['asset1:content', 'asset2:content', 'other-key'];
94
+ const mockValues = [
95
+ Buffer.from('content1'),
96
+ Buffer.from('content2'),
97
+ Buffer.from('other'),
98
+ ];
99
+ mockCache.keys.returns(mockKeys);
100
+ mockCache.getBlobSync.onCall(0).returns(mockValues[0]);
101
+ mockCache.getBlobSync.onCall(1).returns(mockValues[1]);
102
+ mockCache.getBlobSync.onCall(2).returns(mockValues[2]);
103
+ const result = (0, getCacheStats_1.getCacheStats)(mockCache);
104
+ assert_1.default.equal(result.assetContentCount, 2);
105
+ assert_1.default.equal(result.assetContentSize, mockValues[0].length + mockValues[1].length);
106
+ });
107
+ it('should count asset map keys correctly', function () {
108
+ const mockKeys = ['asset1:map', 'asset2:map', 'other-key'];
109
+ const mockValues = [
110
+ Buffer.from('map1'),
111
+ Buffer.from('map2'),
112
+ Buffer.from('other'),
113
+ ];
114
+ mockCache.keys.returns(mockKeys);
115
+ mockCache.getBlobSync.onCall(0).returns(mockValues[0]);
116
+ mockCache.getBlobSync.onCall(1).returns(mockValues[1]);
117
+ mockCache.getBlobSync.onCall(2).returns(mockValues[2]);
118
+ const result = (0, getCacheStats_1.getCacheStats)(mockCache);
119
+ assert_1.default.equal(result.assetMapCount, 2);
120
+ assert_1.default.equal(result.assetMapSize, mockValues[0].length + mockValues[1].length);
121
+ });
122
+ it('should handle mixed cache keys correctly', function () {
123
+ const mockKeys = [
124
+ 'asset1:content',
125
+ 'asset2:map',
126
+ 'regular-key',
127
+ 'asset3:content',
128
+ 'asset4:map',
129
+ ];
130
+ const mockValues = [
131
+ Buffer.from('content1'),
132
+ Buffer.from('map1'),
133
+ Buffer.from('regular'),
134
+ Buffer.from('content2'),
135
+ Buffer.from('map2'),
136
+ ];
137
+ mockCache.keys.returns(mockKeys);
138
+ mockValues.forEach((value, index) => {
139
+ mockCache.getBlobSync.onCall(index).returns(value);
140
+ });
141
+ const result = (0, getCacheStats_1.getCacheStats)(mockCache);
142
+ const totalSize = mockValues.reduce((sum, val) => sum + val.length, 0);
143
+ const totalKeySize = mockKeys.reduce((sum, key) => sum + Buffer.from(key).length, 0);
144
+ assert_1.default.equal(result.size, totalSize);
145
+ assert_1.default.equal(result.count, 5);
146
+ assert_1.default.equal(result.keySize, totalKeySize);
147
+ assert_1.default.equal(result.assetContentCount, 2);
148
+ assert_1.default.equal(result.assetContentSize, mockValues[0].length + mockValues[3].length);
149
+ assert_1.default.equal(result.assetMapCount, 2);
150
+ assert_1.default.equal(result.assetMapSize, mockValues[1].length + mockValues[4].length);
151
+ });
152
+ it('should handle empty string keys', function () {
153
+ const mockKeys = [''];
154
+ const mockValues = [Buffer.from('')];
155
+ mockCache.keys.returns(mockKeys);
156
+ mockCache.getBlobSync.onCall(0).returns(mockValues[0]);
157
+ const result = (0, getCacheStats_1.getCacheStats)(mockCache);
158
+ assert_1.default.equal(result.size, 0);
159
+ assert_1.default.equal(result.count, 1);
160
+ assert_1.default.equal(result.keySize, 0);
161
+ });
162
+ });
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getDisplayName = getDisplayName;
4
+ function getDisplayName(node) {
5
+ if (node.type === 'asset') {
6
+ return `asset: ${node.value.filePath}`;
7
+ }
8
+ if (node.type === 'dependency') {
9
+ return `dependency: import '${node.value.specifier}'`;
10
+ }
11
+ if (node.type === 'asset_group') {
12
+ return `asset group: ${node.value.filePath}`;
13
+ }
14
+ if (node.type === 'bundle') {
15
+ return `bundle: ${node.value.displayName}`;
16
+ }
17
+ return node.id;
18
+ }
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const assert_1 = __importDefault(require("assert"));
7
+ const getDisplayName_1 = require("./getDisplayName");
8
+ describe('getDisplayName', function () {
9
+ it('should return display name for asset node', function () {
10
+ const assetNode = {
11
+ type: 'asset',
12
+ value: {
13
+ filePath: '/path/to/file.js',
14
+ },
15
+ id: 'asset1',
16
+ };
17
+ const result = (0, getDisplayName_1.getDisplayName)(assetNode);
18
+ assert_1.default.equal(result, 'asset: /path/to/file.js');
19
+ });
20
+ it('should return display name for dependency node', function () {
21
+ const dependencyNode = {
22
+ type: 'dependency',
23
+ value: {
24
+ specifier: './module',
25
+ },
26
+ id: 'dep1',
27
+ };
28
+ const result = (0, getDisplayName_1.getDisplayName)(dependencyNode);
29
+ assert_1.default.equal(result, "dependency: import './module'");
30
+ });
31
+ it('should return display name for asset_group node', function () {
32
+ const assetGroupNode = {
33
+ type: 'asset_group',
34
+ value: {
35
+ filePath: '/path/to/asset-group.js',
36
+ },
37
+ id: 'group1',
38
+ };
39
+ const result = (0, getDisplayName_1.getDisplayName)(assetGroupNode);
40
+ assert_1.default.equal(result, 'asset group: /path/to/asset-group.js');
41
+ });
42
+ it('should return display name for bundle node', function () {
43
+ const bundleNode = {
44
+ type: 'bundle',
45
+ value: {
46
+ displayName: 'main.js',
47
+ },
48
+ id: 'bundle1',
49
+ };
50
+ const result = (0, getDisplayName_1.getDisplayName)(bundleNode);
51
+ assert_1.default.equal(result, 'bundle: main.js');
52
+ });
53
+ it('should return node id for unknown node type', function () {
54
+ const unknownNode = {
55
+ type: 'unknown',
56
+ value: {},
57
+ id: 'unknown123',
58
+ };
59
+ const result = (0, getDisplayName_1.getDisplayName)(unknownNode);
60
+ assert_1.default.equal(result, 'unknown123');
61
+ });
62
+ it('should return node id when value is null', function () {
63
+ const nodeWithNullValue = {
64
+ type: 'unknown_type',
65
+ value: null,
66
+ id: 'null-asset',
67
+ };
68
+ const result = (0, getDisplayName_1.getDisplayName)(nodeWithNullValue);
69
+ assert_1.default.equal(result, 'null-asset');
70
+ });
71
+ });
@@ -0,0 +1,209 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.loadRequestTracker = loadRequestTracker;
7
+ exports.findCachePath = findCachePath;
8
+ exports.loadCacheData = loadCacheData;
9
+ /* eslint-disable monorepo/no-internal-import */
10
+ const path_1 = __importDefault(require("path"));
11
+ const v8_1 = __importDefault(require("v8"));
12
+ const build_cache_1 = require("@atlaspack/build-cache");
13
+ const cache_1 = require("@atlaspack/cache");
14
+ // @ts-expect-error TS2749
15
+ const RequestTracker_js_1 = __importDefault(require("@atlaspack/core/lib/RequestTracker.js"));
16
+ const package_json_1 = require("@atlaspack/core/package.json");
17
+ const RequestTracker_js_2 = require("@atlaspack/core/lib/RequestTracker.js");
18
+ const fs_1 = __importDefault(require("fs"));
19
+ const buildTreemap_1 = require("./buildTreemap");
20
+ const logger_1 = require("../config/logger");
21
+ const LazyValue_1 = require("./LazyValue");
22
+ /**
23
+ * Similar to `@atlaspack/query`.
24
+ *
25
+ * Since query is using a different approach to determine valid BundleGraph/AssetGraph in
26
+ * the cache it was easier to rewrite this here.
27
+ *
28
+ * This will find the first `RequestGraph` entry in the cache and load it.
29
+ *
30
+ * We should be keeping meta-data about the builds that correspond to these entries so as
31
+ * to load the most relevant one (for example the most recent) as well as performing
32
+ * clean-up in other areas of the `atlaspack` codebase.
33
+ */
34
+ async function loadRequestTracker(cache) {
35
+ let requestGraphBlob = null;
36
+ for (let key of cache.keys()) {
37
+ if (key.startsWith('RequestTracker/') && key.endsWith('/RequestGraph')) {
38
+ requestGraphBlob = key;
39
+ }
40
+ }
41
+ if (!requestGraphBlob) {
42
+ logger_1.logger.warn('No request graph key found in cache');
43
+ return { requestTracker: null };
44
+ }
45
+ const requestGraphKey = requestGraphBlob.split('/').slice(0, -1).join('/');
46
+ try {
47
+ logger_1.logger.debug({ requestGraphBlob, requestGraphKey }, 'Loading RequestGraph...');
48
+ const { requestGraph } = await (0, RequestTracker_js_2.readAndDeserializeRequestGraph)(cache, requestGraphBlob, requestGraphKey);
49
+ const requestTracker = new RequestTracker_js_1.default({
50
+ graph: requestGraph,
51
+ farm: null,
52
+ options: null,
53
+ });
54
+ return {
55
+ requestTracker,
56
+ };
57
+ }
58
+ catch (e) {
59
+ logger_1.logger.error(e, `Error loading Request Graph.
60
+
61
+ A failure happened when loading atlaspack cache data.
62
+
63
+ This might happen because:
64
+
65
+ - There is a version mismatch between the atlaspack-inspector and the atlaspack CLI used to build the cache
66
+ - The cache was built without the required 'cachePerformanceImprovements' feature flag set to true
67
+
68
+ The inspector will try to load caches even if there are version mismatches, but it might fail due to breaking
69
+ changes between versions.
70
+
71
+ You can run "atlaspack-inspector build <entrypoint...>" to build the app for the inspector with correct
72
+ feature-flags.`);
73
+ return {
74
+ requestTracker: null,
75
+ };
76
+ }
77
+ }
78
+ /**
79
+ * Find the cache path from the `--target` flag.
80
+ *
81
+ * This is meant to make the tool nicer to use by forgiving a developer if they specify
82
+ * `--target` as the path to their project root or to a sub-directory, instead of the
83
+ * cache.
84
+ *
85
+ * It will also prevent creating caches where there were none, since opening a non-existent
86
+ * cache would create a new empty cache.
87
+ */
88
+ function findCachePath(target) {
89
+ target = path_1.default.resolve(process.cwd(), target);
90
+ if (fs_1.default.existsSync(path_1.default.join(target, 'data.mdb'))) {
91
+ return target;
92
+ }
93
+ if (fs_1.default.existsSync(path_1.default.join(target, '.parcel-cache'))) {
94
+ return path_1.default.join(target, '.parcel-cache');
95
+ }
96
+ if (fs_1.default.existsSync(path_1.default.join(target, '.atlaspack-cache'))) {
97
+ return path_1.default.join(target, '.atlaspack-cache');
98
+ }
99
+ if (path_1.default.dirname(target) !== target &&
100
+ target &&
101
+ target !== '/' &&
102
+ target !== '.') {
103
+ return findCachePath(path_1.default.dirname(target));
104
+ }
105
+ return null;
106
+ }
107
+ function mapObjectStringValues(object, fn) {
108
+ if (typeof object !== 'object' || object === null) {
109
+ return object;
110
+ }
111
+ if (Array.isArray(object)) {
112
+ return object;
113
+ }
114
+ return Object.fromEntries(Object.entries(object).map(([key, value]) => {
115
+ if (typeof value === 'string') {
116
+ return [key, fn(key, value)];
117
+ }
118
+ if (value &&
119
+ typeof value === 'object' &&
120
+ value.constructor.name !== 'Object') {
121
+ return [key, value];
122
+ }
123
+ return [key, mapObjectStringValues(value, fn)];
124
+ }));
125
+ }
126
+ function getSync(cache, key) {
127
+ const blob = cache.getBlobSync(key);
128
+ if (!blob) {
129
+ return null;
130
+ }
131
+ let deserialized = v8_1.default.deserialize(blob);
132
+ deserialized = mapObjectStringValues(deserialized, (key, value) => {
133
+ if (key === '$$type') {
134
+ return value.replace(/^\d+\.\d+\.\d+:/, `${package_json_1.version}:`);
135
+ }
136
+ return value;
137
+ });
138
+ return (0, build_cache_1.restoreDeserializedObject)(deserialized);
139
+ }
140
+ /**
141
+ * Loads the cache and pre-processes some data.
142
+ */
143
+ async function loadCacheData({ target, projectRoot, repositoryRoot, }) {
144
+ const cachePath = findCachePath(target);
145
+ if (!cachePath) {
146
+ throw new Error(`Invalid cache path provided, could not find cache in any directory above the path provided: ${target}.
147
+
148
+ Make sure you have run "atlaspack build --feature-flag cachePerformanceImprovements=true" before running the inspector.
149
+
150
+ Alternatively you can run "atlaspack-inspector build <entrypoint...>" to build the app for the inspector.`);
151
+ }
152
+ logger_1.logger.info({ cachePath, projectRoot }, 'Loading graphs...');
153
+ const cache = new cache_1.LMDBLiteCache(cachePath);
154
+ const { requestTracker } = await loadRequestTracker(cache);
155
+ if (!requestTracker) {
156
+ throw new Error('Failed to load request tracker');
157
+ }
158
+ logger_1.logger.debug('Loaded RequestTracker');
159
+ const bundleGraphLazyValue = new LazyValue_1.LazyValue(() => {
160
+ logger_1.logger.info('Loading BundleGraph...');
161
+ const bundleGraphRequest = requestTracker.graph.nodes.find((node) => node &&
162
+ node.type === 1 &&
163
+ node.requestType === RequestTracker_js_2.requestTypes.bundle_graph_request);
164
+ const bundleGraph = bundleGraphRequest?.resultCacheKey &&
165
+ getSync(cache, bundleGraphRequest.resultCacheKey)?.bundleGraph;
166
+ if (!bundleGraphRequest) {
167
+ logger_1.logger.error('Failed to find bundle graph request');
168
+ }
169
+ else if (bundleGraph != null) {
170
+ logger_1.logger.debug('Loaded BundleGraph');
171
+ }
172
+ return bundleGraph;
173
+ });
174
+ const treemap = new LazyValue_1.LazyValue(() => {
175
+ logger_1.logger.info({ projectRoot }, 'Building treemap...');
176
+ const bundleGraph = bundleGraphLazyValue.get();
177
+ return bundleGraph && requestTracker
178
+ ? (0, buildTreemap_1.buildTreemap)({ projectRoot, repositoryRoot, bundleGraph, requestTracker })
179
+ : null;
180
+ });
181
+ const assetGraph = new LazyValue_1.LazyValue(() => {
182
+ logger_1.logger.info('Loading AssetGraph...');
183
+ const assetGraphRequest = requestTracker.graph.nodes.find((node) => node &&
184
+ node.type === 1 &&
185
+ node.requestType === RequestTracker_js_2.requestTypes.asset_graph_request);
186
+ const assetGraph = assetGraphRequest?.resultCacheKey &&
187
+ getSync(cache, assetGraphRequest.resultCacheKey)?.assetGraph;
188
+ if (!assetGraphRequest) {
189
+ logger_1.logger.error('Failed to find asset graph request');
190
+ }
191
+ else if (assetGraph != null) {
192
+ logger_1.logger.debug('Loaded AssetGraph');
193
+ }
194
+ return assetGraph;
195
+ });
196
+ return {
197
+ get assetGraph() {
198
+ return assetGraph.get();
199
+ },
200
+ get bundleGraph() {
201
+ return bundleGraphLazyValue.get();
202
+ },
203
+ get treemap() {
204
+ return treemap.get();
205
+ },
206
+ cache,
207
+ requestTracker,
208
+ };
209
+ }
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const path_1 = __importDefault(require("path"));
7
+ const TemporaryDirectory_1 = require("../testing/TemporaryDirectory");
8
+ const core_1 = __importDefault(require("@atlaspack/core"));
9
+ const fs_1 = __importDefault(require("fs"));
10
+ const loadCacheData_1 = require("./loadCacheData");
11
+ const assert_1 = __importDefault(require("assert"));
12
+ jest.mock('../config/logger');
13
+ async function setupMockProject() {
14
+ const tempDir = new TemporaryDirectory_1.TemporaryDirectory();
15
+ await fs_1.default.promises.writeFile(path_1.default.join(tempDir.get(), '.git'), '', 'utf-8');
16
+ await fs_1.default.promises.writeFile(path_1.default.join(tempDir.get(), '.parcelrc'), JSON.stringify({
17
+ extends: '@atlaspack/config-default',
18
+ }), 'utf-8');
19
+ await fs_1.default.promises.writeFile(path_1.default.join(tempDir.get(), 'index.js'), `
20
+ import './a.js';
21
+ import './b.js';
22
+ `, 'utf-8');
23
+ await fs_1.default.promises.writeFile(path_1.default.join(tempDir.get(), 'a.js'), 'console.log("Hello, world!");', 'utf-8');
24
+ await fs_1.default.promises.writeFile(path_1.default.join(tempDir.get(), 'b.js'), 'console.log("Hello, world!");', 'utf-8');
25
+ const atlaspack = new core_1.default({
26
+ featureFlags: {
27
+ cachePerformanceImprovements: true,
28
+ },
29
+ entries: [path_1.default.join(tempDir.get(), 'index.js')],
30
+ });
31
+ await atlaspack.run();
32
+ return tempDir;
33
+ }
34
+ describe('loadCacheData', () => {
35
+ it('should load the cache data', async () => {
36
+ const tempDir = await setupMockProject();
37
+ const cacheData = await (0, loadCacheData_1.loadCacheData)({
38
+ target: tempDir.get(),
39
+ projectRoot: tempDir.get(),
40
+ repositoryRoot: tempDir.get(),
41
+ });
42
+ const assetGraph = cacheData.assetGraph;
43
+ let numAssets = 0;
44
+ assetGraph.traverseAssets(() => {
45
+ numAssets++;
46
+ });
47
+ assert_1.default.equal(numAssets, 3);
48
+ const treemap = cacheData.treemap;
49
+ const assetTree = treemap?.bundles[0].assetTree;
50
+ const cleanNode = (node) => {
51
+ delete node.id;
52
+ Object.values(node.children).forEach(cleanNode);
53
+ };
54
+ cleanNode(assetTree);
55
+ expect(assetTree).toMatchInlineSnapshot(`
56
+ {
57
+ "children": {
58
+ "a.js": {
59
+ "children": {},
60
+ "path": "/a.js",
61
+ "size": 30,
62
+ },
63
+ "b.js": {
64
+ "children": {},
65
+ "path": "/b.js",
66
+ "size": 30,
67
+ },
68
+ "index.js": {
69
+ "children": {},
70
+ "path": "/index.js",
71
+ "size": 60,
72
+ },
73
+ },
74
+ "path": "",
75
+ "size": 120,
76
+ }
77
+ `);
78
+ });
79
+ });
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.TemporaryDirectory = void 0;
7
+ const fs_1 = require("fs");
8
+ const crypto_1 = require("crypto");
9
+ const path_1 = __importDefault(require("path"));
10
+ afterAll(() => {
11
+ const tmpDir = path_1.default.join(__dirname, 'tmp');
12
+ if ((0, fs_1.existsSync)(tmpDir)) {
13
+ (0, fs_1.rmSync)(tmpDir, { recursive: true, force: true });
14
+ }
15
+ });
16
+ /**
17
+ * Testing helper to create a temporary directory and remove it when
18
+ * tests complete.
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * {
23
+ * const tempDir = new TemporaryDirectory();
24
+ * console.log(tempDir.get());
25
+ * }
26
+ * // the directory will be automatically removed
27
+ * // both by testing hooks and by custom dispose logic.
28
+ * ```
29
+ */
30
+ class TemporaryDirectory {
31
+ constructor() {
32
+ const randomId = (0, crypto_1.randomUUID)();
33
+ this.path = path_1.default.join(__dirname, 'tmp', 'atlaspack-inspector-tests', `${randomId}`);
34
+ (0, fs_1.mkdirSync)(this.path, { recursive: true });
35
+ }
36
+ /**
37
+ * The file-path to the temporary directory.
38
+ */
39
+ get() {
40
+ return this.path;
41
+ }
42
+ [Symbol.dispose]() {
43
+ (0, fs_1.rmSync)(this.path, { recursive: true, force: true });
44
+ }
45
+ }
46
+ exports.TemporaryDirectory = TemporaryDirectory;