@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,11 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <title>Atlaspack Inspector</title>
5
+ </head>
6
+ <body>
7
+ <div id="root"></div>
8
+
9
+ <script src="src/main.tsx" type="module"></script>
10
+ </body>
11
+ </html>
@@ -0,0 +1,16 @@
1
+ const {createDefaultPreset} = require('ts-jest');
2
+
3
+ const tsJestTransformCfg = createDefaultPreset().transform;
4
+
5
+ /** @type {import("jest").Config} **/
6
+ module.exports = {
7
+ testEnvironment: 'jsdom',
8
+ transform: {
9
+ ...tsJestTransformCfg,
10
+ },
11
+ moduleNameMapper: {
12
+ '\\.css$': '<rootDir>/src/test/stubCssModule.js',
13
+ '\\.module\\.css$': '<rootDir>/src/test/stubCssModule.js',
14
+ },
15
+ collectCoverageFrom: ['src/**/*.tsx'],
16
+ };
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "@atlaspack/inspector-frontend",
3
+ "version": "0.1.0",
4
+ "license": "MIT",
5
+ "authors": [
6
+ "Pedro Tacla Yamada"
7
+ ],
8
+ "publishConfig": {
9
+ "access": "public"
10
+ },
11
+ "scripts": {
12
+ "dev": "ATLASPACK_INSPECTOR_BACKEND_URL='http://localhost:3000' atlaspack serve --feature-flag cachePerformanceImprovements=true --cache-dir=.atlaspack-cache ./index.html",
13
+ "build:css-types": "rm -rf src/**/*.module.css.d.ts && tcm --namedExports ./src && prettier --write src/**/*.css.d.ts",
14
+ "lint": "oxlint",
15
+ "build": "yarn build:css-types && rm -rf .atlaspack-cache && rm -rf dist && ATLASPACK_INSPECTOR_BACKEND_URL='' atlaspack build --feature-flag cachePerformanceImprovements=false --cache-dir=.atlaspack-cache ./index.html",
16
+ "prepack": "yarn run build",
17
+ "test": "yarn test:unit",
18
+ "test:unit": "jest",
19
+ "typecheck": "tsc --noEmit"
20
+ },
21
+ "dependencies": {
22
+ "@atlaskit/app-provider": "^2.2.1",
23
+ "@atlaskit/code": "^17.2.2",
24
+ "@atlaskit/css-reset": "^7.3.2",
25
+ "@atlaskit/heading": "^5.2.1",
26
+ "@atlaskit/logo": "^19.0.1",
27
+ "@atlaskit/navigation-system": "^0.170.0",
28
+ "@atlaskit/primitives": "^14.8.4",
29
+ "@atlaskit/tabs": "^18.1.2",
30
+ "@atlaspack/cli": "2.14.4",
31
+ "@atlaspack/core": "2.23.2",
32
+ "@atlaspack/graph": "3.5.18",
33
+ "@carrotsearch/foamtree": "^3.5.2",
34
+ "@tanstack/react-query": "^5.81.5",
35
+ "@tanstack/react-virtual": "^3.13.12",
36
+ "axios": "^1.9.0",
37
+ "graphology": "^0.26.0",
38
+ "graphology-layout": "^0.6.1",
39
+ "graphology-layout-forceatlas2": "^0.10.1",
40
+ "graphology-types": "^0.24.8",
41
+ "mobx": "^6.13.7",
42
+ "mobx-react-lite": "^4.1.0",
43
+ "path-browserify": "^1.0.1",
44
+ "react": "^18.2.0",
45
+ "react-dom": "^18.2.0",
46
+ "react-router": "^7.6.0",
47
+ "sigma": "^3.0.1"
48
+ },
49
+ "browserslist": "Chrome 75",
50
+ "devDependencies": {
51
+ "@testing-library/dom": "^10.4.0",
52
+ "@testing-library/react": "^16.3.0",
53
+ "@testing-library/jest-dom": "^6.6.3",
54
+ "@types/react": "^18.2.0",
55
+ "@types/react-dom": "^18.2.0",
56
+ "eslint-config-react-app": "^7.0.1",
57
+ "jest": "^30.0.4",
58
+ "jest-environment-jsdom": "^30.0.4",
59
+ "oxlint": "^1.2.0",
60
+ "ts-jest": "^29.4.0",
61
+ "typed-css-modules": "^0.9.1"
62
+ },
63
+ "type": "commonjs"
64
+ }
@@ -0,0 +1,72 @@
1
+ import assert from 'assert';
2
+ import {AxiosError} from 'axios';
3
+
4
+ import {APIError} from './APIError';
5
+
6
+ /**
7
+ * Helper to create a minimal AxiosError-like object for testing purposes.
8
+ */
9
+ function createAxiosError(
10
+ method: string,
11
+ url: string,
12
+ status?: number,
13
+ statusText?: string,
14
+ data?: unknown,
15
+ cause?: Error,
16
+ ): AxiosError {
17
+ return {
18
+ name: 'AxiosError',
19
+ message: 'mock',
20
+ config: {method, url} as any,
21
+ response: status ? ({status, statusText, data} as any) : undefined,
22
+ cause,
23
+ isAxiosError: true,
24
+ toJSON() {
25
+ return {};
26
+ },
27
+ } as unknown as AxiosError;
28
+ }
29
+
30
+ describe('APIError', function () {
31
+ it('should create message including method, url, status, statusText and data', function () {
32
+ const axiosErr = createAxiosError(
33
+ 'get',
34
+ '/api/test',
35
+ 404,
36
+ 'Not Found',
37
+ 'Page not found',
38
+ );
39
+
40
+ const error = new APIError(axiosErr);
41
+
42
+ assert(
43
+ error.message.includes('GET /api/test 404 Not Found'),
44
+ 'Expected message to include HTTP method, url, and status',
45
+ );
46
+ assert(
47
+ error.message.includes('Page not found'),
48
+ 'Expected message to include response data',
49
+ );
50
+ assert(error instanceof Error);
51
+ assert(error instanceof APIError);
52
+ });
53
+
54
+ it('should include cause message when provided', function () {
55
+ const cause = new Error('connection closed');
56
+ const axiosErr = createAxiosError(
57
+ 'post',
58
+ '/api/submit',
59
+ 500,
60
+ 'Internal Server Error',
61
+ undefined,
62
+ cause,
63
+ );
64
+
65
+ const error = new APIError(axiosErr);
66
+
67
+ assert(
68
+ error.message.includes('connection closed'),
69
+ 'Expected error message to include cause',
70
+ );
71
+ });
72
+ });
@@ -0,0 +1,29 @@
1
+ import {AxiosError} from 'axios';
2
+
3
+ /**
4
+ * A custom error class for HTTP errors.
5
+ */
6
+ export class APIError extends Error {
7
+ constructor(err: AxiosError) {
8
+ const url = err.config?.url;
9
+ const method = err.config?.method;
10
+ const status = err.response?.status;
11
+ const statusText = err.response?.statusText;
12
+ const data = err.response?.data;
13
+ const cause = err.cause;
14
+
15
+ super(
16
+ `Failed to fetch: ${[
17
+ method?.toUpperCase(),
18
+ url,
19
+ status,
20
+ statusText,
21
+ cause?.message,
22
+ '\n',
23
+ JSON.stringify(data, null, 2),
24
+ ]
25
+ .filter(Boolean)
26
+ .join(' ')}`,
27
+ );
28
+ }
29
+ }
@@ -0,0 +1,56 @@
1
+ import {Routes, Route} from 'react-router';
2
+ import {Suspense} from 'react';
3
+
4
+ import {CacheValuePage} from './ui/app/cache/[key]/CacheValuePage';
5
+ import {CacheKeysIndexPage} from './ui/app/cache/CacheKeysIndexPage';
6
+ import {StatsPage} from './ui/app/StatsPage';
7
+ import {FoamTreemapPage} from './ui/app/treemap/FoamTreemapPage';
8
+ import {AppLayout} from './ui/AppLayout/AppLayout';
9
+ import {CacheKeysPage} from './ui/app/cache/CacheKeysPage';
10
+ import {CacheInvalidationPage} from './ui/app/cache-invalidation/CacheInvalidationPage';
11
+ import {NotFoundPage} from './ui/not-found/NotFoundPage';
12
+ import {ErrorBoundary} from './ui/util/ErrorBoundary';
13
+ import {DefaultLoadingIndicator} from './ui/DefaultLoadingIndicator/DefaultLoadingIndicator';
14
+ import {CacheInvalidationFilePage} from './ui/app/cache-invalidation/[fileId]/CacheInvalidationFilePage';
15
+
16
+ /**
17
+ * All the routes in the atlaspack-inspector app.
18
+ */
19
+ export default function AppRoutes() {
20
+ return (
21
+ <Suspense
22
+ fallback={
23
+ <DefaultLoadingIndicator message="Loading atlaspack-inspector..." />
24
+ }
25
+ >
26
+ <ErrorBoundary>
27
+ <Routes>
28
+ <Route path="/" element={<AppLayout />}>
29
+ <Route index element={<FoamTreemapPage />} />
30
+
31
+ <Route path="/app/cache-stats" element={<StatsPage />} />
32
+ <Route path="/app/cache" element={<CacheKeysPage />}>
33
+ <Route index element={<CacheKeysIndexPage />} />
34
+ <Route path="/app/cache/:key" element={<CacheValuePage />} />
35
+ </Route>
36
+
37
+ <Route
38
+ path="/app/cache-invalidation"
39
+ element={<CacheInvalidationPage />}
40
+ >
41
+ <Route index element={null} />
42
+ <Route
43
+ path="/app/cache-invalidation/:fileId"
44
+ element={<CacheInvalidationFilePage />}
45
+ />
46
+ </Route>
47
+
48
+ <Route path="/app/treemap" element={<FoamTreemapPage />} />
49
+
50
+ <Route path="*" element={<NotFoundPage />} />
51
+ </Route>
52
+ </Routes>
53
+ </ErrorBoundary>
54
+ </Suspense>
55
+ );
56
+ }
@@ -0,0 +1,6 @@
1
+ // @ts-expect-error
2
+ window.__PLATFORM_FEATURE_FLAGS__ = {
3
+ booleanResolver() {
4
+ return true;
5
+ },
6
+ };
@@ -0,0 +1,50 @@
1
+ import './hack-feature-flags';
2
+ import './ui/globals.css';
3
+ import {createRoot} from 'react-dom/client';
4
+ import {BrowserRouter} from 'react-router';
5
+ import {
6
+ QueryClient,
7
+ QueryClientProvider,
8
+ QueryFunction,
9
+ } from '@tanstack/react-query';
10
+ import axios, {AxiosError} from 'axios';
11
+
12
+ import AppRoutes from './AppRoutes';
13
+ import {APIError} from './APIError';
14
+
15
+ const defaultQueryFn: QueryFunction = async ({queryKey}) => {
16
+ const backendUrl = process.env.ATLASPACK_INSPECTOR_BACKEND_URL;
17
+ try {
18
+ const {data} = await axios.get(`${backendUrl}${queryKey[0]}`);
19
+ return data;
20
+ } catch (err) {
21
+ if (err instanceof AxiosError) {
22
+ throw new APIError(err);
23
+ }
24
+
25
+ throw err;
26
+ }
27
+ };
28
+
29
+ const queryClient = new QueryClient({
30
+ defaultOptions: {
31
+ queries: {
32
+ queryFn: defaultQueryFn,
33
+ },
34
+ },
35
+ });
36
+
37
+ const rootElement = document.getElementById('root');
38
+ if (!rootElement) {
39
+ throw new Error('Failed to find the root element');
40
+ }
41
+
42
+ const root = createRoot(rootElement);
43
+
44
+ root.render(
45
+ <QueryClientProvider client={queryClient}>
46
+ <BrowserRouter>
47
+ <AppRoutes />
48
+ </BrowserRouter>
49
+ </QueryClientProvider>,
50
+ );
@@ -0,0 +1 @@
1
+ module.exports = {};
@@ -0,0 +1,122 @@
1
+ .app {
2
+ display: flex;
3
+ height: 100vh;
4
+ width: 100vw;
5
+
6
+ color: var(--color);
7
+ background-color: var(--background-color);
8
+
9
+ --background-color: rgb(255, 255, 255);
10
+ --color: rgb(0, 0, 0);
11
+ --border-color: #b8b8b8;
12
+ --base-spacing: 4px;
13
+ }
14
+
15
+ h1,
16
+ h2,
17
+ h3,
18
+ h4,
19
+ h5,
20
+ h6 {
21
+ margin: 0;
22
+ padding: 0;
23
+ }
24
+
25
+ .sidebar {
26
+ height: 100vh;
27
+ overflow-y: scroll;
28
+ /* width: 300px; */
29
+ border-right: 1px solid #434343;
30
+ display: flex;
31
+ flex-direction: column;
32
+ /* flex: 0 0 300px; */
33
+ }
34
+
35
+ .sidebar h1 {
36
+ padding: calc(var(--base-spacing) / 2) var(--base-spacing);
37
+ border-bottom: 1px solid var(--border-color);
38
+ }
39
+
40
+ .sidebar ul {
41
+ list-style: none;
42
+ padding: 0px;
43
+ margin: 0;
44
+ display: flex;
45
+ flex-direction: column;
46
+ }
47
+
48
+ .sidebar .sidebarItem {
49
+ padding: var(--base-spacing);
50
+ white-space: nowrap;
51
+ border-bottom: 1px solid var(--border-color);
52
+ text-overflow: ellipsis;
53
+ max-width: 100%;
54
+ overflow: hidden;
55
+ }
56
+
57
+ .sidebar .sidebarItem:hover {
58
+ background-color: var(--color);
59
+ color: var(--background-color);
60
+ }
61
+
62
+ .sidebar .sidebarItem a {
63
+ text-decoration: none;
64
+ color: inherit;
65
+ display: inline-block;
66
+ text-overflow: ellipsis;
67
+ height: 100%;
68
+ width: 100%;
69
+ overflow: hidden;
70
+ }
71
+
72
+ .sidebarFilter {
73
+ display: flex;
74
+ gap: calc(var(--base-spacing) * 2);
75
+ border-bottom: 1px solid var(--border-color);
76
+ padding: calc(var(--base-spacing) * 2) var(--base-spacing);
77
+ }
78
+
79
+ .sidebarFilter select {
80
+ flex: 1;
81
+ }
82
+
83
+ table {
84
+ border-collapse: collapse;
85
+ }
86
+
87
+ table td {
88
+ border: solid 1px var(--border-color);
89
+ margin: 0;
90
+ padding: calc(var(--base-spacing) / 2) var(--base-spacing);
91
+ }
92
+
93
+ .content {
94
+ flex: 1;
95
+ display: flex;
96
+ width: calc(100% - 300px);
97
+ overflow-x: scroll;
98
+ flex-direction: column;
99
+ gap: calc(var(--base-spacing) * 2);
100
+ min-height: 100%;
101
+ /* padding: calc(var(--base-spacing) / 2) var(--base-spacing); */
102
+ }
103
+
104
+ .contentInner {
105
+ min-height: 100%;
106
+ }
107
+
108
+ .treemapTable tr {
109
+ border-bottom: solid 1px var(--ds-border);
110
+ }
111
+
112
+ .treemapTable tr:focus-within {
113
+ background-color: #dbe7ff !important;
114
+ }
115
+
116
+ .treemapTable tr:nth-child(even) {
117
+ background-color: #e7e7e79b;
118
+ }
119
+
120
+ .treemapTable tr:hover {
121
+ background-color: var(--ds-background-neutral-hovered);
122
+ }
@@ -0,0 +1,8 @@
1
+ export const __esModule: true;
2
+ export const app: string;
3
+ export const content: string;
4
+ export const contentInner: string;
5
+ export const sidebar: string;
6
+ export const sidebarFilter: string;
7
+ export const sidebarItem: string;
8
+ export const treemapTable: string;
@@ -0,0 +1,26 @@
1
+ import '@atlaskit/css-reset';
2
+ import {Root as PageLayoutRoot} from '@atlaskit/navigation-system/layout/root';
3
+ import AppProvider from '@atlaskit/app-provider';
4
+ import {Main} from '@atlaskit/navigation-system';
5
+ import {Outlet} from 'react-router';
6
+ import {useState} from 'react';
7
+ import {TopNavigation} from './TopNavigation/TopNavigation';
8
+ import {SidebarNavigation} from './SidebarNavigation/SidebarNavigation';
9
+
10
+ export function AppLayout() {
11
+ const [sidebarCollapsed, setSidebarCollapsed] = useState(false);
12
+
13
+ return (
14
+ <AppProvider>
15
+ <PageLayoutRoot>
16
+ <TopNavigation setSidebarCollapsed={setSidebarCollapsed} />
17
+
18
+ {sidebarCollapsed ? null : <SidebarNavigation />}
19
+
20
+ <Main>
21
+ <Outlet />
22
+ </Main>
23
+ </PageLayoutRoot>
24
+ </AppProvider>
25
+ );
26
+ }
@@ -0,0 +1,26 @@
1
+ import {LinkMenuItem} from '@atlaskit/navigation-system';
2
+ import {useCallback} from 'react';
3
+ import {useNavigate} from 'react-router';
4
+
5
+ interface LinkItemProps {
6
+ href: string;
7
+ children: React.ReactNode;
8
+ elemBefore: React.ReactNode;
9
+ }
10
+
11
+ export function LinkItem({href, children, elemBefore}: LinkItemProps) {
12
+ const navigate = useNavigate();
13
+ const onClick = useCallback(
14
+ (e: React.MouseEvent<HTMLAnchorElement>) => {
15
+ e.preventDefault();
16
+ navigate(href);
17
+ },
18
+ [href, navigate],
19
+ );
20
+
21
+ return (
22
+ <LinkMenuItem href={href} onClick={onClick} elemBefore={elemBefore}>
23
+ {children}
24
+ </LinkMenuItem>
25
+ );
26
+ }
@@ -0,0 +1,45 @@
1
+ import '@atlaskit/css-reset';
2
+ import {
3
+ SideNav,
4
+ SideNavContent,
5
+ } from '@atlaskit/navigation-system/layout/side-nav';
6
+ import {PanelSplitter} from '@atlaskit/navigation-system';
7
+ import HomeIcon from '@atlaskit/icon/glyph/home';
8
+ import CacheData from '@atlaskit/icon/glyph/component';
9
+ import PageIcon from '@atlaskit/icon/glyph/page';
10
+ import {LinkItem} from './LinkItem';
11
+
12
+ export function SidebarNavigation() {
13
+ return (
14
+ <SideNav>
15
+ <SideNavContent>
16
+ <LinkItem elemBefore={<PageIcon label="Page" />} href="/">
17
+ Bundle size data
18
+ </LinkItem>
19
+
20
+ <LinkItem
21
+ elemBefore={<HomeIcon label="Home" />}
22
+ href="/app/cache-stats"
23
+ >
24
+ Cache statistics
25
+ </LinkItem>
26
+
27
+ <LinkItem
28
+ elemBefore={<CacheData label="Cache invalidation" />}
29
+ href="/app/cache-invalidation"
30
+ >
31
+ Cache invalidation
32
+ </LinkItem>
33
+
34
+ <LinkItem
35
+ elemBefore={<CacheData label="Cache data" />}
36
+ href="/app/cache"
37
+ >
38
+ Cache data
39
+ </LinkItem>
40
+ </SideNavContent>
41
+
42
+ <PanelSplitter label="Resize side nav" />
43
+ </SideNav>
44
+ );
45
+ }
@@ -0,0 +1,12 @@
1
+ .logo {
2
+ display: flex;
3
+ align-items: center;
4
+ gap: 8px;
5
+ }
6
+
7
+ .logoText {
8
+ color: var(--ds-text);
9
+ font-size: 20px;
10
+ font-weight: 600;
11
+ text-decoration: none !important;
12
+ }
@@ -0,0 +1,4 @@
1
+ export const __esModule: true;
2
+ export const logo: string;
3
+ export const logoText: string;
4
+
@@ -0,0 +1,11 @@
1
+ import atlaspackBadge from './badge-light.png';
2
+ import * as styles from './Logo.module.css';
3
+
4
+ export function Logo() {
5
+ return (
6
+ <div className={styles.logo}>
7
+ <img src={atlaspackBadge} alt="Atlaspack" />
8
+ <span className={styles.logoText}>Atlaspack</span>
9
+ </div>
10
+ );
11
+ }
@@ -0,0 +1,14 @@
1
+ .logoContainer {
2
+ max-height: 48px;
3
+ display: flex;
4
+ align-items: center;
5
+ }
6
+
7
+ .logoContainer img {
8
+ height: calc(48px - 24px);
9
+ width: auto;
10
+ }
11
+
12
+ .logoContainer a {
13
+ text-decoration: none !important;
14
+ }
@@ -0,0 +1,3 @@
1
+ export const __esModule: true;
2
+ export const logoContainer: string;
3
+
@@ -0,0 +1,45 @@
1
+ import '@atlaskit/css-reset';
2
+ import {SideNavToggleButton} from '@atlaskit/navigation-system/layout/side-nav';
3
+ import {TopNav, TopNavStart} from '@atlaskit/navigation-system/layout/top-nav';
4
+ import {Link, useNavigate} from 'react-router';
5
+ import {useCallback} from 'react';
6
+ import {Logo} from './Logo';
7
+ import * as styles from './TopNavigation.module.css';
8
+
9
+ interface TopNavigationProps {
10
+ setSidebarCollapsed: (update: (collapsed: boolean) => boolean) => void;
11
+ }
12
+
13
+ export function TopNavigation({setSidebarCollapsed}: TopNavigationProps) {
14
+ const navigate = useNavigate();
15
+
16
+ const onClickLogo = useCallback(
17
+ (e: React.MouseEvent<HTMLAnchorElement>) => {
18
+ e.preventDefault();
19
+ navigate('/');
20
+ },
21
+ [navigate],
22
+ );
23
+ const onClickSideNavToggleButton = useCallback(() => {
24
+ setSidebarCollapsed((collapsed) => !collapsed);
25
+ }, [setSidebarCollapsed]);
26
+
27
+ return (
28
+ <TopNav>
29
+ <TopNavStart>
30
+ <SideNavToggleButton
31
+ defaultCollapsed={false}
32
+ expandLabel="Expand sidebar"
33
+ collapseLabel="Collapse sidebar"
34
+ onClick={onClickSideNavToggleButton}
35
+ />
36
+
37
+ <div className={styles.logoContainer}>
38
+ <Link to="/" onClick={onClickLogo}>
39
+ <Logo />
40
+ </Link>
41
+ </div>
42
+ </TopNavStart>
43
+ </TopNav>
44
+ );
45
+ }
@@ -0,0 +1,9 @@
1
+ .defaultLoadingIndicator {
2
+ display: flex;
3
+ padding-top: 100px;
4
+ flex-direction: column;
5
+ gap: 32px;
6
+ align-items: center;
7
+ height: 100%;
8
+ width: 100%;
9
+ }
@@ -0,0 +1,3 @@
1
+ export const __esModule: true;
2
+ export const defaultLoadingIndicator: string;
3
+
@@ -0,0 +1,15 @@
1
+ import '@testing-library/jest-dom';
2
+ import {render, screen} from '@testing-library/react';
3
+ import {DefaultLoadingIndicator} from './DefaultLoadingIndicator';
4
+
5
+ describe('DefaultLoadingIndicator', () => {
6
+ it('should render', () => {
7
+ render(<DefaultLoadingIndicator />);
8
+ expect(screen.getByText('Loading cache stats...')).toBeInTheDocument();
9
+ });
10
+
11
+ it('renders provided message', () => {
12
+ render(<DefaultLoadingIndicator message="Loading..." />);
13
+ expect(screen.getByText('Loading...')).toBeInTheDocument();
14
+ });
15
+ });