@64mb/freelens-power 2.1.1 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/out/main/common/power-logs.js.map +1 -1
- package/out/main/power-logs-child.js +3 -3
- package/out/main/power-logs-child.js.map +1 -1
- package/out/main/power-logs-database.js +165 -7
- package/out/main/power-logs-database.js.map +1 -1
- package/out/main/power-logs-ipc.js +12 -3
- package/out/main/power-logs-ipc.js.map +1 -1
- package/out/main/power-logs-worker.js +29 -7
- package/out/main/power-logs-worker.js.map +1 -1
- package/out/renderer/ai-diagnostic-handoff.js +2 -2
- package/out/renderer/ai-diagnostic-handoff.js.map +1 -1
- package/out/renderer/ai-extras.js +1 -1
- package/out/renderer/ai-extras.js.map +1 -1
- package/out/renderer/ai.js +4 -1
- package/out/renderer/ai.js.map +1 -1
- package/out/renderer/diagnostics-screen-finding.js +51 -0
- package/out/renderer/diagnostics-screen-finding.js.map +1 -0
- package/out/renderer/diagnostics.css.js +1 -1
- package/out/renderer/diagnostics.css.js.map +1 -1
- package/out/renderer/diagnostics.js +12 -0
- package/out/renderer/diagnostics.js.map +1 -1
- package/out/renderer/index.js +2 -0
- package/out/renderer/index.js.map +1 -1
- package/out/renderer/pod-details-enhancements.js +106 -0
- package/out/renderer/pod-details-enhancements.js.map +1 -0
- package/out/renderer/power-log-json-cell.js +15 -14
- package/out/renderer/power-log-json-cell.js.map +1 -1
- package/out/renderer/power-log-json.js +14 -6
- package/out/renderer/power-log-json.js.map +1 -1
- package/out/renderer/power-log-sql-editor.js +31 -2
- package/out/renderer/power-log-sql-editor.js.map +1 -1
- package/out/renderer/power-logs-client.js +5 -0
- package/out/renderer/power-logs-client.js.map +1 -1
- package/out/renderer/power-logs-entrypoints.js +10 -36
- package/out/renderer/power-logs-entrypoints.js.map +1 -1
- package/out/renderer/power-logs.css.js +9 -2
- package/out/renderer/power-logs.css.js.map +1 -1
- package/out/renderer/power-logs.js +220 -91
- package/out/renderer/power-logs.js.map +1 -1
- package/out/renderer/preferences/logs-preferences.js +1 -1
- package/out/renderer/preferences/logs-preferences.js.map +1 -1
- package/out/renderer/relationship-map-finding.js +53 -0
- package/out/renderer/relationship-map-finding.js.map +1 -0
- package/out/renderer/resource-relationships.css.js +6 -0
- package/out/renderer/resource-relationships.css.js.map +1 -1
- package/out/renderer/resource-relationships.js +50 -5
- package/out/renderer/resource-relationships.js.map +1 -1
- package/out/renderer/resource-search.js +13 -3
- package/out/renderer/resource-search.js.map +1 -1
- package/out/renderer/src/common/gateway-relationships.js +8 -7
- package/out/renderer/src/common/gateway-relationships.js.map +1 -1
- package/out/renderer/src/common/power-log-json-filter-sql.js +12 -0
- package/out/renderer/src/common/power-log-json-filter-sql.js.map +1 -1
- package/out/renderer/src/common/power-log-json-preset.js +2 -2
- package/out/renderer/src/common/power-log-json-preset.js.map +1 -1
- package/out/renderer/src/common/power-logs.js.map +1 -1
- package/out/renderer/src/common/resource-relationships.js +10 -8
- package/out/renderer/src/common/resource-relationships.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logs-preferences.js","names":[],"sources":["../../../src/renderer/preferences/logs-preferences.tsx"],"sourcesContent":["import { Renderer } from \"@freelensapp/extensions\";\nimport { observer } from \"mobx-react\";\nimport { POWER_LOGS_DEFAULT_LIMITS, type PowerLogsLimits } from \"../../common/power-logs\";\nimport { applyPowerLogsLimits } from \"../../common/power-logs-limits\";\nimport { LogsPreferencesStore } from \"../../common/store/logs-preferences-store\";\n\nconst MiB = 1024 * 1024;\ninterface LimitPreset {\n label: string;\n limits: Partial<PowerLogsLimits>;\n}\ninterface LimitSetting {\n key: keyof PowerLogsLimits;\n label: string;\n hint: string;\n presets: LimitPreset[];\n describe(limits: PowerLogsLimits): string;\n}\nconst settings: LimitSetting[] = [\n {\n key: \"liveRows\",\n label: \"Live buffer\",\n hint: \"Maximum rows and memory kept in the live log view.\",\n presets: [1000, 5000, 10000, 50000, 100000].map((liveRows, index) => ({\n label: `${liveRows.toLocaleString(\"en-US\")} rows / ${[2, 8, 16, 80, 160][index]} MiB`,\n limits: { liveRows, liveBytes: [2, 8, 16, 80, 160][index] * MiB },\n })),\n describe: (limits) => `${limits.liveRows.toLocaleString(\"en-US\")} rows / ${limits.liveBytes / MiB} MiB`,\n },\n {\n key: \"historyLines\",\n label: \"History per container\",\n hint: \"Maximum recent lines and data fetched for each container.\",\n presets: [500, 1000, 5000].map((historyLines, index) => ({\n label: `${historyLines.toLocaleString(\"en-US\")} lines / ${[0.5, 1, 5][index]} MiB`,\n limits: { historyLines, historyBytes: [0.5, 1, 5][index] * MiB },\n })),\n describe: (limits) => `${limits.historyLines.toLocaleString(\"en-US\")} lines / ${limits.historyBytes / MiB} MiB`,\n },\n {\n key: \"captureBytes\",\n label: \"Capture size\",\n hint: \"Maximum data stored in each temporary capture.\",\n presets: [64, 128, 256, 512].map((size) => ({\n label: `${size} MiB`,\n limits: { captureBytes: size * MiB },\n })),\n describe: (limits) => `${limits.captureBytes / MiB} MiB`,\n },\n {\n key: \"captures\",\n label: \"Saved captures\",\n hint: \"Maximum number of temporary captures retained.\",\n presets: [1, 3, 5, 10].map((captures) => ({\n label: `${captures} ${captures === 1 ? \"capture\" : \"captures\"}`,\n limits: { captures },\n })),\n describe: (limits) => `${limits.captures} captures`,\n },\n {\n key: \"ttlMs\",\n label: \"Retention\",\n hint: \"How long temporary captures remain available.\",\n presets: [30, 60, 360, 1440, 4320].map((minutes) => ({\n label:\n minutes >= 1440\n ? `${minutes / 1440} ${minutes === 1440 ? \"day\" : \"days\"}`\n : minutes < 60\n ? `${minutes} minutes`\n : `${minutes / 60} ${minutes === 60 ? \"hour\" : \"hours\"}`,\n limits: { ttlMs: minutes * 60000 },\n })),\n describe: (limits) => `${limits.ttlMs / 60000} minutes`,\n },\n];\n\nconst LogLimitSelect = observer(function LogLimitSelect({\n setting,\n preferences,\n}: {\n setting: LimitSetting;\n preferences: LogsPreferencesStore;\n}) {\n const selected = setting.presets.findIndex((preset) =>\n Object.entries(preset.limits).every(([key, value]) => preferences.limits[key as keyof PowerLogsLimits] === value),\n );\n const options = setting.presets.map((preset, index) => ({ value: String(index), label: preset.label }));\n if (selected === -1) options.push({ value: \"custom\", label: `Custom: ${setting.describe(preferences.limits)}` });\n const id = `freelens-power-logs-${setting.key}`;\n return (\n <div\n className=\"power-settings-row\"\n style={{ display: \"flex\", alignItems: \"center\", justifyContent: \"space-between\", gap: 20 }}\n >\n <div>\n <label id={`${id}-label`} htmlFor={id}>\n {setting.label}\n </label>\n <div className=\"power-settings-hint\">{setting.hint}</div>\n </div>\n <div style={{ width: 260, maxWidth: \"100%\", flexShrink: 0 }}>\n <Renderer.Component.Select\n id={id}\n aria-labelledby={`${id}-label`}\n options={options}\n value={selected === -1 ? \"custom\" : String(selected)}\n isSearchable={false}\n isClearable={false}\n onChange={(option) => {\n if (!option || option.value === \"custom\") return;\n const preset = setting.presets[Number(option.value)];\n if (!preset) return;\n preferences.limits = { ...preferences.limits, ...preset.limits };\n applyPowerLogsLimits(preferences.limits);\n }}\n />\n </div>\n </div>\n );\n});\n\nexport const LogsPreferences = observer(() => {\n const preferences = LogsPreferencesStore.getInstanceOrCreate<LogsPreferencesStore>();\n return (\n <div style={{ display: \"grid\", gap: 20 }}>\n <div>\n <Renderer.Component.Switch\n checked={preferences.enabled}\n onChange={(value) => {\n preferences.enabled = value;\n }}\n >\n Use Power Logs\n </Renderer.Component.Switch>\n <div className=\"power-settings-hint\">\n Colored workload logs and temporary SQLite captures for SQL analysis. Native logs return when disabled.\n Temporary captures follow the retention settings below and are deleted when Power Logs stops.\n </div>\n </div>\n <div className=\"power-settings-hint\">\n Changes apply to new requests, captures and SQL queries. Existing captures retain their capacity and expiry.\n </div>\n {settings.map((setting) => (\n <LogLimitSelect key={setting.key} setting={setting} preferences={preferences} />\n ))}\n <div style={{ display: \"flex\", justifyContent: \"flex-end\" }}>\n <Renderer.Component.Button\n onClick={() => {\n preferences.limits = { ...POWER_LOGS_DEFAULT_LIMITS };\n applyPowerLogsLimits(preferences.limits);\n }}\n >\n <Renderer.Component.Icon material=\"restore\" size={16} /> Reset log limits\n </Renderer.Component.Button>\n </div>\n </div>\n );\n});\n"],"mappings":"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
|
|
1
|
+
{"version":3,"file":"logs-preferences.js","names":[],"sources":["../../../src/renderer/preferences/logs-preferences.tsx"],"sourcesContent":["import { Renderer } from \"@freelensapp/extensions\";\nimport { observer } from \"mobx-react\";\nimport { POWER_LOGS_DEFAULT_LIMITS, type PowerLogsLimits } from \"../../common/power-logs\";\nimport { applyPowerLogsLimits } from \"../../common/power-logs-limits\";\nimport { LogsPreferencesStore } from \"../../common/store/logs-preferences-store\";\n\nconst MiB = 1024 * 1024;\ninterface LimitPreset {\n label: string;\n limits: Partial<PowerLogsLimits>;\n}\ninterface LimitSetting {\n key: keyof PowerLogsLimits;\n label: string;\n hint: string;\n presets: LimitPreset[];\n describe(limits: PowerLogsLimits): string;\n}\nconst settings: LimitSetting[] = [\n {\n key: \"liveRows\",\n label: \"Live buffer\",\n hint: \"Maximum rows and memory kept in the live log view.\",\n presets: [1000, 5000, 10000, 50000, 100000].map((liveRows, index) => ({\n label: `${liveRows.toLocaleString(\"en-US\")} rows / ${[2, 8, 16, 80, 160][index]} MiB`,\n limits: { liveRows, liveBytes: [2, 8, 16, 80, 160][index] * MiB },\n })),\n describe: (limits) => `${limits.liveRows.toLocaleString(\"en-US\")} rows / ${limits.liveBytes / MiB} MiB`,\n },\n {\n key: \"historyLines\",\n label: \"History per container\",\n hint: \"Maximum recent lines and data fetched for each container.\",\n presets: [500, 1000, 5000].map((historyLines, index) => ({\n label: `${historyLines.toLocaleString(\"en-US\")} lines / ${[0.5, 1, 5][index]} MiB`,\n limits: { historyLines, historyBytes: [0.5, 1, 5][index] * MiB },\n })),\n describe: (limits) => `${limits.historyLines.toLocaleString(\"en-US\")} lines / ${limits.historyBytes / MiB} MiB`,\n },\n {\n key: \"captureBytes\",\n label: \"Capture size\",\n hint: \"Maximum data stored in each temporary capture.\",\n presets: [64, 128, 256, 512].map((size) => ({\n label: `${size} MiB`,\n limits: { captureBytes: size * MiB },\n })),\n describe: (limits) => `${limits.captureBytes / MiB} MiB`,\n },\n {\n key: \"captures\",\n label: \"Saved captures\",\n hint: \"Maximum number of temporary captures retained.\",\n presets: [1, 3, 5, 10].map((captures) => ({\n label: `${captures} ${captures === 1 ? \"capture\" : \"captures\"}`,\n limits: { captures },\n })),\n describe: (limits) => `${limits.captures} captures`,\n },\n {\n key: \"ttlMs\",\n label: \"Retention\",\n hint: \"How long temporary captures remain available.\",\n presets: [30, 60, 360, 1440, 4320].map((minutes) => ({\n label:\n minutes >= 1440\n ? `${minutes / 1440} ${minutes === 1440 ? \"day\" : \"days\"}`\n : minutes < 60\n ? `${minutes} minutes`\n : `${minutes / 60} ${minutes === 60 ? \"hour\" : \"hours\"}`,\n limits: { ttlMs: minutes * 60000 },\n })),\n describe: (limits) => `${limits.ttlMs / 60000} minutes`,\n },\n];\n\nconst LogLimitSelect = observer(function LogLimitSelect({\n setting,\n preferences,\n}: {\n setting: LimitSetting;\n preferences: LogsPreferencesStore;\n}) {\n const selected = setting.presets.findIndex((preset) =>\n Object.entries(preset.limits).every(([key, value]) => preferences.limits[key as keyof PowerLogsLimits] === value),\n );\n const options = setting.presets.map((preset, index) => ({ value: String(index), label: preset.label }));\n if (selected === -1) options.push({ value: \"custom\", label: `Custom: ${setting.describe(preferences.limits)}` });\n const id = `freelens-power-logs-${setting.key}`;\n return (\n <div\n className=\"power-settings-row\"\n style={{ display: \"flex\", alignItems: \"center\", justifyContent: \"space-between\", gap: 20 }}\n >\n <div>\n <label id={`${id}-label`} htmlFor={id}>\n {setting.label}\n </label>\n <div className=\"power-settings-hint\">{setting.hint}</div>\n </div>\n <div style={{ width: 260, maxWidth: \"100%\", flexShrink: 0 }}>\n <Renderer.Component.Select\n id={id}\n aria-labelledby={`${id}-label`}\n options={options}\n value={selected === -1 ? \"custom\" : String(selected)}\n isSearchable={false}\n isClearable={false}\n onChange={(option) => {\n if (!option || option.value === \"custom\") return;\n const preset = setting.presets[Number(option.value)];\n if (!preset) return;\n preferences.limits = { ...preferences.limits, ...preset.limits };\n applyPowerLogsLimits(preferences.limits);\n }}\n />\n </div>\n </div>\n );\n});\n\nexport const LogsPreferences = observer(() => {\n const preferences = LogsPreferencesStore.getInstanceOrCreate<LogsPreferencesStore>();\n return (\n <div style={{ display: \"grid\", gap: 20 }}>\n <div>\n <Renderer.Component.Switch\n checked={preferences.enabled}\n onChange={(value) => {\n preferences.enabled = value;\n }}\n >\n Use Power Logs\n </Renderer.Component.Switch>\n <div className=\"power-settings-hint\">\n Colored workload logs and temporary SQLite captures for SQL analysis. Native logs return when disabled.\n Temporary captures follow the retention settings below and are deleted when Power Logs stops. Pinned snapshots\n remain until manually deleted.\n </div>\n </div>\n <div className=\"power-settings-hint\">\n Changes apply to new requests, captures and SQL queries. Existing captures retain their capacity and expiry.\n </div>\n {settings.map((setting) => (\n <LogLimitSelect key={setting.key} setting={setting} preferences={preferences} />\n ))}\n <div style={{ display: \"flex\", justifyContent: \"flex-end\" }}>\n <Renderer.Component.Button\n onClick={() => {\n preferences.limits = { ...POWER_LOGS_DEFAULT_LIMITS };\n applyPowerLogsLimits(preferences.limits);\n }}\n >\n <Renderer.Component.Icon material=\"restore\" size={16} /> Reset log limits\n </Renderer.Component.Button>\n </div>\n </div>\n );\n});\n"],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
//#region src/renderer/relationship-map-finding.ts
|
|
2
|
+
function relationshipMapFinding(clusterId, namespace, service, graph, hideUpstreams) {
|
|
3
|
+
const text = (value) => value.slice(0, 300);
|
|
4
|
+
const visible = graph.nodes.filter((node) => !hideUpstreams || node.role !== "upstream");
|
|
5
|
+
const nodes = visible.slice(0, 60);
|
|
6
|
+
const ids = new Set(nodes.map((node) => node.id));
|
|
7
|
+
const edges = graph.edges.filter((edge) => ids.has(edge.from) && ids.has(edge.to));
|
|
8
|
+
const snapshot = {
|
|
9
|
+
namespace,
|
|
10
|
+
service,
|
|
11
|
+
summary: text(graph.diagnostics.summary),
|
|
12
|
+
nodes: nodes.map(({ id, kind, name, role, detail, tone, inferred }) => ({
|
|
13
|
+
id: text(id),
|
|
14
|
+
kind,
|
|
15
|
+
name: text(name),
|
|
16
|
+
role,
|
|
17
|
+
detail: text(detail),
|
|
18
|
+
tone,
|
|
19
|
+
...inferred ? { inferred } : {}
|
|
20
|
+
})),
|
|
21
|
+
edges: edges.slice(0, 100).map(({ from, to, label }) => ({
|
|
22
|
+
from: text(from),
|
|
23
|
+
to: text(to),
|
|
24
|
+
label: text(label)
|
|
25
|
+
})),
|
|
26
|
+
gaps: graph.gaps.slice(0, 20).map(text),
|
|
27
|
+
omitted: graph.omitted + visible.length - nodes.length + Math.max(0, edges.length - 100),
|
|
28
|
+
upstreamsHidden: hideUpstreams,
|
|
29
|
+
scope: "Visible map snapshot from Kubernetes API evidence; does not prove network reachability"
|
|
30
|
+
};
|
|
31
|
+
let summary = JSON.stringify(snapshot);
|
|
32
|
+
while (summary.length > 8e3 && (snapshot.edges.length || snapshot.nodes.length)) {
|
|
33
|
+
if (snapshot.edges.length) snapshot.edges.pop();
|
|
34
|
+
else snapshot.nodes.pop();
|
|
35
|
+
snapshot.omitted++;
|
|
36
|
+
summary = JSON.stringify(snapshot);
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
clusterId,
|
|
40
|
+
source: "relationships",
|
|
41
|
+
title: `Relationships · ${service}`,
|
|
42
|
+
resource: {
|
|
43
|
+
kind: "Service",
|
|
44
|
+
name: service,
|
|
45
|
+
namespace
|
|
46
|
+
},
|
|
47
|
+
summary
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
//#endregion
|
|
51
|
+
exports.relationshipMapFinding = relationshipMapFinding;
|
|
52
|
+
|
|
53
|
+
//# sourceMappingURL=relationship-map-finding.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relationship-map-finding.js","names":[],"sources":["../../src/renderer/relationship-map-finding.ts"],"sourcesContent":["import type { buildResourceRelationships } from \"../common/resource-relationships\";\nimport type { DiagnosticFinding } from \"./ai-diagnostic-handoff\";\n\ntype RelationshipGraph = ReturnType<typeof buildResourceRelationships>;\n\nexport function relationshipMapFinding(\n clusterId: string,\n namespace: string,\n service: string,\n graph: RelationshipGraph,\n hideUpstreams: boolean,\n): DiagnosticFinding {\n const text = (value: string) => value.slice(0, 300);\n const visible = graph.nodes.filter((node) => !hideUpstreams || node.role !== \"upstream\");\n const nodes = visible.slice(0, 60);\n const ids = new Set(nodes.map((node) => node.id));\n const edges = graph.edges.filter((edge) => ids.has(edge.from) && ids.has(edge.to));\n const snapshot = {\n namespace,\n service,\n summary: text(graph.diagnostics.summary),\n nodes: nodes.map(({ id, kind, name, role, detail, tone, inferred }) => ({\n id: text(id),\n kind,\n name: text(name),\n role,\n detail: text(detail),\n tone,\n ...(inferred ? { inferred } : {}),\n })),\n edges: edges.slice(0, 100).map(({ from, to, label }) => ({ from: text(from), to: text(to), label: text(label) })),\n gaps: graph.gaps.slice(0, 20).map(text),\n omitted: graph.omitted + visible.length - nodes.length + Math.max(0, edges.length - 100),\n upstreamsHidden: hideUpstreams,\n scope: \"Visible map snapshot from Kubernetes API evidence; does not prove network reachability\",\n };\n let summary = JSON.stringify(snapshot);\n while (summary.length > 8000 && (snapshot.edges.length || snapshot.nodes.length)) {\n if (snapshot.edges.length) snapshot.edges.pop();\n else snapshot.nodes.pop();\n snapshot.omitted++;\n summary = JSON.stringify(snapshot);\n }\n return {\n clusterId,\n source: \"relationships\",\n title: `Relationships · ${service}`,\n resource: { kind: \"Service\", name: service, namespace },\n summary,\n };\n}\n"],"mappings":";AAKA,SAAgB,uBACd,WACA,WACA,SACA,OACA,eACmB;CACnB,MAAM,QAAQ,UAAkB,MAAM,MAAM,GAAG,GAAG;CAClD,MAAM,UAAU,MAAM,MAAM,QAAQ,SAAS,CAAC,iBAAiB,KAAK,SAAS,UAAU;CACvF,MAAM,QAAQ,QAAQ,MAAM,GAAG,EAAE;CACjC,MAAM,MAAM,IAAI,IAAI,MAAM,KAAK,SAAS,KAAK,EAAE,CAAC;CAChD,MAAM,QAAQ,MAAM,MAAM,QAAQ,SAAS,IAAI,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,KAAK,EAAE,CAAC;CACjF,MAAM,WAAW;EACf;EACA;EACA,SAAS,KAAK,MAAM,YAAY,OAAO;EACvC,OAAO,MAAM,KAAK,EAAE,IAAI,MAAM,MAAM,MAAM,QAAQ,MAAM,gBAAgB;GACtE,IAAI,KAAK,EAAE;GACX;GACA,MAAM,KAAK,IAAI;GACf;GACA,QAAQ,KAAK,MAAM;GACnB;GACA,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;EACjC,EAAE;EACF,OAAO,MAAM,MAAM,GAAG,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,IAAI,aAAa;GAAE,MAAM,KAAK,IAAI;GAAG,IAAI,KAAK,EAAE;GAAG,OAAO,KAAK,KAAK;EAAE,EAAE;EAChH,MAAM,MAAM,KAAK,MAAM,GAAG,EAAE,CAAC,CAAC,IAAI,IAAI;EACtC,SAAS,MAAM,UAAU,QAAQ,SAAS,MAAM,SAAS,KAAK,IAAI,GAAG,MAAM,SAAS,GAAG;EACvF,iBAAiB;EACjB,OAAO;CACT;CACA,IAAI,UAAU,KAAK,UAAU,QAAQ;CACrC,OAAO,QAAQ,SAAS,QAAS,SAAS,MAAM,UAAU,SAAS,MAAM,SAAS;EAChF,IAAI,SAAS,MAAM,QAAQ,SAAS,MAAM,IAAI;OACzC,SAAS,MAAM,IAAI;EACxB,SAAS;EACT,UAAU,KAAK,UAAU,QAAQ;CACnC;CACA,OAAO;EACL;EACA,QAAQ;EACR,OAAO,mBAAmB;EAC1B,UAAU;GAAE,MAAM;GAAW,MAAM;GAAS;EAAU;EACtD;CACF;AACF"}
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
//#region src/renderer/resource-relationships.css.ts
|
|
2
2
|
var resourceRelationshipsStyles = `
|
|
3
|
+
.power-relationships .graph-omitted-notice { display:flex; align-items:center; gap:8px; }
|
|
4
|
+
.graph-omitted-notice > span { flex:1; }
|
|
5
|
+
.graph-omitted-warning { color:var(--colorWarning); flex-shrink:0; }
|
|
6
|
+
.power-relationships .graph-show-all { display:inline-flex; padding:4px; border:0; background:transparent; color:inherit; }
|
|
7
|
+
.power-relationships .graph-show-all:hover, .power-relationships .graph-show-all:focus-visible { color:var(--primary); }
|
|
8
|
+
|
|
3
9
|
.power-relationships{height:100%;overflow:auto;box-sizing:border-box;min-width:0;padding:24px;max-width:1550px;margin:auto;color:var(--textColorPrimary)}.power-relationships h2{margin:0}.power-relationships .page-heading{display:flex;justify-content:space-between;align-items:center;gap:16px;flex-wrap:wrap;margin-bottom:8px}.power-relationships .intro{color:var(--textColorSecondary);max-width:900px;line-height:1.6}.power-relationships .controls{display:flex;gap:24px;align-items:end;flex-wrap:wrap;margin:24px 0}.power-relationships .control{min-width:200px;flex:1;max-width:340px}.power-relationships .control>span{display:block;font-size:12px;margin-bottom:8px;color:var(--textColorSecondary)}.power-relationships button{min-height:32px;cursor:pointer}.power-relationships .refresh{background:transparent;border:1px solid var(--borderColor);border-radius:5px;padding:5px 10px;color:var(--textColorPrimary);display:flex;align-items:center;gap:8px}.power-relationships .notice{padding:14px 16px;background:var(--contentColor);border:1px solid var(--borderColor);border-radius:7px;margin:16px 0;line-height:1.6}.power-relationships .warning{color:var(--colorWarning)}.power-relationships .healthy{color:var(--colorOk)}.power-relationships .neutral{color:var(--textColorSecondary)}.power-relationships .graph-scroll{min-width:0;max-width:100%;overflow:auto;margin-top:24px}.power-relationships .graph{min-width:1000px;display:grid;grid-template-columns:repeat(4,minmax(180px,1fr));column-gap:64px;row-gap:16px;position:relative;padding:6px 2px 56px}.power-relationships .graph.upstream-gutter{padding-left:42px}.power-relationships .gateway-evidence{font-size:11px}.power-relationships .gateway-evidence summary{min-height:24px}.power-relationships .graph.hide-upstreams{min-width:740px;grid-template-columns:repeat(3,minmax(180px,1fr))}.power-relationships .graph-option{display:inline-flex;align-items:center;justify-content:center;gap:8px;flex-shrink:0;min-height:32px;padding:5px 10px;border:1px solid var(--borderColor);border-radius:5px;background:transparent;color:var(--textColorPrimary);font:inherit;cursor:pointer;transition:background-color .15s,border-color .15s}.power-relationships .graph-option[aria-pressed="true"]{background:color-mix(in srgb,var(--primary) 14%,var(--contentColor));border-color:var(--primary);color:var(--primary)}.power-relationships .graph-option:hover,.power-relationships .refresh:hover{background:color-mix(in srgb,var(--primary) 10%,var(--contentColor))}.power-relationships .graph-option:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.power-relationships .column{position:relative;min-width:0;display:grid;grid-row:1/-1;grid-template-rows:subgrid}.power-relationships .column>h3{font-size:13px;margin:0;color:var(--textColorSecondary);font-weight:500}.power-relationships .card{background:var(--contentColor);border:1px solid var(--borderColor);border-radius:8px;padding:14px;margin:0;position:relative;z-index:1;overflow-wrap:anywhere}.power-relationships .card-kind{display:flex;align-items:center;gap:7px;font-size:11px;color:var(--textColorSecondary);margin-bottom:6px}.power-relationships .resource-name{font-size:14px;font-weight:600;color:var(--textColorPrimary);text-align:left;background:transparent;border:0;padding:0;max-width:100%}.power-relationships .resource-name:hover{color:var(--primary)}.power-relationships .card p{font-size:12px;line-height:1.5;margin:6px 0 0}.power-relationships .relation-label{font-size:10px;text-transform:uppercase;letter-spacing:.04em;color:var(--textColorSecondary);margin-bottom:6px}.power-relationships .resource-connections{position:absolute;inset:0;overflow:visible;pointer-events:none;color:var(--textColorSecondary)}.power-relationships .connection{fill:none;stroke:currentColor;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;opacity:.55;transition:opacity .15s,stroke .15s,stroke-width .15s}.power-relationships .connection.highlighted{opacity:1;stroke:var(--primary);stroke-width:2.5}.power-relationships .connection.dimmed{opacity:.12}.power-relationships .scope{max-width:68ch;margin-top:8px;color:var(--textColorSecondary);font-size:12px;line-height:1.6}.power-relationships .scope>span{display:block;margin-top:3px}.power-relationships details{margin-top:16px}.power-relationships summary{cursor:pointer;min-height:32px}.power-relationships .edge-list{columns:2;line-height:1.7;font-size:12px;list-style:none;padding:0}.power-relationships .empty{padding:28px;border:1px dashed var(--borderColor);border-radius:8px;color:var(--textColorSecondary);text-align:center}.power-relationships .relationship-summary{padding:16px;display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:12px 24px}.power-relationships .ports{margin-left:auto;justify-content:flex-end;display:flex;gap:12px;flex-wrap:wrap;font-size:12px}.power-relationships .ports span{padding:4px 8px;border-radius:4px;background:var(--contentColor);border:1px solid var(--borderColor)}@media(max-width:900px){.power-relationships{padding:16px}.power-relationships .controls{gap:16px}.power-relationships .edge-list{columns:1}}`;
|
|
4
10
|
//#endregion
|
|
5
11
|
exports.resourceRelationshipsStyles = resourceRelationshipsStyles;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resource-relationships.css.js","names":[],"sources":["../../src/renderer/resource-relationships.css.ts"],"sourcesContent":["export const resourceRelationshipsStyles = `\n.power-relationships{height:100%;overflow:auto;box-sizing:border-box;min-width:0;padding:24px;max-width:1550px;margin:auto;color:var(--textColorPrimary)}.power-relationships h2{margin:0}.power-relationships .page-heading{display:flex;justify-content:space-between;align-items:center;gap:16px;flex-wrap:wrap;margin-bottom:8px}.power-relationships .intro{color:var(--textColorSecondary);max-width:900px;line-height:1.6}.power-relationships .controls{display:flex;gap:24px;align-items:end;flex-wrap:wrap;margin:24px 0}.power-relationships .control{min-width:200px;flex:1;max-width:340px}.power-relationships .control>span{display:block;font-size:12px;margin-bottom:8px;color:var(--textColorSecondary)}.power-relationships button{min-height:32px;cursor:pointer}.power-relationships .refresh{background:transparent;border:1px solid var(--borderColor);border-radius:5px;padding:5px 10px;color:var(--textColorPrimary);display:flex;align-items:center;gap:8px}.power-relationships .notice{padding:14px 16px;background:var(--contentColor);border:1px solid var(--borderColor);border-radius:7px;margin:16px 0;line-height:1.6}.power-relationships .warning{color:var(--colorWarning)}.power-relationships .healthy{color:var(--colorOk)}.power-relationships .neutral{color:var(--textColorSecondary)}.power-relationships .graph-scroll{min-width:0;max-width:100%;overflow:auto;margin-top:24px}.power-relationships .graph{min-width:1000px;display:grid;grid-template-columns:repeat(4,minmax(180px,1fr));column-gap:64px;row-gap:16px;position:relative;padding:6px 2px 56px}.power-relationships .graph.upstream-gutter{padding-left:42px}.power-relationships .gateway-evidence{font-size:11px}.power-relationships .gateway-evidence summary{min-height:24px}.power-relationships .graph.hide-upstreams{min-width:740px;grid-template-columns:repeat(3,minmax(180px,1fr))}.power-relationships .graph-option{display:inline-flex;align-items:center;justify-content:center;gap:8px;flex-shrink:0;min-height:32px;padding:5px 10px;border:1px solid var(--borderColor);border-radius:5px;background:transparent;color:var(--textColorPrimary);font:inherit;cursor:pointer;transition:background-color .15s,border-color .15s}.power-relationships .graph-option[aria-pressed=\"true\"]{background:color-mix(in srgb,var(--primary) 14%,var(--contentColor));border-color:var(--primary);color:var(--primary)}.power-relationships .graph-option:hover,.power-relationships .refresh:hover{background:color-mix(in srgb,var(--primary) 10%,var(--contentColor))}.power-relationships .graph-option:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.power-relationships .column{position:relative;min-width:0;display:grid;grid-row:1/-1;grid-template-rows:subgrid}.power-relationships .column>h3{font-size:13px;margin:0;color:var(--textColorSecondary);font-weight:500}.power-relationships .card{background:var(--contentColor);border:1px solid var(--borderColor);border-radius:8px;padding:14px;margin:0;position:relative;z-index:1;overflow-wrap:anywhere}.power-relationships .card-kind{display:flex;align-items:center;gap:7px;font-size:11px;color:var(--textColorSecondary);margin-bottom:6px}.power-relationships .resource-name{font-size:14px;font-weight:600;color:var(--textColorPrimary);text-align:left;background:transparent;border:0;padding:0;max-width:100%}.power-relationships .resource-name:hover{color:var(--primary)}.power-relationships .card p{font-size:12px;line-height:1.5;margin:6px 0 0}.power-relationships .relation-label{font-size:10px;text-transform:uppercase;letter-spacing:.04em;color:var(--textColorSecondary);margin-bottom:6px}.power-relationships .resource-connections{position:absolute;inset:0;overflow:visible;pointer-events:none;color:var(--textColorSecondary)}.power-relationships .connection{fill:none;stroke:currentColor;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;opacity:.55;transition:opacity .15s,stroke .15s,stroke-width .15s}.power-relationships .connection.highlighted{opacity:1;stroke:var(--primary);stroke-width:2.5}.power-relationships .connection.dimmed{opacity:.12}.power-relationships .scope{max-width:68ch;margin-top:8px;color:var(--textColorSecondary);font-size:12px;line-height:1.6}.power-relationships .scope>span{display:block;margin-top:3px}.power-relationships details{margin-top:16px}.power-relationships summary{cursor:pointer;min-height:32px}.power-relationships .edge-list{columns:2;line-height:1.7;font-size:12px;list-style:none;padding:0}.power-relationships .empty{padding:28px;border:1px dashed var(--borderColor);border-radius:8px;color:var(--textColorSecondary);text-align:center}.power-relationships .relationship-summary{padding:16px;display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:12px 24px}.power-relationships .ports{margin-left:auto;justify-content:flex-end;display:flex;gap:12px;flex-wrap:wrap;font-size:12px}.power-relationships .ports span{padding:4px 8px;border-radius:4px;background:var(--contentColor);border:1px solid var(--borderColor)}@media(max-width:900px){.power-relationships{padding:16px}.power-relationships .controls{gap:16px}.power-relationships .edge-list{columns:1}}`;\n"],"mappings":";AAAA,IAAa,8BAA8B"}
|
|
1
|
+
{"version":3,"file":"resource-relationships.css.js","names":[],"sources":["../../src/renderer/resource-relationships.css.ts"],"sourcesContent":["export const resourceRelationshipsStyles = `\n.power-relationships .graph-omitted-notice { display:flex; align-items:center; gap:8px; }\n.graph-omitted-notice > span { flex:1; }\n.graph-omitted-warning { color:var(--colorWarning); flex-shrink:0; }\n.power-relationships .graph-show-all { display:inline-flex; padding:4px; border:0; background:transparent; color:inherit; }\n.power-relationships .graph-show-all:hover, .power-relationships .graph-show-all:focus-visible { color:var(--primary); }\n\n.power-relationships{height:100%;overflow:auto;box-sizing:border-box;min-width:0;padding:24px;max-width:1550px;margin:auto;color:var(--textColorPrimary)}.power-relationships h2{margin:0}.power-relationships .page-heading{display:flex;justify-content:space-between;align-items:center;gap:16px;flex-wrap:wrap;margin-bottom:8px}.power-relationships .intro{color:var(--textColorSecondary);max-width:900px;line-height:1.6}.power-relationships .controls{display:flex;gap:24px;align-items:end;flex-wrap:wrap;margin:24px 0}.power-relationships .control{min-width:200px;flex:1;max-width:340px}.power-relationships .control>span{display:block;font-size:12px;margin-bottom:8px;color:var(--textColorSecondary)}.power-relationships button{min-height:32px;cursor:pointer}.power-relationships .refresh{background:transparent;border:1px solid var(--borderColor);border-radius:5px;padding:5px 10px;color:var(--textColorPrimary);display:flex;align-items:center;gap:8px}.power-relationships .notice{padding:14px 16px;background:var(--contentColor);border:1px solid var(--borderColor);border-radius:7px;margin:16px 0;line-height:1.6}.power-relationships .warning{color:var(--colorWarning)}.power-relationships .healthy{color:var(--colorOk)}.power-relationships .neutral{color:var(--textColorSecondary)}.power-relationships .graph-scroll{min-width:0;max-width:100%;overflow:auto;margin-top:24px}.power-relationships .graph{min-width:1000px;display:grid;grid-template-columns:repeat(4,minmax(180px,1fr));column-gap:64px;row-gap:16px;position:relative;padding:6px 2px 56px}.power-relationships .graph.upstream-gutter{padding-left:42px}.power-relationships .gateway-evidence{font-size:11px}.power-relationships .gateway-evidence summary{min-height:24px}.power-relationships .graph.hide-upstreams{min-width:740px;grid-template-columns:repeat(3,minmax(180px,1fr))}.power-relationships .graph-option{display:inline-flex;align-items:center;justify-content:center;gap:8px;flex-shrink:0;min-height:32px;padding:5px 10px;border:1px solid var(--borderColor);border-radius:5px;background:transparent;color:var(--textColorPrimary);font:inherit;cursor:pointer;transition:background-color .15s,border-color .15s}.power-relationships .graph-option[aria-pressed=\"true\"]{background:color-mix(in srgb,var(--primary) 14%,var(--contentColor));border-color:var(--primary);color:var(--primary)}.power-relationships .graph-option:hover,.power-relationships .refresh:hover{background:color-mix(in srgb,var(--primary) 10%,var(--contentColor))}.power-relationships .graph-option:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.power-relationships .column{position:relative;min-width:0;display:grid;grid-row:1/-1;grid-template-rows:subgrid}.power-relationships .column>h3{font-size:13px;margin:0;color:var(--textColorSecondary);font-weight:500}.power-relationships .card{background:var(--contentColor);border:1px solid var(--borderColor);border-radius:8px;padding:14px;margin:0;position:relative;z-index:1;overflow-wrap:anywhere}.power-relationships .card-kind{display:flex;align-items:center;gap:7px;font-size:11px;color:var(--textColorSecondary);margin-bottom:6px}.power-relationships .resource-name{font-size:14px;font-weight:600;color:var(--textColorPrimary);text-align:left;background:transparent;border:0;padding:0;max-width:100%}.power-relationships .resource-name:hover{color:var(--primary)}.power-relationships .card p{font-size:12px;line-height:1.5;margin:6px 0 0}.power-relationships .relation-label{font-size:10px;text-transform:uppercase;letter-spacing:.04em;color:var(--textColorSecondary);margin-bottom:6px}.power-relationships .resource-connections{position:absolute;inset:0;overflow:visible;pointer-events:none;color:var(--textColorSecondary)}.power-relationships .connection{fill:none;stroke:currentColor;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;opacity:.55;transition:opacity .15s,stroke .15s,stroke-width .15s}.power-relationships .connection.highlighted{opacity:1;stroke:var(--primary);stroke-width:2.5}.power-relationships .connection.dimmed{opacity:.12}.power-relationships .scope{max-width:68ch;margin-top:8px;color:var(--textColorSecondary);font-size:12px;line-height:1.6}.power-relationships .scope>span{display:block;margin-top:3px}.power-relationships details{margin-top:16px}.power-relationships summary{cursor:pointer;min-height:32px}.power-relationships .edge-list{columns:2;line-height:1.7;font-size:12px;list-style:none;padding:0}.power-relationships .empty{padding:28px;border:1px dashed var(--borderColor);border-radius:8px;color:var(--textColorSecondary);text-align:center}.power-relationships .relationship-summary{padding:16px;display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:12px 24px}.power-relationships .ports{margin-left:auto;justify-content:flex-end;display:flex;gap:12px;flex-wrap:wrap;font-size:12px}.power-relationships .ports span{padding:4px 8px;border-radius:4px;background:var(--contentColor);border:1px solid var(--borderColor)}@media(max-width:900px){.power-relationships{padding:16px}.power-relationships .controls{gap:16px}.power-relationships .edge-list{columns:1}}`;\n"],"mappings":";AAAA,IAAa,8BAA8B"}
|
|
@@ -4,9 +4,11 @@ const require_monitoring_preferences_store = require("./src/common/store/monitor
|
|
|
4
4
|
const require__global_external_react = require("./_virtual/_global-external_react.js");
|
|
5
5
|
const require_jsx_runtime = require("./_virtual/_global-external_react/jsx-runtime.js");
|
|
6
6
|
const require_native_tooltip = require("./native-tooltip.js");
|
|
7
|
+
const require_ai_diagnostic_handoff = require("./ai-diagnostic-handoff.js");
|
|
7
8
|
const require_resource_search_client = require("./resource-search-client.js");
|
|
8
9
|
const require_resource_relationships = require("./src/common/resource-relationships.js");
|
|
9
10
|
const require_gateway_relationships_client = require("./gateway-relationships-client.js");
|
|
11
|
+
const require_relationship_map_finding = require("./relationship-map-finding.js");
|
|
10
12
|
const require_resource_relationships_css = require("./resource-relationships.css.js");
|
|
11
13
|
const require_resource_search_routing = require("./resource-search-routing.js");
|
|
12
14
|
//#region src/renderer/resource-relationships.tsx
|
|
@@ -307,6 +309,12 @@ function EnabledResourceRelationshipsPage() {
|
|
|
307
309
|
const [services, setServices] = require__global_external_react.useState([]);
|
|
308
310
|
const [serviceName, setServiceName] = require__global_external_react.useState("");
|
|
309
311
|
const [focusedPod, setFocusedPod] = require__global_external_react.useState("");
|
|
312
|
+
const [showAll, setShowAll] = require__global_external_react.useState(false);
|
|
313
|
+
require__global_external_react.useEffect(() => setShowAll(false), [
|
|
314
|
+
namespace,
|
|
315
|
+
serviceName,
|
|
316
|
+
focusedPod
|
|
317
|
+
]);
|
|
310
318
|
const preferences = require_monitoring_preferences_store.MonitoringPreferencesStore.getInstanceOrCreate();
|
|
311
319
|
const [hideUpstreams, setHideUpstreams] = require__global_external_react.useState(() => preferences.hiddenUpstreamClusters.includes(clusterId.current ?? ""));
|
|
312
320
|
const toggleUpstreams = () => {
|
|
@@ -393,7 +401,20 @@ function EnabledResourceRelationshipsPage() {
|
|
|
393
401
|
refresh
|
|
394
402
|
]);
|
|
395
403
|
const current = inventory?.namespace === namespace && inventory.service === serviceName ? inventory : void 0;
|
|
396
|
-
const graph = current && service ? require_resource_relationships.buildResourceRelationships(service, current.data, focusedPod || void 0) : void 0;
|
|
404
|
+
const graph = current && service ? require_resource_relationships.buildResourceRelationships(service, current.data, focusedPod || void 0, showAll) : void 0;
|
|
405
|
+
require__global_external_react.useEffect(() => {
|
|
406
|
+
if (!graph || loading || !clusterId.current) return;
|
|
407
|
+
const id = clusterId.current;
|
|
408
|
+
const attach = () => require_ai_diagnostic_handoff.explainDiagnosticFinding(require_relationship_map_finding.relationshipMapFinding(id, namespace, serviceName, graph, hideUpstreams));
|
|
409
|
+
window.addEventListener("power-ai-request-screen-context", attach);
|
|
410
|
+
return () => window.removeEventListener("power-ai-request-screen-context", attach);
|
|
411
|
+
}, [
|
|
412
|
+
graph,
|
|
413
|
+
loading,
|
|
414
|
+
namespace,
|
|
415
|
+
serviceName,
|
|
416
|
+
hideUpstreams
|
|
417
|
+
]);
|
|
397
418
|
const openResource = (path) => {
|
|
398
419
|
const currentCluster = () => mounted.current && require_extensions.Renderer.Catalog.activeCluster.get()?.metadata.uid === clusterId.current;
|
|
399
420
|
setOpenError("");
|
|
@@ -475,7 +496,7 @@ function EnabledResourceRelationshipsPage() {
|
|
|
475
496
|
value: focusedPod,
|
|
476
497
|
options: [{
|
|
477
498
|
value: "",
|
|
478
|
-
label: "All selected pods (up to 8)"
|
|
499
|
+
label: showAll ? "All selected pods" : "All selected pods (up to 8)"
|
|
479
500
|
}, ...(graph?.podOptions ?? []).map((name) => ({
|
|
480
501
|
value: name,
|
|
481
502
|
label: name
|
|
@@ -570,9 +591,33 @@ function EnabledResourceRelationshipsPage() {
|
|
|
570
591
|
ingressAvailable: current?.data.ingresses !== void 0,
|
|
571
592
|
hideUpstreams
|
|
572
593
|
}),
|
|
573
|
-
graph.omitted > 0 && /* @__PURE__ */ require_jsx_runtime.jsxs("div", {
|
|
574
|
-
className: "notice",
|
|
575
|
-
children: [
|
|
594
|
+
(graph.omitted > 0 || showAll) && /* @__PURE__ */ require_jsx_runtime.jsxs("div", {
|
|
595
|
+
className: "notice graph-omitted-notice",
|
|
596
|
+
children: [
|
|
597
|
+
!showAll && /* @__PURE__ */ require_jsx_runtime.jsx(Icon, {
|
|
598
|
+
material: "warning_amber",
|
|
599
|
+
className: "graph-omitted-warning",
|
|
600
|
+
size: 16
|
|
601
|
+
}),
|
|
602
|
+
/* @__PURE__ */ require_jsx_runtime.jsx("span", { children: showAll ? "All available resources are shown." : /* @__PURE__ */ require_jsx_runtime.jsxs(require_jsx_runtime.Fragment, { children: [
|
|
603
|
+
"Hidden resources: ",
|
|
604
|
+
/* @__PURE__ */ require_jsx_runtime.jsx("strong", { children: graph.omitted }),
|
|
605
|
+
". Show all to expand the map."
|
|
606
|
+
] }) }),
|
|
607
|
+
!showAll && /* @__PURE__ */ require_jsx_runtime.jsx(require_native_tooltip.NativeTooltip, {
|
|
608
|
+
title: "Show all available resources",
|
|
609
|
+
children: /* @__PURE__ */ require_jsx_runtime.jsx("button", {
|
|
610
|
+
type: "button",
|
|
611
|
+
className: "graph-show-all",
|
|
612
|
+
"aria-label": "Show all available resources",
|
|
613
|
+
onClick: () => setShowAll(true),
|
|
614
|
+
children: /* @__PURE__ */ require_jsx_runtime.jsx(Icon, {
|
|
615
|
+
material: "visibility",
|
|
616
|
+
size: 16
|
|
617
|
+
})
|
|
618
|
+
})
|
|
619
|
+
})
|
|
620
|
+
]
|
|
576
621
|
}),
|
|
577
622
|
/* @__PURE__ */ require_jsx_runtime.jsxs("details", { children: [/* @__PURE__ */ require_jsx_runtime.jsxs("summary", { children: [
|
|
578
623
|
"Accessible connection list (",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resource-relationships.js","names":[],"sources":["../../src/renderer/resource-relationships.tsx"],"sourcesContent":["import { Renderer } from \"@freelensapp/extensions\";\nimport { observer } from \"mobx-react\";\nimport { useEffect, useLayoutEffect, useRef, useState } from \"react\";\nimport {\n buildResourceRelationships,\n type RelationshipInventory,\n type RelationshipNode,\n type RelationshipObject,\n} from \"../common/resource-relationships\";\nimport { MonitoringPreferencesStore } from \"../common/store/monitoring-preferences-store\";\nimport { loadGatewayInventory } from \"./gateway-relationships-client\";\nimport { NativeTooltip } from \"./native-tooltip\";\nimport { resourceRelationshipsStyles } from \"./resource-relationships.css\";\nimport { createResourceSearchTransport } from \"./resource-search-client\";\nimport { openSearchResource } from \"./resource-search-routing\";\n\nconst { Icon, Select } = Renderer.Component;\nconst LIMIT = 100;\ntype Service = Renderer.K8sApi.Service;\ninterface InventoryState {\n namespace: string;\n service: string;\n data: RelationshipInventory;\n}\nconst roles = [\n { id: \"upstream\", name: \"Upstream references\", relation: \"references backend\" },\n { id: \"service\", name: \"Focused Service\", relation: \"API configuration\" },\n { id: \"backend\", name: \"Selected & published backends\", relation: \"selector matches / published in\" },\n { id: \"placement\", name: \"Ownership & placement\", relation: \"owned by / assigned to\" },\n] as const;\nconst icons: Record<string, string> = {\n Ingress: \"login\",\n Service: \"share\",\n Pod: \"view_in_ar\",\n EndpointSlice: \"hub\",\n Node: \"dns\",\n ReplicaSet: \"layers\",\n Deployment: \"layers\",\n StatefulSet: \"layers\",\n DaemonSet: \"layers\",\n Job: \"work\",\n CronJob: \"schedule\",\n};\nexport async function loadRelationshipInventory(\n namespace: string,\n service: Service,\n signal: AbortSignal,\n): Promise<RelationshipInventory> {\n const gaps: string[] = [];\n const list = async <T,>(name: string, request: () => Promise<T[] | null>) => {\n try {\n const items = await request();\n if (!items) {\n gaps.push(`${name} inventory unavailable`);\n return undefined;\n }\n if (items.length > LIMIT)\n gaps.push(`${name} inventory capped at ${LIMIT} objects; additional relationships may be omitted`);\n return items.slice(0, LIMIT);\n } catch {\n if (!signal.aborted) gaps.push(`${name} inventory unavailable; access or API availability may be restricted`);\n return undefined;\n }\n };\n const options = { namespace, reqInit: { signal } };\n const query = { limit: LIMIT + 1 };\n const selector = Object.entries(service.spec.selector ?? {})\n .map(([key, value]) => `${key}=${value}`)\n .join(\",\");\n const external = service.spec.type === \"ExternalName\";\n const ownerApis = external\n ? []\n : [\n Renderer.K8sApi.replicaSetApi,\n Renderer.K8sApi.deploymentApi,\n Renderer.K8sApi.statefulSetApi,\n Renderer.K8sApi.daemonSetApi,\n Renderer.K8sApi.jobApi,\n Renderer.K8sApi.cronJobApi,\n ];\n const [pods, slices, ingresses, ...owners] = await Promise.all([\n selector && !external\n ? list(\"Pod\", () => Renderer.K8sApi.podsApi.list(options, { ...query, labelSelector: selector }))\n : Promise.resolve([]),\n service.spec.type === \"ExternalName\"\n ? Promise.resolve([])\n : list(\"EndpointSlice\", () =>\n Renderer.K8sApi.endpointSliceApi.list(options, {\n ...query,\n labelSelector: `kubernetes.io/service-name=${service.getName()}`,\n }),\n ),\n list(\"Ingress\", () => Renderer.K8sApi.ingressApi.list(options, query)),\n ...ownerApis.map((api) => list<RelationshipObject>(\"Controller\", () => api.list(options, query))),\n ]);\n const clusterId = Renderer.Catalog.activeCluster.get()?.metadata.uid;\n const gateway = clusterId\n ? await loadGatewayInventory(createResourceSearchTransport(clusterId, signal), signal, {\n focusedNamespace: namespace,\n })\n : undefined;\n return { pods, slices, ingresses, owners: owners.flatMap((items) => items ?? []), gaps, gateway };\n}\nfunction ResourceCard({\n node,\n incoming,\n incomingEvidence,\n onOpen,\n onHighlight,\n}: {\n onHighlight: (id?: string) => void;\n node: RelationshipNode;\n incoming: string[];\n incomingEvidence?: string[];\n onOpen: (path: string) => void;\n}) {\n return (\n <article\n className=\"card\"\n data-node-id={node.id}\n onMouseEnter={() => onHighlight(node.id)}\n onMouseLeave={() => onHighlight()}\n onFocus={() => onHighlight(node.id)}\n onBlur={() => onHighlight()}\n >\n <div className=\"relation-label\">{incoming.join(\" · \") || \"Focus\"}</div>\n <div className=\"card-kind\">\n <Icon material={icons[node.kind] ?? \"account_tree\"} size={16} />\n {node.kind}\n {node.inferred && \" · reference\"}\n </div>\n {node.selfLink ? (\n <NativeTooltip title={`Open ${node.kind} ${node.name}`}>\n <button\n type=\"button\"\n className=\"resource-name\"\n onClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n onOpen(node.selfLink as string);\n }}\n >\n {node.name}\n </button>\n </NativeTooltip>\n ) : (\n <strong>{node.name}</strong>\n )}\n <p className={node.tone}>\n <Icon\n material={node.tone === \"warning\" ? \"warning\" : node.tone === \"healthy\" ? \"check_circle\" : \"info\"}\n size={14}\n />{\" \"}\n {node.detail}\n </p>\n {!!(node.evidence?.length || incomingEvidence?.length) && (\n <details className=\"gateway-evidence\">\n <summary>API evidence</summary>\n {[...(node.evidence ?? []), ...(incomingEvidence ?? [])].map((evidence) => (\n <p key={evidence}>{evidence}</p>\n ))}\n </details>\n )}\n </article>\n );\n}\nfunction roundedConnector(points: [number, number][]) {\n let path = `M ${points[0][0]} ${points[0][1]}`;\n for (let index = 1; index < points.length - 1; index++) {\n const [x, y] = points[index];\n const [px, py] = points[index - 1];\n const [nx, ny] = points[index + 1];\n const before = Math.hypot(x - px, y - py);\n const after = Math.hypot(nx - x, ny - y);\n if (!before || !after) continue;\n const radius = Math.min(6, before / 2, after / 2);\n path += ` L ${x + ((px - x) * radius) / before} ${y + ((py - y) * radius) / before}`;\n path += ` Q ${x} ${y} ${x + ((nx - x) * radius) / after} ${y + ((ny - y) * radius) / after}`;\n }\n const last = points[points.length - 1];\n return `${path} L ${last[0]} ${last[1]}`;\n}\nexport function RelationshipGraph({\n graph,\n onOpen,\n ingressAvailable,\n hideUpstreams = false,\n}: {\n graph: ReturnType<typeof buildResourceRelationships>;\n onOpen: (path: string) => void;\n ingressAvailable: boolean;\n hideUpstreams?: boolean;\n}) {\n const upstreamIds = new Set(graph.nodes.filter((node) => node.role === \"upstream\").map((node) => node.id));\n const upstreamGutter =\n !hideUpstreams && graph.edges.some((edge) => upstreamIds.has(edge.from) && upstreamIds.has(edge.to));\n const visibleRoles = roles.filter((role) => !hideUpstreams || role.id !== \"upstream\");\n const element = useRef<HTMLDivElement>(null);\n const [paths, setPaths] = useState<{ from: string; to: string; label: string; path: string }[]>([]);\n const [highlight, setHighlight] = useState<string>();\n useLayoutEffect(() => {\n const container = element.current;\n if (!container) return;\n const measure = () => {\n const origin = container.getBoundingClientRect();\n const cards = new Map(\n Array.from(container.querySelectorAll<HTMLElement>(\"[data-node-id]\")).map((card) => [\n card.dataset.nodeId,\n card.getBoundingClientRect(),\n ]),\n );\n setPaths(\n graph.edges.flatMap((edge, index) => {\n const from = cards.get(edge.from);\n const to = cards.get(edge.to);\n if (!from || !to) return [];\n const sy = from.top + from.height / 2 - origin.top;\n const ty = to.top + to.height / 2 - origin.top;\n const sameColumn = Math.abs(from.left - to.left) < 2;\n const sx = (sameColumn ? from.left : from.right) - origin.left;\n const tx = to.left - origin.left;\n const laneOffset = ((index % 3) - 1) * 8;\n const gutter = sameColumn ? sx - 28 + laneOffset : (sx + tx) / 2 + laneOffset;\n const crossesColumn = Array.from(cards.values()).some(\n (card) => card.left > from.left + 2 && card.right < to.left - 2,\n );\n let path =\n !sameColumn && sy === ty\n ? `M ${sx} ${sy} H ${tx}`\n : roundedConnector([\n [sx, sy],\n [gutter, sy],\n [gutter, ty],\n [tx, ty],\n ]);\n if (crossesColumn) {\n const bottom =\n Math.max(...Array.from(cards.values(), (card) => card.bottom)) - origin.top + 24 + (index % 3) * 8;\n const sourceGutter = sx + 32 + laneOffset;\n const targetGutter = tx - 32 + laneOffset;\n path = roundedConnector([\n [sx, sy],\n [sourceGutter, sy],\n [sourceGutter, bottom],\n [targetGutter, bottom],\n [targetGutter, ty],\n [tx, ty],\n ]);\n }\n return [{ ...edge, path }];\n }),\n );\n };\n measure();\n const observer = typeof ResizeObserver === \"undefined\" ? undefined : new ResizeObserver(measure);\n observer?.observe(container);\n for (const card of container.querySelectorAll(\"[data-node-id]\")) observer?.observe(card);\n window.addEventListener(\"resize\", measure);\n return () => {\n observer?.disconnect();\n window.removeEventListener(\"resize\", measure);\n };\n }, [graph, hideUpstreams]);\n return (\n <div className=\"graph-scroll\">\n <div\n ref={element}\n className={`graph${hideUpstreams ? \" hide-upstreams\" : \"\"}${upstreamGutter ? \" upstream-gutter\" : \"\"}`}\n style={{\n gridTemplateRows: `auto repeat(${Math.max(1, ...visibleRoles.map((role) => graph.nodes.filter((node) => node.role === role.id).length))}, auto)`,\n }}\n aria-label=\"Service resource relationship graph\"\n >\n <svg className=\"resource-connections\" width=\"100%\" height=\"100%\" aria-hidden=\"true\">\n <defs>\n <marker id=\"relationship-arrow\" markerWidth=\"5\" markerHeight=\"5\" refX=\"4\" refY=\"2.5\" orient=\"auto\">\n <path d=\"M0 0L5 2.5L0 5\" fill=\"currentColor\" />\n </marker>\n </defs>\n {paths.map((edge) => (\n <NativeTooltip\n key={`${edge.from}/${edge.to}/${edge.label}`}\n title={`${graph.nodes.find((node) => node.id === edge.from)?.name} → ${edge.label} → ${graph.nodes.find((node) => node.id === edge.to)?.name}`}\n >\n <path\n data-edge-from={edge.from}\n data-edge-to={edge.to}\n className={\n highlight\n ? edge.from === highlight || edge.to === highlight\n ? \"connection highlighted\"\n : \"connection dimmed\"\n : \"connection\"\n }\n d={edge.path}\n markerEnd=\"url(#relationship-arrow)\"\n />\n </NativeTooltip>\n ))}\n </svg>\n {visibleRoles.map((role) => (\n <section className=\"column\" key={role.id} aria-label={role.name}>\n <h3>{role.name}</h3>\n {graph.nodes\n .filter((node) => node.role === role.id)\n .map((node) => (\n <ResourceCard\n key={node.id}\n node={node}\n incoming={[...new Set(graph.edges.filter((edge) => edge.to === node.id).map((edge) => edge.label))]}\n incomingEvidence={graph.edges\n .filter((edge) => edge.to === node.id && edge.evidence)\n .map((edge) => edge.evidence as string)}\n onOpen={onOpen}\n onHighlight={setHighlight}\n />\n ))}\n {!graph.nodes.some((node) => node.role === role.id) && (\n <div className=\"card neutral\">\n {role.id === \"upstream\"\n ? ingressAvailable\n ? \"No matching upstream references observed\"\n : \"Ingress evidence unavailable\"\n : \"No relationships observed in available evidence\"}\n </div>\n )}\n </section>\n ))}\n </div>\n </div>\n );\n}\nexport const ResourceRelationshipsPage = observer(({ enabled = true }: { enabled?: boolean }) => {\n if (!enabled)\n return (\n <div className=\"power-relationships\">\n <p>Resource relationships are disabled in Power settings</p>\n </div>\n );\n return <EnabledResourceRelationshipsPage key={Renderer.Catalog.activeCluster.get()?.metadata.uid ?? \"cluster\"} />;\n});\nfunction EnabledResourceRelationshipsPage() {\n const mounted = useRef(true);\n const clusterId = useRef(Renderer.Catalog.activeCluster.get()?.metadata.uid);\n useEffect(() => {\n mounted.current = true;\n return () => {\n mounted.current = false;\n };\n }, []);\n const [namespaces, setNamespaces] = useState<string[]>([]);\n const [namespace, setNamespace] = useState(\"\");\n const [services, setServices] = useState<Service[]>([]);\n const [serviceName, setServiceName] = useState(\"\");\n const [focusedPod, setFocusedPod] = useState(\"\");\n const preferences = MonitoringPreferencesStore.getInstanceOrCreate<MonitoringPreferencesStore>();\n const [hideUpstreams, setHideUpstreams] = useState(() =>\n preferences.hiddenUpstreamClusters.includes(clusterId.current ?? \"\"),\n );\n const toggleUpstreams = () => {\n const id = clusterId.current;\n if (!id || Renderer.Catalog.activeCluster.get()?.metadata.uid !== id) return;\n const hidden = !hideUpstreams;\n const otherClusters = preferences.hiddenUpstreamClusters.filter((cluster) => cluster !== id);\n preferences.hiddenUpstreamClusters = hidden ? [...otherClusters, id].slice(-100) : otherClusters;\n setHideUpstreams(hidden);\n };\n const [inventory, setInventory] = useState<InventoryState>();\n const [refresh, setRefresh] = useState(0);\n const [scopeRefresh, setScopeRefresh] = useState(0);\n const [namespaceMessage, setNamespaceMessage] = useState(\"\");\n const [scopeLoading, setScopeLoading] = useState(true);\n const [loading, setLoading] = useState(false);\n const [scopeMessage, setScopeMessage] = useState(\"\");\n const [openError, setOpenError] = useState(\"\");\n useEffect(() => {\n const controller = new AbortController();\n setScopeLoading(true);\n setNamespaceMessage(\"\");\n void Renderer.K8sApi.namespacesApi\n .list({ reqInit: { signal: controller.signal } }, { limit: LIMIT + 1 })\n .then((items) => {\n if (controller.signal.aborted) return;\n const names = (items ?? [])\n .slice(0, LIMIT)\n .map((item) => item.getName())\n .sort();\n setNamespaces(names);\n setNamespace((current) => (names.includes(current) ? current : (names[0] ?? \"\")));\n if ((items?.length ?? 0) > LIMIT) setNamespaceMessage(`Namespace selector is capped at ${LIMIT} entries`);\n else if (!names.length) setScopeMessage(\"No visible namespaces returned by the API\");\n })\n .catch(() => {\n if (!controller.signal.aborted)\n setScopeMessage(\"Namespace inventory unavailable; check access to namespace listing\");\n })\n .finally(() => {\n if (!controller.signal.aborted) setScopeLoading(false);\n });\n return () => controller.abort();\n }, [scopeRefresh]);\n useEffect(() => {\n if (!namespace) return;\n const controller = new AbortController();\n setLoading(false);\n setServices([]);\n setServiceName(\"\");\n setInventory(undefined);\n setScopeLoading(true);\n setScopeMessage(\"\");\n void Renderer.K8sApi.serviceApi\n .list({ namespace, reqInit: { signal: controller.signal } }, { limit: LIMIT + 1 })\n .then((items) => {\n if (controller.signal.aborted) return;\n const visible = (items ?? []).slice(0, LIMIT).sort((a, b) => a.getName().localeCompare(b.getName()));\n setServices(visible);\n setServiceName(visible[0]?.getName() ?? \"\");\n if ((items?.length ?? 0) > LIMIT)\n setScopeMessage(`Service selector is capped at ${LIMIT} entries; additional Services are not shown`);\n else if (!visible.length) setScopeMessage(\"No visible Services in this namespace\");\n })\n .catch(() => {\n if (!controller.signal.aborted) setScopeMessage(\"Service inventory unavailable; check namespace access\");\n })\n .finally(() => {\n if (!controller.signal.aborted) setScopeLoading(false);\n });\n return () => controller.abort();\n }, [namespace, scopeRefresh]);\n const service = services.find((item) => item.getName() === serviceName);\n useEffect(() => {\n if (!service || !namespace || service.metadata.namespace !== namespace) return;\n const controller = new AbortController();\n setLoading(true);\n setInventory(undefined);\n setFocusedPod(\"\");\n setOpenError(\"\");\n void loadRelationshipInventory(namespace, service, controller.signal)\n .then((data) => {\n if (!controller.signal.aborted) setInventory({ namespace, service: service.getName(), data });\n })\n .finally(() => {\n if (!controller.signal.aborted) setLoading(false);\n });\n return () => controller.abort();\n }, [namespace, service, refresh]);\n const current = inventory?.namespace === namespace && inventory.service === serviceName ? inventory : undefined;\n const graph =\n current && service ? buildResourceRelationships(service, current.data, focusedPod || undefined) : undefined;\n const openResource = (path: string) => {\n const currentCluster = () =>\n mounted.current && Renderer.Catalog.activeCluster.get()?.metadata.uid === clusterId.current;\n setOpenError(\"\");\n void Promise.resolve()\n .then(() => {\n if (!currentCluster()) return;\n const gatewayPath = path.match(\n /^\\/apis\\/(gateway\\.networking\\.k8s\\.io)\\/([^/]+)\\/(?:namespaces\\/([^/]+)\\/)?([^/]+)\\/([^/]+)$/,\n );\n if (gatewayPath) {\n const [, group, version, namespace, resource, name] = gatewayPath;\n const kind = (\n {\n gateways: \"Gateway\",\n gatewayclasses: \"GatewayClass\",\n httproutes: \"HTTPRoute\",\n grpcroutes: \"GRPCRoute\",\n tcproutes: \"TCPRoute\",\n tlsroutes: \"TLSRoute\",\n udproutes: \"UDPRoute\",\n } as Record<string, string>\n )[resource];\n return openSearchResource({ path, group, version, namespace, resource, name, kind, labels: {} });\n }\n return Renderer.Navigation.showDetails(path);\n })\n .catch(() => {\n if (currentCluster()) setOpenError(\"Resource details could not be opened; the object may be unavailable\");\n });\n };\n return (\n <div className=\"power-relationships\">\n <style>{resourceRelationshipsStyles}</style>\n <div className=\"page-heading\">\n <h2>Resource relationships</h2>\n </div>\n <p className=\"intro\">\n Follow one Service from upstream Ingress and Gateway API references to selected pods, published EndpointSlices\n and controller ownership. Connections show Kubernetes API evidence; they do not prove network reachability.\n </p>\n <div className=\"controls\">\n <label className=\"control\">\n <span>Namespace</span>\n <Select\n aria-label=\"Relationship namespace\"\n value={namespace}\n options={namespaces.map((name) => ({ value: name, label: name }))}\n onChange={(option) => setNamespace(option?.value ?? \"\")}\n isDisabled={!namespaces.length}\n />\n </label>\n <label className=\"control\">\n <span>Service</span>\n <Select\n aria-label=\"Relationship Service\"\n value={serviceName}\n options={services.map((item) => ({ value: item.getName(), label: item.getName() }))}\n onChange={(option) => setServiceName(option?.value ?? \"\")}\n isDisabled={!services.length || scopeLoading}\n />\n </label>\n <label className=\"control\">\n <span>Pod focus</span>\n <Select\n aria-label=\"Relationship pod focus\"\n value={focusedPod}\n options={[\n { value: \"\", label: \"All selected pods (up to 8)\" },\n ...(graph?.podOptions ?? []).map((name) => ({ value: name, label: name })),\n ]}\n onChange={(option) => setFocusedPod(option?.value ?? \"\")}\n isDisabled={!graph?.podOptions.length}\n />\n </label>\n <NativeTooltip title={hideUpstreams ? \"Show upstream references\" : \"Hide upstream references\"}>\n <button\n type=\"button\"\n className=\"graph-option\"\n aria-pressed={hideUpstreams}\n onClick={toggleUpstreams}\n disabled={!clusterId.current}\n >\n <Icon material={hideUpstreams ? \"visibility_off\" : \"visibility\"} size={16} />\n Hide Upstream\n </button>\n </NativeTooltip>\n <NativeTooltip title=\"Refresh scoped API evidence\">\n <button\n type=\"button\"\n className=\"refresh\"\n onClick={() => (service ? setRefresh((value) => value + 1) : setScopeRefresh((value) => value + 1))}\n disabled={loading || scopeLoading}\n >\n <Icon material=\"refresh\" size={18} />\n Refresh\n </button>\n </NativeTooltip>\n </div>\n {namespaceMessage && (\n <div className=\"notice\" role=\"status\">\n {namespaceMessage}\n </div>\n )}\n {scopeMessage && (\n <div className=\"notice\" role=\"status\">\n {scopeMessage}\n </div>\n )}\n {openError && (\n <div className=\"notice warning\" role=\"alert\">\n {openError}\n </div>\n )}\n {(scopeLoading || loading) && (\n <div className=\"empty\" role=\"status\">\n Loading scoped relationship evidence…\n </div>\n )}\n {!scopeLoading && !loading && !service && (\n <div className=\"empty\">Select a namespace with a visible Service to inspect relationships</div>\n )}\n {graph && !loading && (\n <>\n <div className=\"notice relationship-summary\">\n <strong>{graph.diagnostics.summary}</strong>\n <div className=\"ports\">\n {graph.diagnostics.ports.map((port) => (\n <span key={port.name}>\n {port.name} · {port.protocol} → {port.target} · published:{\" \"}\n {port.endpointPorts.join(\", \") || \"unknown\"}\n {port.unresolved ? ` · ${port.unresolved} unresolved named targets` : \"\"}\n </span>\n ))}\n </div>\n </div>\n {graph.gaps.length > 0 && (\n <details open className=\"notice\">\n <summary>Partial coverage ({graph.gaps.length})</summary>\n <ul>\n {graph.gaps.map((gap) => (\n <li key={gap}>{gap}</li>\n ))}\n </ul>\n </details>\n )}\n <RelationshipGraph\n graph={graph}\n onOpen={openResource}\n ingressAvailable={current?.data.ingresses !== undefined}\n hideUpstreams={hideUpstreams}\n />\n {graph.omitted > 0 && (\n <div className=\"notice\">\n {graph.omitted} additional visible resources omitted to keep the graph readable. Focus a pod to inspect\n its ownership and placement.\n </div>\n )}\n <details>\n <summary>Accessible connection list ({graph.edges.length})</summary>\n <ul className=\"edge-list\">\n {graph.edges.map((edge) => (\n <li key={`${edge.from}/${edge.to}/${edge.label}`}>\n {graph.nodes.find((node) => node.id === edge.from)?.name} → {edge.label} →{\" \"}\n {graph.nodes.find((node) => node.id === edge.to)?.name}\n {edge.evidence && <div>{edge.evidence}</div>}\n </li>\n ))}\n </ul>\n </details>\n <p className=\"scope\">\n <span>\n Snapshot from read-only API requests; Gateway discovery and references include other namespaces.\n </span>\n <span>Owner and node references can point to objects that were not queried.</span>\n <span>Endpoint counts can include separate address families.</span>\n <span>No Secret or ConfigMap data is read.</span>\n </p>\n </>\n )}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;AAgBA,IAAM,EAAE,MAAM,WAAW,mBAAA,SAAS;AAClC,IAAM,QAAQ;AAOd,IAAM,QAAQ;CACZ;EAAE,IAAI;EAAY,MAAM;EAAuB,UAAU;CAAqB;CAC9E;EAAE,IAAI;EAAW,MAAM;EAAmB,UAAU;CAAoB;CACxE;EAAE,IAAI;EAAW,MAAM;EAAiC,UAAU;CAAkC;CACpG;EAAE,IAAI;EAAa,MAAM;EAAyB,UAAU;CAAyB;AACvF;AACA,IAAM,QAAgC;CACpC,SAAS;CACT,SAAS;CACT,KAAK;CACL,eAAe;CACf,MAAM;CACN,YAAY;CACZ,YAAY;CACZ,aAAa;CACb,WAAW;CACX,KAAK;CACL,SAAS;AACX;AACA,eAAsB,0BACpB,WACA,SACA,QACgC;CAChC,MAAM,OAAiB,CAAC;CACxB,MAAM,OAAO,OAAW,MAAc,YAAuC;EAC3E,IAAI;GACF,MAAM,QAAQ,MAAM,QAAQ;GAC5B,IAAI,CAAC,OAAO;IACV,KAAK,KAAK,GAAG,KAAK,uBAAuB;IACzC;GACF;GACA,IAAI,MAAM,SAAS,OACjB,KAAK,KAAK,GAAG,KAAK,uBAAuB,MAAM,kDAAkD;GACnG,OAAO,MAAM,MAAM,GAAG,KAAK;EAC7B,QAAQ;GACN,IAAI,CAAC,OAAO,SAAS,KAAK,KAAK,GAAG,KAAK,qEAAqE;GAC5G;EACF;CACF;CACA,MAAM,UAAU;EAAE;EAAW,SAAS,EAAE,OAAO;CAAE;CACjD,MAAM,QAAQ,EAAE,OAAO,IAAU;CACjC,MAAM,WAAW,OAAO,QAAQ,QAAQ,KAAK,YAAY,CAAC,CAAC,CAAC,CACzD,KAAK,CAAC,KAAK,WAAW,GAAG,IAAI,GAAG,OAAO,CAAC,CACxC,KAAK,GAAG;CACX,MAAM,WAAW,QAAQ,KAAK,SAAS;CACvC,MAAM,YAAY,WACd,CAAC,IACD;EACE,mBAAA,SAAS,OAAO;EAChB,mBAAA,SAAS,OAAO;EAChB,mBAAA,SAAS,OAAO;EAChB,mBAAA,SAAS,OAAO;EAChB,mBAAA,SAAS,OAAO;EAChB,mBAAA,SAAS,OAAO;CAClB;CACJ,MAAM,CAAC,MAAM,QAAQ,WAAW,GAAG,UAAU,MAAM,QAAQ,IAAI;EAC7D,YAAY,CAAC,WACT,KAAK,aAAa,mBAAA,SAAS,OAAO,QAAQ,KAAK,SAAS;GAAE,GAAG;GAAO,eAAe;EAAS,CAAC,CAAC,IAC9F,QAAQ,QAAQ,CAAC,CAAC;EACtB,QAAQ,KAAK,SAAS,iBAClB,QAAQ,QAAQ,CAAC,CAAC,IAClB,KAAK,uBACH,mBAAA,SAAS,OAAO,iBAAiB,KAAK,SAAS;GAC7C,GAAG;GACH,eAAe,8BAA8B,QAAQ,QAAQ;EAC/D,CAAC,CACH;EACJ,KAAK,iBAAiB,mBAAA,SAAS,OAAO,WAAW,KAAK,SAAS,KAAK,CAAC;EACrE,GAAG,UAAU,KAAK,QAAQ,KAAyB,oBAAoB,IAAI,KAAK,SAAS,KAAK,CAAC,CAAC;CAClG,CAAC;CACD,MAAM,YAAY,mBAAA,SAAS,QAAQ,cAAc,IAAI,CAAC,EAAE,SAAS;CACjE,MAAM,UAAU,YACZ,MAAM,qCAAA,qBAAqB,+BAAA,8BAA8B,WAAW,MAAM,GAAG,QAAQ,EACnF,kBAAkB,UACpB,CAAC,IACD,KAAA;CACJ,OAAO;EAAE;EAAM;EAAQ;EAAW,QAAQ,OAAO,SAAS,UAAU,SAAS,CAAC,CAAC;EAAG;EAAM;CAAQ;AAClG;AACA,SAAS,aAAa,EACpB,MACA,UACA,kBACA,QACA,eAOC;CACD,OACE,oCAAA,KAAC,WAAD;EACE,WAAU;EACV,gBAAc,KAAK;EACnB,oBAAoB,YAAY,KAAK,EAAE;EACvC,oBAAoB,YAAY;EAChC,eAAe,YAAY,KAAK,EAAE;EAClC,cAAc,YAAY;YAN5B;GAQE,oCAAA,IAAC,OAAD;IAAK,WAAU;cAAkB,SAAS,KAAK,KAAK,KAAK;GAAa,CAAA;GACtE,oCAAA,KAAC,OAAD;IAAK,WAAU;cAAf;KACE,oCAAA,IAAC,MAAD;MAAM,UAAU,MAAM,KAAK,SAAS;MAAgB,MAAM;KAAK,CAAA;KAC9D,KAAK;KACL,KAAK,YAAY;IACf;;GACJ,KAAK,WACJ,oCAAA,IAAC,uBAAA,eAAD;IAAe,OAAO,QAAQ,KAAK,KAAK,GAAG,KAAK;cAC9C,oCAAA,IAAC,UAAD;KACE,MAAK;KACL,WAAU;KACV,UAAU,UAAU;MAClB,MAAM,eAAe;MACrB,MAAM,gBAAgB;MACtB,OAAO,KAAK,QAAkB;KAChC;eAEC,KAAK;IACA,CAAA;GACK,CAAA,IAEf,oCAAA,IAAC,UAAD,EAAA,UAAS,KAAK,KAAa,CAAA;GAE7B,oCAAA,KAAC,KAAD;IAAG,WAAW,KAAK;cAAnB;KACE,oCAAA,IAAC,MAAD;MACE,UAAU,KAAK,SAAS,YAAY,YAAY,KAAK,SAAS,YAAY,iBAAiB;MAC3F,MAAM;KACP,CAAA;KAAE;KACF,KAAK;IACL;;GACF,CAAC,EAAE,KAAK,UAAU,UAAU,kBAAkB,WAC7C,oCAAA,KAAC,WAAD;IAAS,WAAU;cAAnB,CACE,oCAAA,IAAC,WAAD,EAAA,UAAS,eAAqB,CAAA,GAC7B,CAAC,GAAI,KAAK,YAAY,CAAC,GAAI,GAAI,oBAAoB,CAAC,CAAE,CAAC,CAAC,KAAK,aAC5D,oCAAA,IAAC,KAAD,EAAA,UAAmB,SAAY,GAAvB,QAAuB,CAChC,CACM;;EAEJ;;AAEb;AACA,SAAS,iBAAiB,QAA4B;CACpD,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC,GAAG,GAAG,OAAO,EAAE,CAAC;CAC1C,KAAK,IAAI,QAAQ,GAAG,QAAQ,OAAO,SAAS,GAAG,SAAS;EACtD,MAAM,CAAC,GAAG,KAAK,OAAO;EACtB,MAAM,CAAC,IAAI,MAAM,OAAO,QAAQ;EAChC,MAAM,CAAC,IAAI,MAAM,OAAO,QAAQ;EAChC,MAAM,SAAS,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE;EACxC,MAAM,QAAQ,KAAK,MAAM,KAAK,GAAG,KAAK,CAAC;EACvC,IAAI,CAAC,UAAU,CAAC,OAAO;EACvB,MAAM,SAAS,KAAK,IAAI,GAAG,SAAS,GAAG,QAAQ,CAAC;EAChD,QAAQ,MAAM,KAAM,KAAK,KAAK,SAAU,OAAO,GAAG,KAAM,KAAK,KAAK,SAAU;EAC5E,QAAQ,MAAM,EAAE,GAAG,EAAE,GAAG,KAAM,KAAK,KAAK,SAAU,MAAM,GAAG,KAAM,KAAK,KAAK,SAAU;CACvF;CACA,MAAM,OAAO,OAAO,OAAO,SAAS;CACpC,OAAO,GAAG,KAAK,KAAK,KAAK,GAAG,GAAG,KAAK;AACtC;AACA,SAAgB,kBAAkB,EAChC,OACA,QACA,kBACA,gBAAgB,SAMf;CACD,MAAM,cAAc,IAAI,IAAI,MAAM,MAAM,QAAQ,SAAS,KAAK,SAAS,UAAU,CAAC,CAAC,KAAK,SAAS,KAAK,EAAE,CAAC;CACzG,MAAM,iBACJ,CAAC,iBAAiB,MAAM,MAAM,MAAM,SAAS,YAAY,IAAI,KAAK,IAAI,KAAK,YAAY,IAAI,KAAK,EAAE,CAAC;CACrG,MAAM,eAAe,MAAM,QAAQ,SAAS,CAAC,iBAAiB,KAAK,OAAO,UAAU;CACpF,MAAM,UAAU,+BAAA,OAAuB,IAAI;CAC3C,MAAM,CAAC,OAAO,YAAY,+BAAA,SAAsE,CAAC,CAAC;CAClG,MAAM,CAAC,WAAW,gBAAgB,+BAAA,SAAiB;CACnD,+BAAA,sBAAsB;EACpB,MAAM,YAAY,QAAQ;EAC1B,IAAI,CAAC,WAAW;EAChB,MAAM,gBAAgB;GACpB,MAAM,SAAS,UAAU,sBAAsB;GAC/C,MAAM,QAAQ,IAAI,IAChB,MAAM,KAAK,UAAU,iBAA8B,gBAAgB,CAAC,CAAC,CAAC,KAAK,SAAS,CAClF,KAAK,QAAQ,QACb,KAAK,sBAAsB,CAC7B,CAAC,CACH;GACA,SACE,MAAM,MAAM,SAAS,MAAM,UAAU;IACnC,MAAM,OAAO,MAAM,IAAI,KAAK,IAAI;IAChC,MAAM,KAAK,MAAM,IAAI,KAAK,EAAE;IAC5B,IAAI,CAAC,QAAQ,CAAC,IAAI,OAAO,CAAC;IAC1B,MAAM,KAAK,KAAK,MAAM,KAAK,SAAS,IAAI,OAAO;IAC/C,MAAM,KAAK,GAAG,MAAM,GAAG,SAAS,IAAI,OAAO;IAC3C,MAAM,aAAa,KAAK,IAAI,KAAK,OAAO,GAAG,IAAI,IAAI;IACnD,MAAM,MAAM,aAAa,KAAK,OAAO,KAAK,SAAS,OAAO;IAC1D,MAAM,KAAK,GAAG,OAAO,OAAO;IAC5B,MAAM,cAAe,QAAQ,IAAK,KAAK;IACvC,MAAM,SAAS,aAAa,KAAK,KAAK,cAAc,KAAK,MAAM,IAAI;IACnE,MAAM,gBAAgB,MAAM,KAAK,MAAM,OAAO,CAAC,CAAC,CAAC,MAC9C,SAAS,KAAK,OAAO,KAAK,OAAO,KAAK,KAAK,QAAQ,GAAG,OAAO,CAChE;IACA,IAAI,OACF,CAAC,cAAc,OAAO,KAClB,KAAK,GAAG,GAAG,GAAG,KAAK,OACnB,iBAAiB;KACf,CAAC,IAAI,EAAE;KACP,CAAC,QAAQ,EAAE;KACX,CAAC,QAAQ,EAAE;KACX,CAAC,IAAI,EAAE;IACT,CAAC;IACP,IAAI,eAAe;KACjB,MAAM,SACJ,KAAK,IAAI,GAAG,MAAM,KAAK,MAAM,OAAO,IAAI,SAAS,KAAK,MAAM,CAAC,IAAI,OAAO,MAAM,KAAM,QAAQ,IAAK;KACnG,MAAM,eAAe,KAAK,KAAK;KAC/B,MAAM,eAAe,KAAK,KAAK;KAC/B,OAAO,iBAAiB;MACtB,CAAC,IAAI,EAAE;MACP,CAAC,cAAc,EAAE;MACjB,CAAC,cAAc,MAAM;MACrB,CAAC,cAAc,MAAM;MACrB,CAAC,cAAc,EAAE;MACjB,CAAC,IAAI,EAAE;KACT,CAAC;IACH;IACA,OAAO,CAAC;KAAE,GAAG;KAAM;IAAK,CAAC;GAC3B,CAAC,CACH;EACF;EACA,QAAQ;EACR,MAAM,WAAW,OAAO,mBAAmB,cAAc,KAAA,IAAY,IAAI,eAAe,OAAO;EAC/F,UAAU,QAAQ,SAAS;EAC3B,KAAK,MAAM,QAAQ,UAAU,iBAAiB,gBAAgB,GAAG,UAAU,QAAQ,IAAI;EACvF,OAAO,iBAAiB,UAAU,OAAO;EACzC,aAAa;GACX,UAAU,WAAW;GACrB,OAAO,oBAAoB,UAAU,OAAO;EAC9C;CACF,GAAG,CAAC,OAAO,aAAa,CAAC;CACzB,OACE,oCAAA,IAAC,OAAD;EAAK,WAAU;YACb,oCAAA,KAAC,OAAD;GACE,KAAK;GACL,WAAW,QAAQ,gBAAgB,oBAAoB,KAAK,iBAAiB,qBAAqB;GAClG,OAAO,EACL,kBAAkB,eAAe,KAAK,IAAI,GAAG,GAAG,aAAa,KAAK,SAAS,MAAM,MAAM,QAAQ,SAAS,KAAK,SAAS,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,SAC1I;GACA,cAAW;aANb,CAQE,oCAAA,KAAC,OAAD;IAAK,WAAU;IAAuB,OAAM;IAAO,QAAO;IAAO,eAAY;cAA7E,CACE,oCAAA,IAAC,QAAD,EAAA,UACE,oCAAA,IAAC,UAAD;KAAQ,IAAG;KAAqB,aAAY;KAAI,cAAa;KAAI,MAAK;KAAI,MAAK;KAAM,QAAO;eAC1F,oCAAA,IAAC,QAAD;MAAM,GAAE;MAAiB,MAAK;KAAgB,CAAA;IACxC,CAAA,EACJ,CAAA,GACL,MAAM,KAAK,SACV,oCAAA,IAAC,uBAAA,eAAD;KAEE,OAAO,GAAG,MAAM,MAAM,MAAM,SAAS,KAAK,OAAO,KAAK,IAAI,CAAC,EAAE,KAAK,KAAK,KAAK,MAAM,KAAK,MAAM,MAAM,MAAM,SAAS,KAAK,OAAO,KAAK,EAAE,CAAC,EAAE;eAExI,oCAAA,IAAC,QAAD;MACE,kBAAgB,KAAK;MACrB,gBAAc,KAAK;MACnB,WACE,YACI,KAAK,SAAS,aAAa,KAAK,OAAO,YACrC,2BACA,sBACF;MAEN,GAAG,KAAK;MACR,WAAU;KACX,CAAA;IACY,GAhBR,GAAG,KAAK,KAAK,GAAG,KAAK,GAAG,GAAG,KAAK,OAgBxB,CAChB,CACE;OACJ,aAAa,KAAK,SACjB,oCAAA,KAAC,WAAD;IAAS,WAAU;IAAuB,cAAY,KAAK;cAA3D;KACE,oCAAA,IAAC,MAAD,EAAA,UAAK,KAAK,KAAS,CAAA;KAClB,MAAM,MACJ,QAAQ,SAAS,KAAK,SAAS,KAAK,EAAE,CAAC,CACvC,KAAK,SACJ,oCAAA,IAAC,cAAD;MAEQ;MACN,UAAU,CAAC,GAAG,IAAI,IAAI,MAAM,MAAM,QAAQ,SAAS,KAAK,OAAO,KAAK,EAAE,CAAC,CAAC,KAAK,SAAS,KAAK,KAAK,CAAC,CAAC;MAClG,kBAAkB,MAAM,MACrB,QAAQ,SAAS,KAAK,OAAO,KAAK,MAAM,KAAK,QAAQ,CAAC,CACtD,KAAK,SAAS,KAAK,QAAkB;MAChC;MACR,aAAa;KACd,GARM,KAAK,EAQX,CACF;KACF,CAAC,MAAM,MAAM,MAAM,SAAS,KAAK,SAAS,KAAK,EAAE,KAChD,oCAAA,IAAC,OAAD;MAAK,WAAU;gBACZ,KAAK,OAAO,aACT,mBACE,6CACA,iCACF;KACD,CAAA;IAEA;MAzBwB,KAAK,EAyB7B,CACV,CACE;;CACF,CAAA;AAET;AACA,IAAa,4BAA4B,oCAAA,UAAU,EAAE,UAAU,WAAkC;CAC/F,IAAI,CAAC,SACH,OACE,oCAAA,IAAC,OAAD;EAAK,WAAU;YACb,oCAAA,IAAC,KAAD,EAAA,UAAG,wDAAwD,CAAA;CACxD,CAAA;CAET,OAAO,oCAAA,IAAC,kCAAD,CAAyG,GAAlE,mBAAA,SAAS,QAAQ,cAAc,IAAI,CAAC,EAAE,SAAS,OAAO,SAAY;AAClH,CAAC;AACD,SAAS,mCAAmC;CAC1C,MAAM,UAAU,+BAAA,OAAO,IAAI;CAC3B,MAAM,YAAY,+BAAA,OAAO,mBAAA,SAAS,QAAQ,cAAc,IAAI,CAAC,EAAE,SAAS,GAAG;CAC3E,+BAAA,gBAAgB;EACd,QAAQ,UAAU;EAClB,aAAa;GACX,QAAQ,UAAU;EACpB;CACF,GAAG,CAAC,CAAC;CACL,MAAM,CAAC,YAAY,iBAAiB,+BAAA,SAAmB,CAAC,CAAC;CACzD,MAAM,CAAC,WAAW,gBAAgB,+BAAA,SAAS,EAAE;CAC7C,MAAM,CAAC,UAAU,eAAe,+BAAA,SAAoB,CAAC,CAAC;CACtD,MAAM,CAAC,aAAa,kBAAkB,+BAAA,SAAS,EAAE;CACjD,MAAM,CAAC,YAAY,iBAAiB,+BAAA,SAAS,EAAE;CAC/C,MAAM,cAAc,qCAAA,2BAA2B,oBAAgD;CAC/F,MAAM,CAAC,eAAe,oBAAoB,+BAAA,eACxC,YAAY,uBAAuB,SAAS,UAAU,WAAW,EAAE,CACrE;CACA,MAAM,wBAAwB;EAC5B,MAAM,KAAK,UAAU;EACrB,IAAI,CAAC,MAAM,mBAAA,SAAS,QAAQ,cAAc,IAAI,CAAC,EAAE,SAAS,QAAQ,IAAI;EACtE,MAAM,SAAS,CAAC;EAChB,MAAM,gBAAgB,YAAY,uBAAuB,QAAQ,YAAY,YAAY,EAAE;EAC3F,YAAY,yBAAyB,SAAS,CAAC,GAAG,eAAe,EAAE,CAAC,CAAC,MAAM,IAAI,IAAI;EACnF,iBAAiB,MAAM;CACzB;CACA,MAAM,CAAC,WAAW,gBAAgB,+BAAA,SAAyB;CAC3D,MAAM,CAAC,SAAS,cAAc,+BAAA,SAAS,CAAC;CACxC,MAAM,CAAC,cAAc,mBAAmB,+BAAA,SAAS,CAAC;CAClD,MAAM,CAAC,kBAAkB,uBAAuB,+BAAA,SAAS,EAAE;CAC3D,MAAM,CAAC,cAAc,mBAAmB,+BAAA,SAAS,IAAI;CACrD,MAAM,CAAC,SAAS,cAAc,+BAAA,SAAS,KAAK;CAC5C,MAAM,CAAC,cAAc,mBAAmB,+BAAA,SAAS,EAAE;CACnD,MAAM,CAAC,WAAW,gBAAgB,+BAAA,SAAS,EAAE;CAC7C,+BAAA,gBAAgB;EACd,MAAM,aAAa,IAAI,gBAAgB;EACvC,gBAAgB,IAAI;EACpB,oBAAoB,EAAE;EACtB,mBAAK,SAAS,OAAO,cAClB,KAAK,EAAE,SAAS,EAAE,QAAQ,WAAW,OAAO,EAAE,GAAG,EAAE,OAAO,IAAU,CAAC,CAAC,CACtE,MAAM,UAAU;GACf,IAAI,WAAW,OAAO,SAAS;GAC/B,MAAM,SAAS,SAAS,CAAC,EAAA,CACtB,MAAM,GAAG,KAAK,CAAC,CACf,KAAK,SAAS,KAAK,QAAQ,CAAC,CAAC,CAC7B,KAAK;GACR,cAAc,KAAK;GACnB,cAAc,YAAa,MAAM,SAAS,OAAO,IAAI,UAAW,MAAM,MAAM,EAAI;GAChF,KAAK,OAAO,UAAU,KAAK,OAAO,oBAAoB,mCAAmC,MAAM,SAAS;QACnG,IAAI,CAAC,MAAM,QAAQ,gBAAgB,2CAA2C;EACrF,CAAC,CAAC,CACD,YAAY;GACX,IAAI,CAAC,WAAW,OAAO,SACrB,gBAAgB,oEAAoE;EACxF,CAAC,CAAC,CACD,cAAc;GACb,IAAI,CAAC,WAAW,OAAO,SAAS,gBAAgB,KAAK;EACvD,CAAC;EACH,aAAa,WAAW,MAAM;CAChC,GAAG,CAAC,YAAY,CAAC;CACjB,+BAAA,gBAAgB;EACd,IAAI,CAAC,WAAW;EAChB,MAAM,aAAa,IAAI,gBAAgB;EACvC,WAAW,KAAK;EAChB,YAAY,CAAC,CAAC;EACd,eAAe,EAAE;EACjB,aAAa,KAAA,CAAS;EACtB,gBAAgB,IAAI;EACpB,gBAAgB,EAAE;EAClB,mBAAK,SAAS,OAAO,WAClB,KAAK;GAAE;GAAW,SAAS,EAAE,QAAQ,WAAW,OAAO;EAAE,GAAG,EAAE,OAAO,IAAU,CAAC,CAAC,CACjF,MAAM,UAAU;GACf,IAAI,WAAW,OAAO,SAAS;GAC/B,MAAM,WAAW,SAAS,CAAC,EAAA,CAAG,MAAM,GAAG,KAAK,CAAC,CAAC,MAAM,GAAG,MAAM,EAAE,QAAQ,CAAC,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC;GACnG,YAAY,OAAO;GACnB,eAAe,QAAQ,EAAE,EAAE,QAAQ,KAAK,EAAE;GAC1C,KAAK,OAAO,UAAU,KAAK,OACzB,gBAAgB,iCAAiC,MAAM,4CAA4C;QAChG,IAAI,CAAC,QAAQ,QAAQ,gBAAgB,uCAAuC;EACnF,CAAC,CAAC,CACD,YAAY;GACX,IAAI,CAAC,WAAW,OAAO,SAAS,gBAAgB,uDAAuD;EACzG,CAAC,CAAC,CACD,cAAc;GACb,IAAI,CAAC,WAAW,OAAO,SAAS,gBAAgB,KAAK;EACvD,CAAC;EACH,aAAa,WAAW,MAAM;CAChC,GAAG,CAAC,WAAW,YAAY,CAAC;CAC5B,MAAM,UAAU,SAAS,MAAM,SAAS,KAAK,QAAQ,MAAM,WAAW;CACtE,+BAAA,gBAAgB;EACd,IAAI,CAAC,WAAW,CAAC,aAAa,QAAQ,SAAS,cAAc,WAAW;EACxE,MAAM,aAAa,IAAI,gBAAgB;EACvC,WAAW,IAAI;EACf,aAAa,KAAA,CAAS;EACtB,cAAc,EAAE;EAChB,aAAa,EAAE;EACf,0BAA+B,WAAW,SAAS,WAAW,MAAM,CAAC,CAClE,MAAM,SAAS;GACd,IAAI,CAAC,WAAW,OAAO,SAAS,aAAa;IAAE;IAAW,SAAS,QAAQ,QAAQ;IAAG;GAAK,CAAC;EAC9F,CAAC,CAAC,CACD,cAAc;GACb,IAAI,CAAC,WAAW,OAAO,SAAS,WAAW,KAAK;EAClD,CAAC;EACH,aAAa,WAAW,MAAM;CAChC,GAAG;EAAC;EAAW;EAAS;CAAO,CAAC;CAChC,MAAM,UAAU,WAAW,cAAc,aAAa,UAAU,YAAY,cAAc,YAAY,KAAA;CACtG,MAAM,QACJ,WAAW,UAAU,+BAAA,2BAA2B,SAAS,QAAQ,MAAM,cAAc,KAAA,CAAS,IAAI,KAAA;CACpG,MAAM,gBAAgB,SAAiB;EACrC,MAAM,uBACJ,QAAQ,WAAW,mBAAA,SAAS,QAAQ,cAAc,IAAI,CAAC,EAAE,SAAS,QAAQ,UAAU;EACtF,aAAa,EAAE;EACf,QAAa,QAAQ,CAAC,CACnB,WAAW;GACV,IAAI,CAAC,eAAe,GAAG;GACvB,MAAM,cAAc,KAAK,MACvB,+FACF;GACA,IAAI,aAAa;IACf,MAAM,GAAG,OAAO,SAAS,WAAW,UAAU,QAAQ;IACtD,MAAM,OACJ;KACE,UAAU;KACV,gBAAgB;KAChB,YAAY;KACZ,YAAY;KACZ,WAAW;KACX,WAAW;KACX,WAAW;IACb,EACA;IACF,OAAO,gCAAA,mBAAmB;KAAE;KAAM;KAAO;KAAS;KAAW;KAAU;KAAM;KAAM,QAAQ,CAAC;IAAE,CAAC;GACjG;GACA,OAAO,mBAAA,SAAS,WAAW,YAAY,IAAI;EAC7C,CAAC,CAAC,CACD,YAAY;GACX,IAAI,eAAe,GAAG,aAAa,qEAAqE;EAC1G,CAAC;CACL;CACA,OACE,oCAAA,KAAC,OAAD;EAAK,WAAU;YAAf;GACE,oCAAA,IAAC,SAAD,EAAA,UAAQ,mCAAA,4BAAmC,CAAA;GAC3C,oCAAA,IAAC,OAAD;IAAK,WAAU;cACb,oCAAA,IAAC,MAAD,EAAA,UAAI,yBAA0B,CAAA;GAC3B,CAAA;GACL,oCAAA,IAAC,KAAD;IAAG,WAAU;cAAQ;GAGlB,CAAA;GACH,oCAAA,KAAC,OAAD;IAAK,WAAU;cAAf;KACE,oCAAA,KAAC,SAAD;MAAO,WAAU;gBAAjB,CACE,oCAAA,IAAC,QAAD,EAAA,UAAM,YAAe,CAAA,GACrB,oCAAA,IAAC,QAAD;OACE,cAAW;OACX,OAAO;OACP,SAAS,WAAW,KAAK,UAAU;QAAE,OAAO;QAAM,OAAO;OAAK,EAAE;OAChE,WAAW,WAAW,aAAa,QAAQ,SAAS,EAAE;OACtD,YAAY,CAAC,WAAW;MACzB,CAAA,CACI;;KACP,oCAAA,KAAC,SAAD;MAAO,WAAU;gBAAjB,CACE,oCAAA,IAAC,QAAD,EAAA,UAAM,UAAa,CAAA,GACnB,oCAAA,IAAC,QAAD;OACE,cAAW;OACX,OAAO;OACP,SAAS,SAAS,KAAK,UAAU;QAAE,OAAO,KAAK,QAAQ;QAAG,OAAO,KAAK,QAAQ;OAAE,EAAE;OAClF,WAAW,WAAW,eAAe,QAAQ,SAAS,EAAE;OACxD,YAAY,CAAC,SAAS,UAAU;MACjC,CAAA,CACI;;KACP,oCAAA,KAAC,SAAD;MAAO,WAAU;gBAAjB,CACE,oCAAA,IAAC,QAAD,EAAA,UAAM,YAAe,CAAA,GACrB,oCAAA,IAAC,QAAD;OACE,cAAW;OACX,OAAO;OACP,SAAS,CACP;QAAE,OAAO;QAAI,OAAO;OAA8B,GAClD,IAAI,OAAO,cAAc,CAAC,EAAA,CAAG,KAAK,UAAU;QAAE,OAAO;QAAM,OAAO;OAAK,EAAE,CAC3E;OACA,WAAW,WAAW,cAAc,QAAQ,SAAS,EAAE;OACvD,YAAY,CAAC,OAAO,WAAW;MAChC,CAAA,CACI;;KACP,oCAAA,IAAC,uBAAA,eAAD;MAAe,OAAO,gBAAgB,6BAA6B;gBACjE,oCAAA,KAAC,UAAD;OACE,MAAK;OACL,WAAU;OACV,gBAAc;OACd,SAAS;OACT,UAAU,CAAC,UAAU;iBALvB,CAOE,oCAAA,IAAC,MAAD;QAAM,UAAU,gBAAgB,mBAAmB;QAAc,MAAM;OAAK,CAAA,GAAC,eAEvE;;KACK,CAAA;KACf,oCAAA,IAAC,uBAAA,eAAD;MAAe,OAAM;gBACnB,oCAAA,KAAC,UAAD;OACE,MAAK;OACL,WAAU;OACV,eAAgB,UAAU,YAAY,UAAU,QAAQ,CAAC,IAAI,iBAAiB,UAAU,QAAQ,CAAC;OACjG,UAAU,WAAW;iBAJvB,CAME,oCAAA,IAAC,MAAD;QAAM,UAAS;QAAU,MAAM;OAAK,CAAA,GAAC,SAE/B;;KACK,CAAA;IACZ;;GACJ,oBACC,oCAAA,IAAC,OAAD;IAAK,WAAU;IAAS,MAAK;cAC1B;GACE,CAAA;GAEN,gBACC,oCAAA,IAAC,OAAD;IAAK,WAAU;IAAS,MAAK;cAC1B;GACE,CAAA;GAEN,aACC,oCAAA,IAAC,OAAD;IAAK,WAAU;IAAiB,MAAK;cAClC;GACE,CAAA;IAEL,gBAAgB,YAChB,oCAAA,IAAC,OAAD;IAAK,WAAU;IAAQ,MAAK;cAAS;GAEhC,CAAA;GAEN,CAAC,gBAAgB,CAAC,WAAW,CAAC,WAC7B,oCAAA,IAAC,OAAD;IAAK,WAAU;cAAQ;GAAuE,CAAA;GAE/F,SAAS,CAAC,WACT,oCAAA,KAAA,oBAAA,UAAA,EAAA,UAAA;IACE,oCAAA,KAAC,OAAD;KAAK,WAAU;eAAf,CACE,oCAAA,IAAC,UAAD,EAAA,UAAS,MAAM,YAAY,QAAgB,CAAA,GAC3C,oCAAA,IAAC,OAAD;MAAK,WAAU;gBACZ,MAAM,YAAY,MAAM,KAAK,SAC5B,oCAAA,KAAC,QAAD,EAAA,UAAA;OACG,KAAK;OAAK;OAAI,KAAK;OAAS;OAAI,KAAK;OAAO;OAAc;OAC1D,KAAK,cAAc,KAAK,IAAI,KAAK;OACjC,KAAK,aAAa,MAAM,KAAK,WAAW,6BAA6B;MAClE,EAAA,GAJK,KAAK,IAIV,CACP;KACE,CAAA,CACF;;IACJ,MAAM,KAAK,SAAS,KACnB,oCAAA,KAAC,WAAD;KAAS,MAAA;KAAK,WAAU;eAAxB,CACE,oCAAA,KAAC,WAAD,EAAA,UAAA;MAAS;MAAmB,MAAM,KAAK;MAAO;KAAU,EAAA,CAAA,GACxD,oCAAA,IAAC,MAAD,EAAA,UACG,MAAM,KAAK,KAAK,QACf,oCAAA,IAAC,MAAD,EAAA,UAAe,IAAQ,GAAd,GAAc,CACxB,EACC,CAAA,CACG;;IAEX,oCAAA,IAAC,mBAAD;KACS;KACP,QAAQ;KACR,kBAAkB,SAAS,KAAK,cAAc,KAAA;KAC/B;IAChB,CAAA;IACA,MAAM,UAAU,KACf,oCAAA,KAAC,OAAD;KAAK,WAAU;eAAf,CACG,MAAM,SAAQ,uHAEZ;;IAEP,oCAAA,KAAC,WAAD,EAAA,UAAA,CACE,oCAAA,KAAC,WAAD,EAAA,UAAA;KAAS;KAA6B,MAAM,MAAM;KAAO;IAAU,EAAA,CAAA,GACnE,oCAAA,IAAC,MAAD;KAAI,WAAU;eACX,MAAM,MAAM,KAAK,SAChB,oCAAA,KAAC,MAAD,EAAA,UAAA;MACG,MAAM,MAAM,MAAM,SAAS,KAAK,OAAO,KAAK,IAAI,CAAC,EAAE;MAAK;MAAI,KAAK;MAAM;MAAG;MAC1E,MAAM,MAAM,MAAM,SAAS,KAAK,OAAO,KAAK,EAAE,CAAC,EAAE;MACjD,KAAK,YAAY,oCAAA,IAAC,OAAD,EAAA,UAAM,KAAK,SAAc,CAAA;KACzC,EAAA,GAJK,GAAG,KAAK,KAAK,GAAG,KAAK,GAAG,GAAG,KAAK,OAIrC,CACL;IACC,CAAA,CACG,EAAA,CAAA;IACT,oCAAA,KAAC,KAAD;KAAG,WAAU;eAAb;MACE,oCAAA,IAAC,QAAD,EAAA,UAAM,mGAEA,CAAA;MACN,oCAAA,IAAC,QAAD,EAAA,UAAM,wEAA2E,CAAA;MACjF,oCAAA,IAAC,QAAD,EAAA,UAAM,yDAA4D,CAAA;MAClE,oCAAA,IAAC,QAAD,EAAA,UAAM,uCAA0C,CAAA;KAC/C;;GACH,EAAA,CAAA;EAED;;AAET"}
|
|
1
|
+
{"version":3,"file":"resource-relationships.js","names":[],"sources":["../../src/renderer/resource-relationships.tsx"],"sourcesContent":["import { Renderer } from \"@freelensapp/extensions\";\nimport { observer } from \"mobx-react\";\nimport { useEffect, useLayoutEffect, useRef, useState } from \"react\";\nimport {\n buildResourceRelationships,\n type RelationshipInventory,\n type RelationshipNode,\n type RelationshipObject,\n} from \"../common/resource-relationships\";\nimport { MonitoringPreferencesStore } from \"../common/store/monitoring-preferences-store\";\nimport { explainDiagnosticFinding } from \"./ai-diagnostic-handoff\";\nimport { loadGatewayInventory } from \"./gateway-relationships-client\";\nimport { NativeTooltip } from \"./native-tooltip\";\nimport { relationshipMapFinding } from \"./relationship-map-finding\";\nimport { resourceRelationshipsStyles } from \"./resource-relationships.css\";\nimport { createResourceSearchTransport } from \"./resource-search-client\";\nimport { openSearchResource } from \"./resource-search-routing\";\n\nconst { Icon, Select } = Renderer.Component;\nconst LIMIT = 100;\ntype Service = Renderer.K8sApi.Service;\ninterface InventoryState {\n namespace: string;\n service: string;\n data: RelationshipInventory;\n}\nconst roles = [\n { id: \"upstream\", name: \"Upstream references\", relation: \"references backend\" },\n { id: \"service\", name: \"Focused Service\", relation: \"API configuration\" },\n { id: \"backend\", name: \"Selected & published backends\", relation: \"selector matches / published in\" },\n { id: \"placement\", name: \"Ownership & placement\", relation: \"owned by / assigned to\" },\n] as const;\nconst icons: Record<string, string> = {\n Ingress: \"login\",\n Service: \"share\",\n Pod: \"view_in_ar\",\n EndpointSlice: \"hub\",\n Node: \"dns\",\n ReplicaSet: \"layers\",\n Deployment: \"layers\",\n StatefulSet: \"layers\",\n DaemonSet: \"layers\",\n Job: \"work\",\n CronJob: \"schedule\",\n};\nexport async function loadRelationshipInventory(\n namespace: string,\n service: Service,\n signal: AbortSignal,\n): Promise<RelationshipInventory> {\n const gaps: string[] = [];\n const list = async <T,>(name: string, request: () => Promise<T[] | null>) => {\n try {\n const items = await request();\n if (!items) {\n gaps.push(`${name} inventory unavailable`);\n return undefined;\n }\n if (items.length > LIMIT)\n gaps.push(`${name} inventory capped at ${LIMIT} objects; additional relationships may be omitted`);\n return items.slice(0, LIMIT);\n } catch {\n if (!signal.aborted) gaps.push(`${name} inventory unavailable; access or API availability may be restricted`);\n return undefined;\n }\n };\n const options = { namespace, reqInit: { signal } };\n const query = { limit: LIMIT + 1 };\n const selector = Object.entries(service.spec.selector ?? {})\n .map(([key, value]) => `${key}=${value}`)\n .join(\",\");\n const external = service.spec.type === \"ExternalName\";\n const ownerApis = external\n ? []\n : [\n Renderer.K8sApi.replicaSetApi,\n Renderer.K8sApi.deploymentApi,\n Renderer.K8sApi.statefulSetApi,\n Renderer.K8sApi.daemonSetApi,\n Renderer.K8sApi.jobApi,\n Renderer.K8sApi.cronJobApi,\n ];\n const [pods, slices, ingresses, ...owners] = await Promise.all([\n selector && !external\n ? list(\"Pod\", () => Renderer.K8sApi.podsApi.list(options, { ...query, labelSelector: selector }))\n : Promise.resolve([]),\n service.spec.type === \"ExternalName\"\n ? Promise.resolve([])\n : list(\"EndpointSlice\", () =>\n Renderer.K8sApi.endpointSliceApi.list(options, {\n ...query,\n labelSelector: `kubernetes.io/service-name=${service.getName()}`,\n }),\n ),\n list(\"Ingress\", () => Renderer.K8sApi.ingressApi.list(options, query)),\n ...ownerApis.map((api) => list<RelationshipObject>(\"Controller\", () => api.list(options, query))),\n ]);\n const clusterId = Renderer.Catalog.activeCluster.get()?.metadata.uid;\n const gateway = clusterId\n ? await loadGatewayInventory(createResourceSearchTransport(clusterId, signal), signal, {\n focusedNamespace: namespace,\n })\n : undefined;\n return { pods, slices, ingresses, owners: owners.flatMap((items) => items ?? []), gaps, gateway };\n}\nfunction ResourceCard({\n node,\n incoming,\n incomingEvidence,\n onOpen,\n onHighlight,\n}: {\n onHighlight: (id?: string) => void;\n node: RelationshipNode;\n incoming: string[];\n incomingEvidence?: string[];\n onOpen: (path: string) => void;\n}) {\n return (\n <article\n className=\"card\"\n data-node-id={node.id}\n onMouseEnter={() => onHighlight(node.id)}\n onMouseLeave={() => onHighlight()}\n onFocus={() => onHighlight(node.id)}\n onBlur={() => onHighlight()}\n >\n <div className=\"relation-label\">{incoming.join(\" · \") || \"Focus\"}</div>\n <div className=\"card-kind\">\n <Icon material={icons[node.kind] ?? \"account_tree\"} size={16} />\n {node.kind}\n {node.inferred && \" · reference\"}\n </div>\n {node.selfLink ? (\n <NativeTooltip title={`Open ${node.kind} ${node.name}`}>\n <button\n type=\"button\"\n className=\"resource-name\"\n onClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n onOpen(node.selfLink as string);\n }}\n >\n {node.name}\n </button>\n </NativeTooltip>\n ) : (\n <strong>{node.name}</strong>\n )}\n <p className={node.tone}>\n <Icon\n material={node.tone === \"warning\" ? \"warning\" : node.tone === \"healthy\" ? \"check_circle\" : \"info\"}\n size={14}\n />{\" \"}\n {node.detail}\n </p>\n {!!(node.evidence?.length || incomingEvidence?.length) && (\n <details className=\"gateway-evidence\">\n <summary>API evidence</summary>\n {[...(node.evidence ?? []), ...(incomingEvidence ?? [])].map((evidence) => (\n <p key={evidence}>{evidence}</p>\n ))}\n </details>\n )}\n </article>\n );\n}\nfunction roundedConnector(points: [number, number][]) {\n let path = `M ${points[0][0]} ${points[0][1]}`;\n for (let index = 1; index < points.length - 1; index++) {\n const [x, y] = points[index];\n const [px, py] = points[index - 1];\n const [nx, ny] = points[index + 1];\n const before = Math.hypot(x - px, y - py);\n const after = Math.hypot(nx - x, ny - y);\n if (!before || !after) continue;\n const radius = Math.min(6, before / 2, after / 2);\n path += ` L ${x + ((px - x) * radius) / before} ${y + ((py - y) * radius) / before}`;\n path += ` Q ${x} ${y} ${x + ((nx - x) * radius) / after} ${y + ((ny - y) * radius) / after}`;\n }\n const last = points[points.length - 1];\n return `${path} L ${last[0]} ${last[1]}`;\n}\nexport function RelationshipGraph({\n graph,\n onOpen,\n ingressAvailable,\n hideUpstreams = false,\n}: {\n graph: ReturnType<typeof buildResourceRelationships>;\n onOpen: (path: string) => void;\n ingressAvailable: boolean;\n hideUpstreams?: boolean;\n}) {\n const upstreamIds = new Set(graph.nodes.filter((node) => node.role === \"upstream\").map((node) => node.id));\n const upstreamGutter =\n !hideUpstreams && graph.edges.some((edge) => upstreamIds.has(edge.from) && upstreamIds.has(edge.to));\n const visibleRoles = roles.filter((role) => !hideUpstreams || role.id !== \"upstream\");\n const element = useRef<HTMLDivElement>(null);\n const [paths, setPaths] = useState<{ from: string; to: string; label: string; path: string }[]>([]);\n const [highlight, setHighlight] = useState<string>();\n useLayoutEffect(() => {\n const container = element.current;\n if (!container) return;\n const measure = () => {\n const origin = container.getBoundingClientRect();\n const cards = new Map(\n Array.from(container.querySelectorAll<HTMLElement>(\"[data-node-id]\")).map((card) => [\n card.dataset.nodeId,\n card.getBoundingClientRect(),\n ]),\n );\n setPaths(\n graph.edges.flatMap((edge, index) => {\n const from = cards.get(edge.from);\n const to = cards.get(edge.to);\n if (!from || !to) return [];\n const sy = from.top + from.height / 2 - origin.top;\n const ty = to.top + to.height / 2 - origin.top;\n const sameColumn = Math.abs(from.left - to.left) < 2;\n const sx = (sameColumn ? from.left : from.right) - origin.left;\n const tx = to.left - origin.left;\n const laneOffset = ((index % 3) - 1) * 8;\n const gutter = sameColumn ? sx - 28 + laneOffset : (sx + tx) / 2 + laneOffset;\n const crossesColumn = Array.from(cards.values()).some(\n (card) => card.left > from.left + 2 && card.right < to.left - 2,\n );\n let path =\n !sameColumn && sy === ty\n ? `M ${sx} ${sy} H ${tx}`\n : roundedConnector([\n [sx, sy],\n [gutter, sy],\n [gutter, ty],\n [tx, ty],\n ]);\n if (crossesColumn) {\n const bottom =\n Math.max(...Array.from(cards.values(), (card) => card.bottom)) - origin.top + 24 + (index % 3) * 8;\n const sourceGutter = sx + 32 + laneOffset;\n const targetGutter = tx - 32 + laneOffset;\n path = roundedConnector([\n [sx, sy],\n [sourceGutter, sy],\n [sourceGutter, bottom],\n [targetGutter, bottom],\n [targetGutter, ty],\n [tx, ty],\n ]);\n }\n return [{ ...edge, path }];\n }),\n );\n };\n measure();\n const observer = typeof ResizeObserver === \"undefined\" ? undefined : new ResizeObserver(measure);\n observer?.observe(container);\n for (const card of container.querySelectorAll(\"[data-node-id]\")) observer?.observe(card);\n window.addEventListener(\"resize\", measure);\n return () => {\n observer?.disconnect();\n window.removeEventListener(\"resize\", measure);\n };\n }, [graph, hideUpstreams]);\n return (\n <div className=\"graph-scroll\">\n <div\n ref={element}\n className={`graph${hideUpstreams ? \" hide-upstreams\" : \"\"}${upstreamGutter ? \" upstream-gutter\" : \"\"}`}\n style={{\n gridTemplateRows: `auto repeat(${Math.max(1, ...visibleRoles.map((role) => graph.nodes.filter((node) => node.role === role.id).length))}, auto)`,\n }}\n aria-label=\"Service resource relationship graph\"\n >\n <svg className=\"resource-connections\" width=\"100%\" height=\"100%\" aria-hidden=\"true\">\n <defs>\n <marker id=\"relationship-arrow\" markerWidth=\"5\" markerHeight=\"5\" refX=\"4\" refY=\"2.5\" orient=\"auto\">\n <path d=\"M0 0L5 2.5L0 5\" fill=\"currentColor\" />\n </marker>\n </defs>\n {paths.map((edge) => (\n <NativeTooltip\n key={`${edge.from}/${edge.to}/${edge.label}`}\n title={`${graph.nodes.find((node) => node.id === edge.from)?.name} → ${edge.label} → ${graph.nodes.find((node) => node.id === edge.to)?.name}`}\n >\n <path\n data-edge-from={edge.from}\n data-edge-to={edge.to}\n className={\n highlight\n ? edge.from === highlight || edge.to === highlight\n ? \"connection highlighted\"\n : \"connection dimmed\"\n : \"connection\"\n }\n d={edge.path}\n markerEnd=\"url(#relationship-arrow)\"\n />\n </NativeTooltip>\n ))}\n </svg>\n {visibleRoles.map((role) => (\n <section className=\"column\" key={role.id} aria-label={role.name}>\n <h3>{role.name}</h3>\n {graph.nodes\n .filter((node) => node.role === role.id)\n .map((node) => (\n <ResourceCard\n key={node.id}\n node={node}\n incoming={[...new Set(graph.edges.filter((edge) => edge.to === node.id).map((edge) => edge.label))]}\n incomingEvidence={graph.edges\n .filter((edge) => edge.to === node.id && edge.evidence)\n .map((edge) => edge.evidence as string)}\n onOpen={onOpen}\n onHighlight={setHighlight}\n />\n ))}\n {!graph.nodes.some((node) => node.role === role.id) && (\n <div className=\"card neutral\">\n {role.id === \"upstream\"\n ? ingressAvailable\n ? \"No matching upstream references observed\"\n : \"Ingress evidence unavailable\"\n : \"No relationships observed in available evidence\"}\n </div>\n )}\n </section>\n ))}\n </div>\n </div>\n );\n}\nexport const ResourceRelationshipsPage = observer(({ enabled = true }: { enabled?: boolean }) => {\n if (!enabled)\n return (\n <div className=\"power-relationships\">\n <p>Resource relationships are disabled in Power settings</p>\n </div>\n );\n return <EnabledResourceRelationshipsPage key={Renderer.Catalog.activeCluster.get()?.metadata.uid ?? \"cluster\"} />;\n});\nfunction EnabledResourceRelationshipsPage() {\n const mounted = useRef(true);\n const clusterId = useRef(Renderer.Catalog.activeCluster.get()?.metadata.uid);\n useEffect(() => {\n mounted.current = true;\n return () => {\n mounted.current = false;\n };\n }, []);\n const [namespaces, setNamespaces] = useState<string[]>([]);\n const [namespace, setNamespace] = useState(\"\");\n const [services, setServices] = useState<Service[]>([]);\n const [serviceName, setServiceName] = useState(\"\");\n const [focusedPod, setFocusedPod] = useState(\"\");\n const [showAll, setShowAll] = useState(false);\n useEffect(() => setShowAll(false), [namespace, serviceName, focusedPod]);\n const preferences = MonitoringPreferencesStore.getInstanceOrCreate<MonitoringPreferencesStore>();\n const [hideUpstreams, setHideUpstreams] = useState(() =>\n preferences.hiddenUpstreamClusters.includes(clusterId.current ?? \"\"),\n );\n const toggleUpstreams = () => {\n const id = clusterId.current;\n if (!id || Renderer.Catalog.activeCluster.get()?.metadata.uid !== id) return;\n const hidden = !hideUpstreams;\n const otherClusters = preferences.hiddenUpstreamClusters.filter((cluster) => cluster !== id);\n preferences.hiddenUpstreamClusters = hidden ? [...otherClusters, id].slice(-100) : otherClusters;\n setHideUpstreams(hidden);\n };\n const [inventory, setInventory] = useState<InventoryState>();\n const [refresh, setRefresh] = useState(0);\n const [scopeRefresh, setScopeRefresh] = useState(0);\n const [namespaceMessage, setNamespaceMessage] = useState(\"\");\n const [scopeLoading, setScopeLoading] = useState(true);\n const [loading, setLoading] = useState(false);\n const [scopeMessage, setScopeMessage] = useState(\"\");\n const [openError, setOpenError] = useState(\"\");\n useEffect(() => {\n const controller = new AbortController();\n setScopeLoading(true);\n setNamespaceMessage(\"\");\n void Renderer.K8sApi.namespacesApi\n .list({ reqInit: { signal: controller.signal } }, { limit: LIMIT + 1 })\n .then((items) => {\n if (controller.signal.aborted) return;\n const names = (items ?? [])\n .slice(0, LIMIT)\n .map((item) => item.getName())\n .sort();\n setNamespaces(names);\n setNamespace((current) => (names.includes(current) ? current : (names[0] ?? \"\")));\n if ((items?.length ?? 0) > LIMIT) setNamespaceMessage(`Namespace selector is capped at ${LIMIT} entries`);\n else if (!names.length) setScopeMessage(\"No visible namespaces returned by the API\");\n })\n .catch(() => {\n if (!controller.signal.aborted)\n setScopeMessage(\"Namespace inventory unavailable; check access to namespace listing\");\n })\n .finally(() => {\n if (!controller.signal.aborted) setScopeLoading(false);\n });\n return () => controller.abort();\n }, [scopeRefresh]);\n useEffect(() => {\n if (!namespace) return;\n const controller = new AbortController();\n setLoading(false);\n setServices([]);\n setServiceName(\"\");\n setInventory(undefined);\n setScopeLoading(true);\n setScopeMessage(\"\");\n void Renderer.K8sApi.serviceApi\n .list({ namespace, reqInit: { signal: controller.signal } }, { limit: LIMIT + 1 })\n .then((items) => {\n if (controller.signal.aborted) return;\n const visible = (items ?? []).slice(0, LIMIT).sort((a, b) => a.getName().localeCompare(b.getName()));\n setServices(visible);\n setServiceName(visible[0]?.getName() ?? \"\");\n if ((items?.length ?? 0) > LIMIT)\n setScopeMessage(`Service selector is capped at ${LIMIT} entries; additional Services are not shown`);\n else if (!visible.length) setScopeMessage(\"No visible Services in this namespace\");\n })\n .catch(() => {\n if (!controller.signal.aborted) setScopeMessage(\"Service inventory unavailable; check namespace access\");\n })\n .finally(() => {\n if (!controller.signal.aborted) setScopeLoading(false);\n });\n return () => controller.abort();\n }, [namespace, scopeRefresh]);\n const service = services.find((item) => item.getName() === serviceName);\n useEffect(() => {\n if (!service || !namespace || service.metadata.namespace !== namespace) return;\n const controller = new AbortController();\n setLoading(true);\n setInventory(undefined);\n setFocusedPod(\"\");\n setOpenError(\"\");\n void loadRelationshipInventory(namespace, service, controller.signal)\n .then((data) => {\n if (!controller.signal.aborted) setInventory({ namespace, service: service.getName(), data });\n })\n .finally(() => {\n if (!controller.signal.aborted) setLoading(false);\n });\n return () => controller.abort();\n }, [namespace, service, refresh]);\n const current = inventory?.namespace === namespace && inventory.service === serviceName ? inventory : undefined;\n const graph =\n current && service\n ? buildResourceRelationships(service, current.data, focusedPod || undefined, showAll)\n : undefined;\n useEffect(() => {\n if (!graph || loading || !clusterId.current) return;\n const id = clusterId.current;\n const attach = () =>\n explainDiagnosticFinding(relationshipMapFinding(id, namespace, serviceName, graph, hideUpstreams));\n window.addEventListener(\"power-ai-request-screen-context\", attach);\n return () => window.removeEventListener(\"power-ai-request-screen-context\", attach);\n }, [graph, loading, namespace, serviceName, hideUpstreams]);\n const openResource = (path: string) => {\n const currentCluster = () =>\n mounted.current && Renderer.Catalog.activeCluster.get()?.metadata.uid === clusterId.current;\n setOpenError(\"\");\n void Promise.resolve()\n .then(() => {\n if (!currentCluster()) return;\n const gatewayPath = path.match(\n /^\\/apis\\/(gateway\\.networking\\.k8s\\.io)\\/([^/]+)\\/(?:namespaces\\/([^/]+)\\/)?([^/]+)\\/([^/]+)$/,\n );\n if (gatewayPath) {\n const [, group, version, namespace, resource, name] = gatewayPath;\n const kind = (\n {\n gateways: \"Gateway\",\n gatewayclasses: \"GatewayClass\",\n httproutes: \"HTTPRoute\",\n grpcroutes: \"GRPCRoute\",\n tcproutes: \"TCPRoute\",\n tlsroutes: \"TLSRoute\",\n udproutes: \"UDPRoute\",\n } as Record<string, string>\n )[resource];\n return openSearchResource({ path, group, version, namespace, resource, name, kind, labels: {} });\n }\n return Renderer.Navigation.showDetails(path);\n })\n .catch(() => {\n if (currentCluster()) setOpenError(\"Resource details could not be opened; the object may be unavailable\");\n });\n };\n return (\n <div className=\"power-relationships\">\n <style>{resourceRelationshipsStyles}</style>\n <div className=\"page-heading\">\n <h2>Resource relationships</h2>\n </div>\n <p className=\"intro\">\n Follow one Service from upstream Ingress and Gateway API references to selected pods, published EndpointSlices\n and controller ownership. Connections show Kubernetes API evidence; they do not prove network reachability.\n </p>\n <div className=\"controls\">\n <label className=\"control\">\n <span>Namespace</span>\n <Select\n aria-label=\"Relationship namespace\"\n value={namespace}\n options={namespaces.map((name) => ({ value: name, label: name }))}\n onChange={(option) => setNamespace(option?.value ?? \"\")}\n isDisabled={!namespaces.length}\n />\n </label>\n <label className=\"control\">\n <span>Service</span>\n <Select\n aria-label=\"Relationship Service\"\n value={serviceName}\n options={services.map((item) => ({ value: item.getName(), label: item.getName() }))}\n onChange={(option) => setServiceName(option?.value ?? \"\")}\n isDisabled={!services.length || scopeLoading}\n />\n </label>\n <label className=\"control\">\n <span>Pod focus</span>\n <Select\n aria-label=\"Relationship pod focus\"\n value={focusedPod}\n options={[\n { value: \"\", label: showAll ? \"All selected pods\" : \"All selected pods (up to 8)\" },\n ...(graph?.podOptions ?? []).map((name) => ({ value: name, label: name })),\n ]}\n onChange={(option) => setFocusedPod(option?.value ?? \"\")}\n isDisabled={!graph?.podOptions.length}\n />\n </label>\n <NativeTooltip title={hideUpstreams ? \"Show upstream references\" : \"Hide upstream references\"}>\n <button\n type=\"button\"\n className=\"graph-option\"\n aria-pressed={hideUpstreams}\n onClick={toggleUpstreams}\n disabled={!clusterId.current}\n >\n <Icon material={hideUpstreams ? \"visibility_off\" : \"visibility\"} size={16} />\n Hide Upstream\n </button>\n </NativeTooltip>\n <NativeTooltip title=\"Refresh scoped API evidence\">\n <button\n type=\"button\"\n className=\"refresh\"\n onClick={() => (service ? setRefresh((value) => value + 1) : setScopeRefresh((value) => value + 1))}\n disabled={loading || scopeLoading}\n >\n <Icon material=\"refresh\" size={18} />\n Refresh\n </button>\n </NativeTooltip>\n </div>\n {namespaceMessage && (\n <div className=\"notice\" role=\"status\">\n {namespaceMessage}\n </div>\n )}\n {scopeMessage && (\n <div className=\"notice\" role=\"status\">\n {scopeMessage}\n </div>\n )}\n {openError && (\n <div className=\"notice warning\" role=\"alert\">\n {openError}\n </div>\n )}\n {(scopeLoading || loading) && (\n <div className=\"empty\" role=\"status\">\n Loading scoped relationship evidence…\n </div>\n )}\n {!scopeLoading && !loading && !service && (\n <div className=\"empty\">Select a namespace with a visible Service to inspect relationships</div>\n )}\n {graph && !loading && (\n <>\n <div className=\"notice relationship-summary\">\n <strong>{graph.diagnostics.summary}</strong>\n <div className=\"ports\">\n {graph.diagnostics.ports.map((port) => (\n <span key={port.name}>\n {port.name} · {port.protocol} → {port.target} · published:{\" \"}\n {port.endpointPorts.join(\", \") || \"unknown\"}\n {port.unresolved ? ` · ${port.unresolved} unresolved named targets` : \"\"}\n </span>\n ))}\n </div>\n </div>\n {graph.gaps.length > 0 && (\n <details open className=\"notice\">\n <summary>Partial coverage ({graph.gaps.length})</summary>\n <ul>\n {graph.gaps.map((gap) => (\n <li key={gap}>{gap}</li>\n ))}\n </ul>\n </details>\n )}\n <RelationshipGraph\n graph={graph}\n onOpen={openResource}\n ingressAvailable={current?.data.ingresses !== undefined}\n hideUpstreams={hideUpstreams}\n />\n {(graph.omitted > 0 || showAll) && (\n <div className=\"notice graph-omitted-notice\">\n {!showAll && <Icon material=\"warning_amber\" className=\"graph-omitted-warning\" size={16} />}\n <span>\n {showAll ? (\n \"All available resources are shown.\"\n ) : (\n <>\n Hidden resources: <strong>{graph.omitted}</strong>. Show all to expand the map.\n </>\n )}\n </span>\n {!showAll && (\n <NativeTooltip title=\"Show all available resources\">\n <button\n type=\"button\"\n className=\"graph-show-all\"\n aria-label=\"Show all available resources\"\n onClick={() => setShowAll(true)}\n >\n <Icon material=\"visibility\" size={16} />\n </button>\n </NativeTooltip>\n )}\n </div>\n )}\n <details>\n <summary>Accessible connection list ({graph.edges.length})</summary>\n <ul className=\"edge-list\">\n {graph.edges.map((edge) => (\n <li key={`${edge.from}/${edge.to}/${edge.label}`}>\n {graph.nodes.find((node) => node.id === edge.from)?.name} → {edge.label} →{\" \"}\n {graph.nodes.find((node) => node.id === edge.to)?.name}\n {edge.evidence && <div>{edge.evidence}</div>}\n </li>\n ))}\n </ul>\n </details>\n <p className=\"scope\">\n <span>\n Snapshot from read-only API requests; Gateway discovery and references include other namespaces.\n </span>\n <span>Owner and node references can point to objects that were not queried.</span>\n <span>Endpoint counts can include separate address families.</span>\n <span>No Secret or ConfigMap data is read.</span>\n </p>\n </>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -156,6 +156,17 @@ function SearchDialog({ close, clusterId }) {
|
|
|
156
156
|
const [allFor, setAllFor] = require__global_external_react.useState();
|
|
157
157
|
const fetchAll = allFor === searchKey;
|
|
158
158
|
const [allRequests, setAllRequests] = require__global_external_react.useState(0);
|
|
159
|
+
const inventoryRevision = `${coverage.scanned}/${coverage.indexing}/${coverage.completedAt ?? ""}`;
|
|
160
|
+
const [allInventoryRevision, setAllInventoryRevision] = require__global_external_react.useState(inventoryRevision);
|
|
161
|
+
require__global_external_react.useEffect(() => {
|
|
162
|
+
if (!fetchAll || !loading && !coverage.indexing) setAllInventoryRevision(inventoryRevision);
|
|
163
|
+
}, [
|
|
164
|
+
fetchAll,
|
|
165
|
+
loading,
|
|
166
|
+
coverage.indexing,
|
|
167
|
+
inventoryRevision
|
|
168
|
+
]);
|
|
169
|
+
const queryInventoryRevision = fetchAll ? allInventoryRevision : inventoryRevision;
|
|
159
170
|
const [progress, setProgress] = require__global_external_react.useState({
|
|
160
171
|
loaded: 0,
|
|
161
172
|
total: 0
|
|
@@ -191,7 +202,7 @@ function SearchDialog({ close, clusterId }) {
|
|
|
191
202
|
if (!live || activeId() !== clusterId) return;
|
|
192
203
|
const previousCount = documents.size;
|
|
193
204
|
for (const document of result.documents) documents.set(document.path, document);
|
|
194
|
-
setResources([...documents.values()]);
|
|
205
|
+
if (!fetchAll || documents.size >= resources.length || !result.hasMore) setResources([...documents.values()]);
|
|
195
206
|
setProgress({
|
|
196
207
|
loaded: documents.size,
|
|
197
208
|
total: result.total
|
|
@@ -225,8 +236,7 @@ function SearchDialog({ close, clusterId }) {
|
|
|
225
236
|
allRequests,
|
|
226
237
|
kindFilter,
|
|
227
238
|
namespaceFilter,
|
|
228
|
-
|
|
229
|
-
coverage.indexing
|
|
239
|
+
queryInventoryRevision
|
|
230
240
|
]);
|
|
231
241
|
require__global_external_react.useEffect(() => {
|
|
232
242
|
document.getElementById(`power-resource-result-${selected}`)?.scrollIntoView?.({ block: "nearest" });
|