@burdenoff/microfe-adaptercloud 2026.825.1 → 2026.825.3

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.
@@ -104,6 +104,7 @@ export interface CostRecordListFilter {
104
104
  resourceId?: string;
105
105
  service?: string;
106
106
  }
107
+ export declare const LIST_COST_RECORDS_QUERY = "query AdaListCostRecords($connectionId: ID, $resourceId: ID, $service: String, $pagination: PaginationInput) {\n adaListCostRecords(connectionId: $connectionId, resourceId: $resourceId, service: $service, pagination: $pagination) {\n items {\n id service amount currency periodStart periodEnd breakdown\n connectionId resourceId workspaceId createdAt updatedAt\n resource { id name }\n connection { id name }\n }\n pageInfo { cursor hasMore totalCount }\n }\n}";
107
108
  export declare const useCostRecords: (filter?: CostRecordListFilter) => import('@tanstack/react-query').UseQueryResult<NoInfer<AdaCostRecord[]>, Error>;
108
109
  export interface TopologyFilter {
109
110
  resourceId?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"useAdapterCloudApi.d.ts","sourceRoot":"","sources":["../../../src/adaptercloud/hooks/useAdapterCloudApi.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useAdapterCloudApi.d.ts","sourceRoot":"","sources":["../../../src/adaptercloud/hooks/useAdapterCloudApi.ts"],"names":[],"mappings":"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"}
@@ -447,18 +447,39 @@ var s = {
447
447
  queryFn: async () => (await c("query AdaCostSummary($connectionId: ID) {\n adaCostSummary(connectionId: $connectionId) {\n currency total\n lines { service total }\n }\n }", { connectionId: t }, n)).adaCostSummary,
448
448
  staleTime: l
449
449
  });
450
- }, W = (t = {}) => {
450
+ }, W = `query AdaListCostRecords($connectionId: ID, $resourceId: ID, $service: String, $pagination: PaginationInput) {
451
+ adaListCostRecords(connectionId: $connectionId, resourceId: $resourceId, service: $service, pagination: $pagination) {
452
+ items {
453
+ id service amount currency periodStart periodEnd breakdown
454
+ connectionId resourceId workspaceId createdAt updatedAt
455
+ resource { id name }
456
+ connection { id name }
457
+ }
458
+ pageInfo { ${_} }
459
+ }
460
+ }`, G = (t = {}) => {
451
461
  let { apiGatewayUrl: n } = e();
452
462
  return r({
453
463
  queryKey: s.costRecords(t),
454
- queryFn: async () => (await c("query AdaListCostRecords($connectionId: ID, $resourceId: ID, $service: String) {\n adaListCostRecords(connectionId: $connectionId, resourceId: $resourceId, service: $service) {\n id service amount currency periodStart periodEnd breakdown\n connectionId resourceId workspaceId createdAt updatedAt\n resource { id name }\n connection { id name }\n }\n }", {
455
- connectionId: t.connectionId,
456
- resourceId: t.resourceId,
457
- service: t.service
458
- }, n)).adaListCostRecords,
464
+ queryFn: async () => {
465
+ let e = [], r = 0;
466
+ for (;;) {
467
+ let i = (await c(W, {
468
+ connectionId: t.connectionId,
469
+ resourceId: t.resourceId,
470
+ service: t.service,
471
+ pagination: {
472
+ limit: 100,
473
+ offset: r
474
+ }
475
+ }, n)).adaListCostRecords;
476
+ if (e.push(...i.items), !i.pageInfo.hasMore || i.items.length === 0) return e;
477
+ r += i.items.length;
478
+ }
479
+ },
459
480
  staleTime: l
460
481
  });
461
- }, G = 100, K = () => {
482
+ }, K = 100, q = () => {
462
483
  let { apiGatewayUrl: t } = e();
463
484
  return r({
464
485
  queryKey: s.topologyResources(),
@@ -474,7 +495,7 @@ var s = {
474
495
  pageInfo { ${_} }
475
496
  }
476
497
  }`, { pagination: {
477
- limit: G,
498
+ limit: K,
478
499
  offset: n
479
500
  } }, t)).adaListResources;
480
501
  if (e.push(...r.items), !r.pageInfo.hasMore || r.items.length === 0) return e;
@@ -483,7 +504,7 @@ var s = {
483
504
  },
484
505
  staleTime: l
485
506
  });
486
- }, q = (t = {}) => {
507
+ }, J = (t = {}) => {
487
508
  let { apiGatewayUrl: n } = e();
488
509
  return r({
489
510
  queryKey: s.topology(t),
@@ -502,7 +523,7 @@ var s = {
502
523
  resourceId: t.resourceId,
503
524
  kind: t.kind,
504
525
  pagination: {
505
- limit: G,
526
+ limit: K,
506
527
  offset: r
507
528
  }
508
529
  }, n)).adaListTopologyEdges;
@@ -514,6 +535,6 @@ var s = {
514
535
  });
515
536
  };
516
537
  //#endregion
517
- export { y as useAdapter, v as useAdapters, S as useArchiveAdapter, F as useArchivePolicy, H as useCancelSyncRun, w as useConnection, C as useConnections, W as useCostRecords, U as useCostSummary, b as useCreateAdapter, T as useCreateConnection, N as useCreatePolicy, O as useDisableConnection, R as useDriftRecords, j as usePolicies, M as usePolicy, z as useRemediateDrift, L as useResolveViolation, A as useResource, k as useResources, D as useSetConnectionStatus, V as useStartSyncRun, B as useSyncRuns, q as useTopology, K as useTopologyResources, x as useUpdateAdapter, E as useUpdateConnection, P as useUpdatePolicy, I as useViolations };
538
+ export { y as useAdapter, v as useAdapters, S as useArchiveAdapter, F as useArchivePolicy, H as useCancelSyncRun, w as useConnection, C as useConnections, G as useCostRecords, U as useCostSummary, b as useCreateAdapter, T as useCreateConnection, N as useCreatePolicy, O as useDisableConnection, R as useDriftRecords, j as usePolicies, M as usePolicy, z as useRemediateDrift, L as useResolveViolation, A as useResource, k as useResources, D as useSetConnectionStatus, V as useStartSyncRun, B as useSyncRuns, J as useTopology, q as useTopologyResources, x as useUpdateAdapter, E as useUpdateConnection, P as useUpdatePolicy, I as useViolations };
518
539
 
519
540
  //# sourceMappingURL=useAdapterCloudApi.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useAdapterCloudApi.js","names":[],"sources":["../../../src/adaptercloud/hooks/useAdapterCloudApi.ts"],"sourcesContent":["/**\n * AdapterCloud API Hooks\n * @module adaptercloud/hooks\n *\n * Real, typed data layer for AdapterCloud (InfraVerse). Every hook talks to the\n * deployed `wspace-adaptercloud-svc` subgraph through the workspace GraphQL\n * gateway via `graphqlFetch`. Operations, fields, inputs, enums and the\n * Connection/pageInfo shapes are taken verbatim from the service's\n * `.hive-schema.graphql`. No mocks — every screen reads/writes real data.\n */\n\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';\n\nimport { graphqlFetch } from '@burdenoff/fe-libs/shared/graphql';\nimport { clearGraphqlFetchResponseCache } from '@burdenoff/fe-libs/shared/graphql/fetch';\n\nimport { useAdapterCloud } from '../context';\nimport { notify } from '../lib/toast';\nimport type {\n AdaAdapter,\n AdaAdapterConnectionPage,\n AdaAdapterKind,\n AdaAdapterStatus,\n AdaConnection,\n AdaConnectionPage,\n AdaConnectionStatus,\n AdaCostRecord,\n AdaCostSummary,\n AdaDriftRecord,\n AdaDriftRecordPage,\n AdaDriftStatus,\n AdaPolicy,\n AdaPolicyKind,\n AdaPolicyPage,\n AdaPolicyViolation,\n AdaPolicyViolationPage,\n AdaResource,\n AdaResourcePage,\n AdaResourceState,\n AdaSyncRun,\n AdaSyncRunPage,\n AdaSyncStatus,\n AdaTopologyEdge,\n AdaEdgeKind,\n AdaViolationStatus,\n PaginationInput,\n AdaCreateAdapterInput,\n AdaUpdateAdapterInput,\n AdaCreateConnectionInput,\n AdaUpdateConnectionInput,\n AdaCreatePolicyInput,\n AdaUpdatePolicyInput,\n AdaStartSyncRunInput,\n} from '../types';\n\n// ============================================================================\n// Query keys\n// ============================================================================\n\nexport const adaKeys = {\n all: ['adaptercloud'] as const,\n health: () => [...adaKeys.all, 'health'] as const,\n costSummary: (connectionId?: string) =>\n [...adaKeys.all, 'cost-summary', connectionId ?? null] as const,\n costRecords: (filter: Record<string, unknown>) =>\n [...adaKeys.all, 'cost-records', filter] as const,\n adapters: (filter: Record<string, unknown>) => [...adaKeys.all, 'adapters', filter] as const,\n adapter: (id: string) => [...adaKeys.all, 'adapter', id] as const,\n connections: (filter: Record<string, unknown>) =>\n [...adaKeys.all, 'connections', filter] as const,\n connection: (id: string) => [...adaKeys.all, 'connection', id] as const,\n resources: (filter: Record<string, unknown>) => [...adaKeys.all, 'resources', filter] as const,\n resource: (id: string) => [...adaKeys.all, 'resource', id] as const,\n policies: (filter: Record<string, unknown>) => [...adaKeys.all, 'policies', filter] as const,\n policy: (id: string) => [...adaKeys.all, 'policy', id] as const,\n violations: (filter: Record<string, unknown>) => [...adaKeys.all, 'violations', filter] as const,\n drift: (filter: Record<string, unknown>) => [...adaKeys.all, 'drift', filter] as const,\n syncRuns: (filter: Record<string, unknown>) => [...adaKeys.all, 'sync-runs', filter] as const,\n syncRun: (id: string) => [...adaKeys.all, 'sync-run', id] as const,\n topology: (filter: Record<string, unknown>) => [...adaKeys.all, 'topology', filter] as const,\n topologyResources: () => [...adaKeys.all, 'topology-resources'] as const,\n};\n\n// ============================================================================\n// Low-level query wrapper\n// ============================================================================\n\nconst adaQuery = async <TData>(\n query: string,\n variables: Record<string, unknown>,\n baseUrl?: string\n): Promise<TData> => {\n const response = await graphqlFetch<TData>({\n gateway: 'workspace',\n baseUrl,\n query,\n variables,\n workspaceToken: true,\n });\n\n if (response.errors?.length) {\n throw new Error(response.errors[0]?.message ?? 'GraphQL request failed');\n }\n\n if (!response.data) {\n throw new Error('GraphQL response did not include data');\n }\n\n // After a successful mutation, drop the fe-libs graphqlFetch response cache\n // (≤30s TTL) so the follow-up React-Query refetch reads fresh data instead of\n // a stale cached response — otherwise writes appear to \"not take effect\" for\n // up to 30s. (fe-libs' own Apollo client does the same on every mutation.)\n if (/^\\s*mutation\\b/.test(query)) {\n clearGraphqlFetchResponseCache();\n }\n\n return response.data;\n};\n\nconst STALE = 30 * 1000;\n\n// ============================================================================\n// Reusable GraphQL field selections (inline strings)\n// ============================================================================\n\nconst ADAPTER_FIELDS = `\n id name slug kind status vendor version description capabilities tags\n configSchema workspaceId createdAt updatedAt\n`;\n\nconst CONNECTION_FIELDS = `\n id name adapterId authMethod status environment region resourceCount\n secretRef targetRef config tags lastError lastSyncedAt workspaceId createdAt updatedAt\n`;\n\nconst RESOURCE_FIELDS = `\n id connectionId externalId resourceType name region state monthlyCost\n providerTags attributes tags lastSeenAt workspaceId createdAt updatedAt\n`;\n\nconst POLICY_FIELDS = `\n id name description kind enforcement severity expression appliesTo isActive\n tags workspaceId createdAt updatedAt\n`;\n\nconst VIOLATION_FIELDS = `\n id policyId resourceId message status severity evidence waiverReason\n detectedAt resolvedAt resolvedById workspaceId createdAt updatedAt\n`;\n\nconst DRIFT_FIELDS = `\n id resourceId attributePath expectedValue observedValue severity status\n detectedAt remediatedAt workspaceId createdAt updatedAt\n`;\n\nconst SYNC_RUN_FIELDS = `\n id connectionId kind status discoveredCount reconciledCount driftCount\n violationCount error summary startedAt finishedAt workspaceId createdAt updatedAt\n`;\n\n// `totalCount` is the real estate-wide count exposed on AdaPageInfo (svc-added).\n// Requested where the Overview tiles need an accurate total; consumers fall back\n// to `items.length` when it is null/undefined so the UI keeps working if absent.\nconst PAGE_INFO_FIELDS = `cursor hasMore totalCount`;\n\n// ============================================================================\n// Health\n// ============================================================================\n\nexport const useAdaHealth = () => {\n const { apiGatewayUrl } = useAdapterCloud();\n return useQuery({\n queryKey: adaKeys.health(),\n queryFn: async () => {\n const result = await adaQuery<{ adaHealth: string }>(\n `query AdaHealth { adaHealth }`,\n {},\n apiGatewayUrl\n );\n return result.adaHealth;\n },\n staleTime: STALE,\n });\n};\n\n// ============================================================================\n// Adapters\n// ============================================================================\n\nexport interface AdapterListFilter {\n kind?: AdaAdapterKind;\n status?: AdaAdapterStatus;\n pagination?: PaginationInput;\n}\n\nexport const useAdapters = (filter: AdapterListFilter = {}) => {\n const { apiGatewayUrl } = useAdapterCloud();\n return useQuery({\n queryKey: adaKeys.adapters(filter as Record<string, unknown>),\n queryFn: async () => {\n const result = await adaQuery<{ adaListAdapters: AdaAdapterConnectionPage }>(\n `query AdaListAdapters($kind: AdaAdapterKind, $status: AdaAdapterStatus, $pagination: PaginationInput) {\n adaListAdapters(kind: $kind, status: $status, pagination: $pagination) {\n items { ${ADAPTER_FIELDS} }\n pageInfo { ${PAGE_INFO_FIELDS} }\n }\n }`,\n {\n kind: filter.kind,\n status: filter.status,\n pagination: filter.pagination,\n },\n apiGatewayUrl\n );\n return result.adaListAdapters;\n },\n placeholderData: (prev) => prev,\n staleTime: STALE,\n });\n};\n\nexport const useAdapter = (id: string | undefined) => {\n const { apiGatewayUrl } = useAdapterCloud();\n return useQuery({\n queryKey: adaKeys.adapter(id ?? ''),\n queryFn: async () => {\n const result = await adaQuery<{ adaAdapter: AdaAdapter | null }>(\n `query AdaAdapter($id: ID!) {\n adaAdapter(id: $id) {\n ${ADAPTER_FIELDS}\n connections { ${CONNECTION_FIELDS} }\n }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.adaAdapter;\n },\n enabled: Boolean(id),\n staleTime: STALE,\n });\n};\n\nexport const useCreateAdapter = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAdapterCloud();\n return useMutation({\n mutationFn: async (input: AdaCreateAdapterInput) => {\n const result = await adaQuery<{ adaCreateAdapter: AdaAdapter }>(\n `mutation AdaCreateAdapter($input: AdaCreateAdapterInput!) {\n adaCreateAdapter(input: $input) { ${ADAPTER_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.adaCreateAdapter;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: [...adaKeys.all, 'adapters'] });\n },\n });\n};\n\nexport const useUpdateAdapter = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAdapterCloud();\n return useMutation({\n mutationFn: async ({ id, input }: { id: string; input: AdaUpdateAdapterInput }) => {\n const result = await adaQuery<{ adaUpdateAdapter: AdaAdapter }>(\n `mutation AdaUpdateAdapter($id: ID!, $input: AdaUpdateAdapterInput!) {\n adaUpdateAdapter(id: $id, input: $input) { ${ADAPTER_FIELDS} }\n }`,\n { id, input },\n apiGatewayUrl\n );\n return result.adaUpdateAdapter;\n },\n onSuccess: (adapter) => {\n void queryClient.invalidateQueries({ queryKey: [...adaKeys.all, 'adapters'] });\n void queryClient.invalidateQueries({ queryKey: adaKeys.adapter(adapter.id) });\n },\n });\n};\n\nexport const useArchiveAdapter = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAdapterCloud();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await adaQuery<{ adaArchiveAdapter: boolean }>(\n `mutation AdaArchiveAdapter($id: ID!) { adaArchiveAdapter(id: $id) }`,\n { id },\n apiGatewayUrl\n );\n return result.adaArchiveAdapter;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: [...adaKeys.all, 'adapters'] });\n },\n });\n};\n\n// ============================================================================\n// Connections\n// ============================================================================\n\nexport interface ConnectionListFilter {\n adapterId?: string;\n status?: AdaConnectionStatus;\n pagination?: PaginationInput;\n}\n\nexport const useConnections = (filter: ConnectionListFilter = {}) => {\n const { apiGatewayUrl } = useAdapterCloud();\n return useQuery({\n queryKey: adaKeys.connections(filter as Record<string, unknown>),\n queryFn: async () => {\n const result = await adaQuery<{ adaListConnections: AdaConnectionPage }>(\n `query AdaListConnections($adapterId: ID, $status: AdaConnectionStatus, $pagination: PaginationInput) {\n adaListConnections(adapterId: $adapterId, status: $status, pagination: $pagination) {\n items {\n ${CONNECTION_FIELDS}\n adapter { id name slug kind }\n }\n pageInfo { ${PAGE_INFO_FIELDS} }\n }\n }`,\n {\n adapterId: filter.adapterId,\n status: filter.status,\n pagination: filter.pagination,\n },\n apiGatewayUrl\n );\n return result.adaListConnections;\n },\n placeholderData: (prev) => prev,\n staleTime: STALE,\n });\n};\n\nexport const useConnection = (id: string | undefined) => {\n const { apiGatewayUrl } = useAdapterCloud();\n return useQuery({\n queryKey: adaKeys.connection(id ?? ''),\n queryFn: async () => {\n const result = await adaQuery<{ adaConnection: AdaConnection | null }>(\n `query AdaConnection($id: ID!) {\n adaConnection(id: $id) {\n ${CONNECTION_FIELDS}\n adapter { ${ADAPTER_FIELDS} }\n resources { ${RESOURCE_FIELDS} }\n }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.adaConnection;\n },\n enabled: Boolean(id),\n staleTime: STALE,\n });\n};\n\nexport const useCreateConnection = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAdapterCloud();\n return useMutation({\n mutationFn: async (input: AdaCreateConnectionInput) => {\n const result = await adaQuery<{ adaCreateConnection: AdaConnection }>(\n `mutation AdaCreateConnection($input: AdaCreateConnectionInput!) {\n adaCreateConnection(input: $input) { ${CONNECTION_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.adaCreateConnection;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: [...adaKeys.all, 'connections'] });\n },\n });\n};\n\nexport const useUpdateConnection = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAdapterCloud();\n return useMutation({\n mutationFn: async ({ id, input }: { id: string; input: AdaUpdateConnectionInput }) => {\n const result = await adaQuery<{ adaUpdateConnection: AdaConnection }>(\n `mutation AdaUpdateConnection($id: ID!, $input: AdaUpdateConnectionInput!) {\n adaUpdateConnection(id: $id, input: $input) { ${CONNECTION_FIELDS} }\n }`,\n { id, input },\n apiGatewayUrl\n );\n return result.adaUpdateConnection;\n },\n onSuccess: (connection) => {\n void queryClient.invalidateQueries({ queryKey: [...adaKeys.all, 'connections'] });\n void queryClient.invalidateQueries({ queryKey: adaKeys.connection(connection.id) });\n },\n });\n};\n\nexport const useSetConnectionStatus = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAdapterCloud();\n return useMutation({\n mutationFn: async ({ id, status }: { id: string; status: AdaConnectionStatus }) => {\n const result = await adaQuery<{ adaSetConnectionStatus: AdaConnection }>(\n `mutation AdaSetConnectionStatus($id: ID!, $status: AdaConnectionStatus!) {\n adaSetConnectionStatus(id: $id, status: $status) { ${CONNECTION_FIELDS} }\n }`,\n { id, status },\n apiGatewayUrl\n );\n return result.adaSetConnectionStatus;\n },\n onSuccess: (connection) => {\n notify.success('Connection health updated');\n void queryClient.invalidateQueries({ queryKey: [...adaKeys.all, 'connections'] });\n void queryClient.invalidateQueries({ queryKey: adaKeys.connection(connection.id) });\n },\n });\n};\n\nexport const useDisableConnection = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAdapterCloud();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await adaQuery<{ adaDisableConnection: AdaConnection }>(\n `mutation AdaDisableConnection($id: ID!) {\n adaDisableConnection(id: $id) { ${CONNECTION_FIELDS} }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.adaDisableConnection;\n },\n onSuccess: (connection) => {\n notify.success('Connection disabled');\n void queryClient.invalidateQueries({ queryKey: [...adaKeys.all, 'connections'] });\n void queryClient.invalidateQueries({ queryKey: adaKeys.connection(connection.id) });\n },\n });\n};\n\n// ============================================================================\n// Resources\n// ============================================================================\n\nexport interface ResourceListFilter {\n connectionId?: string;\n resourceType?: string;\n state?: AdaResourceState;\n pagination?: PaginationInput;\n}\n\nexport const useResources = (filter: ResourceListFilter = {}) => {\n const { apiGatewayUrl } = useAdapterCloud();\n return useQuery({\n queryKey: adaKeys.resources(filter as Record<string, unknown>),\n queryFn: async () => {\n const result = await adaQuery<{ adaListResources: AdaResourcePage }>(\n `query AdaListResources($connectionId: ID, $resourceType: String, $state: AdaResourceState, $pagination: PaginationInput) {\n adaListResources(connectionId: $connectionId, resourceType: $resourceType, state: $state, pagination: $pagination) {\n items {\n ${RESOURCE_FIELDS}\n connection { id name }\n }\n pageInfo { ${PAGE_INFO_FIELDS} }\n }\n }`,\n {\n connectionId: filter.connectionId,\n resourceType: filter.resourceType,\n state: filter.state,\n pagination: filter.pagination,\n },\n apiGatewayUrl\n );\n return result.adaListResources;\n },\n placeholderData: (prev) => prev,\n staleTime: STALE,\n });\n};\n\nexport const useResource = (id: string | undefined) => {\n const { apiGatewayUrl } = useAdapterCloud();\n return useQuery({\n queryKey: adaKeys.resource(id ?? ''),\n queryFn: async () => {\n const result = await adaQuery<{ adaResource: AdaResource | null }>(\n `query AdaResource($id: ID!) {\n adaResource(id: $id) {\n ${RESOURCE_FIELDS}\n connection { ${CONNECTION_FIELDS} adapter { id name slug kind } }\n dependsOn { id name resourceType region state monthlyCost }\n }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.adaResource;\n },\n enabled: Boolean(id),\n staleTime: STALE,\n });\n};\n\n// ============================================================================\n// Policies\n// ============================================================================\n\nexport interface PolicyListFilter {\n isActive?: boolean;\n kind?: AdaPolicyKind;\n pagination?: PaginationInput;\n}\n\nexport const usePolicies = (filter: PolicyListFilter = {}) => {\n const { apiGatewayUrl } = useAdapterCloud();\n return useQuery({\n queryKey: adaKeys.policies(filter as Record<string, unknown>),\n queryFn: async () => {\n const result = await adaQuery<{ adaListPolicies: AdaPolicyPage }>(\n `query AdaListPolicies($isActive: Boolean, $kind: AdaPolicyKind, $pagination: PaginationInput) {\n adaListPolicies(isActive: $isActive, kind: $kind, pagination: $pagination) {\n items { ${POLICY_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n {\n isActive: filter.isActive,\n kind: filter.kind,\n pagination: filter.pagination,\n },\n apiGatewayUrl\n );\n return result.adaListPolicies;\n },\n placeholderData: (prev) => prev,\n staleTime: STALE,\n });\n};\n\nexport const usePolicy = (id: string | undefined) => {\n const { apiGatewayUrl } = useAdapterCloud();\n return useQuery({\n queryKey: adaKeys.policy(id ?? ''),\n queryFn: async () => {\n const result = await adaQuery<{ adaPolicy: AdaPolicy | null }>(\n `query AdaPolicy($id: ID!) {\n adaPolicy(id: $id) {\n ${POLICY_FIELDS}\n violations { ${VIOLATION_FIELDS} }\n }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.adaPolicy;\n },\n enabled: Boolean(id),\n staleTime: STALE,\n });\n};\n\nexport const useCreatePolicy = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAdapterCloud();\n return useMutation({\n mutationFn: async (input: AdaCreatePolicyInput) => {\n const result = await adaQuery<{ adaCreatePolicy: AdaPolicy }>(\n `mutation AdaCreatePolicy($input: AdaCreatePolicyInput!) {\n adaCreatePolicy(input: $input) { ${POLICY_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.adaCreatePolicy;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: [...adaKeys.all, 'policies'] });\n },\n });\n};\n\nexport const useUpdatePolicy = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAdapterCloud();\n return useMutation({\n mutationFn: async ({ id, input }: { id: string; input: AdaUpdatePolicyInput }) => {\n const result = await adaQuery<{ adaUpdatePolicy: AdaPolicy }>(\n `mutation AdaUpdatePolicy($id: ID!, $input: AdaUpdatePolicyInput!) {\n adaUpdatePolicy(id: $id, input: $input) { ${POLICY_FIELDS} }\n }`,\n { id, input },\n apiGatewayUrl\n );\n return result.adaUpdatePolicy;\n },\n onSuccess: (policy) => {\n notify.success('Policy updated');\n void queryClient.invalidateQueries({ queryKey: [...adaKeys.all, 'policies'] });\n void queryClient.invalidateQueries({ queryKey: adaKeys.policy(policy.id) });\n },\n });\n};\n\nexport const useArchivePolicy = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAdapterCloud();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await adaQuery<{ adaArchivePolicy: boolean }>(\n `mutation AdaArchivePolicy($id: ID!) { adaArchivePolicy(id: $id) }`,\n { id },\n apiGatewayUrl\n );\n return result.adaArchivePolicy;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: [...adaKeys.all, 'policies'] });\n },\n });\n};\n\n// ============================================================================\n// Violations\n// ============================================================================\n\nexport interface ViolationListFilter {\n policyId?: string;\n resourceId?: string;\n status?: AdaViolationStatus;\n pagination?: PaginationInput;\n}\n\nexport const useViolations = (filter: ViolationListFilter = {}) => {\n const { apiGatewayUrl } = useAdapterCloud();\n return useQuery({\n queryKey: adaKeys.violations(filter as Record<string, unknown>),\n queryFn: async () => {\n const result = await adaQuery<{ adaListViolations: AdaPolicyViolationPage }>(\n `query AdaListViolations($policyId: ID, $resourceId: ID, $status: AdaViolationStatus, $pagination: PaginationInput) {\n adaListViolations(policyId: $policyId, resourceId: $resourceId, status: $status, pagination: $pagination) {\n items {\n ${VIOLATION_FIELDS}\n policy { id name kind severity }\n }\n pageInfo { ${PAGE_INFO_FIELDS} }\n }\n }`,\n {\n policyId: filter.policyId,\n resourceId: filter.resourceId,\n status: filter.status,\n pagination: filter.pagination,\n },\n apiGatewayUrl\n );\n return result.adaListViolations;\n },\n placeholderData: (prev) => prev,\n staleTime: STALE,\n });\n};\n\nexport const useResolveViolation = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAdapterCloud();\n return useMutation({\n mutationFn: async ({\n id,\n status,\n waiverReason,\n }: {\n id: string;\n status: AdaViolationStatus;\n waiverReason?: string;\n }) => {\n const result = await adaQuery<{ adaResolveViolation: AdaPolicyViolation }>(\n `mutation AdaResolveViolation($id: ID!, $status: AdaViolationStatus!, $waiverReason: String) {\n adaResolveViolation(id: $id, status: $status, waiverReason: $waiverReason) {\n ${VIOLATION_FIELDS}\n }\n }`,\n { id, status, waiverReason },\n apiGatewayUrl\n );\n return result.adaResolveViolation;\n },\n onSuccess: (violation) => {\n const label: Record<string, string> = {\n ACKNOWLEDGED: 'Violation acknowledged',\n RESOLVED: 'Violation resolved',\n WAIVED: 'Violation waived',\n OPEN: 'Violation reopened',\n };\n notify.success(label[violation.status] ?? 'Violation updated');\n void queryClient.invalidateQueries({ queryKey: [...adaKeys.all, 'violations'] });\n },\n });\n};\n\n// ============================================================================\n// Drift\n// ============================================================================\n\nexport interface DriftListFilter {\n resourceId?: string;\n status?: AdaDriftStatus;\n}\n\nexport const useDriftRecords = (filter: DriftListFilter = {}) => {\n const { apiGatewayUrl } = useAdapterCloud();\n return useQuery({\n queryKey: adaKeys.drift(filter as Record<string, unknown>),\n queryFn: async () => {\n // adaListDriftRecords returns AdaDriftRecordConnection (items + pageInfo),\n // matching every other ada*List query — the drift fields must be\n // requested under `items`, not directly on the connection.\n const result = await adaQuery<{ adaListDriftRecords: AdaDriftRecordPage }>(\n `query AdaListDriftRecords($resourceId: ID, $status: AdaDriftStatus, $pagination: PaginationInput) {\n adaListDriftRecords(resourceId: $resourceId, status: $status, pagination: $pagination) {\n items { ${DRIFT_FIELDS} }\n pageInfo { ${PAGE_INFO_FIELDS} }\n }\n }`,\n {\n resourceId: filter.resourceId,\n status: filter.status,\n // Callers historically relied on an unpaginated \"all matching drift\"\n // result (see DriftListPage) — request the server's page-size\n // ceiling (MAX_LIMIT in wspace-adaptercloud-svc's pagination utils)\n // explicitly rather than relying on the smaller default of 50.\n pagination: { limit: 100 },\n },\n apiGatewayUrl\n );\n return result.adaListDriftRecords.items;\n },\n staleTime: STALE,\n });\n};\n\nexport const useRemediateDrift = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAdapterCloud();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await adaQuery<{ adaRemediateDrift: AdaDriftRecord }>(\n `mutation AdaRemediateDrift($id: ID!) {\n adaRemediateDrift(id: $id) { ${DRIFT_FIELDS} }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.adaRemediateDrift;\n },\n onSuccess: () => {\n notify.success('Drift marked remediated');\n void queryClient.invalidateQueries({ queryKey: [...adaKeys.all, 'drift'] });\n void queryClient.invalidateQueries({ queryKey: [...adaKeys.all, 'resources'] });\n },\n });\n};\n\n// ============================================================================\n// Sync runs\n// ============================================================================\n\nexport interface SyncRunListFilter {\n connectionId?: string;\n status?: AdaSyncStatus;\n pagination?: PaginationInput;\n}\n\nexport const useSyncRuns = (filter: SyncRunListFilter = {}) => {\n const { apiGatewayUrl } = useAdapterCloud();\n return useQuery({\n queryKey: adaKeys.syncRuns(filter as Record<string, unknown>),\n queryFn: async () => {\n const result = await adaQuery<{ adaListSyncRuns: AdaSyncRunPage }>(\n `query AdaListSyncRuns($connectionId: ID, $status: AdaSyncStatus, $pagination: PaginationInput) {\n adaListSyncRuns(connectionId: $connectionId, status: $status, pagination: $pagination) {\n items {\n ${SYNC_RUN_FIELDS}\n connection { id name adapter { id kind } }\n }\n pageInfo { ${PAGE_INFO_FIELDS} }\n }\n }`,\n {\n connectionId: filter.connectionId,\n status: filter.status,\n pagination: filter.pagination,\n },\n apiGatewayUrl\n );\n return result.adaListSyncRuns;\n },\n placeholderData: (prev) => prev,\n staleTime: STALE,\n });\n};\n\nexport const useStartSyncRun = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAdapterCloud();\n return useMutation({\n mutationFn: async (input: AdaStartSyncRunInput) => {\n const result = await adaQuery<{ adaStartSyncRun: AdaSyncRun }>(\n `mutation AdaStartSyncRun($input: AdaStartSyncRunInput!) {\n adaStartSyncRun(input: $input) { ${SYNC_RUN_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.adaStartSyncRun;\n },\n onSuccess: () => {\n notify.success('Sync run started');\n void queryClient.invalidateQueries({ queryKey: [...adaKeys.all, 'sync-runs'] });\n void queryClient.invalidateQueries({ queryKey: [...adaKeys.all, 'connections'] });\n },\n });\n};\n\nexport const useCancelSyncRun = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAdapterCloud();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await adaQuery<{ adaCancelSyncRun: AdaSyncRun }>(\n `mutation AdaCancelSyncRun($id: ID!) {\n adaCancelSyncRun(id: $id) { ${SYNC_RUN_FIELDS} }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.adaCancelSyncRun;\n },\n onSuccess: () => {\n notify.success('Sync run cancelled');\n void queryClient.invalidateQueries({ queryKey: [...adaKeys.all, 'sync-runs'] });\n },\n });\n};\n\n// ============================================================================\n// FinOps — cost\n// ============================================================================\n\nexport const useCostSummary = (connectionId?: string) => {\n const { apiGatewayUrl } = useAdapterCloud();\n return useQuery({\n queryKey: adaKeys.costSummary(connectionId),\n queryFn: async () => {\n const result = await adaQuery<{ adaCostSummary: AdaCostSummary }>(\n `query AdaCostSummary($connectionId: ID) {\n adaCostSummary(connectionId: $connectionId) {\n currency total\n lines { service total }\n }\n }`,\n { connectionId },\n apiGatewayUrl\n );\n return result.adaCostSummary;\n },\n staleTime: STALE,\n });\n};\n\nexport interface CostRecordListFilter {\n connectionId?: string;\n resourceId?: string;\n service?: string;\n}\n\nexport const useCostRecords = (filter: CostRecordListFilter = {}) => {\n const { apiGatewayUrl } = useAdapterCloud();\n return useQuery({\n queryKey: adaKeys.costRecords(filter as Record<string, unknown>),\n queryFn: async () => {\n const result = await adaQuery<{ adaListCostRecords: AdaCostRecord[] }>(\n `query AdaListCostRecords($connectionId: ID, $resourceId: ID, $service: String) {\n adaListCostRecords(connectionId: $connectionId, resourceId: $resourceId, service: $service) {\n id service amount currency periodStart periodEnd breakdown\n connectionId resourceId workspaceId createdAt updatedAt\n resource { id name }\n connection { id name }\n }\n }`,\n {\n connectionId: filter.connectionId,\n resourceId: filter.resourceId,\n service: filter.service,\n },\n apiGatewayUrl\n );\n return result.adaListCostRecords;\n },\n staleTime: STALE,\n });\n};\n\n// ============================================================================\n// Topology\n// ============================================================================\n\nexport interface TopologyFilter {\n resourceId?: string;\n kind?: AdaEdgeKind;\n}\n\nconst TOPOLOGY_PAGE_SIZE = 100;\n\n/**\n * Load every resource needed by the estate graph. The normal inventory hook is\n * intentionally page-oriented; a dependency graph cannot silently drop nodes\n * after the first page without producing incorrect impact results.\n */\nexport const useTopologyResources = () => {\n const { apiGatewayUrl } = useAdapterCloud();\n return useQuery({\n queryKey: adaKeys.topologyResources(),\n queryFn: async () => {\n const items: AdaResource[] = [];\n let offset = 0;\n\n for (;;) {\n const result = await adaQuery<{ adaListResources: AdaResourcePage }>(\n `query AdaTopologyResources($pagination: PaginationInput) {\n adaListResources(pagination: $pagination) {\n items {\n ${RESOURCE_FIELDS}\n connection { id name }\n }\n pageInfo { ${PAGE_INFO_FIELDS} }\n }\n }`,\n { pagination: { limit: TOPOLOGY_PAGE_SIZE, offset } },\n apiGatewayUrl\n );\n const page = result.adaListResources;\n items.push(...page.items);\n if (!page.pageInfo.hasMore || page.items.length === 0) return items;\n offset += page.items.length;\n }\n },\n staleTime: STALE,\n });\n};\n\n/**\n * The estate's dependency edges (`adaListTopologyEdges`). Consumers pair this\n * with `useResources` to render the topology graph — edges reference resources\n * by id, resources supply the node labels/state/type.\n */\nexport const useTopology = (filter: TopologyFilter = {}) => {\n const { apiGatewayUrl } = useAdapterCloud();\n return useQuery({\n queryKey: adaKeys.topology(filter as Record<string, unknown>),\n queryFn: async () => {\n const items: AdaTopologyEdge[] = [];\n let offset = 0;\n\n for (;;) {\n const result = await adaQuery<{\n adaListTopologyEdges: { items: AdaTopologyEdge[]; pageInfo: { hasMore: boolean } };\n }>(\n `query AdaListTopologyEdges($resourceId: ID, $kind: AdaEdgeKind, $pagination: PaginationInput) {\n adaListTopologyEdges(resourceId: $resourceId, kind: $kind, pagination: $pagination) {\n items {\n id fromResourceId toResourceId kind bidirectional weight attributes\n workspaceId createdAt updatedAt\n }\n pageInfo { ${PAGE_INFO_FIELDS} }\n }\n }`,\n {\n resourceId: filter.resourceId,\n kind: filter.kind,\n pagination: { limit: TOPOLOGY_PAGE_SIZE, offset },\n },\n apiGatewayUrl\n );\n const page = result.adaListTopologyEdges;\n items.push(...page.items);\n if (!page.pageInfo.hasMore || page.items.length === 0) return items;\n offset += page.items.length;\n }\n },\n staleTime: STALE,\n });\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"useAdapterCloudApi.js","names":[],"sources":["../../../src/adaptercloud/hooks/useAdapterCloudApi.ts"],"sourcesContent":["/**\n * AdapterCloud API Hooks\n * @module adaptercloud/hooks\n *\n * Real, typed data layer for AdapterCloud (InfraVerse). Every hook talks to the\n * deployed `wspace-adaptercloud-svc` subgraph through the workspace GraphQL\n * gateway via `graphqlFetch`. Operations, fields, inputs, enums and the\n * Connection/pageInfo shapes are taken verbatim from the service's\n * `.hive-schema.graphql`. No mocks — every screen reads/writes real data.\n */\n\nimport { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';\n\nimport { graphqlFetch } from '@burdenoff/fe-libs/shared/graphql';\nimport { clearGraphqlFetchResponseCache } from '@burdenoff/fe-libs/shared/graphql/fetch';\n\nimport { useAdapterCloud } from '../context';\nimport { notify } from '../lib/toast';\nimport type {\n AdaAdapter,\n AdaAdapterConnectionPage,\n AdaAdapterKind,\n AdaAdapterStatus,\n AdaConnection,\n AdaConnectionPage,\n AdaConnectionStatus,\n AdaCostRecord,\n AdaCostSummary,\n AdaDriftRecord,\n AdaDriftRecordPage,\n AdaDriftStatus,\n AdaPolicy,\n AdaPolicyKind,\n AdaPolicyPage,\n AdaPolicyViolation,\n AdaPolicyViolationPage,\n AdaResource,\n AdaResourcePage,\n AdaResourceState,\n AdaSyncRun,\n AdaSyncRunPage,\n AdaSyncStatus,\n AdaTopologyEdge,\n AdaEdgeKind,\n AdaViolationStatus,\n PaginationInput,\n AdaCreateAdapterInput,\n AdaUpdateAdapterInput,\n AdaCreateConnectionInput,\n AdaUpdateConnectionInput,\n AdaCreatePolicyInput,\n AdaUpdatePolicyInput,\n AdaStartSyncRunInput,\n} from '../types';\n\n// ============================================================================\n// Query keys\n// ============================================================================\n\nexport const adaKeys = {\n all: ['adaptercloud'] as const,\n health: () => [...adaKeys.all, 'health'] as const,\n costSummary: (connectionId?: string) =>\n [...adaKeys.all, 'cost-summary', connectionId ?? null] as const,\n costRecords: (filter: Record<string, unknown>) =>\n [...adaKeys.all, 'cost-records', filter] as const,\n adapters: (filter: Record<string, unknown>) => [...adaKeys.all, 'adapters', filter] as const,\n adapter: (id: string) => [...adaKeys.all, 'adapter', id] as const,\n connections: (filter: Record<string, unknown>) =>\n [...adaKeys.all, 'connections', filter] as const,\n connection: (id: string) => [...adaKeys.all, 'connection', id] as const,\n resources: (filter: Record<string, unknown>) => [...adaKeys.all, 'resources', filter] as const,\n resource: (id: string) => [...adaKeys.all, 'resource', id] as const,\n policies: (filter: Record<string, unknown>) => [...adaKeys.all, 'policies', filter] as const,\n policy: (id: string) => [...adaKeys.all, 'policy', id] as const,\n violations: (filter: Record<string, unknown>) => [...adaKeys.all, 'violations', filter] as const,\n drift: (filter: Record<string, unknown>) => [...adaKeys.all, 'drift', filter] as const,\n syncRuns: (filter: Record<string, unknown>) => [...adaKeys.all, 'sync-runs', filter] as const,\n syncRun: (id: string) => [...adaKeys.all, 'sync-run', id] as const,\n topology: (filter: Record<string, unknown>) => [...adaKeys.all, 'topology', filter] as const,\n topologyResources: () => [...adaKeys.all, 'topology-resources'] as const,\n};\n\n// ============================================================================\n// Low-level query wrapper\n// ============================================================================\n\nconst adaQuery = async <TData>(\n query: string,\n variables: Record<string, unknown>,\n baseUrl?: string\n): Promise<TData> => {\n const response = await graphqlFetch<TData>({\n gateway: 'workspace',\n baseUrl,\n query,\n variables,\n workspaceToken: true,\n });\n\n if (response.errors?.length) {\n throw new Error(response.errors[0]?.message ?? 'GraphQL request failed');\n }\n\n if (!response.data) {\n throw new Error('GraphQL response did not include data');\n }\n\n // After a successful mutation, drop the fe-libs graphqlFetch response cache\n // (≤30s TTL) so the follow-up React-Query refetch reads fresh data instead of\n // a stale cached response — otherwise writes appear to \"not take effect\" for\n // up to 30s. (fe-libs' own Apollo client does the same on every mutation.)\n if (/^\\s*mutation\\b/.test(query)) {\n clearGraphqlFetchResponseCache();\n }\n\n return response.data;\n};\n\nconst STALE = 30 * 1000;\n\n// ============================================================================\n// Reusable GraphQL field selections (inline strings)\n// ============================================================================\n\nconst ADAPTER_FIELDS = `\n id name slug kind status vendor version description capabilities tags\n configSchema workspaceId createdAt updatedAt\n`;\n\nconst CONNECTION_FIELDS = `\n id name adapterId authMethod status environment region resourceCount\n secretRef targetRef config tags lastError lastSyncedAt workspaceId createdAt updatedAt\n`;\n\nconst RESOURCE_FIELDS = `\n id connectionId externalId resourceType name region state monthlyCost\n providerTags attributes tags lastSeenAt workspaceId createdAt updatedAt\n`;\n\nconst POLICY_FIELDS = `\n id name description kind enforcement severity expression appliesTo isActive\n tags workspaceId createdAt updatedAt\n`;\n\nconst VIOLATION_FIELDS = `\n id policyId resourceId message status severity evidence waiverReason\n detectedAt resolvedAt resolvedById workspaceId createdAt updatedAt\n`;\n\nconst DRIFT_FIELDS = `\n id resourceId attributePath expectedValue observedValue severity status\n detectedAt remediatedAt workspaceId createdAt updatedAt\n`;\n\nconst SYNC_RUN_FIELDS = `\n id connectionId kind status discoveredCount reconciledCount driftCount\n violationCount error summary startedAt finishedAt workspaceId createdAt updatedAt\n`;\n\n// `totalCount` is the real estate-wide count exposed on AdaPageInfo (svc-added).\n// Requested where the Overview tiles need an accurate total; consumers fall back\n// to `items.length` when it is null/undefined so the UI keeps working if absent.\nconst PAGE_INFO_FIELDS = `cursor hasMore totalCount`;\n\n// ============================================================================\n// Health\n// ============================================================================\n\nexport const useAdaHealth = () => {\n const { apiGatewayUrl } = useAdapterCloud();\n return useQuery({\n queryKey: adaKeys.health(),\n queryFn: async () => {\n const result = await adaQuery<{ adaHealth: string }>(\n `query AdaHealth { adaHealth }`,\n {},\n apiGatewayUrl\n );\n return result.adaHealth;\n },\n staleTime: STALE,\n });\n};\n\n// ============================================================================\n// Adapters\n// ============================================================================\n\nexport interface AdapterListFilter {\n kind?: AdaAdapterKind;\n status?: AdaAdapterStatus;\n pagination?: PaginationInput;\n}\n\nexport const useAdapters = (filter: AdapterListFilter = {}) => {\n const { apiGatewayUrl } = useAdapterCloud();\n return useQuery({\n queryKey: adaKeys.adapters(filter as Record<string, unknown>),\n queryFn: async () => {\n const result = await adaQuery<{ adaListAdapters: AdaAdapterConnectionPage }>(\n `query AdaListAdapters($kind: AdaAdapterKind, $status: AdaAdapterStatus, $pagination: PaginationInput) {\n adaListAdapters(kind: $kind, status: $status, pagination: $pagination) {\n items { ${ADAPTER_FIELDS} }\n pageInfo { ${PAGE_INFO_FIELDS} }\n }\n }`,\n {\n kind: filter.kind,\n status: filter.status,\n pagination: filter.pagination,\n },\n apiGatewayUrl\n );\n return result.adaListAdapters;\n },\n placeholderData: (prev) => prev,\n staleTime: STALE,\n });\n};\n\nexport const useAdapter = (id: string | undefined) => {\n const { apiGatewayUrl } = useAdapterCloud();\n return useQuery({\n queryKey: adaKeys.adapter(id ?? ''),\n queryFn: async () => {\n const result = await adaQuery<{ adaAdapter: AdaAdapter | null }>(\n `query AdaAdapter($id: ID!) {\n adaAdapter(id: $id) {\n ${ADAPTER_FIELDS}\n connections { ${CONNECTION_FIELDS} }\n }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.adaAdapter;\n },\n enabled: Boolean(id),\n staleTime: STALE,\n });\n};\n\nexport const useCreateAdapter = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAdapterCloud();\n return useMutation({\n mutationFn: async (input: AdaCreateAdapterInput) => {\n const result = await adaQuery<{ adaCreateAdapter: AdaAdapter }>(\n `mutation AdaCreateAdapter($input: AdaCreateAdapterInput!) {\n adaCreateAdapter(input: $input) { ${ADAPTER_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.adaCreateAdapter;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: [...adaKeys.all, 'adapters'] });\n },\n });\n};\n\nexport const useUpdateAdapter = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAdapterCloud();\n return useMutation({\n mutationFn: async ({ id, input }: { id: string; input: AdaUpdateAdapterInput }) => {\n const result = await adaQuery<{ adaUpdateAdapter: AdaAdapter }>(\n `mutation AdaUpdateAdapter($id: ID!, $input: AdaUpdateAdapterInput!) {\n adaUpdateAdapter(id: $id, input: $input) { ${ADAPTER_FIELDS} }\n }`,\n { id, input },\n apiGatewayUrl\n );\n return result.adaUpdateAdapter;\n },\n onSuccess: (adapter) => {\n void queryClient.invalidateQueries({ queryKey: [...adaKeys.all, 'adapters'] });\n void queryClient.invalidateQueries({ queryKey: adaKeys.adapter(adapter.id) });\n },\n });\n};\n\nexport const useArchiveAdapter = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAdapterCloud();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await adaQuery<{ adaArchiveAdapter: boolean }>(\n `mutation AdaArchiveAdapter($id: ID!) { adaArchiveAdapter(id: $id) }`,\n { id },\n apiGatewayUrl\n );\n return result.adaArchiveAdapter;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: [...adaKeys.all, 'adapters'] });\n },\n });\n};\n\n// ============================================================================\n// Connections\n// ============================================================================\n\nexport interface ConnectionListFilter {\n adapterId?: string;\n status?: AdaConnectionStatus;\n pagination?: PaginationInput;\n}\n\nexport const useConnections = (filter: ConnectionListFilter = {}) => {\n const { apiGatewayUrl } = useAdapterCloud();\n return useQuery({\n queryKey: adaKeys.connections(filter as Record<string, unknown>),\n queryFn: async () => {\n const result = await adaQuery<{ adaListConnections: AdaConnectionPage }>(\n `query AdaListConnections($adapterId: ID, $status: AdaConnectionStatus, $pagination: PaginationInput) {\n adaListConnections(adapterId: $adapterId, status: $status, pagination: $pagination) {\n items {\n ${CONNECTION_FIELDS}\n adapter { id name slug kind }\n }\n pageInfo { ${PAGE_INFO_FIELDS} }\n }\n }`,\n {\n adapterId: filter.adapterId,\n status: filter.status,\n pagination: filter.pagination,\n },\n apiGatewayUrl\n );\n return result.adaListConnections;\n },\n placeholderData: (prev) => prev,\n staleTime: STALE,\n });\n};\n\nexport const useConnection = (id: string | undefined) => {\n const { apiGatewayUrl } = useAdapterCloud();\n return useQuery({\n queryKey: adaKeys.connection(id ?? ''),\n queryFn: async () => {\n const result = await adaQuery<{ adaConnection: AdaConnection | null }>(\n `query AdaConnection($id: ID!) {\n adaConnection(id: $id) {\n ${CONNECTION_FIELDS}\n adapter { ${ADAPTER_FIELDS} }\n resources { ${RESOURCE_FIELDS} }\n }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.adaConnection;\n },\n enabled: Boolean(id),\n staleTime: STALE,\n });\n};\n\nexport const useCreateConnection = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAdapterCloud();\n return useMutation({\n mutationFn: async (input: AdaCreateConnectionInput) => {\n const result = await adaQuery<{ adaCreateConnection: AdaConnection }>(\n `mutation AdaCreateConnection($input: AdaCreateConnectionInput!) {\n adaCreateConnection(input: $input) { ${CONNECTION_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.adaCreateConnection;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: [...adaKeys.all, 'connections'] });\n },\n });\n};\n\nexport const useUpdateConnection = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAdapterCloud();\n return useMutation({\n mutationFn: async ({ id, input }: { id: string; input: AdaUpdateConnectionInput }) => {\n const result = await adaQuery<{ adaUpdateConnection: AdaConnection }>(\n `mutation AdaUpdateConnection($id: ID!, $input: AdaUpdateConnectionInput!) {\n adaUpdateConnection(id: $id, input: $input) { ${CONNECTION_FIELDS} }\n }`,\n { id, input },\n apiGatewayUrl\n );\n return result.adaUpdateConnection;\n },\n onSuccess: (connection) => {\n void queryClient.invalidateQueries({ queryKey: [...adaKeys.all, 'connections'] });\n void queryClient.invalidateQueries({ queryKey: adaKeys.connection(connection.id) });\n },\n });\n};\n\nexport const useSetConnectionStatus = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAdapterCloud();\n return useMutation({\n mutationFn: async ({ id, status }: { id: string; status: AdaConnectionStatus }) => {\n const result = await adaQuery<{ adaSetConnectionStatus: AdaConnection }>(\n `mutation AdaSetConnectionStatus($id: ID!, $status: AdaConnectionStatus!) {\n adaSetConnectionStatus(id: $id, status: $status) { ${CONNECTION_FIELDS} }\n }`,\n { id, status },\n apiGatewayUrl\n );\n return result.adaSetConnectionStatus;\n },\n onSuccess: (connection) => {\n notify.success('Connection health updated');\n void queryClient.invalidateQueries({ queryKey: [...adaKeys.all, 'connections'] });\n void queryClient.invalidateQueries({ queryKey: adaKeys.connection(connection.id) });\n },\n });\n};\n\nexport const useDisableConnection = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAdapterCloud();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await adaQuery<{ adaDisableConnection: AdaConnection }>(\n `mutation AdaDisableConnection($id: ID!) {\n adaDisableConnection(id: $id) { ${CONNECTION_FIELDS} }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.adaDisableConnection;\n },\n onSuccess: (connection) => {\n notify.success('Connection disabled');\n void queryClient.invalidateQueries({ queryKey: [...adaKeys.all, 'connections'] });\n void queryClient.invalidateQueries({ queryKey: adaKeys.connection(connection.id) });\n },\n });\n};\n\n// ============================================================================\n// Resources\n// ============================================================================\n\nexport interface ResourceListFilter {\n connectionId?: string;\n resourceType?: string;\n state?: AdaResourceState;\n pagination?: PaginationInput;\n}\n\nexport const useResources = (filter: ResourceListFilter = {}) => {\n const { apiGatewayUrl } = useAdapterCloud();\n return useQuery({\n queryKey: adaKeys.resources(filter as Record<string, unknown>),\n queryFn: async () => {\n const result = await adaQuery<{ adaListResources: AdaResourcePage }>(\n `query AdaListResources($connectionId: ID, $resourceType: String, $state: AdaResourceState, $pagination: PaginationInput) {\n adaListResources(connectionId: $connectionId, resourceType: $resourceType, state: $state, pagination: $pagination) {\n items {\n ${RESOURCE_FIELDS}\n connection { id name }\n }\n pageInfo { ${PAGE_INFO_FIELDS} }\n }\n }`,\n {\n connectionId: filter.connectionId,\n resourceType: filter.resourceType,\n state: filter.state,\n pagination: filter.pagination,\n },\n apiGatewayUrl\n );\n return result.adaListResources;\n },\n placeholderData: (prev) => prev,\n staleTime: STALE,\n });\n};\n\nexport const useResource = (id: string | undefined) => {\n const { apiGatewayUrl } = useAdapterCloud();\n return useQuery({\n queryKey: adaKeys.resource(id ?? ''),\n queryFn: async () => {\n const result = await adaQuery<{ adaResource: AdaResource | null }>(\n `query AdaResource($id: ID!) {\n adaResource(id: $id) {\n ${RESOURCE_FIELDS}\n connection { ${CONNECTION_FIELDS} adapter { id name slug kind } }\n dependsOn { id name resourceType region state monthlyCost }\n }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.adaResource;\n },\n enabled: Boolean(id),\n staleTime: STALE,\n });\n};\n\n// ============================================================================\n// Policies\n// ============================================================================\n\nexport interface PolicyListFilter {\n isActive?: boolean;\n kind?: AdaPolicyKind;\n pagination?: PaginationInput;\n}\n\nexport const usePolicies = (filter: PolicyListFilter = {}) => {\n const { apiGatewayUrl } = useAdapterCloud();\n return useQuery({\n queryKey: adaKeys.policies(filter as Record<string, unknown>),\n queryFn: async () => {\n const result = await adaQuery<{ adaListPolicies: AdaPolicyPage }>(\n `query AdaListPolicies($isActive: Boolean, $kind: AdaPolicyKind, $pagination: PaginationInput) {\n adaListPolicies(isActive: $isActive, kind: $kind, pagination: $pagination) {\n items { ${POLICY_FIELDS} }\n pageInfo { cursor hasMore }\n }\n }`,\n {\n isActive: filter.isActive,\n kind: filter.kind,\n pagination: filter.pagination,\n },\n apiGatewayUrl\n );\n return result.adaListPolicies;\n },\n placeholderData: (prev) => prev,\n staleTime: STALE,\n });\n};\n\nexport const usePolicy = (id: string | undefined) => {\n const { apiGatewayUrl } = useAdapterCloud();\n return useQuery({\n queryKey: adaKeys.policy(id ?? ''),\n queryFn: async () => {\n const result = await adaQuery<{ adaPolicy: AdaPolicy | null }>(\n `query AdaPolicy($id: ID!) {\n adaPolicy(id: $id) {\n ${POLICY_FIELDS}\n violations { ${VIOLATION_FIELDS} }\n }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.adaPolicy;\n },\n enabled: Boolean(id),\n staleTime: STALE,\n });\n};\n\nexport const useCreatePolicy = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAdapterCloud();\n return useMutation({\n mutationFn: async (input: AdaCreatePolicyInput) => {\n const result = await adaQuery<{ adaCreatePolicy: AdaPolicy }>(\n `mutation AdaCreatePolicy($input: AdaCreatePolicyInput!) {\n adaCreatePolicy(input: $input) { ${POLICY_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.adaCreatePolicy;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: [...adaKeys.all, 'policies'] });\n },\n });\n};\n\nexport const useUpdatePolicy = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAdapterCloud();\n return useMutation({\n mutationFn: async ({ id, input }: { id: string; input: AdaUpdatePolicyInput }) => {\n const result = await adaQuery<{ adaUpdatePolicy: AdaPolicy }>(\n `mutation AdaUpdatePolicy($id: ID!, $input: AdaUpdatePolicyInput!) {\n adaUpdatePolicy(id: $id, input: $input) { ${POLICY_FIELDS} }\n }`,\n { id, input },\n apiGatewayUrl\n );\n return result.adaUpdatePolicy;\n },\n onSuccess: (policy) => {\n notify.success('Policy updated');\n void queryClient.invalidateQueries({ queryKey: [...adaKeys.all, 'policies'] });\n void queryClient.invalidateQueries({ queryKey: adaKeys.policy(policy.id) });\n },\n });\n};\n\nexport const useArchivePolicy = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAdapterCloud();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await adaQuery<{ adaArchivePolicy: boolean }>(\n `mutation AdaArchivePolicy($id: ID!) { adaArchivePolicy(id: $id) }`,\n { id },\n apiGatewayUrl\n );\n return result.adaArchivePolicy;\n },\n onSuccess: () => {\n void queryClient.invalidateQueries({ queryKey: [...adaKeys.all, 'policies'] });\n },\n });\n};\n\n// ============================================================================\n// Violations\n// ============================================================================\n\nexport interface ViolationListFilter {\n policyId?: string;\n resourceId?: string;\n status?: AdaViolationStatus;\n pagination?: PaginationInput;\n}\n\nexport const useViolations = (filter: ViolationListFilter = {}) => {\n const { apiGatewayUrl } = useAdapterCloud();\n return useQuery({\n queryKey: adaKeys.violations(filter as Record<string, unknown>),\n queryFn: async () => {\n const result = await adaQuery<{ adaListViolations: AdaPolicyViolationPage }>(\n `query AdaListViolations($policyId: ID, $resourceId: ID, $status: AdaViolationStatus, $pagination: PaginationInput) {\n adaListViolations(policyId: $policyId, resourceId: $resourceId, status: $status, pagination: $pagination) {\n items {\n ${VIOLATION_FIELDS}\n policy { id name kind severity }\n }\n pageInfo { ${PAGE_INFO_FIELDS} }\n }\n }`,\n {\n policyId: filter.policyId,\n resourceId: filter.resourceId,\n status: filter.status,\n pagination: filter.pagination,\n },\n apiGatewayUrl\n );\n return result.adaListViolations;\n },\n placeholderData: (prev) => prev,\n staleTime: STALE,\n });\n};\n\nexport const useResolveViolation = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAdapterCloud();\n return useMutation({\n mutationFn: async ({\n id,\n status,\n waiverReason,\n }: {\n id: string;\n status: AdaViolationStatus;\n waiverReason?: string;\n }) => {\n const result = await adaQuery<{ adaResolveViolation: AdaPolicyViolation }>(\n `mutation AdaResolveViolation($id: ID!, $status: AdaViolationStatus!, $waiverReason: String) {\n adaResolveViolation(id: $id, status: $status, waiverReason: $waiverReason) {\n ${VIOLATION_FIELDS}\n }\n }`,\n { id, status, waiverReason },\n apiGatewayUrl\n );\n return result.adaResolveViolation;\n },\n onSuccess: (violation) => {\n const label: Record<string, string> = {\n ACKNOWLEDGED: 'Violation acknowledged',\n RESOLVED: 'Violation resolved',\n WAIVED: 'Violation waived',\n OPEN: 'Violation reopened',\n };\n notify.success(label[violation.status] ?? 'Violation updated');\n void queryClient.invalidateQueries({ queryKey: [...adaKeys.all, 'violations'] });\n },\n });\n};\n\n// ============================================================================\n// Drift\n// ============================================================================\n\nexport interface DriftListFilter {\n resourceId?: string;\n status?: AdaDriftStatus;\n}\n\nexport const useDriftRecords = (filter: DriftListFilter = {}) => {\n const { apiGatewayUrl } = useAdapterCloud();\n return useQuery({\n queryKey: adaKeys.drift(filter as Record<string, unknown>),\n queryFn: async () => {\n // adaListDriftRecords returns AdaDriftRecordConnection (items + pageInfo),\n // matching every other ada*List query — the drift fields must be\n // requested under `items`, not directly on the connection.\n const result = await adaQuery<{ adaListDriftRecords: AdaDriftRecordPage }>(\n `query AdaListDriftRecords($resourceId: ID, $status: AdaDriftStatus, $pagination: PaginationInput) {\n adaListDriftRecords(resourceId: $resourceId, status: $status, pagination: $pagination) {\n items { ${DRIFT_FIELDS} }\n pageInfo { ${PAGE_INFO_FIELDS} }\n }\n }`,\n {\n resourceId: filter.resourceId,\n status: filter.status,\n // Callers historically relied on an unpaginated \"all matching drift\"\n // result (see DriftListPage) — request the server's page-size\n // ceiling (MAX_LIMIT in wspace-adaptercloud-svc's pagination utils)\n // explicitly rather than relying on the smaller default of 50.\n pagination: { limit: 100 },\n },\n apiGatewayUrl\n );\n return result.adaListDriftRecords.items;\n },\n staleTime: STALE,\n });\n};\n\nexport const useRemediateDrift = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAdapterCloud();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await adaQuery<{ adaRemediateDrift: AdaDriftRecord }>(\n `mutation AdaRemediateDrift($id: ID!) {\n adaRemediateDrift(id: $id) { ${DRIFT_FIELDS} }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.adaRemediateDrift;\n },\n onSuccess: () => {\n notify.success('Drift marked remediated');\n void queryClient.invalidateQueries({ queryKey: [...adaKeys.all, 'drift'] });\n void queryClient.invalidateQueries({ queryKey: [...adaKeys.all, 'resources'] });\n },\n });\n};\n\n// ============================================================================\n// Sync runs\n// ============================================================================\n\nexport interface SyncRunListFilter {\n connectionId?: string;\n status?: AdaSyncStatus;\n pagination?: PaginationInput;\n}\n\nexport const useSyncRuns = (filter: SyncRunListFilter = {}) => {\n const { apiGatewayUrl } = useAdapterCloud();\n return useQuery({\n queryKey: adaKeys.syncRuns(filter as Record<string, unknown>),\n queryFn: async () => {\n const result = await adaQuery<{ adaListSyncRuns: AdaSyncRunPage }>(\n `query AdaListSyncRuns($connectionId: ID, $status: AdaSyncStatus, $pagination: PaginationInput) {\n adaListSyncRuns(connectionId: $connectionId, status: $status, pagination: $pagination) {\n items {\n ${SYNC_RUN_FIELDS}\n connection { id name adapter { id kind } }\n }\n pageInfo { ${PAGE_INFO_FIELDS} }\n }\n }`,\n {\n connectionId: filter.connectionId,\n status: filter.status,\n pagination: filter.pagination,\n },\n apiGatewayUrl\n );\n return result.adaListSyncRuns;\n },\n placeholderData: (prev) => prev,\n staleTime: STALE,\n });\n};\n\nexport const useStartSyncRun = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAdapterCloud();\n return useMutation({\n mutationFn: async (input: AdaStartSyncRunInput) => {\n const result = await adaQuery<{ adaStartSyncRun: AdaSyncRun }>(\n `mutation AdaStartSyncRun($input: AdaStartSyncRunInput!) {\n adaStartSyncRun(input: $input) { ${SYNC_RUN_FIELDS} }\n }`,\n { input },\n apiGatewayUrl\n );\n return result.adaStartSyncRun;\n },\n onSuccess: () => {\n notify.success('Sync run started');\n void queryClient.invalidateQueries({ queryKey: [...adaKeys.all, 'sync-runs'] });\n void queryClient.invalidateQueries({ queryKey: [...adaKeys.all, 'connections'] });\n },\n });\n};\n\nexport const useCancelSyncRun = () => {\n const queryClient = useQueryClient();\n const { apiGatewayUrl } = useAdapterCloud();\n return useMutation({\n mutationFn: async (id: string) => {\n const result = await adaQuery<{ adaCancelSyncRun: AdaSyncRun }>(\n `mutation AdaCancelSyncRun($id: ID!) {\n adaCancelSyncRun(id: $id) { ${SYNC_RUN_FIELDS} }\n }`,\n { id },\n apiGatewayUrl\n );\n return result.adaCancelSyncRun;\n },\n onSuccess: () => {\n notify.success('Sync run cancelled');\n void queryClient.invalidateQueries({ queryKey: [...adaKeys.all, 'sync-runs'] });\n },\n });\n};\n\n// ============================================================================\n// FinOps — cost\n// ============================================================================\n\nexport const useCostSummary = (connectionId?: string) => {\n const { apiGatewayUrl } = useAdapterCloud();\n return useQuery({\n queryKey: adaKeys.costSummary(connectionId),\n queryFn: async () => {\n const result = await adaQuery<{ adaCostSummary: AdaCostSummary }>(\n `query AdaCostSummary($connectionId: ID) {\n adaCostSummary(connectionId: $connectionId) {\n currency total\n lines { service total }\n }\n }`,\n { connectionId },\n apiGatewayUrl\n );\n return result.adaCostSummary;\n },\n staleTime: STALE,\n });\n};\n\nexport interface CostRecordListFilter {\n connectionId?: string;\n resourceId?: string;\n service?: string;\n}\n\nexport const LIST_COST_RECORDS_QUERY = `query AdaListCostRecords($connectionId: ID, $resourceId: ID, $service: String, $pagination: PaginationInput) {\n adaListCostRecords(connectionId: $connectionId, resourceId: $resourceId, service: $service, pagination: $pagination) {\n items {\n id service amount currency periodStart periodEnd breakdown\n connectionId resourceId workspaceId createdAt updatedAt\n resource { id name }\n connection { id name }\n }\n pageInfo { ${PAGE_INFO_FIELDS} }\n }\n}`;\n\nexport const useCostRecords = (filter: CostRecordListFilter = {}) => {\n const { apiGatewayUrl } = useAdapterCloud();\n return useQuery({\n queryKey: adaKeys.costRecords(filter as Record<string, unknown>),\n queryFn: async () => {\n const items: AdaCostRecord[] = [];\n let offset = 0;\n for (;;) {\n const result = await adaQuery<{\n adaListCostRecords: { items: AdaCostRecord[]; pageInfo: { hasMore: boolean } };\n }>(\n LIST_COST_RECORDS_QUERY,\n {\n connectionId: filter.connectionId,\n resourceId: filter.resourceId,\n service: filter.service,\n pagination: { limit: 100, offset },\n },\n apiGatewayUrl\n );\n const page = result.adaListCostRecords;\n items.push(...page.items);\n if (!page.pageInfo.hasMore || page.items.length === 0) return items;\n offset += page.items.length;\n }\n },\n staleTime: STALE,\n });\n};\n\n// ============================================================================\n// Topology\n// ============================================================================\n\nexport interface TopologyFilter {\n resourceId?: string;\n kind?: AdaEdgeKind;\n}\n\nconst TOPOLOGY_PAGE_SIZE = 100;\n\n/**\n * Load every resource needed by the estate graph. The normal inventory hook is\n * intentionally page-oriented; a dependency graph cannot silently drop nodes\n * after the first page without producing incorrect impact results.\n */\nexport const useTopologyResources = () => {\n const { apiGatewayUrl } = useAdapterCloud();\n return useQuery({\n queryKey: adaKeys.topologyResources(),\n queryFn: async () => {\n const items: AdaResource[] = [];\n let offset = 0;\n\n for (;;) {\n const result = await adaQuery<{ adaListResources: AdaResourcePage }>(\n `query AdaTopologyResources($pagination: PaginationInput) {\n adaListResources(pagination: $pagination) {\n items {\n ${RESOURCE_FIELDS}\n connection { id name }\n }\n pageInfo { ${PAGE_INFO_FIELDS} }\n }\n }`,\n { pagination: { limit: TOPOLOGY_PAGE_SIZE, offset } },\n apiGatewayUrl\n );\n const page = result.adaListResources;\n items.push(...page.items);\n if (!page.pageInfo.hasMore || page.items.length === 0) return items;\n offset += page.items.length;\n }\n },\n staleTime: STALE,\n });\n};\n\n/**\n * The estate's dependency edges (`adaListTopologyEdges`). Consumers pair this\n * with `useResources` to render the topology graph — edges reference resources\n * by id, resources supply the node labels/state/type.\n */\nexport const useTopology = (filter: TopologyFilter = {}) => {\n const { apiGatewayUrl } = useAdapterCloud();\n return useQuery({\n queryKey: adaKeys.topology(filter as Record<string, unknown>),\n queryFn: async () => {\n const items: AdaTopologyEdge[] = [];\n let offset = 0;\n\n for (;;) {\n const result = await adaQuery<{\n adaListTopologyEdges: { items: AdaTopologyEdge[]; pageInfo: { hasMore: boolean } };\n }>(\n `query AdaListTopologyEdges($resourceId: ID, $kind: AdaEdgeKind, $pagination: PaginationInput) {\n adaListTopologyEdges(resourceId: $resourceId, kind: $kind, pagination: $pagination) {\n items {\n id fromResourceId toResourceId kind bidirectional weight attributes\n workspaceId createdAt updatedAt\n }\n pageInfo { ${PAGE_INFO_FIELDS} }\n }\n }`,\n {\n resourceId: filter.resourceId,\n kind: filter.kind,\n pagination: { limit: TOPOLOGY_PAGE_SIZE, offset },\n },\n apiGatewayUrl\n );\n const page = result.adaListTopologyEdges;\n items.push(...page.items);\n if (!page.pageInfo.hasMore || page.items.length === 0) return items;\n offset += page.items.length;\n }\n },\n staleTime: STALE,\n });\n};\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ConnectionDetailPage.d.ts","sourceRoot":"","sources":["../../../../src/adaptercloud/pages/connections/ConnectionDetailPage.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAiCH,wBAAgB,oBAAoB,gCAoUnC"}
1
+ {"version":3,"file":"ConnectionDetailPage.d.ts","sourceRoot":"","sources":["../../../../src/adaptercloud/pages/connections/ConnectionDetailPage.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAqCH,wBAAgB,oBAAoB,gCA2VnC"}
@@ -6,192 +6,204 @@ import { DataState as c } from "../../components/DataState.js";
6
6
  import { useConnection as l, useDisableConnection as u, useSetConnectionStatus as d, useStartSyncRun as f } from "../../hooks/useAdapterCloudApi.js";
7
7
  import { formatDate as p } from "../../utils/formatters.js";
8
8
  import { ConfirmDialog as m } from "../../components/ConfirmDialog.js";
9
- import { canStartConnectionSync as h } from "./connectionSync.js";
10
- import { useCallback as g, useState as _ } from "react";
11
- import { useI18n as v } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
12
- import { ArrowLeft as y, Ban as b, Loader2 as x, Pencil as S, Play as C, RefreshCw as w, Server as T } from "lucide-react";
13
- import { useParams as E } from "react-router";
14
- import { jsx as D, jsxs as O } from "react/jsx-runtime";
15
- import { GlassCard as k } from "@burdenoff/fe-libs/ui";
9
+ import { canStartConnectionSync as h, canStartConnectionSyncKind as g, isConnectionSyncKindExecutable as _ } from "./connectionSync.js";
10
+ import { useCallback as v, useState as y } from "react";
11
+ import { useI18n as b } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
12
+ import { ArrowLeft as x, Ban as S, Loader2 as C, Pencil as w, Play as T, RefreshCw as E, Server as D } from "lucide-react";
13
+ import { useParams as O } from "react-router";
14
+ import { jsx as k, jsxs as A } from "react/jsx-runtime";
15
+ import { GlassCard as j } from "@burdenoff/fe-libs/ui";
16
16
  //#region src/adaptercloud/pages/connections/ConnectionDetailPage.tsx
17
- var A = [
17
+ var M = [
18
18
  "CONNECTED",
19
19
  "DEGRADED",
20
20
  "ERROR",
21
21
  "PENDING"
22
- ], j = [
22
+ ], N = [
23
23
  "DISCOVERY",
24
24
  "RECONCILE",
25
25
  "COST_INGEST",
26
26
  "FULL"
27
27
  ];
28
- function M() {
29
- let { id: M } = E(), { navigateTo: N } = e(), { t: P } = v(), F = g((e, t) => {
30
- let n = P(e);
28
+ function P() {
29
+ let { id: P } = O(), { navigateTo: F } = e(), { t: I } = b(), L = v((e, t) => {
30
+ let n = I(e);
31
31
  return n === e ? t : n;
32
- }, [P]), I = l(M), L = d(), R = u(), z = f(), B = I.data, V = B ? h(B.status) : !1, [H, U] = _(null), [W, G] = _(null), [K, q] = _(!1), J = g((e) => G(e instanceof Error ? e.message : "Action failed. Please try again."), []), Y = g((e) => {
33
- M && (G(null), L.mutate({
34
- id: M,
32
+ }, [I]), R = l(P), z = d(), B = u(), V = f(), H = R.data, U = H ? h(H.status) : !1, [W, G] = y(null), [K, q] = y(null), [J, Y] = y(!1), X = v((e) => q(e instanceof Error ? e.message : "Action failed. Please try again."), []), Z = v((e) => {
33
+ P && (q(null), z.mutate({
34
+ id: P,
35
35
  status: e
36
- }, { onError: J }));
36
+ }, { onError: X }));
37
37
  }, [
38
- M,
39
- L,
40
- J
41
- ]), X = g(() => {
42
- M && (G(null), R.mutate(M, {
43
- onSuccess: () => q(!1),
44
- onError: J
38
+ P,
39
+ z,
40
+ X
41
+ ]), Q = v(() => {
42
+ P && (q(null), B.mutate(P, {
43
+ onSuccess: () => Y(!1),
44
+ onError: X
45
45
  }));
46
46
  }, [
47
- M,
48
- R,
49
- J
50
- ]), Z = g((e) => {
51
- !M || !V || (G(null), U(e), z.mutate({
52
- connectionId: M,
47
+ P,
48
+ B,
49
+ X
50
+ ]), $ = v((e) => {
51
+ !P || !H || !g(H.status, e) || (q(null), G(e), V.mutate({
52
+ connectionId: P,
53
53
  kind: e
54
54
  }, {
55
55
  onSuccess: () => {
56
- U(null), N("/sync-runs");
56
+ G(null), F("/sync-runs");
57
57
  },
58
58
  onError: (e) => {
59
- U(null), J(e);
59
+ G(null), X(e);
60
60
  }
61
61
  }));
62
62
  }, [
63
- M,
63
+ P,
64
+ H,
64
65
  V,
65
- z,
66
- N,
67
- J
66
+ F,
67
+ X
68
68
  ]);
69
- return /* @__PURE__ */ O(t, {
70
- title: B?.name ?? F("adaptercloud.connections.detailTitle", "Connection"),
71
- description: B?.adapter?.name,
72
- actions: /* @__PURE__ */ O("div", {
69
+ return /* @__PURE__ */ A(t, {
70
+ title: H?.name ?? L("adaptercloud.connections.detailTitle", "Connection"),
71
+ description: H?.adapter?.name,
72
+ actions: /* @__PURE__ */ A("div", {
73
73
  className: "flex items-center gap-2",
74
- children: [/* @__PURE__ */ O("button", {
74
+ children: [/* @__PURE__ */ A("button", {
75
75
  type: "button",
76
- onClick: () => N("/connections"),
76
+ onClick: () => F("/connections"),
77
77
  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",
78
- children: [/* @__PURE__ */ D(y, { className: "h-4 w-4" }), F("adaptercloud.common.back", "Back")]
79
- }), B && /* @__PURE__ */ O("button", {
78
+ children: [/* @__PURE__ */ k(x, { className: "h-4 w-4" }), L("adaptercloud.common.back", "Back")]
79
+ }), H && /* @__PURE__ */ A("button", {
80
80
  type: "button",
81
- onClick: () => N(`/connections/${B.id}/edit`),
81
+ onClick: () => F(`/connections/${H.id}/edit`),
82
82
  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",
83
- children: [/* @__PURE__ */ D(S, { className: "h-4 w-4" }), F("adaptercloud.common.edit", "Edit")]
83
+ children: [/* @__PURE__ */ k(w, { className: "h-4 w-4" }), L("adaptercloud.common.edit", "Edit")]
84
84
  })]
85
85
  }),
86
- children: [/* @__PURE__ */ D(c, {
87
- isLoading: I.isLoading,
88
- isError: I.isError,
89
- isEmpty: !I.isLoading && !B,
90
- error: I.error,
91
- onRetry: () => void I.refetch(),
92
- emptyTitle: F("adaptercloud.connections.notFound", "Connection not found"),
93
- children: B && /* @__PURE__ */ O("div", {
86
+ children: [/* @__PURE__ */ k(c, {
87
+ isLoading: R.isLoading,
88
+ isError: R.isError,
89
+ isEmpty: !R.isLoading && !H,
90
+ error: R.error,
91
+ onRetry: () => void R.refetch(),
92
+ emptyTitle: L("adaptercloud.connections.notFound", "Connection not found"),
93
+ children: H && /* @__PURE__ */ A("div", {
94
94
  className: "space-y-6",
95
95
  children: [
96
- W && /* @__PURE__ */ D("p", {
96
+ K && /* @__PURE__ */ k("p", {
97
97
  role: "alert",
98
98
  "aria-live": "polite",
99
99
  className: "rounded-lg bg-status-error-bg-subtle px-3 py-2 text-sm text-status-error-text",
100
- children: W
100
+ children: K
101
101
  }),
102
- /* @__PURE__ */ O(k, {
102
+ /* @__PURE__ */ A(j, {
103
103
  className: "p-6",
104
104
  children: [
105
- /* @__PURE__ */ O("div", {
105
+ /* @__PURE__ */ A("div", {
106
106
  className: "mb-4 flex flex-wrap items-center gap-3",
107
- children: [/* @__PURE__ */ D(s, { status: B.status }), /* @__PURE__ */ D("span", {
107
+ children: [/* @__PURE__ */ k(s, { status: H.status }), /* @__PURE__ */ k("span", {
108
108
  className: "inline-flex items-center rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs font-medium text-text-secondary",
109
- children: n[B.authMethod]
109
+ children: n[H.authMethod]
110
110
  })]
111
111
  }),
112
- /* @__PURE__ */ O("dl", {
112
+ /* @__PURE__ */ A("dl", {
113
113
  className: "grid grid-cols-2 gap-4 text-sm sm:grid-cols-4",
114
114
  children: [
115
- /* @__PURE__ */ O("div", { children: [/* @__PURE__ */ D("dt", {
115
+ /* @__PURE__ */ A("div", { children: [/* @__PURE__ */ k("dt", {
116
116
  className: "text-text-secondary",
117
- children: F("adaptercloud.connections.region", "Region")
118
- }), /* @__PURE__ */ D("dd", {
117
+ children: L("adaptercloud.connections.region", "Region")
118
+ }), /* @__PURE__ */ k("dd", {
119
119
  className: "mt-0.5 font-medium text-text-primary",
120
- children: B.region ?? "—"
120
+ children: H.region ?? "—"
121
121
  })] }),
122
- /* @__PURE__ */ O("div", { children: [/* @__PURE__ */ D("dt", {
122
+ /* @__PURE__ */ A("div", { children: [/* @__PURE__ */ k("dt", {
123
123
  className: "text-text-secondary",
124
- children: F("adaptercloud.connections.environment", "Environment")
125
- }), /* @__PURE__ */ D("dd", {
124
+ children: L("adaptercloud.connections.environment", "Environment")
125
+ }), /* @__PURE__ */ k("dd", {
126
126
  className: "mt-0.5 font-medium text-text-primary",
127
- children: B.environment ?? "—"
127
+ children: H.environment ?? "—"
128
128
  })] }),
129
- /* @__PURE__ */ O("div", { children: [/* @__PURE__ */ D("dt", {
129
+ /* @__PURE__ */ A("div", { children: [/* @__PURE__ */ k("dt", {
130
130
  className: "text-text-secondary",
131
- children: F("adaptercloud.connections.resourceCount", "Resources")
132
- }), /* @__PURE__ */ D("dd", {
131
+ children: L("adaptercloud.connections.resourceCount", "Resources")
132
+ }), /* @__PURE__ */ k("dd", {
133
133
  className: "mt-0.5 font-medium tabular-nums text-text-primary",
134
- children: B.resourceCount
134
+ children: H.resourceCount
135
135
  })] }),
136
- /* @__PURE__ */ O("div", { children: [/* @__PURE__ */ D("dt", {
136
+ /* @__PURE__ */ A("div", { children: [/* @__PURE__ */ k("dt", {
137
137
  className: "text-text-secondary",
138
- children: F("adaptercloud.connections.lastSynced", "Last synced")
139
- }), /* @__PURE__ */ D("dd", {
138
+ children: L("adaptercloud.connections.lastSynced", "Last synced")
139
+ }), /* @__PURE__ */ k("dd", {
140
140
  className: "mt-0.5 font-medium text-text-primary",
141
- children: B.lastSyncedAt ? p(B.lastSyncedAt) : "—"
141
+ children: H.lastSyncedAt ? p(H.lastSyncedAt) : "—"
142
142
  })] })
143
143
  ]
144
144
  }),
145
- B.lastError && /* @__PURE__ */ D("p", {
145
+ H.lastError && /* @__PURE__ */ k("p", {
146
146
  className: "mt-4 rounded-lg bg-status-error-bg-subtle px-3 py-2 text-sm text-status-error-text",
147
- children: B.lastError
147
+ children: H.lastError
148
148
  }),
149
- /* @__PURE__ */ O("div", {
149
+ /* @__PURE__ */ A("div", {
150
150
  className: "mt-5 border-t border-border-subtle pt-5",
151
- children: [/* @__PURE__ */ D("h3", {
151
+ children: [/* @__PURE__ */ k("h3", {
152
152
  className: "mb-3 text-sm font-semibold text-text-primary",
153
- children: F("adaptercloud.connections.setHealth", "Set health")
154
- }), /* @__PURE__ */ O("div", {
153
+ children: L("adaptercloud.connections.setHealth", "Set health")
154
+ }), /* @__PURE__ */ A("div", {
155
155
  className: "flex flex-wrap gap-2",
156
- children: [A.map((e) => /* @__PURE__ */ D("button", {
156
+ children: [M.map((e) => /* @__PURE__ */ k("button", {
157
157
  type: "button",
158
- disabled: L.isPending || B.status === e,
159
- onClick: () => Y(e),
158
+ disabled: z.isPending || H.status === e,
159
+ onClick: () => Z(e),
160
160
  className: "rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-text-primary transition-colors hover:bg-accent disabled:cursor-not-allowed disabled:opacity-40",
161
161
  children: r[e]
162
- }, e)), B.status !== "DISABLED" && /* @__PURE__ */ O("button", {
162
+ }, e)), H.status !== "DISABLED" && /* @__PURE__ */ A("button", {
163
163
  type: "button",
164
- disabled: R.isPending,
165
- onClick: () => q(!0),
164
+ disabled: B.isPending,
165
+ onClick: () => Y(!0),
166
166
  className: "inline-flex items-center gap-1.5 rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-status-error-text transition-colors hover:bg-status-error-bg-subtle disabled:opacity-40",
167
- children: [/* @__PURE__ */ D(b, { className: "h-3.5 w-3.5" }), F("adaptercloud.connections.disable", "Disable")]
167
+ children: [/* @__PURE__ */ k(S, { className: "h-3.5 w-3.5" }), L("adaptercloud.connections.disable", "Disable")]
168
168
  })]
169
169
  })]
170
170
  }),
171
- /* @__PURE__ */ O("div", {
171
+ /* @__PURE__ */ A("div", {
172
172
  className: "mt-5 border-t border-border-subtle pt-5",
173
173
  children: [
174
- /* @__PURE__ */ O("h3", {
174
+ /* @__PURE__ */ A("h3", {
175
175
  className: "mb-3 flex items-center gap-2 text-sm font-semibold text-text-primary",
176
- children: [/* @__PURE__ */ D(w, { className: "h-4 w-4" }), F("adaptercloud.connections.startSync", "Start a sync run")]
176
+ children: [/* @__PURE__ */ k(E, { className: "h-4 w-4" }), L("adaptercloud.connections.startSync", "Start a sync run")]
177
177
  }),
178
- !V && /* @__PURE__ */ D("p", {
178
+ !U && /* @__PURE__ */ k("p", {
179
179
  id: "disabled-connection-sync-help",
180
180
  className: "mb-3 text-sm text-text-secondary",
181
- children: F("adaptercloud.connections.disabledSyncHelp", "Sync runs are unavailable while this connection is disabled. Set its health to re-enable sync.")
181
+ children: L("adaptercloud.connections.disabledSyncHelp", "Sync runs are unavailable while this connection is disabled. Set its health to re-enable sync.")
182
+ }),
183
+ /* @__PURE__ */ k("p", {
184
+ id: "unsupported-sync-kind-help",
185
+ className: "mb-3 text-sm text-text-secondary",
186
+ children: L("adaptercloud.connections.syncModeAvailabilityHelp", "Discovery is executable today. Reconcile, Cost Ingest, and Full need distinct backend workers and are not available yet.")
182
187
  }),
183
- /* @__PURE__ */ D("div", {
188
+ /* @__PURE__ */ k("div", {
184
189
  className: "flex flex-wrap gap-2",
185
- children: j.map((e) => {
186
- let t = z.isPending && H === e;
187
- return /* @__PURE__ */ O("button", {
190
+ children: N.map((e) => {
191
+ let t = V.isPending && W === e, n = _(e);
192
+ return /* @__PURE__ */ A("button", {
188
193
  type: "button",
189
- disabled: z.isPending || !V,
190
- "aria-describedby": V ? void 0 : "disabled-connection-sync-help",
191
- title: V ? void 0 : F("adaptercloud.connections.disabledSyncTooltip", "Re-enable this connection before starting a sync run."),
192
- onClick: () => Z(e),
193
- 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 disabled:opacity-50",
194
- children: [t ? /* @__PURE__ */ D(x, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ D(C, { className: "h-4 w-4" }), o[e]]
194
+ disabled: V.isPending || !U || !n,
195
+ "aria-describedby": n ? U ? void 0 : "disabled-connection-sync-help" : "unsupported-sync-kind-help",
196
+ title: n ? U ? void 0 : L("adaptercloud.connections.disabledSyncTooltip", "Re-enable this connection before starting a sync run.") : L("adaptercloud.connections.unsupportedSyncModeTooltip", "This sync mode is not available yet because it needs a distinct backend worker."),
197
+ onClick: () => $(e),
198
+ 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 disabled:cursor-not-allowed disabled:opacity-50",
199
+ children: [
200
+ t ? /* @__PURE__ */ k(C, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ k(T, { className: "h-4 w-4" }),
201
+ o[e],
202
+ !n && /* @__PURE__ */ k("span", {
203
+ className: "rounded bg-bg-sunken px-1.5 py-0.5 text-[10px] font-normal text-text-secondary",
204
+ children: L("adaptercloud.connections.notAvailable", "Not available")
205
+ })
206
+ ]
195
207
  }, e);
196
208
  })
197
209
  })
@@ -199,75 +211,75 @@ function M() {
199
211
  })
200
212
  ]
201
213
  }),
202
- B.config != null && /* @__PURE__ */ O(k, {
214
+ H.config != null && /* @__PURE__ */ A(j, {
203
215
  className: "p-6",
204
- children: [/* @__PURE__ */ D("h3", {
216
+ children: [/* @__PURE__ */ k("h3", {
205
217
  className: "mb-3 text-sm font-semibold text-text-primary",
206
- children: F("adaptercloud.connections.config", "Configuration")
207
- }), /* @__PURE__ */ D("pre", {
218
+ children: L("adaptercloud.connections.config", "Configuration")
219
+ }), /* @__PURE__ */ k("pre", {
208
220
  className: "overflow-auto rounded-lg bg-bg-sunken p-4 text-xs text-text-secondary",
209
- children: JSON.stringify(B.config, null, 2)
221
+ children: JSON.stringify(H.config, null, 2)
210
222
  })]
211
223
  }),
212
- /* @__PURE__ */ O("section", { children: [/* @__PURE__ */ O("div", {
224
+ /* @__PURE__ */ A("section", { children: [/* @__PURE__ */ A("div", {
213
225
  className: "mb-3 flex items-center justify-between",
214
- children: [/* @__PURE__ */ D("h3", {
226
+ children: [/* @__PURE__ */ k("h3", {
215
227
  className: "text-base font-semibold text-text-primary",
216
- children: F("adaptercloud.connections.discoveredResources", "Discovered Resources")
217
- }), /* @__PURE__ */ D("button", {
228
+ children: L("adaptercloud.connections.discoveredResources", "Discovered Resources")
229
+ }), /* @__PURE__ */ k("button", {
218
230
  type: "button",
219
- onClick: () => N(`/resources?connectionId=${B.id}`),
231
+ onClick: () => F(`/resources?connectionId=${H.id}`),
220
232
  className: "text-sm font-medium text-accent-blue hover:underline",
221
- children: F("adaptercloud.common.viewAll", "View all")
233
+ children: L("adaptercloud.common.viewAll", "View all")
222
234
  })]
223
- }), B.resources && B.resources.length > 0 ? /* @__PURE__ */ D("div", {
235
+ }), H.resources && H.resources.length > 0 ? /* @__PURE__ */ k("div", {
224
236
  className: "divide-y divide-border rounded-xl border border-border-subtle bg-bg-surface",
225
- children: B.resources.slice(0, 10).map((e) => /* @__PURE__ */ O("button", {
237
+ children: H.resources.slice(0, 10).map((e) => /* @__PURE__ */ A("button", {
226
238
  type: "button",
227
- onClick: () => N(`/resources/${e.id}`),
239
+ onClick: () => F(`/resources/${e.id}`),
228
240
  className: "flex w-full items-center gap-3 px-4 py-3 text-left transition-colors hover:bg-accent/50",
229
241
  children: [
230
- /* @__PURE__ */ D(T, { className: "h-4 w-4 shrink-0 text-text-secondary" }),
231
- /* @__PURE__ */ O("div", {
242
+ /* @__PURE__ */ k(D, { className: "h-4 w-4 shrink-0 text-text-secondary" }),
243
+ /* @__PURE__ */ A("div", {
232
244
  className: "min-w-0 flex-1",
233
- children: [/* @__PURE__ */ D("p", {
245
+ children: [/* @__PURE__ */ k("p", {
234
246
  className: "truncate text-sm font-medium text-text-primary",
235
247
  children: e.name
236
- }), /* @__PURE__ */ O("p", {
248
+ }), /* @__PURE__ */ A("p", {
237
249
  className: "mt-0.5 text-xs text-text-secondary",
238
250
  children: [e.resourceType, e.region ? ` · ${e.region}` : ""]
239
251
  })]
240
252
  }),
241
- /* @__PURE__ */ D("span", {
253
+ /* @__PURE__ */ k("span", {
242
254
  className: "hidden text-xs text-text-secondary sm:inline",
243
255
  children: i(e.monthlyCost)
244
256
  }),
245
- /* @__PURE__ */ D(s, {
257
+ /* @__PURE__ */ k(s, {
246
258
  status: e.state,
247
259
  label: a[e.state]
248
260
  })
249
261
  ]
250
262
  }, e.id))
251
- }) : /* @__PURE__ */ D("p", {
263
+ }) : /* @__PURE__ */ k("p", {
252
264
  className: "rounded-xl border border-border-subtle bg-bg-surface px-4 py-6 text-center text-sm text-text-secondary",
253
- children: F("adaptercloud.connections.noResources", "No resources discovered yet. Start a discovery sync run.")
265
+ children: L("adaptercloud.connections.noResources", "No resources discovered yet. Start a discovery sync run.")
254
266
  })] })
255
267
  ]
256
268
  })
257
- }), /* @__PURE__ */ D(m, {
258
- open: K,
259
- onOpenChange: q,
260
- title: F("adaptercloud.connections.disableTitle", "Disable this connection?"),
261
- description: F("adaptercloud.connections.disablePrompt", "Disabling stops discovery and sync runs against this target. You can re-enable it later by setting its health."),
262
- confirmLabel: F("adaptercloud.connections.disable", "Disable"),
263
- cancelLabel: F("adaptercloud.common.cancel", "Cancel"),
264
- onConfirm: X,
265
- isPending: R.isPending,
269
+ }), /* @__PURE__ */ k(m, {
270
+ open: J,
271
+ onOpenChange: Y,
272
+ title: L("adaptercloud.connections.disableTitle", "Disable this connection?"),
273
+ description: L("adaptercloud.connections.disablePrompt", "Disabling stops discovery and sync runs against this target. You can re-enable it later by setting its health."),
274
+ confirmLabel: L("adaptercloud.connections.disable", "Disable"),
275
+ cancelLabel: L("adaptercloud.common.cancel", "Cancel"),
276
+ onConfirm: Q,
277
+ isPending: B.isPending,
266
278
  tone: "danger"
267
279
  })]
268
280
  });
269
281
  }
270
282
  //#endregion
271
- export { M as ConnectionDetailPage };
283
+ export { P as ConnectionDetailPage };
272
284
 
273
285
  //# sourceMappingURL=ConnectionDetailPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ConnectionDetailPage.js","names":[],"sources":["../../../../src/adaptercloud/pages/connections/ConnectionDetailPage.tsx"],"sourcesContent":["/**\n * Connection Detail Page\n * @module adaptercloud/pages/connections\n *\n * One connection (`adaConnection`) — its adapter, health, config, and the\n * resources it has discovered. Supports the validated health transition\n * (`adaSetConnectionStatus`), disable (`adaDisableConnection`), and starting a\n * sync run (`adaStartSyncRun`) against it.\n */\n\nimport { useCallback, useState } from 'react';\nimport { Loader2 } from 'lucide-react';\nimport { useParams } from 'react-router';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { ArrowLeft, Ban, Pencil, Play, RefreshCw, Server } 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 { ConfirmDialog } from '../../components/ConfirmDialog';\nimport { useAdapterCloud } from '../../context/AdapterCloudContext';\nimport {\n useConnection,\n useDisableConnection,\n useSetConnectionStatus,\n useStartSyncRun,\n} from '../../hooks/useAdapterCloudApi';\nimport {\n authMethodLabels,\n connectionStatusLabels,\n resourceStateLabels,\n syncKindLabels,\n} from '../../utils/domain';\nimport { formatDate } from '../../utils/formatters';\nimport { formatMoney } from '../../utils/domain';\nimport type { AdaConnectionStatus, AdaSyncKind } from '../../types';\nimport { canStartConnectionSync } from './connectionSync';\n\nconst TRANSITIONABLE: AdaConnectionStatus[] = ['CONNECTED', 'DEGRADED', 'ERROR', 'PENDING'];\nconst SYNC_KINDS: AdaSyncKind[] = ['DISCOVERY', 'RECONCILE', 'COST_INGEST', 'FULL'];\n\nexport function ConnectionDetailPage() {\n const { id } = useParams<{ id: string }>();\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 query = useConnection(id);\n const setStatus = useSetConnectionStatus();\n const disable = useDisableConnection();\n const startRun = useStartSyncRun();\n const conn = query.data;\n const syncEnabled = conn ? canStartConnectionSync(conn.status) : false;\n\n const [runningKind, setRunningKind] = useState<AdaSyncKind | null>(null);\n const [actionError, setActionError] = useState<string | null>(null);\n const [confirmDisableOpen, setConfirmDisableOpen] = useState(false);\n\n const onError = useCallback(\n (err: unknown) =>\n setActionError(err instanceof Error ? err.message : 'Action failed. Please try again.'),\n []\n );\n\n const handleSetStatus = useCallback(\n (newStatus: AdaConnectionStatus) => {\n if (!id) return;\n setActionError(null);\n setStatus.mutate({ id, status: newStatus }, { onError });\n },\n [id, setStatus, onError]\n );\n\n const handleDisable = useCallback(() => {\n if (!id) return;\n setActionError(null);\n disable.mutate(id, {\n onSuccess: () => setConfirmDisableOpen(false),\n onError,\n });\n }, [id, disable, onError]);\n\n const handleStartKind = useCallback(\n (kind: AdaSyncKind) => {\n if (!id || !syncEnabled) return;\n setActionError(null);\n setRunningKind(kind);\n startRun.mutate(\n { connectionId: id, kind },\n {\n onSuccess: () => {\n setRunningKind(null);\n navigateTo('/sync-runs');\n },\n onError: (err) => {\n setRunningKind(null);\n onError(err);\n },\n }\n );\n },\n [id, syncEnabled, startRun, navigateTo, onError]\n );\n\n return (\n <PageLayout\n title={conn?.name ?? t('adaptercloud.connections.detailTitle', 'Connection')}\n description={conn?.adapter?.name}\n actions={\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n onClick={() => navigateTo('/connections')}\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 <ArrowLeft className=\"h-4 w-4\" />\n {t('adaptercloud.common.back', 'Back')}\n </button>\n {conn && (\n <button\n type=\"button\"\n onClick={() => navigateTo(`/connections/${conn.id}/edit`)}\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 <Pencil className=\"h-4 w-4\" />\n {t('adaptercloud.common.edit', 'Edit')}\n </button>\n )}\n </div>\n }\n >\n <DataState\n isLoading={query.isLoading}\n isError={query.isError}\n isEmpty={!query.isLoading && !conn}\n error={query.error}\n onRetry={() => void query.refetch()}\n emptyTitle={t('adaptercloud.connections.notFound', 'Connection not found')}\n >\n {conn && (\n <div className=\"space-y-6\">\n {actionError && (\n <p\n role=\"alert\"\n aria-live=\"polite\"\n className=\"rounded-lg bg-status-error-bg-subtle px-3 py-2 text-sm text-status-error-text\"\n >\n {actionError}\n </p>\n )}\n\n {/* Health + actions */}\n <GlassCard className=\"p-6\">\n <div className=\"mb-4 flex flex-wrap items-center gap-3\">\n <StatusBadge status={conn.status} />\n <span className=\"inline-flex items-center rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs font-medium text-text-secondary\">\n {authMethodLabels[conn.authMethod]}\n </span>\n </div>\n\n <dl className=\"grid grid-cols-2 gap-4 text-sm sm:grid-cols-4\">\n <div>\n <dt className=\"text-text-secondary\">\n {t('adaptercloud.connections.region', 'Region')}\n </dt>\n <dd className=\"mt-0.5 font-medium text-text-primary\">{conn.region ?? '—'}</dd>\n </div>\n <div>\n <dt className=\"text-text-secondary\">\n {t('adaptercloud.connections.environment', 'Environment')}\n </dt>\n <dd className=\"mt-0.5 font-medium text-text-primary\">\n {conn.environment ?? '—'}\n </dd>\n </div>\n <div>\n <dt className=\"text-text-secondary\">\n {t('adaptercloud.connections.resourceCount', 'Resources')}\n </dt>\n <dd className=\"mt-0.5 font-medium tabular-nums text-text-primary\">\n {conn.resourceCount}\n </dd>\n </div>\n <div>\n <dt className=\"text-text-secondary\">\n {t('adaptercloud.connections.lastSynced', 'Last synced')}\n </dt>\n <dd className=\"mt-0.5 font-medium text-text-primary\">\n {conn.lastSyncedAt ? formatDate(conn.lastSyncedAt) : '—'}\n </dd>\n </div>\n </dl>\n\n {conn.lastError && (\n <p className=\"mt-4 rounded-lg bg-status-error-bg-subtle px-3 py-2 text-sm text-status-error-text\">\n {conn.lastError}\n </p>\n )}\n\n {/* Health transitions */}\n <div className=\"mt-5 border-t border-border-subtle pt-5\">\n <h3 className=\"mb-3 text-sm font-semibold text-text-primary\">\n {t('adaptercloud.connections.setHealth', 'Set health')}\n </h3>\n <div className=\"flex flex-wrap gap-2\">\n {TRANSITIONABLE.map((s) => (\n <button\n key={s}\n type=\"button\"\n disabled={setStatus.isPending || conn.status === s}\n onClick={() => handleSetStatus(s)}\n className=\"rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-text-primary transition-colors hover:bg-accent disabled:cursor-not-allowed disabled:opacity-40\"\n >\n {connectionStatusLabels[s]}\n </button>\n ))}\n {conn.status !== 'DISABLED' && (\n <button\n type=\"button\"\n disabled={disable.isPending}\n onClick={() => setConfirmDisableOpen(true)}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-status-error-text transition-colors hover:bg-status-error-bg-subtle disabled:opacity-40\"\n >\n <Ban className=\"h-3.5 w-3.5\" />\n {t('adaptercloud.connections.disable', 'Disable')}\n </button>\n )}\n </div>\n </div>\n\n {/* Start sync run */}\n <div className=\"mt-5 border-t border-border-subtle pt-5\">\n <h3 className=\"mb-3 flex items-center gap-2 text-sm font-semibold text-text-primary\">\n <RefreshCw className=\"h-4 w-4\" />\n {t('adaptercloud.connections.startSync', 'Start a sync run')}\n </h3>\n {!syncEnabled && (\n <p\n id=\"disabled-connection-sync-help\"\n className=\"mb-3 text-sm text-text-secondary\"\n >\n {t(\n 'adaptercloud.connections.disabledSyncHelp',\n 'Sync runs are unavailable while this connection is disabled. Set its health to re-enable sync.'\n )}\n </p>\n )}\n <div className=\"flex flex-wrap gap-2\">\n {SYNC_KINDS.map((k) => {\n const pending = startRun.isPending && runningKind === k;\n return (\n <button\n key={k}\n type=\"button\"\n disabled={startRun.isPending || !syncEnabled}\n aria-describedby={syncEnabled ? undefined : 'disabled-connection-sync-help'}\n title={\n syncEnabled\n ? undefined\n : t(\n 'adaptercloud.connections.disabledSyncTooltip',\n 'Re-enable this connection before starting a sync run.'\n )\n }\n onClick={() => handleStartKind(k)}\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 disabled:opacity-50\"\n >\n {pending ? (\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n ) : (\n <Play className=\"h-4 w-4\" />\n )}\n {syncKindLabels[k]}\n </button>\n );\n })}\n </div>\n </div>\n </GlassCard>\n\n {/* Config */}\n {conn.config != null && (\n <GlassCard className=\"p-6\">\n <h3 className=\"mb-3 text-sm font-semibold text-text-primary\">\n {t('adaptercloud.connections.config', 'Configuration')}\n </h3>\n <pre className=\"overflow-auto rounded-lg bg-bg-sunken p-4 text-xs text-text-secondary\">\n {JSON.stringify(conn.config, null, 2)}\n </pre>\n </GlassCard>\n )}\n\n {/* Resources */}\n <section>\n <div className=\"mb-3 flex items-center justify-between\">\n <h3 className=\"text-base font-semibold text-text-primary\">\n {t('adaptercloud.connections.discoveredResources', 'Discovered Resources')}\n </h3>\n <button\n type=\"button\"\n onClick={() => navigateTo(`/resources?connectionId=${conn.id}`)}\n className=\"text-sm font-medium text-accent-blue hover:underline\"\n >\n {t('adaptercloud.common.viewAll', 'View all')}\n </button>\n </div>\n {conn.resources && conn.resources.length > 0 ? (\n <div className=\"divide-y divide-border rounded-xl border border-border-subtle bg-bg-surface\">\n {conn.resources.slice(0, 10).map((r) => (\n <button\n key={r.id}\n type=\"button\"\n onClick={() => navigateTo(`/resources/${r.id}`)}\n className=\"flex w-full items-center gap-3 px-4 py-3 text-left transition-colors hover:bg-accent/50\"\n >\n <Server className=\"h-4 w-4 shrink-0 text-text-secondary\" />\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-sm font-medium text-text-primary\">{r.name}</p>\n <p className=\"mt-0.5 text-xs text-text-secondary\">\n {r.resourceType}\n {r.region ? ` · ${r.region}` : ''}\n </p>\n </div>\n <span className=\"hidden text-xs text-text-secondary sm:inline\">\n {formatMoney(r.monthlyCost)}\n </span>\n <StatusBadge status={r.state} label={resourceStateLabels[r.state]} />\n </button>\n ))}\n </div>\n ) : (\n <p className=\"rounded-xl border border-border-subtle bg-bg-surface px-4 py-6 text-center text-sm text-text-secondary\">\n {t(\n 'adaptercloud.connections.noResources',\n 'No resources discovered yet. Start a discovery sync run.'\n )}\n </p>\n )}\n </section>\n </div>\n )}\n </DataState>\n\n <ConfirmDialog\n open={confirmDisableOpen}\n onOpenChange={setConfirmDisableOpen}\n title={t('adaptercloud.connections.disableTitle', 'Disable this connection?')}\n description={t(\n 'adaptercloud.connections.disablePrompt',\n 'Disabling stops discovery and sync runs against this target. You can re-enable it later by setting its health.'\n )}\n confirmLabel={t('adaptercloud.connections.disable', 'Disable')}\n cancelLabel={t('adaptercloud.common.cancel', 'Cancel')}\n onConfirm={handleDisable}\n isPending={disable.isPending}\n tone=\"danger\"\n />\n </PageLayout>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ConnectionDetailPage.js","names":[],"sources":["../../../../src/adaptercloud/pages/connections/ConnectionDetailPage.tsx"],"sourcesContent":["/**\n * Connection Detail Page\n * @module adaptercloud/pages/connections\n *\n * One connection (`adaConnection`) — its adapter, health, config, and the\n * resources it has discovered. Supports the validated health transition\n * (`adaSetConnectionStatus`), disable (`adaDisableConnection`), and starting a\n * sync run (`adaStartSyncRun`) against it.\n */\n\nimport { useCallback, useState } from 'react';\nimport { Loader2 } from 'lucide-react';\nimport { useParams } from 'react-router';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { ArrowLeft, Ban, Pencil, Play, RefreshCw, Server } 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 { ConfirmDialog } from '../../components/ConfirmDialog';\nimport { useAdapterCloud } from '../../context/AdapterCloudContext';\nimport {\n useConnection,\n useDisableConnection,\n useSetConnectionStatus,\n useStartSyncRun,\n} from '../../hooks/useAdapterCloudApi';\nimport {\n authMethodLabels,\n connectionStatusLabels,\n resourceStateLabels,\n syncKindLabels,\n} from '../../utils/domain';\nimport { formatDate } from '../../utils/formatters';\nimport { formatMoney } from '../../utils/domain';\nimport type { AdaConnectionStatus, AdaSyncKind } from '../../types';\nimport {\n canStartConnectionSync,\n canStartConnectionSyncKind,\n isConnectionSyncKindExecutable,\n} from './connectionSync';\n\nconst TRANSITIONABLE: AdaConnectionStatus[] = ['CONNECTED', 'DEGRADED', 'ERROR', 'PENDING'];\nconst SYNC_KINDS: AdaSyncKind[] = ['DISCOVERY', 'RECONCILE', 'COST_INGEST', 'FULL'];\n\nexport function ConnectionDetailPage() {\n const { id } = useParams<{ id: string }>();\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 query = useConnection(id);\n const setStatus = useSetConnectionStatus();\n const disable = useDisableConnection();\n const startRun = useStartSyncRun();\n const conn = query.data;\n const syncEnabled = conn ? canStartConnectionSync(conn.status) : false;\n\n const [runningKind, setRunningKind] = useState<AdaSyncKind | null>(null);\n const [actionError, setActionError] = useState<string | null>(null);\n const [confirmDisableOpen, setConfirmDisableOpen] = useState(false);\n\n const onError = useCallback(\n (err: unknown) =>\n setActionError(err instanceof Error ? err.message : 'Action failed. Please try again.'),\n []\n );\n\n const handleSetStatus = useCallback(\n (newStatus: AdaConnectionStatus) => {\n if (!id) return;\n setActionError(null);\n setStatus.mutate({ id, status: newStatus }, { onError });\n },\n [id, setStatus, onError]\n );\n\n const handleDisable = useCallback(() => {\n if (!id) return;\n setActionError(null);\n disable.mutate(id, {\n onSuccess: () => setConfirmDisableOpen(false),\n onError,\n });\n }, [id, disable, onError]);\n\n const handleStartKind = useCallback(\n (kind: AdaSyncKind) => {\n if (!id || !conn || !canStartConnectionSyncKind(conn.status, kind)) return;\n setActionError(null);\n setRunningKind(kind);\n startRun.mutate(\n { connectionId: id, kind },\n {\n onSuccess: () => {\n setRunningKind(null);\n navigateTo('/sync-runs');\n },\n onError: (err) => {\n setRunningKind(null);\n onError(err);\n },\n }\n );\n },\n [id, conn, startRun, navigateTo, onError]\n );\n\n return (\n <PageLayout\n title={conn?.name ?? t('adaptercloud.connections.detailTitle', 'Connection')}\n description={conn?.adapter?.name}\n actions={\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n onClick={() => navigateTo('/connections')}\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 <ArrowLeft className=\"h-4 w-4\" />\n {t('adaptercloud.common.back', 'Back')}\n </button>\n {conn && (\n <button\n type=\"button\"\n onClick={() => navigateTo(`/connections/${conn.id}/edit`)}\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 <Pencil className=\"h-4 w-4\" />\n {t('adaptercloud.common.edit', 'Edit')}\n </button>\n )}\n </div>\n }\n >\n <DataState\n isLoading={query.isLoading}\n isError={query.isError}\n isEmpty={!query.isLoading && !conn}\n error={query.error}\n onRetry={() => void query.refetch()}\n emptyTitle={t('adaptercloud.connections.notFound', 'Connection not found')}\n >\n {conn && (\n <div className=\"space-y-6\">\n {actionError && (\n <p\n role=\"alert\"\n aria-live=\"polite\"\n className=\"rounded-lg bg-status-error-bg-subtle px-3 py-2 text-sm text-status-error-text\"\n >\n {actionError}\n </p>\n )}\n\n {/* Health + actions */}\n <GlassCard className=\"p-6\">\n <div className=\"mb-4 flex flex-wrap items-center gap-3\">\n <StatusBadge status={conn.status} />\n <span className=\"inline-flex items-center rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs font-medium text-text-secondary\">\n {authMethodLabels[conn.authMethod]}\n </span>\n </div>\n\n <dl className=\"grid grid-cols-2 gap-4 text-sm sm:grid-cols-4\">\n <div>\n <dt className=\"text-text-secondary\">\n {t('adaptercloud.connections.region', 'Region')}\n </dt>\n <dd className=\"mt-0.5 font-medium text-text-primary\">{conn.region ?? '—'}</dd>\n </div>\n <div>\n <dt className=\"text-text-secondary\">\n {t('adaptercloud.connections.environment', 'Environment')}\n </dt>\n <dd className=\"mt-0.5 font-medium text-text-primary\">\n {conn.environment ?? '—'}\n </dd>\n </div>\n <div>\n <dt className=\"text-text-secondary\">\n {t('adaptercloud.connections.resourceCount', 'Resources')}\n </dt>\n <dd className=\"mt-0.5 font-medium tabular-nums text-text-primary\">\n {conn.resourceCount}\n </dd>\n </div>\n <div>\n <dt className=\"text-text-secondary\">\n {t('adaptercloud.connections.lastSynced', 'Last synced')}\n </dt>\n <dd className=\"mt-0.5 font-medium text-text-primary\">\n {conn.lastSyncedAt ? formatDate(conn.lastSyncedAt) : '—'}\n </dd>\n </div>\n </dl>\n\n {conn.lastError && (\n <p className=\"mt-4 rounded-lg bg-status-error-bg-subtle px-3 py-2 text-sm text-status-error-text\">\n {conn.lastError}\n </p>\n )}\n\n {/* Health transitions */}\n <div className=\"mt-5 border-t border-border-subtle pt-5\">\n <h3 className=\"mb-3 text-sm font-semibold text-text-primary\">\n {t('adaptercloud.connections.setHealth', 'Set health')}\n </h3>\n <div className=\"flex flex-wrap gap-2\">\n {TRANSITIONABLE.map((s) => (\n <button\n key={s}\n type=\"button\"\n disabled={setStatus.isPending || conn.status === s}\n onClick={() => handleSetStatus(s)}\n className=\"rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-text-primary transition-colors hover:bg-accent disabled:cursor-not-allowed disabled:opacity-40\"\n >\n {connectionStatusLabels[s]}\n </button>\n ))}\n {conn.status !== 'DISABLED' && (\n <button\n type=\"button\"\n disabled={disable.isPending}\n onClick={() => setConfirmDisableOpen(true)}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-status-error-text transition-colors hover:bg-status-error-bg-subtle disabled:opacity-40\"\n >\n <Ban className=\"h-3.5 w-3.5\" />\n {t('adaptercloud.connections.disable', 'Disable')}\n </button>\n )}\n </div>\n </div>\n\n {/* Start sync run */}\n <div className=\"mt-5 border-t border-border-subtle pt-5\">\n <h3 className=\"mb-3 flex items-center gap-2 text-sm font-semibold text-text-primary\">\n <RefreshCw className=\"h-4 w-4\" />\n {t('adaptercloud.connections.startSync', 'Start a sync run')}\n </h3>\n {!syncEnabled && (\n <p\n id=\"disabled-connection-sync-help\"\n className=\"mb-3 text-sm text-text-secondary\"\n >\n {t(\n 'adaptercloud.connections.disabledSyncHelp',\n 'Sync runs are unavailable while this connection is disabled. Set its health to re-enable sync.'\n )}\n </p>\n )}\n <p id=\"unsupported-sync-kind-help\" className=\"mb-3 text-sm text-text-secondary\">\n {t(\n 'adaptercloud.connections.syncModeAvailabilityHelp',\n 'Discovery is executable today. Reconcile, Cost Ingest, and Full need distinct backend workers and are not available yet.'\n )}\n </p>\n <div className=\"flex flex-wrap gap-2\">\n {SYNC_KINDS.map((k) => {\n const pending = startRun.isPending && runningKind === k;\n const executable = isConnectionSyncKindExecutable(k);\n return (\n <button\n key={k}\n type=\"button\"\n disabled={startRun.isPending || !syncEnabled || !executable}\n aria-describedby={\n !executable\n ? 'unsupported-sync-kind-help'\n : syncEnabled\n ? undefined\n : 'disabled-connection-sync-help'\n }\n title={\n !executable\n ? t(\n 'adaptercloud.connections.unsupportedSyncModeTooltip',\n 'This sync mode is not available yet because it needs a distinct backend worker.'\n )\n : !syncEnabled\n ? t(\n 'adaptercloud.connections.disabledSyncTooltip',\n 'Re-enable this connection before starting a sync run.'\n )\n : undefined\n }\n onClick={() => handleStartKind(k)}\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 disabled:cursor-not-allowed disabled:opacity-50\"\n >\n {pending ? (\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n ) : (\n <Play className=\"h-4 w-4\" />\n )}\n {syncKindLabels[k]}\n {!executable && (\n <span className=\"rounded bg-bg-sunken px-1.5 py-0.5 text-[10px] font-normal text-text-secondary\">\n {t('adaptercloud.connections.notAvailable', 'Not available')}\n </span>\n )}\n </button>\n );\n })}\n </div>\n </div>\n </GlassCard>\n\n {/* Config */}\n {conn.config != null && (\n <GlassCard className=\"p-6\">\n <h3 className=\"mb-3 text-sm font-semibold text-text-primary\">\n {t('adaptercloud.connections.config', 'Configuration')}\n </h3>\n <pre className=\"overflow-auto rounded-lg bg-bg-sunken p-4 text-xs text-text-secondary\">\n {JSON.stringify(conn.config, null, 2)}\n </pre>\n </GlassCard>\n )}\n\n {/* Resources */}\n <section>\n <div className=\"mb-3 flex items-center justify-between\">\n <h3 className=\"text-base font-semibold text-text-primary\">\n {t('adaptercloud.connections.discoveredResources', 'Discovered Resources')}\n </h3>\n <button\n type=\"button\"\n onClick={() => navigateTo(`/resources?connectionId=${conn.id}`)}\n className=\"text-sm font-medium text-accent-blue hover:underline\"\n >\n {t('adaptercloud.common.viewAll', 'View all')}\n </button>\n </div>\n {conn.resources && conn.resources.length > 0 ? (\n <div className=\"divide-y divide-border rounded-xl border border-border-subtle bg-bg-surface\">\n {conn.resources.slice(0, 10).map((r) => (\n <button\n key={r.id}\n type=\"button\"\n onClick={() => navigateTo(`/resources/${r.id}`)}\n className=\"flex w-full items-center gap-3 px-4 py-3 text-left transition-colors hover:bg-accent/50\"\n >\n <Server className=\"h-4 w-4 shrink-0 text-text-secondary\" />\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-sm font-medium text-text-primary\">{r.name}</p>\n <p className=\"mt-0.5 text-xs text-text-secondary\">\n {r.resourceType}\n {r.region ? ` · ${r.region}` : ''}\n </p>\n </div>\n <span className=\"hidden text-xs text-text-secondary sm:inline\">\n {formatMoney(r.monthlyCost)}\n </span>\n <StatusBadge status={r.state} label={resourceStateLabels[r.state]} />\n </button>\n ))}\n </div>\n ) : (\n <p className=\"rounded-xl border border-border-subtle bg-bg-surface px-4 py-6 text-center text-sm text-text-secondary\">\n {t(\n 'adaptercloud.connections.noResources',\n 'No resources discovered yet. Start a discovery sync run.'\n )}\n </p>\n )}\n </section>\n </div>\n )}\n </DataState>\n\n <ConfirmDialog\n open={confirmDisableOpen}\n onOpenChange={setConfirmDisableOpen}\n title={t('adaptercloud.connections.disableTitle', 'Disable this connection?')}\n description={t(\n 'adaptercloud.connections.disablePrompt',\n 'Disabling stops discovery and sync runs against this target. You can re-enable it later by setting its health.'\n )}\n confirmLabel={t('adaptercloud.connections.disable', 'Disable')}\n cancelLabel={t('adaptercloud.common.cancel', 'Cancel')}\n onConfirm={handleDisable}\n isPending={disable.isPending}\n tone=\"danger\"\n />\n </PageLayout>\n );\n}\n"],"mappings":"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"}
@@ -1,4 +1,6 @@
1
- import { AdaConnectionStatus } from '../../types';
1
+ import { AdaConnectionStatus, AdaSyncKind } from '../../types';
2
2
 
3
3
  export declare function canStartConnectionSync(status: AdaConnectionStatus): boolean;
4
+ export declare function isConnectionSyncKindExecutable(kind: AdaSyncKind): boolean;
5
+ export declare function canStartConnectionSyncKind(status: AdaConnectionStatus, kind: AdaSyncKind): boolean;
4
6
  //# sourceMappingURL=connectionSync.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"connectionSync.d.ts","sourceRoot":"","sources":["../../../../src/adaptercloud/pages/connections/connectionSync.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEvD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAE3E"}
1
+ {"version":3,"file":"connectionSync.d.ts","sourceRoot":"","sources":["../../../../src/adaptercloud/pages/connections/connectionSync.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAIpE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAE3E;AAED,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAEzE;AAED,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,mBAAmB,EAC3B,IAAI,EAAE,WAAW,GAChB,OAAO,CAET"}
@@ -1,8 +1,15 @@
1
1
  //#region src/adaptercloud/pages/connections/connectionSync.ts
2
- function e(e) {
2
+ var e = new Set(["DISCOVERY"]);
3
+ function t(e) {
3
4
  return e !== "DISABLED";
4
5
  }
6
+ function n(t) {
7
+ return e.has(t);
8
+ }
9
+ function r(e, r) {
10
+ return t(e) && n(r);
11
+ }
5
12
  //#endregion
6
- export { e as canStartConnectionSync };
13
+ export { t as canStartConnectionSync, r as canStartConnectionSyncKind, n as isConnectionSyncKindExecutable };
7
14
 
8
15
  //# sourceMappingURL=connectionSync.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"connectionSync.js","names":[],"sources":["../../../../src/adaptercloud/pages/connections/connectionSync.ts"],"sourcesContent":["import type { AdaConnectionStatus } from '../../types';\n\nexport function canStartConnectionSync(status: AdaConnectionStatus): boolean {\n return status !== 'DISABLED';\n}\n"],"mappings":";AAEA,SAAgB,EAAuB,GAAsC;CAC3E,OAAO,MAAW;AACpB"}
1
+ {"version":3,"file":"connectionSync.js","names":[],"sources":["../../../../src/adaptercloud/pages/connections/connectionSync.ts"],"sourcesContent":["import type { AdaConnectionStatus, AdaSyncKind } from '../../types';\n\nconst EXECUTABLE_SYNC_KINDS: ReadonlySet<AdaSyncKind> = new Set(['DISCOVERY']);\n\nexport function canStartConnectionSync(status: AdaConnectionStatus): boolean {\n return status !== 'DISABLED';\n}\n\nexport function isConnectionSyncKindExecutable(kind: AdaSyncKind): boolean {\n return EXECUTABLE_SYNC_KINDS.has(kind);\n}\n\nexport function canStartConnectionSyncKind(\n status: AdaConnectionStatus,\n kind: AdaSyncKind\n): boolean {\n return canStartConnectionSync(status) && isConnectionSyncKindExecutable(kind);\n}\n"],"mappings":";AAEA,IAAM,IAAkD,IAAI,IAAI,CAAC,WAAW,CAAC;AAE7E,SAAgB,EAAuB,GAAsC;CAC3E,OAAO,MAAW;AACpB;AAEA,SAAgB,EAA+B,GAA4B;CACzE,OAAO,EAAsB,IAAI,CAAI;AACvC;AAEA,SAAgB,EACd,GACA,GACS;CACT,OAAO,EAAuB,CAAM,KAAK,EAA+B,CAAI;AAC9E"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/microfe-adaptercloud",
3
- "version": "2026.825.1",
3
+ "version": "2026.825.3",
4
4
  "description": "Burdenoff AdapterCloud Microfrontend",
5
5
  "type": "module",
6
6
  "files": [