pkgviz 0.7.7 → 0.8.0
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/.next/BUILD_ID +1 -1
- package/.next/app-path-routes-manifest.json +2 -1
- package/.next/build-manifest.json +15 -24
- package/.next/fallback-build-manifest.json +15 -0
- package/.next/images-manifest.json +14 -3
- package/.next/next-minimal-server.js.nft.json +1 -1
- package/.next/next-server.js.nft.json +1 -1
- package/.next/prerender-manifest.json +52 -16
- package/.next/required-server-files.js +349 -0
- package/.next/required-server-files.json +106 -75
- package/.next/routes-manifest.json +16 -6
- package/.next/server/app/_global-error/page/app-paths-manifest.json +3 -0
- package/.next/server/app/_global-error/page/build-manifest.json +20 -0
- package/.next/server/app/_global-error/page/next-font-manifest.json +6 -0
- package/.next/server/app/_global-error/page/server-reference-manifest.json +4 -0
- package/.next/server/app/_global-error/page.js +9 -0
- package/.next/server/app/_global-error/page.js.map +5 -0
- package/.next/server/app/_global-error/page.js.nft.json +1 -0
- package/.next/server/app/_global-error/page_client-reference-manifest.js +3 -0
- package/.next/server/app/_global-error.html +1 -0
- package/.next/server/app/_global-error.meta +22 -0
- package/.next/server/app/_global-error.rsc +15 -0
- package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +20 -0
- package/.next/server/app/_global-error.segments/_full.segment.rsc +15 -0
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -0
- package/.next/server/app/_not-found/page/app-paths-manifest.json +3 -0
- package/.next/server/app/_not-found/page/build-manifest.json +20 -0
- package/.next/server/app/_not-found/page/next-font-manifest.json +11 -0
- package/.next/server/app/_not-found/page/react-loadable-manifest.json +1 -0
- package/.next/server/app/_not-found/page/server-reference-manifest.json +4 -0
- package/.next/server/app/_not-found/page.js +13 -2
- package/.next/server/app/_not-found/page.js.map +5 -0
- package/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.js +3 -1
- package/.next/server/app/_not-found.html +1 -1
- package/.next/server/app/_not-found.meta +19 -0
- package/.next/server/app/_not-found.rsc +18 -19
- package/.next/server/app/_not-found.segments/_full.segment.rsc +18 -0
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +24 -0
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -0
- package/.next/server/app/favicon.ico/route/app-paths-manifest.json +3 -0
- package/.next/server/app/favicon.ico/route/build-manifest.json +12 -0
- package/.next/server/app/favicon.ico/route.js +6 -1
- package/.next/server/app/favicon.ico/route.js.map +5 -0
- package/.next/server/app/favicon.ico/route.js.nft.json +1 -1
- package/.next/server/app/page/app-paths-manifest.json +3 -0
- package/.next/server/app/page/build-manifest.json +20 -0
- package/.next/server/app/page/next-font-manifest.json +11 -0
- package/.next/server/app/page/react-loadable-manifest.json +1 -0
- package/.next/server/app/page/server-reference-manifest.json +93 -0
- package/.next/server/app/page.js +16 -13
- package/.next/server/app/page.js.map +5 -0
- package/.next/server/app/page.js.nft.json +1 -1
- package/.next/server/app/page_client-reference-manifest.js +3 -1
- package/.next/server/app-paths-manifest.json +2 -1
- package/.next/server/chunks/[externals]__0l8ei7u._.js +3 -0
- package/.next/server/chunks/[externals]__0l8ei7u._.js.map +1 -0
- package/.next/server/chunks/[root-of-the-server]__1to-yfd._.js +160 -0
- package/.next/server/chunks/[root-of-the-server]__1to-yfd._.js.map +1 -0
- package/.next/server/chunks/[turbopack]_runtime.js +807 -0
- package/.next/server/chunks/[turbopack]_runtime.js.map +10 -0
- package/.next/server/chunks/_next-internal_server_app_favicon_ico_route_actions_0g2jjls.js +3 -0
- package/.next/server/chunks/_next-internal_server_app_favicon_ico_route_actions_0g2jjls.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0agsrep._.js +28 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0agsrep._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0f_e7c8._.js +33 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0f_e7c8._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0yqn68e._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__0yqn68e._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__112mz-6._.js +14 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__112mz-6._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__11_76b7._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__11_76b7._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__12ovu0c._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__12ovu0c._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__16pmw__._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__16pmw__._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__1f2jx51._.js +33 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__1f2jx51._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__1rn09vt._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__1rn09vt._.js.map +1 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__20e4gkp._.js +3 -0
- package/.next/server/chunks/ssr/[root-of-the-server]__20e4gkp._.js.map +1 -0
- package/.next/server/chunks/ssr/[turbopack]_runtime.js +807 -0
- package/.next/server/chunks/ssr/[turbopack]_runtime.js.map +10 -0
- package/.next/server/chunks/ssr/_1acy_2s._.js +158 -0
- package/.next/server/chunks/ssr/_1acy_2s._.js.map +1 -0
- package/.next/server/chunks/ssr/_1rh2tf9._.js +367 -0
- package/.next/server/chunks/ssr/_1rh2tf9._.js.map +1 -0
- package/.next/server/chunks/ssr/_next-internal_server_app__global-error_page_actions_0zi5s8-.js +3 -0
- package/.next/server/chunks/ssr/_next-internal_server_app__global-error_page_actions_0zi5s8-.js.map +1 -0
- package/.next/server/chunks/ssr/_next-internal_server_app__not-found_page_actions_0pt47yr.js +3 -0
- package/.next/server/chunks/ssr/_next-internal_server_app__not-found_page_actions_0pt47yr.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_01xbj_9._.js +33 -0
- package/.next/server/chunks/ssr/node_modules_01xbj_9._.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_1c5ky4f._.js +3 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_1c5ky4f._.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_1n3w9lb._.js +6 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_1n3w9lb._.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_client_components_0wpq8j3._.js +3 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_client_components_0wpq8j3._.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_client_components_builtin_forbidden_0symwr9.js +3 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_client_components_builtin_forbidden_0symwr9.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_client_components_builtin_global-error_0q-w892.js +3 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_client_components_builtin_global-error_0q-w892.js.map +1 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_client_components_builtin_unauthorized_0l_sp0x.js +3 -0
- package/.next/server/chunks/ssr/node_modules_next_dist_client_components_builtin_unauthorized_0l_sp0x.js.map +1 -0
- package/.next/server/chunks/ssr/src_app_loading_tsx_01g_-m0._.js +3 -0
- package/.next/server/chunks/ssr/src_app_loading_tsx_01g_-m0._.js.map +1 -0
- package/.next/server/middleware-build-manifest.js +24 -1
- package/.next/server/middleware-manifest.json +2 -2
- package/.next/server/next-font-manifest.js +1 -1
- package/.next/server/next-font-manifest.json +15 -1
- package/.next/server/pages/404.html +1 -1
- package/.next/server/pages/500.html +1 -1
- package/.next/server/pages-manifest.json +2 -4
- package/.next/server/prefetch-hints.json +25 -0
- package/.next/server/server-reference-manifest.js +1 -1
- package/.next/server/server-reference-manifest.json +94 -1
- package/.next/static/chunks/19mx3mg6lkumu.js +1 -0
- package/.next/static/chunks/1las_6j17xa9p.js +1 -0
- package/.next/static/chunks/1xk6snnh6e5_j.css +3 -0
- package/.next/static/chunks/2-rtuqsgzmno4.js +22 -0
- package/.next/static/chunks/27t_qfc-3_lzs.js +1 -0
- package/.next/static/chunks/2sswp23h6zh08.js +345 -0
- package/.next/static/chunks/310vm2bl3xxpt.js +31 -0
- package/.next/static/chunks/3fntmmi971322.js +1 -0
- package/.next/static/chunks/turbopack-1b6uko1cu_h42.js +1 -0
- package/.next/static/media/4fa387ec64143e14-s.2tuy5pz7dlieh.woff2 +0 -0
- package/.next/static/media/53b9e256198e5412-s.390ncx5urfkfu.woff2 +0 -0
- package/.next/static/media/5ce348bf30bf5439-s.31988l_ccedte.woff2 +0 -0
- package/.next/static/media/6306c77e7c8268e4-s.2dbetqa9o8jxf.woff2 +0 -0
- package/.next/static/media/7178b3e590c64307-s.21jp631_3pja2.woff2 +0 -0
- package/.next/static/media/797e433ab948586e-s.p.0r6juujl39pe6.woff2 +0 -0
- package/.next/static/media/7d817b4c03b0c5f1-s.1uyisp29ctx0d.woff2 +0 -0
- package/.next/static/media/8a480f0b521d4e75-s.1qq4vpdcun5oj.woff2 +0 -0
- package/.next/static/media/bbc41e54d2fcbd21-s.1rgnod-3esatf.woff2 +0 -0
- package/.next/static/media/caa3a2e1cccd8315-s.p.0wgildi0cnwt9.woff2 +0 -0
- package/.next/static/media/favicon.2246eezznj2ab.ico +0 -0
- package/.next/static/media/fef07dbb0973bf53-s.3p2_lha1f2xer.woff2 +0 -0
- package/.next/static/rjdzHqzPw2GCNhDbjcu0-/_buildManifest.js +11 -0
- package/.next/static/rjdzHqzPw2GCNhDbjcu0-/_clientMiddlewareManifest.js +1 -0
- package/README.md +176 -4
- package/bin/pkgviz.ts +57 -29
- package/package.json +57 -36
- package/src/app/actions/audit.actions.ts +7 -49
- package/src/app/globals.css +0 -2
- package/src/app/layout.tsx +3 -2
- package/src/app/loading.tsx +8 -0
- package/src/app/page.tsx +16 -2
- package/src/app/utils/buildGraph.ts +99 -100
- package/src/app/utils/getParsedFileStructure.ts +128 -54
- package/src/app/utils/inspectParserLanguageAsync.ts +39 -0
- package/src/app/utils/markCyclicPackages.ts +45 -185
- package/src/app/utils/parser/cpp/parseCppFile.ts +68 -86
- package/src/app/utils/parser/delphi/parseFile.ts +36 -120
- package/src/app/utils/parser/java/findEntryPoint.ts +2 -1
- package/src/app/utils/parser/java/parseJavaFile.ts +33 -45
- package/src/app/utils/parser/kotlin/parseFile.ts +34 -87
- package/src/app/utils/parser/python/parseFile.ts +30 -100
- package/src/app/utils/parser/typescript/parseFile.ts +17 -52
- package/src/app/utils/selectParserLanguage.ts +39 -0
- package/src/cli/formatAuditRuleFailures.ts +21 -0
- package/src/cli/runAuditAsync.ts +41 -0
- package/src/components/Breadcrumb.tsx +5 -4
- package/src/components/ExportPanel.tsx +53 -0
- package/src/components/Header.tsx +1 -0
- package/src/components/Loader.tsx +8 -2
- package/src/components/ProjectLoadError.tsx +15 -0
- package/src/components/SettingsPanel.tsx +184 -0
- package/src/components/Switch.tsx +9 -17
- package/src/components/ThemeToggle.tsx +2 -1
- package/src/components/ToggleSwitch.tsx +36 -0
- package/src/components/sidebar/Sidebar.tsx +14 -0
- package/src/components/sidebar/SidebarBadge.tsx +25 -0
- package/src/components/sidebar/SidebarRow.tsx +14 -0
- package/src/components/sidebar/SidebarSection.tsx +16 -0
- package/src/components/sidebar/SidebarTabs.tsx +58 -0
- package/src/contexts/SettingsContext.tsx +19 -20
- package/src/features/audit/adapters/inbound/react/AuditRuleList.tsx +76 -0
- package/src/features/audit/adapters/inbound/react/AuditRulePanel.tsx +30 -0
- package/src/features/audit/adapters/inbound/react/CycleInspector.tsx +116 -0
- package/src/features/audit/adapters/inbound/react/CyclicDependenciesRuleDetails.tsx +124 -0
- package/src/features/audit/adapters/inbound/react/useCycleSelection.ts +47 -0
- package/src/features/audit/application/use-cases/createAuditFromSnapshot.ts +28 -0
- package/src/features/audit/application/use-cases/resolveSelectedCycleIds.ts +18 -0
- package/src/features/audit/composition/createAuditAsync.ts +11 -0
- package/src/features/audit/domain/evaluateAuditRules.ts +42 -0
- package/src/features/audit/domain/hasBlockingAuditRuleFailure.ts +6 -0
- package/src/features/audit/domain/resolveAuditConfiguration.ts +27 -0
- package/src/features/audit/utils/cycleVisualization.ts +86 -0
- package/src/features/dependency-analysis/adapters/outbound/dependency-graph/analyzeDependencyImportsAsync.ts +172 -0
- package/src/features/dependency-analysis/adapters/outbound/dependency-graph/analyzeTypeScriptImportsAsync.ts +6 -0
- package/src/features/graph-view/adapters/inbound/react/DependencyGraphView.tsx +184 -0
- package/src/features/graph-view/adapters/inbound/react/GraphZoomControls.tsx +48 -0
- package/src/features/graph-view/adapters/inbound/react/applyGraphInteractionPresentation.ts +35 -0
- package/src/features/graph-view/adapters/inbound/react/createGraphViewModel.ts +240 -0
- package/src/features/graph-view/adapters/inbound/react/createGraphViewStyles.ts +37 -0
- package/src/features/graph-view/adapters/inbound/react/useGraphFocus.ts +104 -0
- package/src/features/graph-view/adapters/inbound/react/useGraphInteractions.ts +50 -0
- package/src/features/graph-view/adapters/inbound/react/useGraphProjection.ts +71 -0
- package/src/features/graph-view/adapters/inbound/react/useGraphViewport.ts +48 -0
- package/src/features/graph-view/domain/getDependencyHighlightClasses.ts +39 -0
- package/src/features/graph-view/domain/reduceGraphInteraction.ts +23 -0
- package/src/features/graph-view/utils/createCompoundOpacityIndex.ts +38 -0
- package/src/features/graph-view/utils/projectVisibleGraph.ts +94 -0
- package/src/features/graph-view/utils/readNodeDefinitionId.ts +7 -0
- package/src/features/graph-view/utils/removeEmptyStructuralNodes.ts +27 -0
- package/src/features/project-analysis/adapters/outbound/filesystem/readProjectSnapshotAsync.ts +12 -0
- package/src/features/project-analysis/application/use-cases/createProjectSnapshotReader.ts +29 -0
- package/src/features/project-analysis/composition/loadProjectOverviewAsync.ts +14 -0
- package/src/features/project-analysis/composition/loadProjectSnapshotAsync.ts +12 -0
- package/src/features/project-tree/adapters/inbound/react/ProjectTreePanel.tsx +52 -0
- package/src/features/project-tree/adapters/inbound/react/useProjectTreeExpansion.ts +46 -0
- package/src/features/project-tree/application/use-cases/buildProjectTree.ts +61 -0
- package/src/features/project-tree/application/use-cases/resolveProjectTreeNavigation.ts +13 -0
- package/src/features/project-tree/utils/findProjectTreeNode.ts +14 -0
- package/src/features/project-tree/utils/findProjectTreeNodeByGraphPackage.ts +21 -0
- package/src/features/project-tree/utils/getProjectTreeAncestorIds.ts +26 -0
- package/src/features/settings/utils/readSettingsEnvironment.ts +53 -0
- package/src/i18n/en.ts +21 -2
- package/src/i18n/i18n.ts +2 -3
- package/src/layouts/breadthfirst/style.ts +1 -0
- package/src/layouts/circle/style.ts +1 -0
- package/src/layouts/concentric/style.ts +1 -0
- package/src/layouts/elk/layout.ts +1 -3
- package/src/layouts/elk/style.ts +1 -0
- package/src/layouts/getWeightBuckets.ts +3 -1
- package/src/layouts/grid/style.ts +1 -0
- package/src/layouts/index.ts +0 -4
- package/src/layouts/style.ts +172 -25
- package/src/screens/home/Home.tsx +73 -25
- package/src/screens/home/HomeGraph.tsx +43 -0
- package/src/screens/home/HomeSidebar.tsx +129 -0
- package/src/shared/types/index.ts +0 -9
- package/src/shared/utils/getProjectName.ts +4 -1
- package/src/shared/utils/parseProjectPath.ts +1 -0
- package/src/shared/utils/toPosix.ts +1 -1
- package/src/types/audit.ts +76 -0
- package/src/types/auditVisualization.ts +22 -0
- package/src/types/graphInteraction.ts +9 -0
- package/src/types/parserSelection.ts +11 -0
- package/src/types/projectAnalysis.ts +20 -0
- package/src/types/projectAnalysisActionResult.ts +2 -0
- package/src/types/projectTree.ts +7 -0
- package/src/utils/filter/filterByPackagePrefix.ts +25 -7
- package/src/utils/filter/filterEmptyPackages.ts +28 -29
- package/src/utils/filter/filterSubPackagesFromDepth.ts +20 -17
- package/src/utils/filter/filterVendorPackages.ts +1 -1
- package/src/utils/filter/isIntrinsicGraphNode.ts +8 -0
- package/src/utils/filter/toggleCompoundNodes.ts +41 -31
- package/src/utils/runProjectAnalysisActionAsync.ts +14 -0
- package/tsconfig.json +11 -3
- package/.next/app-build-manifest.json +0 -29
- package/.next/cache/.previewinfo +0 -1
- package/.next/cache/.rscinfo +0 -1
- package/.next/cache/.tsbuildinfo +0 -1
- package/.next/cache/chrome-devtools-workspace-uuid +0 -1
- package/.next/cache/eslint/.cache_6t30dc +0 -1
- package/.next/cache/webpack/client-production/0.pack +0 -4
- package/.next/cache/webpack/client-production/1.pack +0 -0
- package/.next/cache/webpack/client-production/10.pack +0 -0
- package/.next/cache/webpack/client-production/11.pack +0 -0
- package/.next/cache/webpack/client-production/12.pack +0 -0
- package/.next/cache/webpack/client-production/13.pack +0 -0
- package/.next/cache/webpack/client-production/14.pack +0 -0
- package/.next/cache/webpack/client-production/15.pack +0 -0
- package/.next/cache/webpack/client-production/16.pack +0 -0
- package/.next/cache/webpack/client-production/2.pack +0 -0
- package/.next/cache/webpack/client-production/3.pack +0 -0
- package/.next/cache/webpack/client-production/4.pack +0 -0
- package/.next/cache/webpack/client-production/5.pack +0 -0
- package/.next/cache/webpack/client-production/6.pack +0 -0
- package/.next/cache/webpack/client-production/7.pack +0 -0
- package/.next/cache/webpack/client-production/8.pack +0 -0
- package/.next/cache/webpack/client-production/9.pack +0 -0
- package/.next/cache/webpack/client-production/index.pack +0 -0
- package/.next/cache/webpack/client-production/index.pack.old +0 -0
- package/.next/cache/webpack/edge-server-production/0.pack +0 -0
- package/.next/cache/webpack/edge-server-production/index.pack +0 -0
- package/.next/cache/webpack/edge-server-production/index.pack.old +0 -0
- package/.next/cache/webpack/server-production/0.pack +0 -0
- package/.next/cache/webpack/server-production/1.pack +0 -0
- package/.next/cache/webpack/server-production/10.pack +0 -4
- package/.next/cache/webpack/server-production/11.pack +0 -0
- package/.next/cache/webpack/server-production/12.pack +0 -0
- package/.next/cache/webpack/server-production/13.pack +0 -0
- package/.next/cache/webpack/server-production/14.pack +0 -0
- package/.next/cache/webpack/server-production/15.pack +0 -0
- package/.next/cache/webpack/server-production/16.pack +0 -0
- package/.next/cache/webpack/server-production/17.pack +0 -0
- package/.next/cache/webpack/server-production/18.pack +0 -4
- package/.next/cache/webpack/server-production/2.pack +0 -0
- package/.next/cache/webpack/server-production/3.pack +0 -0
- package/.next/cache/webpack/server-production/4.pack +0 -0
- package/.next/cache/webpack/server-production/5.pack +0 -0
- package/.next/cache/webpack/server-production/6.pack +0 -0
- package/.next/cache/webpack/server-production/7.pack +0 -0
- package/.next/cache/webpack/server-production/8.pack +0 -0
- package/.next/cache/webpack/server-production/9.pack +0 -0
- package/.next/cache/webpack/server-production/index.pack +0 -0
- package/.next/cache/webpack/server-production/index.pack.old +0 -0
- package/.next/diagnostics/build-diagnostics.json +0 -6
- package/.next/diagnostics/framework.json +0 -1
- package/.next/server/app/index.html +0 -1
- package/.next/server/app/index.meta +0 -7
- package/.next/server/app/index.rsc +0 -20
- package/.next/server/chunks/548.js +0 -6
- package/.next/server/chunks/610.js +0 -7
- package/.next/server/chunks/985.js +0 -22
- package/.next/server/middleware-react-loadable-manifest.js +0 -1
- package/.next/server/pages/_app.js +0 -1
- package/.next/server/pages/_app.js.nft.json +0 -1
- package/.next/server/pages/_document.js +0 -1
- package/.next/server/pages/_document.js.nft.json +0 -1
- package/.next/server/pages/_error.js +0 -19
- package/.next/server/pages/_error.js.nft.json +0 -1
- package/.next/server/webpack-runtime.js +0 -1
- package/.next/static/_YC2p40ZiYT2Gcw-h_tjC/_buildManifest.js +0 -1
- package/.next/static/chunks/4bd1b696-cf72ae8a39fa05aa.js +0 -1
- package/.next/static/chunks/680-55ad17895c8fb70b.js +0 -1
- package/.next/static/chunks/90542734-29e255269788f1bd.js +0 -1
- package/.next/static/chunks/91dbc596-b9cdccd3f5cba95d.js +0 -1
- package/.next/static/chunks/964-b440f7af22c41ca5.js +0 -1
- package/.next/static/chunks/app/_not-found/page-11e4fea8e290f304.js +0 -1
- package/.next/static/chunks/app/layout-8aae7fba5ed8afb3.js +0 -1
- package/.next/static/chunks/app/page-91450b1230da8bca.js +0 -1
- package/.next/static/chunks/framework-bc35dade6ff9684e.js +0 -1
- package/.next/static/chunks/main-9e86d333c1e02dd1.js +0 -1
- package/.next/static/chunks/main-app-69a9ff75ff3465ca.js +0 -1
- package/.next/static/chunks/pages/_app-0a0020ddd67f79cf.js +0 -1
- package/.next/static/chunks/pages/_error-03529f2c21436739.js +0 -1
- package/.next/static/chunks/webpack-7adfafc806738767.js +0 -1
- package/.next/static/css/ec31779168107a11.css +0 -3
- package/.next/static/media/4cf2300e9c8272f7-s.p.woff2 +0 -0
- package/.next/static/media/747892c23ea88013-s.woff2 +0 -0
- package/.next/static/media/8d697b304b401681-s.woff2 +0 -0
- package/.next/static/media/93f479601ee12b01-s.p.woff2 +0 -0
- package/.next/static/media/9610d9e46709d722-s.woff2 +0 -0
- package/.next/static/media/ba015fad6dcf6784-s.woff2 +0 -0
- package/.next/trace +0 -2
- package/.next/types/app/layout.ts +0 -84
- package/.next/types/app/page.ts +0 -84
- package/.next/types/cache-life.d.ts +0 -141
- package/.next/types/package.json +0 -1
- package/src/app/actions/graph.actions.ts +0 -25
- package/src/app/utils/parser/cpp/extractCppPackageFromImport.ts +0 -18
- package/src/app/utils/parser/delphi/extractPackageFromImport.ts +0 -21
- package/src/app/utils/parser/java/extractJavaPackageFromImport.ts +0 -39
- package/src/app/utils/parser/java/getIntrinsicPackagesRecursive.ts +0 -33
- package/src/app/utils/parser/kotlin/extractPackageFromImport.ts +0 -19
- package/src/app/utils/parser/python/extractPythonPackageFromImport.ts +0 -18
- package/src/app/utils/parser/typescript/extractTypeScriptPackageFromImport.ts +0 -18
- package/src/components/Cytoscape.tsx +0 -23
- package/src/components/Setting.tsx +0 -17
- package/src/components/Settings.tsx +0 -189
- package/src/components/ZoomInput.tsx +0 -94
- package/src/components/useCytoscape.ts +0 -343
- package/src/layouts/getLayoutStyle.ts +0 -19
- package/src/shared/utils/detectLanguage.ts +0 -255
- package/src/shared/utils/getJsonAsync.ts +0 -13
- package/src/shared/utils/parseEnv.ts +0 -91
- package/src/store/useLocalStorage.ts +0 -29
- package/src/utils/hasChildren.ts +0 -7
- /package/.next/{react-loadable-manifest.json → server/app/_global-error/page/react-loadable-manifest.json} +0 -0
- /package/.next/static/chunks/{polyfills-42372ed130431b0a.js → 0cz1d0mv5g_q7.js} +0 -0
- /package/.next/static/{_YC2p40ZiYT2Gcw-h_tjC → rjdzHqzPw2GCNhDbjcu0-}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import type { ElementsDefinition } from 'cytoscape';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
|
|
5
|
+
import Loader from '@/components/Loader';
|
|
6
|
+
import { CycleInspector } from '@/features/audit/adapters/inbound/react/CycleInspector';
|
|
7
|
+
import { DependencyGraphView } from '@/features/graph-view/adapters/inbound/react/DependencyGraphView';
|
|
8
|
+
import type { CycleHighlight, CycleInspection } from '@/types/auditVisualization';
|
|
9
|
+
|
|
10
|
+
/*** Renders the graph surface together with its optional cycle inspector overlay. */
|
|
11
|
+
export function HomeGraph({
|
|
12
|
+
currentPackage,
|
|
13
|
+
cycleHighlights,
|
|
14
|
+
cycleInspection,
|
|
15
|
+
packageGraph,
|
|
16
|
+
setCurrentPackage,
|
|
17
|
+
onCloseInspection,
|
|
18
|
+
}: HomeGraphProps) {
|
|
19
|
+
if (!packageGraph) return <Loader />;
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<DependencyGraphView
|
|
23
|
+
currentPackage={currentPackage}
|
|
24
|
+
setCurrentPackage={setCurrentPackage}
|
|
25
|
+
packageGraph={packageGraph}
|
|
26
|
+
cycleHighlights={cycleHighlights}
|
|
27
|
+
overlay={
|
|
28
|
+
cycleInspection === null ? null : (
|
|
29
|
+
<CycleInspector inspection={cycleInspection} onClose={onCloseInspection} />
|
|
30
|
+
)
|
|
31
|
+
}
|
|
32
|
+
/>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
interface HomeGraphProps {
|
|
37
|
+
readonly currentPackage: string;
|
|
38
|
+
readonly cycleHighlights: readonly CycleHighlight[];
|
|
39
|
+
readonly cycleInspection: CycleInspection | null;
|
|
40
|
+
readonly packageGraph: ElementsDefinition | null;
|
|
41
|
+
readonly setCurrentPackage: (path: string) => void;
|
|
42
|
+
readonly onCloseInspection: () => void;
|
|
43
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
4
|
+
import { ExportPanel } from '@/components/ExportPanel';
|
|
5
|
+
import { SettingsPanel } from '@/components/SettingsPanel';
|
|
6
|
+
import { Sidebar } from '@/components/sidebar/Sidebar';
|
|
7
|
+
import { SidebarTabs } from '@/components/sidebar/SidebarTabs';
|
|
8
|
+
import { AuditRulePanel } from '@/features/audit/adapters/inbound/react/AuditRulePanel';
|
|
9
|
+
import { ProjectTreePanel } from '@/features/project-tree/adapters/inbound/react/ProjectTreePanel';
|
|
10
|
+
import { t } from '@/i18n/i18n';
|
|
11
|
+
import type { Audit } from '@/types/audit';
|
|
12
|
+
import type { CycleInspection, CycleSelection } from '@/types/auditVisualization';
|
|
13
|
+
import type { ProjectTreeNode } from '@/types/projectTree';
|
|
14
|
+
|
|
15
|
+
/*** Composes Tree, Rules, and Export above persistent graph settings. */
|
|
16
|
+
export function HomeSidebar(props: HomeSidebarProps) {
|
|
17
|
+
const [activeTool, setActiveTool] = React.useState<string | null>('tree');
|
|
18
|
+
|
|
19
|
+
/*** Closes the evidence panel without changing the user's cycle visualization choices. */
|
|
20
|
+
const selectTool = (value: string) => {
|
|
21
|
+
if (activeTool === 'rules' && value !== 'rules') {
|
|
22
|
+
props.onCycleInspectionChange(null);
|
|
23
|
+
}
|
|
24
|
+
setActiveTool(value);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<Sidebar>
|
|
29
|
+
<SidebarToolTabs
|
|
30
|
+
activeTool={activeTool}
|
|
31
|
+
evaluation={props.evaluation}
|
|
32
|
+
cycleSelection={props.cycleSelection}
|
|
33
|
+
inspectedCycleId={props.inspectedCycleId}
|
|
34
|
+
onCycleInspectionChange={props.onCycleInspectionChange}
|
|
35
|
+
onProjectTreeSelect={props.onProjectTreeSelect}
|
|
36
|
+
onValueChange={selectTool}
|
|
37
|
+
projectTree={props.projectTree}
|
|
38
|
+
selectedTreeId={props.selectedTreeId}
|
|
39
|
+
/>
|
|
40
|
+
<div className="shrink-0">
|
|
41
|
+
<SettingsPanel />
|
|
42
|
+
</div>
|
|
43
|
+
</Sidebar>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/*** Renders project-tree navigation together with secondary Rules and Export tools. */
|
|
48
|
+
function SidebarToolTabs({
|
|
49
|
+
activeTool,
|
|
50
|
+
evaluation,
|
|
51
|
+
cycleSelection,
|
|
52
|
+
inspectedCycleId,
|
|
53
|
+
onCycleInspectionChange,
|
|
54
|
+
onProjectTreeSelect,
|
|
55
|
+
onValueChange,
|
|
56
|
+
projectTree,
|
|
57
|
+
selectedTreeId,
|
|
58
|
+
}: SidebarToolTabsProps) {
|
|
59
|
+
const violatedRuleCount = evaluation?.rules.filter(rule => rule.status === 'failed').length ?? 0;
|
|
60
|
+
const findingCount =
|
|
61
|
+
evaluation?.rules
|
|
62
|
+
.filter(rule => rule.status === 'failed')
|
|
63
|
+
.reduce(
|
|
64
|
+
(count, rule) =>
|
|
65
|
+
count +
|
|
66
|
+
(rule.id === 'cyclic-dependencies'
|
|
67
|
+
? evaluation.cyclicPackages.length
|
|
68
|
+
: rule.details.length),
|
|
69
|
+
0
|
|
70
|
+
) ?? 0;
|
|
71
|
+
|
|
72
|
+
return (
|
|
73
|
+
<SidebarTabs
|
|
74
|
+
ariaLabel={t('sidebar.tools')}
|
|
75
|
+
value={activeTool}
|
|
76
|
+
onValueChange={onValueChange}
|
|
77
|
+
tabs={[
|
|
78
|
+
{
|
|
79
|
+
id: 'tree',
|
|
80
|
+
label: t('settings.tree'),
|
|
81
|
+
content: (
|
|
82
|
+
<ProjectTreePanel
|
|
83
|
+
nodes={projectTree}
|
|
84
|
+
selectedId={selectedTreeId}
|
|
85
|
+
onSelect={onProjectTreeSelect}
|
|
86
|
+
/>
|
|
87
|
+
),
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
id: 'rules',
|
|
91
|
+
label: `${t('settings.rules')} · ${findingCount} ${t('audit.findings')}`,
|
|
92
|
+
disabled: violatedRuleCount === 0,
|
|
93
|
+
content:
|
|
94
|
+
evaluation === null ? null : (
|
|
95
|
+
<AuditRulePanel
|
|
96
|
+
evaluation={evaluation}
|
|
97
|
+
cycleSelection={cycleSelection}
|
|
98
|
+
inspectedCycleId={inspectedCycleId}
|
|
99
|
+
onCycleInspectionChange={onCycleInspectionChange}
|
|
100
|
+
/>
|
|
101
|
+
),
|
|
102
|
+
},
|
|
103
|
+
{ id: 'export', label: t('settings.export'), content: <ExportPanel /> },
|
|
104
|
+
]}
|
|
105
|
+
/>
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
interface HomeSidebarProps {
|
|
110
|
+
readonly inspectedCycleId: string | null;
|
|
111
|
+
readonly evaluation: Audit['evaluation'] | null;
|
|
112
|
+
readonly projectTree: readonly ProjectTreeNode[];
|
|
113
|
+
readonly selectedTreeId: string | null;
|
|
114
|
+
readonly onProjectTreeSelect: (node: ProjectTreeNode) => void;
|
|
115
|
+
readonly cycleSelection: CycleSelection;
|
|
116
|
+
readonly onCycleInspectionChange: (inspection: CycleInspection | null) => void;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
interface SidebarToolTabsProps {
|
|
120
|
+
readonly inspectedCycleId: string | null;
|
|
121
|
+
readonly activeTool: string | null;
|
|
122
|
+
readonly evaluation: Audit['evaluation'] | null;
|
|
123
|
+
readonly cycleSelection: CycleSelection;
|
|
124
|
+
readonly onCycleInspectionChange: (inspection: CycleInspection | null) => void;
|
|
125
|
+
readonly onProjectTreeSelect: (node: ProjectTreeNode) => void;
|
|
126
|
+
readonly onValueChange: (value: string) => void;
|
|
127
|
+
readonly projectTree: readonly ProjectTreeNode[];
|
|
128
|
+
readonly selectedTreeId: string | null;
|
|
129
|
+
}
|
|
@@ -15,15 +15,6 @@ export enum Language {
|
|
|
15
15
|
Unknown = 'unknown',
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
/**
|
|
19
|
-
* Language Detection Result
|
|
20
|
-
*/
|
|
21
|
-
export interface LanguageDetectionResult {
|
|
22
|
-
language: Language;
|
|
23
|
-
confidence: number;
|
|
24
|
-
indicators: string[];
|
|
25
|
-
}
|
|
26
|
-
|
|
27
18
|
//////////////////////////////////////////////////////////////////////////
|
|
28
19
|
// Parser Types
|
|
29
20
|
|
|
@@ -1,3 +1,6 @@
|
|
|
1
1
|
import { parseProjectPath } from '@/shared/utils/parseProjectPath';
|
|
2
|
+
import { toPosix } from '@/shared/utils/toPosix';
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
/*** Returns the project name for an explicit or configured project path. */
|
|
5
|
+
export const getProjectName = (projectPath: string = parseProjectPath()) =>
|
|
6
|
+
toPosix(projectPath).split('/').pop() || '{unknown}';
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { toPosix } from '@/shared/utils/toPosix';
|
|
2
2
|
|
|
3
|
+
/*** Returns the configured project path in POSIX form. */
|
|
3
4
|
export const parseProjectPath = () => {
|
|
4
5
|
const projectPath = process.env.NEXT_PUBLIC_PROJECT_PATH;
|
|
5
6
|
if (!projectPath) throw new Error('Missing ENV: NEXT_PUBLIC_PROJECT_PATH');
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { ParsedDirectory } from '@/shared/types';
|
|
2
|
+
import type { ParserSelection } from '@/types/parserSelection';
|
|
3
|
+
|
|
4
|
+
type AuditRuleMode = 'audit' | 'block' | 'off';
|
|
5
|
+
type AuditRulePolicy = 'advisory' | 'blocking';
|
|
6
|
+
type AuditRuleStatus = 'failed' | 'passed';
|
|
7
|
+
|
|
8
|
+
export interface AuditRuleConfiguration {
|
|
9
|
+
readonly id: string;
|
|
10
|
+
readonly mode: AuditRuleMode;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface AuditConfiguration {
|
|
14
|
+
readonly failOnRuleViolation: boolean;
|
|
15
|
+
readonly rules: readonly AuditRuleConfiguration[];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface ResolveAuditConfigurationInput {
|
|
19
|
+
readonly failOnRuleViolation?: boolean;
|
|
20
|
+
readonly rules?: readonly AuditRuleConfiguration[];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface ImportEvidence {
|
|
24
|
+
readonly filePath: string;
|
|
25
|
+
readonly fileClass: string;
|
|
26
|
+
readonly importName: string;
|
|
27
|
+
readonly isIntrinsic?: boolean;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface CycleEdgeEvidence {
|
|
31
|
+
readonly from: string;
|
|
32
|
+
readonly to: string;
|
|
33
|
+
readonly via: readonly ImportEvidence[];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface PackageCycleDetail {
|
|
37
|
+
readonly packages: readonly string[];
|
|
38
|
+
readonly edges: readonly CycleEdgeEvidence[];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface AuditRuleResult<TEvidence = unknown> {
|
|
42
|
+
readonly id: string;
|
|
43
|
+
readonly status: AuditRuleStatus;
|
|
44
|
+
readonly policy: AuditRulePolicy;
|
|
45
|
+
readonly message: string;
|
|
46
|
+
readonly details: readonly string[];
|
|
47
|
+
readonly evidence: TEvidence;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface CyclicDependenciesEvidence {
|
|
51
|
+
readonly cycles: readonly PackageCycleDetail[];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
interface AuditEvaluation {
|
|
55
|
+
readonly cyclicPackages: readonly PackageCycleDetail[];
|
|
56
|
+
readonly rules: readonly AuditRuleResult[];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
interface AuditMeta {
|
|
60
|
+
readonly timeEnd: number;
|
|
61
|
+
readonly timeStart: number;
|
|
62
|
+
readonly language: ParserSelection;
|
|
63
|
+
readonly projectName: string;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export interface Audit {
|
|
67
|
+
readonly configuration: AuditConfiguration;
|
|
68
|
+
readonly evaluation: AuditEvaluation;
|
|
69
|
+
readonly meta: AuditMeta;
|
|
70
|
+
readonly files: ParsedDirectory;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export interface EvaluateAuditRulesInput {
|
|
74
|
+
readonly configuration: AuditConfiguration;
|
|
75
|
+
readonly cyclicPackages: readonly PackageCycleDetail[];
|
|
76
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { PackageCycleDetail } from '@/types/audit';
|
|
2
|
+
|
|
3
|
+
export interface CycleHighlight {
|
|
4
|
+
readonly id: string;
|
|
5
|
+
readonly color: string;
|
|
6
|
+
readonly cycle: PackageCycleDetail;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface CycleInspection extends CycleHighlight {
|
|
10
|
+
readonly label: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface CycleFocus {
|
|
14
|
+
readonly currentPackage: string;
|
|
15
|
+
readonly packageDepth: number;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface CycleSelection {
|
|
19
|
+
readonly highlights: readonly CycleHighlight[];
|
|
20
|
+
readonly selectedIds: readonly string[];
|
|
21
|
+
readonly setSelected: (id: string, selected: boolean) => void;
|
|
22
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface GraphInteractionState {
|
|
2
|
+
readonly hoveredNodeId: string | null;
|
|
3
|
+
readonly selectedNodeIds: readonly string[];
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export interface GraphInteractionEvent {
|
|
7
|
+
readonly id: string;
|
|
8
|
+
readonly type: 'pointer-enter' | 'pointer-leave' | 'select' | 'unselect';
|
|
9
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { DetectedLanguage } from '@ankhorage/project-detector/types';
|
|
2
|
+
|
|
3
|
+
import type { Language } from '../shared/types';
|
|
4
|
+
|
|
5
|
+
/** pkgviz's parser choice, not a generic project's single language or a probability. */
|
|
6
|
+
export interface ParserSelection {
|
|
7
|
+
readonly language: Language;
|
|
8
|
+
readonly score: number;
|
|
9
|
+
readonly indicators: readonly string[];
|
|
10
|
+
readonly candidates: readonly DetectedLanguage[];
|
|
11
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ElementsDefinition } from 'cytoscape';
|
|
2
|
+
|
|
3
|
+
import type { ParsedDirectory } from '@/shared/types';
|
|
4
|
+
import type { Audit } from '@/types/audit';
|
|
5
|
+
import type { ParserSelection } from '@/types/parserSelection';
|
|
6
|
+
import type { ProjectTreeNode } from '@/types/projectTree';
|
|
7
|
+
|
|
8
|
+
export interface ProjectSnapshot {
|
|
9
|
+
readonly files: ParsedDirectory;
|
|
10
|
+
readonly graph: ElementsDefinition;
|
|
11
|
+
readonly language: ParserSelection;
|
|
12
|
+
readonly projectPath: string;
|
|
13
|
+
readonly timeStart: number;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface ProjectOverview {
|
|
17
|
+
readonly graph: ElementsDefinition;
|
|
18
|
+
readonly tree: readonly ProjectTreeNode[];
|
|
19
|
+
readonly evaluation: Audit['evaluation'];
|
|
20
|
+
}
|
|
@@ -1,16 +1,34 @@
|
|
|
1
|
+
import { isIntrinsicGraphNode } from '@/utils/filter/isIntrinsicGraphNode';
|
|
2
|
+
|
|
3
|
+
/***
|
|
4
|
+
* Filters project descendants while retaining their adjacent external dependency endpoints.
|
|
5
|
+
* @performance Use endpoint sets to retain adjacent vendors without per-vendor edge scans.
|
|
6
|
+
*/
|
|
1
7
|
export function filterByPackagePrefix(
|
|
2
8
|
allElements: cytoscape.ElementsDefinition,
|
|
3
9
|
packagePrefix: string
|
|
4
10
|
): cytoscape.ElementsDefinition {
|
|
5
|
-
|
|
6
|
-
if (!
|
|
11
|
+
const normalizedPrefix = packagePrefix.replace(/\.+$/, '');
|
|
12
|
+
if (!normalizedPrefix) return allElements;
|
|
7
13
|
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
return (node
|
|
14
|
+
const descendantPrefix = normalizedPrefix + '.';
|
|
15
|
+
const projectNodes = allElements.nodes.filter(node => {
|
|
16
|
+
const id = node.data.id ?? '';
|
|
17
|
+
return isIntrinsicGraphNode(node) && id.startsWith(descendantPrefix);
|
|
12
18
|
});
|
|
13
|
-
|
|
19
|
+
const projectIds = new Set(projectNodes.map(node => node.data.id));
|
|
20
|
+
const connectedIds = new Set(
|
|
21
|
+
allElements.edges.flatMap(edge =>
|
|
22
|
+
projectIds.has(edge.data.source) || projectIds.has(edge.data.target)
|
|
23
|
+
? [edge.data.source, edge.data.target]
|
|
24
|
+
: []
|
|
25
|
+
)
|
|
26
|
+
);
|
|
27
|
+
const allowedNodes = allElements.nodes.filter(
|
|
28
|
+
node =>
|
|
29
|
+
projectIds.has(node.data.id) ||
|
|
30
|
+
(!isIntrinsicGraphNode(node) && connectedIds.has(String(node.data.id)))
|
|
31
|
+
);
|
|
14
32
|
const allowedNodeIds = new Set(allowedNodes.map(node => node.data.id));
|
|
15
33
|
const allowedEdges = allElements.edges.filter(
|
|
16
34
|
edge => allowedNodeIds.has(edge.data.source) && allowedNodeIds.has(edge.data.target)
|
|
@@ -1,36 +1,35 @@
|
|
|
1
|
-
import { ElementsDefinition } from 'cytoscape';
|
|
1
|
+
import type { ElementsDefinition } from 'cytoscape';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
* Returns root package if only one inside, or '' (root folder)
|
|
5
|
-
*/
|
|
6
|
-
function getRootPackage(elements: ElementsDefinition) {
|
|
7
|
-
const rootPackages = elements.nodes.filter(n => {
|
|
8
|
-
return !n.data.id?.includes('.');
|
|
9
|
-
});
|
|
10
|
-
return rootPackages.length > 1 ? '' : (rootPackages[0].data.id as string);
|
|
11
|
-
}
|
|
3
|
+
import { isIntrinsicGraphNode } from '@/utils/filter/isIntrinsicGraphNode';
|
|
12
4
|
|
|
13
|
-
|
|
14
|
-
*
|
|
5
|
+
/***
|
|
6
|
+
* Skips a unique chain of structural project packages, stopping before real dependency endpoints.
|
|
7
|
+
* @performance Use full-graph indexes: navigation must not depend on depth projection or vendors.
|
|
8
|
+
* Preserve real isolated leaves and branching packages rather than silently filtering them away.
|
|
15
9
|
*/
|
|
16
10
|
export function filterEmptyPackages(currentPackage: string, elements: ElementsDefinition): string {
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
);
|
|
27
|
-
|
|
28
|
-
if (childPackages.length === 1) {
|
|
29
|
-
currentPackage = childPackages[0];
|
|
30
|
-
} else {
|
|
31
|
-
break;
|
|
32
|
-
}
|
|
11
|
+
const children = new Map<string, string[]>();
|
|
12
|
+
for (const node of elements.nodes.filter(isIntrinsicGraphNode)) {
|
|
13
|
+
const id = String(node.data.id ?? '');
|
|
14
|
+
if (!id) continue;
|
|
15
|
+
const boundary = id.lastIndexOf('.');
|
|
16
|
+
const parent = boundary < 0 ? '' : id.slice(0, boundary);
|
|
17
|
+
const siblings = children.get(parent) ?? [];
|
|
18
|
+
siblings.push(id);
|
|
19
|
+
children.set(parent, siblings);
|
|
33
20
|
}
|
|
21
|
+
const connected = new Set(elements.edges.flatMap(edge => [edge.data.source, edge.data.target]));
|
|
22
|
+
return descend(currentPackage, children, connected);
|
|
23
|
+
}
|
|
34
24
|
|
|
35
|
-
|
|
25
|
+
/*** Descends only when the next package is a relationship-free structural container. */
|
|
26
|
+
function descend(
|
|
27
|
+
scope: string,
|
|
28
|
+
children: ReadonlyMap<string, readonly string[]>,
|
|
29
|
+
connected: ReadonlySet<string>
|
|
30
|
+
): string {
|
|
31
|
+
const candidates = children.get(scope) ?? [];
|
|
32
|
+
const next = candidates[0];
|
|
33
|
+
if (candidates.length !== 1 || !next || connected.has(next) || !children.has(next)) return scope;
|
|
34
|
+
return descend(next, children, connected);
|
|
36
35
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { EdgeDefinition, ElementsDefinition } from 'cytoscape';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
/***
|
|
4
4
|
* Compute the minimal set of "root" packages that have no ancestor in the list.
|
|
5
5
|
* Example: ['x.y', 'x.y.z', 'a', 'a.c.x'] => ['a', 'x.y']
|
|
6
6
|
*/
|
|
@@ -16,7 +16,7 @@ function findRoots(packages: string[]): string[] {
|
|
|
16
16
|
return roots;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
/***
|
|
20
20
|
* Ascend from a package to its nearest ancestor that is in the `roots` set.
|
|
21
21
|
*/
|
|
22
22
|
function nearestRoot(pkg: string, roots: Set<string>): string {
|
|
@@ -31,7 +31,7 @@ function nearestRoot(pkg: string, roots: Set<string>): string {
|
|
|
31
31
|
return pkg;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
/***
|
|
35
35
|
* Given a root and a leaf pkg, return the visible ancestor at `maxDepth`
|
|
36
36
|
* under the root, preferring the deepest existing package <= target depth.
|
|
37
37
|
*
|
|
@@ -59,7 +59,7 @@ function visibleAncestorForDepth(
|
|
|
59
59
|
return root; // fallback
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
/***
|
|
63
63
|
* Global maximum depth across all roots.
|
|
64
64
|
* Depth is counted relative to the nearest root: root=1, root.child=2, etc.
|
|
65
65
|
*/
|
|
@@ -79,7 +79,7 @@ export function getMaxDepth(elements: ElementsDefinition): number {
|
|
|
79
79
|
return maxDepth;
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
|
|
82
|
+
/***
|
|
83
83
|
* Maximum depth per root, e.g. { 'a': 3, 'x.y': 2 }.
|
|
84
84
|
*/
|
|
85
85
|
export function getMaxDepthByRoot(elements: ElementsDefinition): Record<string, number> {
|
|
@@ -96,19 +96,17 @@ export function getMaxDepthByRoot(elements: ElementsDefinition): Record<string,
|
|
|
96
96
|
return result;
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
|
|
99
|
+
/***
|
|
100
100
|
* Filters sub-packages so only the desired number of levels under each root are shown.
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
* @param allowSelfLoops - Keep self loops after lifting/aggregation
|
|
104
|
-
* @param maxDepth - Number of levels to keep under each root (1 = roots only, 2 = +children, etc.)
|
|
101
|
+
* @performance Aggregate weights and origin IDs in local maps without repeatedly copying growing
|
|
102
|
+
* evidence arrays. Inputs remain immutable; a large lifted bundle must stay linear in edge count.
|
|
105
103
|
*/
|
|
106
104
|
export function filterSubPackagesByDepth(
|
|
107
105
|
elements: ElementsDefinition,
|
|
108
|
-
allowSelfLoops
|
|
109
|
-
maxDepth
|
|
106
|
+
allowSelfLoops = false,
|
|
107
|
+
maxDepth = 1
|
|
110
108
|
): ElementsDefinition {
|
|
111
|
-
const allPackages = elements.nodes.map(n => n.data.id
|
|
109
|
+
const allPackages = elements.nodes.map(n => n.data.id!);
|
|
112
110
|
const existingSet = new Set(allPackages);
|
|
113
111
|
|
|
114
112
|
// 1) Identify minimal roots (no ancestor present)
|
|
@@ -125,14 +123,15 @@ export function filterSubPackagesByDepth(
|
|
|
125
123
|
|
|
126
124
|
// 3) Visible nodes = unique set of chosen ancestors
|
|
127
125
|
const visibleNodeIds = new Set<string>(pkgToVisible.values());
|
|
128
|
-
const filteredNodes = elements.nodes.filter(n => visibleNodeIds.has(n.data.id
|
|
126
|
+
const filteredNodes = elements.nodes.filter(n => visibleNodeIds.has(n.data.id!));
|
|
129
127
|
|
|
130
128
|
// 4) Lift & aggregate edges to visible ancestors (sum weights)
|
|
131
129
|
const edgeMap = new Map<string, EdgeDefinition>();
|
|
130
|
+
const edgeOrigins = new Map<string, string[]>();
|
|
132
131
|
|
|
133
132
|
for (const e of elements.edges) {
|
|
134
|
-
const rawSource = e.data.source
|
|
135
|
-
const rawTarget = e.data.target
|
|
133
|
+
const rawSource = e.data.source;
|
|
134
|
+
const rawTarget = e.data.target;
|
|
136
135
|
|
|
137
136
|
const liftedSource = pkgToVisible.get(rawSource) ?? rawSource;
|
|
138
137
|
const liftedTarget = pkgToVisible.get(rawTarget) ?? rawTarget;
|
|
@@ -145,13 +144,17 @@ export function filterSubPackagesByDepth(
|
|
|
145
144
|
}
|
|
146
145
|
|
|
147
146
|
const key = `${liftedSource}->${liftedTarget}`;
|
|
147
|
+
const origins = edgeOrigins.get(key) ?? [];
|
|
148
|
+
origins.push(e.data.id ?? `${rawSource}->${rawTarget}`);
|
|
149
|
+
edgeOrigins.set(key, origins);
|
|
148
150
|
if (!edgeMap.has(key)) {
|
|
149
151
|
// clone with lifted endpoints; keep your metadata; (optionally set a stable id)
|
|
150
152
|
edgeMap.set(key, {
|
|
151
153
|
...e,
|
|
152
154
|
data: {
|
|
153
155
|
...e.data,
|
|
154
|
-
|
|
156
|
+
id: key,
|
|
157
|
+
originalEdgeIds: origins,
|
|
155
158
|
source: liftedSource,
|
|
156
159
|
target: liftedTarget,
|
|
157
160
|
// initialize aggregated weight
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { NodeDefinition } from 'cytoscape';
|
|
2
|
+
|
|
3
|
+
/*** Identifies project nodes using the graph builder's classification, not namespace spelling. */
|
|
4
|
+
export function isIntrinsicGraphNode(node: NodeDefinition): boolean {
|
|
5
|
+
if (typeof node.data.isIntrinsic === 'boolean') return node.data.isIntrinsic;
|
|
6
|
+
const classes = Array.isArray(node.classes) ? node.classes : (node.classes ?? '').split(/\s+/);
|
|
7
|
+
return !classes.includes('isVendor');
|
|
8
|
+
}
|