@atlaspack/inspector-frontend 0.1.1
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.
- package/.atlaspackrc +4 -0
- package/.eslintrc.json +19 -0
- package/CHANGELOG.md +12 -0
- package/dist/atlassian-dark-brand-refresh.91b786da.js +2 -0
- package/dist/atlassian-dark-brand-refresh.91b786da.js.map +1 -0
- package/dist/atlassian-dark-future.59ebadca.js +2 -0
- package/dist/atlassian-dark-future.59ebadca.js.map +1 -0
- package/dist/atlassian-dark-increased-contrast.ff6775f2.js +2 -0
- package/dist/atlassian-dark-increased-contrast.ff6775f2.js.map +1 -0
- package/dist/atlassian-dark.ad679134.js +2 -0
- package/dist/atlassian-dark.ad679134.js.map +1 -0
- package/dist/atlassian-legacy-dark.8aa27f7f.js +2 -0
- package/dist/atlassian-legacy-dark.8aa27f7f.js.map +1 -0
- package/dist/atlassian-legacy-light.2eb372ce.js +2 -0
- package/dist/atlassian-legacy-light.2eb372ce.js.map +1 -0
- package/dist/atlassian-light-brand-refresh.fadcab0a.js +2 -0
- package/dist/atlassian-light-brand-refresh.fadcab0a.js.map +1 -0
- package/dist/atlassian-light-future.612afe8a.js +2 -0
- package/dist/atlassian-light-future.612afe8a.js.map +1 -0
- package/dist/atlassian-light-increased-contrast.7161cd79.js +2 -0
- package/dist/atlassian-light-increased-contrast.7161cd79.js.map +1 -0
- package/dist/atlassian-light.bc343d4c.js +2 -0
- package/dist/atlassian-light.bc343d4c.js.map +1 -0
- package/dist/atlassian-shape.b92d69c0.js +2 -0
- package/dist/atlassian-shape.b92d69c0.js.map +1 -0
- package/dist/atlassian-spacing.60ddd8e7.js +2 -0
- package/dist/atlassian-spacing.60ddd8e7.js.map +1 -0
- package/dist/atlassian-typography-adg3.f88947f6.js +2 -0
- package/dist/atlassian-typography-adg3.f88947f6.js.map +1 -0
- package/dist/atlassian-typography-modernized.42016c51.js +2 -0
- package/dist/atlassian-typography-modernized.42016c51.js.map +1 -0
- package/dist/atlassian-typography-refreshed.ec0d111b.js +2 -0
- package/dist/atlassian-typography-refreshed.ec0d111b.js.map +1 -0
- package/dist/atlassian-typography.66d7e8f4.js +2 -0
- package/dist/atlassian-typography.66d7e8f4.js.map +1 -0
- package/dist/badge-light.7e55986a.png +0 -0
- package/dist/custom-theme.4680282a.js +2 -0
- package/dist/custom-theme.4680282a.js.map +1 -0
- package/dist/drag-handle.136830d3.js +2 -0
- package/dist/drag-handle.136830d3.js.map +1 -0
- package/dist/drag-handle.63bdb345.css +2 -0
- package/dist/drag-handle.63bdb345.css.map +1 -0
- package/dist/index.13289f53.js +28 -0
- package/dist/index.13289f53.js.map +1 -0
- package/dist/index.a41fafce.css +2 -0
- package/dist/index.a41fafce.css.map +1 -0
- package/dist/index.html +1 -0
- package/dist/index.runtime.3c39d71d.js +2 -0
- package/dist/index.runtime.3c39d71d.js.map +1 -0
- package/dist/refractor.2c1fd9a1.js +2 -0
- package/dist/refractor.2c1fd9a1.js.map +1 -0
- package/index.html +11 -0
- package/jest.config.js +16 -0
- package/package.json +64 -0
- package/src/APIError.test.ts +72 -0
- package/src/APIError.tsx +29 -0
- package/src/AppRoutes.tsx +56 -0
- package/src/hack-feature-flags.ts +6 -0
- package/src/main.tsx +50 -0
- package/src/test/stubCssModule.js +1 -0
- package/src/ui/App.module.css +122 -0
- package/src/ui/App.module.css.d.ts +8 -0
- package/src/ui/AppLayout/AppLayout.tsx +26 -0
- package/src/ui/AppLayout/SidebarNavigation/LinkItem.tsx +26 -0
- package/src/ui/AppLayout/SidebarNavigation/SidebarNavigation.tsx +45 -0
- package/src/ui/AppLayout/TopNavigation/Logo.module.css +12 -0
- package/src/ui/AppLayout/TopNavigation/Logo.module.css.d.ts +4 -0
- package/src/ui/AppLayout/TopNavigation/Logo.tsx +11 -0
- package/src/ui/AppLayout/TopNavigation/TopNavigation.module.css +14 -0
- package/src/ui/AppLayout/TopNavigation/TopNavigation.module.css.d.ts +3 -0
- package/src/ui/AppLayout/TopNavigation/TopNavigation.tsx +45 -0
- package/src/ui/AppLayout/TopNavigation/badge-light.png +0 -0
- package/src/ui/AppLayout/TopNavigation/logo-light.png +0 -0
- package/src/ui/DefaultLoadingIndicator/DefaultLoadingIndicator.module.css +9 -0
- package/src/ui/DefaultLoadingIndicator/DefaultLoadingIndicator.module.css.d.ts +3 -0
- package/src/ui/DefaultLoadingIndicator/DefaultLoadingIndicator.test.tsx +15 -0
- package/src/ui/DefaultLoadingIndicator/DefaultLoadingIndicator.tsx +14 -0
- package/src/ui/app/StatsPage.tsx +77 -0
- package/src/ui/app/cache/CacheKeysIndexPage.tsx +13 -0
- package/src/ui/app/cache/CacheKeysPage.module.css +11 -0
- package/src/ui/app/cache/CacheKeysPage.module.css.d.ts +4 -0
- package/src/ui/app/cache/CacheKeysPage.tsx +23 -0
- package/src/ui/app/cache/[key]/CacheValuePage.tsx +40 -0
- package/src/ui/app/cache/ui/CacheKeyList.module.css +40 -0
- package/src/ui/app/cache/ui/CacheKeyList.module.css.d.ts +7 -0
- package/src/ui/app/cache/ui/CacheKeyList.tsx +187 -0
- package/src/ui/app/cache-invalidation/CacheInvalidationPage.tsx +22 -0
- package/src/ui/app/cache-invalidation/[fileId]/CacheInvalidationFilePage.tsx +22 -0
- package/src/ui/app/cache-invalidation/ui/CacheFileList.module.css +40 -0
- package/src/ui/app/cache-invalidation/ui/CacheFileList.module.css.d.ts +7 -0
- package/src/ui/app/cache-invalidation/ui/CacheFileList.tsx +185 -0
- package/src/ui/app/treemap/BottomPanelResizeState.test.ts +25 -0
- package/src/ui/app/treemap/BottomPanelResizeState.tsx +48 -0
- package/src/ui/app/treemap/FoamTreemapPage.module.css +24 -0
- package/src/ui/app/treemap/FoamTreemapPage.module.css.d.ts +6 -0
- package/src/ui/app/treemap/FoamTreemapPage.tsx +47 -0
- package/src/ui/app/treemap/controllers/RelatedBundlesController.tsx +41 -0
- package/src/ui/app/treemap/controllers/UrlFocusController.tsx +33 -0
- package/src/ui/app/treemap/ui/BottomPanel/BottomPanel.module.css +24 -0
- package/src/ui/app/treemap/ui/BottomPanel/BottomPanel.module.css.d.ts +5 -0
- package/src/ui/app/treemap/ui/BottomPanel/BottomPanel.tsx +24 -0
- package/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/AdvancedSettings.module.css +13 -0
- package/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/AdvancedSettings.module.css.d.ts +5 -0
- package/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/AdvancedSettings.tsx +53 -0
- package/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/AssetTable/AssetTable.tsx +135 -0
- package/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/AssetTable/CollapsibleTable/CollapsibleTable.module.css +7 -0
- package/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/AssetTable/CollapsibleTable/CollapsibleTable.module.css.d.ts +3 -0
- package/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/AssetTable/CollapsibleTable/CollapsibleTable.tsx +123 -0
- package/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/AssetTable/CollapsibleTable/CollapsibleTableModel.tsx +18 -0
- package/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/AssetTable/CollapsibleTable/CollapsibleTableRow.module.css +20 -0
- package/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/AssetTable/CollapsibleTable/CollapsibleTableRow.module.css.d.ts +6 -0
- package/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/AssetTable/CollapsibleTable/CollapsibleTableRow.tsx +79 -0
- package/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/AssetTable/getFileURL.test.ts +19 -0
- package/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/AssetTable/getFileURL.ts +24 -0
- package/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/FocusedGroupInfo.module.css +20 -0
- package/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/FocusedGroupInfo.module.css.d.ts +5 -0
- package/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/FocusedGroupInfo.tsx +42 -0
- package/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/FocusedGroupInfoInner.module.css +29 -0
- package/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/FocusedGroupInfoInner.module.css.d.ts +6 -0
- package/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/FocusedGroupInfoInner.tsx +107 -0
- package/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/GraphContainer.module.css +7 -0
- package/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/GraphContainer.module.css.d.ts +3 -0
- package/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/GraphContainer.tsx +20 -0
- package/src/ui/app/treemap/ui/BottomPanel/FocusedGroupInfo/SourceCodeURL.tsx +5 -0
- package/src/ui/app/treemap/ui/BundleGraphRenderer.module.css +13 -0
- package/src/ui/app/treemap/ui/BundleGraphRenderer.module.css.d.ts +4 -0
- package/src/ui/app/treemap/ui/BundleGraphRenderer.tsx +95 -0
- package/src/ui/app/treemap/ui/FocusBreadcrumbs/FocusBreadcrumbs.module.css +6 -0
- package/src/ui/app/treemap/ui/FocusBreadcrumbs/FocusBreadcrumbs.module.css.d.ts +3 -0
- package/src/ui/app/treemap/ui/FocusBreadcrumbs/FocusBreadcrumbs.tsx +49 -0
- package/src/ui/app/treemap/ui/SigmaGraph.module.css +5 -0
- package/src/ui/app/treemap/ui/SigmaGraph.module.css.d.ts +3 -0
- package/src/ui/app/treemap/ui/SigmaGraph.tsx +80 -0
- package/src/ui/app/treemap/ui/Treemap.tsx +14 -0
- package/src/ui/app/treemap/ui/TreemapRenderer/ImpactScore.module.css +32 -0
- package/src/ui/app/treemap/ui/TreemapRenderer/ImpactScore.module.css.d.ts +5 -0
- package/src/ui/app/treemap/ui/TreemapRenderer/ImpactScore.tsx +24 -0
- package/src/ui/app/treemap/ui/TreemapRenderer/TreemapRenderer.module.css +14 -0
- package/src/ui/app/treemap/ui/TreemapRenderer/TreemapRenderer.module.css.d.ts +4 -0
- package/src/ui/app/treemap/ui/TreemapRenderer/TreemapRenderer.tsx +271 -0
- package/src/ui/app/treemap/ui/TreemapRenderer/TreemapTooltip.module.css +15 -0
- package/src/ui/app/treemap/ui/TreemapRenderer/TreemapTooltip.module.css.d.ts +4 -0
- package/src/ui/app/treemap/ui/TreemapRenderer/TreemapTooltip.tsx +111 -0
- package/src/ui/app/treemap/ui/TreemapRenderer/controllers/useStableCallback.test.ts +27 -0
- package/src/ui/app/treemap/ui/TreemapRenderer/controllers/useStableCallback.ts +21 -0
- package/src/ui/app/treemap/ui/TreemapRenderer/useMouseMoveController.ts +20 -0
- package/src/ui/globals.css +26 -0
- package/src/ui/globals.css.d.ts +1 -0
- package/src/ui/globals.d.ts +9 -0
- package/src/ui/model/ViewModel.test.ts +31 -0
- package/src/ui/model/ViewModel.ts +62 -0
- package/src/ui/not-found/NotFoundPage.module.css +7 -0
- package/src/ui/not-found/NotFoundPage.module.css.d.ts +3 -0
- package/src/ui/not-found/NotFoundPage.tsx +9 -0
- package/src/ui/types/Graph.tsx +12 -0
- package/src/ui/util/ErrorBoundary.module.css +3 -0
- package/src/ui/util/ErrorBoundary.module.css.d.ts +3 -0
- package/src/ui/util/ErrorBoundary.test.tsx +65 -0
- package/src/ui/util/ErrorBoundary.tsx +75 -0
- package/src/ui/util/colorPalette.tsx +122 -0
- package/src/ui/util/formatBytes.test.ts +13 -0
- package/src/ui/util/formatBytes.tsx +9 -0
- package/src/ui/util/getRandomDarkerColor.tsx +31 -0
- package/tsconfig.json +12 -0
package/index.html
ADDED
package/jest.config.js
ADDED
|
@@ -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
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@atlaspack/inspector-frontend",
|
|
3
|
+
"version": "0.1.1",
|
|
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.13",
|
|
31
|
+
"@atlaspack/core": "2.25.1",
|
|
32
|
+
"@atlaspack/graph": "3.5.23",
|
|
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
|
+
});
|
package/src/APIError.tsx
ADDED
|
@@ -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
|
+
}
|
package/src/main.tsx
ADDED
|
@@ -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,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,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
|
+
}
|
|
Binary file
|
|
Binary file
|
|
@@ -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
|
+
});
|