@burdenoff/microfe-adaptercloud 2026.802.1 → 2026.805.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.
@@ -1 +1 @@
1
- {"version":3,"file":"TopologyPage.js","names":[],"sources":["../../../../src/adaptercloud/pages/topology/TopologyPage.tsx"],"sourcesContent":["/**\n * Estate Topology Page\n * @module adaptercloud/pages/topology\n *\n * The estate-wide dependency graph — every discovered resource laid out in one\n * live node-link map, grouped into human \"zones\" (Public Cloud, Kubernetes,\n * Edge / IoT, Data Systems, Network) and wired together by the topology edges\n * (`adaListTopologyEdges`). Selecting a node opens an inspector with its\n * dependency count and downstream blast-radius. All data is live from the\n * deployed `wspace-adaptercloud-svc` subgraph — nodes from `adaListResources`,\n * edges from `adaListTopologyEdges`. No mocks.\n */\n\nimport { useCallback, useMemo, useState } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n Waypoints,\n Search,\n X,\n RefreshCw,\n ArrowRight,\n Layers,\n Boxes,\n GitBranch,\n} from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { DataState } from '../../components/DataState';\nimport { useAdapterCloud } from '../../context/AdapterCloudContext';\nimport { useResources, useTopology } from '../../hooks/useAdapterCloudApi';\nimport { resourceStateLabels, humanizeEnum } from '../../utils/domain';\nimport { TopologyGraph, type TopologyNode, type TopologyEdge } from '../../components/viz';\nimport type { AdaEdgeKind, AdaResourceState } from '../../types';\n\n/** Canonical edge kinds — drives the legend so it stays in sync with the enum. */\nconst EDGE_KINDS: AdaEdgeKind[] = [\n 'DEPENDS_ON',\n 'CONNECTS_TO',\n 'ROUTES_TO',\n 'REPLICATES_TO',\n 'CONTAINS',\n];\n\n/**\n * Derive a human \"zone\" (graph column) for a resource from its type prefix,\n * falling back to the connection name. Data stores route to \"Data Systems\" even\n * when they carry a cloud prefix, matching how operators think about the estate.\n */\nfunction zoneFor(resourceType: string, connectionName?: string | null): string {\n const t = resourceType.toLowerCase();\n\n // Kubernetes clusters/workloads\n if (/^(gke|k8s|kubernetes|eks|aks)\\./.test(t)) return 'Kubernetes';\n // Edge / IoT devices and gateways\n if (/^(iot|edge)\\./.test(t)) return 'Edge / IoT';\n // Data systems — warehouses, databases, object storage\n if (\n /^snowflake\\./.test(t) ||\n /\\.(db|rds|postgres|mysql|redshift|bigquery|dynamodb|s3|bucket|storage)\\b/.test(t) ||\n t.endsWith('.db')\n ) {\n return 'Data Systems';\n }\n // Network fabric — CDNs, VPCs, routers\n if (t.endsWith('.network') || /^cloudflare\\./.test(t) || /\\.(vpc|cdn)\\b/.test(t)) {\n return 'Network';\n }\n // Public cloud compute/etc.\n if (/^(aws|azure|gcp|oci|alicloud)\\./.test(t)) return 'Public Cloud';\n\n // Fallback: infer from the connection name\n const c = (connectionName ?? '').toLowerCase();\n if (c) {\n if (/gke|k8s|kube/.test(c)) return 'Kubernetes';\n if (/iot|edge/.test(c)) return 'Edge / IoT';\n if (/snowflake|warehouse|postgres|database|\\bdb\\b/.test(c)) return 'Data Systems';\n if (/cloudflare|network|vpc|cdn/.test(c)) return 'Network';\n if (/aws|azure|gcp|cloud/.test(c)) return 'Public Cloud';\n }\n return 'Other';\n}\n\nexport function TopologyPage() {\n const { navigateTo } = useAdapterCloud();\n const { t: translate } = useI18n();\n const t = useCallback(\n (key: string, fallback: string): string => {\n const value = translate(key);\n return value === key ? fallback : value;\n },\n [translate]\n );\n\n const resourcesQuery = useResources({ pagination: { limit: 100 } });\n const topologyQuery = useTopology();\n\n const [search, setSearch] = useState('');\n const [kindFilter, setKindFilter] = useState<AdaEdgeKind | ''>('');\n const [selectedId, setSelectedId] = useState<string | null>(null);\n\n const resources = useMemo(() => resourcesQuery.data?.items ?? [], [resourcesQuery.data]);\n const topoEdges = useMemo(() => topologyQuery.data ?? [], [topologyQuery.data]);\n\n // ---- Build the node set from resources -----------------------------------\n const allNodes: TopologyNode[] = useMemo(\n () =>\n resources.map((r) => ({\n id: r.id,\n label: r.name,\n type: r.resourceType,\n state: r.state,\n group: zoneFor(r.resourceType, r.connection?.name),\n })),\n [resources]\n );\n\n const nodeIds = useMemo(() => new Set(allNodes.map((n) => n.id)), [allNodes]);\n const stateById = useMemo(\n () => new Map(resources.map((r) => [r.id, r.state] as const)),\n [resources]\n );\n const nodeById = useMemo(() => new Map(allNodes.map((n) => [n.id, n] as const)), [allNodes]);\n\n // ---- Build edges — only where BOTH endpoints are in the node set ---------\n const allEdges: TopologyEdge[] = useMemo(\n () =>\n topoEdges\n .filter((e) => nodeIds.has(e.fromResourceId) && nodeIds.has(e.toResourceId))\n .map((e) => ({\n id: e.id,\n from: e.fromResourceId,\n to: e.toResourceId,\n kind: e.kind,\n drifted:\n stateById.get(e.fromResourceId) === 'DRIFTED' ||\n stateById.get(e.toResourceId) === 'DRIFTED',\n })),\n [topoEdges, nodeIds, stateById]\n );\n\n // Forward adjacency for inspector metrics (dependencies + blast radius).\n const outAdj = useMemo(() => {\n const adj = new Map<string, string[]>();\n for (const e of allEdges) {\n const list = adj.get(e.from) ?? [];\n list.push(e.to);\n adj.set(e.from, list);\n }\n return adj;\n }, [allEdges]);\n\n // ---- Search + edge-kind filtering (what the graph actually renders) ------\n const q = search.trim().toLowerCase();\n const displayNodes = useMemo(() => {\n if (!q) return allNodes;\n return allNodes.filter(\n (n) => n.label.toLowerCase().includes(q) || (n.type ?? '').toLowerCase().includes(q)\n );\n }, [allNodes, q]);\n\n const displayNodeIds = useMemo(() => new Set(displayNodes.map((n) => n.id)), [displayNodes]);\n\n const displayEdges = useMemo(\n () =>\n allEdges.filter(\n (e) =>\n displayNodeIds.has(e.from) &&\n displayNodeIds.has(e.to) &&\n (kindFilter === '' || e.kind === kindFilter)\n ),\n [allEdges, displayNodeIds, kindFilter]\n );\n\n // Count edges by kind for the legend badges.\n const kindCounts = useMemo(() => {\n const counts: Record<string, number> = {};\n for (const e of allEdges) counts[e.kind ?? ''] = (counts[e.kind ?? ''] ?? 0) + 1;\n return counts;\n }, [allEdges]);\n\n // ---- Inspector metrics for the selected node -----------------------------\n const inspector = useMemo(() => {\n if (!selectedId) return null;\n const node = nodeById.get(selectedId);\n if (!node) return null;\n\n const dependencies = outAdj.get(selectedId)?.length ?? 0;\n\n // Blast radius = every resource transitively reachable downstream.\n const seen = new Set<string>();\n const stack = [...(outAdj.get(selectedId) ?? [])];\n while (stack.length) {\n const cur = stack.pop();\n if (cur === undefined || cur === selectedId || seen.has(cur)) continue;\n seen.add(cur);\n for (const next of outAdj.get(cur) ?? []) stack.push(next);\n }\n\n return { node, dependencies, blastRadius: seen.size };\n }, [selectedId, nodeById, outAdj]);\n\n const zoneCount = useMemo(() => new Set(allNodes.map((n) => n.group)).size, [allNodes]);\n\n const onSelect = useCallback((id: string) => {\n setSelectedId((prev) => (prev === id ? null : id));\n }, []);\n\n const isLoading = resourcesQuery.isLoading || topologyQuery.isLoading;\n const isError = resourcesQuery.isError || topologyQuery.isError;\n\n const refetchAll = useCallback(() => {\n void resourcesQuery.refetch();\n void topologyQuery.refetch();\n }, [resourcesQuery, topologyQuery]);\n\n return (\n <PageLayout\n title={t('adaptercloud.topology.title', 'Estate Topology')}\n description={t(\n 'adaptercloud.topology.subtitle',\n 'A live dependency map of your entire infrastructure — every system in one graph.'\n )}\n actions={\n <button\n type=\"button\"\n onClick={refetchAll}\n className=\"inline-flex items-center gap-2 rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-accent\"\n >\n <RefreshCw className=\"h-4 w-4\" />\n {t('adaptercloud.common.refresh', 'Refresh')}\n </button>\n }\n >\n {/* Toolbar — search + edge-kind filter + estate counts */}\n <div className=\"mb-6 flex flex-wrap items-center gap-3\">\n <div className=\"relative w-full sm:w-64\">\n <Search className=\"pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-secondary\" />\n <input\n type=\"text\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n aria-label={t('adaptercloud.topology.searchNodes', 'Search nodes')}\n placeholder={t('adaptercloud.topology.searchPlaceholder', 'Search nodes…')}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface py-2 pl-9 pr-9 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n {search && (\n <button\n type=\"button\"\n onClick={() => setSearch('')}\n aria-label={t('adaptercloud.topology.clearSearch', 'Clear search')}\n className=\"absolute right-2 top-1/2 -translate-y-1/2 rounded p-0.5 text-text-secondary transition-colors hover:text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n )}\n </div>\n\n <select\n value={kindFilter}\n onChange={(e) => setKindFilter(e.target.value as AdaEdgeKind | '')}\n aria-label={t('adaptercloud.topology.filterByKind', 'Filter by edge kind')}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] sm:w-auto\"\n >\n <option value=\"\">{t('adaptercloud.topology.allKinds', 'All edge kinds')}</option>\n {EDGE_KINDS.map((k) => (\n <option key={k} value={k}>\n {humanizeEnum(k)}\n </option>\n ))}\n </select>\n\n {!isLoading && !isError && allNodes.length > 0 && (\n <div className=\"ml-auto flex flex-wrap items-center gap-4 text-xs text-text-secondary\">\n <span className=\"inline-flex items-center gap-1.5\">\n <Boxes className=\"h-3.5 w-3.5\" />\n <span className=\"tabular-nums font-medium text-text-primary\">\n {allNodes.length}\n </span>{' '}\n {t('adaptercloud.topology.nodes', 'nodes')}\n </span>\n <span className=\"inline-flex items-center gap-1.5\">\n <GitBranch className=\"h-3.5 w-3.5\" />\n <span className=\"tabular-nums font-medium text-text-primary\">\n {allEdges.length}\n </span>{' '}\n {t('adaptercloud.topology.edges', 'edges')}\n </span>\n <span className=\"inline-flex items-center gap-1.5\">\n <Layers className=\"h-3.5 w-3.5\" />\n <span className=\"tabular-nums font-medium text-text-primary\">{zoneCount}</span>{' '}\n {t('adaptercloud.topology.zones', 'zones')}\n </span>\n </div>\n )}\n </div>\n\n <DataState\n isLoading={isLoading}\n isError={isError}\n isEmpty={allNodes.length === 0}\n error={resourcesQuery.error ?? topologyQuery.error}\n onRetry={refetchAll}\n emptyTitle={t('adaptercloud.topology.emptyTitle', 'No topology yet')}\n emptyDescription={t(\n 'adaptercloud.topology.emptyDescription',\n 'No topology yet — register resources and their dependencies to see them mapped here.'\n )}\n emptyIcon={<Waypoints className=\"h-10 w-10\" />}\n emptyAction={\n <button\n type=\"button\"\n onClick={() => navigateTo('/resources')}\n className=\"rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:opacity-90\"\n >\n {t('adaptercloud.topology.goToResources', 'Go to resources')}\n </button>\n }\n >\n <div className=\"grid gap-6 lg:grid-cols-[minmax(0,1fr)_20rem]\">\n {/* Graph + legend */}\n <div className=\"min-w-0 space-y-4\">\n {allEdges.length === 0 && (\n <p className=\"rounded-lg border border-border-subtle bg-bg-sunken/50 px-4 py-3 text-sm text-text-secondary\">\n {t(\n 'adaptercloud.topology.noEdges',\n 'No dependency edges recorded yet — nodes are shown grouped by zone. Add dependencies from a resource to connect the graph.'\n )}\n </p>\n )}\n\n {displayNodes.length > 0 ? (\n <TopologyGraph\n nodes={displayNodes}\n edges={displayEdges}\n selectedId={selectedId}\n onSelect={onSelect}\n />\n ) : (\n <div className=\"flex min-h-[200px] flex-col items-center justify-center gap-2 rounded-xl border border-border-subtle bg-bg-surface p-8 text-center\">\n <Search className=\"h-8 w-8 text-text-secondary\" />\n <p className=\"text-sm text-text-secondary\">\n {t('adaptercloud.topology.noMatches', 'No nodes match your search.')}\n </p>\n </div>\n )}\n\n {/* Edge-kinds legend */}\n <GlassCard className=\"p-4\">\n <h3 className=\"mb-3 text-sm font-semibold text-text-primary\">\n {t('adaptercloud.topology.legend', 'Legend')}\n </h3>\n <div className=\"grid gap-4 sm:grid-cols-2\">\n {/* Edge signals (how the graph paints edges) */}\n <div>\n <p className=\"mb-2 text-xs font-medium uppercase tracking-wide text-text-secondary\">\n {t('adaptercloud.topology.edgeSignals', 'Edge signals')}\n </p>\n <ul className=\"space-y-1.5 text-xs text-text-secondary\">\n <li className=\"flex items-center gap-2\">\n <span className=\"h-0.5 w-6 shrink-0 rounded bg-border-strong\" aria-hidden />\n {t('adaptercloud.topology.dependency', 'Dependency')}\n </li>\n <li className=\"flex items-center gap-2\">\n <span className=\"h-0.5 w-6 shrink-0 rounded bg-accent-blue\" aria-hidden />\n {t('adaptercloud.topology.selectedPath', 'Selected node path')}\n </li>\n <li className=\"flex items-center gap-2\">\n <span\n className=\"h-0.5 w-6 shrink-0 rounded bg-status-warning-text\"\n aria-hidden\n />\n {t('adaptercloud.topology.drift', 'Drift (endpoint drifted)')}\n </li>\n </ul>\n </div>\n\n {/* Edge kinds (semantic relationship types) */}\n <div>\n <p className=\"mb-2 text-xs font-medium uppercase tracking-wide text-text-secondary\">\n {t('adaptercloud.topology.edgeKinds', 'Edge kinds')}\n </p>\n <ul className=\"flex flex-wrap gap-1.5\">\n {EDGE_KINDS.map((k) => (\n <li key={k}>\n <span className=\"inline-flex items-center gap-1.5 rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs text-text-secondary\">\n {humanizeEnum(k)}\n <span className=\"tabular-nums font-medium text-text-primary\">\n {kindCounts[k] ?? 0}\n </span>\n </span>\n </li>\n ))}\n </ul>\n </div>\n </div>\n </GlassCard>\n </div>\n\n {/* Inspector */}\n <aside className=\"lg:sticky lg:top-6 lg:h-fit\">\n <GlassCard className=\"p-5\">\n {inspector ? (\n <div className=\"space-y-5\">\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"flex min-w-0 items-center gap-2.5\">\n <span className=\"flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-bg-sunken\">\n <Waypoints className=\"h-4.5 w-4.5 text-accent-blue\" />\n </span>\n <div className=\"min-w-0\">\n <h3 className=\"truncate text-base font-semibold text-text-primary\">\n {inspector.node.label}\n </h3>\n <p className=\"text-xs text-text-secondary\">\n {t('adaptercloud.topology.inspector', 'Inspector')}\n </p>\n </div>\n </div>\n <button\n type=\"button\"\n onClick={() => setSelectedId(null)}\n aria-label={t('adaptercloud.topology.closeInspector', 'Close inspector')}\n className=\"rounded p-1 text-text-secondary transition-colors hover:bg-accent hover:text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n </div>\n\n <dl className=\"space-y-3 text-sm\">\n <div className=\"flex items-center justify-between gap-3\">\n <dt className=\"text-text-secondary\">\n {t('adaptercloud.topology.type', 'Type')}\n </dt>\n <dd className=\"truncate font-mono text-xs text-text-primary\">\n {inspector.node.type ?? '—'}\n </dd>\n </div>\n <div className=\"flex items-center justify-between gap-3\">\n <dt className=\"text-text-secondary\">\n {t('adaptercloud.topology.zone', 'Zone')}\n </dt>\n <dd className=\"text-text-primary\">{inspector.node.group}</dd>\n </div>\n <div className=\"flex items-center justify-between gap-3\">\n <dt className=\"text-text-secondary\">\n {t('adaptercloud.topology.state', 'State')}\n </dt>\n <dd>\n <StatusBadge\n status={inspector.node.state ?? ''}\n label={\n inspector.node.state\n ? resourceStateLabels[inspector.node.state as AdaResourceState]\n : undefined\n }\n />\n </dd>\n </div>\n </dl>\n\n <div className=\"grid grid-cols-2 gap-3\">\n <div className=\"rounded-lg border border-border-subtle bg-bg-sunken/50 p-3\">\n <p className=\"text-2xl font-bold tabular-nums text-text-primary\">\n {inspector.dependencies}\n </p>\n <p className=\"mt-0.5 text-xs text-text-secondary\">\n {t('adaptercloud.topology.dependencies', 'Dependencies')}\n </p>\n </div>\n <div className=\"rounded-lg border border-border-subtle bg-bg-sunken/50 p-3\">\n <p className=\"text-2xl font-bold tabular-nums text-text-primary\">\n {inspector.blastRadius}\n </p>\n <p className=\"mt-0.5 text-xs text-text-secondary\">\n {t('adaptercloud.topology.blastRadius', 'Blast radius')}\n </p>\n </div>\n </div>\n\n <button\n type=\"button\"\n onClick={() => navigateTo(`/resources/${inspector.node.id}`)}\n className=\"inline-flex w-full items-center justify-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:opacity-90\"\n >\n {t('adaptercloud.topology.viewResource', 'View resource')}\n <ArrowRight className=\"h-4 w-4\" />\n </button>\n </div>\n ) : (\n <div className=\"flex flex-col items-center gap-3 py-8 text-center\">\n <span className=\"flex h-11 w-11 items-center justify-center rounded-full bg-bg-sunken\">\n <Waypoints className=\"h-5 w-5 text-text-secondary\" />\n </span>\n <p className=\"text-sm font-medium text-text-primary\">\n {t('adaptercloud.topology.inspectorTitle', 'Inspector')}\n </p>\n <p className=\"max-w-[16rem] text-xs text-text-secondary\">\n {t(\n 'adaptercloud.topology.inspectorHint',\n 'Select any node in the graph to see its type, state, dependencies and downstream blast radius.'\n )}\n </p>\n </div>\n )}\n </GlassCard>\n </aside>\n </div>\n </DataState>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"TopologyPage.js","names":[],"sources":["../../../../src/adaptercloud/pages/topology/TopologyPage.tsx"],"sourcesContent":["/**\n * Estate Topology Page\n * @module adaptercloud/pages/topology\n *\n * The estate-wide dependency graph — every discovered resource laid out in one\n * live node-link map, grouped into human \"zones\" (Public Cloud, Kubernetes,\n * Edge / IoT, Data Systems, Network) and wired together by the topology edges\n * (`adaListTopologyEdges`). Selecting a node opens an inspector with its\n * dependency count and downstream blast-radius. All data is live from the\n * deployed `wspace-adaptercloud-svc` subgraph — nodes from `adaListResources`,\n * edges from `adaListTopologyEdges`. No mocks.\n */\n\nimport { useCallback, useMemo, useState } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n Waypoints,\n Search,\n X,\n RefreshCw,\n ArrowRight,\n Layers,\n Boxes,\n GitBranch,\n} from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { DataState } from '../../components/DataState';\nimport { useAdapterCloud } from '../../context/AdapterCloudContext';\nimport { useResources, useTopology } from '../../hooks/useAdapterCloudApi';\nimport { resourceStateLabels, humanizeEnum } from '../../utils/domain';\nimport { TopologyGraph, type TopologyNode, type TopologyEdge } from '../../components/viz';\nimport type { AdaEdgeKind, AdaResourceState } from '../../types';\n\n/** Canonical edge kinds — drives the legend so it stays in sync with the enum. */\nconst EDGE_KINDS: AdaEdgeKind[] = [\n 'DEPENDS_ON',\n 'CONNECTS_TO',\n 'ROUTES_TO',\n 'REPLICATES_TO',\n 'CONTAINS',\n];\n\n/**\n * Derive a human \"zone\" (graph column) for a resource from its type prefix,\n * falling back to the connection name. Data stores route to \"Data Systems\" even\n * when they carry a cloud prefix, matching how operators think about the estate.\n */\nfunction zoneFor(resourceType: string, connectionName?: string | null): string {\n const t = resourceType.toLowerCase();\n\n // Kubernetes clusters/workloads\n if (/^(gke|k8s|kubernetes|eks|aks)\\./.test(t)) return 'Kubernetes';\n // Edge / IoT devices and gateways\n if (/^(iot|edge)\\./.test(t)) return 'Edge / IoT';\n // Data systems — warehouses, databases, object storage\n if (\n /^snowflake\\./.test(t) ||\n /\\.(db|rds|postgres|mysql|redshift|bigquery|dynamodb|s3|bucket|storage)\\b/.test(t) ||\n t.endsWith('.db')\n ) {\n return 'Data Systems';\n }\n // Network fabric — CDNs, VPCs, routers\n if (t.endsWith('.network') || /^cloudflare\\./.test(t) || /\\.(vpc|cdn)\\b/.test(t)) {\n return 'Network';\n }\n // Public cloud compute/etc.\n if (/^(aws|azure|gcp|oci|alicloud)\\./.test(t)) return 'Public Cloud';\n\n // Fallback: infer from the connection name\n const c = (connectionName ?? '').toLowerCase();\n if (c) {\n if (/gke|k8s|kube/.test(c)) return 'Kubernetes';\n if (/iot|edge/.test(c)) return 'Edge / IoT';\n if (/snowflake|warehouse|postgres|database|\\bdb\\b/.test(c)) return 'Data Systems';\n if (/cloudflare|network|vpc|cdn/.test(c)) return 'Network';\n if (/aws|azure|gcp|cloud/.test(c)) return 'Public Cloud';\n }\n return 'Other';\n}\n\nexport function TopologyPage() {\n const { navigateTo } = useAdapterCloud();\n const { t: translate } = useI18n();\n const t = useCallback(\n (key: string, fallback: string): string => {\n const value = translate(key);\n return value === key ? fallback : value;\n },\n [translate]\n );\n\n const resourcesQuery = useResources({ pagination: { limit: 100 } });\n const topologyQuery = useTopology();\n\n const [search, setSearch] = useState('');\n const [kindFilter, setKindFilter] = useState<AdaEdgeKind | ''>('');\n const [selectedId, setSelectedId] = useState<string | null>(null);\n\n const resources = useMemo(() => resourcesQuery.data?.items ?? [], [resourcesQuery.data]);\n const topoEdges = useMemo(() => topologyQuery.data ?? [], [topologyQuery.data]);\n\n // ---- Build the node set from resources -----------------------------------\n const allNodes: TopologyNode[] = useMemo(\n () =>\n resources.map((r) => ({\n id: r.id,\n label: r.name,\n type: r.resourceType,\n state: r.state,\n group: zoneFor(r.resourceType, r.connection?.name),\n })),\n [resources]\n );\n\n const nodeIds = useMemo(() => new Set(allNodes.map((n) => n.id)), [allNodes]);\n const stateById = useMemo(\n () => new Map(resources.map((r) => [r.id, r.state] as const)),\n [resources]\n );\n const nodeById = useMemo(() => new Map(allNodes.map((n) => [n.id, n] as const)), [allNodes]);\n\n // ---- Build edges — only where BOTH endpoints are in the node set ---------\n const allEdges: TopologyEdge[] = useMemo(\n () =>\n topoEdges\n .filter((e) => nodeIds.has(e.fromResourceId) && nodeIds.has(e.toResourceId))\n .map((e) => ({\n id: e.id,\n from: e.fromResourceId,\n to: e.toResourceId,\n kind: e.kind,\n drifted:\n stateById.get(e.fromResourceId) === 'DRIFTED' ||\n stateById.get(e.toResourceId) === 'DRIFTED',\n })),\n [topoEdges, nodeIds, stateById]\n );\n\n // Forward adjacency for inspector metrics (dependencies + blast radius).\n const outAdj = useMemo(() => {\n const adj = new Map<string, string[]>();\n for (const e of allEdges) {\n const list = adj.get(e.from) ?? [];\n list.push(e.to);\n adj.set(e.from, list);\n }\n return adj;\n }, [allEdges]);\n\n // ---- Search + edge-kind filtering (what the graph actually renders) ------\n const q = search.trim().toLowerCase();\n const displayNodes = useMemo(() => {\n if (!q) return allNodes;\n return allNodes.filter(\n (n) => n.label.toLowerCase().includes(q) || (n.type ?? '').toLowerCase().includes(q)\n );\n }, [allNodes, q]);\n\n const displayNodeIds = useMemo(() => new Set(displayNodes.map((n) => n.id)), [displayNodes]);\n\n const displayEdges = useMemo(\n () =>\n allEdges.filter(\n (e) =>\n displayNodeIds.has(e.from) &&\n displayNodeIds.has(e.to) &&\n (kindFilter === '' || e.kind === kindFilter)\n ),\n [allEdges, displayNodeIds, kindFilter]\n );\n\n // Count edges by kind for the legend badges.\n const kindCounts = useMemo(() => {\n const counts: Record<string, number> = {};\n for (const e of allEdges) counts[e.kind ?? ''] = (counts[e.kind ?? ''] ?? 0) + 1;\n return counts;\n }, [allEdges]);\n\n // ---- Inspector metrics for the selected node -----------------------------\n const inspector = useMemo(() => {\n if (!selectedId) return null;\n const node = nodeById.get(selectedId);\n if (!node) return null;\n\n const dependencies = outAdj.get(selectedId)?.length ?? 0;\n\n // Blast radius = every resource transitively reachable downstream.\n const seen = new Set<string>();\n const stack = [...(outAdj.get(selectedId) ?? [])];\n while (stack.length) {\n const cur = stack.pop();\n if (cur === undefined || cur === selectedId || seen.has(cur)) continue;\n seen.add(cur);\n for (const next of outAdj.get(cur) ?? []) stack.push(next);\n }\n\n return { node, dependencies, blastRadius: seen.size };\n }, [selectedId, nodeById, outAdj]);\n\n const zoneCount = useMemo(() => new Set(allNodes.map((n) => n.group)).size, [allNodes]);\n\n const onSelect = useCallback((id: string) => {\n setSelectedId((prev) => (prev === id ? null : id));\n }, []);\n\n const isLoading = resourcesQuery.isLoading || topologyQuery.isLoading;\n const isError = resourcesQuery.isError || topologyQuery.isError;\n\n const refetchAll = useCallback(() => {\n void resourcesQuery.refetch();\n void topologyQuery.refetch();\n }, [resourcesQuery, topologyQuery]);\n\n return (\n <PageLayout\n title={t('adaptercloud.topology.title', 'Estate Topology')}\n description={t(\n 'adaptercloud.topology.subtitle',\n 'A live dependency map of your entire infrastructure — every system in one graph.'\n )}\n actions={\n <button\n type=\"button\"\n onClick={refetchAll}\n className=\"inline-flex items-center gap-2 rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-accent\"\n >\n <RefreshCw className=\"h-4 w-4\" />\n {t('adaptercloud.common.refresh', 'Refresh')}\n </button>\n }\n >\n {/* Toolbar — search + edge-kind filter + estate counts */}\n <div className=\"mb-6 flex flex-wrap items-center gap-3\">\n <div className=\"relative w-full sm:w-64\">\n <Search className=\"pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-secondary\" />\n <input\n type=\"text\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n aria-label={t('adaptercloud.topology.searchNodes', 'Search nodes')}\n placeholder={t('adaptercloud.topology.searchPlaceholder', 'Search nodes…')}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface py-2 pl-9 pr-9 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n {search && (\n <button\n type=\"button\"\n onClick={() => setSearch('')}\n aria-label={t('adaptercloud.topology.clearSearch', 'Clear search')}\n className=\"absolute right-2 top-1/2 -translate-y-1/2 rounded p-0.5 text-text-secondary transition-colors hover:text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n )}\n </div>\n\n <select\n value={kindFilter}\n onChange={(e) => setKindFilter(e.target.value as AdaEdgeKind | '')}\n aria-label={t('adaptercloud.topology.filterByKind', 'Filter by edge kind')}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] sm:w-auto\"\n >\n <option value=\"\">{t('adaptercloud.topology.allKinds', 'All edge kinds')}</option>\n {EDGE_KINDS.map((k) => (\n <option key={k} value={k}>\n {humanizeEnum(k)}\n </option>\n ))}\n </select>\n\n {!isLoading && !isError && allNodes.length > 0 && (\n <div className=\"ml-auto flex flex-wrap items-center gap-4 text-xs text-text-secondary\">\n <span className=\"inline-flex items-center gap-1.5\">\n <Boxes className=\"h-3.5 w-3.5\" />\n <span className=\"tabular-nums font-medium text-text-primary\">\n {allNodes.length}\n </span>{' '}\n {t('adaptercloud.topology.nodes', 'nodes')}\n </span>\n <span className=\"inline-flex items-center gap-1.5\">\n <GitBranch className=\"h-3.5 w-3.5\" />\n <span className=\"tabular-nums font-medium text-text-primary\">\n {allEdges.length}\n </span>{' '}\n {t('adaptercloud.topology.edges', 'edges')}\n </span>\n <span className=\"inline-flex items-center gap-1.5\">\n <Layers className=\"h-3.5 w-3.5\" />\n <span className=\"tabular-nums font-medium text-text-primary\">{zoneCount}</span>{' '}\n {t('adaptercloud.topology.zones', 'zones')}\n </span>\n </div>\n )}\n </div>\n\n <DataState\n isLoading={isLoading}\n isError={isError}\n isEmpty={allNodes.length === 0}\n error={resourcesQuery.error ?? topologyQuery.error}\n onRetry={refetchAll}\n emptyTitle={t('adaptercloud.topology.emptyTitle', 'No topology yet')}\n emptyDescription={t(\n 'adaptercloud.topology.emptyDescription',\n 'No topology yet — register resources and their dependencies to see them mapped here.'\n )}\n emptyIcon={<Waypoints className=\"h-10 w-10\" />}\n emptyAction={\n <button\n type=\"button\"\n onClick={() => navigateTo('/resources')}\n className=\"rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:opacity-90\"\n >\n {t('adaptercloud.topology.goToResources', 'Go to resources')}\n </button>\n }\n >\n <div className=\"grid gap-6 lg:grid-cols-[minmax(0,1fr)_20rem]\">\n {/* Graph + legend */}\n <div className=\"min-w-0 space-y-4\">\n {allEdges.length === 0 && (\n <p className=\"rounded-lg border border-border-subtle bg-bg-sunken/50 px-4 py-3 text-sm text-text-secondary\">\n {t(\n 'adaptercloud.topology.noEdges',\n 'No dependency edges recorded yet — nodes are shown grouped by zone. Add dependencies from a resource to connect the graph.'\n )}\n </p>\n )}\n\n {displayNodes.length > 0 ? (\n <TopologyGraph\n nodes={displayNodes}\n edges={displayEdges}\n selectedId={selectedId}\n onSelect={onSelect}\n />\n ) : (\n <div className=\"flex min-h-[200px] flex-col items-center justify-center gap-2 rounded-xl border border-border-subtle bg-bg-surface p-8 text-center\">\n <Search className=\"h-8 w-8 text-text-secondary\" />\n <p className=\"text-sm text-text-secondary\">\n {t('adaptercloud.topology.noMatches', 'No nodes match your search.')}\n </p>\n </div>\n )}\n\n {/* Edge-kinds legend */}\n <GlassCard className=\"p-4\">\n <h3 className=\"mb-3 text-sm font-semibold text-text-primary\">\n {t('adaptercloud.topology.legend', 'Legend')}\n </h3>\n <div className=\"grid gap-4 sm:grid-cols-2\">\n {/* Edge signals (how the graph paints edges) */}\n <div>\n <p className=\"mb-2 text-xs font-medium uppercase tracking-wide text-text-secondary\">\n {t('adaptercloud.topology.edgeSignals', 'Edge signals')}\n </p>\n <ul className=\"space-y-1.5 text-xs text-text-secondary\">\n <li className=\"flex items-center gap-2\">\n <span className=\"h-0.5 w-6 shrink-0 rounded bg-border-strong\" aria-hidden />\n {t('adaptercloud.topology.dependency', 'Dependency')}\n </li>\n <li className=\"flex items-center gap-2\">\n <span className=\"h-0.5 w-6 shrink-0 rounded bg-accent-blue\" aria-hidden />\n {t('adaptercloud.topology.selectedPath', 'Selected node path')}\n </li>\n <li className=\"flex items-center gap-2\">\n <span\n className=\"h-0.5 w-6 shrink-0 rounded bg-status-warning-text\"\n aria-hidden\n />\n {t('adaptercloud.topology.drift', 'Drift (endpoint drifted)')}\n </li>\n </ul>\n </div>\n\n {/* Edge kinds (semantic relationship types) */}\n <div>\n <p className=\"mb-2 text-xs font-medium uppercase tracking-wide text-text-secondary\">\n {t('adaptercloud.topology.edgeKinds', 'Edge kinds')}\n </p>\n <ul className=\"flex flex-wrap gap-1.5\">\n {EDGE_KINDS.map((k) => (\n <li key={k}>\n <span className=\"inline-flex items-center gap-1.5 rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs text-text-secondary\">\n {humanizeEnum(k)}\n <span className=\"tabular-nums font-medium text-text-primary\">\n {kindCounts[k] ?? 0}\n </span>\n </span>\n </li>\n ))}\n </ul>\n </div>\n </div>\n </GlassCard>\n </div>\n\n {/* Inspector */}\n <aside className=\"lg:sticky lg:top-6 lg:h-fit\">\n <GlassCard className=\"p-5\">\n {inspector ? (\n <div className=\"space-y-5\">\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"flex min-w-0 items-center gap-2.5\">\n <span className=\"flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-bg-sunken\">\n <Waypoints className=\"h-4.5 w-4.5 text-accent-blue\" />\n </span>\n <div className=\"min-w-0\">\n <h3 className=\"truncate text-base font-semibold text-text-primary\">\n {inspector.node.label}\n </h3>\n <p className=\"text-xs text-text-secondary\">\n {t('adaptercloud.topology.inspector', 'Inspector')}\n </p>\n </div>\n </div>\n <button\n type=\"button\"\n onClick={() => setSelectedId(null)}\n aria-label={t('adaptercloud.topology.closeInspector', 'Close inspector')}\n className=\"rounded p-1 text-text-secondary transition-colors hover:bg-accent hover:text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n </div>\n\n <dl className=\"space-y-3 text-sm\">\n <div className=\"flex items-center justify-between gap-3\">\n <dt className=\"text-text-secondary\">\n {t('adaptercloud.topology.type', 'Type')}\n </dt>\n <dd className=\"truncate font-mono text-xs text-text-primary\">\n {inspector.node.type ?? '—'}\n </dd>\n </div>\n <div className=\"flex items-center justify-between gap-3\">\n <dt className=\"text-text-secondary\">\n {t('adaptercloud.topology.zone', 'Zone')}\n </dt>\n <dd className=\"text-text-primary\">{inspector.node.group}</dd>\n </div>\n <div className=\"flex items-center justify-between gap-3\">\n <dt className=\"text-text-secondary\">\n {t('adaptercloud.topology.state', 'State')}\n </dt>\n <dd>\n <StatusBadge\n status={inspector.node.state ?? ''}\n label={\n inspector.node.state\n ? resourceStateLabels[inspector.node.state as AdaResourceState]\n : undefined\n }\n />\n </dd>\n </div>\n </dl>\n\n <div className=\"grid grid-cols-2 gap-3\">\n <div className=\"rounded-lg border border-border-subtle bg-bg-sunken/50 p-3\">\n <p className=\"text-2xl font-bold tabular-nums text-text-primary\">\n {inspector.dependencies}\n </p>\n <p className=\"mt-0.5 text-xs text-text-secondary\">\n {t('adaptercloud.topology.dependencies', 'Dependencies')}\n </p>\n </div>\n <div className=\"rounded-lg border border-border-subtle bg-bg-sunken/50 p-3\">\n <p className=\"text-2xl font-bold tabular-nums text-text-primary\">\n {inspector.blastRadius}\n </p>\n <p className=\"mt-0.5 text-xs text-text-secondary\">\n {t('adaptercloud.topology.blastRadius', 'Blast radius')}\n </p>\n </div>\n </div>\n\n <button\n type=\"button\"\n onClick={() => navigateTo(`/resources/${inspector.node.id}`)}\n className=\"inline-flex w-full items-center justify-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-colors hover:opacity-90\"\n >\n {t('adaptercloud.topology.viewResource', 'View resource')}\n <ArrowRight className=\"h-4 w-4\" />\n </button>\n </div>\n ) : (\n <div className=\"flex flex-col items-center gap-3 py-8 text-center\">\n <span className=\"flex h-11 w-11 items-center justify-center rounded-full bg-bg-sunken\">\n <Waypoints className=\"h-5 w-5 text-text-secondary\" />\n </span>\n <p className=\"text-sm font-medium text-text-primary\">\n {t('adaptercloud.topology.inspectorTitle', 'Inspector')}\n </p>\n <p className=\"max-w-[16rem] text-xs text-text-secondary\">\n {t(\n 'adaptercloud.topology.inspectorHint',\n 'Select any node in the graph to see its type, state, dependencies and downstream blast radius.'\n )}\n </p>\n </div>\n )}\n </GlassCard>\n </aside>\n </div>\n </DataState>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/microfe-adaptercloud",
3
- "version": "2026.802.1",
3
+ "version": "2026.805.1",
4
4
  "description": "Burdenoff AdapterCloud Microfrontend",
5
5
  "type": "module",
6
6
  "files": [
@@ -99,7 +99,7 @@
99
99
  "zustand": "^5.0.0"
100
100
  },
101
101
  "publishConfig": {
102
- "access": "restricted"
102
+ "access": "public"
103
103
  },
104
104
  "overrides": {
105
105
  "@burdenoff/fe-libs": "2026.801.1",