@opensip-cli/dashboard 0.1.7 → 0.1.9
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/README.md +2 -2
- package/dist/__tests__/catalog-provenance.test.js +6 -24
- package/dist/__tests__/catalog-provenance.test.js.map +1 -1
- package/dist/__tests__/coupling-attribution.test.js +10 -14
- package/dist/__tests__/coupling-attribution.test.js.map +1 -1
- package/dist/__tests__/dashboard-bundle-weight.test.d.ts +9 -2
- package/dist/__tests__/dashboard-bundle-weight.test.d.ts.map +1 -1
- package/dist/__tests__/dashboard-bundle-weight.test.js +19 -12
- package/dist/__tests__/dashboard-bundle-weight.test.js.map +1 -1
- package/dist/__tests__/dashboard-cell-containment.test.js +5 -2
- package/dist/__tests__/dashboard-cell-containment.test.js.map +1 -1
- package/dist/__tests__/dashboard-editor-link.test.d.ts +9 -0
- package/dist/__tests__/dashboard-editor-link.test.d.ts.map +1 -1
- package/dist/__tests__/dashboard-editor-link.test.js +72 -21
- package/dist/__tests__/dashboard-editor-link.test.js.map +1 -1
- package/dist/__tests__/dashboard-el.test.d.ts +18 -0
- package/dist/__tests__/dashboard-el.test.d.ts.map +1 -0
- package/dist/__tests__/dashboard-el.test.js +90 -0
- package/dist/__tests__/dashboard-el.test.js.map +1 -0
- package/dist/__tests__/dashboard-filters.test.js +6 -14
- package/dist/__tests__/dashboard-filters.test.js.map +1 -1
- package/dist/__tests__/dashboard-function-card-singleton.test.js +15 -27
- package/dist/__tests__/dashboard-function-card-singleton.test.js.map +1 -1
- package/dist/__tests__/dashboard-function-card.test.d.ts +4 -4
- package/dist/__tests__/dashboard-function-card.test.js +80 -44
- package/dist/__tests__/dashboard-function-card.test.js.map +1 -1
- package/dist/__tests__/dashboard-function-row.test.js +52 -51
- package/dist/__tests__/dashboard-function-row.test.js.map +1 -1
- package/dist/__tests__/dashboard-generator-graph-catalog.test.js +3 -1
- package/dist/__tests__/dashboard-generator-graph-catalog.test.js.map +1 -1
- package/dist/__tests__/dashboard-graph-offline.integration.test.js +3 -1
- package/dist/__tests__/dashboard-graph-offline.integration.test.js.map +1 -1
- package/dist/__tests__/dashboard-help-drawer.test.js +11 -17
- package/dist/__tests__/dashboard-help-drawer.test.js.map +1 -1
- package/dist/__tests__/dashboard-indexes.test.d.ts +6 -4
- package/dist/__tests__/dashboard-indexes.test.d.ts.map +1 -1
- package/dist/__tests__/dashboard-indexes.test.js +10 -7
- package/dist/__tests__/dashboard-indexes.test.js.map +1 -1
- package/dist/__tests__/dashboard-pagination.test.d.ts +15 -0
- package/dist/__tests__/dashboard-pagination.test.d.ts.map +1 -0
- package/dist/__tests__/dashboard-pagination.test.js +140 -0
- package/dist/__tests__/dashboard-pagination.test.js.map +1 -0
- package/dist/__tests__/dashboard-path-utils.test.d.ts +7 -0
- package/dist/__tests__/dashboard-path-utils.test.d.ts.map +1 -1
- package/dist/__tests__/dashboard-path-utils.test.js +11 -3
- package/dist/__tests__/dashboard-path-utils.test.js.map +1 -1
- package/dist/__tests__/dashboard-search.test.d.ts +5 -0
- package/dist/__tests__/dashboard-search.test.d.ts.map +1 -1
- package/dist/__tests__/dashboard-search.test.js +9 -3
- package/dist/__tests__/dashboard-search.test.js.map +1 -1
- package/dist/__tests__/dashboard-sessions.test.js +13 -11
- package/dist/__tests__/dashboard-sessions.test.js.map +1 -1
- package/dist/__tests__/dashboard-trace.test.d.ts +11 -0
- package/dist/__tests__/dashboard-trace.test.d.ts.map +1 -1
- package/dist/__tests__/dashboard-trace.test.js +55 -32
- package/dist/__tests__/dashboard-trace.test.js.map +1 -1
- package/dist/__tests__/dashboard-view-conformance.test.js +9 -15
- package/dist/__tests__/dashboard-view-conformance.test.js.map +1 -1
- package/dist/__tests__/dashboard-view-coupling.test.js +14 -35
- package/dist/__tests__/dashboard-view-coupling.test.js.map +1 -1
- package/dist/__tests__/dashboard-view-distribution.test.js +14 -37
- package/dist/__tests__/dashboard-view-distribution.test.js.map +1 -1
- package/dist/__tests__/dashboard-view-graph.test.js +29 -62
- package/dist/__tests__/dashboard-view-graph.test.js.map +1 -1
- package/dist/__tests__/dashboard-view-template.test.d.ts +13 -14
- package/dist/__tests__/dashboard-view-template.test.d.ts.map +1 -1
- package/dist/__tests__/dashboard-view-template.test.js +165 -112
- package/dist/__tests__/dashboard-view-template.test.js.map +1 -1
- package/dist/__tests__/graph-tab.test.js +4 -2
- package/dist/__tests__/graph-tab.test.js.map +1 -1
- package/dist/client/el.d.ts +17 -0
- package/dist/client/el.d.ts.map +1 -0
- package/dist/client/el.js +36 -0
- package/dist/client/el.js.map +1 -0
- package/dist/client-bundle.generated.d.ts +2 -0
- package/dist/client-bundle.generated.d.ts.map +1 -0
- package/dist/client-bundle.generated.js +3 -0
- package/dist/client-bundle.generated.js.map +1 -0
- package/dist/code-paths/__tests__/views-registry.test.d.ts +13 -8
- package/dist/code-paths/__tests__/views-registry.test.d.ts.map +1 -1
- package/dist/code-paths/__tests__/views-registry.test.js +27 -25
- package/dist/code-paths/__tests__/views-registry.test.js.map +1 -1
- package/dist/code-paths.d.ts +21 -62
- package/dist/code-paths.d.ts.map +1 -1
- package/dist/code-paths.js +24 -349
- package/dist/code-paths.js.map +1 -1
- package/dist/generator.d.ts +2 -0
- package/dist/generator.d.ts.map +1 -1
- package/dist/generator.js +28 -17
- package/dist/generator.js.map +1 -1
- package/package.json +5 -4
- package/dist/checks.d.ts +0 -7
- package/dist/checks.d.ts.map +0 -1
- package/dist/checks.js +0 -283
- package/dist/checks.js.map +0 -1
- package/dist/code-paths/catalog-provenance.d.ts +0 -22
- package/dist/code-paths/catalog-provenance.d.ts.map +0 -1
- package/dist/code-paths/catalog-provenance.js +0 -108
- package/dist/code-paths/catalog-provenance.js.map +0 -1
- package/dist/code-paths/catalog-recipes-tables.d.ts +0 -11
- package/dist/code-paths/catalog-recipes-tables.d.ts.map +0 -1
- package/dist/code-paths/catalog-recipes-tables.js +0 -86
- package/dist/code-paths/catalog-recipes-tables.js.map +0 -1
- package/dist/code-paths/editor-link.d.ts +0 -10
- package/dist/code-paths/editor-link.d.ts.map +0 -1
- package/dist/code-paths/editor-link.js +0 -20
- package/dist/code-paths/editor-link.js.map +0 -1
- package/dist/code-paths/filters.d.ts +0 -19
- package/dist/code-paths/filters.d.ts.map +0 -1
- package/dist/code-paths/filters.js +0 -47
- package/dist/code-paths/filters.js.map +0 -1
- package/dist/code-paths/function-card.d.ts +0 -15
- package/dist/code-paths/function-card.d.ts.map +0 -1
- package/dist/code-paths/function-card.js +0 -169
- package/dist/code-paths/function-card.js.map +0 -1
- package/dist/code-paths/function-row.d.ts +0 -17
- package/dist/code-paths/function-row.d.ts.map +0 -1
- package/dist/code-paths/function-row.js +0 -77
- package/dist/code-paths/function-row.js.map +0 -1
- package/dist/code-paths/graph-controls.d.ts +0 -27
- package/dist/code-paths/graph-controls.d.ts.map +0 -1
- package/dist/code-paths/graph-controls.js +0 -257
- package/dist/code-paths/graph-controls.js.map +0 -1
- package/dist/code-paths/graph-stylesheet.d.ts +0 -22
- package/dist/code-paths/graph-stylesheet.d.ts.map +0 -1
- package/dist/code-paths/graph-stylesheet.js +0 -121
- package/dist/code-paths/graph-stylesheet.js.map +0 -1
- package/dist/code-paths/help-drawer.d.ts +0 -18
- package/dist/code-paths/help-drawer.d.ts.map +0 -1
- package/dist/code-paths/help-drawer.js +0 -54
- package/dist/code-paths/help-drawer.js.map +0 -1
- package/dist/code-paths/indexes.d.ts +0 -28
- package/dist/code-paths/indexes.d.ts.map +0 -1
- package/dist/code-paths/indexes.js +0 -97
- package/dist/code-paths/indexes.js.map +0 -1
- package/dist/code-paths/path-utils.d.ts +0 -15
- package/dist/code-paths/path-utils.d.ts.map +0 -1
- package/dist/code-paths/path-utils.js +0 -47
- package/dist/code-paths/path-utils.js.map +0 -1
- package/dist/code-paths/search.d.ts +0 -14
- package/dist/code-paths/search.d.ts.map +0 -1
- package/dist/code-paths/search.js +0 -54
- package/dist/code-paths/search.js.map +0 -1
- package/dist/code-paths/trace.d.ts +0 -11
- package/dist/code-paths/trace.d.ts.map +0 -1
- package/dist/code-paths/trace.js +0 -60
- package/dist/code-paths/trace.js.map +0 -1
- package/dist/code-paths/view-coupling.d.ts +0 -22
- package/dist/code-paths/view-coupling.d.ts.map +0 -1
- package/dist/code-paths/view-coupling.js +0 -218
- package/dist/code-paths/view-coupling.js.map +0 -1
- package/dist/code-paths/view-distribution.d.ts +0 -20
- package/dist/code-paths/view-distribution.d.ts.map +0 -1
- package/dist/code-paths/view-distribution.js +0 -82
- package/dist/code-paths/view-distribution.js.map +0 -1
- package/dist/code-paths/view-graph.d.ts +0 -35
- package/dist/code-paths/view-graph.d.ts.map +0 -1
- package/dist/code-paths/view-graph.js +0 -379
- package/dist/code-paths/view-graph.js.map +0 -1
- package/dist/code-paths/view-template.d.ts +0 -154
- package/dist/code-paths/view-template.d.ts.map +0 -1
- package/dist/code-paths/view-template.js +0 -218
- package/dist/code-paths/view-template.js.map +0 -1
- package/dist/code-paths/views-registry.d.ts +0 -13
- package/dist/code-paths/views-registry.d.ts.map +0 -1
- package/dist/code-paths/views-registry.js +0 -53
- package/dist/code-paths/views-registry.js.map +0 -1
- package/dist/overview.d.ts +0 -13
- package/dist/overview.d.ts.map +0 -1
- package/dist/overview.js +0 -91
- package/dist/overview.js.map +0 -1
- package/dist/recipes.d.ts +0 -6
- package/dist/recipes.d.ts.map +0 -1
- package/dist/recipes.js +0 -68
- package/dist/recipes.js.map +0 -1
- package/dist/sessions.d.ts +0 -6
- package/dist/sessions.d.ts.map +0 -1
- package/dist/sessions.js +0 -288
- package/dist/sessions.js.map +0 -1
- package/dist/shared/el.d.ts +0 -13
- package/dist/shared/el.d.ts.map +0 -1
- package/dist/shared/el.js +0 -27
- package/dist/shared/el.js.map +0 -1
- package/dist/shared/pagination.d.ts +0 -15
- package/dist/shared/pagination.d.ts.map +0 -1
- package/dist/shared/pagination.js +0 -113
- package/dist/shared/pagination.js.map +0 -1
- package/dist/shared/sortable.d.ts +0 -14
- package/dist/shared/sortable.d.ts.map +0 -1
- package/dist/shared/sortable.js +0 -101
- package/dist/shared/sortable.js.map +0 -1
- package/dist/shared/tab-activators.d.ts +0 -16
- package/dist/shared/tab-activators.d.ts.map +0 -1
- package/dist/shared/tab-activators.js +0 -33
- package/dist/shared/tab-activators.js.map +0 -1
- package/dist/shared/tab-bar.d.ts +0 -8
- package/dist/shared/tab-bar.d.ts.map +0 -1
- package/dist/shared/tab-bar.js +0 -20
- package/dist/shared/tab-bar.js.map +0 -1
- package/dist/shared.d.ts +0 -26
- package/dist/shared.d.ts.map +0 -1
- package/dist/shared.js +0 -39
- package/dist/shared.js.map +0 -1
- package/dist/subtab-bar.d.ts +0 -23
- package/dist/subtab-bar.d.ts.map +0 -1
- package/dist/subtab-bar.js +0 -77
- package/dist/subtab-bar.js.map +0 -1
- package/dist/tool-tabs.d.ts +0 -12
- package/dist/tool-tabs.d.ts.map +0 -1
- package/dist/tool-tabs.js +0 -80
- package/dist/tool-tabs.js.map +0 -1
|
@@ -1,218 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* View 4 — "Package coupling heat map".
|
|
3
|
-
*
|
|
4
|
-
* Reads the engine-emitted `catalog.features.edge` rows (Plan C — the
|
|
5
|
-
* dashboard no longer re-aggregates call edges client-side); each row is a
|
|
6
|
-
* { callerPackage, calleePackage, count } directed coupling edge. Renders a
|
|
7
|
-
* per-package N×N table with text-shaded density (CSS custom property
|
|
8
|
-
* --coupling-density).
|
|
9
|
-
*
|
|
10
|
-
* The matrix is the WHOLE-GRAPH (unfiltered) coupling matrix — the filter
|
|
11
|
-
* chips no longer narrow it (it is a whole-graph insight). When the catalog
|
|
12
|
-
* carries no `edge` feature (a non-dashboard run) the view shows a no-data
|
|
13
|
-
* empty state.
|
|
14
|
-
*
|
|
15
|
-
* Empty cells (no calls in this direction) show '·' and are not
|
|
16
|
-
* clickable. Non-empty cells render the count; click → opens a
|
|
17
|
-
* Function Card list of the actual call sites for that pair (the drilldown
|
|
18
|
-
* keeps its own per-call-site walk, which the aggregate edge feature can't
|
|
19
|
-
* provide).
|
|
20
|
-
*/
|
|
21
|
-
export function dashboardViewCouplingJs() {
|
|
22
|
-
return String.raw `
|
|
23
|
-
views.push({
|
|
24
|
-
id: 'coupling',
|
|
25
|
-
label: 'Coupling',
|
|
26
|
-
help: {
|
|
27
|
-
title: 'Package coupling heat map',
|
|
28
|
-
sections: [
|
|
29
|
-
{ heading: 'What this is', body: 'A caller-by-callee matrix. Each cell counts the static call edges from one package into another. Darker shading = more calls. Click a cell to see the actual call sites.' },
|
|
30
|
-
{ heading: 'Why you care', body: 'Layered architectures want a clear flow of dependencies. Surprises in this matrix — a leaf package calling into core, a kernel package calling a peer — are usually layering violations or stale abstractions.' },
|
|
31
|
-
{ heading: 'How to read it', body: 'Read rows as "this package calls". Read columns as "this package is called by". The diagonal (a package calling itself) is normally densest. Off-diagonal density tells you which packages know about each other; absence of a cell means no call sites in that direction.' },
|
|
32
|
-
{ heading: 'What to do', body: 'Cells you did not expect deserve investigation. If a package is called by everyone (a column with many filled cells), that is a hub — make sure its API is intentional. If two peers both call into each other, you may have a circular dependency hiding in plain sight.' },
|
|
33
|
-
],
|
|
34
|
-
},
|
|
35
|
-
render(container, catalog, indexes, filterState) {
|
|
36
|
-
while (container.firstChild) container.removeChild(container.firstChild);
|
|
37
|
-
if (!catalog || !catalog.functions) {
|
|
38
|
-
container.appendChild(el('div', { class: 'empty', text: 'No catalog loaded.' }));
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
// The coupling matrix is read from the engine-emitted 'edge' feature
|
|
42
|
-
// (Plan C) — the dashboard no longer re-aggregates call edges client-side.
|
|
43
|
-
// Each edge is { callerPackage, calleePackage, count } computed via the
|
|
44
|
-
// canonical resolveCallee. Note: the engine matrix is the WHOLE-GRAPH
|
|
45
|
-
// (unfiltered) matrix; the filter chips no longer narrow it (the matrix is
|
|
46
|
-
// a whole-graph insight). Absent features ⇒ no-data empty state (a
|
|
47
|
-
// non-dashboard run does not materialize coupling).
|
|
48
|
-
const edges = (catalog.features && catalog.features.edge) || null;
|
|
49
|
-
if (!edges) {
|
|
50
|
-
container.appendChild(el('div', { class: 'empty', text: 'No coupling data in this catalog. Re-run the graph for a dashboard to compute the package matrix.' }));
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
const counts = new Map();
|
|
54
|
-
let max = 0;
|
|
55
|
-
for (const e of edges) {
|
|
56
|
-
let row = counts.get(e.callerPackage);
|
|
57
|
-
if (!row) { row = new Map(); counts.set(e.callerPackage, row); }
|
|
58
|
-
row.set(e.calleePackage, e.count);
|
|
59
|
-
if (e.count > max) max = e.count;
|
|
60
|
-
}
|
|
61
|
-
const pkgs = Array.from(new Set([...counts.keys(), ...[].concat(...Array.from(counts.values(), m => Array.from(m.keys())))])).sort();
|
|
62
|
-
if (pkgs.length === 0) {
|
|
63
|
-
container.appendChild(el('div', { class: 'empty', text: 'No cross-package calls found.' }));
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
const section = el('div', { class: 'section' });
|
|
67
|
-
section.appendChild(makeSectionHeading('Package coupling (' + pkgs.length + '×' + pkgs.length + ')', 'coupling'));
|
|
68
|
-
// Export the FULL (untruncated) coupling counts as long-format CSV.
|
|
69
|
-
const toolbar = el('div', { class: 'coupling-toolbar' });
|
|
70
|
-
toolbar.appendChild(el('button', {
|
|
71
|
-
class: 'coupling-export-btn',
|
|
72
|
-
text: 'Export CSV',
|
|
73
|
-
onclick: () => downloadCouplingCsv(counts),
|
|
74
|
-
}));
|
|
75
|
-
section.appendChild(toolbar);
|
|
76
|
-
const card = el('div', { class: 'card' });
|
|
77
|
-
const table = el('table', { class: 'coupling-table' });
|
|
78
|
-
const thead = el('thead');
|
|
79
|
-
const headRow = el('tr');
|
|
80
|
-
headRow.appendChild(el('th', { class: 'row-label', text: 'caller \\\\ callee' }));
|
|
81
|
-
for (const callee of pkgs) headRow.appendChild(el('th', { text: callee }));
|
|
82
|
-
thead.appendChild(headRow);
|
|
83
|
-
table.appendChild(thead);
|
|
84
|
-
const tbody = el('tbody');
|
|
85
|
-
for (const caller of pkgs) {
|
|
86
|
-
const row = el('tr');
|
|
87
|
-
row.appendChild(el('th', { class: 'row-label', text: caller }));
|
|
88
|
-
const rowCounts = counts.get(caller);
|
|
89
|
-
for (const callee of pkgs) {
|
|
90
|
-
const c = (rowCounts && rowCounts.get(callee)) || 0;
|
|
91
|
-
if (c === 0) {
|
|
92
|
-
row.appendChild(el('td', { class: 'coupling-cell empty', text: '·' }));
|
|
93
|
-
} else {
|
|
94
|
-
const density = max > 0 ? (c / max).toFixed(2) : '0';
|
|
95
|
-
const cell = el('td', {
|
|
96
|
-
class: 'coupling-cell',
|
|
97
|
-
style: '--coupling-density: ' + density,
|
|
98
|
-
text: String(c),
|
|
99
|
-
'data-caller': caller,
|
|
100
|
-
'data-callee': callee,
|
|
101
|
-
onclick: () => openCouplingDrilldown(caller, callee, indexes, filterState),
|
|
102
|
-
});
|
|
103
|
-
row.appendChild(cell);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
tbody.appendChild(row);
|
|
107
|
-
}
|
|
108
|
-
table.appendChild(tbody);
|
|
109
|
-
// Bounded, scrollable viewport: a large N×N matrix would otherwise run off
|
|
110
|
-
// the page. overflow:auto gives both scrollbars; the sticky header/label
|
|
111
|
-
// styling (see code-paths.css .coupling-scroll) keeps the axes readable.
|
|
112
|
-
const scroll = el('div', { class: 'coupling-scroll' });
|
|
113
|
-
scroll.appendChild(table);
|
|
114
|
-
card.appendChild(scroll);
|
|
115
|
-
section.appendChild(card);
|
|
116
|
-
container.appendChild(section);
|
|
117
|
-
},
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
// Build the coupling CSV as the SAME wide matrix the on-screen table shows
|
|
121
|
-
// (Map<callerPkg, Map<calleePkg, count>>): a 'caller \\ callee' corner cell,
|
|
122
|
-
// one column per callee package, one row per caller package, cells = the
|
|
123
|
-
// directed call count (0 where there is no edge). The package set and its sort
|
|
124
|
-
// are computed exactly as the table builds them, so the CSV is the grid —
|
|
125
|
-
// easier to navigate in a spreadsheet than our scrollable matrix on very large
|
|
126
|
-
// repos. Full and untruncated. Returned as a string so it is unit testable
|
|
127
|
-
// without touching the DOM / Blob APIs.
|
|
128
|
-
function buildCouplingCsv(counts) {
|
|
129
|
-
const callees = [].concat(...Array.from(counts.values(), m => Array.from(m.keys())));
|
|
130
|
-
const pkgs = Array.from(new Set([...counts.keys(), ...callees])).sort();
|
|
131
|
-
const header = [csvField('caller \\\\ callee')].concat(pkgs.map(csvField)).join(',');
|
|
132
|
-
const rows = [header];
|
|
133
|
-
for (const caller of pkgs) {
|
|
134
|
-
const row = counts.get(caller);
|
|
135
|
-
const cells = [csvField(caller)];
|
|
136
|
-
for (const callee of pkgs) {
|
|
137
|
-
cells.push(String((row && row.get(callee)) || 0));
|
|
138
|
-
}
|
|
139
|
-
rows.push(cells.join(','));
|
|
140
|
-
}
|
|
141
|
-
return rows.join('\n');
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// RFC-4180-ish field quoting: wrap in double quotes and double any embedded
|
|
145
|
-
// quote when the value contains a comma, quote, CR, or LF. Package names are
|
|
146
|
-
// normally bare, but '<unknown>' and odd repo layouts make this cheap insurance.
|
|
147
|
-
function csvField(value) {
|
|
148
|
-
let s = String(value == null ? '' : value);
|
|
149
|
-
// CSV/formula-injection guard: a cell a spreadsheet could read as a formula
|
|
150
|
-
// (leading =, +, -, @, tab, or CR) is neutralized with a leading apostrophe
|
|
151
|
-
// so Excel/Sheets treat it as text. Package names are untrusted — they come
|
|
152
|
-
// from arbitrary analyzed repos and can legitimately start with '@' (scoped
|
|
153
|
-
// packages) — so guard before the RFC-4180 quoting below.
|
|
154
|
-
if (s.length > 0 && /^[=+\-@\t\r]/.test(s)) s = "'" + s;
|
|
155
|
-
if (/[",\r\n]/.test(s)) return '"' + s.replace(/"/g, '""') + '"';
|
|
156
|
-
return s;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// Trigger a client-side download of the coupling CSV via a Blob + a transient
|
|
160
|
-
// anchor. No-ops gracefully in environments without URL.createObjectURL.
|
|
161
|
-
function downloadCouplingCsv(counts) {
|
|
162
|
-
const csv = buildCouplingCsv(counts);
|
|
163
|
-
try {
|
|
164
|
-
const blob = new Blob([csv], { type: 'text/csv;charset=utf-8' });
|
|
165
|
-
const url = URL.createObjectURL(blob);
|
|
166
|
-
const a = el('a', { href: url, download: 'coupling.csv', style: 'display:none' });
|
|
167
|
-
document.body.appendChild(a);
|
|
168
|
-
a.click();
|
|
169
|
-
document.body.removeChild(a);
|
|
170
|
-
setTimeout(() => { try { URL.revokeObjectURL(url); } catch (e) { /* ignore */ } }, 0);
|
|
171
|
-
} catch (e) { /* download unsupported in this environment */ }
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
function openCouplingDrilldown(callerPkg, calleePkg, indexes, filterState) {
|
|
175
|
-
// Render an inline Function Card overlay listing the call sites for
|
|
176
|
-
// the (callerPkg, calleePkg) pair. We piggyback on the overlay used
|
|
177
|
-
// by the universal Function Card to keep the singleton invariant.
|
|
178
|
-
let overlay = document.querySelector('.function-card-overlay');
|
|
179
|
-
if (!overlay) {
|
|
180
|
-
overlay = el('div', { class: 'function-card-overlay' });
|
|
181
|
-
overlay.addEventListener('click', e => { if (e.target === overlay) closeFunctionCard(); });
|
|
182
|
-
document.body.appendChild(overlay);
|
|
183
|
-
}
|
|
184
|
-
while (overlay.firstChild) overlay.removeChild(overlay.firstChild);
|
|
185
|
-
const card = el('div', { class: 'function-card' });
|
|
186
|
-
overlay.appendChild(card);
|
|
187
|
-
card.appendChild(el('button', { class: 'fc-close', text: '×', onclick: closeFunctionCard }));
|
|
188
|
-
card.appendChild(el('h3', { text: callerPkg + ' → ' + calleePkg }));
|
|
189
|
-
card.appendChild(el('div', { class: 'fc-loc', text: 'Call sites between these packages' }));
|
|
190
|
-
const list = el('ul', { class: 'fc-list' });
|
|
191
|
-
let count = 0;
|
|
192
|
-
for (const occ of indexes.byBodyHash.values()) {
|
|
193
|
-
if (!passesFilter(occ, filterState)) continue;
|
|
194
|
-
if (pkgOf(occ) !== callerPkg) continue;
|
|
195
|
-
for (const edge of (occ.calls || [])) {
|
|
196
|
-
for (const target of (edge.to || [])) {
|
|
197
|
-
const callee = resolveCalleeOcc(target, occ, indexes);
|
|
198
|
-
if (!callee) continue;
|
|
199
|
-
if (pkgOf(callee) !== calleePkg) continue;
|
|
200
|
-
const item = el('li', {
|
|
201
|
-
'data-body-hash': occ.bodyHash,
|
|
202
|
-
text: displayName(occ.simpleName) + ' → ' + displayName(callee.simpleName) + ' (' + occ.filePath + ':' + edge.line + ')',
|
|
203
|
-
});
|
|
204
|
-
item.addEventListener('click', () => openFunctionCard(occ.bodyHash));
|
|
205
|
-
list.appendChild(item);
|
|
206
|
-
count++;
|
|
207
|
-
if (count > 200) break;
|
|
208
|
-
}
|
|
209
|
-
if (count > 200) break;
|
|
210
|
-
}
|
|
211
|
-
if (count > 200) break;
|
|
212
|
-
}
|
|
213
|
-
if (count === 0) list.appendChild(el('li', { class: 'external', text: 'No call sites found.' }));
|
|
214
|
-
card.appendChild(list);
|
|
215
|
-
}
|
|
216
|
-
`;
|
|
217
|
-
}
|
|
218
|
-
//# sourceMappingURL=view-coupling.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"view-coupling.js","sourceRoot":"","sources":["../../src/code-paths/view-coupling.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,MAAM,UAAU,uBAAuB;IACrC,OAAO,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkMlB,CAAC;AACF,CAAC"}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* View — "Functions" (ranked-distribution affordance).
|
|
3
|
-
*
|
|
4
|
-
* Replaces the four single-metric ranked tabs (big / hot / wide / untested)
|
|
5
|
-
* with ONE sortable, paginated, filter-aware function table whose columns are
|
|
6
|
-
* the union those tabs covered: lines, callers (hot), params/width (wide), and
|
|
7
|
-
* a test-reachable flag (untested). The default sort is by lines descending
|
|
8
|
-
* (the most-requested triage axis); the shared `makeSortable` lets the reader
|
|
9
|
-
* re-sort by any column, so the sub-threshold tail (e.g. a 140-line function
|
|
10
|
-
* under a 150 gate) stays triageable once the single-metric tabs are gone.
|
|
11
|
-
*
|
|
12
|
-
* Built on `defineRankedView` (the same skeleton the removed tabs used), so it
|
|
13
|
-
* reuses `renderFunctionRows` / `makeSortable` / `paginateTable` and the
|
|
14
|
-
* row-click → Function Card delegation with no new plumbing.
|
|
15
|
-
*
|
|
16
|
-
* Part of the Plan B Code Paths restructure; concatenated only in the
|
|
17
|
-
* restructured (flag = true) branch of `dashboardCodePathsJs`.
|
|
18
|
-
*/
|
|
19
|
-
export declare function dashboardViewDistributionJs(): string;
|
|
20
|
-
//# sourceMappingURL=view-distribution.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"view-distribution.d.ts","sourceRoot":"","sources":["../../src/code-paths/view-distribution.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,wBAAgB,2BAA2B,IAAI,MAAM,CA6DpD"}
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* View — "Functions" (ranked-distribution affordance).
|
|
3
|
-
*
|
|
4
|
-
* Replaces the four single-metric ranked tabs (big / hot / wide / untested)
|
|
5
|
-
* with ONE sortable, paginated, filter-aware function table whose columns are
|
|
6
|
-
* the union those tabs covered: lines, callers (hot), params/width (wide), and
|
|
7
|
-
* a test-reachable flag (untested). The default sort is by lines descending
|
|
8
|
-
* (the most-requested triage axis); the shared `makeSortable` lets the reader
|
|
9
|
-
* re-sort by any column, so the sub-threshold tail (e.g. a 140-line function
|
|
10
|
-
* under a 150 gate) stays triageable once the single-metric tabs are gone.
|
|
11
|
-
*
|
|
12
|
-
* Built on `defineRankedView` (the same skeleton the removed tabs used), so it
|
|
13
|
-
* reuses `renderFunctionRows` / `makeSortable` / `paginateTable` and the
|
|
14
|
-
* row-click → Function Card delegation with no new plumbing.
|
|
15
|
-
*
|
|
16
|
-
* Part of the Plan B Code Paths restructure; concatenated only in the
|
|
17
|
-
* restructured (flag = true) branch of `dashboardCodePathsJs`.
|
|
18
|
-
*/
|
|
19
|
-
import { defineRankedView } from './view-template.js';
|
|
20
|
-
export function dashboardViewDistributionJs() {
|
|
21
|
-
return defineRankedView({
|
|
22
|
-
id: 'distribution',
|
|
23
|
-
label: 'Functions',
|
|
24
|
-
help: {
|
|
25
|
-
title: 'Functions (distribution)',
|
|
26
|
-
sections: [
|
|
27
|
-
{
|
|
28
|
-
heading: 'What this is',
|
|
29
|
-
body: 'Every function in the catalog in one sortable table. Columns cover the metrics the former single-metric tabs ranked individually: body length (lines), inbound callers, parameter count (width), and whether the function is reachable only from tests.',
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
heading: 'Why you care',
|
|
33
|
-
body: 'Findings surface the rules that actually fired; this table is the raw distribution behind them. It is where you triage the sub-threshold tail — a 140-line function under a 150-line gate, a 3-param function just under a width rule — that a pass/fail findings list cannot show.',
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
heading: 'How to read it',
|
|
37
|
-
body: 'Sort by any column (click the header). Lines descending is the default. Callers = 0 plus no test reachability is an orphan; Test-only = yes means production code reached only from tests. Use the filter chips above the tab bar to scope by package, kind, or test-file membership.',
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
heading: 'What to do',
|
|
41
|
-
body: 'Click a row to open the Function Card and inspect callers/callees. Long bodies split along callee boundaries; wide signatures often want an options object; test-only functions usually belong in a __tests__/ helper.',
|
|
42
|
-
},
|
|
43
|
-
],
|
|
44
|
-
},
|
|
45
|
-
// Default ranking metric: body length (lines). Re-sortable to any column.
|
|
46
|
-
metric: 'Math.max(0, (occ.endLine || occ.line) - occ.line + 1)',
|
|
47
|
-
preamble: String.raw `
|
|
48
|
-
function distCallerCount(o) { return (indexes.callers.get(o.bodyHash) || []).length; }
|
|
49
|
-
function distParamCount(o) { return (o.params || []).length; }
|
|
50
|
-
function distTestOnly(o) {
|
|
51
|
-
if (o.inTestFile) return false;
|
|
52
|
-
const callers = indexes.callers.get(o.bodyHash) || [];
|
|
53
|
-
if (callers.length === 0) return false;
|
|
54
|
-
return callers.every(function(h) {
|
|
55
|
-
const c = indexes.byBodyHash.get(h);
|
|
56
|
-
return c && c.inTestFile === true;
|
|
57
|
-
});
|
|
58
|
-
}`,
|
|
59
|
-
columns: [
|
|
60
|
-
{ label: 'Function', value: 'o => displayName(o.simpleName)' },
|
|
61
|
-
{ label: 'Lines', value: 'o => o.__metric' },
|
|
62
|
-
{ label: 'Callers', value: 'o => distCallerCount(o)' },
|
|
63
|
-
{ label: 'Params', value: 'o => distParamCount(o)' },
|
|
64
|
-
// The former 'Test-only' column moved to a "Test-only" filter toggle (below).
|
|
65
|
-
{ label: 'Kind', value: 'o => o.kind' },
|
|
66
|
-
{ label: 'Package', value: 'o => pkgOf(o)' },
|
|
67
|
-
{ label: 'File', value: "o => o.filePath + ':' + o.line" },
|
|
68
|
-
],
|
|
69
|
-
headingText: 'Functions',
|
|
70
|
-
emptyMessage: 'No functions match the active filters.',
|
|
71
|
-
// Absorbs the former standalone Search subtab: a name filter above
|
|
72
|
-
// the table, re-filtering rows in place by function simple-name.
|
|
73
|
-
searchByName: true,
|
|
74
|
-
// Kind (single-select) + Package (single-select) dropdowns in the same
|
|
75
|
-
// controls row, before the search box: Kind · Package · search.
|
|
76
|
-
filterByKindPackage: true,
|
|
77
|
-
// A "Test-only" checkbox after the search box — when checked, narrows the
|
|
78
|
-
// table to production functions reached only from tests (distTestOnly).
|
|
79
|
-
filterToggle: { label: 'Test-only', predicate: 'distTestOnly(occ)' },
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
//# sourceMappingURL=view-distribution.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"view-distribution.js","sourceRoot":"","sources":["../../src/code-paths/view-distribution.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,MAAM,UAAU,2BAA2B;IACzC,OAAO,gBAAgB,CAAC;QACtB,EAAE,EAAE,cAAc;QAClB,KAAK,EAAE,WAAW;QAClB,IAAI,EAAE;YACJ,KAAK,EAAE,0BAA0B;YACjC,QAAQ,EAAE;gBACR;oBACE,OAAO,EAAE,cAAc;oBACvB,IAAI,EAAE,yPAAyP;iBAChQ;gBACD;oBACE,OAAO,EAAE,cAAc;oBACvB,IAAI,EAAE,qRAAqR;iBAC5R;gBACD;oBACE,OAAO,EAAE,gBAAgB;oBACzB,IAAI,EAAE,uRAAuR;iBAC9R;gBACD;oBACE,OAAO,EAAE,YAAY;oBACrB,IAAI,EAAE,wNAAwN;iBAC/N;aACF;SACF;QACD,0EAA0E;QAC1E,MAAM,EAAE,uDAAuD;QAC/D,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;MAWlB;QACF,OAAO,EAAE;YACP,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,gCAAgC,EAAE;YAC9D,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,iBAAiB,EAAE;YAC5C,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,yBAAyB,EAAE;YACtD,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,wBAAwB,EAAE;YACpD,8EAA8E;YAC9E,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE;YACvC,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,eAAe,EAAE;YAC5C,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,gCAAgC,EAAE;SAC3D;QACD,WAAW,EAAE,WAAW;QACxB,YAAY,EAAE,wCAAwC;QACtD,mEAAmE;QACnE,iEAAiE;QACjE,YAAY,EAAE,IAAI;QAClB,uEAAuE;QACvE,gEAAgE;QAChE,mBAAmB,EAAE,IAAI;QACzB,0EAA0E;QAC1E,wEAAwE;QACxE,YAAY,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,mBAAmB,EAAE;KACrE,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* View 8 — "Visualization" (node-link topology, Cytoscape.js + dagre).
|
|
3
|
-
*
|
|
4
|
-
* The non-tabular Code Graph view. A self-contained **Level** control switches
|
|
5
|
-
* what the graph shows:
|
|
6
|
-
*
|
|
7
|
-
* - PACKAGE level (default) — one node per package, one edge per directed
|
|
8
|
-
* package→package coupling. Function granularity across the whole repo
|
|
9
|
-
* produced thousands of nodes, unusable in a node-link layout; the package
|
|
10
|
-
* rollup is the same data the Coupling matrix shows, drawn as a graph.
|
|
11
|
-
* Source: the pre-projected `graph-view-model` JSON blob embedded by
|
|
12
|
-
* `generator.ts` (projector in `graph-view-model.ts`, run at
|
|
13
|
-
* report-generation time) — NOT the raw catalog. Absent blob → empty state.
|
|
14
|
-
* - FUNCTION level — the functions of ONE selected package and the calls
|
|
15
|
-
* among them, projected client-side from the embedded catalog indexes by
|
|
16
|
-
* `gvBuildFunctionElements`. Scoping to a single package keeps the node
|
|
17
|
-
* count bounded. The "Edges" toggle chooses intra-package only (default) or
|
|
18
|
-
* "+ cross-package" (also draw calls leaving the package, to faded external
|
|
19
|
-
* nodes). Honors the Scope (test inclusion) and Kind (multi-select) filters.
|
|
20
|
-
*
|
|
21
|
-
* The view owns its controls (Level / Scope / Package / Kind / Edges) in
|
|
22
|
-
* `gvRenderControls`; the shared Explore filter chips govern the Functions
|
|
23
|
-
* table, NOT this view. Package + Kind only apply at function level, so they
|
|
24
|
-
* are disabled at package level. Renderer is the vendored `cytoscape` global +
|
|
25
|
-
* the `cytoscapeDagre` layout extension, both inlined by
|
|
26
|
-
* `dashboardCytoscapeVendorJs()` ahead of this emitter in `code-paths.ts`.
|
|
27
|
-
*
|
|
28
|
-
* Features: pan/zoom, layout selector (dagre/cose/breadthfirst), name search,
|
|
29
|
-
* node-click impact highlight (direct caller/callee neighbors), and
|
|
30
|
-
* cross-package cycle highlighting (package level). Visual encoding
|
|
31
|
-
* (totalCoupling→size, weight→edge thickness, sccId→accent, external→faded) is
|
|
32
|
-
* applied in `gvStylesheet` / `gvBuildElements` / `gvBuildFunctionElements`.
|
|
33
|
-
*/
|
|
34
|
-
export declare function dashboardViewGraphJs(): string;
|
|
35
|
-
//# sourceMappingURL=view-graph.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"view-graph.d.ts","sourceRoot":"","sources":["../../src/code-paths/view-graph.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAMH,wBAAgB,oBAAoB,IAAI,MAAM,CAqV7C"}
|