Files
CDNManager/packages/shared/src/fleet.ts
T
Denozordec 8700dc2957
quality / commitlint (push) Skipped
quality / changes (push) Successful in 5s
quality / docker-check (push) Skipped
CD / update-wiki (push) Successful in 6s
quality / web (push) Successful in 53s
quality / api (push) Successful in 49s
CD / quality (push) Successful in 1m57s
CD / publish (push) Successful in 27s
Enhance CDN Manager: Add Cloudflare API token support, update documentation, and introduce new routes for managing nodes, aliases, and topology. Improve UI components and status badges for better user experience.
2026-09-04 12:49:51 +07:00

269 lines
7.5 KiB
TypeScript

import { z } from "zod";
export const nodeRoleSchema = z.enum(["hub", "gw", "edge", "ix"]);
export type NodeRole = z.infer<typeof nodeRoleSchema>;
export const aliasPurposeSchema = z.enum([
"geo",
"ix",
"backup",
"admin",
"custom",
]);
export type AliasPurpose = z.infer<typeof aliasPurposeSchema>;
export const aliasModeSchema = z.enum(["primary", "pair"]);
export type AliasMode = z.infer<typeof aliasModeSchema>;
export const syncStatusSchema = z.enum([
"pending",
"ok",
"drift",
"missing",
"error",
]);
export type SyncStatus = z.infer<typeof syncStatusSchema>;
export const addressFamilySchema = z.enum(["v4", "v6"]);
export const cfZoneSchema = z.object({
id: z.string(),
name: z.string(),
status: z.string().optional(),
});
export type CfZone = z.infer<typeof cfZoneSchema>;
export const cfDnsRecordSchema = z.object({
id: z.string().optional(),
type: z.string(),
name: z.string(),
content: z.string(),
ttl: z.number(),
proxied: z.boolean().optional(),
priority: z.number().optional(),
});
export type CfDnsRecord = z.infer<typeof cfDnsRecordSchema>;
export const createDnsRecordPayloadSchema = z.object({
type: z.string(),
name: z.string(),
content: z.string(),
ttl: z.number(),
proxied: z.boolean().optional(),
priority: z.number().optional(),
});
export type CreateDnsRecordPayload = z.infer<typeof createDnsRecordPayloadSchema>;
export const patchDnsRecordPayloadSchema = createDnsRecordPayloadSchema.partial();
export type PatchDnsRecordPayload = z.infer<typeof patchDnsRecordPayloadSchema>;
export const locationSchema = z.object({
id: z.string(),
code: z.string(),
name: z.string(),
country: z.string().nullable(),
sortOrder: z.number(),
});
export type Location = z.infer<typeof locationSchema>;
export const zoneSchema = z.object({
id: z.string(),
cfZoneId: z.string().nullable(),
name: z.string(),
role: z.string(),
namingTemplate: z.string(),
defaultTtl: z.number(),
lastSyncAt: z.string().nullable(),
createdAt: z.string(),
updatedAt: z.string(),
});
export type Zone = z.infer<typeof zoneSchema>;
export const zoneCreateSchema = z.object({
name: z.string().min(1),
cfZoneId: z.string().optional().nullable(),
role: z.string().default("routing"),
namingTemplate: z.string().optional(),
defaultTtl: z.number().int().min(60).max(86400).optional(),
});
export type ZoneCreate = z.infer<typeof zoneCreateSchema>;
export const zonePatchSchema = zoneCreateSchema.partial();
export type ZonePatch = z.infer<typeof zonePatchSchema>;
export const nodeAddressSchema = z.object({
id: z.string(),
family: addressFamilySchema,
ip: z.string(),
});
export type NodeAddress = z.infer<typeof nodeAddressSchema>;
export const nodeSchema = z.object({
id: z.string(),
zoneId: z.string(),
locationId: z.string(),
locationCode: z.string().optional(),
locationName: z.string().optional(),
hostname: z.string(),
role: nodeRoleSchema,
indexNum: z.number(),
providerTag: z.string().nullable(),
notes: z.string().nullable(),
syncStatus: syncStatusSchema,
cfARecordId: z.string().nullable(),
cfAaaaRecordId: z.string().nullable(),
lastError: z.string().nullable(),
addresses: z.array(nodeAddressSchema).default([]),
aliasCount: z.number().optional(),
createdAt: z.string(),
updatedAt: z.string(),
});
export type Node = z.infer<typeof nodeSchema>;
export const nodeCreateSchema = z.object({
zoneId: z.string().min(1),
locationId: z.string().min(1),
role: nodeRoleSchema,
indexNum: z.number().int().min(1).max(99).default(1),
hostname: z.string().min(1).optional(),
providerTag: z.string().optional().nullable(),
notes: z.string().optional().nullable(),
ipv4: z.string().min(1),
ipv6: z.string().optional().nullable(),
});
export type NodeCreate = z.infer<typeof nodeCreateSchema>;
export const nodePatchSchema = z.object({
locationId: z.string().optional(),
role: nodeRoleSchema.optional(),
indexNum: z.number().int().min(1).max(99).optional(),
hostname: z.string().min(1).optional(),
providerTag: z.string().optional().nullable(),
notes: z.string().optional().nullable(),
ipv4: z.string().min(1).optional(),
ipv6: z.string().optional().nullable(),
});
export type NodePatch = z.infer<typeof nodePatchSchema>;
export const aliasSchema = z.object({
id: z.string(),
zoneId: z.string(),
name: z.string(),
purpose: aliasPurposeSchema,
mode: aliasModeSchema,
targetNodeId: z.string(),
targetHostname: z.string().optional(),
syncStatus: syncStatusSchema,
cfRecordId: z.string().nullable(),
lastError: z.string().nullable(),
createdAt: z.string(),
updatedAt: z.string(),
});
export type Alias = z.infer<typeof aliasSchema>;
export const aliasCreateSchema = z.object({
zoneId: z.string().min(1),
name: z.string().min(1),
purpose: aliasPurposeSchema.default("geo"),
mode: aliasModeSchema.default("primary"),
targetNodeId: z.string().min(1),
});
export type AliasCreate = z.infer<typeof aliasCreateSchema>;
export const aliasPatchSchema = z.object({
name: z.string().min(1).optional(),
purpose: aliasPurposeSchema.optional(),
mode: aliasModeSchema.optional(),
targetNodeId: z.string().min(1).optional(),
});
export type AliasPatch = z.infer<typeof aliasPatchSchema>;
export const aliasRetargetSchema = z.object({
targetNodeId: z.string().min(1),
});
export type AliasRetarget = z.infer<typeof aliasRetargetSchema>;
export const syncDiffOpSchema = z.object({
id: z.string(),
kind: z.enum([
"create",
"update",
"delete",
"orphan",
"proxy_violation",
"noop",
]),
entityType: z.enum(["node_a", "node_aaaa", "alias", "orphan"]),
entityId: z.string().nullable(),
recordName: z.string(),
recordType: z.string(),
desired: z.record(z.string(), z.unknown()).nullable(),
observed: z.record(z.string(), z.unknown()).nullable(),
detail: z.string().optional(),
});
export type SyncDiffOp = z.infer<typeof syncDiffOpSchema>;
export const syncJobSchema = z.object({
id: z.string(),
zoneId: z.string(),
status: z.enum(["pending", "running", "done", "failed"]),
diff: z.array(syncDiffOpSchema).optional(),
error: z.string().nullable(),
createdAt: z.string(),
finishedAt: z.string().nullable(),
});
export type SyncJob = z.infer<typeof syncJobSchema>;
export const syncApplySchema = z.object({
opIds: z.array(z.string()).optional(),
});
export type SyncApply = z.infer<typeof syncApplySchema>;
export const dashboardStatsSchema = z.object({
nodes: z.number(),
aliases: z.number(),
syncOk: z.number(),
drift: z.number(),
proxyViolations: z.number(),
orphans: z.number(),
lastSyncAt: z.string().nullable(),
nodesWithoutIp: z.number(),
brokenAliases: z.number(),
});
export type DashboardStats = z.infer<typeof dashboardStatsSchema>;
export const topologyNodeSchema = z.object({
id: z.string(),
hostname: z.string(),
role: nodeRoleSchema,
locationCode: z.string(),
ipv4: z.string().nullable(),
syncStatus: syncStatusSchema,
});
export const topologyEdgeSchema = z.object({
id: z.string(),
aliasName: z.string(),
purpose: aliasPurposeSchema,
fromNodeId: z.string(),
toHostname: z.string(),
});
export const topologySchema = z.object({
nodes: z.array(topologyNodeSchema),
edges: z.array(topologyEdgeSchema),
locations: z.array(locationSchema),
});
export type Topology = z.infer<typeof topologySchema>;
export const bindExportSchema = z.object({
zoneName: z.string(),
content: z.string(),
});
export type BindExport = z.infer<typeof bindExportSchema>;
export const orphanIgnoreSchema = z.object({
recordName: z.string().min(1),
recordType: z.string().min(1),
});