pkgviz 0.7.7 → 0.8.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/.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/0_j-_aavigxqr.js +345 -0
- 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/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/qznDSVYlkQxVdRx-TE_Wk/_buildManifest.js +11 -0
- package/.next/static/qznDSVYlkQxVdRx-TE_Wk/_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 +109 -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 → qznDSVYlkQxVdRx-TE_Wk}/_ssgManifest.js +0 -0
package/package.json
CHANGED
|
@@ -4,62 +4,83 @@
|
|
|
4
4
|
"pkgviz": "bin/pkgviz.ts"
|
|
5
5
|
},
|
|
6
6
|
"files": [
|
|
7
|
-
"
|
|
8
|
-
"
|
|
7
|
+
"bin",
|
|
8
|
+
"src",
|
|
9
9
|
"tsconfig.json",
|
|
10
|
-
".next"
|
|
10
|
+
".next/BUILD_ID",
|
|
11
|
+
".next/*.js",
|
|
12
|
+
".next/*.json",
|
|
13
|
+
".next/server",
|
|
14
|
+
".next/static"
|
|
11
15
|
],
|
|
12
16
|
"type": "module",
|
|
13
17
|
"engines": {
|
|
14
|
-
"node": ">=
|
|
18
|
+
"node": ">=24",
|
|
15
19
|
"bun": ">=1.2.18",
|
|
16
20
|
"npm": ">=10.9.2"
|
|
17
21
|
},
|
|
18
|
-
"version": "0.
|
|
22
|
+
"version": "0.8.1",
|
|
23
|
+
"description": "Analyze and visualize codebases, dependencies, architecture rules, and audit evidence.",
|
|
24
|
+
"keywords": [
|
|
25
|
+
"code-analysis",
|
|
26
|
+
"dependency-graph",
|
|
27
|
+
"architecture",
|
|
28
|
+
"visualization",
|
|
29
|
+
"static-analysis",
|
|
30
|
+
"cytoscape",
|
|
31
|
+
"developer-tools",
|
|
32
|
+
"typescript",
|
|
33
|
+
"audit",
|
|
34
|
+
"codebase"
|
|
35
|
+
],
|
|
19
36
|
"scripts": {
|
|
20
|
-
"dev": "next dev
|
|
21
|
-
"build": "next build",
|
|
22
|
-
"docs:deploy": "bun --filter forensics-docs run deploy",
|
|
37
|
+
"dev": "bun run zora:materialize && next dev",
|
|
38
|
+
"build": "bun run zora:materialize && next build",
|
|
23
39
|
"start": "next start",
|
|
24
|
-
"lint": "
|
|
25
|
-
"format:check": "prettier --check .",
|
|
26
|
-
"format:write": "prettier --write \"**/*.{js,jsx,ts,tsx,json,md,yml,yaml,mjs,cjs,html,css,scss,mdx}\"",
|
|
27
|
-
"test": "
|
|
40
|
+
"lint": "bun run zora:materialize && ankhorage-eslint . --max-warnings=0",
|
|
41
|
+
"format:check": "ankhorage-prettier --check .",
|
|
42
|
+
"format:write": "ankhorage-prettier --write \"**/*.{js,jsx,ts,tsx,json,md,yml,yaml,mjs,cjs,html,css,scss,mdx}\"",
|
|
43
|
+
"test": "testosterone && bun run test:maven",
|
|
28
44
|
"test:cov": "c8 --reporter=text --reporter=text-summary tsx --test",
|
|
29
|
-
"test:cov:html": "c8 --report-dir=./test/coverage --reporter=html tsx --test"
|
|
45
|
+
"test:cov:html": "c8 --report-dir=./test/coverage --reporter=html tsx --test",
|
|
46
|
+
"lint:fix": "bun run zora:materialize && ankhorage-eslint . --fix --max-warnings=0",
|
|
47
|
+
"format": "ankhorage-prettier --write .",
|
|
48
|
+
"knip:check": "bun run zora:materialize && ankhorage-knip",
|
|
49
|
+
"changeset": "ankhorage-changeset",
|
|
50
|
+
"changeset:status": "ankhorage-changeset status --since=origin/main",
|
|
51
|
+
"version-packages": "ankhorage-changeset version",
|
|
52
|
+
"test:maven": "mvn -B -f maven-plugin/pom.xml test",
|
|
53
|
+
"zora:materialize": "ANKH_CACHE_DIR=.generated/ankh bunx @ankhorage/ankh@0.10.4 zora create tree-view --web --out .generated/zora/tree-view && ANKH_CACHE_DIR=.generated/ankh bunx @ankhorage/ankh@0.10.4 zora create graph-view --web --out .generated/zora/graph-view"
|
|
30
54
|
},
|
|
31
55
|
"dependencies": {
|
|
32
|
-
"@
|
|
33
|
-
"
|
|
34
|
-
"cytoscape
|
|
35
|
-
"
|
|
56
|
+
"@ankhorage/dependency-graph": "^0.6.0",
|
|
57
|
+
"@ankhorage/graph": "^0.2.0",
|
|
58
|
+
"@ankhorage/graph-cytoscape": "^0.1.1",
|
|
59
|
+
"@ankhorage/project-detector": "^0.1.0",
|
|
60
|
+
"@ankhorage/utility": "^1.4.0",
|
|
61
|
+
"@artiphishle/testosterone": "^0.3.9",
|
|
62
|
+
"ankh-hooks": "^1.5.2",
|
|
63
|
+
"cytoscape": "^3.34.3",
|
|
36
64
|
"lucide-react": "^0.487.0",
|
|
37
|
-
"
|
|
38
|
-
"next": "15.4.10",
|
|
65
|
+
"next": "16.3.5",
|
|
39
66
|
"next-themes": "^0.4.6",
|
|
40
67
|
"radix-ui": "^1.4.3",
|
|
41
|
-
"react": "^19.2.
|
|
42
|
-
"react-dom": "^19.2.
|
|
43
|
-
"typescript": "
|
|
68
|
+
"react": "^19.2.4",
|
|
69
|
+
"react-dom": "^19.2.4",
|
|
70
|
+
"typescript": "~6.0.3",
|
|
44
71
|
"xml-js": "^1.6.11"
|
|
45
72
|
},
|
|
46
73
|
"devDependencies": {
|
|
47
|
-
"@
|
|
48
|
-
"@tailwindcss/postcss": "^4.1.
|
|
49
|
-
"@types/bun": "^1.
|
|
50
|
-
"@types/
|
|
51
|
-
"@types/
|
|
52
|
-
"@types/react": "^19.2.5",
|
|
74
|
+
"@ankhorage/devtools": "^1.16.0",
|
|
75
|
+
"@tailwindcss/postcss": "^4.1.18",
|
|
76
|
+
"@types/bun": "^1.4.2",
|
|
77
|
+
"@types/node": "^24.13.5",
|
|
78
|
+
"@types/react": "^19.2.10",
|
|
53
79
|
"@types/react-dom": "^19.2.3",
|
|
54
|
-
"autoprefixer": "^10.4.22",
|
|
55
80
|
"c8": "^10.1.3",
|
|
56
|
-
"eslint": "^9.39.1",
|
|
57
|
-
"eslint-config-next": "15.3.0",
|
|
58
81
|
"postcss": "^8.5.6",
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"tailwindcss-cli": "^0.1.2",
|
|
62
|
-
"tsx": "^4.20.6"
|
|
82
|
+
"tailwindcss": "^4.1.18",
|
|
83
|
+
"tsx": "^4.21.0"
|
|
63
84
|
},
|
|
64
|
-
"packageManager": "
|
|
85
|
+
"packageManager": "bun@1.4.2"
|
|
65
86
|
}
|
|
@@ -1,44 +1,16 @@
|
|
|
1
1
|
'use server';
|
|
2
|
-
import
|
|
2
|
+
import { js2xml } from 'xml-js';
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
import { detectLanguage } from '@/shared/utils/detectLanguage';
|
|
6
|
-
import {
|
|
7
|
-
getPackageCyclesWithMembers,
|
|
8
|
-
type PackageCycleDetail,
|
|
9
|
-
} from '@/app/utils/markCyclicPackages';
|
|
10
|
-
import { buildGraph } from '@/app/utils/buildGraph';
|
|
4
|
+
import { createAuditAsync } from '@/features/audit/composition/createAuditAsync';
|
|
11
5
|
import { parseProjectPath } from '@/shared/utils/parseProjectPath';
|
|
12
|
-
import {
|
|
13
|
-
import { js2xml } from 'xml-js';
|
|
6
|
+
import type { Audit } from '@/types/audit';
|
|
14
7
|
|
|
8
|
+
/*** Builds the audit payload for the configured project. */
|
|
15
9
|
export async function getAuditAction(): Promise<Audit> {
|
|
16
|
-
|
|
17
|
-
const projectName = getProjectName();
|
|
18
|
-
const timeStart = Date.now();
|
|
19
|
-
const language = await detectLanguage(projectPath);
|
|
20
|
-
const files = await getParsedFileStructure();
|
|
21
|
-
const graph = buildGraph(files);
|
|
22
|
-
const cyclicPackages = getPackageCyclesWithMembers(files, graph).cycles;
|
|
23
|
-
|
|
24
|
-
const audit: Partial<Audit> = {
|
|
25
|
-
evaluation: {
|
|
26
|
-
cyclicPackages,
|
|
27
|
-
},
|
|
28
|
-
files,
|
|
29
|
-
meta: {
|
|
30
|
-
language,
|
|
31
|
-
projectName,
|
|
32
|
-
timeStart,
|
|
33
|
-
timeEnd: timeStart,
|
|
34
|
-
},
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
audit.meta!.timeEnd = Date.now();
|
|
38
|
-
|
|
39
|
-
return audit as Audit;
|
|
10
|
+
return await createAuditAsync(parseProjectPath());
|
|
40
11
|
}
|
|
41
12
|
|
|
13
|
+
/*** Serializes the current project audit as JSON. */
|
|
42
14
|
export async function downloadAuditJsonAction(): Promise<{ data: string; filename: string }> {
|
|
43
15
|
const audit = await getAuditAction();
|
|
44
16
|
const jsonString = JSON.stringify(audit, null, 2);
|
|
@@ -47,6 +19,7 @@ export async function downloadAuditJsonAction(): Promise<{ data: string; filenam
|
|
|
47
19
|
return { data: jsonString, filename };
|
|
48
20
|
}
|
|
49
21
|
|
|
22
|
+
/*** Serializes the current project audit as XML. */
|
|
50
23
|
export async function downloadAuditXmlAction(): Promise<{ data: string; filename: string }> {
|
|
51
24
|
const audit = await getAuditAction();
|
|
52
25
|
const xmlString = js2xml({ audit }, { compact: true, spaces: 2 });
|
|
@@ -54,18 +27,3 @@ export async function downloadAuditXmlAction(): Promise<{ data: string; filename
|
|
|
54
27
|
|
|
55
28
|
return { data: xmlString, filename };
|
|
56
29
|
}
|
|
57
|
-
|
|
58
|
-
interface AuditMeta {
|
|
59
|
-
timeEnd: number;
|
|
60
|
-
readonly timeStart: number;
|
|
61
|
-
readonly language: LanguageDetectionResult;
|
|
62
|
-
readonly projectName: string;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export interface Audit {
|
|
66
|
-
readonly evaluation: {
|
|
67
|
-
readonly cyclicPackages: PackageCycleDetail[];
|
|
68
|
-
};
|
|
69
|
-
readonly meta: AuditMeta;
|
|
70
|
-
readonly files: ParsedDirectory;
|
|
71
|
-
}
|
package/src/app/globals.css
CHANGED
package/src/app/layout.tsx
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import '@/app/globals.css';
|
|
2
2
|
|
|
3
|
+
import type { Metadata } from 'next';
|
|
3
4
|
import { Geist, Geist_Mono } from 'next/font/google';
|
|
4
5
|
import { ThemeProvider } from 'next-themes';
|
|
5
|
-
import '@/app/globals.css';
|
|
6
6
|
|
|
7
7
|
const geistSans = Geist({ variable: '--font-geist-sans', subsets: ['latin'] });
|
|
8
8
|
const geistMono = Geist_Mono({ variable: '--font-geist-mono', subsets: ['latin'] });
|
|
@@ -12,6 +12,7 @@ export const metadata: Metadata = {
|
|
|
12
12
|
description: 'Package visualization',
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
+
/*** Renders the application root layout. */
|
|
15
16
|
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
16
17
|
return (
|
|
17
18
|
<html lang="en" suppressHydrationWarning>
|
package/src/app/page.tsx
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
|
+
import { connection } from 'next/server';
|
|
2
|
+
|
|
3
|
+
import { loadProjectOverviewAsync } from '@/features/project-analysis/composition/loadProjectOverviewAsync';
|
|
1
4
|
import HomeScreen from '@/screens/home/Home';
|
|
5
|
+
import { parseProjectPath } from '@/shared/utils/parseProjectPath';
|
|
6
|
+
import { runProjectAnalysisActionAsync } from '@/utils/runProjectAnalysisActionAsync';
|
|
2
7
|
|
|
3
|
-
|
|
4
|
-
|
|
8
|
+
/***
|
|
9
|
+
* Loads one overview per page request rather than starting analysis from client mount effects.
|
|
10
|
+
* @performance Keep this request-time read dynamic: build-time or persistent caching would hide
|
|
11
|
+
* source edits. Client Strict Mode rendering must not trigger another filesystem analysis.
|
|
12
|
+
*/
|
|
13
|
+
export default async function Home() {
|
|
14
|
+
await connection();
|
|
15
|
+
const project = await runProjectAnalysisActionAsync(() =>
|
|
16
|
+
loadProjectOverviewAsync(parseProjectPath())
|
|
17
|
+
);
|
|
18
|
+
return <HomeScreen project={project} />;
|
|
5
19
|
}
|
|
@@ -1,119 +1,118 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
NodeDefinition,
|
|
6
|
-
} from 'cytoscape';
|
|
1
|
+
import type { Graph, GraphEdge, GraphNode } from '@ankhorage/graph';
|
|
2
|
+
import { toCytoscapeElements } from '@ankhorage/graph-cytoscape';
|
|
3
|
+
import type { ElementsDefinition } from 'cytoscape';
|
|
4
|
+
|
|
7
5
|
import type { ParsedDirectory, ParsedFile } from '@/shared/types';
|
|
8
6
|
|
|
9
|
-
|
|
10
|
-
* Builds a weighted dependency graph
|
|
11
|
-
* - Adds intrinsic directory nodes (from folder structure)
|
|
12
|
-
* - Aggregates edges (source pkg -> target pkg) with cumulative weight
|
|
13
|
-
* - Adds vendor nodes for any edge endpoints not present as intrinsic nodes
|
|
14
|
-
* - Sanitizes: skips empty package ids and self-edges
|
|
7
|
+
/***
|
|
8
|
+
* Builds a weighted dependency graph and converts it through the canonical Cytoscape adapter.
|
|
15
9
|
*/
|
|
16
|
-
export function buildGraph(dir: ParsedDirectory) {
|
|
17
|
-
|
|
18
|
-
* Build graph (nodes/edges) recursively
|
|
19
|
-
*/
|
|
20
|
-
function buildGraphRecursively(
|
|
21
|
-
currentDir: ParsedDirectory,
|
|
22
|
-
currentPath = '',
|
|
23
|
-
nodes: NodeDefinition[] = [],
|
|
24
|
-
edges: Map<string, EdgeDefinition> = new Map()
|
|
25
|
-
) {
|
|
26
|
-
Object.keys(currentDir).forEach(key => {
|
|
27
|
-
const dirOrFile = (currentDir as Record<string, ParsedDirectory | ParsedFile>)[key];
|
|
28
|
-
const isDirectory = !(dirOrFile as ParsedFile)?.className;
|
|
29
|
-
|
|
30
|
-
// 1) Add directory as a node
|
|
31
|
-
if (isDirectory) {
|
|
32
|
-
const pkg = currentPath ? `${currentPath}.${key}` : key;
|
|
33
|
-
|
|
34
|
-
nodes.push({
|
|
35
|
-
data: {
|
|
36
|
-
id: pkg,
|
|
37
|
-
path: pkg,
|
|
38
|
-
parent: currentPath,
|
|
39
|
-
label: key,
|
|
40
|
-
name: key.split('.').pop() || key,
|
|
41
|
-
isIntrinsic: true,
|
|
42
|
-
},
|
|
43
|
-
group: 'nodes',
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
// Recurse into subdirectories
|
|
47
|
-
return buildGraphRecursively(dirOrFile as ParsedDirectory, pkg, nodes, edges);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// 2) Aggregate file imports as weighted package edges (package perspective)
|
|
51
|
-
const file = dirOrFile as ParsedFile;
|
|
52
|
-
const source = file.package?.trim();
|
|
53
|
-
if (!source) return; // skip empty/default package ids
|
|
54
|
-
|
|
55
|
-
const targets = (file.imports ?? [])
|
|
56
|
-
.map(imp => imp.pkg?.trim())
|
|
57
|
-
.filter((t): t is string => !!t);
|
|
58
|
-
|
|
59
|
-
targets.forEach(target => {
|
|
60
|
-
if (target === source) return; // skip self-edges at package level
|
|
61
|
-
|
|
62
|
-
const edgeId = `${source}->${target}`;
|
|
63
|
-
const existing = edges.get(edgeId);
|
|
64
|
-
const prev = (existing?.data as EdgeDataDefinitionWithWeight | undefined)?.weight ?? 0;
|
|
65
|
-
const weight: EdgeDataDefinitionWithWeight['weight'] = prev + 1;
|
|
66
|
-
|
|
67
|
-
const data: EdgeDataDefinitionWithWeight = { source, target, weight };
|
|
68
|
-
edges.set(edgeId, { data, group: 'edges' });
|
|
69
|
-
});
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
return { nodes, edges };
|
|
73
|
-
}
|
|
10
|
+
export function buildGraph(dir: ParsedDirectory): ElementsDefinition {
|
|
11
|
+
const graph = buildCanonicalGraph(dir);
|
|
74
12
|
|
|
75
|
-
|
|
13
|
+
return toCytoscapeElements(graph, {
|
|
14
|
+
nodeClasses: node => (node.data.isIntrinsic === true ? undefined : 'isVendor'),
|
|
15
|
+
});
|
|
16
|
+
}
|
|
76
17
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const id = String(maybeNode ?? '').trim();
|
|
81
|
-
if (!id) return; // don't create a node with empty id
|
|
18
|
+
/*** Builds PKGViz package dependencies in the canonical Ankhorage graph model. */
|
|
19
|
+
function buildCanonicalGraph(dir: ParsedDirectory): Graph<PackageNodeData, PackageEdgeData> {
|
|
20
|
+
const { nodes, edges } = buildGraphRecursively(dir);
|
|
82
21
|
|
|
83
|
-
|
|
84
|
-
|
|
22
|
+
for (const edge of edges.values()) {
|
|
23
|
+
for (const endpoint of [edge.source, edge.target]) {
|
|
24
|
+
if (nodes.some(node => node.id === endpoint)) continue;
|
|
85
25
|
|
|
86
|
-
|
|
87
|
-
const
|
|
26
|
+
const parent = endpoint.includes('.') ? endpoint.split('.').slice(0, -1).join('.') : '';
|
|
27
|
+
const name = endpoint.split('.').pop() || endpoint;
|
|
88
28
|
|
|
89
|
-
|
|
90
|
-
|
|
29
|
+
nodes.push({
|
|
30
|
+
id: endpoint,
|
|
91
31
|
data: {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
path: id,
|
|
32
|
+
label: endpoint,
|
|
33
|
+
path: endpoint,
|
|
95
34
|
parent,
|
|
96
|
-
name
|
|
35
|
+
name,
|
|
97
36
|
},
|
|
98
|
-
group: 'nodes',
|
|
99
|
-
classes: 'isVendor',
|
|
100
37
|
});
|
|
101
|
-
}
|
|
102
|
-
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
103
40
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
edges: Array.from(rawElements.edges.values()),
|
|
41
|
+
return {
|
|
42
|
+
nodes,
|
|
43
|
+
edges: Array.from(edges.values()),
|
|
108
44
|
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/*** Recursively collects intrinsic package nodes and weighted dependency edges. */
|
|
48
|
+
function buildGraphRecursively(
|
|
49
|
+
currentDir: ParsedDirectory,
|
|
50
|
+
currentPath = '',
|
|
51
|
+
nodes: GraphNode<PackageNodeData>[] = [],
|
|
52
|
+
edges = new Map<string, GraphEdge<PackageEdgeData>>()
|
|
53
|
+
): CanonicalGraphAccumulator {
|
|
54
|
+
for (const key of Object.keys(currentDir)) {
|
|
55
|
+
const dirOrFile = (currentDir as Record<string, ParsedDirectory | ParsedFile>)[key];
|
|
56
|
+
const isDirectory = !(dirOrFile as ParsedFile)?.className;
|
|
57
|
+
|
|
58
|
+
if (isDirectory) {
|
|
59
|
+
const pkg = currentPath ? `${currentPath}.${key}` : key;
|
|
60
|
+
|
|
61
|
+
nodes.push({
|
|
62
|
+
id: pkg,
|
|
63
|
+
data: {
|
|
64
|
+
path: pkg,
|
|
65
|
+
parent: currentPath,
|
|
66
|
+
label: key,
|
|
67
|
+
name: key.split('.').pop() || key,
|
|
68
|
+
isIntrinsic: true,
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
buildGraphRecursively(dirOrFile as ParsedDirectory, pkg, nodes, edges);
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const file = dirOrFile as ParsedFile;
|
|
77
|
+
const source = file.package?.trim();
|
|
78
|
+
if (!source) continue;
|
|
79
|
+
|
|
80
|
+
const targets = (file.imports ?? [])
|
|
81
|
+
.map(imp => imp.pkg?.trim())
|
|
82
|
+
.filter((target): target is string => Boolean(target));
|
|
83
|
+
|
|
84
|
+
for (const target of targets) {
|
|
85
|
+
if (target === source) continue;
|
|
86
|
+
|
|
87
|
+
const edgeId = `${source}->${target}`;
|
|
88
|
+
const existing = edges.get(edgeId);
|
|
89
|
+
const weight = (existing?.data.weight ?? 0) + 1;
|
|
109
90
|
|
|
110
|
-
|
|
91
|
+
edges.set(edgeId, {
|
|
92
|
+
id: edgeId,
|
|
93
|
+
source,
|
|
94
|
+
target,
|
|
95
|
+
data: { weight },
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return { nodes, edges };
|
|
111
101
|
}
|
|
112
102
|
|
|
113
|
-
interface
|
|
114
|
-
|
|
103
|
+
interface PackageNodeData extends Readonly<Record<string, unknown>> {
|
|
104
|
+
readonly path: string;
|
|
105
|
+
readonly parent: string;
|
|
106
|
+
readonly label: string;
|
|
107
|
+
readonly name: string;
|
|
108
|
+
readonly isIntrinsic?: boolean;
|
|
115
109
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
readonly
|
|
110
|
+
|
|
111
|
+
interface PackageEdgeData extends Readonly<Record<string, unknown>> {
|
|
112
|
+
readonly weight: number;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
interface CanonicalGraphAccumulator {
|
|
116
|
+
readonly nodes: GraphNode<PackageNodeData>[];
|
|
117
|
+
readonly edges: Map<string, GraphEdge<PackageEdgeData>>;
|
|
119
118
|
}
|