@anyshift/backstage-plugin-anyshift 0.1.0-beta.1

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.
Files changed (37) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/LICENSE +176 -0
  3. package/README.md +9 -0
  4. package/dist/api/AnyshiftApi.esm.js +80 -0
  5. package/dist/api/AnyshiftApi.esm.js.map +1 -0
  6. package/dist/components/AnyshiftPermissionBoundary.esm.js +25 -0
  7. package/dist/components/AnyshiftPermissionBoundary.esm.js.map +1 -0
  8. package/dist/components/entity/AnyshiftEntityContent.esm.js +213 -0
  9. package/dist/components/entity/AnyshiftEntityContent.esm.js.map +1 -0
  10. package/dist/components/entity/BriefSections.esm.js +218 -0
  11. package/dist/components/entity/BriefSections.esm.js.map +1 -0
  12. package/dist/components/entity/DatadogLiveSignal.esm.js +190 -0
  13. package/dist/components/entity/DatadogLiveSignal.esm.js.map +1 -0
  14. package/dist/components/entity/EvidenceDisclosure.esm.js +20 -0
  15. package/dist/components/entity/EvidenceDisclosure.esm.js.map +1 -0
  16. package/dist/components/entity/MermaidArchitecture.esm.js +89 -0
  17. package/dist/components/entity/MermaidArchitecture.esm.js.map +1 -0
  18. package/dist/components/entity/SectionPresenters.esm.js +341 -0
  19. package/dist/components/entity/SectionPresenters.esm.js.map +1 -0
  20. package/dist/components/entity/architectureDiagram.esm.js +236 -0
  21. package/dist/components/entity/architectureDiagram.esm.js.map +1 -0
  22. package/dist/components/entity/sectionData.esm.js +127 -0
  23. package/dist/components/entity/sectionData.esm.js.map +1 -0
  24. package/dist/components/explorer/AnyshiftExplorerPage.esm.js +193 -0
  25. package/dist/components/explorer/AnyshiftExplorerPage.esm.js.map +1 -0
  26. package/dist/components/explorer/DatadogOperationsRadar.esm.js +294 -0
  27. package/dist/components/explorer/DatadogOperationsRadar.esm.js.map +1 -0
  28. package/dist/index.d.ts +127 -0
  29. package/dist/index.esm.js +4 -0
  30. package/dist/index.esm.js.map +1 -0
  31. package/dist/package.json.esm.js +96 -0
  32. package/dist/package.json.esm.js.map +1 -0
  33. package/dist/plugin.esm.js +49 -0
  34. package/dist/plugin.esm.js.map +1 -0
  35. package/dist/routes.esm.js +6 -0
  36. package/dist/routes.esm.js.map +1 -0
  37. package/package.json +84 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"architectureDiagram.esm.js","sources":["../../../src/components/entity/architectureDiagram.ts"],"sourcesContent":["export interface ArchitectureNode {\n id: string;\n name: string;\n type?: string | null;\n namespace?: string | null;\n image?: string | null;\n}\n\nexport interface ArchitectureEdge {\n from: string;\n to: string;\n type: string;\n}\n\nexport interface ArchitectureGraph {\n nodes: ArchitectureNode[];\n edges: ArchitectureEdge[];\n}\n\nexport interface ArchitectureDiagramDefinition {\n source: string;\n fallbackRelationships: string[];\n}\n\ninterface CompactGraph {\n nodes: ArchitectureNode[];\n edges: ArchitectureEdge[];\n}\n\nconst RUNTIME_INSTANCE_TYPES = new Set(['K8S_REPLICASET', 'K8S_POD']);\nconst MAX_DIRECT_DEPENDENCIES = 5;\n\nexport function buildArchitectureDiagram(\n graph: ArchitectureGraph,\n options: { view?: 'context' | 'runtime' } = {},\n): ArchitectureDiagramDefinition {\n const base = compactArchitectureGraph(graph);\n const viewed = options.view === 'context' ? serviceContextGraph(base) : base;\n const compact = summarizeDirectDependencies(viewed);\n const nodeIds = new Map(\n compact.nodes.map((node, index) => [node.id, `n${index}`]),\n );\n const names = new Map(\n compact.nodes.map(node => [node.id, readableNodeLabel(node)]),\n );\n const lines = ['flowchart LR'];\n\n compact.nodes.forEach(node => {\n const id = nodeIds.get(node.id)!;\n const label = mermaidNodeLabel(node);\n if (node.type === 'DATADOG_DATASTORE') {\n lines.push(` ${id}[(\"${label}\")]`);\n } else if (\n node.type === 'DATADOG_EXTERNAL' ||\n node.type === 'DATADOG_DESTINATION'\n ) {\n lines.push(` ${id}([\"${label}\"])`);\n } else {\n lines.push(` ${id}[\"${label}\"]`);\n }\n });\n\n compact.edges.forEach(edge => {\n const from = nodeIds.get(edge.from);\n const to = nodeIds.get(edge.to);\n if (from && to) {\n lines.push(` ${from} -->|${sanitize(edge.type)}| ${to}`);\n }\n });\n\n lines.push(\n ' classDef service fill:#e8f0fe,stroke:#1967d2,color:#174ea6',\n ' classDef runtime fill:#e6f4ea,stroke:#188038,color:#137333',\n ' classDef dependency fill:#fef7e0,stroke:#f9ab00,color:#7a4f01',\n );\n compact.nodes.forEach(node => {\n const id = nodeIds.get(node.id)!;\n lines.push(` class ${id} ${className(node)}`);\n });\n\n return {\n source: lines.join('\\n'),\n fallbackRelationships: compact.edges.flatMap(edge => {\n const from = names.get(edge.from);\n const to = names.get(edge.to);\n return from && to\n ? [`${from} → ${readableRelationship(edge.type)} → ${to}`]\n : [];\n }),\n };\n}\n\nfunction serviceContextGraph(graph: CompactGraph): CompactGraph {\n const nodes = graph.nodes.filter(node => node.type !== 'K8S_CONTAINER');\n const visible = new Set(nodes.map(node => node.id));\n return {\n nodes,\n edges: graph.edges.filter(\n edge => visible.has(edge.from) && visible.has(edge.to),\n ),\n };\n}\n\nfunction compactArchitectureGraph(graph: ArchitectureGraph): CompactGraph {\n const nodeById = new Map(graph.nodes.map(node => [node.id, node]));\n const visibleNodes = graph.nodes\n .filter(node => !isRuntimeInstance(node))\n .map(normalizeNode);\n const canonicalNodes = new Map<string, ArchitectureNode>();\n const canonicalId = new Map<string, string>();\n\n visibleNodes.forEach(node => {\n const key = semanticNodeKey(node);\n const existing = canonicalNodes.get(key);\n if (existing) {\n canonicalId.set(node.id, existing.id);\n } else {\n canonicalNodes.set(key, node);\n canonicalId.set(node.id, node.id);\n }\n });\n\n const outgoing = new Map<string, ArchitectureEdge[]>();\n graph.edges.forEach(edge => {\n const list = outgoing.get(edge.from) ?? [];\n list.push(edge);\n outgoing.set(edge.from, list);\n });\n\n const compactEdges = new Map<string, ArchitectureEdge>();\n visibleNodes.forEach(source => {\n const sourceId = canonicalId.get(source.id)!;\n walkToVisibleTargets(source.id, outgoing, nodeById).forEach(target => {\n const targetId = canonicalId.get(target.node.id);\n if (!targetId || sourceId === targetId) return;\n const type = target.collapsed ? 'RUNS' : target.edgeType;\n const key = `${sourceId}|${type}|${targetId}`;\n compactEdges.set(key, { from: sourceId, to: targetId, type });\n });\n });\n\n return {\n nodes: [...canonicalNodes.values()],\n edges: [...compactEdges.values()],\n };\n}\n\nfunction summarizeDirectDependencies(graph: CompactGraph): CompactGraph {\n const root = graph.edges.find(edge => edge.type === 'RESOLVES_TO')?.from;\n if (!root) return graph;\n\n const nodes = new Map(graph.nodes.map(node => [node.id, node]));\n const groups = new Map<string, ArchitectureEdge[]>();\n const groupedEdges = new Set<ArchitectureEdge>();\n\n graph.edges.forEach(edge => {\n if (edge.type === 'RESOLVES_TO') return;\n let neighborId: string | undefined;\n if (edge.from === root) neighborId = edge.to;\n if (edge.to === root) neighborId = edge.from;\n if (!neighborId) return;\n const neighbor = nodes.get(neighborId);\n if (!neighbor || neighbor.type?.startsWith('K8S_')) return;\n const direction = edge.from === root ? 'out' : 'in';\n const key = `${direction}|${edge.type}|${neighbor.type ?? ''}`;\n const group = groups.get(key) ?? [];\n group.push(edge);\n groups.set(key, group);\n groupedEdges.add(edge);\n });\n\n const edges = graph.edges.filter(edge => !groupedEdges.has(edge));\n const aggregateNodes: ArchitectureNode[] = [];\n groups.forEach((group, key) => {\n if (group.length <= MAX_DIRECT_DEPENDENCIES) {\n edges.push(...group);\n return;\n }\n\n const visible = group.slice(0, MAX_DIRECT_DEPENDENCIES - 1);\n const hidden = group.slice(MAX_DIRECT_DEPENDENCIES - 1);\n const sample = group[0];\n const direction = sample.from === root ? 'out' : 'in';\n const neighbor = nodes.get(direction === 'out' ? sample.to : sample.from)!;\n const aggregateId = `aggregate-${key.replace(/[^A-Za-z0-9]/g, '-')}`;\n aggregateNodes.push({\n id: aggregateId,\n name: `${hidden.length} more ${pluralType(neighbor.type)}`,\n type: neighbor.type,\n });\n edges.push(...visible);\n edges.push(\n direction === 'out'\n ? { from: root, to: aggregateId, type: sample.type }\n : { from: aggregateId, to: root, type: sample.type },\n );\n });\n\n const referenced = new Set(edges.flatMap(edge => [edge.from, edge.to]));\n return {\n nodes: [\n ...graph.nodes.filter(node => referenced.has(node.id)),\n ...aggregateNodes,\n ],\n edges,\n };\n}\n\nfunction walkToVisibleTargets(\n start: string,\n outgoing: Map<string, ArchitectureEdge[]>,\n nodeById: Map<string, ArchitectureNode>,\n): Array<{\n node: ArchitectureNode;\n edgeType: string;\n collapsed: boolean;\n}> {\n const targets: Array<{\n node: ArchitectureNode;\n edgeType: string;\n collapsed: boolean;\n }> = [];\n const queue = (outgoing.get(start) ?? []).map(edge => ({\n id: edge.to,\n edgeType: edge.type,\n collapsed: false,\n }));\n const visited = new Set<string>();\n\n while (queue.length > 0) {\n const current = queue.shift()!;\n const visitKey = `${current.id}|${current.collapsed}`;\n if (visited.has(visitKey)) continue;\n visited.add(visitKey);\n\n const node = nodeById.get(current.id);\n if (!node) continue;\n if (!isRuntimeInstance(node)) {\n targets.push({ node, ...current });\n continue;\n }\n\n (outgoing.get(current.id) ?? []).forEach(edge => {\n queue.push({ id: edge.to, edgeType: edge.type, collapsed: true });\n });\n }\n\n return targets;\n}\n\nfunction isRuntimeInstance(node: ArchitectureNode): boolean {\n return RUNTIME_INSTANCE_TYPES.has(node.type ?? '');\n}\n\nfunction normalizeNode(node: ArchitectureNode): ArchitectureNode {\n if (node.type !== 'K8S_CONTAINER') return node;\n const slash = node.name.lastIndexOf('/');\n return {\n ...node,\n name: slash >= 0 ? node.name.slice(slash + 1) : node.name,\n image: node.image ? imageRepository(node.image) : node.image,\n };\n}\n\nfunction imageRepository(image: string): string {\n const withoutDigest = image.split('@', 1)[0];\n const slash = withoutDigest.lastIndexOf('/');\n const tag = withoutDigest.lastIndexOf(':');\n const repository = tag > slash ? withoutDigest.slice(0, tag) : withoutDigest;\n return repository.slice(repository.lastIndexOf('/') + 1);\n}\n\nfunction semanticNodeKey(node: ArchitectureNode): string {\n return [\n node.type ?? '',\n node.namespace ?? '',\n node.name,\n node.image ?? '',\n ].join('|');\n}\n\nfunction readableNodeLabel(node: ArchitectureNode): string {\n const type = shortType(node.type);\n const typed = type ? `${node.name} [${type}]` : node.name;\n return node.type?.startsWith('K8S_') && node.namespace\n ? `${typed} (${node.namespace})`\n : typed;\n}\n\nfunction mermaidNodeLabel(node: ArchitectureNode): string {\n const parts = [sanitize(node.name)];\n const type = shortType(node.type);\n if (type) parts.push(`[${type}]`);\n if (node.type?.startsWith('K8S_') && node.namespace) {\n parts.push(`namespace: ${sanitize(node.namespace)}`);\n }\n if (node.image) parts.push(sanitize(node.image));\n return parts.join('<br/>');\n}\n\nfunction shortType(type?: string | null): string {\n return (type ?? '').replace(/^K8S_|^DATADOG_/, '');\n}\n\nfunction pluralType(type?: string | null): string {\n return `${shortType(type).toLocaleLowerCase()}s`;\n}\n\nfunction readableRelationship(type: string): string {\n return type.toLocaleLowerCase().replace(/_/g, ' ');\n}\n\nfunction sanitize(value: string): string {\n return value\n .replace(/\"/g, \"'\")\n .replace(/[<>|]/g, ' ')\n .replace(/\\s+/g, ' ')\n .trim();\n}\n\nfunction className(node: ArchitectureNode): string {\n if (node.type?.startsWith('K8S_')) return 'runtime';\n if (node.type === 'DATADOG_SERVICE') return 'service';\n return 'dependency';\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,127 @@
1
+ const COLLECTION_KEYS = [
2
+ "recent",
3
+ "items",
4
+ "resources",
5
+ "nodes",
6
+ "events",
7
+ "deployments",
8
+ "affected",
9
+ "dependencies",
10
+ "claims"
11
+ ];
12
+ const RESULT_ENVELOPE_KEYS = [
13
+ "spof",
14
+ "scaling",
15
+ "pdb",
16
+ "deployments",
17
+ "blastRadius",
18
+ "topology"
19
+ ];
20
+ const EVENT_FACT_KEYS = /* @__PURE__ */ new Set([
21
+ "type",
22
+ "eventType",
23
+ "kind",
24
+ "target",
25
+ "resource",
26
+ "name",
27
+ "ts",
28
+ "timestamp",
29
+ "time",
30
+ "occurredAt",
31
+ "summary",
32
+ "message",
33
+ "description"
34
+ ]);
35
+ const TRANSPORT_METADATA_KEYS = /* @__PURE__ */ new Set([
36
+ "question",
37
+ "intent",
38
+ "countOnly",
39
+ "elapsedMs",
40
+ "sql",
41
+ "projectId"
42
+ ]);
43
+ function recordsFrom(value) {
44
+ if (Array.isArray(value)) return value.filter(isRecord);
45
+ if (!isRecord(value)) return [];
46
+ for (const key of COLLECTION_KEYS) {
47
+ const candidate = value[key];
48
+ if (Array.isArray(candidate)) return candidate.filter(isRecord);
49
+ if (isRecord(candidate)) {
50
+ const nested = recordsFrom(candidate);
51
+ if (nested.length > 0) return nested;
52
+ }
53
+ }
54
+ for (const key of RESULT_ENVELOPE_KEYS) {
55
+ const nested = recordsFrom(value[key]);
56
+ if (nested.length > 0) return nested;
57
+ }
58
+ return [];
59
+ }
60
+ function firstRecordFrom(value) {
61
+ const records = recordsFrom(value);
62
+ if (records.length > 0) return records[0];
63
+ if (isRecord(value) && primitiveEntries(value).length > 0) return value;
64
+ return void 0;
65
+ }
66
+ function factsFrom(value, limit = 6) {
67
+ if (!isRecord(value)) return [];
68
+ return primitiveEntries(value).filter(([key]) => !TRANSPORT_METADATA_KEYS.has(key)).slice(0, limit).map(([key, item]) => ({ label: titleCase(key), value: String(item) }));
69
+ }
70
+ function eventFrom(value) {
71
+ const record = firstRecordFrom(value) ?? {};
72
+ return {
73
+ type: readableText(readText(record, ["type", "eventType", "kind"])),
74
+ target: readText(record, ["target", "resource", "name"]),
75
+ timestamp: readText(record, ["ts", "timestamp", "time", "occurredAt"]),
76
+ summary: readText(record, ["summary", "message", "description"]),
77
+ status: statusFrom(record),
78
+ facts: primitiveEntries(record).filter(([key]) => !EVENT_FACT_KEYS.has(key)).slice(0, 6).map(([key, item]) => ({ label: titleCase(key), value: String(item) }))
79
+ };
80
+ }
81
+ function statusFrom(value) {
82
+ if (!isRecord(value)) return void 0;
83
+ const status = readText(value, ["status", "state", "severity", "health"]);
84
+ if (!status) return void 0;
85
+ const normalized = status.toLocaleLowerCase().replace(/[\s_-]+/g, "");
86
+ const success = ["healthy", "ok", "passing", "ready", "stable", "success"];
87
+ const warning = ["warning", "warn", "degraded", "atrisk", "pending"];
88
+ const error = [
89
+ "error",
90
+ "critical",
91
+ "failed",
92
+ "failure",
93
+ "unhealthy",
94
+ "breached"
95
+ ];
96
+ return {
97
+ label: titleCase(status),
98
+ tone: success.includes(normalized) ? "success" : warning.includes(normalized) ? "warning" : error.includes(normalized) ? "error" : "default"
99
+ };
100
+ }
101
+ function readText(value, keys) {
102
+ if (!isRecord(value)) return void 0;
103
+ for (const key of keys) {
104
+ const item = value[key];
105
+ if (typeof item === "string" && item.trim()) return item.trim();
106
+ if (typeof item === "number") return String(item);
107
+ }
108
+ return void 0;
109
+ }
110
+ function titleCase(value) {
111
+ const words = value.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[_-]+/g, " ").trim().toLocaleLowerCase();
112
+ return words ? `${words[0].toLocaleUpperCase()}${words.slice(1)}` : value;
113
+ }
114
+ function isRecord(value) {
115
+ return typeof value === "object" && value !== null && !Array.isArray(value);
116
+ }
117
+ function primitiveEntries(value) {
118
+ return Object.entries(value).filter(
119
+ (entry) => ["string", "number", "boolean"].includes(typeof entry[1])
120
+ );
121
+ }
122
+ function readableText(value) {
123
+ return value?.replace(/[_-]+/g, " ").toLocaleLowerCase();
124
+ }
125
+
126
+ export { eventFrom, factsFrom, firstRecordFrom, isRecord, readText, recordsFrom, statusFrom, titleCase };
127
+ //# sourceMappingURL=sectionData.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sectionData.esm.js","sources":["../../../src/components/entity/sectionData.ts"],"sourcesContent":["export interface Fact {\n label: string;\n value: string;\n}\n\nexport interface EventSummary {\n type?: string;\n target?: string;\n timestamp?: string;\n summary?: string;\n status?: StatusSummary;\n facts: Fact[];\n}\n\nexport interface StatusSummary {\n label: string;\n tone: 'default' | 'success' | 'warning' | 'error';\n}\n\nconst COLLECTION_KEYS = [\n 'recent',\n 'items',\n 'resources',\n 'nodes',\n 'events',\n 'deployments',\n 'affected',\n 'dependencies',\n 'claims',\n] as const;\n\nconst RESULT_ENVELOPE_KEYS = [\n 'spof',\n 'scaling',\n 'pdb',\n 'deployments',\n 'blastRadius',\n 'topology',\n] as const;\n\nconst EVENT_FACT_KEYS = new Set([\n 'type',\n 'eventType',\n 'kind',\n 'target',\n 'resource',\n 'name',\n 'ts',\n 'timestamp',\n 'time',\n 'occurredAt',\n 'summary',\n 'message',\n 'description',\n]);\n\nconst TRANSPORT_METADATA_KEYS = new Set([\n 'question',\n 'intent',\n 'countOnly',\n 'elapsedMs',\n 'sql',\n 'projectId',\n]);\n\nexport function recordsFrom(value: unknown): Record<string, unknown>[] {\n if (Array.isArray(value)) return value.filter(isRecord);\n if (!isRecord(value)) return [];\n\n for (const key of COLLECTION_KEYS) {\n const candidate = value[key];\n if (Array.isArray(candidate)) return candidate.filter(isRecord);\n if (isRecord(candidate)) {\n const nested = recordsFrom(candidate);\n if (nested.length > 0) return nested;\n }\n }\n for (const key of RESULT_ENVELOPE_KEYS) {\n const nested = recordsFrom(value[key]);\n if (nested.length > 0) return nested;\n }\n return [];\n}\n\nexport function firstRecordFrom(\n value: unknown,\n): Record<string, unknown> | undefined {\n const records = recordsFrom(value);\n if (records.length > 0) return records[0];\n if (isRecord(value) && primitiveEntries(value).length > 0) return value;\n return undefined;\n}\n\nexport function factsFrom(value: unknown, limit = 6): Fact[] {\n if (!isRecord(value)) return [];\n return primitiveEntries(value)\n .filter(([key]) => !TRANSPORT_METADATA_KEYS.has(key))\n .slice(0, limit)\n .map(([key, item]) => ({ label: titleCase(key), value: String(item) }));\n}\n\nexport function eventFrom(value: unknown): EventSummary {\n const record = firstRecordFrom(value) ?? {};\n return {\n type: readableText(readText(record, ['type', 'eventType', 'kind'])),\n target: readText(record, ['target', 'resource', 'name']),\n timestamp: readText(record, ['ts', 'timestamp', 'time', 'occurredAt']),\n summary: readText(record, ['summary', 'message', 'description']),\n status: statusFrom(record),\n facts: primitiveEntries(record)\n .filter(([key]) => !EVENT_FACT_KEYS.has(key))\n .slice(0, 6)\n .map(([key, item]) => ({ label: titleCase(key), value: String(item) })),\n };\n}\n\nexport function statusFrom(value: unknown): StatusSummary | undefined {\n if (!isRecord(value)) return undefined;\n const status = readText(value, ['status', 'state', 'severity', 'health']);\n if (!status) return undefined;\n\n const normalized = status.toLocaleLowerCase().replace(/[\\s_-]+/g, '');\n const success = ['healthy', 'ok', 'passing', 'ready', 'stable', 'success'];\n const warning = ['warning', 'warn', 'degraded', 'atrisk', 'pending'];\n const error = [\n 'error',\n 'critical',\n 'failed',\n 'failure',\n 'unhealthy',\n 'breached',\n ];\n\n return {\n label: titleCase(status),\n tone: success.includes(normalized)\n ? 'success'\n : warning.includes(normalized)\n ? 'warning'\n : error.includes(normalized)\n ? 'error'\n : 'default',\n };\n}\n\nexport function readText(\n value: unknown,\n keys: readonly string[],\n): string | undefined {\n if (!isRecord(value)) return undefined;\n for (const key of keys) {\n const item = value[key];\n if (typeof item === 'string' && item.trim()) return item.trim();\n if (typeof item === 'number') return String(item);\n }\n return undefined;\n}\n\nexport function titleCase(value: string): string {\n const words = value\n .replace(/([a-z0-9])([A-Z])/g, '$1 $2')\n .replace(/[_-]+/g, ' ')\n .trim()\n .toLocaleLowerCase();\n return words ? `${words[0].toLocaleUpperCase()}${words.slice(1)}` : value;\n}\n\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction primitiveEntries(\n value: Record<string, unknown>,\n): Array<[string, string | number | boolean]> {\n return Object.entries(value).filter(\n (entry): entry is [string, string | number | boolean] =>\n ['string', 'number', 'boolean'].includes(typeof entry[1]),\n );\n}\n\nfunction readableText(value: string | undefined): string | undefined {\n return value?.replace(/[_-]+/g, ' ').toLocaleLowerCase();\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,193 @@
1
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
+ import { useState, useEffect } from 'react';
3
+ import { Typography, TextField, Grid, Button } from '@material-ui/core';
4
+ import { Page, Header, Content, Progress, ContentHeader, InfoCard } from '@backstage/core-components';
5
+ import { useApi } from '@backstage/frontend-plugin-api';
6
+ import { usePermission } from '@backstage/plugin-permission-react';
7
+ import { anyshiftQueryPermission } from '@anyshift/backstage-plugin-anyshift-common';
8
+ import { catalogApiRef, EntityRefLink } from '@backstage/plugin-catalog-react';
9
+ import { anyshiftApiRef } from '../../api/AnyshiftApi.esm.js';
10
+ import { TimelinePresenter, ImpactPresenter } from '../entity/SectionPresenters.esm.js';
11
+ import { DatadogOperationsRadar } from './DatadogOperationsRadar.esm.js';
12
+
13
+ const DEFAULT_QUERY = "SELECT * FROM resources WHERE type = deployment LIMIT 10";
14
+ function isDeterministicSelect(value) {
15
+ const sql = value.trim();
16
+ return /^SELECT\b/i.test(sql) && sql.length <= 4096 && !sql.includes(";") && !sql.includes("--") && !sql.includes("/*");
17
+ }
18
+ function matchesCatalogEntity(entity, value) {
19
+ const query = value.trim().toLocaleLowerCase();
20
+ if (!query) return true;
21
+ const searchable = [
22
+ entity.metadata.name,
23
+ entity.metadata.title,
24
+ entity.metadata.description,
25
+ entity.metadata.annotations?.["anyshift.io/target"],
26
+ typeof entity.spec?.owner === "string" ? entity.spec.owner : void 0
27
+ ];
28
+ return searchable.some((item) => item?.toLocaleLowerCase().includes(query));
29
+ }
30
+ const EstateInsightsGrid = ({
31
+ insights
32
+ }) => /* @__PURE__ */ jsx(Fragment, { children: insights.sections.map((item) => /* @__PURE__ */ jsx(Grid, { item: true, xs: 12, md: 6, children: /* @__PURE__ */ jsx(InfoCard, { title: item.title, children: item.section.state === "error" ? /* @__PURE__ */ jsx(Typography, { color: "error", children: item.section.message }) : item.section.state === "empty" || item.section.state === "unsupported" || item.section.data === void 0 ? /* @__PURE__ */ jsx(Typography, { color: "textSecondary", children: item.section.message || "No insight evidence is available." }) : item.id === "recent-change" ? /* @__PURE__ */ jsx(
33
+ TimelinePresenter,
34
+ {
35
+ data: item.section.data,
36
+ fallbackLabel: "Deployment"
37
+ }
38
+ ) : /* @__PURE__ */ jsx(ImpactPresenter, { data: item.section.data }) }) }, item.id)) });
39
+ const AnyshiftExplorerPage = () => {
40
+ const api = useApi(anyshiftApiRef);
41
+ const catalogApi = useApi(catalogApiRef);
42
+ const queryPermission = usePermission({
43
+ permission: anyshiftQueryPermission
44
+ });
45
+ const [queryEnabled, setQueryEnabled] = useState(false);
46
+ const [insights, setInsights] = useState();
47
+ const [insightError, setInsightError] = useState();
48
+ const [datadogSignals, setDatadogSignals] = useState();
49
+ const [datadogError, setDatadogError] = useState();
50
+ const [refreshingDatadog, setRefreshingDatadog] = useState(false);
51
+ const [catalogEntities, setCatalogEntities] = useState([]);
52
+ const [catalogError, setCatalogError] = useState();
53
+ const [catalogQuery, setCatalogQuery] = useState("");
54
+ const [sql, setSql] = useState(DEFAULT_QUERY);
55
+ const [queryResult, setQueryResult] = useState();
56
+ const [queryError, setQueryError] = useState();
57
+ useEffect(() => {
58
+ api.capabilities().then((capabilities) => setQueryEnabled(capabilities.queryEnabled)).catch(() => setQueryEnabled(false));
59
+ }, [api]);
60
+ useEffect(() => {
61
+ api.datadogSignals().then(setDatadogSignals).catch((error) => {
62
+ setDatadogError(error instanceof Error ? error.message : String(error));
63
+ });
64
+ }, [api]);
65
+ useEffect(() => {
66
+ api.insights().then(setInsights).catch((error) => {
67
+ setInsightError(error instanceof Error ? error.message : String(error));
68
+ });
69
+ }, [api]);
70
+ useEffect(() => {
71
+ catalogApi.getEntities({
72
+ filter: [{ kind: "Component" }, { kind: "Resource" }]
73
+ }).then(
74
+ (response) => setCatalogEntities(
75
+ response.items.filter(
76
+ (entity) => entity.metadata.annotations?.["anyshift.io/target"]
77
+ )
78
+ )
79
+ ).catch((error) => {
80
+ setCatalogError(error instanceof Error ? error.message : String(error));
81
+ });
82
+ }, [catalogApi]);
83
+ const matchingEntities = catalogEntities.filter((entity) => matchesCatalogEntity(entity, catalogQuery)).slice(0, 12);
84
+ const runQuery = async () => {
85
+ if (!isDeterministicSelect(sql)) {
86
+ setQueryError("Enter one deterministic SELECT query.");
87
+ return;
88
+ }
89
+ setQueryError(void 0);
90
+ try {
91
+ setQueryResult(await api.query(sql.trim()));
92
+ } catch (error) {
93
+ setQueryError(error instanceof Error ? error.message : String(error));
94
+ }
95
+ };
96
+ const refreshDatadog = async () => {
97
+ setRefreshingDatadog(true);
98
+ setDatadogError(void 0);
99
+ try {
100
+ setDatadogSignals(await api.datadogSignals({ refresh: true }));
101
+ } catch (error) {
102
+ setDatadogError(error instanceof Error ? error.message : String(error));
103
+ } finally {
104
+ setRefreshingDatadog(false);
105
+ }
106
+ };
107
+ return /* @__PURE__ */ jsxs(Page, { themeId: "tool", children: [
108
+ /* @__PURE__ */ jsx(
109
+ Header,
110
+ {
111
+ title: "Anyshift",
112
+ subtitle: "Live infrastructure context for your software catalog"
113
+ }
114
+ ),
115
+ /* @__PURE__ */ jsxs(Content, { children: [
116
+ datadogSignals ? /* @__PURE__ */ jsx(
117
+ DatadogOperationsRadar,
118
+ {
119
+ signals: datadogSignals,
120
+ catalogEntities,
121
+ onRefresh: refreshDatadog,
122
+ refreshing: refreshingDatadog,
123
+ error: datadogError
124
+ }
125
+ ) : datadogError ? /* @__PURE__ */ jsx(Typography, { color: "error", children: datadogError }) : /* @__PURE__ */ jsx(Progress, {}),
126
+ /* @__PURE__ */ jsx(ContentHeader, { title: "Find a service" }),
127
+ /* @__PURE__ */ jsxs(InfoCard, { subheader: "Anyshift-annotated Components and Resources in the Backstage catalog", children: [
128
+ /* @__PURE__ */ jsx(
129
+ TextField,
130
+ {
131
+ fullWidth: true,
132
+ variant: "outlined",
133
+ label: "Search services and resources",
134
+ value: catalogQuery,
135
+ onChange: (event) => setCatalogQuery(event.target.value)
136
+ }
137
+ ),
138
+ catalogError && /* @__PURE__ */ jsx(Typography, { color: "error", children: catalogError }),
139
+ !catalogError && matchingEntities.length === 0 ? /* @__PURE__ */ jsx(Typography, { color: "textSecondary", style: { marginTop: 12 }, children: "No matching Anyshift catalog entities." }) : /* @__PURE__ */ jsx("ul", { children: matchingEntities.map((entity) => /* @__PURE__ */ jsxs(
140
+ "li",
141
+ {
142
+ children: [
143
+ /* @__PURE__ */ jsx(EntityRefLink, { entityRef: entity }),
144
+ entity.metadata.description ? ` - ${entity.metadata.description}` : null
145
+ ]
146
+ },
147
+ `${entity.kind}:${entity.metadata.namespace ?? "default"}/${entity.metadata.name}`
148
+ )) })
149
+ ] }),
150
+ /* @__PURE__ */ jsx(ContentHeader, { title: "Estate insights" }),
151
+ insightError && /* @__PURE__ */ jsx(Typography, { color: "error", children: insightError }),
152
+ !insights && !insightError ? /* @__PURE__ */ jsx(Progress, {}) : null,
153
+ /* @__PURE__ */ jsxs(Grid, { container: true, spacing: 3, children: [
154
+ insights && /* @__PURE__ */ jsx(EstateInsightsGrid, { insights }),
155
+ queryEnabled && queryPermission.allowed && /* @__PURE__ */ jsx(Grid, { item: true, xs: 12, children: /* @__PURE__ */ jsxs(
156
+ InfoCard,
157
+ {
158
+ title: "Advanced query",
159
+ subheader: "Deterministic Graph API SELECT queries only",
160
+ children: [
161
+ /* @__PURE__ */ jsx(
162
+ TextField,
163
+ {
164
+ fullWidth: true,
165
+ multiline: true,
166
+ minRows: 2,
167
+ variant: "outlined",
168
+ value: sql,
169
+ onChange: (event) => setSql(event.target.value)
170
+ }
171
+ ),
172
+ /* @__PURE__ */ jsx(
173
+ Button,
174
+ {
175
+ variant: "contained",
176
+ color: "primary",
177
+ onClick: runQuery,
178
+ style: { marginTop: 12 },
179
+ children: "Run query"
180
+ }
181
+ ),
182
+ queryError && /* @__PURE__ */ jsx(Typography, { color: "error", children: queryError }),
183
+ queryResult && /* @__PURE__ */ jsx("pre", { style: { whiteSpace: "pre-wrap", fontSize: 12 }, children: JSON.stringify(queryResult, null, 2) })
184
+ ]
185
+ }
186
+ ) })
187
+ ] })
188
+ ] })
189
+ ] });
190
+ };
191
+
192
+ export { AnyshiftExplorerPage, EstateInsightsGrid, isDeterministicSelect, matchesCatalogEntity };
193
+ //# sourceMappingURL=AnyshiftExplorerPage.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AnyshiftExplorerPage.esm.js","sources":["../../../src/components/explorer/AnyshiftExplorerPage.tsx"],"sourcesContent":["import { useEffect, useState } from 'react';\nimport { Button, Grid, TextField, Typography } from '@material-ui/core';\nimport {\n Content,\n ContentHeader,\n Header,\n InfoCard,\n Page,\n Progress,\n} from '@backstage/core-components';\nimport { useApi } from '@backstage/frontend-plugin-api';\nimport { usePermission } from '@backstage/plugin-permission-react';\nimport { anyshiftQueryPermission } from '@anyshift/backstage-plugin-anyshift-common';\nimport type { Entity } from '@backstage/catalog-model';\nimport { catalogApiRef, EntityRefLink } from '@backstage/plugin-catalog-react';\nimport { anyshiftApiRef } from '../../api/AnyshiftApi';\nimport type {\n DatadogSignals,\n EstateInsights,\n QueryResult,\n} from '../../api/types';\nimport {\n ImpactPresenter,\n TimelinePresenter,\n} from '../entity/SectionPresenters';\nimport { DatadogOperationsRadar } from './DatadogOperationsRadar';\n\nconst DEFAULT_QUERY =\n 'SELECT * FROM resources WHERE type = deployment LIMIT 10';\n\nexport function isDeterministicSelect(value: string): boolean {\n const sql = value.trim();\n return (\n /^SELECT\\b/i.test(sql) &&\n sql.length <= 4_096 &&\n !sql.includes(';') &&\n !sql.includes('--') &&\n !sql.includes('/*')\n );\n}\n\nexport function matchesCatalogEntity(entity: Entity, value: string): boolean {\n const query = value.trim().toLocaleLowerCase();\n if (!query) return true;\n const searchable = [\n entity.metadata.name,\n entity.metadata.title,\n entity.metadata.description,\n entity.metadata.annotations?.['anyshift.io/target'],\n typeof entity.spec?.owner === 'string' ? entity.spec.owner : undefined,\n ];\n return searchable.some(item => item?.toLocaleLowerCase().includes(query));\n}\n\nexport const EstateInsightsGrid = ({\n insights,\n}: {\n insights: EstateInsights;\n}) => (\n <>\n {insights.sections.map(item => (\n <Grid item xs={12} md={6} key={item.id}>\n <InfoCard title={item.title}>\n {item.section.state === 'error' ? (\n <Typography color=\"error\">{item.section.message}</Typography>\n ) : item.section.state === 'empty' ||\n item.section.state === 'unsupported' ||\n item.section.data === undefined ? (\n <Typography color=\"textSecondary\">\n {item.section.message || 'No insight evidence is available.'}\n </Typography>\n ) : item.id === 'recent-change' ? (\n <TimelinePresenter\n data={item.section.data}\n fallbackLabel=\"Deployment\"\n />\n ) : (\n <ImpactPresenter data={item.section.data} />\n )}\n </InfoCard>\n </Grid>\n ))}\n </>\n);\n\nexport const AnyshiftExplorerPage = () => {\n const api = useApi(anyshiftApiRef);\n const catalogApi = useApi(catalogApiRef);\n const queryPermission = usePermission({\n permission: anyshiftQueryPermission,\n });\n const [queryEnabled, setQueryEnabled] = useState(false);\n const [insights, setInsights] = useState<EstateInsights>();\n const [insightError, setInsightError] = useState<string>();\n const [datadogSignals, setDatadogSignals] = useState<DatadogSignals>();\n const [datadogError, setDatadogError] = useState<string>();\n const [refreshingDatadog, setRefreshingDatadog] = useState(false);\n const [catalogEntities, setCatalogEntities] = useState<Entity[]>([]);\n const [catalogError, setCatalogError] = useState<string>();\n const [catalogQuery, setCatalogQuery] = useState('');\n const [sql, setSql] = useState(DEFAULT_QUERY);\n const [queryResult, setQueryResult] = useState<QueryResult>();\n const [queryError, setQueryError] = useState<string>();\n\n useEffect(() => {\n api\n .capabilities()\n .then(capabilities => setQueryEnabled(capabilities.queryEnabled))\n .catch(() => setQueryEnabled(false));\n }, [api]);\n\n useEffect(() => {\n api\n .datadogSignals()\n .then(setDatadogSignals)\n .catch(error => {\n setDatadogError(error instanceof Error ? error.message : String(error));\n });\n }, [api]);\n\n useEffect(() => {\n api\n .insights()\n .then(setInsights)\n .catch(error => {\n setInsightError(error instanceof Error ? error.message : String(error));\n });\n }, [api]);\n\n useEffect(() => {\n catalogApi\n .getEntities({\n filter: [{ kind: 'Component' }, { kind: 'Resource' }],\n })\n .then(response =>\n setCatalogEntities(\n response.items.filter(\n entity => entity.metadata.annotations?.['anyshift.io/target'],\n ),\n ),\n )\n .catch(error => {\n setCatalogError(error instanceof Error ? error.message : String(error));\n });\n }, [catalogApi]);\n\n const matchingEntities = catalogEntities\n .filter(entity => matchesCatalogEntity(entity, catalogQuery))\n .slice(0, 12);\n\n const runQuery = async () => {\n if (!isDeterministicSelect(sql)) {\n setQueryError('Enter one deterministic SELECT query.');\n return;\n }\n setQueryError(undefined);\n try {\n setQueryResult(await api.query(sql.trim()));\n } catch (error) {\n setQueryError(error instanceof Error ? error.message : String(error));\n }\n };\n\n const refreshDatadog = async () => {\n setRefreshingDatadog(true);\n setDatadogError(undefined);\n try {\n setDatadogSignals(await api.datadogSignals({ refresh: true }));\n } catch (error) {\n setDatadogError(error instanceof Error ? error.message : String(error));\n } finally {\n setRefreshingDatadog(false);\n }\n };\n\n return (\n <Page themeId=\"tool\">\n <Header\n title=\"Anyshift\"\n subtitle=\"Live infrastructure context for your software catalog\"\n />\n <Content>\n {datadogSignals ? (\n <DatadogOperationsRadar\n signals={datadogSignals}\n catalogEntities={catalogEntities}\n onRefresh={refreshDatadog}\n refreshing={refreshingDatadog}\n error={datadogError}\n />\n ) : datadogError ? (\n <Typography color=\"error\">{datadogError}</Typography>\n ) : (\n <Progress />\n )}\n <ContentHeader title=\"Find a service\" />\n <InfoCard subheader=\"Anyshift-annotated Components and Resources in the Backstage catalog\">\n <TextField\n fullWidth\n variant=\"outlined\"\n label=\"Search services and resources\"\n value={catalogQuery}\n onChange={event => setCatalogQuery(event.target.value)}\n />\n {catalogError && (\n <Typography color=\"error\">{catalogError}</Typography>\n )}\n {!catalogError && matchingEntities.length === 0 ? (\n <Typography color=\"textSecondary\" style={{ marginTop: 12 }}>\n No matching Anyshift catalog entities.\n </Typography>\n ) : (\n <ul>\n {matchingEntities.map(entity => (\n <li\n key={`${entity.kind}:${\n entity.metadata.namespace ?? 'default'\n }/${entity.metadata.name}`}\n >\n <EntityRefLink entityRef={entity} />\n {entity.metadata.description\n ? ` - ${entity.metadata.description}`\n : null}\n </li>\n ))}\n </ul>\n )}\n </InfoCard>\n <ContentHeader title=\"Estate insights\" />\n {insightError && <Typography color=\"error\">{insightError}</Typography>}\n {!insights && !insightError ? <Progress /> : null}\n <Grid container spacing={3}>\n {insights && <EstateInsightsGrid insights={insights} />}\n {queryEnabled && queryPermission.allowed && (\n <Grid item xs={12}>\n <InfoCard\n title=\"Advanced query\"\n subheader=\"Deterministic Graph API SELECT queries only\"\n >\n <TextField\n fullWidth\n multiline\n minRows={2}\n variant=\"outlined\"\n value={sql}\n onChange={event => setSql(event.target.value)}\n />\n <Button\n variant=\"contained\"\n color=\"primary\"\n onClick={runQuery}\n style={{ marginTop: 12 }}\n >\n Run query\n </Button>\n {queryError && (\n <Typography color=\"error\">{queryError}</Typography>\n )}\n {queryResult && (\n <pre style={{ whiteSpace: 'pre-wrap', fontSize: 12 }}>\n {JSON.stringify(queryResult, null, 2)}\n </pre>\n )}\n </InfoCard>\n </Grid>\n )}\n </Grid>\n </Content>\n </Page>\n );\n};\n"],"names":[],"mappings":"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"}