From f1fd378f833ccff4ede6bad41f0e32ff00ebc47b Mon Sep 17 00:00:00 2001 From: shats Date: Tue, 7 Apr 2026 23:24:15 +0700 Subject: [PATCH] feat(integration): use EvoBGP router-lists catalog endpoint Load communities, domains, IP ranges, and ASNs from /v1/router-lists/catalog with fallback to legacy per-endpoint reads to keep compatibility during rollout. Made-with: Cursor --- frontend/src/lib/evobgpData.js | 102 +++++++++++++++++++++++++-------- 1 file changed, 77 insertions(+), 25 deletions(-) diff --git a/frontend/src/lib/evobgpData.js b/frontend/src/lib/evobgpData.js index 6829b03..7f4b01b 100644 --- a/frontend/src/lib/evobgpData.js +++ b/frontend/src/lib/evobgpData.js @@ -41,8 +41,24 @@ async function paginate(path, params = {}) { return items; } +async function fetchRouterListsCatalog() { + const res = await evobgpApi.get('/router-lists/catalog'); + return res.data || {}; +} + +function getCatalogItems(section) { + if (!section || typeof section !== 'object') return []; + return Array.isArray(section.items) ? section.items : []; +} + export async function listCommunities() { - const communities = await paginate('/communities'); + let communities = []; + try { + const catalog = await fetchRouterListsCatalog(); + communities = getCatalogItems(catalog.communities); + } catch { + communities = await paginate('/communities'); + } return communities.map((c) => ({ id: c.id, value: String(c.community || ''), @@ -149,14 +165,26 @@ async function syncEntries({ } export async function fetchDomainsData() { - const module = await getOrCreateModule('DOMAINS', 'Domains'); - const { byId } = await buildCommunityMaps(); - const rows = await paginate(`/modules/${module.id}/domain-entries`); - return rows.map((row) => ({ - id: row.id, - domain: String(row.fqdn || '').trim().toLowerCase(), - community: mapCommunityToValue(row.community_id, byId), - })); + try { + const catalog = await fetchRouterListsCatalog(); + const communities = getCatalogItems(catalog.communities); + const byId = new Map(communities.map((c) => [c.id, String(c.community || '')])); + const rows = getCatalogItems(catalog.domains); + return rows.map((row) => ({ + id: row?.entry?.id || row?.id || '', + domain: String(row?.entry?.fqdn || row?.fqdn || '').trim().toLowerCase(), + community: mapCommunityToValue(row?.entry?.community_id || row?.community_id || null, byId), + })).filter((row) => row.domain); + } catch { + const module = await getOrCreateModule('DOMAINS', 'Domains'); + const { byId } = await buildCommunityMaps(); + const rows = await paginate(`/modules/${module.id}/domain-entries`); + return rows.map((row) => ({ + id: row.id, + domain: String(row.fqdn || '').trim().toLowerCase(), + community: mapCommunityToValue(row.community_id, byId), + })); + } } export async function saveDomainsData(currentItems, originalItems) { @@ -173,14 +201,26 @@ export async function saveDomainsData(currentItems, originalItems) { } export async function fetchIpRangesData() { - const module = await getOrCreateModule('IP_RANGES', 'IP ranges'); - const { byId } = await buildCommunityMaps(); - const rows = await paginate(`/modules/${module.id}/ip-range-entries`); - return rows.map((row) => ({ - id: row.id, - ipRange: String(row.prefix || '').trim(), - community: mapCommunityToValue(row.community_id, byId), - })); + try { + const catalog = await fetchRouterListsCatalog(); + const communities = getCatalogItems(catalog.communities); + const byId = new Map(communities.map((c) => [c.id, String(c.community || '')])); + const rows = getCatalogItems(catalog.ip_ranges); + return rows.map((row) => ({ + id: row?.entry?.id || row?.id || '', + ipRange: String(row?.entry?.prefix || row?.prefix || '').trim(), + community: mapCommunityToValue(row?.entry?.community_id || row?.community_id || null, byId), + })).filter((row) => row.ipRange); + } catch { + const module = await getOrCreateModule('IP_RANGES', 'IP ranges'); + const { byId } = await buildCommunityMaps(); + const rows = await paginate(`/modules/${module.id}/ip-range-entries`); + return rows.map((row) => ({ + id: row.id, + ipRange: String(row.prefix || '').trim(), + community: mapCommunityToValue(row.community_id, byId), + })); + } } export async function saveIpRangesData(currentItems, originalItems) { @@ -198,14 +238,26 @@ export async function saveIpRangesData(currentItems, originalItems) { } export async function fetchAsnsData() { - const module = await getOrCreateModule('AS_PREFIXES', 'ASNs'); - const { byId } = await buildCommunityMaps(); - const rows = await paginate(`/modules/${module.id}/as-entries`); - return rows.map((row) => ({ - id: row.id, - asn: String(row.asn || '').trim(), - community: mapCommunityToValue(row.community_id, byId), - })); + try { + const catalog = await fetchRouterListsCatalog(); + const communities = getCatalogItems(catalog.communities); + const byId = new Map(communities.map((c) => [c.id, String(c.community || '')])); + const rows = getCatalogItems(catalog.asns); + return rows.map((row) => ({ + id: row?.entry?.id || row?.id || '', + asn: String(row?.entry?.asn || row?.asn || '').trim(), + community: mapCommunityToValue(row?.entry?.community_id || row?.community_id || null, byId), + })).filter((row) => row.asn); + } catch { + const module = await getOrCreateModule('AS_PREFIXES', 'ASNs'); + const { byId } = await buildCommunityMaps(); + const rows = await paginate(`/modules/${module.id}/as-entries`); + return rows.map((row) => ({ + id: row.id, + asn: String(row.asn || '').trim(), + community: mapCommunityToValue(row.community_id, byId), + })); + } } export async function saveAsnsData(currentItems, originalItems) {