import { queryOptions } from '@tanstack/react-query' import type { Alias, AliasCreate, AliasPatch, AliasRetarget, BindExport, DashboardStats, Location, Node, NodeCreate, NodePatch, Topology, Zone, ZoneCreate, ZonePatch, SyncJob, CfZone, } from '@cdnmanager/shared' import { api } from '@/lib/api-client' export const fleetKeys = { all: ['fleet'] as const, locations: () => [...fleetKeys.all, 'locations'] as const, zones: () => [...fleetKeys.all, 'zones'] as const, cfZones: () => [...fleetKeys.all, 'cf-zones'] as const, nodes: (filters?: Record) => [...fleetKeys.all, 'nodes', filters ?? {}] as const, node: (id: string) => [...fleetKeys.all, 'node', id] as const, aliases: (filters?: Record) => [...fleetKeys.all, 'aliases', filters ?? {}] as const, alias: (id: string) => [...fleetKeys.all, 'alias', id] as const, dashboard: () => [...fleetKeys.all, 'dashboard'] as const, topology: (zoneId?: string) => [...fleetKeys.all, 'topology', zoneId ?? 'all'] as const, syncJobs: (zoneId: string) => [...fleetKeys.all, 'sync-jobs', zoneId] as const, bindExport: (zoneId: string) => [...fleetKeys.all, 'bind', zoneId] as const, namingPreview: (params: Record) => [...fleetKeys.all, 'naming', params] as const, } function qs(filters?: Record) { if (!filters) return '' const p = new URLSearchParams() for (const [k, v] of Object.entries(filters)) { if (v) p.set(k, v) } const s = p.toString() return s ? `?${s}` : '' } export const locationsQueryOptions = () => queryOptions({ queryKey: fleetKeys.locations(), queryFn: () => api.get('/api/v1/locations'), }) export const zonesQueryOptions = () => queryOptions({ queryKey: fleetKeys.zones(), queryFn: () => api.get('/api/v1/zones'), }) export const cfZonesQueryOptions = () => queryOptions({ queryKey: fleetKeys.cfZones(), queryFn: () => api.get('/api/v1/cloudflare/zones'), retry: false, }) export const nodesQueryOptions = (filters?: Record) => queryOptions({ queryKey: fleetKeys.nodes(filters), queryFn: () => api.get(`/api/v1/nodes${qs(filters)}`), }) export const aliasesQueryOptions = ( filters?: Record, ) => queryOptions({ queryKey: fleetKeys.aliases(filters), queryFn: () => api.get(`/api/v1/aliases${qs(filters)}`), }) export const dashboardStatsQueryOptions = () => queryOptions({ queryKey: fleetKeys.dashboard(), queryFn: () => api.get('/api/v1/dashboard/stats'), staleTime: 15_000, }) export const topologyQueryOptions = (zoneId?: string) => queryOptions({ queryKey: fleetKeys.topology(zoneId), queryFn: () => api.get( `/api/v1/topology${zoneId ? `?zoneId=${encodeURIComponent(zoneId)}` : ''}`, ), }) export const syncJobsQueryOptions = (zoneId: string) => queryOptions({ queryKey: fleetKeys.syncJobs(zoneId), queryFn: () => api.get(`/api/v1/zones/${zoneId}/sync-jobs`), enabled: Boolean(zoneId), }) export const bindExportQueryOptions = (zoneId: string) => queryOptions({ queryKey: fleetKeys.bindExport(zoneId), queryFn: () => api.get(`/api/v1/zones/${zoneId}/export/bind`), enabled: Boolean(zoneId), }) export async function createZone(body: ZoneCreate) { return api.post('/api/v1/zones', body) } export async function patchZone(id: string, body: ZonePatch) { return api.patch(`/api/v1/zones/${id}`, body) } export async function removeZone(id: string) { return api.delete(`/api/v1/zones/${id}`) } export async function syncZone(id: string) { return api.post(`/api/v1/zones/${id}/sync`, {}) } export async function applyZone(id: string, opIds?: string[]) { return api.post(`/api/v1/zones/${id}/apply`, { opIds }) } export async function createNode(body: NodeCreate) { return api.post('/api/v1/nodes', body) } export async function patchNode(id: string, body: NodePatch) { return api.patch(`/api/v1/nodes/${id}`, body) } export async function removeNode(id: string) { return api.delete(`/api/v1/nodes/${id}`) } export async function createAlias(body: AliasCreate) { return api.post('/api/v1/aliases', body) } export async function patchAlias(id: string, body: AliasPatch) { return api.patch(`/api/v1/aliases/${id}`, body) } export async function retargetAliasApi(id: string, body: AliasRetarget) { return api.post(`/api/v1/aliases/${id}/retarget`, body) } export async function removeAlias(id: string) { return api.delete(`/api/v1/aliases/${id}`) } export async function ignoreOrphan( zoneId: string, recordName: string, recordType: string, ) { return api.post(`/api/v1/zones/${zoneId}/orphans/ignore`, { recordName, recordType, }) } export async function previewHostname(params: { zoneId: string locationId: string role: string indexNum?: number providerTag?: string ipv4?: string ipv6?: string nodeId?: string }) { const p = new URLSearchParams({ zoneId: params.zoneId, locationId: params.locationId, role: params.role, indexNum: String(params.indexNum ?? 1), }) if (params.providerTag) p.set('providerTag', params.providerTag) if (params.ipv4) p.set('ipv4', params.ipv4) if (params.ipv6) p.set('ipv6', params.ipv6) if (params.nodeId) p.set('nodeId', params.nodeId) return api.get<{ hostname: string ttl: number records: Array<{ type: 'A' | 'AAAA' | 'CNAME' name: string content: string ttl: number note?: string }> }>(`/api/v1/naming/preview?${p}`) }