@opensip-cli/dashboard 0.1.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/LICENSE +202 -0
- package/NOTICE +8 -0
- package/README.md +31 -0
- package/dist/__tests__/catalog-provenance.test.d.ts +11 -0
- package/dist/__tests__/catalog-provenance.test.d.ts.map +1 -0
- package/dist/__tests__/catalog-provenance.test.js +130 -0
- package/dist/__tests__/catalog-provenance.test.js.map +1 -0
- package/dist/__tests__/coupling-attribution.test.d.ts +9 -0
- package/dist/__tests__/coupling-attribution.test.d.ts.map +1 -0
- package/dist/__tests__/coupling-attribution.test.js +99 -0
- package/dist/__tests__/coupling-attribution.test.js.map +1 -0
- package/dist/__tests__/dashboard-bundle-weight.test.d.ts +16 -0
- package/dist/__tests__/dashboard-bundle-weight.test.d.ts.map +1 -0
- package/dist/__tests__/dashboard-bundle-weight.test.js +73 -0
- package/dist/__tests__/dashboard-bundle-weight.test.js.map +1 -0
- package/dist/__tests__/dashboard-cell-containment.test.d.ts +2 -0
- package/dist/__tests__/dashboard-cell-containment.test.d.ts.map +1 -0
- package/dist/__tests__/dashboard-cell-containment.test.js +49 -0
- package/dist/__tests__/dashboard-cell-containment.test.js.map +1 -0
- package/dist/__tests__/dashboard-cytoscape-vendor.test.d.ts +10 -0
- package/dist/__tests__/dashboard-cytoscape-vendor.test.d.ts.map +1 -0
- package/dist/__tests__/dashboard-cytoscape-vendor.test.js +40 -0
- package/dist/__tests__/dashboard-cytoscape-vendor.test.js.map +1 -0
- package/dist/__tests__/dashboard-editor-link.test.d.ts +5 -0
- package/dist/__tests__/dashboard-editor-link.test.d.ts.map +1 -0
- package/dist/__tests__/dashboard-editor-link.test.js +36 -0
- package/dist/__tests__/dashboard-editor-link.test.js.map +1 -0
- package/dist/__tests__/dashboard-filters.test.d.ts +9 -0
- package/dist/__tests__/dashboard-filters.test.d.ts.map +1 -0
- package/dist/__tests__/dashboard-filters.test.js +95 -0
- package/dist/__tests__/dashboard-filters.test.js.map +1 -0
- package/dist/__tests__/dashboard-function-card-singleton.test.d.ts +9 -0
- package/dist/__tests__/dashboard-function-card-singleton.test.d.ts.map +1 -0
- package/dist/__tests__/dashboard-function-card-singleton.test.js +87 -0
- package/dist/__tests__/dashboard-function-card-singleton.test.js.map +1 -0
- package/dist/__tests__/dashboard-function-card.test.d.ts +10 -0
- package/dist/__tests__/dashboard-function-card.test.d.ts.map +1 -0
- package/dist/__tests__/dashboard-function-card.test.js +403 -0
- package/dist/__tests__/dashboard-function-card.test.js.map +1 -0
- package/dist/__tests__/dashboard-function-row.test.d.ts +11 -0
- package/dist/__tests__/dashboard-function-row.test.d.ts.map +1 -0
- package/dist/__tests__/dashboard-function-row.test.js +101 -0
- package/dist/__tests__/dashboard-function-row.test.js.map +1 -0
- package/dist/__tests__/dashboard-generator-graph-catalog.test.d.ts +9 -0
- package/dist/__tests__/dashboard-generator-graph-catalog.test.d.ts.map +1 -0
- package/dist/__tests__/dashboard-generator-graph-catalog.test.js +75 -0
- package/dist/__tests__/dashboard-generator-graph-catalog.test.js.map +1 -0
- package/dist/__tests__/dashboard-graph-offline.integration.test.d.ts +13 -0
- package/dist/__tests__/dashboard-graph-offline.integration.test.d.ts.map +1 -0
- package/dist/__tests__/dashboard-graph-offline.integration.test.js +55 -0
- package/dist/__tests__/dashboard-graph-offline.integration.test.js.map +1 -0
- package/dist/__tests__/dashboard-graph-scc.test.d.ts +17 -0
- package/dist/__tests__/dashboard-graph-scc.test.d.ts.map +1 -0
- package/dist/__tests__/dashboard-graph-scc.test.js +89 -0
- package/dist/__tests__/dashboard-graph-scc.test.js.map +1 -0
- package/dist/__tests__/dashboard-graph-view-model.test.d.ts +12 -0
- package/dist/__tests__/dashboard-graph-view-model.test.d.ts.map +1 -0
- package/dist/__tests__/dashboard-graph-view-model.test.js +331 -0
- package/dist/__tests__/dashboard-graph-view-model.test.js.map +1 -0
- package/dist/__tests__/dashboard-help-drawer.test.d.ts +9 -0
- package/dist/__tests__/dashboard-help-drawer.test.d.ts.map +1 -0
- package/dist/__tests__/dashboard-help-drawer.test.js +101 -0
- package/dist/__tests__/dashboard-help-drawer.test.js.map +1 -0
- package/dist/__tests__/dashboard-html.test.d.ts +2 -0
- package/dist/__tests__/dashboard-html.test.d.ts.map +1 -0
- package/dist/__tests__/dashboard-html.test.js +169 -0
- package/dist/__tests__/dashboard-html.test.js.map +1 -0
- package/dist/__tests__/dashboard-indexes.test.d.ts +9 -0
- package/dist/__tests__/dashboard-indexes.test.d.ts.map +1 -0
- package/dist/__tests__/dashboard-indexes.test.js +211 -0
- package/dist/__tests__/dashboard-indexes.test.js.map +1 -0
- package/dist/__tests__/dashboard-path-utils.test.d.ts +6 -0
- package/dist/__tests__/dashboard-path-utils.test.d.ts.map +1 -0
- package/dist/__tests__/dashboard-path-utils.test.js +54 -0
- package/dist/__tests__/dashboard-path-utils.test.js.map +1 -0
- package/dist/__tests__/dashboard-search.test.d.ts +5 -0
- package/dist/__tests__/dashboard-search.test.d.ts.map +1 -0
- package/dist/__tests__/dashboard-search.test.js +46 -0
- package/dist/__tests__/dashboard-search.test.js.map +1 -0
- package/dist/__tests__/dashboard-sessions.test.d.ts +14 -0
- package/dist/__tests__/dashboard-sessions.test.d.ts.map +1 -0
- package/dist/__tests__/dashboard-sessions.test.js +330 -0
- package/dist/__tests__/dashboard-sessions.test.js.map +1 -0
- package/dist/__tests__/dashboard-trace.test.d.ts +5 -0
- package/dist/__tests__/dashboard-trace.test.d.ts.map +1 -0
- package/dist/__tests__/dashboard-trace.test.js +147 -0
- package/dist/__tests__/dashboard-trace.test.js.map +1 -0
- package/dist/__tests__/dashboard-validation.integration.test.d.ts +14 -0
- package/dist/__tests__/dashboard-validation.integration.test.d.ts.map +1 -0
- package/dist/__tests__/dashboard-validation.integration.test.js +221 -0
- package/dist/__tests__/dashboard-validation.integration.test.js.map +1 -0
- package/dist/__tests__/dashboard-view-conformance.test.d.ts +12 -0
- package/dist/__tests__/dashboard-view-conformance.test.d.ts.map +1 -0
- package/dist/__tests__/dashboard-view-conformance.test.js +58 -0
- package/dist/__tests__/dashboard-view-conformance.test.js.map +1 -0
- package/dist/__tests__/dashboard-view-coupling.test.d.ts +7 -0
- package/dist/__tests__/dashboard-view-coupling.test.d.ts.map +1 -0
- package/dist/__tests__/dashboard-view-coupling.test.js +381 -0
- package/dist/__tests__/dashboard-view-coupling.test.js.map +1 -0
- package/dist/__tests__/dashboard-view-distribution.test.d.ts +10 -0
- package/dist/__tests__/dashboard-view-distribution.test.d.ts.map +1 -0
- package/dist/__tests__/dashboard-view-distribution.test.js +272 -0
- package/dist/__tests__/dashboard-view-distribution.test.js.map +1 -0
- package/dist/__tests__/dashboard-view-graph.test.d.ts +13 -0
- package/dist/__tests__/dashboard-view-graph.test.d.ts.map +1 -0
- package/dist/__tests__/dashboard-view-graph.test.js +332 -0
- package/dist/__tests__/dashboard-view-graph.test.js.map +1 -0
- package/dist/__tests__/dashboard-view-template.test.d.ts +21 -0
- package/dist/__tests__/dashboard-view-template.test.d.ts.map +1 -0
- package/dist/__tests__/dashboard-view-template.test.js +153 -0
- package/dist/__tests__/dashboard-view-template.test.js.map +1 -0
- package/dist/__tests__/dashboard.test.d.ts +2 -0
- package/dist/__tests__/dashboard.test.d.ts.map +1 -0
- package/dist/__tests__/dashboard.test.js +129 -0
- package/dist/__tests__/dashboard.test.js.map +1 -0
- package/dist/__tests__/graph-tab.test.d.ts +10 -0
- package/dist/__tests__/graph-tab.test.d.ts.map +1 -0
- package/dist/__tests__/graph-tab.test.js +76 -0
- package/dist/__tests__/graph-tab.test.js.map +1 -0
- package/dist/checks.d.ts +7 -0
- package/dist/checks.d.ts.map +1 -0
- package/dist/checks.js +283 -0
- package/dist/checks.js.map +1 -0
- package/dist/code-paths/__tests__/views-registry.test.d.ts +13 -0
- package/dist/code-paths/__tests__/views-registry.test.d.ts.map +1 -0
- package/dist/code-paths/__tests__/views-registry.test.js +39 -0
- package/dist/code-paths/__tests__/views-registry.test.js.map +1 -0
- package/dist/code-paths/catalog-provenance.d.ts +22 -0
- package/dist/code-paths/catalog-provenance.d.ts.map +1 -0
- package/dist/code-paths/catalog-provenance.js +108 -0
- package/dist/code-paths/catalog-provenance.js.map +1 -0
- package/dist/code-paths/catalog-recipes-tables.d.ts +11 -0
- package/dist/code-paths/catalog-recipes-tables.d.ts.map +1 -0
- package/dist/code-paths/catalog-recipes-tables.js +86 -0
- package/dist/code-paths/catalog-recipes-tables.js.map +1 -0
- package/dist/code-paths/cytoscape-vendor.d.ts +27 -0
- package/dist/code-paths/cytoscape-vendor.d.ts.map +1 -0
- package/dist/code-paths/cytoscape-vendor.js +68 -0
- package/dist/code-paths/cytoscape-vendor.js.map +1 -0
- package/dist/code-paths/editor-link.d.ts +10 -0
- package/dist/code-paths/editor-link.d.ts.map +1 -0
- package/dist/code-paths/editor-link.js +20 -0
- package/dist/code-paths/editor-link.js.map +1 -0
- package/dist/code-paths/filters.d.ts +19 -0
- package/dist/code-paths/filters.d.ts.map +1 -0
- package/dist/code-paths/filters.js +47 -0
- package/dist/code-paths/filters.js.map +1 -0
- package/dist/code-paths/function-card.d.ts +15 -0
- package/dist/code-paths/function-card.d.ts.map +1 -0
- package/dist/code-paths/function-card.js +169 -0
- package/dist/code-paths/function-card.js.map +1 -0
- package/dist/code-paths/function-row.d.ts +17 -0
- package/dist/code-paths/function-row.d.ts.map +1 -0
- package/dist/code-paths/function-row.js +77 -0
- package/dist/code-paths/function-row.js.map +1 -0
- package/dist/code-paths/graph-controls.d.ts +27 -0
- package/dist/code-paths/graph-controls.d.ts.map +1 -0
- package/dist/code-paths/graph-controls.js +257 -0
- package/dist/code-paths/graph-controls.js.map +1 -0
- package/dist/code-paths/graph-scc.d.ts +32 -0
- package/dist/code-paths/graph-scc.d.ts.map +1 -0
- package/dist/code-paths/graph-scc.js +136 -0
- package/dist/code-paths/graph-scc.js.map +1 -0
- package/dist/code-paths/graph-stylesheet.d.ts +22 -0
- package/dist/code-paths/graph-stylesheet.d.ts.map +1 -0
- package/dist/code-paths/graph-stylesheet.js +121 -0
- package/dist/code-paths/graph-stylesheet.js.map +1 -0
- package/dist/code-paths/graph-view-model.d.ts +120 -0
- package/dist/code-paths/graph-view-model.d.ts.map +1 -0
- package/dist/code-paths/graph-view-model.js +199 -0
- package/dist/code-paths/graph-view-model.js.map +1 -0
- package/dist/code-paths/help-drawer.d.ts +18 -0
- package/dist/code-paths/help-drawer.d.ts.map +1 -0
- package/dist/code-paths/help-drawer.js +54 -0
- package/dist/code-paths/help-drawer.js.map +1 -0
- package/dist/code-paths/indexes.d.ts +28 -0
- package/dist/code-paths/indexes.d.ts.map +1 -0
- package/dist/code-paths/indexes.js +97 -0
- package/dist/code-paths/indexes.js.map +1 -0
- package/dist/code-paths/path-utils.d.ts +15 -0
- package/dist/code-paths/path-utils.d.ts.map +1 -0
- package/dist/code-paths/path-utils.js +47 -0
- package/dist/code-paths/path-utils.js.map +1 -0
- package/dist/code-paths/search.d.ts +14 -0
- package/dist/code-paths/search.d.ts.map +1 -0
- package/dist/code-paths/search.js +54 -0
- package/dist/code-paths/search.js.map +1 -0
- package/dist/code-paths/trace.d.ts +11 -0
- package/dist/code-paths/trace.d.ts.map +1 -0
- package/dist/code-paths/trace.js +60 -0
- package/dist/code-paths/trace.js.map +1 -0
- package/dist/code-paths/view-coupling.d.ts +22 -0
- package/dist/code-paths/view-coupling.d.ts.map +1 -0
- package/dist/code-paths/view-coupling.js +218 -0
- package/dist/code-paths/view-coupling.js.map +1 -0
- package/dist/code-paths/view-distribution.d.ts +20 -0
- package/dist/code-paths/view-distribution.d.ts.map +1 -0
- package/dist/code-paths/view-distribution.js +82 -0
- package/dist/code-paths/view-distribution.js.map +1 -0
- package/dist/code-paths/view-graph.d.ts +35 -0
- package/dist/code-paths/view-graph.d.ts.map +1 -0
- package/dist/code-paths/view-graph.js +379 -0
- package/dist/code-paths/view-graph.js.map +1 -0
- package/dist/code-paths/view-template.d.ts +154 -0
- package/dist/code-paths/view-template.d.ts.map +1 -0
- package/dist/code-paths/view-template.js +218 -0
- package/dist/code-paths/view-template.js.map +1 -0
- package/dist/code-paths/views-registry.d.ts +13 -0
- package/dist/code-paths/views-registry.d.ts.map +1 -0
- package/dist/code-paths/views-registry.js +53 -0
- package/dist/code-paths/views-registry.js.map +1 -0
- package/dist/code-paths.d.ts +69 -0
- package/dist/code-paths.d.ts.map +1 -0
- package/dist/code-paths.js +356 -0
- package/dist/code-paths.js.map +1 -0
- package/dist/css/cards.d.ts +9 -0
- package/dist/css/cards.d.ts.map +1 -0
- package/dist/css/cards.js +36 -0
- package/dist/css/cards.js.map +1 -0
- package/dist/css/code-paths.d.ts +9 -0
- package/dist/css/code-paths.d.ts.map +1 -0
- package/dist/css/code-paths.js +111 -0
- package/dist/css/code-paths.js.map +1 -0
- package/dist/css/data-table.d.ts +12 -0
- package/dist/css/data-table.d.ts.map +1 -0
- package/dist/css/data-table.js +103 -0
- package/dist/css/data-table.js.map +1 -0
- package/dist/css/function-card.d.ts +6 -0
- package/dist/css/function-card.d.ts.map +1 -0
- package/dist/css/function-card.js +26 -0
- package/dist/css/function-card.js.map +1 -0
- package/dist/css/help-drawer.d.ts +6 -0
- package/dist/css/help-drawer.d.ts.map +1 -0
- package/dist/css/help-drawer.js +22 -0
- package/dist/css/help-drawer.js.map +1 -0
- package/dist/css/tabs.d.ts +9 -0
- package/dist/css/tabs.d.ts.map +1 -0
- package/dist/css/tabs.js +28 -0
- package/dist/css/tabs.js.map +1 -0
- package/dist/css/theme.d.ts +8 -0
- package/dist/css/theme.d.ts.map +1 -0
- package/dist/css/theme.js +34 -0
- package/dist/css/theme.js.map +1 -0
- package/dist/css.d.ts +13 -0
- package/dist/css.d.ts.map +1 -0
- package/dist/css.js +30 -0
- package/dist/css.js.map +1 -0
- package/dist/generator.d.ts +33 -0
- package/dist/generator.d.ts.map +1 -0
- package/dist/generator.js +161 -0
- package/dist/generator.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/overview.d.ts +13 -0
- package/dist/overview.d.ts.map +1 -0
- package/dist/overview.js +91 -0
- package/dist/overview.js.map +1 -0
- package/dist/recipes.d.ts +6 -0
- package/dist/recipes.d.ts.map +1 -0
- package/dist/recipes.js +68 -0
- package/dist/recipes.js.map +1 -0
- package/dist/sessions.d.ts +6 -0
- package/dist/sessions.d.ts.map +1 -0
- package/dist/sessions.js +288 -0
- package/dist/sessions.js.map +1 -0
- package/dist/shared/el.d.ts +13 -0
- package/dist/shared/el.d.ts.map +1 -0
- package/dist/shared/el.js +27 -0
- package/dist/shared/el.js.map +1 -0
- package/dist/shared/pagination.d.ts +15 -0
- package/dist/shared/pagination.d.ts.map +1 -0
- package/dist/shared/pagination.js +113 -0
- package/dist/shared/pagination.js.map +1 -0
- package/dist/shared/sortable.d.ts +14 -0
- package/dist/shared/sortable.d.ts.map +1 -0
- package/dist/shared/sortable.js +101 -0
- package/dist/shared/sortable.js.map +1 -0
- package/dist/shared/tab-activators.d.ts +16 -0
- package/dist/shared/tab-activators.d.ts.map +1 -0
- package/dist/shared/tab-activators.js +33 -0
- package/dist/shared/tab-activators.js.map +1 -0
- package/dist/shared/tab-bar.d.ts +8 -0
- package/dist/shared/tab-bar.d.ts.map +1 -0
- package/dist/shared/tab-bar.js +20 -0
- package/dist/shared/tab-bar.js.map +1 -0
- package/dist/shared.d.ts +26 -0
- package/dist/shared.d.ts.map +1 -0
- package/dist/shared.js +39 -0
- package/dist/shared.js.map +1 -0
- package/dist/subtab-bar.d.ts +23 -0
- package/dist/subtab-bar.d.ts.map +1 -0
- package/dist/subtab-bar.js +77 -0
- package/dist/subtab-bar.js.map +1 -0
- package/dist/tool-tab-registry.d.ts +76 -0
- package/dist/tool-tab-registry.d.ts.map +1 -0
- package/dist/tool-tab-registry.js +44 -0
- package/dist/tool-tab-registry.js.map +1 -0
- package/dist/tool-tabs-registrations.d.ts +19 -0
- package/dist/tool-tabs-registrations.d.ts.map +1 -0
- package/dist/tool-tabs-registrations.js +46 -0
- package/dist/tool-tabs-registrations.js.map +1 -0
- package/dist/tool-tabs.d.ts +12 -0
- package/dist/tool-tabs.d.ts.map +1 -0
- package/dist/tool-tabs.js +80 -0
- package/dist/tool-tabs.js.map +1 -0
- package/dist/vendor/cytoscape-bundle.js +600 -0
- package/package.json +52 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* View-model projection for the Code Graph "Visualization" view.
|
|
3
|
+
*
|
|
4
|
+
* Projects the raw graph `GraphCatalog` (consumed by JSON shape from
|
|
5
|
+
* `@opensip-cli/contracts` — never from `@opensip-cli/graph`) into
|
|
6
|
+
* the slim, embed-ready `GraphViewModel` the Cytoscape renderer consumes.
|
|
7
|
+
*
|
|
8
|
+
* PACKAGE-LEVEL projection (item 10): the visualization renders a
|
|
9
|
+
* node-link graph at *package* granularity, NOT function granularity.
|
|
10
|
+
* Function-level catalogs on real repos contain thousands of function
|
|
11
|
+
* nodes — unusable in a node-link layout. This projector aggregates the
|
|
12
|
+
* function call graph up to packages:
|
|
13
|
+
*
|
|
14
|
+
* - Node = one package (id = label = package name via the same
|
|
15
|
+
* attribution the Coupling view uses — see `packageOf` below, which
|
|
16
|
+
* mirrors `pkgOf` in `path-utils.ts`).
|
|
17
|
+
* - Edge = caller-package → callee-package, with `weight` = the number
|
|
18
|
+
* of underlying function→function call edges between those packages.
|
|
19
|
+
*
|
|
20
|
+
* This is intentionally the same package→package data the Coupling grid
|
|
21
|
+
* shows — a node-link rendering of it rather than a matrix. Every OTHER
|
|
22
|
+
* consumer (Coupling drilldown, Functions table, rules, …) still reads
|
|
23
|
+
* the function-level catalog directly; only THIS view aggregates up.
|
|
24
|
+
*
|
|
25
|
+
* This module is the bundle-size budget enforcement point: the report
|
|
26
|
+
* ships what this projector emits, not the catalog's storage shape.
|
|
27
|
+
*
|
|
28
|
+
* Architecture decisions:
|
|
29
|
+
* - Projection runs at report-generation time (server-side, in
|
|
30
|
+
* `generator.ts`) and the result is embedded as a JSON blob, mirroring
|
|
31
|
+
* the existing `graph-catalog` blob.
|
|
32
|
+
* - Cross-package cycles are detected with Tarjan's SCC over the package
|
|
33
|
+
* graph (cheap at package granularity — tens of nodes, not thousands).
|
|
34
|
+
* The engine's SCC implementation is off-limits to this package (the
|
|
35
|
+
* catalog-decoupling rule §2.4); the local replica lives in the sibling
|
|
36
|
+
* `graph-scc.ts` module.
|
|
37
|
+
*/
|
|
38
|
+
import type { GraphCatalog, GraphFunctionOccurrence } from '@opensip-cli/contracts';
|
|
39
|
+
/**
|
|
40
|
+
* Slim, embed-ready projection of a graph catalog for the dashboard's
|
|
41
|
+
* Visualization view. Produced by {@link projectCatalogToGraphViewModel}
|
|
42
|
+
* and consumed by `view-graph.ts`.
|
|
43
|
+
*
|
|
44
|
+
* Aggregated to PACKAGE granularity — one node per package, one edge per
|
|
45
|
+
* directed package→package coupling.
|
|
46
|
+
*/
|
|
47
|
+
export interface GraphViewModel {
|
|
48
|
+
/**
|
|
49
|
+
* Catalog-level language (e.g. `'typescript'`). Copied here so the view
|
|
50
|
+
* doesn't need a separate handle on `graphCatalog`. The catalog is
|
|
51
|
+
* single-language; this is NOT a per-node filter.
|
|
52
|
+
*/
|
|
53
|
+
readonly language: string;
|
|
54
|
+
readonly nodes: readonly GraphViewModelNode[];
|
|
55
|
+
readonly edges: readonly GraphViewModelEdge[];
|
|
56
|
+
}
|
|
57
|
+
export interface GraphViewModelNode {
|
|
58
|
+
/** Stable handle AND display label — the package name. */
|
|
59
|
+
readonly id: string;
|
|
60
|
+
/** Display label — the package name (same as {@link id}). */
|
|
61
|
+
readonly label: string;
|
|
62
|
+
/**
|
|
63
|
+
* Total coupling degree = fan-in + fan-out call count (sum of incident
|
|
64
|
+
* edge weights). Drives node *size* — hub packages render larger.
|
|
65
|
+
* Pre-computed here so the renderer can size without re-iterating edges.
|
|
66
|
+
*/
|
|
67
|
+
readonly totalCoupling: number;
|
|
68
|
+
/**
|
|
69
|
+
* SCC membership over the PACKAGE graph. `null` = not in a non-trivial
|
|
70
|
+
* package-level cycle. Non-null = string id shared by every package in
|
|
71
|
+
* the same cyclic cluster. Drives cross-package-cycle highlighting.
|
|
72
|
+
*/
|
|
73
|
+
readonly sccId: string | null;
|
|
74
|
+
}
|
|
75
|
+
export interface GraphViewModelEdge {
|
|
76
|
+
/** Source package name (caller). */
|
|
77
|
+
readonly source: string;
|
|
78
|
+
/** Target package name (callee). */
|
|
79
|
+
readonly target: string;
|
|
80
|
+
/**
|
|
81
|
+
* Number of underlying function→function call edges from the source
|
|
82
|
+
* package into the target package. Drives edge *thickness*.
|
|
83
|
+
*/
|
|
84
|
+
readonly weight: number;
|
|
85
|
+
/**
|
|
86
|
+
* `true` iff this edge participates in a package-level cycle (both
|
|
87
|
+
* endpoints in the same non-null `sccId`). Highlights cross-package
|
|
88
|
+
* cycle backbones in concert with the node `sccId` grouping.
|
|
89
|
+
*/
|
|
90
|
+
readonly isCycleEdge: boolean;
|
|
91
|
+
}
|
|
92
|
+
/** Thrown when the catalog is structurally unusable for projection. */
|
|
93
|
+
export declare class GraphViewModelError extends Error {
|
|
94
|
+
constructor(message: string);
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Project a graph catalog into the slim, PACKAGE-LEVEL {@link GraphViewModel}.
|
|
98
|
+
*
|
|
99
|
+
* Pure function — no I/O, no side effects. Four passes:
|
|
100
|
+
* - Pass A: map every function `bodyHash` to its package (so call targets,
|
|
101
|
+
* which are bodyHashes, can be resolved to a package).
|
|
102
|
+
* - Pass B: walk function call edges, aggregate to package→package edges
|
|
103
|
+
* keyed by `caller→callee`, accumulating a call-count `weight`.
|
|
104
|
+
* - Pass C: derive package nodes (one per package seen) and accumulate
|
|
105
|
+
* `totalCoupling` (fan-in + fan-out weight) on each.
|
|
106
|
+
* - Pass D: Tarjan SCC over the package graph — stamp `sccId` on cyclic
|
|
107
|
+
* packages and `isCycleEdge` on edges whose endpoints share an `sccId`.
|
|
108
|
+
*
|
|
109
|
+
* @throws {GraphViewModelError} when `catalog` or `catalog.functions` is missing.
|
|
110
|
+
*/
|
|
111
|
+
export declare function projectCatalogToGraphViewModel(catalog: GraphCatalog): GraphViewModel;
|
|
112
|
+
/**
|
|
113
|
+
* The package a function occurrence belongs to. Mirrors `pkgOf` in
|
|
114
|
+
* `path-utils.ts` (the browser-side helper the Coupling view uses) so the
|
|
115
|
+
* server-side projection and the client-side coupling matrix attribute
|
|
116
|
+
* functions to packages identically: prefer the build-time-stamped
|
|
117
|
+
* `occurrence.package` (scope-stripped), else the path heuristic.
|
|
118
|
+
*/
|
|
119
|
+
export declare function packageOf(occ: GraphFunctionOccurrence): string;
|
|
120
|
+
//# sourceMappingURL=graph-view-model.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph-view-model.d.ts","sourceRoot":"","sources":["../../src/code-paths/graph-view-model.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAEpF;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B,QAAQ,CAAC,KAAK,EAAE,SAAS,kBAAkB,EAAE,CAAC;IAC9C,QAAQ,CAAC,KAAK,EAAE,SAAS,kBAAkB,EAAE,CAAC;CAC/C;AAED,MAAM,WAAW,kBAAkB;IACjC,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAEpB,6DAA6D;IAC7D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAEvB;;;;OAIG;IACH,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAE/B;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,MAAM,WAAW,kBAAkB;IACjC,oCAAoC;IACpC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB,oCAAoC;IACpC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB;;;;OAIG;IACH,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;CAC/B;AAED,uEAAuE;AACvE,qBAAa,mBAAoB,SAAQ,KAAK;gBAChC,OAAO,EAAE,MAAM;CAI5B;AAcD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,8BAA8B,CAAC,OAAO,EAAE,YAAY,GAAG,cAAc,CA4BpF;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,uBAAuB,GAAG,MAAM,CAK9D"}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* View-model projection for the Code Graph "Visualization" view.
|
|
3
|
+
*
|
|
4
|
+
* Projects the raw graph `GraphCatalog` (consumed by JSON shape from
|
|
5
|
+
* `@opensip-cli/contracts` — never from `@opensip-cli/graph`) into
|
|
6
|
+
* the slim, embed-ready `GraphViewModel` the Cytoscape renderer consumes.
|
|
7
|
+
*
|
|
8
|
+
* PACKAGE-LEVEL projection (item 10): the visualization renders a
|
|
9
|
+
* node-link graph at *package* granularity, NOT function granularity.
|
|
10
|
+
* Function-level catalogs on real repos contain thousands of function
|
|
11
|
+
* nodes — unusable in a node-link layout. This projector aggregates the
|
|
12
|
+
* function call graph up to packages:
|
|
13
|
+
*
|
|
14
|
+
* - Node = one package (id = label = package name via the same
|
|
15
|
+
* attribution the Coupling view uses — see `packageOf` below, which
|
|
16
|
+
* mirrors `pkgOf` in `path-utils.ts`).
|
|
17
|
+
* - Edge = caller-package → callee-package, with `weight` = the number
|
|
18
|
+
* of underlying function→function call edges between those packages.
|
|
19
|
+
*
|
|
20
|
+
* This is intentionally the same package→package data the Coupling grid
|
|
21
|
+
* shows — a node-link rendering of it rather than a matrix. Every OTHER
|
|
22
|
+
* consumer (Coupling drilldown, Functions table, rules, …) still reads
|
|
23
|
+
* the function-level catalog directly; only THIS view aggregates up.
|
|
24
|
+
*
|
|
25
|
+
* This module is the bundle-size budget enforcement point: the report
|
|
26
|
+
* ships what this projector emits, not the catalog's storage shape.
|
|
27
|
+
*
|
|
28
|
+
* Architecture decisions:
|
|
29
|
+
* - Projection runs at report-generation time (server-side, in
|
|
30
|
+
* `generator.ts`) and the result is embedded as a JSON blob, mirroring
|
|
31
|
+
* the existing `graph-catalog` blob.
|
|
32
|
+
* - Cross-package cycles are detected with Tarjan's SCC over the package
|
|
33
|
+
* graph (cheap at package granularity — tens of nodes, not thousands).
|
|
34
|
+
* The engine's SCC implementation is off-limits to this package (the
|
|
35
|
+
* catalog-decoupling rule §2.4); the local replica lives in the sibling
|
|
36
|
+
* `graph-scc.ts` module.
|
|
37
|
+
*/
|
|
38
|
+
import { buildAdjacency, tarjanSccIds } from './graph-scc.js';
|
|
39
|
+
/** Thrown when the catalog is structurally unusable for projection. */
|
|
40
|
+
export class GraphViewModelError extends Error {
|
|
41
|
+
constructor(message) {
|
|
42
|
+
super(message);
|
|
43
|
+
this.name = 'GraphViewModelError';
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Project a graph catalog into the slim, PACKAGE-LEVEL {@link GraphViewModel}.
|
|
48
|
+
*
|
|
49
|
+
* Pure function — no I/O, no side effects. Four passes:
|
|
50
|
+
* - Pass A: map every function `bodyHash` to its package (so call targets,
|
|
51
|
+
* which are bodyHashes, can be resolved to a package).
|
|
52
|
+
* - Pass B: walk function call edges, aggregate to package→package edges
|
|
53
|
+
* keyed by `caller→callee`, accumulating a call-count `weight`.
|
|
54
|
+
* - Pass C: derive package nodes (one per package seen) and accumulate
|
|
55
|
+
* `totalCoupling` (fan-in + fan-out weight) on each.
|
|
56
|
+
* - Pass D: Tarjan SCC over the package graph — stamp `sccId` on cyclic
|
|
57
|
+
* packages and `isCycleEdge` on edges whose endpoints share an `sccId`.
|
|
58
|
+
*
|
|
59
|
+
* @throws {GraphViewModelError} when `catalog` or `catalog.functions` is missing.
|
|
60
|
+
*/
|
|
61
|
+
export function projectCatalogToGraphViewModel(catalog) {
|
|
62
|
+
if (!catalog || typeof catalog !== 'object' || !catalog.functions) {
|
|
63
|
+
throw new GraphViewModelError('catalog is missing or has no functions map');
|
|
64
|
+
}
|
|
65
|
+
const packageByHash = mapHashesToPackages(catalog); // Pass A
|
|
66
|
+
const edgeByKey = aggregatePackageEdges(catalog, packageByHash); // Pass B
|
|
67
|
+
const { nodes, edges } = deriveNodesAndEdges(packageByHash, edgeByKey); // Pass C
|
|
68
|
+
// Pass D: Tarjan SCC over the package graph. Self-loops (intra-package
|
|
69
|
+
// calls — the matrix diagonal) are excluded so a single package with
|
|
70
|
+
// internal calls is NOT flagged as a cycle; only genuine multi-package
|
|
71
|
+
// cycles (A→B→A) earn an sccId.
|
|
72
|
+
const adjacency = buildAdjacency(nodes, edges.filter((e) => e.source !== e.target));
|
|
73
|
+
const sccByNode = tarjanSccIds(nodes.map((n) => n.id), adjacency);
|
|
74
|
+
for (const node of nodes)
|
|
75
|
+
node.sccId = sccByNode.get(node.id) ?? null;
|
|
76
|
+
return {
|
|
77
|
+
language: catalog.language,
|
|
78
|
+
nodes: nodes.map(toViewModelNode),
|
|
79
|
+
edges: edges.map((e) => toViewModelEdge(e, sccByNode)),
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* The package a function occurrence belongs to. Mirrors `pkgOf` in
|
|
84
|
+
* `path-utils.ts` (the browser-side helper the Coupling view uses) so the
|
|
85
|
+
* server-side projection and the client-side coupling matrix attribute
|
|
86
|
+
* functions to packages identically: prefer the build-time-stamped
|
|
87
|
+
* `occurrence.package` (scope-stripped), else the path heuristic.
|
|
88
|
+
*/
|
|
89
|
+
export function packageOf(occ) {
|
|
90
|
+
if (occ && typeof occ.package === 'string' && occ.package.length > 0) {
|
|
91
|
+
return shortPackage(occ.package);
|
|
92
|
+
}
|
|
93
|
+
return packageOfPath(occ ? occ.filePath : '');
|
|
94
|
+
}
|
|
95
|
+
/** Strip an npm scope for display: "@opensip-cli/lang-typescript" → "lang-typescript". */
|
|
96
|
+
function shortPackage(name) {
|
|
97
|
+
if (typeof name !== 'string')
|
|
98
|
+
return '<unknown>';
|
|
99
|
+
return name.codePointAt(0) === 64 /* @ */ ? name.slice(name.indexOf('/') + 1) : name;
|
|
100
|
+
}
|
|
101
|
+
/** Path-only fallback (first segment under `packages/`). */
|
|
102
|
+
function packageOfPath(filePath) {
|
|
103
|
+
if (typeof filePath !== 'string' || filePath.length === 0)
|
|
104
|
+
return '<unknown>';
|
|
105
|
+
const m = /^packages\/([^/]+)\//.exec(filePath);
|
|
106
|
+
return m ? m[1] : '<unknown>';
|
|
107
|
+
}
|
|
108
|
+
/** Pass A — bodyHash → package name (last write wins, mirroring buildIndexes). */
|
|
109
|
+
function mapHashesToPackages(catalog) {
|
|
110
|
+
const packageByHash = new Map();
|
|
111
|
+
for (const name of Object.keys(catalog.functions)) {
|
|
112
|
+
const occs = catalog.functions[name] ?? [];
|
|
113
|
+
for (const occ of occs)
|
|
114
|
+
packageByHash.set(occ.bodyHash, packageOf(occ));
|
|
115
|
+
}
|
|
116
|
+
return packageByHash;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Pass B — aggregate function call edges to directed package→package edges
|
|
120
|
+
* keyed by `callercallee`, accumulating a call-count `weight`. Call
|
|
121
|
+
* targets whose bodyHash is not an in-project function are dropped (matching
|
|
122
|
+
* the function-level projector's handling of unresolved/external calls).
|
|
123
|
+
* Self-package edges (intra-package calls) are kept — they show up as
|
|
124
|
+
* self-loops, consistent with the Coupling matrix diagonal.
|
|
125
|
+
*/
|
|
126
|
+
function aggregatePackageEdges(catalog, packageByHash) {
|
|
127
|
+
const edgeByKey = new Map();
|
|
128
|
+
for (const name of Object.keys(catalog.functions)) {
|
|
129
|
+
for (const occ of catalog.functions[name] ?? []) {
|
|
130
|
+
accumulateOccurrenceEdges(occ, packageByHash, edgeByKey);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return edgeByKey;
|
|
134
|
+
}
|
|
135
|
+
/** Add one weighted package edge per resolved call target of `occ`. */
|
|
136
|
+
function accumulateOccurrenceEdges(occ, packageByHash, edgeByKey) {
|
|
137
|
+
const callerPkg = packageByHash.get(occ.bodyHash);
|
|
138
|
+
if (callerPkg === undefined)
|
|
139
|
+
return;
|
|
140
|
+
for (const edge of occ.calls ?? []) {
|
|
141
|
+
for (const target of edge.to ?? []) {
|
|
142
|
+
const calleePkg = packageByHash.get(target);
|
|
143
|
+
if (calleePkg === undefined)
|
|
144
|
+
continue; // external / unresolved
|
|
145
|
+
bumpEdge(edgeByKey, callerPkg, calleePkg);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
/** Increment (or create) the weighted edge for a caller-to-callee package pair. */
|
|
150
|
+
function bumpEdge(edgeByKey, source, target) {
|
|
151
|
+
// Newline delimiter: package names never contain one, so caller+callee keys
|
|
152
|
+
// can't collide (unlike empty-string concat).
|
|
153
|
+
const key = source + '\n' + target;
|
|
154
|
+
const existing = edgeByKey.get(key);
|
|
155
|
+
if (existing)
|
|
156
|
+
existing.weight += 1;
|
|
157
|
+
else
|
|
158
|
+
edgeByKey.set(key, { source, target, weight: 1 });
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Pass C — derive one node per package (every package that appears as a
|
|
162
|
+
* function's package OR as an edge endpoint) and accumulate `totalCoupling`
|
|
163
|
+
* (sum of incident edge weights) on each.
|
|
164
|
+
*/
|
|
165
|
+
function deriveNodesAndEdges(packageByHash, edgeByKey) {
|
|
166
|
+
const nodeById = new Map();
|
|
167
|
+
// @fitness-ignore-next-line toctou-race-condition -- synchronous single-pass projector; `nodeById` is a local Map with no async/concurrent access, so there is no time-of-check/time-of-use window between the get and the set.
|
|
168
|
+
const ensure = (id) => {
|
|
169
|
+
let n = nodeById.get(id);
|
|
170
|
+
if (!n) {
|
|
171
|
+
n = { id, totalCoupling: 0, sccId: null };
|
|
172
|
+
nodeById.set(id, n);
|
|
173
|
+
}
|
|
174
|
+
return n;
|
|
175
|
+
};
|
|
176
|
+
// Every package that hosts a function is a node, even if it has no edges.
|
|
177
|
+
for (const pkg of packageByHash.values())
|
|
178
|
+
ensure(pkg);
|
|
179
|
+
const edges = [...edgeByKey.values()];
|
|
180
|
+
for (const e of edges) {
|
|
181
|
+
ensure(e.source).totalCoupling += e.weight;
|
|
182
|
+
ensure(e.target).totalCoupling += e.weight;
|
|
183
|
+
}
|
|
184
|
+
return { nodes: [...nodeById.values()], edges };
|
|
185
|
+
}
|
|
186
|
+
function toViewModelNode(n) {
|
|
187
|
+
return { id: n.id, label: n.id, totalCoupling: n.totalCoupling, sccId: n.sccId };
|
|
188
|
+
}
|
|
189
|
+
function toViewModelEdge(e, sccByNode) {
|
|
190
|
+
const sourceScc = sccByNode.get(e.source);
|
|
191
|
+
const targetScc = sccByNode.get(e.target);
|
|
192
|
+
return {
|
|
193
|
+
source: e.source,
|
|
194
|
+
target: e.target,
|
|
195
|
+
weight: e.weight,
|
|
196
|
+
isCycleEdge: sourceScc != null && sourceScc === targetScc,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
//# sourceMappingURL=graph-view-model.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph-view-model.js","sourceRoot":"","sources":["../../src/code-paths/graph-view-model.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Right-side help drawer — explains a single Explore view.
|
|
3
|
+
*
|
|
4
|
+
* Each view-*.ts puts a `help` field on its View literal:
|
|
5
|
+
* { title: string, sections: { heading: string, body: string }[] }
|
|
6
|
+
* Clicking the ⓘ icon next to a tab opens this drawer with that
|
|
7
|
+
* view's help. Clicking the backdrop, the × button, or pressing
|
|
8
|
+
* Escape closes it. There is one drawer at a time.
|
|
9
|
+
*
|
|
10
|
+
* The drawer resolves help dynamically via `getView(viewId).help` — there is
|
|
11
|
+
* NO static per-view help map. So the Plan B Code Paths restructure
|
|
12
|
+
* (dropping `big`/`hot`/`wide`/`untested`/`sccs` and folding cycle guidance
|
|
13
|
+
* into the graph view's help) needs no edit here: the drawer simply renders
|
|
14
|
+
* whatever views are registered. The SCC explanation now lives on the graph
|
|
15
|
+
* view's `help` ("Cycles / SCCs" section, view-graph.ts).
|
|
16
|
+
*/
|
|
17
|
+
export declare function dashboardHelpDrawerJs(): string;
|
|
18
|
+
//# sourceMappingURL=help-drawer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"help-drawer.d.ts","sourceRoot":"","sources":["../../src/code-paths/help-drawer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,wBAAgB,qBAAqB,IAAI,MAAM,CAoC9C"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Right-side help drawer — explains a single Explore view.
|
|
3
|
+
*
|
|
4
|
+
* Each view-*.ts puts a `help` field on its View literal:
|
|
5
|
+
* { title: string, sections: { heading: string, body: string }[] }
|
|
6
|
+
* Clicking the ⓘ icon next to a tab opens this drawer with that
|
|
7
|
+
* view's help. Clicking the backdrop, the × button, or pressing
|
|
8
|
+
* Escape closes it. There is one drawer at a time.
|
|
9
|
+
*
|
|
10
|
+
* The drawer resolves help dynamically via `getView(viewId).help` — there is
|
|
11
|
+
* NO static per-view help map. So the Plan B Code Paths restructure
|
|
12
|
+
* (dropping `big`/`hot`/`wide`/`untested`/`sccs` and folding cycle guidance
|
|
13
|
+
* into the graph view's help) needs no edit here: the drawer simply renders
|
|
14
|
+
* whatever views are registered. The SCC explanation now lives on the graph
|
|
15
|
+
* view's `help` ("Cycles / SCCs" section, view-graph.ts).
|
|
16
|
+
*/
|
|
17
|
+
export function dashboardHelpDrawerJs() {
|
|
18
|
+
return String.raw `
|
|
19
|
+
function openHelpDrawer(viewId) {
|
|
20
|
+
const view = (typeof getView === 'function') ? getView(viewId) : null;
|
|
21
|
+
if (!view || !view.help) return;
|
|
22
|
+
closeHelpDrawer();
|
|
23
|
+
const overlay = el('div', { class: 'help-drawer-overlay', id: 'help-drawer-overlay' });
|
|
24
|
+
overlay.addEventListener('click', e => { if (e.target === overlay) closeHelpDrawer(); });
|
|
25
|
+
const drawer = el('aside', { class: 'help-drawer', role: 'dialog', 'aria-label': view.help.title || view.label });
|
|
26
|
+
const header = el('div', { class: 'help-drawer-header' });
|
|
27
|
+
header.appendChild(el('h3', { text: view.help.title || view.label }));
|
|
28
|
+
const closeBtn = el('button', { class: 'help-drawer-close', 'aria-label': 'Close', text: '×', onclick: closeHelpDrawer });
|
|
29
|
+
header.appendChild(closeBtn);
|
|
30
|
+
drawer.appendChild(header);
|
|
31
|
+
const body = el('div', { class: 'help-drawer-body' });
|
|
32
|
+
for (const section of (view.help.sections || [])) {
|
|
33
|
+
body.appendChild(el('h4', { text: section.heading }));
|
|
34
|
+
body.appendChild(el('p', { text: section.body }));
|
|
35
|
+
}
|
|
36
|
+
drawer.appendChild(body);
|
|
37
|
+
overlay.appendChild(drawer);
|
|
38
|
+
document.body.appendChild(overlay);
|
|
39
|
+
// Animate in on next frame so the CSS transition takes effect.
|
|
40
|
+
requestAnimationFrame(() => overlay.classList.add('open'));
|
|
41
|
+
closeBtn.focus();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function closeHelpDrawer() {
|
|
45
|
+
const existing = document.getElementById('help-drawer-overlay');
|
|
46
|
+
if (existing && existing.parentNode) existing.parentNode.removeChild(existing);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
document.addEventListener('keydown', e => {
|
|
50
|
+
if (e.key === 'Escape' && document.getElementById('help-drawer-overlay')) closeHelpDrawer();
|
|
51
|
+
});
|
|
52
|
+
`;
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=help-drawer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"help-drawer.js","sourceRoot":"","sources":["../../src/code-paths/help-drawer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,UAAU,qBAAqB;IACnC,OAAO,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkClB,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser-side `Indexes` builder — emitted as a JS string for the
|
|
3
|
+
* inlined dashboard script. Mirrors v0.2's `pipeline/indexes.ts`
|
|
4
|
+
* but ported to vanilla JS that runs in the page.
|
|
5
|
+
*
|
|
6
|
+
* The catalog persists only `functions[name][i].calls[].to[]`. v0.2's
|
|
7
|
+
* O(1) `Indexes` is in-memory only; the dashboard rebuilds it on
|
|
8
|
+
* panel-init time. Output: { byBodyHash, occurrencesByHash,
|
|
9
|
+
* bySimpleName, callees, callers }.
|
|
10
|
+
*
|
|
11
|
+
* Blast radius is no longer computed here. The engine's features stage
|
|
12
|
+
* (`pipeline/features.ts`, Plan C) is the single canonical home for the
|
|
13
|
+
* bounded reverse-BFS blast score; a dashboard-bound run materializes it
|
|
14
|
+
* into `catalog.features.function[bodyHash].blast` and the Hot view reads
|
|
15
|
+
* it from there (falling back to the raw inbound-caller count when the
|
|
16
|
+
* catalog carries no features). This builder now only assembles the
|
|
17
|
+
* adjacency the views need for navigation and member resolution.
|
|
18
|
+
*
|
|
19
|
+
* Also emits `resolveCalleeOcc(target, callerOcc, indexes)` — the shared
|
|
20
|
+
* call-target → callee-occurrence resolver. It lives here (not in any single
|
|
21
|
+
* view) because more than one view needs it: the Coupling drilldown AND the
|
|
22
|
+
* function-level Visualization both resolve a call target's bodyHash to the
|
|
23
|
+
* occurrence the caller can actually reach, disambiguating body-hash
|
|
24
|
+
* collisions across packages. Emitting it in the prelude (ahead of every
|
|
25
|
+
* view) removes the load-bearing cross-view emission order it used to imply.
|
|
26
|
+
*/
|
|
27
|
+
export declare function dashboardIndexesJs(): string;
|
|
28
|
+
//# sourceMappingURL=indexes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"indexes.d.ts","sourceRoot":"","sources":["../../src/code-paths/indexes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,wBAAgB,kBAAkB,IAAI,MAAM,CAqE3C"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser-side `Indexes` builder — emitted as a JS string for the
|
|
3
|
+
* inlined dashboard script. Mirrors v0.2's `pipeline/indexes.ts`
|
|
4
|
+
* but ported to vanilla JS that runs in the page.
|
|
5
|
+
*
|
|
6
|
+
* The catalog persists only `functions[name][i].calls[].to[]`. v0.2's
|
|
7
|
+
* O(1) `Indexes` is in-memory only; the dashboard rebuilds it on
|
|
8
|
+
* panel-init time. Output: { byBodyHash, occurrencesByHash,
|
|
9
|
+
* bySimpleName, callees, callers }.
|
|
10
|
+
*
|
|
11
|
+
* Blast radius is no longer computed here. The engine's features stage
|
|
12
|
+
* (`pipeline/features.ts`, Plan C) is the single canonical home for the
|
|
13
|
+
* bounded reverse-BFS blast score; a dashboard-bound run materializes it
|
|
14
|
+
* into `catalog.features.function[bodyHash].blast` and the Hot view reads
|
|
15
|
+
* it from there (falling back to the raw inbound-caller count when the
|
|
16
|
+
* catalog carries no features). This builder now only assembles the
|
|
17
|
+
* adjacency the views need for navigation and member resolution.
|
|
18
|
+
*
|
|
19
|
+
* Also emits `resolveCalleeOcc(target, callerOcc, indexes)` — the shared
|
|
20
|
+
* call-target → callee-occurrence resolver. It lives here (not in any single
|
|
21
|
+
* view) because more than one view needs it: the Coupling drilldown AND the
|
|
22
|
+
* function-level Visualization both resolve a call target's bodyHash to the
|
|
23
|
+
* occurrence the caller can actually reach, disambiguating body-hash
|
|
24
|
+
* collisions across packages. Emitting it in the prelude (ahead of every
|
|
25
|
+
* view) removes the load-bearing cross-view emission order it used to imply.
|
|
26
|
+
*/
|
|
27
|
+
export function dashboardIndexesJs() {
|
|
28
|
+
return String.raw `
|
|
29
|
+
function buildIndexes(catalog) {
|
|
30
|
+
const byBodyHash = new Map();
|
|
31
|
+
// All occurrences per body. byBodyHash keeps only one (last-writer-wins),
|
|
32
|
+
// collapsing identical bodies across packages; occurrencesByHash preserves
|
|
33
|
+
// every occurrence so coupling can attribute a callee to the correct
|
|
34
|
+
// package instead of the collision winner.
|
|
35
|
+
const occurrencesByHash = new Map();
|
|
36
|
+
const bySimpleName = new Map();
|
|
37
|
+
const callees = new Map();
|
|
38
|
+
const callers = new Map();
|
|
39
|
+
if (!catalog || !catalog.functions) {
|
|
40
|
+
return { byBodyHash, occurrencesByHash, bySimpleName, callees, callers };
|
|
41
|
+
}
|
|
42
|
+
// Pass 1: byBodyHash + occurrencesByHash + bySimpleName.
|
|
43
|
+
for (const name of Object.keys(catalog.functions)) {
|
|
44
|
+
const occs = catalog.functions[name] || [];
|
|
45
|
+
for (const occ of occs) {
|
|
46
|
+
byBodyHash.set(occ.bodyHash, occ);
|
|
47
|
+
let all = occurrencesByHash.get(occ.bodyHash);
|
|
48
|
+
if (!all) { all = []; occurrencesByHash.set(occ.bodyHash, all); }
|
|
49
|
+
all.push(occ);
|
|
50
|
+
let bucket = bySimpleName.get(name);
|
|
51
|
+
if (!bucket) { bucket = []; bySimpleName.set(name, bucket); }
|
|
52
|
+
bucket.push(occ.bodyHash);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// Pass 2: callees (forward) + callers (reverse). Edges that resolve
|
|
56
|
+
// to a hash not in byBodyHash are dropped; this mirrors v0.2's
|
|
57
|
+
// behavior for unresolved/external targets.
|
|
58
|
+
for (const occ of byBodyHash.values()) {
|
|
59
|
+
const out = [];
|
|
60
|
+
for (const edge of (occ.calls || [])) {
|
|
61
|
+
for (const target of (edge.to || [])) {
|
|
62
|
+
if (!byBodyHash.has(target)) continue;
|
|
63
|
+
out.push(target);
|
|
64
|
+
let inb = callers.get(target);
|
|
65
|
+
if (!inb) { inb = []; callers.set(target, inb); }
|
|
66
|
+
inb.push(occ.bodyHash);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (out.length > 0) callees.set(occ.bodyHash, out);
|
|
70
|
+
}
|
|
71
|
+
return { byBodyHash, occurrencesByHash, bySimpleName, callees, callers };
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Resolve a call target (a bodyHash) to the callee occurrence the caller can
|
|
75
|
+
// reach, disambiguating body-hash collisions across packages. byBodyHash
|
|
76
|
+
// keeps only one occurrence per hash (the collision winner), which
|
|
77
|
+
// mis-attributes the callee's package; occurrencesByHash preserves all, so we
|
|
78
|
+
// prefer the caller's own package, else fall back deterministically (lowest
|
|
79
|
+
// qualifiedName). The dashboard catalog carries no import set, so this mirrors
|
|
80
|
+
// the engine's fast-mode (same-package-only) attribution. Used by the Coupling
|
|
81
|
+
// drilldown and the function-level Visualization projection.
|
|
82
|
+
function resolveCalleeOcc(target, callerOcc, indexes) {
|
|
83
|
+
const candidates = (indexes.occurrencesByHash && indexes.occurrencesByHash.get(target)) || null;
|
|
84
|
+
if (!candidates || candidates.length === 0) return indexes.byBodyHash.get(target);
|
|
85
|
+
if (candidates.length === 1) return candidates[0];
|
|
86
|
+
const callerPkg = pkgOf(callerOcc);
|
|
87
|
+
let samePkg = null;
|
|
88
|
+
let lowest = candidates[0];
|
|
89
|
+
for (const c of candidates) {
|
|
90
|
+
if (!samePkg && pkgOf(c) === callerPkg) samePkg = c;
|
|
91
|
+
if (c.qualifiedName < lowest.qualifiedName) lowest = c;
|
|
92
|
+
}
|
|
93
|
+
return samePkg || lowest;
|
|
94
|
+
}
|
|
95
|
+
`;
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=indexes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"indexes.js","sourceRoot":"","sources":["../../src/code-paths/indexes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,MAAM,UAAU,kBAAkB;IAChC,OAAO,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmElB,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Path / name display helpers shared across the Explore views.
|
|
3
|
+
*
|
|
4
|
+
* - pkgOf: the package an occurrence belongs to — prefers the
|
|
5
|
+
* build-time-stamped `occurrence.package` (nearest package.json name, shown
|
|
6
|
+
* scope-stripped), falling back to the path heuristic for old catalogs.
|
|
7
|
+
* - packageOfPath: path-only fallback (first segment under packages/).
|
|
8
|
+
* - displayName: collapse synthetic graph names like
|
|
9
|
+
* "<arrow:packages/.../foo.ts:234:45>" into a short tag the table
|
|
10
|
+
* can render without horizontal overflow. The underlying simpleName
|
|
11
|
+
* is preserved as the identity (data-body-hash); only the cell text
|
|
12
|
+
* is shortened.
|
|
13
|
+
*/
|
|
14
|
+
export declare function dashboardPathUtilsJs(): string;
|
|
15
|
+
//# sourceMappingURL=path-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path-utils.d.ts","sourceRoot":"","sources":["../../src/code-paths/path-utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,wBAAgB,oBAAoB,IAAI,MAAM,CAgC7C"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Path / name display helpers shared across the Explore views.
|
|
3
|
+
*
|
|
4
|
+
* - pkgOf: the package an occurrence belongs to — prefers the
|
|
5
|
+
* build-time-stamped `occurrence.package` (nearest package.json name, shown
|
|
6
|
+
* scope-stripped), falling back to the path heuristic for old catalogs.
|
|
7
|
+
* - packageOfPath: path-only fallback (first segment under packages/).
|
|
8
|
+
* - displayName: collapse synthetic graph names like
|
|
9
|
+
* "<arrow:packages/.../foo.ts:234:45>" into a short tag the table
|
|
10
|
+
* can render without horizontal overflow. The underlying simpleName
|
|
11
|
+
* is preserved as the identity (data-body-hash); only the cell text
|
|
12
|
+
* is shortened.
|
|
13
|
+
*/
|
|
14
|
+
export function dashboardPathUtilsJs() {
|
|
15
|
+
return String.raw `
|
|
16
|
+
function packageOfPath(filePath) {
|
|
17
|
+
if (typeof filePath !== 'string' || filePath.length === 0) return '<unknown>';
|
|
18
|
+
const m = /^packages\/([^/]+)\//.exec(filePath);
|
|
19
|
+
return m ? m[1] : '<unknown>';
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Strip an npm scope for display: "@opensip-cli/lang-typescript" -> "lang-typescript".
|
|
23
|
+
function shortPkg(name) {
|
|
24
|
+
if (typeof name !== 'string') return '<unknown>';
|
|
25
|
+
return name.charCodeAt(0) === 64 /* @ */ ? name.slice(name.indexOf('/') + 1) : name;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// The package an occurrence belongs to. Prefers the build-time-stamped
|
|
29
|
+
// occurrence.package (accurate for any repo layout); falls back to the path
|
|
30
|
+
// heuristic for legacy catalogs. Scope-stripped for compact display.
|
|
31
|
+
function pkgOf(occ) {
|
|
32
|
+
if (occ && typeof occ.package === 'string' && occ.package.length > 0) return shortPkg(occ.package);
|
|
33
|
+
return packageOfPath(occ ? occ.filePath : '');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function displayName(simpleName) {
|
|
37
|
+
if (typeof simpleName !== 'string') return '';
|
|
38
|
+
// Synthetic names from the graph tool are angle-bracketed:
|
|
39
|
+
// <arrow:path:line:col>, <fn-expr:path:line:col>, <module-init:path>, <default>
|
|
40
|
+
// Render just the kind tag — file:line is shown in the File column.
|
|
41
|
+
const m = /^<([a-z-]+)(?::|>)/.exec(simpleName);
|
|
42
|
+
if (m) return '<' + m[1] + '>';
|
|
43
|
+
return simpleName;
|
|
44
|
+
}
|
|
45
|
+
`;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=path-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path-utils.js","sourceRoot":"","sources":["../../src/code-paths/path-utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,MAAM,UAAU,oBAAoB;IAClC,OAAO,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8BlB,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Substring-with-character-skip fuzzy match for the persistent search
|
|
3
|
+
* input and View 7. Pure algorithm emitted as a JS string.
|
|
4
|
+
*
|
|
5
|
+
* Algorithm: each character of the query must appear in the candidate
|
|
6
|
+
* in order, but not necessarily contiguously. Score is built from:
|
|
7
|
+
* - prefix match (start at index 0): +50
|
|
8
|
+
* - exact-case bonus per matched char: +1
|
|
9
|
+
* - contiguous-run bonus (matched-after-matched): +2 per
|
|
10
|
+
* - shorter candidate preferred: -length * 0.01
|
|
11
|
+
* Returns top matches sorted by score desc, score >= 0.
|
|
12
|
+
*/
|
|
13
|
+
export declare function dashboardSearchJs(): string;
|
|
14
|
+
//# sourceMappingURL=search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/code-paths/search.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,wBAAgB,iBAAiB,IAAI,MAAM,CAwC1C"}
|