@anyshift/backstage-plugin-anyshift 0.1.0-beta.2 → 0.1.0-beta.20
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 +76 -0
- package/README.md +14 -1
- package/dist/api/AnyshiftApi.esm.js +61 -7
- package/dist/api/AnyshiftApi.esm.js.map +1 -1
- package/dist/components/ask/AskAnyshiftCard.esm.js +348 -0
- package/dist/components/ask/AskAnyshiftCard.esm.js.map +1 -0
- package/dist/components/ask/askPresenters.esm.js +1203 -0
- package/dist/components/ask/askPresenters.esm.js.map +1 -0
- package/dist/components/ask/askScope.esm.js +27 -0
- package/dist/components/ask/askScope.esm.js.map +1 -0
- package/dist/components/ask/askSuggestions.esm.js +41 -0
- package/dist/components/ask/askSuggestions.esm.js.map +1 -0
- package/dist/components/cloud/CloudImpactSection.esm.js +54 -0
- package/dist/components/cloud/CloudImpactSection.esm.js.map +1 -0
- package/dist/components/cloud/CloudPage.esm.js +104 -0
- package/dist/components/cloud/CloudPage.esm.js.map +1 -0
- package/dist/components/cloud/CloudRelationshipSections.esm.js +43 -0
- package/dist/components/cloud/CloudRelationshipSections.esm.js.map +1 -0
- package/dist/components/cloud/CloudResourceContent.esm.js +495 -0
- package/dist/components/cloud/CloudResourceContent.esm.js.map +1 -0
- package/dist/components/entity/AnyshiftEntityContent.esm.js +128 -23
- package/dist/components/entity/AnyshiftEntityContent.esm.js.map +1 -1
- package/dist/components/entity/ArchitectureOperationDetails.esm.js +107 -0
- package/dist/components/entity/ArchitectureOperationDetails.esm.js.map +1 -0
- package/dist/components/entity/BriefSections.esm.js +24 -4
- package/dist/components/entity/BriefSections.esm.js.map +1 -1
- package/dist/components/entity/DatadogLiveSignal.esm.js +85 -23
- package/dist/components/entity/DatadogLiveSignal.esm.js.map +1 -1
- 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 +145 -82
- 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/components/entity/entityIdentity.esm.js +40 -0
- package/dist/components/entity/entityIdentity.esm.js.map +1 -0
- package/dist/components/entity/relatedCatalogEntities.esm.js +60 -0
- package/dist/components/entity/relatedCatalogEntities.esm.js.map +1 -0
- package/dist/components/explorer/AnyshiftExplorerPage.esm.js +222 -21
- package/dist/components/explorer/AnyshiftExplorerPage.esm.js.map +1 -1
- package/dist/components/explorer/DatadogOperationsRadar.esm.js +92 -31
- package/dist/components/explorer/DatadogOperationsRadar.esm.js.map +1 -1
- package/dist/index.d.ts +26 -102
- package/dist/index.esm.js +1 -1
- package/dist/package.json.esm.js +10 -10
- package/dist/plugin.esm.js +51 -8
- package/dist/plugin.esm.js.map +1 -1
- package/dist/routes.esm.js +2 -1
- package/dist/routes.esm.js.map +1 -1
- package/package.json +11 -11
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
2
|
import { Box, Typography, Chip, Grid, ButtonGroup, Button, Divider } from '@material-ui/core';
|
|
3
3
|
import { useState } from 'react';
|
|
4
|
+
import { EntityRefLink } from '@backstage/plugin-catalog-react';
|
|
4
5
|
import { ArchitectureDiagram } from './MermaidArchitecture.esm.js';
|
|
6
|
+
import { architectureGraphFrom } from './architectureGraph.esm.js';
|
|
5
7
|
import { EvidenceDisclosure } from './EvidenceDisclosure.esm.js';
|
|
6
8
|
import { recordsFrom, eventFrom, statusFrom, readText, isRecord, factsFrom, firstRecordFrom } from './sectionData.esm.js';
|
|
7
9
|
|
|
@@ -32,7 +34,7 @@ const OverviewPresenter = ({ data }) => {
|
|
|
32
34
|
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "textSecondary", children: "Service level" })
|
|
33
35
|
] }),
|
|
34
36
|
/* @__PURE__ */ jsxs(Grid, { item: true, xs: 6, sm: 4, md: 2, children: [
|
|
35
|
-
/* @__PURE__ */ jsx(Typography, { variant: "subtitle1", children: typeof value.activeAlertCount === "number" ? `${value.activeAlertCount} active` : "N/A" }),
|
|
37
|
+
/* @__PURE__ */ jsx(Typography, { variant: "subtitle1", children: typeof value.activeAlertCount === "number" ? `${value.activeAlertCountIsLowerBound ? "At least " : ""}${value.activeAlertCount} active` : "N/A" }),
|
|
36
38
|
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "textSecondary", children: "Alerts" })
|
|
37
39
|
] })
|
|
38
40
|
] }),
|
|
@@ -47,6 +49,24 @@ const DependencyFootprintPresenter = ({ data }) => {
|
|
|
47
49
|
const direct = isRecord(calls.target) ? calls.target : {};
|
|
48
50
|
const callers = textArray(direct.callers);
|
|
49
51
|
const callees = textArray(direct.callees);
|
|
52
|
+
const configuration = isRecord(root.configuration) ? root.configuration : {};
|
|
53
|
+
const configuredNodes = new Map(
|
|
54
|
+
recordsFrom(configuration.nodes).flatMap((node) => {
|
|
55
|
+
const id = readText(node, ["id"]);
|
|
56
|
+
const name = readText(node, ["name"]);
|
|
57
|
+
return id && name ? [[id, name]] : [];
|
|
58
|
+
})
|
|
59
|
+
);
|
|
60
|
+
const configuredEdges = recordsFrom(configuration.edges);
|
|
61
|
+
const configuredCallers = configuredEdges.flatMap((edge) => {
|
|
62
|
+
const from = readText(edge, ["from"]);
|
|
63
|
+
const to = readText(edge, ["to"]);
|
|
64
|
+
return from && to && !to.startsWith("configured:") ? [configuredNodes.get(from) ?? from] : [];
|
|
65
|
+
});
|
|
66
|
+
const configuredCallees = configuredEdges.flatMap((edge) => {
|
|
67
|
+
const to = readText(edge, ["to"]);
|
|
68
|
+
return to?.startsWith("configured:") ? [configuredNodes.get(to) ?? to.slice("configured:".length)] : [];
|
|
69
|
+
});
|
|
50
70
|
const footprint = [
|
|
51
71
|
metricLabel(tree.serviceCount, "service", "services"),
|
|
52
72
|
metricLabel(tree.datastoreCount, "datastore", "datastores"),
|
|
@@ -74,61 +94,136 @@ const DependencyFootprintPresenter = ({ data }) => {
|
|
|
74
94
|
] })
|
|
75
95
|
] }),
|
|
76
96
|
footprint.length > 0 && /* @__PURE__ */ jsx(Box, { display: "flex", flexWrap: "wrap", gridGap: 8, mt: 2, children: footprint.map((item) => /* @__PURE__ */ jsx(Chip, { size: "small", variant: "outlined", label: item }, item)) }),
|
|
77
|
-
/* @__PURE__ */
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
const alertCause = isRecord(root.alertCause) ? root.alertCause : {};
|
|
89
|
-
const changes = Array.isArray(alertCause.changes) ? alertCause.changes.length : void 0;
|
|
90
|
-
const findings = [
|
|
91
|
-
{
|
|
92
|
-
label: sloTarget.status ? `${readableStatus(sloTarget.status)} SLO` : "SLO not resolved",
|
|
93
|
-
detail: readText(sloTarget, ["name"])
|
|
94
|
-
},
|
|
95
|
-
{
|
|
96
|
-
label: alerts.total === 0 ? "No active alerts" : typeof alerts.total === "number" ? `${alerts.total} active alerts` : "Alerts not resolved"
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
label: typeof deployImpact.rollouts === "number" ? `${deployImpact.rollouts} rollouts \xB7 ${typeof deployImpact.total === "number" ? deployImpact.total : "N/A"} correlated failures` : "Deployment impact not resolved"
|
|
100
|
-
},
|
|
101
|
-
{
|
|
102
|
-
label: owner.application ? String(owner.application) : "No GitOps owner"
|
|
103
|
-
},
|
|
104
|
-
{
|
|
105
|
-
label: changes === void 0 ? "Recent cause not resolved" : `${changes} recent correlated ${changes === 1 ? "change" : "changes"}`
|
|
106
|
-
}
|
|
107
|
-
];
|
|
108
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
109
|
-
/* @__PURE__ */ jsx(Box, { component: "ul", m: 0, p: 0, "aria-label": "Operational findings", children: findings.map((finding, index) => /* @__PURE__ */ jsxs(Box, { component: "li", style: { listStyle: "none" }, children: [
|
|
110
|
-
index > 0 && /* @__PURE__ */ jsx(Divider, {}),
|
|
111
|
-
/* @__PURE__ */ jsxs(Box, { py: 1, children: [
|
|
112
|
-
/* @__PURE__ */ jsx(Typography, { variant: "subtitle2", children: finding.label }),
|
|
113
|
-
finding.detail && /* @__PURE__ */ jsx(Muted, { children: finding.detail })
|
|
97
|
+
(configuredCallers.length > 0 || configuredCallees.length > 0) && /* @__PURE__ */ jsxs(Box, { mt: 2, children: [
|
|
98
|
+
/* @__PURE__ */ jsx(Chip, { size: "small", color: "primary", label: "Configured evidence" }),
|
|
99
|
+
/* @__PURE__ */ jsxs(Grid, { container: true, spacing: 3, children: [
|
|
100
|
+
/* @__PURE__ */ jsxs(Grid, { item: true, xs: 12, md: 6, children: [
|
|
101
|
+
/* @__PURE__ */ jsx(Typography, { variant: "overline", color: "textSecondary", children: "Configured callers" }),
|
|
102
|
+
/* @__PURE__ */ jsx(NamedResources, { names: configuredCallers })
|
|
103
|
+
] }),
|
|
104
|
+
/* @__PURE__ */ jsxs(Grid, { item: true, xs: 12, md: 6, children: [
|
|
105
|
+
/* @__PURE__ */ jsx(Typography, { variant: "overline", color: "textSecondary", children: "Configured dependencies" }),
|
|
106
|
+
/* @__PURE__ */ jsx(NamedResources, { names: configuredCallees })
|
|
107
|
+
] })
|
|
114
108
|
] })
|
|
115
|
-
] }
|
|
109
|
+
] }),
|
|
116
110
|
/* @__PURE__ */ jsx(EvidenceDisclosure, { data })
|
|
117
111
|
] });
|
|
118
112
|
};
|
|
119
|
-
const
|
|
113
|
+
const WHY_NOW_LABELS = {
|
|
114
|
+
deployment_correlated: "Deployment correlated",
|
|
115
|
+
runtime_cause_suspected: "Runtime cause suspected",
|
|
116
|
+
active_alerts: "Active alerts",
|
|
117
|
+
clear: "No active alerts",
|
|
118
|
+
insufficient_evidence: "Insufficient evidence"
|
|
119
|
+
};
|
|
120
|
+
const WhyNowPresenter = ({ data }) => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
121
|
+
/* @__PURE__ */ jsxs(Box, { display: "flex", flexWrap: "wrap", alignItems: "center", gridGap: 8, mb: 1, children: [
|
|
122
|
+
/* @__PURE__ */ jsx(
|
|
123
|
+
Chip,
|
|
124
|
+
{
|
|
125
|
+
size: "small",
|
|
126
|
+
color: data.verdict === "clear" ? "primary" : "default",
|
|
127
|
+
label: WHY_NOW_LABELS[data.verdict]
|
|
128
|
+
}
|
|
129
|
+
),
|
|
130
|
+
/* @__PURE__ */ jsx(Typography, { variant: "subtitle1", children: data.headline })
|
|
131
|
+
] }),
|
|
132
|
+
/* @__PURE__ */ jsxs(Grid, { container: true, spacing: 2, children: [
|
|
133
|
+
/* @__PURE__ */ jsxs(Grid, { item: true, xs: 12, md: 4, children: [
|
|
134
|
+
/* @__PURE__ */ jsx(Typography, { variant: "overline", color: "textSecondary", children: "Current condition" }),
|
|
135
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", children: typeof data.activeAlerts === "number" ? `${data.activeAlerts} active ${data.activeAlerts === 1 ? "alert" : "alerts"}` : "Alert evidence unavailable" }),
|
|
136
|
+
data.firingMonitors.length > 0 && /* @__PURE__ */ jsx(NamedResources, { names: data.firingMonitors })
|
|
137
|
+
] }),
|
|
138
|
+
/* @__PURE__ */ jsxs(Grid, { item: true, xs: 12, md: 4, children: [
|
|
139
|
+
/* @__PURE__ */ jsxs(Typography, { variant: "overline", color: "textSecondary", children: [
|
|
140
|
+
"Runtime suspects \xB7 ",
|
|
141
|
+
data.evidence.runtimeWindow
|
|
142
|
+
] }),
|
|
143
|
+
data.suspectedChanges.length > 0 ? /* @__PURE__ */ jsx(Box, { component: "ul", m: 0, pl: 2, children: data.suspectedChanges.map((change, index) => /* @__PURE__ */ jsxs("li", { children: [
|
|
144
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", children: change.summary || "No graph summary was provided." }),
|
|
145
|
+
/* @__PURE__ */ jsx(Muted, { children: readableStatus(change.type) })
|
|
146
|
+
] }, `${change.timestamp || change.type}-${index}`)) }) : /* @__PURE__ */ jsx(Muted, { children: "No recent runtime suspect was resolved." })
|
|
147
|
+
] }),
|
|
148
|
+
/* @__PURE__ */ jsxs(Grid, { item: true, xs: 12, md: 4, children: [
|
|
149
|
+
/* @__PURE__ */ jsxs(Typography, { variant: "overline", color: "textSecondary", children: [
|
|
150
|
+
"Deployment correlation \xB7 ",
|
|
151
|
+
data.evidence.deploymentWindow
|
|
152
|
+
] }),
|
|
153
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", children: typeof data.deployment.rollouts === "number" ? `${data.deployment.rollouts} ${data.deployment.rollouts === 1 ? "rollout" : "rollouts"} \xB7 ${typeof data.deployment.correlatedFailures === "number" ? data.deployment.correlatedFailures : "N/A"} correlated failures` : "Deployment evidence unavailable" })
|
|
154
|
+
] })
|
|
155
|
+
] }),
|
|
156
|
+
/* @__PURE__ */ jsx(Warnings, { warnings: data.warnings })
|
|
157
|
+
] });
|
|
158
|
+
const IMPACT_METRICS = [
|
|
159
|
+
["affectedWorkloads", "Affected workloads"],
|
|
160
|
+
["downstreamServices", "Downstream services"],
|
|
161
|
+
["datastores", "Datastores"],
|
|
162
|
+
["externalDependencies", "External dependencies"]
|
|
163
|
+
];
|
|
164
|
+
const AffectedFootprintPresenter = ({
|
|
165
|
+
data
|
|
166
|
+
}) => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
167
|
+
/* @__PURE__ */ jsx(Grid, { container: true, spacing: 2, children: IMPACT_METRICS.map(([key, label]) => /* @__PURE__ */ jsxs(Grid, { item: true, xs: 6, children: [
|
|
168
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h5", children: typeof data[key] === "number" ? data[key] : "N/A" }),
|
|
169
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "textSecondary", children: label })
|
|
170
|
+
] }, key)) }),
|
|
171
|
+
/* @__PURE__ */ jsxs(Box, { display: "flex", flexWrap: "wrap", gridGap: 8, mt: 2, children: [
|
|
172
|
+
/* @__PURE__ */ jsx(
|
|
173
|
+
Chip,
|
|
174
|
+
{
|
|
175
|
+
size: "small",
|
|
176
|
+
variant: "outlined",
|
|
177
|
+
label: `${data.monitorCount ?? "N/A"} monitors`
|
|
178
|
+
}
|
|
179
|
+
),
|
|
180
|
+
/* @__PURE__ */ jsx(
|
|
181
|
+
Chip,
|
|
182
|
+
{
|
|
183
|
+
size: "small",
|
|
184
|
+
variant: "outlined",
|
|
185
|
+
label: `${data.sloCount ?? "N/A"} SLOs`
|
|
186
|
+
}
|
|
187
|
+
)
|
|
188
|
+
] }),
|
|
189
|
+
data.relatedEntities.length > 0 && /* @__PURE__ */ jsxs(Box, { mt: 2, children: [
|
|
190
|
+
/* @__PURE__ */ jsx(Typography, { variant: "overline", color: "textSecondary", children: "Related catalog entities" }),
|
|
191
|
+
/* @__PURE__ */ jsx(Box, { display: "flex", flexDirection: "column", gridGap: 4, children: data.relatedEntities.map((entity, index) => /* @__PURE__ */ jsx(Box, { children: entity.entityRef ? /* @__PURE__ */ jsx(
|
|
192
|
+
EntityRefLink,
|
|
193
|
+
{
|
|
194
|
+
entityRef: entity.entityRef,
|
|
195
|
+
title: entity.name
|
|
196
|
+
}
|
|
197
|
+
) : /* @__PURE__ */ jsx(
|
|
198
|
+
Typography,
|
|
199
|
+
{
|
|
200
|
+
variant: "body2",
|
|
201
|
+
"aria-label": `${entity.name} (${entity.category})`,
|
|
202
|
+
children: entity.name
|
|
203
|
+
}
|
|
204
|
+
) }, `${entity.category}:${entity.name}:${index}`)) })
|
|
205
|
+
] }),
|
|
206
|
+
/* @__PURE__ */ jsx(Warnings, { warnings: data.warnings })
|
|
207
|
+
] });
|
|
208
|
+
const ImpactPresenter = ({
|
|
209
|
+
data,
|
|
210
|
+
showEvidence = true,
|
|
211
|
+
summaryMetric
|
|
212
|
+
}) => {
|
|
120
213
|
const affected = namedRecords(data);
|
|
121
214
|
const total = numberFrom(data, ["total", "count", "affectedCount"]);
|
|
122
215
|
const status = statusFrom(data);
|
|
216
|
+
const defaultTotal = total ?? (affected.length > 0 ? affected.length : void 0);
|
|
217
|
+
const visibleSummary = summaryMetric === false ? void 0 : summaryMetric ?? (defaultTotal !== void 0 ? { label: "Affected resources", total: defaultTotal } : void 0);
|
|
123
218
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
124
|
-
|
|
125
|
-
/* @__PURE__ */ jsx(Typography, { variant: "overline", color: "textSecondary", children:
|
|
126
|
-
/* @__PURE__ */ jsx(Typography, { variant: "h5", children: total
|
|
219
|
+
visibleSummary && /* @__PURE__ */ jsxs(Box, { mb: 2, children: [
|
|
220
|
+
/* @__PURE__ */ jsx(Typography, { variant: "overline", color: "textSecondary", children: visibleSummary.label }),
|
|
221
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h5", children: visibleSummary.total })
|
|
127
222
|
] }),
|
|
128
223
|
status && /* @__PURE__ */ jsx(StatusChip, { status }),
|
|
129
224
|
/* @__PURE__ */ jsx(GenericFacts, { data, omit: ["total", "count", "affectedCount"] }),
|
|
130
225
|
/* @__PURE__ */ jsx(NamedResources, { names: affected }),
|
|
131
|
-
/* @__PURE__ */ jsx(EvidenceDisclosure, { data })
|
|
226
|
+
showEvidence && /* @__PURE__ */ jsx(EvidenceDisclosure, { data })
|
|
132
227
|
] });
|
|
133
228
|
};
|
|
134
229
|
const LatestChangePresenter = ({ data }) => {
|
|
@@ -155,7 +250,8 @@ const SafeguardsPresenter = ({ data }) => /* @__PURE__ */ jsxs(Fragment, { child
|
|
|
155
250
|
] });
|
|
156
251
|
const TimelinePresenter = ({
|
|
157
252
|
data,
|
|
158
|
-
fallbackLabel = "Change recorded"
|
|
253
|
+
fallbackLabel = "Change recorded",
|
|
254
|
+
showEvidence = true
|
|
159
255
|
}) => {
|
|
160
256
|
const records = recordsFrom(data).slice(0, 10);
|
|
161
257
|
if (records.length === 0) return /* @__PURE__ */ jsx(PresenterFallback, { data });
|
|
@@ -167,11 +263,11 @@ const TimelinePresenter = ({
|
|
|
167
263
|
event.summary && /* @__PURE__ */ jsx(Typography, { variant: "body2", children: event.summary })
|
|
168
264
|
] }, eventKey(record, index));
|
|
169
265
|
}) }),
|
|
170
|
-
/* @__PURE__ */ jsx(EvidenceDisclosure, { data })
|
|
266
|
+
showEvidence && /* @__PURE__ */ jsx(EvidenceDisclosure, { data })
|
|
171
267
|
] });
|
|
172
268
|
};
|
|
173
269
|
const ArchitecturePresenter = ({ data }) => {
|
|
174
|
-
const graph =
|
|
270
|
+
const graph = architectureGraphFrom(data);
|
|
175
271
|
const [view, setView] = useState("context");
|
|
176
272
|
if (graph.nodes.length === 0) {
|
|
177
273
|
return /* @__PURE__ */ jsx(PresenterFallback, { data });
|
|
@@ -291,41 +387,8 @@ function formatTimestamp(value) {
|
|
|
291
387
|
const timestamp = Date.parse(value);
|
|
292
388
|
return Number.isNaN(timestamp) ? value : new Date(timestamp).toLocaleString();
|
|
293
389
|
}
|
|
294
|
-
function architectureFrom(value) {
|
|
295
|
-
if (!isRecord(value)) return { nodes: [], edges: [] };
|
|
296
|
-
const nodeValues = Array.isArray(value.nodes) ? value.nodes.filter(isRecord) : [];
|
|
297
|
-
const nodes = nodeValues.map((node, index) => {
|
|
298
|
-
const id = readText(node, ["id", "name"]) ?? `node-${index}`;
|
|
299
|
-
const name = readText(node, ["name", "id"]) ?? id;
|
|
300
|
-
return {
|
|
301
|
-
id,
|
|
302
|
-
name,
|
|
303
|
-
type: readText(node, ["type"]),
|
|
304
|
-
namespace: readText(node, ["namespace"]),
|
|
305
|
-
image: readText(node, ["image"])
|
|
306
|
-
};
|
|
307
|
-
});
|
|
308
|
-
const edgeValues = Array.isArray(value.edges) ? value.edges.filter(isRecord) : [];
|
|
309
|
-
const edges = edgeValues.flatMap((edge) => {
|
|
310
|
-
const from = endpointId(edge.from ?? edge.source);
|
|
311
|
-
const to = endpointId(edge.to ?? edge.target);
|
|
312
|
-
if (!from || !to) return [];
|
|
313
|
-
return [
|
|
314
|
-
{
|
|
315
|
-
from,
|
|
316
|
-
to,
|
|
317
|
-
type: readText(edge, ["type", "label", "relationship"]) ?? "RELATES_TO"
|
|
318
|
-
}
|
|
319
|
-
];
|
|
320
|
-
});
|
|
321
|
-
return { nodes, edges };
|
|
322
|
-
}
|
|
323
|
-
function endpointId(value) {
|
|
324
|
-
if (typeof value === "string") return value;
|
|
325
|
-
if (!isRecord(value)) return void 0;
|
|
326
|
-
return readText(value, ["id", "name"]);
|
|
327
|
-
}
|
|
328
390
|
const Muted = ({ children }) => /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "textSecondary", children });
|
|
391
|
+
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;
|
|
329
392
|
function textArray(value) {
|
|
330
393
|
return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
|
|
331
394
|
}
|
|
@@ -337,5 +400,5 @@ function readableStatus(value) {
|
|
|
337
400
|
return value.charAt(0).toUpperCase() + value.slice(1).replace(/_/g, " ");
|
|
338
401
|
}
|
|
339
402
|
|
|
340
|
-
export { ArchitecturePresenter, DependencyFootprintPresenter, GenericFacts, ImpactPresenter, LatestChangePresenter,
|
|
403
|
+
export { AffectedFootprintPresenter, ArchitecturePresenter, DependencyFootprintPresenter, GenericFacts, ImpactPresenter, LatestChangePresenter, OverviewPresenter, SafeguardsPresenter, TimelinePresenter, WhyNowPresenter };
|
|
341
404
|
//# sourceMappingURL=SectionPresenters.esm.js.map
|
|
@@ -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 type { SafeguardResult } 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 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 <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\nexport const ImpactPresenter = ({ data }: { data: unknown }) => {\n const affected = namedRecords(data);\n const total = numberFrom(data, ['total', 'count', 'affectedCount']);\n const status = statusFrom(data);\n\n return (\n <>\n {(total !== undefined || affected.length > 0) && (\n <Box mb={2}>\n <Typography variant=\"overline\" color=\"textSecondary\">\n Affected resources\n </Typography>\n <Typography variant=\"h5\">{total ?? affected.length}</Typography>\n </Box>\n )}\n {status && <StatusChip status={status} />}\n <GenericFacts data={data} omit={['total', 'count', 'affectedCount']} />\n <NamedResources names={affected} />\n <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}: {\n data: unknown;\n fallbackLabel?: string;\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 <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\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.activeAlertCountIsLowerBound ? 'At least ' : ''}${\n value.activeAlertCount\n } 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 alertItems = Array.isArray(alerts.items) ? alerts.items : undefined;\n const firingAlertCount = alertItems?.filter(\n item => isRecord(item) && item.status === 'firing',\n ).length;\n const alertProviders = Array.isArray(alerts.providers)\n ? alerts.providers\n : [];\n const alertPage = isRecord(alerts.page) ? alerts.page : {};\n const alertWarnings = Array.isArray(alerts.warnings) ? alerts.warnings : [];\n const alertEvidenceIncomplete =\n alerts.partial === true ||\n alertPage.hasMore === true ||\n alertWarnings.length > 0 ||\n alertProviders.some(\n provider => isRecord(provider) && provider.status !== 'available',\n );\n let activeAlertLabel = 'Alerts not resolved';\n if (typeof firingAlertCount === 'number') {\n if (firingAlertCount > 0) {\n activeAlertLabel = alertEvidenceIncomplete\n ? `At least ${firingAlertCount} active alerts`\n : `${firingAlertCount} active alerts`;\n } else {\n activeAlertLabel = alertEvidenceIncomplete\n ? 'Active alert evidence is incomplete'\n : 'No active alerts';\n }\n }\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: activeAlertLabel,\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, index) => (\n <Box key={`${entity.category}:${entity.name}:${index}`}>\n {entity.entityRef ? (\n <EntityRefLink\n entityRef={entity.entityRef}\n title={entity.name}\n />\n ) : (\n <Typography\n variant=\"body2\"\n aria-label={`${entity.name} (${entity.category})`}\n >\n {entity.name}\n </Typography>\n )}\n </Box>\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;
|