@anyshift/backstage-plugin-anyshift 0.1.0-beta.13 → 0.1.0-beta.14
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/CHANGELOG.md +5 -0
- package/dist/components/entity/ArchitectureOperationDetails.esm.js +107 -0
- package/dist/components/entity/ArchitectureOperationDetails.esm.js.map +1 -0
- package/dist/components/entity/MermaidArchitecture.esm.js +202 -43
- package/dist/components/entity/MermaidArchitecture.esm.js.map +1 -1
- package/dist/components/entity/SectionPresenters.esm.js +2 -35
- package/dist/components/entity/SectionPresenters.esm.js.map +1 -1
- package/dist/components/entity/architectureDiagram.esm.js +48 -15
- package/dist/components/entity/architectureDiagram.esm.js.map +1 -1
- package/dist/components/entity/architectureGraph.esm.js +145 -0
- package/dist/components/entity/architectureGraph.esm.js.map +1 -0
- package/dist/package.json.esm.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.1.0-beta.14
|
|
6
|
+
|
|
7
|
+
- Expose available APM HTTP methods and templated paths from service `CALLS_TO` edges through a compact architecture-diagram affordance and source-grouped evidence inspector.
|
|
8
|
+
- Keep missing operation or observation metadata explicitly unknown without changing legacy edge rendering or adding per-edge Graph API requests.
|
|
9
|
+
|
|
5
10
|
## 0.1.0-beta.13
|
|
6
11
|
|
|
7
12
|
- Keep zero-event cloud-resource pages quiet: identity-completeness codes do not become alerts
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
2
|
+
import { Box, Typography, Chip } from '@material-ui/core';
|
|
3
|
+
|
|
4
|
+
const formatObservationTime = (value, now = Date.now()) => {
|
|
5
|
+
if (!value) return { relative: "Observation time unavailable" };
|
|
6
|
+
const timestamp = Date.parse(value);
|
|
7
|
+
if (Number.isNaN(timestamp)) {
|
|
8
|
+
return { relative: "Observation time unavailable" };
|
|
9
|
+
}
|
|
10
|
+
const minutes = Math.round((timestamp - now) / 6e4);
|
|
11
|
+
const [amount, unit] = Math.abs(minutes) < 60 ? [minutes, "minute"] : Math.abs(minutes) < 2880 ? [Math.round(minutes / 60), "hour"] : [Math.round(minutes / 1440), "day"];
|
|
12
|
+
const relative = new Intl.RelativeTimeFormat("en", {
|
|
13
|
+
numeric: "auto"
|
|
14
|
+
}).format(amount, unit);
|
|
15
|
+
return {
|
|
16
|
+
relative: `Observed ${relative}`,
|
|
17
|
+
exact: new Date(timestamp).toISOString()
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
const isUsableOperation = (operation) => operation.method !== null || operation.pathTemplate !== null;
|
|
21
|
+
const usableOperations = (relationship) => relationship.operationSources.flatMap((source) => source.operations).filter(isUsableOperation);
|
|
22
|
+
const usableOperationCount = (relationship) => usableOperations(relationship).length;
|
|
23
|
+
const operationPreview = (relationship) => {
|
|
24
|
+
const operations = usableOperations(relationship);
|
|
25
|
+
const operation = operations[0];
|
|
26
|
+
if (relationship.operationCount === 0 || !operation) return "";
|
|
27
|
+
const summary = [
|
|
28
|
+
operation.method ?? "Method unavailable",
|
|
29
|
+
operation.pathTemplate ?? "Path unavailable"
|
|
30
|
+
].join(" ");
|
|
31
|
+
const remaining = relationship.operationCount - 1;
|
|
32
|
+
return remaining > 0 ? `${summary} \xB7 +${remaining} ${remaining === 1 ? "operation" : "operations"}` : summary;
|
|
33
|
+
};
|
|
34
|
+
const ArchitectureOperationDetails = ({
|
|
35
|
+
relationship,
|
|
36
|
+
onClose,
|
|
37
|
+
now
|
|
38
|
+
}) => {
|
|
39
|
+
if (relationship.operationCount === 0 || usableOperationCount(relationship) === 0) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
return /* @__PURE__ */ jsxs(Box, { border: 1, borderColor: "divider", borderRadius: 4, p: 2, children: [
|
|
43
|
+
/* @__PURE__ */ jsxs(
|
|
44
|
+
Box,
|
|
45
|
+
{
|
|
46
|
+
display: "flex",
|
|
47
|
+
justifyContent: "space-between",
|
|
48
|
+
alignItems: "flex-start",
|
|
49
|
+
children: [
|
|
50
|
+
/* @__PURE__ */ jsxs(Typography, { component: "h3", variant: "h6", children: [
|
|
51
|
+
relationship.fromLabel,
|
|
52
|
+
" to ",
|
|
53
|
+
relationship.toLabel
|
|
54
|
+
] }),
|
|
55
|
+
/* @__PURE__ */ jsx(
|
|
56
|
+
"button",
|
|
57
|
+
{
|
|
58
|
+
"aria-label": "Close HTTP operation details",
|
|
59
|
+
onClick: onClose,
|
|
60
|
+
type: "button",
|
|
61
|
+
children: "Close"
|
|
62
|
+
}
|
|
63
|
+
)
|
|
64
|
+
]
|
|
65
|
+
}
|
|
66
|
+
),
|
|
67
|
+
relationship.operationSources.map((source) => /* @__PURE__ */ jsxs(Box, { mt: 2, children: [
|
|
68
|
+
/* @__PURE__ */ jsx(Typography, { variant: "subtitle2", children: source.source }),
|
|
69
|
+
source.operations.filter(isUsableOperation).map((operation, index) => {
|
|
70
|
+
const observed = formatObservationTime(operation.observedAt, now);
|
|
71
|
+
return /* @__PURE__ */ jsxs(
|
|
72
|
+
Box,
|
|
73
|
+
{
|
|
74
|
+
display: "flex",
|
|
75
|
+
flexWrap: "wrap",
|
|
76
|
+
alignItems: "center",
|
|
77
|
+
gridGap: 8,
|
|
78
|
+
mt: 0.5,
|
|
79
|
+
children: [
|
|
80
|
+
operation.method ? /* @__PURE__ */ jsx(
|
|
81
|
+
Chip,
|
|
82
|
+
{
|
|
83
|
+
label: operation.method,
|
|
84
|
+
size: "small",
|
|
85
|
+
variant: "outlined"
|
|
86
|
+
}
|
|
87
|
+
) : /* @__PURE__ */ jsx(Typography, { variant: "body2", children: "Method unavailable" }),
|
|
88
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", children: operation.pathTemplate ?? "Path unavailable" }),
|
|
89
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "textSecondary", children: /* @__PURE__ */ jsxs("time", { dateTime: operation.observedAt ?? void 0, children: [
|
|
90
|
+
/* @__PURE__ */ jsx("span", { children: observed.relative }),
|
|
91
|
+
observed.exact && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
92
|
+
" \xB7 ",
|
|
93
|
+
/* @__PURE__ */ jsx("span", { children: observed.exact })
|
|
94
|
+
] })
|
|
95
|
+
] }) })
|
|
96
|
+
]
|
|
97
|
+
},
|
|
98
|
+
`${operation.method ?? ""}\0${operation.pathTemplate ?? ""}\0${index}`
|
|
99
|
+
);
|
|
100
|
+
}),
|
|
101
|
+
source.hasIncompleteOperations && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "textSecondary", component: "p", children: "Operation details incomplete" })
|
|
102
|
+
] }, source.source))
|
|
103
|
+
] });
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
export { ArchitectureOperationDetails, formatObservationTime, operationPreview };
|
|
107
|
+
//# sourceMappingURL=ArchitectureOperationDetails.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ArchitectureOperationDetails.esm.js","sources":["../../../src/components/entity/ArchitectureOperationDetails.tsx"],"sourcesContent":["import { Box, Chip, Typography } from '@material-ui/core';\nimport type { ArchitectureDiagramRelationship } from './architectureDiagram';\n\nexport const formatObservationTime = (\n value: string | null,\n now = Date.now(),\n): { relative: string; exact?: string } => {\n if (!value) return { relative: 'Observation time unavailable' };\n\n const timestamp = Date.parse(value);\n if (Number.isNaN(timestamp)) {\n return { relative: 'Observation time unavailable' };\n }\n\n const minutes = Math.round((timestamp - now) / 60_000);\n const [amount, unit] =\n Math.abs(minutes) < 60\n ? ([minutes, 'minute'] as const)\n : Math.abs(minutes) < 2_880\n ? ([Math.round(minutes / 60), 'hour'] as const)\n : ([Math.round(minutes / 1_440), 'day'] as const);\n const relative = new Intl.RelativeTimeFormat('en', {\n numeric: 'auto',\n }).format(amount, unit);\n\n return {\n relative: `Observed ${relative}`,\n exact: new Date(timestamp).toISOString(),\n };\n};\n\nconst isUsableOperation = (operation: {\n method: string | null;\n pathTemplate: string | null;\n}) => operation.method !== null || operation.pathTemplate !== null;\n\nconst usableOperations = (relationship: ArchitectureDiagramRelationship) =>\n relationship.operationSources\n .flatMap(source => source.operations)\n .filter(isUsableOperation);\n\nconst usableOperationCount = (relationship: ArchitectureDiagramRelationship) =>\n usableOperations(relationship).length;\n\nexport const operationPreview = (\n relationship: ArchitectureDiagramRelationship,\n): string => {\n const operations = usableOperations(relationship);\n const operation = operations[0];\n if (relationship.operationCount === 0 || !operation) return '';\n\n const summary = [\n operation.method ?? 'Method unavailable',\n operation.pathTemplate ?? 'Path unavailable',\n ].join(' ');\n const remaining = relationship.operationCount - 1;\n return remaining > 0\n ? `${summary} · +${remaining} ${\n remaining === 1 ? 'operation' : 'operations'\n }`\n : summary;\n};\n\nexport const ArchitectureOperationDetails = ({\n relationship,\n onClose,\n now,\n}: {\n relationship: ArchitectureDiagramRelationship;\n onClose: () => void;\n now?: number;\n}) => {\n if (\n relationship.operationCount === 0 ||\n usableOperationCount(relationship) === 0\n ) {\n return null;\n }\n\n return (\n <Box border={1} borderColor=\"divider\" borderRadius={4} p={2}>\n <Box\n display=\"flex\"\n justifyContent=\"space-between\"\n alignItems=\"flex-start\"\n >\n <Typography component=\"h3\" variant=\"h6\">\n {relationship.fromLabel} to {relationship.toLabel}\n </Typography>\n <button\n aria-label=\"Close HTTP operation details\"\n onClick={onClose}\n type=\"button\"\n >\n Close\n </button>\n </Box>\n\n {relationship.operationSources.map(source => (\n <Box key={source.source} mt={2}>\n <Typography variant=\"subtitle2\">{source.source}</Typography>\n {source.operations\n .filter(isUsableOperation)\n .map((operation, index) => {\n const observed = formatObservationTime(operation.observedAt, now);\n return (\n <Box\n key={`${operation.method ?? ''}\\u0000${\n operation.pathTemplate ?? ''\n }\\u0000${index}`}\n display=\"flex\"\n flexWrap=\"wrap\"\n alignItems=\"center\"\n gridGap={8}\n mt={0.5}\n >\n {operation.method ? (\n <Chip\n label={operation.method}\n size=\"small\"\n variant=\"outlined\"\n />\n ) : (\n <Typography variant=\"body2\">Method unavailable</Typography>\n )}\n <Typography variant=\"body2\">\n {operation.pathTemplate ?? 'Path unavailable'}\n </Typography>\n <Typography variant=\"caption\" color=\"textSecondary\">\n <time dateTime={operation.observedAt ?? undefined}>\n <span>{observed.relative}</span>\n {observed.exact && (\n <>\n {' · '}\n <span>{observed.exact}</span>\n </>\n )}\n </time>\n </Typography>\n </Box>\n );\n })}\n {source.hasIncompleteOperations && (\n <Typography variant=\"caption\" color=\"textSecondary\" component=\"p\">\n Operation details incomplete\n </Typography>\n )}\n </Box>\n ))}\n </Box>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -1,47 +1,114 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Box, CircularProgress, Typography } from '@material-ui/core';
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { Box, CircularProgress, Typography, makeStyles } from '@material-ui/core';
|
|
3
3
|
import mermaid from 'mermaid';
|
|
4
4
|
import { useMemo, useRef, useState, useEffect } from 'react';
|
|
5
5
|
import { buildArchitectureDiagram } from './architectureDiagram.esm.js';
|
|
6
|
+
import { operationPreview, ArchitectureOperationDetails } from './ArchitectureOperationDetails.esm.js';
|
|
6
7
|
|
|
7
8
|
let diagramSequence = 0;
|
|
8
9
|
let mermaidInitialized = false;
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
10
|
+
const useStyles = makeStyles((theme) => ({
|
|
11
|
+
diagram: {
|
|
12
|
+
"& .anyshift-http-edge-affordance": {
|
|
13
|
+
cursor: "pointer"
|
|
14
|
+
},
|
|
15
|
+
"& .anyshift-http-edge-affordance:focus": {
|
|
16
|
+
outline: `2px solid ${theme.palette.text.primary}`,
|
|
17
|
+
outlineOffset: 2
|
|
18
|
+
},
|
|
19
|
+
"& .edgeLabel.anyshift-http-edge-affordance rect": {
|
|
20
|
+
rx: 4,
|
|
21
|
+
ry: 4,
|
|
22
|
+
stroke: theme.palette.divider,
|
|
23
|
+
strokeWidth: 1
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
fallbackButton: {
|
|
27
|
+
appearance: "none",
|
|
28
|
+
background: "transparent",
|
|
29
|
+
border: 0,
|
|
30
|
+
color: "inherit",
|
|
31
|
+
cursor: "pointer",
|
|
32
|
+
font: "inherit",
|
|
33
|
+
padding: 0,
|
|
34
|
+
textAlign: "left",
|
|
35
|
+
"&:focus": {
|
|
36
|
+
outline: `2px solid ${theme.palette.text.primary}`,
|
|
37
|
+
outlineOffset: 2
|
|
31
38
|
}
|
|
32
|
-
|
|
33
|
-
|
|
39
|
+
}
|
|
40
|
+
}));
|
|
41
|
+
const hasUsableOperations = (relationship) => relationship.operationCount > 0 && operationPreview(relationship) !== "";
|
|
42
|
+
const RelationshipFallback = ({
|
|
43
|
+
relationships,
|
|
44
|
+
onSelect,
|
|
45
|
+
selectedId
|
|
46
|
+
}) => {
|
|
47
|
+
const classes = useStyles();
|
|
48
|
+
return /* @__PURE__ */ jsxs(Box, { mt: 2, children: [
|
|
49
|
+
/* @__PURE__ */ jsx(Typography, { color: "error", variant: "body2", role: "alert", children: "The architecture diagram could not be drawn. Showing relationships instead." }),
|
|
50
|
+
/* @__PURE__ */ jsx(
|
|
51
|
+
Box,
|
|
52
|
+
{
|
|
53
|
+
component: "ul",
|
|
54
|
+
m: 0,
|
|
55
|
+
mt: 1,
|
|
56
|
+
p: 0,
|
|
57
|
+
"aria-label": "Architecture relationships",
|
|
58
|
+
children: relationships.map((relationship) => /* @__PURE__ */ jsx(
|
|
59
|
+
Box,
|
|
60
|
+
{
|
|
61
|
+
component: "li",
|
|
62
|
+
py: 0.5,
|
|
63
|
+
style: { listStyle: "none" },
|
|
64
|
+
children: hasUsableOperations(relationship) ? /* @__PURE__ */ jsx(
|
|
65
|
+
"button",
|
|
66
|
+
{
|
|
67
|
+
"aria-label": `Show HTTP operations for ${relationship.fromLabel} to ${relationship.toLabel}`,
|
|
68
|
+
"aria-expanded": selectedId === relationship.id,
|
|
69
|
+
className: classes.fallbackButton,
|
|
70
|
+
onClick: () => onSelect(relationship),
|
|
71
|
+
type: "button",
|
|
72
|
+
children: /* @__PURE__ */ jsx(Typography, { component: "span", variant: "body2", children: relationship.label })
|
|
73
|
+
}
|
|
74
|
+
) : /* @__PURE__ */ jsx(Typography, { variant: "body2", children: relationship.label })
|
|
75
|
+
},
|
|
76
|
+
relationship.id
|
|
77
|
+
))
|
|
78
|
+
}
|
|
79
|
+
)
|
|
80
|
+
] });
|
|
81
|
+
};
|
|
34
82
|
const ArchitectureDiagram = ({
|
|
35
83
|
graph,
|
|
36
84
|
view = "runtime"
|
|
37
85
|
}) => {
|
|
86
|
+
const classes = useStyles();
|
|
38
87
|
const definition = useMemo(
|
|
39
88
|
() => buildArchitectureDiagram(graph, { view }),
|
|
40
89
|
[graph, view]
|
|
41
90
|
);
|
|
42
91
|
const diagramId = useRef(`anyshift-architecture-${diagramSequence++}`);
|
|
92
|
+
const diagramRef = useRef(null);
|
|
43
93
|
const [svg, setSvg] = useState();
|
|
44
94
|
const [renderFailed, setRenderFailed] = useState(false);
|
|
95
|
+
const [selectedId, setSelectedId] = useState();
|
|
96
|
+
const [previewId, setPreviewId] = useState();
|
|
97
|
+
const operationRelationships = useMemo(
|
|
98
|
+
() => definition.relationships.filter(hasUsableOperations),
|
|
99
|
+
[definition.relationships]
|
|
100
|
+
);
|
|
101
|
+
const relationshipsById = useMemo(
|
|
102
|
+
() => new Map(
|
|
103
|
+
operationRelationships.map((relationship) => [
|
|
104
|
+
relationship.id,
|
|
105
|
+
relationship
|
|
106
|
+
])
|
|
107
|
+
),
|
|
108
|
+
[operationRelationships]
|
|
109
|
+
);
|
|
110
|
+
const selectedRelationship = selectedId ? relationshipsById.get(selectedId) : void 0;
|
|
111
|
+
const previewRelationship = previewId ? relationshipsById.get(previewId) : void 0;
|
|
45
112
|
useEffect(() => {
|
|
46
113
|
let active = true;
|
|
47
114
|
setSvg(void 0);
|
|
@@ -64,25 +131,117 @@ const ArchitectureDiagram = ({
|
|
|
64
131
|
active = false;
|
|
65
132
|
};
|
|
66
133
|
}, [definition.source]);
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
134
|
+
useEffect(() => {
|
|
135
|
+
if (selectedId && !relationshipsById.has(selectedId)) {
|
|
136
|
+
setSelectedId(void 0);
|
|
137
|
+
}
|
|
138
|
+
if (previewId && !relationshipsById.has(previewId)) {
|
|
139
|
+
setPreviewId(void 0);
|
|
140
|
+
}
|
|
141
|
+
}, [previewId, relationshipsById, selectedId]);
|
|
142
|
+
useEffect(() => {
|
|
143
|
+
if (!svg || !diagramRef.current) return;
|
|
144
|
+
const edgePaths = diagramRef.current.querySelectorAll(".edgePath");
|
|
145
|
+
const edgeLabels = diagramRef.current.querySelectorAll(".edgeLabel");
|
|
146
|
+
operationRelationships.forEach((relationship) => {
|
|
147
|
+
const ariaLabel = `HTTP operations for ${relationship.fromLabel} to ${relationship.toLabel}`;
|
|
148
|
+
[
|
|
149
|
+
edgePaths.item(relationship.diagramIndex),
|
|
150
|
+
edgeLabels.item(relationship.diagramIndex)
|
|
151
|
+
].forEach((element) => {
|
|
152
|
+
if (!(element instanceof HTMLElement || element instanceof SVGElement)) {
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
element.dataset.anyshiftEdgeId = relationship.id;
|
|
156
|
+
element.setAttribute("role", "button");
|
|
157
|
+
element.setAttribute("tabindex", "0");
|
|
158
|
+
element.setAttribute("aria-label", ariaLabel);
|
|
159
|
+
element.setAttribute(
|
|
160
|
+
"aria-expanded",
|
|
161
|
+
String(selectedId === relationship.id)
|
|
162
|
+
);
|
|
163
|
+
element.classList.add("anyshift-http-edge-affordance");
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
}, [operationRelationships, selectedId, svg]);
|
|
167
|
+
const relationshipFromTarget = (target) => {
|
|
168
|
+
if (!(target instanceof Element)) return void 0;
|
|
169
|
+
const edge = target.closest("[data-anyshift-edge-id]");
|
|
170
|
+
const id = edge?.dataset.anyshiftEdgeId;
|
|
171
|
+
return id ? relationshipsById.get(id) : void 0;
|
|
172
|
+
};
|
|
173
|
+
const selectRelationship = (target) => {
|
|
174
|
+
const relationship = relationshipFromTarget(target);
|
|
175
|
+
if (relationship) setSelectedId(relationship.id);
|
|
176
|
+
};
|
|
177
|
+
const handleKeyDown = (event) => {
|
|
178
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
179
|
+
const relationship = relationshipFromTarget(event.target);
|
|
180
|
+
if (relationship) {
|
|
181
|
+
event.preventDefault();
|
|
182
|
+
setSelectedId(relationship.id);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
if (event.key === "Escape") setSelectedId(void 0);
|
|
186
|
+
};
|
|
187
|
+
const handleMouseOver = (event) => {
|
|
188
|
+
const relationship = relationshipFromTarget(event.target);
|
|
189
|
+
if (relationship) setPreviewId(relationship.id);
|
|
190
|
+
};
|
|
191
|
+
const handleMouseOut = (event) => {
|
|
192
|
+
const relationship = relationshipFromTarget(event.target);
|
|
193
|
+
const nextRelationship = relationshipFromTarget(event.relatedTarget);
|
|
194
|
+
if (relationship && relationship.id !== nextRelationship?.id) {
|
|
195
|
+
setPreviewId(void 0);
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
const handleFocus = (event) => {
|
|
199
|
+
const relationship = relationshipFromTarget(event.target);
|
|
200
|
+
if (relationship) setPreviewId(relationship.id);
|
|
201
|
+
};
|
|
202
|
+
const handleBlur = (event) => {
|
|
203
|
+
const relationship = relationshipFromTarget(event.target);
|
|
204
|
+
const nextRelationship = relationshipFromTarget(event.relatedTarget);
|
|
205
|
+
if (relationship && relationship.id !== nextRelationship?.id) {
|
|
206
|
+
setPreviewId(void 0);
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
return /* @__PURE__ */ jsxs(Box, { onKeyDown: handleKeyDown, children: [
|
|
210
|
+
renderFailed ? /* @__PURE__ */ jsx(
|
|
211
|
+
RelationshipFallback,
|
|
212
|
+
{
|
|
213
|
+
relationships: definition.relationships,
|
|
214
|
+
onSelect: (relationship) => setSelectedId(relationship.id),
|
|
215
|
+
selectedId
|
|
216
|
+
}
|
|
217
|
+
) : !svg ? /* @__PURE__ */ jsxs(Box, { display: "flex", alignItems: "center", gridGap: 8, py: 3, children: [
|
|
72
218
|
/* @__PURE__ */ jsx(CircularProgress, { size: 18 }),
|
|
73
219
|
/* @__PURE__ */ jsx(Typography, { variant: "body2", color: "textSecondary", children: "Drawing architecture\u2026" })
|
|
74
|
-
] })
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
220
|
+
] }) : /* @__PURE__ */ jsx(
|
|
221
|
+
Box,
|
|
222
|
+
{
|
|
223
|
+
"aria-label": "C4 architecture diagram",
|
|
224
|
+
className: classes.diagram,
|
|
225
|
+
onBlur: handleBlur,
|
|
226
|
+
onClick: (event) => selectRelationship(event.target),
|
|
227
|
+
onFocus: handleFocus,
|
|
228
|
+
onMouseOut: handleMouseOut,
|
|
229
|
+
onMouseOver: handleMouseOver,
|
|
230
|
+
role: "group",
|
|
231
|
+
mt: 1,
|
|
232
|
+
style: { overflowX: "auto" },
|
|
233
|
+
children: /* @__PURE__ */ jsx("div", { ref: diagramRef, dangerouslySetInnerHTML: { __html: svg } })
|
|
234
|
+
}
|
|
235
|
+
),
|
|
236
|
+
previewRelationship && /* @__PURE__ */ jsx(Typography, { role: "tooltip", variant: "caption", color: "textSecondary", children: operationPreview(previewRelationship) }),
|
|
237
|
+
selectedRelationship && /* @__PURE__ */ jsx(Box, { mt: 2, children: /* @__PURE__ */ jsx(
|
|
238
|
+
ArchitectureOperationDetails,
|
|
239
|
+
{
|
|
240
|
+
relationship: selectedRelationship,
|
|
241
|
+
onClose: () => setSelectedId(void 0)
|
|
242
|
+
}
|
|
243
|
+
) })
|
|
244
|
+
] });
|
|
86
245
|
};
|
|
87
246
|
|
|
88
247
|
export { ArchitectureDiagram };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MermaidArchitecture.esm.js","sources":["../../../src/components/entity/MermaidArchitecture.tsx"],"sourcesContent":["import { Box, CircularProgress, Typography } from '@material-ui/core';\nimport mermaid from 'mermaid';\nimport { useEffect, useMemo, useRef, useState } from 'react';\nimport {\n buildArchitectureDiagram,\n type ArchitectureGraph,\n} from './architectureDiagram';\n\nlet diagramSequence = 0;\nlet mermaidInitialized = false;\n\nconst RelationshipFallback = ({\n relationships,\n}: {\n relationships: string[];\n}) => (\n <Box mt={2}>\n <Typography color=\"error\" variant=\"body2\" role=\"alert\">\n The architecture diagram could not be drawn. Showing relationships\n instead.\n </Typography>\n <Box\n component=\"ul\"\n m={0}\n mt={1}\n p={0}\n aria-label=\"Architecture relationships\"\n >\n {relationships.map(relationship => (\n <Box\n component=\"li\"\n key={relationship}\n py={0.5}\n style={{ listStyle: 'none' }}\n >\n <Typography variant=\"body2\">{relationship}</Typography>\n </Box>\n ))}\n </Box>\n </Box>\n);\n\nexport const ArchitectureDiagram = ({\n graph,\n view = 'runtime',\n}: {\n graph: ArchitectureGraph;\n view?: 'context' | 'runtime';\n}) => {\n const definition = useMemo(\n () => buildArchitectureDiagram(graph, { view }),\n [graph, view],\n );\n const diagramId = useRef(`anyshift-architecture-${diagramSequence++}`);\n const [svg, setSvg] = useState<string>();\n const [renderFailed, setRenderFailed] = useState(false);\n\n useEffect(() => {\n let active = true;\n setSvg(undefined);\n setRenderFailed(false);\n\n if (!mermaidInitialized) {\n mermaid.initialize({\n startOnLoad: false,\n securityLevel: 'strict',\n theme: 'base',\n flowchart: { htmlLabels: false, curve: 'basis' },\n });\n mermaidInitialized = true;\n }\n\n Promise.resolve()\n .then(() => mermaid.render(diagramId.current, definition.source))\n .then(result => {\n if (active) setSvg(result.svg);\n })\n .catch(() => {\n if (active) setRenderFailed(true);\n });\n\n return () => {\n active = false;\n };\n }, [definition.source]);\n\n if (renderFailed) {\n return (\n <RelationshipFallback relationships={definition.fallbackRelationships} />\n );\n }\n\n if (!svg) {\n return (\n <Box display=\"flex\" alignItems=\"center\" gridGap={8} py={3}>\n <CircularProgress size={18} />\n <Typography variant=\"body2\" color=\"textSecondary\">\n Drawing architecture…\n </Typography>\n </Box>\n );\n }\n\n return (\n <Box\n aria-label=\"C4 architecture diagram\"\n role=\"img\"\n mt={1}\n style={{ overflowX: 'auto' }}\n dangerouslySetInnerHTML={{ __html: svg }}\n />\n );\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MermaidArchitecture.esm.js","sources":["../../../src/components/entity/MermaidArchitecture.tsx"],"sourcesContent":["import {\n Box,\n CircularProgress,\n Typography,\n makeStyles,\n} from '@material-ui/core';\nimport mermaid from 'mermaid';\nimport {\n type FocusEvent,\n type KeyboardEvent,\n type MouseEvent,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport {\n buildArchitectureDiagram,\n type ArchitectureGraph,\n type ArchitectureDiagramRelationship,\n} from './architectureDiagram';\nimport {\n ArchitectureOperationDetails,\n operationPreview,\n} from './ArchitectureOperationDetails';\n\nlet diagramSequence = 0;\nlet mermaidInitialized = false;\n\nconst useStyles = makeStyles(theme => ({\n diagram: {\n '& .anyshift-http-edge-affordance': {\n cursor: 'pointer',\n },\n '& .anyshift-http-edge-affordance:focus': {\n outline: `2px solid ${theme.palette.text.primary}`,\n outlineOffset: 2,\n },\n '& .edgeLabel.anyshift-http-edge-affordance rect': {\n rx: 4,\n ry: 4,\n stroke: theme.palette.divider,\n strokeWidth: 1,\n },\n },\n fallbackButton: {\n appearance: 'none',\n background: 'transparent',\n border: 0,\n color: 'inherit',\n cursor: 'pointer',\n font: 'inherit',\n padding: 0,\n textAlign: 'left',\n '&:focus': {\n outline: `2px solid ${theme.palette.text.primary}`,\n outlineOffset: 2,\n },\n },\n}));\n\nconst hasUsableOperations = (\n relationship: ArchitectureDiagramRelationship,\n): boolean =>\n relationship.operationCount > 0 && operationPreview(relationship) !== '';\n\nconst RelationshipFallback = ({\n relationships,\n onSelect,\n selectedId,\n}: {\n relationships: ArchitectureDiagramRelationship[];\n onSelect: (relationship: ArchitectureDiagramRelationship) => void;\n selectedId?: string;\n}) => {\n const classes = useStyles();\n return (\n <Box mt={2}>\n <Typography color=\"error\" variant=\"body2\" role=\"alert\">\n The architecture diagram could not be drawn. Showing relationships\n instead.\n </Typography>\n <Box\n component=\"ul\"\n m={0}\n mt={1}\n p={0}\n aria-label=\"Architecture relationships\"\n >\n {relationships.map(relationship => (\n <Box\n component=\"li\"\n key={relationship.id}\n py={0.5}\n style={{ listStyle: 'none' }}\n >\n {hasUsableOperations(relationship) ? (\n <button\n aria-label={`Show HTTP operations for ${relationship.fromLabel} to ${relationship.toLabel}`}\n aria-expanded={selectedId === relationship.id}\n className={classes.fallbackButton}\n onClick={() => onSelect(relationship)}\n type=\"button\"\n >\n <Typography component=\"span\" variant=\"body2\">\n {relationship.label}\n </Typography>\n </button>\n ) : (\n <Typography variant=\"body2\">{relationship.label}</Typography>\n )}\n </Box>\n ))}\n </Box>\n </Box>\n );\n};\n\nexport const ArchitectureDiagram = ({\n graph,\n view = 'runtime',\n}: {\n graph: ArchitectureGraph;\n view?: 'context' | 'runtime';\n}) => {\n const classes = useStyles();\n const definition = useMemo(\n () => buildArchitectureDiagram(graph, { view }),\n [graph, view],\n );\n const diagramId = useRef(`anyshift-architecture-${diagramSequence++}`);\n const diagramRef = useRef<HTMLDivElement>(null);\n const [svg, setSvg] = useState<string>();\n const [renderFailed, setRenderFailed] = useState(false);\n const [selectedId, setSelectedId] = useState<string>();\n const [previewId, setPreviewId] = useState<string>();\n const operationRelationships = useMemo(\n () => definition.relationships.filter(hasUsableOperations),\n [definition.relationships],\n );\n const relationshipsById = useMemo(\n () =>\n new Map(\n operationRelationships.map(relationship => [\n relationship.id,\n relationship,\n ]),\n ),\n [operationRelationships],\n );\n const selectedRelationship = selectedId\n ? relationshipsById.get(selectedId)\n : undefined;\n const previewRelationship = previewId\n ? relationshipsById.get(previewId)\n : undefined;\n\n useEffect(() => {\n let active = true;\n setSvg(undefined);\n setRenderFailed(false);\n\n if (!mermaidInitialized) {\n mermaid.initialize({\n startOnLoad: false,\n securityLevel: 'strict',\n theme: 'base',\n flowchart: { htmlLabels: false, curve: 'basis' },\n });\n mermaidInitialized = true;\n }\n\n Promise.resolve()\n .then(() => mermaid.render(diagramId.current, definition.source))\n .then(result => {\n if (active) setSvg(result.svg);\n })\n .catch(() => {\n if (active) setRenderFailed(true);\n });\n\n return () => {\n active = false;\n };\n }, [definition.source]);\n\n useEffect(() => {\n if (selectedId && !relationshipsById.has(selectedId)) {\n setSelectedId(undefined);\n }\n if (previewId && !relationshipsById.has(previewId)) {\n setPreviewId(undefined);\n }\n }, [previewId, relationshipsById, selectedId]);\n\n useEffect(() => {\n if (!svg || !diagramRef.current) return;\n\n const edgePaths = diagramRef.current.querySelectorAll('.edgePath');\n const edgeLabels = diagramRef.current.querySelectorAll('.edgeLabel');\n operationRelationships.forEach(relationship => {\n const ariaLabel = `HTTP operations for ${relationship.fromLabel} to ${relationship.toLabel}`;\n [\n edgePaths.item(relationship.diagramIndex),\n edgeLabels.item(relationship.diagramIndex),\n ].forEach(element => {\n if (\n !(element instanceof HTMLElement || element instanceof SVGElement)\n ) {\n return;\n }\n element.dataset.anyshiftEdgeId = relationship.id;\n element.setAttribute('role', 'button');\n element.setAttribute('tabindex', '0');\n element.setAttribute('aria-label', ariaLabel);\n element.setAttribute(\n 'aria-expanded',\n String(selectedId === relationship.id),\n );\n element.classList.add('anyshift-http-edge-affordance');\n });\n });\n }, [operationRelationships, selectedId, svg]);\n\n const relationshipFromTarget = (target: EventTarget | null) => {\n if (!(target instanceof Element)) return undefined;\n const edge = target.closest<HTMLElement>('[data-anyshift-edge-id]');\n const id = edge?.dataset.anyshiftEdgeId;\n return id ? relationshipsById.get(id) : undefined;\n };\n\n const selectRelationship = (target: EventTarget | null) => {\n const relationship = relationshipFromTarget(target);\n if (relationship) setSelectedId(relationship.id);\n };\n\n const handleKeyDown = (event: KeyboardEvent<HTMLElement>) => {\n if (event.key === 'Enter' || event.key === ' ') {\n const relationship = relationshipFromTarget(event.target);\n if (relationship) {\n event.preventDefault();\n setSelectedId(relationship.id);\n }\n }\n if (event.key === 'Escape') setSelectedId(undefined);\n };\n\n const handleMouseOver = (event: MouseEvent<HTMLElement>) => {\n const relationship = relationshipFromTarget(event.target);\n if (relationship) setPreviewId(relationship.id);\n };\n\n const handleMouseOut = (event: MouseEvent<HTMLElement>) => {\n const relationship = relationshipFromTarget(event.target);\n const nextRelationship = relationshipFromTarget(event.relatedTarget);\n if (relationship && relationship.id !== nextRelationship?.id) {\n setPreviewId(undefined);\n }\n };\n\n const handleFocus = (event: FocusEvent<HTMLElement>) => {\n const relationship = relationshipFromTarget(event.target);\n if (relationship) setPreviewId(relationship.id);\n };\n\n const handleBlur = (event: FocusEvent<HTMLElement>) => {\n const relationship = relationshipFromTarget(event.target);\n const nextRelationship = relationshipFromTarget(event.relatedTarget);\n if (relationship && relationship.id !== nextRelationship?.id) {\n setPreviewId(undefined);\n }\n };\n\n return (\n <Box onKeyDown={handleKeyDown}>\n {renderFailed ? (\n <RelationshipFallback\n relationships={definition.relationships}\n onSelect={relationship => setSelectedId(relationship.id)}\n selectedId={selectedId}\n />\n ) : !svg ? (\n <Box display=\"flex\" alignItems=\"center\" gridGap={8} py={3}>\n <CircularProgress size={18} />\n <Typography variant=\"body2\" color=\"textSecondary\">\n Drawing architecture…\n </Typography>\n </Box>\n ) : (\n <Box\n aria-label=\"C4 architecture diagram\"\n className={classes.diagram}\n onBlur={handleBlur}\n onClick={event => selectRelationship(event.target)}\n onFocus={handleFocus}\n onMouseOut={handleMouseOut}\n onMouseOver={handleMouseOver}\n role=\"group\"\n mt={1}\n style={{ overflowX: 'auto' }}\n >\n <div ref={diagramRef} dangerouslySetInnerHTML={{ __html: svg }} />\n </Box>\n )}\n {previewRelationship && (\n <Typography role=\"tooltip\" variant=\"caption\" color=\"textSecondary\">\n {operationPreview(previewRelationship)}\n </Typography>\n )}\n {selectedRelationship && (\n <Box mt={2}>\n <ArchitectureOperationDetails\n relationship={selectedRelationship}\n onClose={() => setSelectedId(undefined)}\n />\n </Box>\n )}\n </Box>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,7 @@ import { Box, Typography, Chip, Grid, ButtonGroup, Button, Divider } from '@mate
|
|
|
3
3
|
import { useState } from 'react';
|
|
4
4
|
import { EntityRefLink } from '@backstage/plugin-catalog-react';
|
|
5
5
|
import { ArchitectureDiagram } from './MermaidArchitecture.esm.js';
|
|
6
|
+
import { architectureGraphFrom } from './architectureGraph.esm.js';
|
|
6
7
|
import { EvidenceDisclosure } from './EvidenceDisclosure.esm.js';
|
|
7
8
|
import { recordsFrom, eventFrom, statusFrom, readText, isRecord, factsFrom, firstRecordFrom } from './sectionData.esm.js';
|
|
8
9
|
|
|
@@ -260,7 +261,7 @@ const TimelinePresenter = ({
|
|
|
260
261
|
] });
|
|
261
262
|
};
|
|
262
263
|
const ArchitecturePresenter = ({ data }) => {
|
|
263
|
-
const graph =
|
|
264
|
+
const graph = architectureGraphFrom(data);
|
|
264
265
|
const [view, setView] = useState("context");
|
|
265
266
|
if (graph.nodes.length === 0) {
|
|
266
267
|
return /* @__PURE__ */ jsx(PresenterFallback, { data });
|
|
@@ -380,40 +381,6 @@ function formatTimestamp(value) {
|
|
|
380
381
|
const timestamp = Date.parse(value);
|
|
381
382
|
return Number.isNaN(timestamp) ? value : new Date(timestamp).toLocaleString();
|
|
382
383
|
}
|
|
383
|
-
function architectureFrom(value) {
|
|
384
|
-
if (!isRecord(value)) return { nodes: [], edges: [] };
|
|
385
|
-
const nodeValues = Array.isArray(value.nodes) ? value.nodes.filter(isRecord) : [];
|
|
386
|
-
const nodes = nodeValues.map((node, index) => {
|
|
387
|
-
const id = readText(node, ["id", "name"]) ?? `node-${index}`;
|
|
388
|
-
const name = readText(node, ["name", "id"]) ?? id;
|
|
389
|
-
return {
|
|
390
|
-
id,
|
|
391
|
-
name,
|
|
392
|
-
type: readText(node, ["type"]),
|
|
393
|
-
namespace: readText(node, ["namespace"]),
|
|
394
|
-
image: readText(node, ["image"])
|
|
395
|
-
};
|
|
396
|
-
});
|
|
397
|
-
const edgeValues = Array.isArray(value.edges) ? value.edges.filter(isRecord) : [];
|
|
398
|
-
const edges = edgeValues.flatMap((edge) => {
|
|
399
|
-
const from = endpointId(edge.from ?? edge.source);
|
|
400
|
-
const to = endpointId(edge.to ?? edge.target);
|
|
401
|
-
if (!from || !to) return [];
|
|
402
|
-
return [
|
|
403
|
-
{
|
|
404
|
-
from,
|
|
405
|
-
to,
|
|
406
|
-
type: readText(edge, ["type", "label", "relationship"]) ?? "RELATES_TO"
|
|
407
|
-
}
|
|
408
|
-
];
|
|
409
|
-
});
|
|
410
|
-
return { nodes, edges };
|
|
411
|
-
}
|
|
412
|
-
function endpointId(value) {
|
|
413
|
-
if (typeof value === "string") return value;
|
|
414
|
-
if (!isRecord(value)) return void 0;
|
|
415
|
-
return readText(value, ["id", "name"]);
|
|
416
|
-
}
|
|
417
384
|
const Muted = ({ children }) => /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "textSecondary", children });
|
|
418
385
|
const Warnings = ({ warnings }) => warnings.length > 0 ? /* @__PURE__ */ jsx(Box, { mt: 2, children: warnings.map((warning) => /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "textSecondary", children: warning }, warning)) }) : null;
|
|
419
386
|
function textArray(value) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SectionPresenters.esm.js","sources":["../../../src/components/entity/SectionPresenters.tsx"],"sourcesContent":["import {\n Box,\n Button,\n ButtonGroup,\n Chip,\n Divider,\n Grid,\n Typography,\n} from '@material-ui/core';\nimport type { ReactNode } from 'react';\nimport { useState } from 'react';\nimport { EntityRefLink } from '@backstage/plugin-catalog-react';\nimport type {\n EntityImpact,\n SafeguardResult,\n WhyNowAssessment,\n} from '../../api/types';\nimport { ArchitectureDiagram } from './MermaidArchitecture';\nimport type { ArchitectureGraph } from './architectureDiagram';\nimport { EvidenceDisclosure } from './EvidenceDisclosure';\nimport {\n eventFrom,\n factsFrom,\n firstRecordFrom,\n isRecord,\n readText,\n recordsFrom,\n statusFrom,\n type Fact,\n type StatusSummary,\n} from './sectionData';\n\nconst SAFEGUARD_LABELS: Record<SafeguardResult['capability'], string> = {\n pdb: 'Pod disruption budget',\n scaling: 'Scaling',\n priority: 'Priority',\n storage: 'Storage',\n};\n\nconst OVERVIEW_SIGNALS = [\n ['callerCount', 'Direct callers'],\n ['calleeCount', 'Direct callees'],\n ['downstreamServiceCount', 'Downstream services'],\n ['datastoreCount', 'Datastores'],\n ['externalCount', 'External systems'],\n ['eventCount24h', 'Changes · 24h'],\n] as const;\n\nexport const OverviewPresenter = ({ data }: { data: unknown }) => {\n const value = isRecord(data) ? data : {};\n return (\n <>\n <Grid container spacing={2} aria-label=\"Service signals\">\n {OVERVIEW_SIGNALS.map(([key, label]) => (\n <Grid item xs={6} sm={4} md={2} key={key}>\n <Typography variant=\"h5\">\n {typeof value[key] === 'number' ? String(value[key]) : 'N/A'}\n </Typography>\n <Typography variant=\"caption\" color=\"textSecondary\">\n {label}\n </Typography>\n </Grid>\n ))}\n <Grid item xs={6} sm={4} md={2}>\n <Typography variant=\"subtitle1\">\n {readableStatus(value.sloStatus)}\n </Typography>\n <Typography variant=\"caption\" color=\"textSecondary\">\n Service level\n </Typography>\n </Grid>\n <Grid item xs={6} sm={4} md={2}>\n <Typography variant=\"subtitle1\">\n {typeof value.activeAlertCount === 'number'\n ? `${value.activeAlertCount} active`\n : 'N/A'}\n </Typography>\n <Typography variant=\"caption\" color=\"textSecondary\">\n Alerts\n </Typography>\n </Grid>\n </Grid>\n <EvidenceDisclosure data={data} />\n </>\n );\n};\n\nexport const DependencyFootprintPresenter = ({ data }: { data: unknown }) => {\n const root = isRecord(data) ? data : {};\n const serviceTree = isRecord(root.serviceTree) ? root.serviceTree : {};\n const tree = isRecord(serviceTree.target) ? serviceTree.target : {};\n const calls = isRecord(root.calls) ? root.calls : {};\n const direct = isRecord(calls.target) ? calls.target : {};\n const callers = textArray(direct.callers);\n const callees = textArray(direct.callees);\n const configuration = isRecord(root.configuration) ? root.configuration : {};\n const configuredNodes = new Map(\n recordsFrom(configuration.nodes).flatMap(node => {\n const id = readText(node, ['id']);\n const name = readText(node, ['name']);\n return id && name ? [[id, name] as const] : [];\n }),\n );\n const configuredEdges = recordsFrom(configuration.edges);\n const configuredCallers = configuredEdges.flatMap(edge => {\n const from = readText(edge, ['from']);\n const to = readText(edge, ['to']);\n return from && to && !to.startsWith('configured:')\n ? [configuredNodes.get(from) ?? from]\n : [];\n });\n const configuredCallees = configuredEdges.flatMap(edge => {\n const to = readText(edge, ['to']);\n return to?.startsWith('configured:')\n ? [configuredNodes.get(to) ?? to.slice('configured:'.length)]\n : [];\n });\n const footprint = [\n metricLabel(tree.serviceCount, 'service', 'services'),\n metricLabel(tree.datastoreCount, 'datastore', 'datastores'),\n metricLabel(tree.externalCount, 'external', 'externals'),\n ].filter((value): value is string => Boolean(value));\n\n return (\n <>\n {tree.hasCycle === true && (\n <Box mb={2}>\n <Chip\n size=\"small\"\n variant=\"outlined\"\n label=\"Dependency cycle detected\"\n />\n </Box>\n )}\n <Grid container spacing={3}>\n <Grid item xs={12} md={6}>\n <Typography variant=\"overline\" color=\"textSecondary\">\n Called by\n </Typography>\n <NamedResources names={callers} />\n {callers.length === 0 && <Muted>Not resolved</Muted>}\n </Grid>\n <Grid item xs={12} md={6}>\n <Typography variant=\"overline\" color=\"textSecondary\">\n Calls\n </Typography>\n <NamedResources names={callees} />\n {callees.length === 0 && <Muted>Not resolved</Muted>}\n </Grid>\n </Grid>\n {footprint.length > 0 && (\n <Box display=\"flex\" flexWrap=\"wrap\" gridGap={8} mt={2}>\n {footprint.map(item => (\n <Chip key={item} size=\"small\" variant=\"outlined\" label={item} />\n ))}\n </Box>\n )}\n {(configuredCallers.length > 0 || configuredCallees.length > 0) && (\n <Box mt={2}>\n <Chip size=\"small\" color=\"primary\" label=\"Configured evidence\" />\n <Grid container spacing={3}>\n <Grid item xs={12} md={6}>\n <Typography variant=\"overline\" color=\"textSecondary\">\n Configured callers\n </Typography>\n <NamedResources names={configuredCallers} />\n </Grid>\n <Grid item xs={12} md={6}>\n <Typography variant=\"overline\" color=\"textSecondary\">\n Configured dependencies\n </Typography>\n <NamedResources names={configuredCallees} />\n </Grid>\n </Grid>\n </Box>\n )}\n <EvidenceDisclosure data={data} />\n </>\n );\n};\n\nexport const OperationalPosturePresenter = ({ data }: { data: unknown }) => {\n const root = isRecord(data) ? data : {};\n const slo = isRecord(root.slo) ? root.slo : {};\n const sloTarget = isRecord(slo.target) ? slo.target : {};\n const alerts = isRecord(root.alerts) ? root.alerts : {};\n const deployImpact = isRecord(root.deployImpact) ? root.deployImpact : {};\n const gitops = isRecord(root.gitops) ? root.gitops : {};\n const owner = isRecord(gitops.owner) ? gitops.owner : {};\n const alertCause = isRecord(root.alertCause) ? root.alertCause : {};\n const changes = Array.isArray(alertCause.changes)\n ? alertCause.changes.length\n : undefined;\n const findings = [\n {\n label: sloTarget.status\n ? `${readableStatus(sloTarget.status)} SLO`\n : 'SLO not resolved',\n detail: readText(sloTarget, ['name']),\n },\n {\n label:\n alerts.total === 0\n ? 'No active alerts'\n : typeof alerts.total === 'number'\n ? `${alerts.total} active alerts`\n : 'Alerts not resolved',\n },\n {\n label:\n typeof deployImpact.rollouts === 'number'\n ? `${deployImpact.rollouts} rollouts · ${\n typeof deployImpact.total === 'number'\n ? deployImpact.total\n : 'N/A'\n } correlated failures`\n : 'Deployment impact not resolved',\n },\n {\n label: owner.application ? String(owner.application) : 'No GitOps owner',\n },\n {\n label:\n changes === undefined\n ? 'Recent cause not resolved'\n : `${changes} recent correlated ${\n changes === 1 ? 'change' : 'changes'\n }`,\n },\n ];\n\n return (\n <>\n <Box component=\"ul\" m={0} p={0} aria-label=\"Operational findings\">\n {findings.map((finding, index) => (\n <Box component=\"li\" key={finding.label} style={{ listStyle: 'none' }}>\n {index > 0 && <Divider />}\n <Box py={1}>\n <Typography variant=\"subtitle2\">{finding.label}</Typography>\n {finding.detail && <Muted>{finding.detail}</Muted>}\n </Box>\n </Box>\n ))}\n </Box>\n <EvidenceDisclosure data={data} />\n </>\n );\n};\n\nconst WHY_NOW_LABELS: Record<WhyNowAssessment['verdict'], string> = {\n deployment_correlated: 'Deployment correlated',\n runtime_cause_suspected: 'Runtime cause suspected',\n active_alerts: 'Active alerts',\n clear: 'No active alerts',\n insufficient_evidence: 'Insufficient evidence',\n};\n\nexport const WhyNowPresenter = ({ data }: { data: WhyNowAssessment }) => (\n <>\n <Box display=\"flex\" flexWrap=\"wrap\" alignItems=\"center\" gridGap={8} mb={1}>\n <Chip\n size=\"small\"\n color={data.verdict === 'clear' ? 'primary' : 'default'}\n label={WHY_NOW_LABELS[data.verdict]}\n />\n <Typography variant=\"subtitle1\">{data.headline}</Typography>\n </Box>\n <Grid container spacing={2}>\n <Grid item xs={12} md={4}>\n <Typography variant=\"overline\" color=\"textSecondary\">\n Current condition\n </Typography>\n <Typography variant=\"body2\">\n {typeof data.activeAlerts === 'number'\n ? `${data.activeAlerts} active ${\n data.activeAlerts === 1 ? 'alert' : 'alerts'\n }`\n : 'Alert evidence unavailable'}\n </Typography>\n {data.firingMonitors.length > 0 && (\n <NamedResources names={data.firingMonitors} />\n )}\n </Grid>\n <Grid item xs={12} md={4}>\n <Typography variant=\"overline\" color=\"textSecondary\">\n Runtime suspects · {data.evidence.runtimeWindow}\n </Typography>\n {data.suspectedChanges.length > 0 ? (\n <Box component=\"ul\" m={0} pl={2}>\n {data.suspectedChanges.map((change, index) => (\n <li key={`${change.timestamp || change.type}-${index}`}>\n <Typography variant=\"body2\">\n {change.summary || 'No graph summary was provided.'}\n </Typography>\n <Muted>{readableStatus(change.type)}</Muted>\n </li>\n ))}\n </Box>\n ) : (\n <Muted>No recent runtime suspect was resolved.</Muted>\n )}\n </Grid>\n <Grid item xs={12} md={4}>\n <Typography variant=\"overline\" color=\"textSecondary\">\n Deployment correlation · {data.evidence.deploymentWindow}\n </Typography>\n <Typography variant=\"body2\">\n {typeof data.deployment.rollouts === 'number'\n ? `${data.deployment.rollouts} ${\n data.deployment.rollouts === 1 ? 'rollout' : 'rollouts'\n } · ${\n typeof data.deployment.correlatedFailures === 'number'\n ? data.deployment.correlatedFailures\n : 'N/A'\n } correlated failures`\n : 'Deployment evidence unavailable'}\n </Typography>\n </Grid>\n </Grid>\n <Warnings warnings={data.warnings} />\n </>\n);\n\nconst IMPACT_METRICS = [\n ['affectedWorkloads', 'Affected workloads'],\n ['downstreamServices', 'Downstream services'],\n ['datastores', 'Datastores'],\n ['externalDependencies', 'External dependencies'],\n] as const;\n\nexport const AffectedFootprintPresenter = ({\n data,\n}: {\n data: EntityImpact;\n}) => (\n <>\n <Grid container spacing={2}>\n {IMPACT_METRICS.map(([key, label]) => (\n <Grid item xs={6} key={key}>\n <Typography variant=\"h5\">\n {typeof data[key] === 'number' ? data[key] : 'N/A'}\n </Typography>\n <Typography variant=\"caption\" color=\"textSecondary\">\n {label}\n </Typography>\n </Grid>\n ))}\n </Grid>\n <Box display=\"flex\" flexWrap=\"wrap\" gridGap={8} mt={2}>\n <Chip\n size=\"small\"\n variant=\"outlined\"\n label={`${data.monitorCount ?? 'N/A'} monitors`}\n />\n <Chip\n size=\"small\"\n variant=\"outlined\"\n label={`${data.sloCount ?? 'N/A'} SLOs`}\n />\n </Box>\n {data.relatedEntities.length > 0 && (\n <Box mt={2}>\n <Typography variant=\"overline\" color=\"textSecondary\">\n Related catalog entities\n </Typography>\n <Box display=\"flex\" flexDirection=\"column\" gridGap={4}>\n {data.relatedEntities.map(entity => (\n <EntityRefLink\n key={entity.entityRef}\n entityRef={entity.entityRef}\n title={entity.name}\n />\n ))}\n </Box>\n </Box>\n )}\n <Warnings warnings={data.warnings} />\n </>\n);\n\nexport const ImpactPresenter = ({\n data,\n showEvidence = true,\n summaryMetric,\n}: {\n data: unknown;\n showEvidence?: boolean;\n summaryMetric?: false | { label: string; total: number };\n}) => {\n const affected = namedRecords(data);\n const total = numberFrom(data, ['total', 'count', 'affectedCount']);\n const status = statusFrom(data);\n const defaultTotal =\n total ?? (affected.length > 0 ? affected.length : undefined);\n const visibleSummary =\n summaryMetric === false\n ? undefined\n : summaryMetric ??\n (defaultTotal !== undefined\n ? { label: 'Affected resources', total: defaultTotal }\n : undefined);\n\n return (\n <>\n {visibleSummary && (\n <Box mb={2}>\n <Typography variant=\"overline\" color=\"textSecondary\">\n {visibleSummary.label}\n </Typography>\n <Typography variant=\"h5\">{visibleSummary.total}</Typography>\n </Box>\n )}\n {status && <StatusChip status={status} />}\n <GenericFacts data={data} omit={['total', 'count', 'affectedCount']} />\n <NamedResources names={affected} />\n {showEvidence && <EvidenceDisclosure data={data} />}\n </>\n );\n};\n\nexport const LatestChangePresenter = ({ data }: { data: unknown }) => {\n const record = firstRecordFrom(data);\n const event = eventFrom(record);\n if (!record) {\n return <PresenterFallback data={data} />;\n }\n\n return (\n <>\n <EventHeading event={event} />\n <FactGrid facts={event.facts} />\n <EvidenceDisclosure data={data} />\n </>\n );\n};\n\nexport const SafeguardsPresenter = ({ data }: { data: SafeguardResult[] }) => (\n <>\n <Box component=\"ul\" m={0} p={0} aria-label=\"Service safeguards\">\n {data.map((item, index) => (\n <Box component=\"li\" key={item.capability} style={{ listStyle: 'none' }}>\n {index > 0 && <Divider />}\n <Box width=\"100%\" py={1}>\n <Typography variant=\"subtitle2\">\n {SAFEGUARD_LABELS[item.capability]}\n </Typography>\n <SafeguardState item={item} />\n </Box>\n </Box>\n ))}\n </Box>\n <EvidenceDisclosure data={data} />\n </>\n);\n\nexport const TimelinePresenter = ({\n data,\n fallbackLabel = 'Change recorded',\n showEvidence = true,\n}: {\n data: unknown;\n fallbackLabel?: string;\n showEvidence?: boolean;\n}) => {\n const records = recordsFrom(data).slice(0, 10);\n if (records.length === 0) return <PresenterFallback data={data} />;\n\n return (\n <>\n <Box component=\"ol\" m={0} pl={3}>\n {records.map((record, index) => {\n const event = eventFrom(record);\n return (\n <Box component=\"li\" key={eventKey(record, index)} pb={2}>\n <EventHeading event={event} fallbackLabel={fallbackLabel} />\n {event.summary && (\n <Typography variant=\"body2\">{event.summary}</Typography>\n )}\n </Box>\n );\n })}\n </Box>\n {showEvidence && <EvidenceDisclosure data={data} />}\n </>\n );\n};\n\nexport const ArchitecturePresenter = ({ data }: { data: unknown }) => {\n const graph = architectureFrom(data);\n const [view, setView] = useState<'context' | 'runtime'>('context');\n if (graph.nodes.length === 0) {\n return <PresenterFallback data={data} />;\n }\n\n return (\n <>\n <Box display=\"flex\" justifyContent=\"flex-end\" mb={1}>\n <ButtonGroup size=\"small\" aria-label=\"Service map depth\">\n <Button\n type=\"button\"\n aria-pressed={view === 'context'}\n color={view === 'context' ? 'primary' : 'default'}\n onClick={() => setView('context')}\n >\n Service context\n </Button>\n <Button\n type=\"button\"\n aria-pressed={view === 'runtime'}\n color={view === 'runtime' ? 'primary' : 'default'}\n onClick={() => setView('runtime')}\n >\n Runtime detail\n </Button>\n </ButtonGroup>\n </Box>\n <ArchitectureDiagram graph={graph} view={view} />\n <EvidenceDisclosure data={data} />\n </>\n );\n};\n\nexport const GenericFacts = ({\n data,\n omit = [],\n}: {\n data: unknown;\n omit?: string[];\n}) => {\n const omitted = new Set(omit);\n const facts = factsFrom(data).filter(fact => !omitted.has(factKey(fact)));\n if (facts.length === 0) {\n return (\n <Typography variant=\"body2\" color=\"textSecondary\">\n No readable summary is available.\n </Typography>\n );\n }\n return <FactGrid facts={facts} />;\n};\n\nconst PresenterFallback = ({ data }: { data: unknown }) => (\n <>\n <GenericFacts data={data} />\n <EvidenceDisclosure data={data} />\n </>\n);\n\nconst SafeguardState = ({ item }: { item: SafeguardResult }) => {\n if (item.section.state === 'error') {\n return <Typography color=\"error\">{item.section.message}</Typography>;\n }\n if (item.section.state === 'empty' || item.section.state === 'unsupported') {\n return (\n <Typography variant=\"body2\" color=\"textSecondary\">\n {item.section.message || 'No evidence returned.'}\n </Typography>\n );\n }\n\n const names = namedRecords(item.section.data);\n return (\n <Box mt={0.5}>\n {statusFrom(item.section.data) && (\n <StatusChip status={statusFrom(item.section.data)!} />\n )}\n <GenericFacts data={item.section.data} />\n <NamedResources names={names} />\n </Box>\n );\n};\n\nconst EventHeading = ({\n event,\n fallbackLabel = 'Change recorded',\n}: {\n event: ReturnType<typeof eventFrom>;\n fallbackLabel?: string;\n}) => (\n <Box>\n <Box display=\"flex\" flexWrap=\"wrap\" alignItems=\"center\" gridGap={8}>\n <Typography variant=\"subtitle2\">{event.type || fallbackLabel}</Typography>\n {event.status && <StatusChip status={event.status} />}\n </Box>\n {event.target && <Typography variant=\"body2\">{event.target}</Typography>}\n {event.timestamp && (\n <Typography variant=\"caption\" color=\"textSecondary\">\n {formatTimestamp(event.timestamp)}\n </Typography>\n )}\n </Box>\n);\n\nconst StatusChip = ({ status }: { status: StatusSummary }) => (\n <Chip\n size=\"small\"\n variant=\"outlined\"\n color={\n status.tone === 'success'\n ? 'primary'\n : status.tone === 'warning' || status.tone === 'error'\n ? 'secondary'\n : 'default'\n }\n label={status.label}\n />\n);\n\nconst FactGrid = ({ facts }: { facts: Fact[] }) => (\n <Grid component=\"dl\" container spacing={1} style={{ margin: 0 }}>\n {facts.map(fact => (\n <Grid\n item\n xs={fact.label === 'Summary' ? 12 : 6}\n sm={fact.label === 'Summary' ? 12 : 4}\n key={`${fact.label}-${fact.value}`}\n >\n <Typography component=\"dt\" variant=\"caption\" color=\"textSecondary\">\n {fact.label}\n </Typography>\n <Typography component=\"dd\" variant=\"body2\" style={{ margin: 0 }}>\n {fact.value}\n </Typography>\n </Grid>\n ))}\n </Grid>\n);\n\nconst NamedResources = ({ names }: { names: string[] }) =>\n names.length > 0 ? (\n <Box display=\"flex\" flexWrap=\"wrap\" gridGap={6} mt={1}>\n {names.slice(0, 20).map(name => (\n <Chip key={name} size=\"small\" label={name} />\n ))}\n </Box>\n ) : null;\n\nfunction namedRecords(value: unknown): string[] {\n return [\n ...new Set(\n recordsFrom(value)\n .map(record => readText(record, ['name', 'target', 'resource', 'id']))\n .filter((name): name is string => Boolean(name)),\n ),\n ].slice(0, 20);\n}\n\nfunction numberFrom(value: unknown, keys: string[]): number | undefined {\n if (!isRecord(value)) return undefined;\n for (const key of keys) {\n if (typeof value[key] === 'number') return value[key];\n }\n return undefined;\n}\n\nfunction factKey(fact: Fact): string {\n return fact.label.replace(/\\s+/g, '').toLocaleLowerCase();\n}\n\nfunction eventKey(record: Record<string, unknown>, index: number): string {\n const identity =\n readText(record, ['id', 'ts', 'timestamp', 'time']) ?? 'event';\n return `${identity}-${index}`;\n}\n\nfunction formatTimestamp(value: string): string {\n const timestamp = Date.parse(value);\n return Number.isNaN(timestamp) ? value : new Date(timestamp).toLocaleString();\n}\n\nfunction architectureFrom(value: unknown): ArchitectureGraph {\n if (!isRecord(value)) return { nodes: [], edges: [] };\n const nodeValues = Array.isArray(value.nodes)\n ? value.nodes.filter(isRecord)\n : [];\n const nodes = nodeValues.map((node, index) => {\n const id = readText(node, ['id', 'name']) ?? `node-${index}`;\n const name = readText(node, ['name', 'id']) ?? id;\n return {\n id,\n name,\n type: readText(node, ['type']),\n namespace: readText(node, ['namespace']),\n image: readText(node, ['image']),\n };\n });\n\n const edgeValues = Array.isArray(value.edges)\n ? value.edges.filter(isRecord)\n : [];\n const edges = edgeValues.flatMap(edge => {\n const from = endpointId(edge.from ?? edge.source);\n const to = endpointId(edge.to ?? edge.target);\n if (!from || !to) return [];\n return [\n {\n from,\n to,\n type: readText(edge, ['type', 'label', 'relationship']) ?? 'RELATES_TO',\n },\n ];\n });\n\n return { nodes, edges };\n}\n\nfunction endpointId(value: unknown): string | undefined {\n if (typeof value === 'string') return value;\n if (!isRecord(value)) return undefined;\n return readText(value, ['id', 'name']);\n}\n\nconst Muted = ({ children }: { children: ReactNode }) => (\n <Typography variant=\"body2\" color=\"textSecondary\">\n {children}\n </Typography>\n);\n\nconst Warnings = ({ warnings }: { warnings: string[] }) =>\n warnings.length > 0 ? (\n <Box mt={2}>\n {warnings.map(warning => (\n <Typography key={warning} variant=\"caption\" color=\"textSecondary\">\n {warning}\n </Typography>\n ))}\n </Box>\n ) : null;\n\nfunction textArray(value: unknown): string[] {\n return Array.isArray(value)\n ? value.filter((item): item is string => typeof item === 'string')\n : [];\n}\n\nfunction metricLabel(\n value: unknown,\n singular: string,\n plural: string,\n): string | undefined {\n return typeof value === 'number'\n ? `${value} ${value === 1 ? singular : plural}`\n : undefined;\n}\n\nfunction readableStatus(value: unknown): string {\n if (typeof value !== 'string' || !value) return 'Not resolved';\n return value.charAt(0).toUpperCase() + value.slice(1).replace(/_/g, ' ');\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SectionPresenters.esm.js","sources":["../../../src/components/entity/SectionPresenters.tsx"],"sourcesContent":["import {\n Box,\n Button,\n ButtonGroup,\n Chip,\n Divider,\n Grid,\n Typography,\n} from '@material-ui/core';\nimport type { ReactNode } from 'react';\nimport { useState } from 'react';\nimport { EntityRefLink } from '@backstage/plugin-catalog-react';\nimport type {\n EntityImpact,\n SafeguardResult,\n WhyNowAssessment,\n} from '../../api/types';\nimport { ArchitectureDiagram } from './MermaidArchitecture';\nimport { architectureGraphFrom } from './architectureGraph';\nimport { EvidenceDisclosure } from './EvidenceDisclosure';\nimport {\n eventFrom,\n factsFrom,\n firstRecordFrom,\n isRecord,\n readText,\n recordsFrom,\n statusFrom,\n type Fact,\n type StatusSummary,\n} from './sectionData';\n\nconst SAFEGUARD_LABELS: Record<SafeguardResult['capability'], string> = {\n pdb: 'Pod disruption budget',\n scaling: 'Scaling',\n priority: 'Priority',\n storage: 'Storage',\n};\n\nconst OVERVIEW_SIGNALS = [\n ['callerCount', 'Direct callers'],\n ['calleeCount', 'Direct callees'],\n ['downstreamServiceCount', 'Downstream services'],\n ['datastoreCount', 'Datastores'],\n ['externalCount', 'External systems'],\n ['eventCount24h', 'Changes · 24h'],\n] as const;\n\nexport const OverviewPresenter = ({ data }: { data: unknown }) => {\n const value = isRecord(data) ? data : {};\n return (\n <>\n <Grid container spacing={2} aria-label=\"Service signals\">\n {OVERVIEW_SIGNALS.map(([key, label]) => (\n <Grid item xs={6} sm={4} md={2} key={key}>\n <Typography variant=\"h5\">\n {typeof value[key] === 'number' ? String(value[key]) : 'N/A'}\n </Typography>\n <Typography variant=\"caption\" color=\"textSecondary\">\n {label}\n </Typography>\n </Grid>\n ))}\n <Grid item xs={6} sm={4} md={2}>\n <Typography variant=\"subtitle1\">\n {readableStatus(value.sloStatus)}\n </Typography>\n <Typography variant=\"caption\" color=\"textSecondary\">\n Service level\n </Typography>\n </Grid>\n <Grid item xs={6} sm={4} md={2}>\n <Typography variant=\"subtitle1\">\n {typeof value.activeAlertCount === 'number'\n ? `${value.activeAlertCount} active`\n : 'N/A'}\n </Typography>\n <Typography variant=\"caption\" color=\"textSecondary\">\n Alerts\n </Typography>\n </Grid>\n </Grid>\n <EvidenceDisclosure data={data} />\n </>\n );\n};\n\nexport const DependencyFootprintPresenter = ({ data }: { data: unknown }) => {\n const root = isRecord(data) ? data : {};\n const serviceTree = isRecord(root.serviceTree) ? root.serviceTree : {};\n const tree = isRecord(serviceTree.target) ? serviceTree.target : {};\n const calls = isRecord(root.calls) ? root.calls : {};\n const direct = isRecord(calls.target) ? calls.target : {};\n const callers = textArray(direct.callers);\n const callees = textArray(direct.callees);\n const configuration = isRecord(root.configuration) ? root.configuration : {};\n const configuredNodes = new Map(\n recordsFrom(configuration.nodes).flatMap(node => {\n const id = readText(node, ['id']);\n const name = readText(node, ['name']);\n return id && name ? [[id, name] as const] : [];\n }),\n );\n const configuredEdges = recordsFrom(configuration.edges);\n const configuredCallers = configuredEdges.flatMap(edge => {\n const from = readText(edge, ['from']);\n const to = readText(edge, ['to']);\n return from && to && !to.startsWith('configured:')\n ? [configuredNodes.get(from) ?? from]\n : [];\n });\n const configuredCallees = configuredEdges.flatMap(edge => {\n const to = readText(edge, ['to']);\n return to?.startsWith('configured:')\n ? [configuredNodes.get(to) ?? to.slice('configured:'.length)]\n : [];\n });\n const footprint = [\n metricLabel(tree.serviceCount, 'service', 'services'),\n metricLabel(tree.datastoreCount, 'datastore', 'datastores'),\n metricLabel(tree.externalCount, 'external', 'externals'),\n ].filter((value): value is string => Boolean(value));\n\n return (\n <>\n {tree.hasCycle === true && (\n <Box mb={2}>\n <Chip\n size=\"small\"\n variant=\"outlined\"\n label=\"Dependency cycle detected\"\n />\n </Box>\n )}\n <Grid container spacing={3}>\n <Grid item xs={12} md={6}>\n <Typography variant=\"overline\" color=\"textSecondary\">\n Called by\n </Typography>\n <NamedResources names={callers} />\n {callers.length === 0 && <Muted>Not resolved</Muted>}\n </Grid>\n <Grid item xs={12} md={6}>\n <Typography variant=\"overline\" color=\"textSecondary\">\n Calls\n </Typography>\n <NamedResources names={callees} />\n {callees.length === 0 && <Muted>Not resolved</Muted>}\n </Grid>\n </Grid>\n {footprint.length > 0 && (\n <Box display=\"flex\" flexWrap=\"wrap\" gridGap={8} mt={2}>\n {footprint.map(item => (\n <Chip key={item} size=\"small\" variant=\"outlined\" label={item} />\n ))}\n </Box>\n )}\n {(configuredCallers.length > 0 || configuredCallees.length > 0) && (\n <Box mt={2}>\n <Chip size=\"small\" color=\"primary\" label=\"Configured evidence\" />\n <Grid container spacing={3}>\n <Grid item xs={12} md={6}>\n <Typography variant=\"overline\" color=\"textSecondary\">\n Configured callers\n </Typography>\n <NamedResources names={configuredCallers} />\n </Grid>\n <Grid item xs={12} md={6}>\n <Typography variant=\"overline\" color=\"textSecondary\">\n Configured dependencies\n </Typography>\n <NamedResources names={configuredCallees} />\n </Grid>\n </Grid>\n </Box>\n )}\n <EvidenceDisclosure data={data} />\n </>\n );\n};\n\nexport const OperationalPosturePresenter = ({ data }: { data: unknown }) => {\n const root = isRecord(data) ? data : {};\n const slo = isRecord(root.slo) ? root.slo : {};\n const sloTarget = isRecord(slo.target) ? slo.target : {};\n const alerts = isRecord(root.alerts) ? root.alerts : {};\n const deployImpact = isRecord(root.deployImpact) ? root.deployImpact : {};\n const gitops = isRecord(root.gitops) ? root.gitops : {};\n const owner = isRecord(gitops.owner) ? gitops.owner : {};\n const alertCause = isRecord(root.alertCause) ? root.alertCause : {};\n const changes = Array.isArray(alertCause.changes)\n ? alertCause.changes.length\n : undefined;\n const findings = [\n {\n label: sloTarget.status\n ? `${readableStatus(sloTarget.status)} SLO`\n : 'SLO not resolved',\n detail: readText(sloTarget, ['name']),\n },\n {\n label:\n alerts.total === 0\n ? 'No active alerts'\n : typeof alerts.total === 'number'\n ? `${alerts.total} active alerts`\n : 'Alerts not resolved',\n },\n {\n label:\n typeof deployImpact.rollouts === 'number'\n ? `${deployImpact.rollouts} rollouts · ${\n typeof deployImpact.total === 'number'\n ? deployImpact.total\n : 'N/A'\n } correlated failures`\n : 'Deployment impact not resolved',\n },\n {\n label: owner.application ? String(owner.application) : 'No GitOps owner',\n },\n {\n label:\n changes === undefined\n ? 'Recent cause not resolved'\n : `${changes} recent correlated ${\n changes === 1 ? 'change' : 'changes'\n }`,\n },\n ];\n\n return (\n <>\n <Box component=\"ul\" m={0} p={0} aria-label=\"Operational findings\">\n {findings.map((finding, index) => (\n <Box component=\"li\" key={finding.label} style={{ listStyle: 'none' }}>\n {index > 0 && <Divider />}\n <Box py={1}>\n <Typography variant=\"subtitle2\">{finding.label}</Typography>\n {finding.detail && <Muted>{finding.detail}</Muted>}\n </Box>\n </Box>\n ))}\n </Box>\n <EvidenceDisclosure data={data} />\n </>\n );\n};\n\nconst WHY_NOW_LABELS: Record<WhyNowAssessment['verdict'], string> = {\n deployment_correlated: 'Deployment correlated',\n runtime_cause_suspected: 'Runtime cause suspected',\n active_alerts: 'Active alerts',\n clear: 'No active alerts',\n insufficient_evidence: 'Insufficient evidence',\n};\n\nexport const WhyNowPresenter = ({ data }: { data: WhyNowAssessment }) => (\n <>\n <Box display=\"flex\" flexWrap=\"wrap\" alignItems=\"center\" gridGap={8} mb={1}>\n <Chip\n size=\"small\"\n color={data.verdict === 'clear' ? 'primary' : 'default'}\n label={WHY_NOW_LABELS[data.verdict]}\n />\n <Typography variant=\"subtitle1\">{data.headline}</Typography>\n </Box>\n <Grid container spacing={2}>\n <Grid item xs={12} md={4}>\n <Typography variant=\"overline\" color=\"textSecondary\">\n Current condition\n </Typography>\n <Typography variant=\"body2\">\n {typeof data.activeAlerts === 'number'\n ? `${data.activeAlerts} active ${\n data.activeAlerts === 1 ? 'alert' : 'alerts'\n }`\n : 'Alert evidence unavailable'}\n </Typography>\n {data.firingMonitors.length > 0 && (\n <NamedResources names={data.firingMonitors} />\n )}\n </Grid>\n <Grid item xs={12} md={4}>\n <Typography variant=\"overline\" color=\"textSecondary\">\n Runtime suspects · {data.evidence.runtimeWindow}\n </Typography>\n {data.suspectedChanges.length > 0 ? (\n <Box component=\"ul\" m={0} pl={2}>\n {data.suspectedChanges.map((change, index) => (\n <li key={`${change.timestamp || change.type}-${index}`}>\n <Typography variant=\"body2\">\n {change.summary || 'No graph summary was provided.'}\n </Typography>\n <Muted>{readableStatus(change.type)}</Muted>\n </li>\n ))}\n </Box>\n ) : (\n <Muted>No recent runtime suspect was resolved.</Muted>\n )}\n </Grid>\n <Grid item xs={12} md={4}>\n <Typography variant=\"overline\" color=\"textSecondary\">\n Deployment correlation · {data.evidence.deploymentWindow}\n </Typography>\n <Typography variant=\"body2\">\n {typeof data.deployment.rollouts === 'number'\n ? `${data.deployment.rollouts} ${\n data.deployment.rollouts === 1 ? 'rollout' : 'rollouts'\n } · ${\n typeof data.deployment.correlatedFailures === 'number'\n ? data.deployment.correlatedFailures\n : 'N/A'\n } correlated failures`\n : 'Deployment evidence unavailable'}\n </Typography>\n </Grid>\n </Grid>\n <Warnings warnings={data.warnings} />\n </>\n);\n\nconst IMPACT_METRICS = [\n ['affectedWorkloads', 'Affected workloads'],\n ['downstreamServices', 'Downstream services'],\n ['datastores', 'Datastores'],\n ['externalDependencies', 'External dependencies'],\n] as const;\n\nexport const AffectedFootprintPresenter = ({\n data,\n}: {\n data: EntityImpact;\n}) => (\n <>\n <Grid container spacing={2}>\n {IMPACT_METRICS.map(([key, label]) => (\n <Grid item xs={6} key={key}>\n <Typography variant=\"h5\">\n {typeof data[key] === 'number' ? data[key] : 'N/A'}\n </Typography>\n <Typography variant=\"caption\" color=\"textSecondary\">\n {label}\n </Typography>\n </Grid>\n ))}\n </Grid>\n <Box display=\"flex\" flexWrap=\"wrap\" gridGap={8} mt={2}>\n <Chip\n size=\"small\"\n variant=\"outlined\"\n label={`${data.monitorCount ?? 'N/A'} monitors`}\n />\n <Chip\n size=\"small\"\n variant=\"outlined\"\n label={`${data.sloCount ?? 'N/A'} SLOs`}\n />\n </Box>\n {data.relatedEntities.length > 0 && (\n <Box mt={2}>\n <Typography variant=\"overline\" color=\"textSecondary\">\n Related catalog entities\n </Typography>\n <Box display=\"flex\" flexDirection=\"column\" gridGap={4}>\n {data.relatedEntities.map(entity => (\n <EntityRefLink\n key={entity.entityRef}\n entityRef={entity.entityRef}\n title={entity.name}\n />\n ))}\n </Box>\n </Box>\n )}\n <Warnings warnings={data.warnings} />\n </>\n);\n\nexport const ImpactPresenter = ({\n data,\n showEvidence = true,\n summaryMetric,\n}: {\n data: unknown;\n showEvidence?: boolean;\n summaryMetric?: false | { label: string; total: number };\n}) => {\n const affected = namedRecords(data);\n const total = numberFrom(data, ['total', 'count', 'affectedCount']);\n const status = statusFrom(data);\n const defaultTotal =\n total ?? (affected.length > 0 ? affected.length : undefined);\n const visibleSummary =\n summaryMetric === false\n ? undefined\n : summaryMetric ??\n (defaultTotal !== undefined\n ? { label: 'Affected resources', total: defaultTotal }\n : undefined);\n\n return (\n <>\n {visibleSummary && (\n <Box mb={2}>\n <Typography variant=\"overline\" color=\"textSecondary\">\n {visibleSummary.label}\n </Typography>\n <Typography variant=\"h5\">{visibleSummary.total}</Typography>\n </Box>\n )}\n {status && <StatusChip status={status} />}\n <GenericFacts data={data} omit={['total', 'count', 'affectedCount']} />\n <NamedResources names={affected} />\n {showEvidence && <EvidenceDisclosure data={data} />}\n </>\n );\n};\n\nexport const LatestChangePresenter = ({ data }: { data: unknown }) => {\n const record = firstRecordFrom(data);\n const event = eventFrom(record);\n if (!record) {\n return <PresenterFallback data={data} />;\n }\n\n return (\n <>\n <EventHeading event={event} />\n <FactGrid facts={event.facts} />\n <EvidenceDisclosure data={data} />\n </>\n );\n};\n\nexport const SafeguardsPresenter = ({ data }: { data: SafeguardResult[] }) => (\n <>\n <Box component=\"ul\" m={0} p={0} aria-label=\"Service safeguards\">\n {data.map((item, index) => (\n <Box component=\"li\" key={item.capability} style={{ listStyle: 'none' }}>\n {index > 0 && <Divider />}\n <Box width=\"100%\" py={1}>\n <Typography variant=\"subtitle2\">\n {SAFEGUARD_LABELS[item.capability]}\n </Typography>\n <SafeguardState item={item} />\n </Box>\n </Box>\n ))}\n </Box>\n <EvidenceDisclosure data={data} />\n </>\n);\n\nexport const TimelinePresenter = ({\n data,\n fallbackLabel = 'Change recorded',\n showEvidence = true,\n}: {\n data: unknown;\n fallbackLabel?: string;\n showEvidence?: boolean;\n}) => {\n const records = recordsFrom(data).slice(0, 10);\n if (records.length === 0) return <PresenterFallback data={data} />;\n\n return (\n <>\n <Box component=\"ol\" m={0} pl={3}>\n {records.map((record, index) => {\n const event = eventFrom(record);\n return (\n <Box component=\"li\" key={eventKey(record, index)} pb={2}>\n <EventHeading event={event} fallbackLabel={fallbackLabel} />\n {event.summary && (\n <Typography variant=\"body2\">{event.summary}</Typography>\n )}\n </Box>\n );\n })}\n </Box>\n {showEvidence && <EvidenceDisclosure data={data} />}\n </>\n );\n};\n\nexport const ArchitecturePresenter = ({ data }: { data: unknown }) => {\n const graph = architectureGraphFrom(data);\n const [view, setView] = useState<'context' | 'runtime'>('context');\n if (graph.nodes.length === 0) {\n return <PresenterFallback data={data} />;\n }\n\n return (\n <>\n <Box display=\"flex\" justifyContent=\"flex-end\" mb={1}>\n <ButtonGroup size=\"small\" aria-label=\"Service map depth\">\n <Button\n type=\"button\"\n aria-pressed={view === 'context'}\n color={view === 'context' ? 'primary' : 'default'}\n onClick={() => setView('context')}\n >\n Service context\n </Button>\n <Button\n type=\"button\"\n aria-pressed={view === 'runtime'}\n color={view === 'runtime' ? 'primary' : 'default'}\n onClick={() => setView('runtime')}\n >\n Runtime detail\n </Button>\n </ButtonGroup>\n </Box>\n <ArchitectureDiagram graph={graph} view={view} />\n <EvidenceDisclosure data={data} />\n </>\n );\n};\n\nexport const GenericFacts = ({\n data,\n omit = [],\n}: {\n data: unknown;\n omit?: string[];\n}) => {\n const omitted = new Set(omit);\n const facts = factsFrom(data).filter(fact => !omitted.has(factKey(fact)));\n if (facts.length === 0) {\n return (\n <Typography variant=\"body2\" color=\"textSecondary\">\n No readable summary is available.\n </Typography>\n );\n }\n return <FactGrid facts={facts} />;\n};\n\nconst PresenterFallback = ({ data }: { data: unknown }) => (\n <>\n <GenericFacts data={data} />\n <EvidenceDisclosure data={data} />\n </>\n);\n\nconst SafeguardState = ({ item }: { item: SafeguardResult }) => {\n if (item.section.state === 'error') {\n return <Typography color=\"error\">{item.section.message}</Typography>;\n }\n if (item.section.state === 'empty' || item.section.state === 'unsupported') {\n return (\n <Typography variant=\"body2\" color=\"textSecondary\">\n {item.section.message || 'No evidence returned.'}\n </Typography>\n );\n }\n\n const names = namedRecords(item.section.data);\n return (\n <Box mt={0.5}>\n {statusFrom(item.section.data) && (\n <StatusChip status={statusFrom(item.section.data)!} />\n )}\n <GenericFacts data={item.section.data} />\n <NamedResources names={names} />\n </Box>\n );\n};\n\nconst EventHeading = ({\n event,\n fallbackLabel = 'Change recorded',\n}: {\n event: ReturnType<typeof eventFrom>;\n fallbackLabel?: string;\n}) => (\n <Box>\n <Box display=\"flex\" flexWrap=\"wrap\" alignItems=\"center\" gridGap={8}>\n <Typography variant=\"subtitle2\">{event.type || fallbackLabel}</Typography>\n {event.status && <StatusChip status={event.status} />}\n </Box>\n {event.target && <Typography variant=\"body2\">{event.target}</Typography>}\n {event.timestamp && (\n <Typography variant=\"caption\" color=\"textSecondary\">\n {formatTimestamp(event.timestamp)}\n </Typography>\n )}\n </Box>\n);\n\nconst StatusChip = ({ status }: { status: StatusSummary }) => (\n <Chip\n size=\"small\"\n variant=\"outlined\"\n color={\n status.tone === 'success'\n ? 'primary'\n : status.tone === 'warning' || status.tone === 'error'\n ? 'secondary'\n : 'default'\n }\n label={status.label}\n />\n);\n\nconst FactGrid = ({ facts }: { facts: Fact[] }) => (\n <Grid component=\"dl\" container spacing={1} style={{ margin: 0 }}>\n {facts.map(fact => (\n <Grid\n item\n xs={fact.label === 'Summary' ? 12 : 6}\n sm={fact.label === 'Summary' ? 12 : 4}\n key={`${fact.label}-${fact.value}`}\n >\n <Typography component=\"dt\" variant=\"caption\" color=\"textSecondary\">\n {fact.label}\n </Typography>\n <Typography component=\"dd\" variant=\"body2\" style={{ margin: 0 }}>\n {fact.value}\n </Typography>\n </Grid>\n ))}\n </Grid>\n);\n\nconst NamedResources = ({ names }: { names: string[] }) =>\n names.length > 0 ? (\n <Box display=\"flex\" flexWrap=\"wrap\" gridGap={6} mt={1}>\n {names.slice(0, 20).map(name => (\n <Chip key={name} size=\"small\" label={name} />\n ))}\n </Box>\n ) : null;\n\nfunction namedRecords(value: unknown): string[] {\n return [\n ...new Set(\n recordsFrom(value)\n .map(record => readText(record, ['name', 'target', 'resource', 'id']))\n .filter((name): name is string => Boolean(name)),\n ),\n ].slice(0, 20);\n}\n\nfunction numberFrom(value: unknown, keys: string[]): number | undefined {\n if (!isRecord(value)) return undefined;\n for (const key of keys) {\n if (typeof value[key] === 'number') return value[key];\n }\n return undefined;\n}\n\nfunction factKey(fact: Fact): string {\n return fact.label.replace(/\\s+/g, '').toLocaleLowerCase();\n}\n\nfunction eventKey(record: Record<string, unknown>, index: number): string {\n const identity =\n readText(record, ['id', 'ts', 'timestamp', 'time']) ?? 'event';\n return `${identity}-${index}`;\n}\n\nfunction formatTimestamp(value: string): string {\n const timestamp = Date.parse(value);\n return Number.isNaN(timestamp) ? value : new Date(timestamp).toLocaleString();\n}\n\nconst Muted = ({ children }: { children: ReactNode }) => (\n <Typography variant=\"body2\" color=\"textSecondary\">\n {children}\n </Typography>\n);\n\nconst Warnings = ({ warnings }: { warnings: string[] }) =>\n warnings.length > 0 ? (\n <Box mt={2}>\n {warnings.map(warning => (\n <Typography key={warning} variant=\"caption\" color=\"textSecondary\">\n {warning}\n </Typography>\n ))}\n </Box>\n ) : null;\n\nfunction textArray(value: unknown): string[] {\n return Array.isArray(value)\n ? value.filter((item): item is string => typeof item === 'string')\n : [];\n}\n\nfunction metricLabel(\n value: unknown,\n singular: string,\n plural: string,\n): string | undefined {\n return typeof value === 'number'\n ? `${value} ${value === 1 ? singular : plural}`\n : undefined;\n}\n\nfunction readableStatus(value: unknown): string {\n if (typeof value !== 'string' || !value) return 'Not resolved';\n return value.charAt(0).toUpperCase() + value.slice(1).replace(/_/g, ' ');\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { uniqueOperationCount, architectureEdgeKey, mergeOperationSources } from './architectureGraph.esm.js';
|
|
2
|
+
|
|
1
3
|
const RUNTIME_INSTANCE_TYPES = /* @__PURE__ */ new Set(["K8S_REPLICASET", "K8S_POD"]);
|
|
2
4
|
const MAX_DIRECT_DEPENDENCIES = 5;
|
|
3
5
|
function buildArchitectureDiagram(graph, options = {}) {
|
|
@@ -11,6 +13,7 @@ function buildArchitectureDiagram(graph, options = {}) {
|
|
|
11
13
|
compact.nodes.map((node) => [node.id, readableNodeLabel(node)])
|
|
12
14
|
);
|
|
13
15
|
const lines = ["flowchart LR"];
|
|
16
|
+
const relationships = [];
|
|
14
17
|
compact.nodes.forEach((node) => {
|
|
15
18
|
const id = nodeIds.get(node.id);
|
|
16
19
|
const label = mermaidNodeLabel(node);
|
|
@@ -25,9 +28,22 @@ function buildArchitectureDiagram(graph, options = {}) {
|
|
|
25
28
|
compact.edges.forEach((edge) => {
|
|
26
29
|
const from = nodeIds.get(edge.from);
|
|
27
30
|
const to = nodeIds.get(edge.to);
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
+
const fromLabel = names.get(edge.from);
|
|
32
|
+
const toLabel = names.get(edge.to);
|
|
33
|
+
if (!from || !to || !fromLabel || !toLabel) return;
|
|
34
|
+
const operationCount = edge.synthetic ? 0 : uniqueOperationCount(edge.operationSources);
|
|
35
|
+
const edgeLabel = operationCount > 0 ? `${edge.type} \xB7 HTTP \xB7 ${operationCount}` : edge.type;
|
|
36
|
+
lines.push(` ${from} -->|${sanitize(edgeLabel)}| ${to}`);
|
|
37
|
+
relationships.push({
|
|
38
|
+
id: architectureEdgeKey(edge),
|
|
39
|
+
diagramIndex: relationships.length,
|
|
40
|
+
label: `${fromLabel} \u2192 ${readableRelationship(edge.type)} \u2192 ${toLabel}`,
|
|
41
|
+
fromLabel,
|
|
42
|
+
toLabel,
|
|
43
|
+
type: edge.type,
|
|
44
|
+
operationCount,
|
|
45
|
+
operationSources: operationCount > 0 ? edge.operationSources ?? [] : []
|
|
46
|
+
});
|
|
31
47
|
});
|
|
32
48
|
lines.push(
|
|
33
49
|
" classDef service fill:#e8f0fe,stroke:#1967d2,color:#174ea6",
|
|
@@ -40,11 +56,8 @@ function buildArchitectureDiagram(graph, options = {}) {
|
|
|
40
56
|
});
|
|
41
57
|
return {
|
|
42
58
|
source: lines.join("\n"),
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const to = names.get(edge.to);
|
|
46
|
-
return from && to ? [`${from} \u2192 ${readableRelationship(edge.type)} \u2192 ${to}`] : [];
|
|
47
|
-
})
|
|
59
|
+
relationships,
|
|
60
|
+
fallbackRelationships: relationships.map((item) => item.label)
|
|
48
61
|
};
|
|
49
62
|
}
|
|
50
63
|
function serviceContextGraph(graph) {
|
|
@@ -86,7 +99,19 @@ function compactArchitectureGraph(graph) {
|
|
|
86
99
|
if (!targetId || sourceId === targetId) return;
|
|
87
100
|
const type = target.collapsed ? "RUNS" : target.edgeType;
|
|
88
101
|
const key = `${sourceId}|${type}|${targetId}`;
|
|
89
|
-
compactEdges.
|
|
102
|
+
const existing = compactEdges.get(key);
|
|
103
|
+
const synthetic = existing?.synthetic || target.synthetic;
|
|
104
|
+
const operationSources = synthetic ? [] : mergeOperationSources(
|
|
105
|
+
existing?.operationSources,
|
|
106
|
+
target.collapsed ? void 0 : target.operationSources
|
|
107
|
+
);
|
|
108
|
+
compactEdges.set(key, {
|
|
109
|
+
from: sourceId,
|
|
110
|
+
to: targetId,
|
|
111
|
+
type,
|
|
112
|
+
...synthetic ? { synthetic: true } : {},
|
|
113
|
+
...operationSources.length > 0 ? { operationSources } : {}
|
|
114
|
+
});
|
|
90
115
|
});
|
|
91
116
|
});
|
|
92
117
|
return {
|
|
@@ -135,7 +160,7 @@ function summarizeDirectDependencies(graph) {
|
|
|
135
160
|
});
|
|
136
161
|
edges.push(...visible);
|
|
137
162
|
edges.push(
|
|
138
|
-
direction === "out" ? { from: root, to: aggregateId, type: sample.type } : { from: aggregateId, to: root, type: sample.type }
|
|
163
|
+
direction === "out" ? { from: root, to: aggregateId, type: sample.type, synthetic: true } : { from: aggregateId, to: root, type: sample.type, synthetic: true }
|
|
139
164
|
);
|
|
140
165
|
});
|
|
141
166
|
const referenced = new Set(edges.flatMap((edge) => [edge.from, edge.to]));
|
|
@@ -152,22 +177,30 @@ function walkToVisibleTargets(start, outgoing, nodeById) {
|
|
|
152
177
|
const queue = (outgoing.get(start) ?? []).map((edge) => ({
|
|
153
178
|
id: edge.to,
|
|
154
179
|
edgeType: edge.type,
|
|
155
|
-
collapsed: false
|
|
180
|
+
collapsed: false,
|
|
181
|
+
operationSources: edge.operationSources,
|
|
182
|
+
synthetic: edge.synthetic
|
|
156
183
|
}));
|
|
157
184
|
const visited = /* @__PURE__ */ new Set();
|
|
158
185
|
while (queue.length > 0) {
|
|
159
186
|
const current = queue.shift();
|
|
160
|
-
const visitKey = `${current.id}|${current.collapsed}`;
|
|
161
|
-
if (visited.has(visitKey)) continue;
|
|
162
|
-
visited.add(visitKey);
|
|
163
187
|
const node = nodeById.get(current.id);
|
|
164
188
|
if (!node) continue;
|
|
165
189
|
if (!isRuntimeInstance(node)) {
|
|
166
190
|
targets.push({ node, ...current });
|
|
167
191
|
continue;
|
|
168
192
|
}
|
|
193
|
+
const visitKey = `${current.id}|${current.collapsed}`;
|
|
194
|
+
if (visited.has(visitKey)) continue;
|
|
195
|
+
visited.add(visitKey);
|
|
169
196
|
(outgoing.get(current.id) ?? []).forEach((edge) => {
|
|
170
|
-
queue.push({
|
|
197
|
+
queue.push({
|
|
198
|
+
id: edge.to,
|
|
199
|
+
edgeType: edge.type,
|
|
200
|
+
collapsed: true,
|
|
201
|
+
operationSources: void 0,
|
|
202
|
+
synthetic: void 0
|
|
203
|
+
});
|
|
171
204
|
});
|
|
172
205
|
}
|
|
173
206
|
return targets;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"architectureDiagram.esm.js","sources":["../../../src/components/entity/architectureDiagram.ts"],"sourcesContent":["export interface ArchitectureNode {\n id: string;\n name: string;\n type?: string | null;\n namespace?: string | null;\n image?: string | null;\n}\n\nexport interface ArchitectureEdge {\n from: string;\n to: string;\n type: string;\n}\n\nexport interface ArchitectureGraph {\n nodes: ArchitectureNode[];\n edges: ArchitectureEdge[];\n}\n\nexport interface ArchitectureDiagramDefinition {\n source: string;\n fallbackRelationships: string[];\n}\n\ninterface CompactGraph {\n nodes: ArchitectureNode[];\n edges: ArchitectureEdge[];\n}\n\nconst RUNTIME_INSTANCE_TYPES = new Set(['K8S_REPLICASET', 'K8S_POD']);\nconst MAX_DIRECT_DEPENDENCIES = 5;\n\nexport function buildArchitectureDiagram(\n graph: ArchitectureGraph,\n options: { view?: 'context' | 'runtime' } = {},\n): ArchitectureDiagramDefinition {\n const base = compactArchitectureGraph(graph);\n const viewed = options.view === 'context' ? serviceContextGraph(base) : base;\n const compact = summarizeDirectDependencies(viewed);\n const nodeIds = new Map(\n compact.nodes.map((node, index) => [node.id, `n${index}`]),\n );\n const names = new Map(\n compact.nodes.map(node => [node.id, readableNodeLabel(node)]),\n );\n const lines = ['flowchart LR'];\n\n compact.nodes.forEach(node => {\n const id = nodeIds.get(node.id)!;\n const label = mermaidNodeLabel(node);\n if (node.type === 'DATADOG_DATASTORE') {\n lines.push(` ${id}[(\"${label}\")]`);\n } else if (\n node.type === 'DATADOG_EXTERNAL' ||\n node.type === 'DATADOG_DESTINATION'\n ) {\n lines.push(` ${id}([\"${label}\"])`);\n } else {\n lines.push(` ${id}[\"${label}\"]`);\n }\n });\n\n compact.edges.forEach(edge => {\n const from = nodeIds.get(edge.from);\n const to = nodeIds.get(edge.to);\n if (from && to) {\n lines.push(` ${from} -->|${sanitize(edge.type)}| ${to}`);\n }\n });\n\n lines.push(\n ' classDef service fill:#e8f0fe,stroke:#1967d2,color:#174ea6',\n ' classDef runtime fill:#e6f4ea,stroke:#188038,color:#137333',\n ' classDef dependency fill:#fef7e0,stroke:#f9ab00,color:#7a4f01',\n );\n compact.nodes.forEach(node => {\n const id = nodeIds.get(node.id)!;\n lines.push(` class ${id} ${className(node)}`);\n });\n\n return {\n source: lines.join('\\n'),\n fallbackRelationships: compact.edges.flatMap(edge => {\n const from = names.get(edge.from);\n const to = names.get(edge.to);\n return from && to\n ? [`${from} → ${readableRelationship(edge.type)} → ${to}`]\n : [];\n }),\n };\n}\n\nfunction serviceContextGraph(graph: CompactGraph): CompactGraph {\n const nodes = graph.nodes.filter(node => node.type !== 'K8S_CONTAINER');\n const visible = new Set(nodes.map(node => node.id));\n return {\n nodes,\n edges: graph.edges.filter(\n edge => visible.has(edge.from) && visible.has(edge.to),\n ),\n };\n}\n\nfunction compactArchitectureGraph(graph: ArchitectureGraph): CompactGraph {\n const nodeById = new Map(graph.nodes.map(node => [node.id, node]));\n const visibleNodes = graph.nodes\n .filter(node => !isRuntimeInstance(node))\n .map(normalizeNode);\n const canonicalNodes = new Map<string, ArchitectureNode>();\n const canonicalId = new Map<string, string>();\n\n visibleNodes.forEach(node => {\n const key = semanticNodeKey(node);\n const existing = canonicalNodes.get(key);\n if (existing) {\n canonicalId.set(node.id, existing.id);\n } else {\n canonicalNodes.set(key, node);\n canonicalId.set(node.id, node.id);\n }\n });\n\n const outgoing = new Map<string, ArchitectureEdge[]>();\n graph.edges.forEach(edge => {\n const list = outgoing.get(edge.from) ?? [];\n list.push(edge);\n outgoing.set(edge.from, list);\n });\n\n const compactEdges = new Map<string, ArchitectureEdge>();\n visibleNodes.forEach(source => {\n const sourceId = canonicalId.get(source.id)!;\n walkToVisibleTargets(source.id, outgoing, nodeById).forEach(target => {\n const targetId = canonicalId.get(target.node.id);\n if (!targetId || sourceId === targetId) return;\n const type = target.collapsed ? 'RUNS' : target.edgeType;\n const key = `${sourceId}|${type}|${targetId}`;\n compactEdges.set(key, { from: sourceId, to: targetId, type });\n });\n });\n\n return {\n nodes: [...canonicalNodes.values()],\n edges: [...compactEdges.values()],\n };\n}\n\nfunction summarizeDirectDependencies(graph: CompactGraph): CompactGraph {\n const root = graph.edges.find(edge => edge.type === 'RESOLVES_TO')?.from;\n if (!root) return graph;\n\n const nodes = new Map(graph.nodes.map(node => [node.id, node]));\n const groups = new Map<string, ArchitectureEdge[]>();\n const groupedEdges = new Set<ArchitectureEdge>();\n\n graph.edges.forEach(edge => {\n if (edge.type === 'RESOLVES_TO') return;\n let neighborId: string | undefined;\n if (edge.from === root) neighborId = edge.to;\n if (edge.to === root) neighborId = edge.from;\n if (!neighborId) return;\n const neighbor = nodes.get(neighborId);\n if (!neighbor || neighbor.type?.startsWith('K8S_')) return;\n const direction = edge.from === root ? 'out' : 'in';\n const key = `${direction}|${edge.type}|${neighbor.type ?? ''}`;\n const group = groups.get(key) ?? [];\n group.push(edge);\n groups.set(key, group);\n groupedEdges.add(edge);\n });\n\n const edges = graph.edges.filter(edge => !groupedEdges.has(edge));\n const aggregateNodes: ArchitectureNode[] = [];\n groups.forEach((group, key) => {\n if (group.length <= MAX_DIRECT_DEPENDENCIES) {\n edges.push(...group);\n return;\n }\n\n const visible = group.slice(0, MAX_DIRECT_DEPENDENCIES - 1);\n const hidden = group.slice(MAX_DIRECT_DEPENDENCIES - 1);\n const sample = group[0];\n const direction = sample.from === root ? 'out' : 'in';\n const neighbor = nodes.get(direction === 'out' ? sample.to : sample.from)!;\n const aggregateId = `aggregate-${key.replace(/[^A-Za-z0-9]/g, '-')}`;\n aggregateNodes.push({\n id: aggregateId,\n name: `${hidden.length} more ${pluralType(neighbor.type)}`,\n type: neighbor.type,\n });\n edges.push(...visible);\n edges.push(\n direction === 'out'\n ? { from: root, to: aggregateId, type: sample.type }\n : { from: aggregateId, to: root, type: sample.type },\n );\n });\n\n const referenced = new Set(edges.flatMap(edge => [edge.from, edge.to]));\n return {\n nodes: [\n ...graph.nodes.filter(node => referenced.has(node.id)),\n ...aggregateNodes,\n ],\n edges,\n };\n}\n\nfunction walkToVisibleTargets(\n start: string,\n outgoing: Map<string, ArchitectureEdge[]>,\n nodeById: Map<string, ArchitectureNode>,\n): Array<{\n node: ArchitectureNode;\n edgeType: string;\n collapsed: boolean;\n}> {\n const targets: Array<{\n node: ArchitectureNode;\n edgeType: string;\n collapsed: boolean;\n }> = [];\n const queue = (outgoing.get(start) ?? []).map(edge => ({\n id: edge.to,\n edgeType: edge.type,\n collapsed: false,\n }));\n const visited = new Set<string>();\n\n while (queue.length > 0) {\n const current = queue.shift()!;\n const visitKey = `${current.id}|${current.collapsed}`;\n if (visited.has(visitKey)) continue;\n visited.add(visitKey);\n\n const node = nodeById.get(current.id);\n if (!node) continue;\n if (!isRuntimeInstance(node)) {\n targets.push({ node, ...current });\n continue;\n }\n\n (outgoing.get(current.id) ?? []).forEach(edge => {\n queue.push({ id: edge.to, edgeType: edge.type, collapsed: true });\n });\n }\n\n return targets;\n}\n\nfunction isRuntimeInstance(node: ArchitectureNode): boolean {\n return RUNTIME_INSTANCE_TYPES.has(node.type ?? '');\n}\n\nfunction normalizeNode(node: ArchitectureNode): ArchitectureNode {\n if (node.type !== 'K8S_CONTAINER') return node;\n const slash = node.name.lastIndexOf('/');\n return {\n ...node,\n name: slash >= 0 ? node.name.slice(slash + 1) : node.name,\n image: node.image ? imageRepository(node.image) : node.image,\n };\n}\n\nfunction imageRepository(image: string): string {\n const withoutDigest = image.split('@', 1)[0];\n const slash = withoutDigest.lastIndexOf('/');\n const tag = withoutDigest.lastIndexOf(':');\n const repository = tag > slash ? withoutDigest.slice(0, tag) : withoutDigest;\n return repository.slice(repository.lastIndexOf('/') + 1);\n}\n\nfunction semanticNodeKey(node: ArchitectureNode): string {\n return [\n node.type ?? '',\n node.namespace ?? '',\n node.name,\n node.image ?? '',\n ].join('|');\n}\n\nfunction readableNodeLabel(node: ArchitectureNode): string {\n const type = shortType(node.type);\n const typed = type ? `${node.name} [${type}]` : node.name;\n return node.type?.startsWith('K8S_') && node.namespace\n ? `${typed} (${node.namespace})`\n : typed;\n}\n\nfunction mermaidNodeLabel(node: ArchitectureNode): string {\n const parts = [sanitize(node.name)];\n const type = shortType(node.type);\n if (type) parts.push(`[${type}]`);\n if (node.type?.startsWith('K8S_') && node.namespace) {\n parts.push(`namespace: ${sanitize(node.namespace)}`);\n }\n if (node.image) parts.push(sanitize(node.image));\n return parts.join('<br/>');\n}\n\nfunction shortType(type?: string | null): string {\n return (type ?? '').replace(/^K8S_|^DATADOG_/, '');\n}\n\nfunction pluralType(type?: string | null): string {\n return `${shortType(type).toLocaleLowerCase()}s`;\n}\n\nfunction readableRelationship(type: string): string {\n return type.toLocaleLowerCase().replace(/_/g, ' ');\n}\n\nfunction sanitize(value: string): string {\n return value\n .replace(/\"/g, \"'\")\n .replace(/[<>|]/g, ' ')\n .replace(/\\s+/g, ' ')\n .trim();\n}\n\nfunction className(node: ArchitectureNode): string {\n if (node.type?.startsWith('K8S_')) return 'runtime';\n if (node.type === 'DATADOG_SERVICE') return 'service';\n return 'dependency';\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"architectureDiagram.esm.js","sources":["../../../src/components/entity/architectureDiagram.ts"],"sourcesContent":["import {\n architectureEdgeKey,\n mergeOperationSources,\n uniqueOperationCount,\n type ArchitectureEdge,\n type ArchitectureGraph,\n type ArchitectureNode,\n type ArchitectureOperationSource,\n} from './architectureGraph';\n\nexport type {\n ArchitectureEdge,\n ArchitectureGraph,\n ArchitectureNode,\n ArchitectureOperationSource,\n} from './architectureGraph';\n\nexport interface ArchitectureDiagramRelationship {\n id: string;\n diagramIndex: number;\n label: string;\n fromLabel: string;\n toLabel: string;\n type: string;\n operationCount: number;\n operationSources: ArchitectureOperationSource[];\n}\n\nexport interface ArchitectureDiagramDefinition {\n source: string;\n relationships: ArchitectureDiagramRelationship[];\n fallbackRelationships: string[];\n}\n\ninterface CompactGraph {\n nodes: ArchitectureNode[];\n edges: ArchitectureEdge[];\n}\n\nconst RUNTIME_INSTANCE_TYPES = new Set(['K8S_REPLICASET', 'K8S_POD']);\nconst MAX_DIRECT_DEPENDENCIES = 5;\n\nexport function buildArchitectureDiagram(\n graph: ArchitectureGraph,\n options: { view?: 'context' | 'runtime' } = {},\n): ArchitectureDiagramDefinition {\n const base = compactArchitectureGraph(graph);\n const viewed = options.view === 'context' ? serviceContextGraph(base) : base;\n const compact = summarizeDirectDependencies(viewed);\n const nodeIds = new Map(\n compact.nodes.map((node, index) => [node.id, `n${index}`]),\n );\n const names = new Map(\n compact.nodes.map(node => [node.id, readableNodeLabel(node)]),\n );\n const lines = ['flowchart LR'];\n const relationships: ArchitectureDiagramRelationship[] = [];\n\n compact.nodes.forEach(node => {\n const id = nodeIds.get(node.id)!;\n const label = mermaidNodeLabel(node);\n if (node.type === 'DATADOG_DATASTORE') {\n lines.push(` ${id}[(\"${label}\")]`);\n } else if (\n node.type === 'DATADOG_EXTERNAL' ||\n node.type === 'DATADOG_DESTINATION'\n ) {\n lines.push(` ${id}([\"${label}\"])`);\n } else {\n lines.push(` ${id}[\"${label}\"]`);\n }\n });\n\n compact.edges.forEach(edge => {\n const from = nodeIds.get(edge.from);\n const to = nodeIds.get(edge.to);\n const fromLabel = names.get(edge.from);\n const toLabel = names.get(edge.to);\n if (!from || !to || !fromLabel || !toLabel) return;\n\n const operationCount = edge.synthetic\n ? 0\n : uniqueOperationCount(edge.operationSources);\n const edgeLabel =\n operationCount > 0\n ? `${edge.type} · HTTP · ${operationCount}`\n : edge.type;\n lines.push(` ${from} -->|${sanitize(edgeLabel)}| ${to}`);\n relationships.push({\n id: architectureEdgeKey(edge),\n diagramIndex: relationships.length,\n label: `${fromLabel} → ${readableRelationship(edge.type)} → ${toLabel}`,\n fromLabel,\n toLabel,\n type: edge.type,\n operationCount,\n operationSources: operationCount > 0 ? edge.operationSources ?? [] : [],\n });\n });\n\n lines.push(\n ' classDef service fill:#e8f0fe,stroke:#1967d2,color:#174ea6',\n ' classDef runtime fill:#e6f4ea,stroke:#188038,color:#137333',\n ' classDef dependency fill:#fef7e0,stroke:#f9ab00,color:#7a4f01',\n );\n compact.nodes.forEach(node => {\n const id = nodeIds.get(node.id)!;\n lines.push(` class ${id} ${className(node)}`);\n });\n\n return {\n source: lines.join('\\n'),\n relationships,\n fallbackRelationships: relationships.map(item => item.label),\n };\n}\n\nfunction serviceContextGraph(graph: CompactGraph): CompactGraph {\n const nodes = graph.nodes.filter(node => node.type !== 'K8S_CONTAINER');\n const visible = new Set(nodes.map(node => node.id));\n return {\n nodes,\n edges: graph.edges.filter(\n edge => visible.has(edge.from) && visible.has(edge.to),\n ),\n };\n}\n\nfunction compactArchitectureGraph(graph: ArchitectureGraph): CompactGraph {\n const nodeById = new Map(graph.nodes.map(node => [node.id, node]));\n const visibleNodes = graph.nodes\n .filter(node => !isRuntimeInstance(node))\n .map(normalizeNode);\n const canonicalNodes = new Map<string, ArchitectureNode>();\n const canonicalId = new Map<string, string>();\n\n visibleNodes.forEach(node => {\n const key = semanticNodeKey(node);\n const existing = canonicalNodes.get(key);\n if (existing) {\n canonicalId.set(node.id, existing.id);\n } else {\n canonicalNodes.set(key, node);\n canonicalId.set(node.id, node.id);\n }\n });\n\n const outgoing = new Map<string, ArchitectureEdge[]>();\n graph.edges.forEach(edge => {\n const list = outgoing.get(edge.from) ?? [];\n list.push(edge);\n outgoing.set(edge.from, list);\n });\n\n const compactEdges = new Map<string, ArchitectureEdge>();\n visibleNodes.forEach(source => {\n const sourceId = canonicalId.get(source.id)!;\n walkToVisibleTargets(source.id, outgoing, nodeById).forEach(target => {\n const targetId = canonicalId.get(target.node.id);\n if (!targetId || sourceId === targetId) return;\n const type = target.collapsed ? 'RUNS' : target.edgeType;\n const key = `${sourceId}|${type}|${targetId}`;\n const existing = compactEdges.get(key);\n const synthetic = existing?.synthetic || target.synthetic;\n const operationSources = synthetic\n ? []\n : mergeOperationSources(\n existing?.operationSources,\n target.collapsed ? undefined : target.operationSources,\n );\n compactEdges.set(key, {\n from: sourceId,\n to: targetId,\n type,\n ...(synthetic ? { synthetic: true } : {}),\n ...(operationSources.length > 0 ? { operationSources } : {}),\n });\n });\n });\n\n return {\n nodes: [...canonicalNodes.values()],\n edges: [...compactEdges.values()],\n };\n}\n\nfunction summarizeDirectDependencies(graph: CompactGraph): CompactGraph {\n const root = graph.edges.find(edge => edge.type === 'RESOLVES_TO')?.from;\n if (!root) return graph;\n\n const nodes = new Map(graph.nodes.map(node => [node.id, node]));\n const groups = new Map<string, ArchitectureEdge[]>();\n const groupedEdges = new Set<ArchitectureEdge>();\n\n graph.edges.forEach(edge => {\n if (edge.type === 'RESOLVES_TO') return;\n let neighborId: string | undefined;\n if (edge.from === root) neighborId = edge.to;\n if (edge.to === root) neighborId = edge.from;\n if (!neighborId) return;\n const neighbor = nodes.get(neighborId);\n if (!neighbor || neighbor.type?.startsWith('K8S_')) return;\n const direction = edge.from === root ? 'out' : 'in';\n const key = `${direction}|${edge.type}|${neighbor.type ?? ''}`;\n const group = groups.get(key) ?? [];\n group.push(edge);\n groups.set(key, group);\n groupedEdges.add(edge);\n });\n\n const edges = graph.edges.filter(edge => !groupedEdges.has(edge));\n const aggregateNodes: ArchitectureNode[] = [];\n groups.forEach((group, key) => {\n if (group.length <= MAX_DIRECT_DEPENDENCIES) {\n edges.push(...group);\n return;\n }\n\n const visible = group.slice(0, MAX_DIRECT_DEPENDENCIES - 1);\n const hidden = group.slice(MAX_DIRECT_DEPENDENCIES - 1);\n const sample = group[0];\n const direction = sample.from === root ? 'out' : 'in';\n const neighbor = nodes.get(direction === 'out' ? sample.to : sample.from)!;\n const aggregateId = `aggregate-${key.replace(/[^A-Za-z0-9]/g, '-')}`;\n aggregateNodes.push({\n id: aggregateId,\n name: `${hidden.length} more ${pluralType(neighbor.type)}`,\n type: neighbor.type,\n });\n edges.push(...visible);\n edges.push(\n direction === 'out'\n ? { from: root, to: aggregateId, type: sample.type, synthetic: true }\n : { from: aggregateId, to: root, type: sample.type, synthetic: true },\n );\n });\n\n const referenced = new Set(edges.flatMap(edge => [edge.from, edge.to]));\n return {\n nodes: [\n ...graph.nodes.filter(node => referenced.has(node.id)),\n ...aggregateNodes,\n ],\n edges,\n };\n}\n\nfunction walkToVisibleTargets(\n start: string,\n outgoing: Map<string, ArchitectureEdge[]>,\n nodeById: Map<string, ArchitectureNode>,\n): Array<{\n node: ArchitectureNode;\n edgeType: string;\n collapsed: boolean;\n operationSources?: ArchitectureOperationSource[];\n synthetic?: boolean;\n}> {\n const targets: Array<{\n node: ArchitectureNode;\n edgeType: string;\n collapsed: boolean;\n operationSources?: ArchitectureOperationSource[];\n synthetic?: boolean;\n }> = [];\n const queue = (outgoing.get(start) ?? []).map(edge => ({\n id: edge.to,\n edgeType: edge.type,\n collapsed: false,\n operationSources: edge.operationSources,\n synthetic: edge.synthetic,\n }));\n const visited = new Set<string>();\n\n while (queue.length > 0) {\n const current = queue.shift()!;\n const node = nodeById.get(current.id);\n if (!node) continue;\n if (!isRuntimeInstance(node)) {\n targets.push({ node, ...current });\n continue;\n }\n\n const visitKey = `${current.id}|${current.collapsed}`;\n if (visited.has(visitKey)) continue;\n visited.add(visitKey);\n\n (outgoing.get(current.id) ?? []).forEach(edge => {\n queue.push({\n id: edge.to,\n edgeType: edge.type,\n collapsed: true,\n operationSources: undefined,\n synthetic: undefined,\n });\n });\n }\n\n return targets;\n}\n\nfunction isRuntimeInstance(node: ArchitectureNode): boolean {\n return RUNTIME_INSTANCE_TYPES.has(node.type ?? '');\n}\n\nfunction normalizeNode(node: ArchitectureNode): ArchitectureNode {\n if (node.type !== 'K8S_CONTAINER') return node;\n const slash = node.name.lastIndexOf('/');\n return {\n ...node,\n name: slash >= 0 ? node.name.slice(slash + 1) : node.name,\n image: node.image ? imageRepository(node.image) : node.image,\n };\n}\n\nfunction imageRepository(image: string): string {\n const withoutDigest = image.split('@', 1)[0];\n const slash = withoutDigest.lastIndexOf('/');\n const tag = withoutDigest.lastIndexOf(':');\n const repository = tag > slash ? withoutDigest.slice(0, tag) : withoutDigest;\n return repository.slice(repository.lastIndexOf('/') + 1);\n}\n\nfunction semanticNodeKey(node: ArchitectureNode): string {\n return [\n node.type ?? '',\n node.namespace ?? '',\n node.name,\n node.image ?? '',\n ].join('|');\n}\n\nfunction readableNodeLabel(node: ArchitectureNode): string {\n const type = shortType(node.type);\n const typed = type ? `${node.name} [${type}]` : node.name;\n return node.type?.startsWith('K8S_') && node.namespace\n ? `${typed} (${node.namespace})`\n : typed;\n}\n\nfunction mermaidNodeLabel(node: ArchitectureNode): string {\n const parts = [sanitize(node.name)];\n const type = shortType(node.type);\n if (type) parts.push(`[${type}]`);\n if (node.type?.startsWith('K8S_') && node.namespace) {\n parts.push(`namespace: ${sanitize(node.namespace)}`);\n }\n if (node.image) parts.push(sanitize(node.image));\n return parts.join('<br/>');\n}\n\nfunction shortType(type?: string | null): string {\n return (type ?? '').replace(/^K8S_|^DATADOG_/, '');\n}\n\nfunction pluralType(type?: string | null): string {\n return `${shortType(type).toLocaleLowerCase()}s`;\n}\n\nfunction readableRelationship(type: string): string {\n return type.toLocaleLowerCase().replace(/_/g, ' ');\n}\n\nfunction sanitize(value: string): string {\n return value\n .replace(/\"/g, \"'\")\n .replace(/[<>|]/g, ' ')\n .replace(/\\s+/g, ' ')\n .trim();\n}\n\nfunction className(node: ArchitectureNode): string {\n if (node.type?.startsWith('K8S_')) return 'runtime';\n if (node.type === 'DATADOG_SERVICE') return 'service';\n return 'dependency';\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
const UNAVAILABLE_APM_SOURCE = "APM source unavailable";
|
|
2
|
+
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3
|
+
const cleanText = (value) => typeof value === "string" && value.trim() ? value.trim() : null;
|
|
4
|
+
const usableTimestamp = (value) => {
|
|
5
|
+
const text = cleanText(value);
|
|
6
|
+
return text && !Number.isNaN(Date.parse(text)) ? text : null;
|
|
7
|
+
};
|
|
8
|
+
const operationKey = (operation) => `${operation.method ?? ""}\0${operation.pathTemplate ?? ""}`;
|
|
9
|
+
const architectureEdgeKey = (edge) => `${edge.from}\0${edge.type}\0${edge.to}`;
|
|
10
|
+
const uniqueOperationCount = (sources) => new Set(
|
|
11
|
+
(sources ?? []).flatMap((source) => source.operations.map(operationKey))
|
|
12
|
+
).size;
|
|
13
|
+
const mergeOperationSources = (left, right) => {
|
|
14
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
15
|
+
[...left ?? [], ...right ?? []].forEach((source) => {
|
|
16
|
+
const displaySource = cleanText(source.source) ?? UNAVAILABLE_APM_SOURCE;
|
|
17
|
+
const key = displaySource.toLowerCase();
|
|
18
|
+
const group = grouped.get(key) ?? {
|
|
19
|
+
source: displaySource,
|
|
20
|
+
operations: /* @__PURE__ */ new Map(),
|
|
21
|
+
hasIncompleteOperations: false
|
|
22
|
+
};
|
|
23
|
+
group.hasIncompleteOperations ||= source.hasIncompleteOperations;
|
|
24
|
+
source.operations.forEach((operation) => {
|
|
25
|
+
const normalized = normalizeOperation(operation);
|
|
26
|
+
if (!normalized) return;
|
|
27
|
+
const normalizedKey = operationKey(normalized);
|
|
28
|
+
const existing = group.operations.get(normalizedKey);
|
|
29
|
+
if (!existing || isNewer(normalized.observedAt, existing.observedAt)) {
|
|
30
|
+
group.operations.set(normalizedKey, normalized);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
grouped.set(key, group);
|
|
34
|
+
});
|
|
35
|
+
return [...grouped.values()].map((group) => ({
|
|
36
|
+
source: group.source,
|
|
37
|
+
operations: [...group.operations.values()].sort(compareOperations),
|
|
38
|
+
hasIncompleteOperations: group.hasIncompleteOperations
|
|
39
|
+
})).sort(
|
|
40
|
+
(leftGroup, rightGroup) => compareText(
|
|
41
|
+
leftGroup.source.toLowerCase(),
|
|
42
|
+
rightGroup.source.toLowerCase()
|
|
43
|
+
)
|
|
44
|
+
);
|
|
45
|
+
};
|
|
46
|
+
const architectureGraphFrom = (value) => {
|
|
47
|
+
if (!isRecord(value)) return { nodes: [], edges: [] };
|
|
48
|
+
const nodes = Array.isArray(value.nodes) ? value.nodes.flatMap((node, index) => architectureNodeFrom(node, index)) : [];
|
|
49
|
+
const edges = Array.isArray(value.edges) ? value.edges.flatMap(architectureEdgeFrom) : [];
|
|
50
|
+
return { nodes, edges };
|
|
51
|
+
};
|
|
52
|
+
function architectureNodeFrom(value, index) {
|
|
53
|
+
if (!isRecord(value)) return [];
|
|
54
|
+
const id = cleanText(value.id) ?? cleanText(value.name) ?? `node-${index}`;
|
|
55
|
+
const name = cleanText(value.name) ?? cleanText(value.id) ?? id;
|
|
56
|
+
return [
|
|
57
|
+
{
|
|
58
|
+
id,
|
|
59
|
+
name,
|
|
60
|
+
type: cleanText(value.type),
|
|
61
|
+
namespace: cleanText(value.namespace),
|
|
62
|
+
image: cleanText(value.image)
|
|
63
|
+
}
|
|
64
|
+
];
|
|
65
|
+
}
|
|
66
|
+
function architectureEdgeFrom(value) {
|
|
67
|
+
if (!isRecord(value)) return [];
|
|
68
|
+
const hasExplicitFrom = Object.prototype.hasOwnProperty.call(value, "from");
|
|
69
|
+
const from = hasExplicitFrom ? endpointId(value.from) : endpointId(value.source);
|
|
70
|
+
const to = endpointId(value.to) ?? endpointId(value.target);
|
|
71
|
+
if (!from || !to) return [];
|
|
72
|
+
const type = cleanText(value.type) ?? cleanText(value.label) ?? cleanText(value.relationship) ?? "RELATES_TO";
|
|
73
|
+
const synthetic = value.synthetic === true;
|
|
74
|
+
const edge = {
|
|
75
|
+
from,
|
|
76
|
+
to,
|
|
77
|
+
type,
|
|
78
|
+
...synthetic ? { synthetic: true } : {}
|
|
79
|
+
};
|
|
80
|
+
const operationSource = synthetic ? null : operationSourceFrom(value, type, hasExplicitFrom);
|
|
81
|
+
if (operationSource) {
|
|
82
|
+
edge.operationSources = mergeOperationSources([operationSource], void 0);
|
|
83
|
+
}
|
|
84
|
+
return [edge];
|
|
85
|
+
}
|
|
86
|
+
function endpointId(value) {
|
|
87
|
+
if (typeof value === "string") return cleanText(value);
|
|
88
|
+
if (!isRecord(value)) return null;
|
|
89
|
+
return cleanText(value.id) ?? cleanText(value.name);
|
|
90
|
+
}
|
|
91
|
+
function operationSourceFrom(edge, type, hasExplicitFrom) {
|
|
92
|
+
if (type !== "CALLS_TO" || !Array.isArray(edge.operations)) return null;
|
|
93
|
+
const observedAt = usableTimestamp(edge.observedAt);
|
|
94
|
+
const operations = [];
|
|
95
|
+
let hasIncompleteOperations = false;
|
|
96
|
+
edge.operations.forEach((value) => {
|
|
97
|
+
if (!isRecord(value)) return;
|
|
98
|
+
if (!isOptionalText(value.method) || !isOptionalText(value.pathTemplate)) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
const method = cleanText(value.method)?.toUpperCase() ?? null;
|
|
102
|
+
const pathTemplate = cleanText(value.pathTemplate) ?? null;
|
|
103
|
+
if (!method && !pathTemplate) {
|
|
104
|
+
hasIncompleteOperations = true;
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
operations.push({ method, pathTemplate, observedAt });
|
|
108
|
+
});
|
|
109
|
+
if (operations.length === 0 && !hasIncompleteOperations) return null;
|
|
110
|
+
const source = hasExplicitFrom ? cleanText(edge.source) ?? UNAVAILABLE_APM_SOURCE : UNAVAILABLE_APM_SOURCE;
|
|
111
|
+
return {
|
|
112
|
+
source,
|
|
113
|
+
operations,
|
|
114
|
+
hasIncompleteOperations
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
function isOptionalText(value) {
|
|
118
|
+
return value === void 0 || value === null || typeof value === "string";
|
|
119
|
+
}
|
|
120
|
+
function normalizeOperation(operation) {
|
|
121
|
+
const method = cleanText(operation.method)?.toUpperCase() ?? null;
|
|
122
|
+
const pathTemplate = cleanText(operation.pathTemplate) ?? null;
|
|
123
|
+
if (!method && !pathTemplate) return null;
|
|
124
|
+
return {
|
|
125
|
+
method,
|
|
126
|
+
pathTemplate,
|
|
127
|
+
observedAt: usableTimestamp(operation.observedAt)
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
function isNewer(candidate, current) {
|
|
131
|
+
if (!candidate) return false;
|
|
132
|
+
if (!current) return true;
|
|
133
|
+
return Date.parse(candidate) > Date.parse(current);
|
|
134
|
+
}
|
|
135
|
+
function compareOperations(left, right) {
|
|
136
|
+
return compareText(operationKey(left), operationKey(right));
|
|
137
|
+
}
|
|
138
|
+
function compareText(left, right) {
|
|
139
|
+
if (left < right) return -1;
|
|
140
|
+
if (left > right) return 1;
|
|
141
|
+
return 0;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export { architectureEdgeKey, architectureGraphFrom, mergeOperationSources, uniqueOperationCount };
|
|
145
|
+
//# sourceMappingURL=architectureGraph.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"architectureGraph.esm.js","sources":["../../../src/components/entity/architectureGraph.ts"],"sourcesContent":["export interface ArchitectureHttpOperation {\n method: string | null;\n pathTemplate: string | null;\n observedAt: string | null;\n}\n\nexport interface ArchitectureOperationSource {\n source: string;\n operations: ArchitectureHttpOperation[];\n hasIncompleteOperations: boolean;\n}\n\nexport interface ArchitectureEdge {\n from: string;\n to: string;\n type: string;\n operationSources?: ArchitectureOperationSource[];\n synthetic?: boolean;\n}\n\nexport interface ArchitectureNode {\n id: string;\n name: string;\n type?: string | null;\n namespace?: string | null;\n image?: string | null;\n}\n\nexport interface ArchitectureGraph {\n nodes: ArchitectureNode[];\n edges: ArchitectureEdge[];\n}\n\nconst UNAVAILABLE_APM_SOURCE = 'APM source unavailable';\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\nconst cleanText = (value: unknown): string | null =>\n typeof value === 'string' && value.trim() ? value.trim() : null;\n\nconst usableTimestamp = (value: unknown): string | null => {\n const text = cleanText(value);\n return text && !Number.isNaN(Date.parse(text)) ? text : null;\n};\n\nconst operationKey = (operation: ArchitectureHttpOperation): string =>\n `${operation.method ?? ''}\\u0000${operation.pathTemplate ?? ''}`;\n\nexport const architectureEdgeKey = (\n edge: Pick<ArchitectureEdge, 'from' | 'to' | 'type'>,\n): string => `${edge.from}\\u0000${edge.type}\\u0000${edge.to}`;\n\nexport const uniqueOperationCount = (\n sources: ArchitectureOperationSource[] | undefined,\n): number =>\n new Set(\n (sources ?? []).flatMap(source => source.operations.map(operationKey)),\n ).size;\n\nexport const mergeOperationSources = (\n left?: ArchitectureOperationSource[],\n right?: ArchitectureOperationSource[],\n): ArchitectureOperationSource[] => {\n const grouped = new Map<\n string,\n {\n source: string;\n operations: Map<string, ArchitectureHttpOperation>;\n hasIncompleteOperations: boolean;\n }\n >();\n\n [...(left ?? []), ...(right ?? [])].forEach(source => {\n const displaySource = cleanText(source.source) ?? UNAVAILABLE_APM_SOURCE;\n const key = displaySource.toLowerCase();\n const group = grouped.get(key) ?? {\n source: displaySource,\n operations: new Map(),\n hasIncompleteOperations: false,\n };\n group.hasIncompleteOperations ||= source.hasIncompleteOperations;\n\n source.operations.forEach(operation => {\n const normalized = normalizeOperation(operation);\n if (!normalized) return;\n const normalizedKey = operationKey(normalized);\n const existing = group.operations.get(normalizedKey);\n if (!existing || isNewer(normalized.observedAt, existing.observedAt)) {\n group.operations.set(normalizedKey, normalized);\n }\n });\n grouped.set(key, group);\n });\n\n return [...grouped.values()]\n .map(group => ({\n source: group.source,\n operations: [...group.operations.values()].sort(compareOperations),\n hasIncompleteOperations: group.hasIncompleteOperations,\n }))\n .sort((leftGroup, rightGroup) =>\n compareText(\n leftGroup.source.toLowerCase(),\n rightGroup.source.toLowerCase(),\n ),\n );\n};\n\nexport const architectureGraphFrom = (value: unknown): ArchitectureGraph => {\n if (!isRecord(value)) return { nodes: [], edges: [] };\n\n const nodes = Array.isArray(value.nodes)\n ? value.nodes.flatMap((node, index) => architectureNodeFrom(node, index))\n : [];\n const edges = Array.isArray(value.edges)\n ? value.edges.flatMap(architectureEdgeFrom)\n : [];\n\n return { nodes, edges };\n};\n\nfunction architectureNodeFrom(\n value: unknown,\n index: number,\n): ArchitectureNode[] {\n if (!isRecord(value)) return [];\n const id = cleanText(value.id) ?? cleanText(value.name) ?? `node-${index}`;\n const name = cleanText(value.name) ?? cleanText(value.id) ?? id;\n return [\n {\n id,\n name,\n type: cleanText(value.type),\n namespace: cleanText(value.namespace),\n image: cleanText(value.image),\n },\n ];\n}\n\nfunction architectureEdgeFrom(value: unknown): ArchitectureEdge[] {\n if (!isRecord(value)) return [];\n\n const hasExplicitFrom = Object.prototype.hasOwnProperty.call(value, 'from');\n const from = hasExplicitFrom\n ? endpointId(value.from)\n : endpointId(value.source);\n const to = endpointId(value.to) ?? endpointId(value.target);\n if (!from || !to) return [];\n\n const type =\n cleanText(value.type) ??\n cleanText(value.label) ??\n cleanText(value.relationship) ??\n 'RELATES_TO';\n const synthetic = value.synthetic === true;\n const edge: ArchitectureEdge = {\n from,\n to,\n type,\n ...(synthetic ? { synthetic: true } : {}),\n };\n const operationSource = synthetic\n ? null\n : operationSourceFrom(value, type, hasExplicitFrom);\n if (operationSource) {\n edge.operationSources = mergeOperationSources([operationSource], undefined);\n }\n return [edge];\n}\n\nfunction endpointId(value: unknown): string | null {\n if (typeof value === 'string') return cleanText(value);\n if (!isRecord(value)) return null;\n return cleanText(value.id) ?? cleanText(value.name);\n}\n\nfunction operationSourceFrom(\n edge: Record<string, unknown>,\n type: string,\n hasExplicitFrom: boolean,\n): ArchitectureOperationSource | null {\n if (type !== 'CALLS_TO' || !Array.isArray(edge.operations)) return null;\n\n const observedAt = usableTimestamp(edge.observedAt);\n const operations: ArchitectureHttpOperation[] = [];\n let hasIncompleteOperations = false;\n edge.operations.forEach(value => {\n if (!isRecord(value)) return;\n if (!isOptionalText(value.method) || !isOptionalText(value.pathTemplate)) {\n return;\n }\n const method = cleanText(value.method)?.toUpperCase() ?? null;\n const pathTemplate = cleanText(value.pathTemplate) ?? null;\n if (!method && !pathTemplate) {\n hasIncompleteOperations = true;\n return;\n }\n operations.push({ method, pathTemplate, observedAt });\n });\n\n if (operations.length === 0 && !hasIncompleteOperations) return null;\n const source = hasExplicitFrom\n ? cleanText(edge.source) ?? UNAVAILABLE_APM_SOURCE\n : UNAVAILABLE_APM_SOURCE;\n return {\n source,\n operations,\n hasIncompleteOperations,\n };\n}\n\nfunction isOptionalText(value: unknown): value is string | null | undefined {\n return value === undefined || value === null || typeof value === 'string';\n}\n\nfunction normalizeOperation(\n operation: ArchitectureHttpOperation,\n): ArchitectureHttpOperation | null {\n const method = cleanText(operation.method)?.toUpperCase() ?? null;\n const pathTemplate = cleanText(operation.pathTemplate) ?? null;\n if (!method && !pathTemplate) return null;\n return {\n method,\n pathTemplate,\n observedAt: usableTimestamp(operation.observedAt),\n };\n}\n\nfunction isNewer(candidate: string | null, current: string | null): boolean {\n if (!candidate) return false;\n if (!current) return true;\n return Date.parse(candidate) > Date.parse(current);\n}\n\nfunction compareOperations(\n left: ArchitectureHttpOperation,\n right: ArchitectureHttpOperation,\n): number {\n return compareText(operationKey(left), operationKey(right));\n}\n\nfunction compareText(left: string, right: string): number {\n if (left < right) return -1;\n if (left > right) return 1;\n return 0;\n}\n"],"names":[],"mappings":"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"}
|
package/dist/package.json.esm.js
CHANGED
package/package.json
CHANGED