Files
CDNManager/apps/web/src/queries/fleet.ts
T
Denozordec 146afc1369
quality / commitlint (push) Skipped
CD / update-wiki (push) Successful in 5s
quality / changes (push) Successful in 5s
quality / docker-check (push) Skipped
quality / web (push) Successful in 56s
quality / api (push) Successful in 43s
CD / quality (push) Successful in 1m46s
CD / publish (push) Successful in 1m40s
feat(dns): Implement DNS preview records generation and enhance hostname preview functionality
- Added `buildDnsPreviewRecords` function to generate DNS records based on hostname, TTL, and provided IPv4/IPv6 addresses.
- Updated `fleetRoutes` to utilize the new DNS records generation for hostname previews.
- Enhanced frontend API calls to support IPv4, IPv6, and node ID parameters for more comprehensive hostname previews.
- Updated UI components to display DNS preview information, including A, AAAA, and CNAME records.
2026-09-04 15:09:30 +07:00

209 lines
5.7 KiB
TypeScript

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<string, string | undefined>) =>
[...fleetKeys.all, 'nodes', filters ?? {}] as const,
node: (id: string) => [...fleetKeys.all, 'node', id] as const,
aliases: (filters?: Record<string, string | undefined>) =>
[...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<string, string>) =>
[...fleetKeys.all, 'naming', params] as const,
}
function qs(filters?: Record<string, string | undefined>) {
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<Location[]>('/api/v1/locations'),
})
export const zonesQueryOptions = () =>
queryOptions({
queryKey: fleetKeys.zones(),
queryFn: () => api.get<Zone[]>('/api/v1/zones'),
})
export const cfZonesQueryOptions = () =>
queryOptions({
queryKey: fleetKeys.cfZones(),
queryFn: () => api.get<CfZone[]>('/api/v1/cloudflare/zones'),
retry: false,
})
export const nodesQueryOptions = (filters?: Record<string, string | undefined>) =>
queryOptions({
queryKey: fleetKeys.nodes(filters),
queryFn: () => api.get<Node[]>(`/api/v1/nodes${qs(filters)}`),
})
export const aliasesQueryOptions = (
filters?: Record<string, string | undefined>,
) =>
queryOptions({
queryKey: fleetKeys.aliases(filters),
queryFn: () => api.get<Alias[]>(`/api/v1/aliases${qs(filters)}`),
})
export const dashboardStatsQueryOptions = () =>
queryOptions({
queryKey: fleetKeys.dashboard(),
queryFn: () => api.get<DashboardStats>('/api/v1/dashboard/stats'),
staleTime: 15_000,
})
export const topologyQueryOptions = (zoneId?: string) =>
queryOptions({
queryKey: fleetKeys.topology(zoneId),
queryFn: () =>
api.get<Topology>(
`/api/v1/topology${zoneId ? `?zoneId=${encodeURIComponent(zoneId)}` : ''}`,
),
})
export const syncJobsQueryOptions = (zoneId: string) =>
queryOptions({
queryKey: fleetKeys.syncJobs(zoneId),
queryFn: () => api.get<SyncJob[]>(`/api/v1/zones/${zoneId}/sync-jobs`),
enabled: Boolean(zoneId),
})
export const bindExportQueryOptions = (zoneId: string) =>
queryOptions({
queryKey: fleetKeys.bindExport(zoneId),
queryFn: () =>
api.get<BindExport>(`/api/v1/zones/${zoneId}/export/bind`),
enabled: Boolean(zoneId),
})
export async function createZone(body: ZoneCreate) {
return api.post<Zone>('/api/v1/zones', body)
}
export async function patchZone(id: string, body: ZonePatch) {
return api.patch<Zone>(`/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<SyncJob>(`/api/v1/zones/${id}/sync`, {})
}
export async function applyZone(id: string, opIds?: string[]) {
return api.post<SyncJob>(`/api/v1/zones/${id}/apply`, { opIds })
}
export async function createNode(body: NodeCreate) {
return api.post<Node>('/api/v1/nodes', body)
}
export async function patchNode(id: string, body: NodePatch) {
return api.patch<Node>(`/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<Alias>('/api/v1/aliases', body)
}
export async function patchAlias(id: string, body: AliasPatch) {
return api.patch<Alias>(`/api/v1/aliases/${id}`, body)
}
export async function retargetAliasApi(id: string, body: AliasRetarget) {
return api.post<Alias>(`/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}`)
}