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
- 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.
209 lines
5.7 KiB
TypeScript
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}`)
|
|
}
|