feat:Update pnpm-lock.yaml to link shared package; modify API routes to utilize new schemas for domain and service management; enhance DNS record handling with CNAME support; refactor service and subdomain routes for improved functionality; implement confirm dialog for domain deletion in the frontend; clean up unused components and improve UI consistency.
Build, Test, and Push CFDM Docker Image / test (push) Failing after 51s
Build, Test, and Push CFDM Docker Image / build-and-push (push) Has been skipped
Build, Test, and Push CFDM Docker Image / update-wiki (push) Has been skipped
Build, Test, and Push CFDM Docker Image / create-release (push) Has been skipped

This commit is contained in:
Denozordec
2026-06-22 13:52:33 +07:00
parent 4a70cf5854
commit 6d1d8ca4f3
99 changed files with 6692 additions and 1483 deletions
+85 -3
View File
@@ -9,6 +9,14 @@ var CERT_WARNING = "warning";
var CERT_EXPIRED = "expired";
var CERT_ERROR = "error";
var CERT_UNKNOWN = "unknown";
var CERT_MONITOR_AUTO = "auto";
var CERT_MONITOR_REQUIRED = "required";
var CERT_MONITOR_SKIPPED = "skipped";
var CERT_MONITORING_VALUES = [
CERT_MONITOR_AUTO,
CERT_MONITOR_REQUIRED,
CERT_MONITOR_SKIPPED
];
// src/validators.ts
var NAME_RE = /^(@|\*|[a-zA-Z0-9_]([a-zA-Z0-9_-]*[a-zA-Z0-9_])?(\.[a-zA-Z0-9_]([a-zA-Z0-9_-]*[a-zA-Z0-9_])?)*)$/;
@@ -64,6 +72,11 @@ function certStatusFromExpiry(daysLeft) {
if (daysLeft <= 30) return CERT_WARNING;
return CERT_OK;
}
function shouldMonitorService(service, group) {
if (!service.enabled) return false;
if (!service.service_group_id) return true;
return group?.enabled ?? false;
}
function isValidIpv4(ip) {
const parts = ip.split(".");
if (parts.length !== 4) return false;
@@ -93,6 +106,16 @@ function dnsNameToSubdomainLabel(recordName, zoneName) {
function subdomainLabelToFqdn(label, zoneName) {
return label === "@" ? zoneName : `${label}.${zoneName}`;
}
function normalizeDnsRecordName(recordName, zoneName) {
const label = dnsNameToSubdomainLabel(recordName, zoneName);
if (label == null) {
return recordName.trim().replace(/\.+$/, "");
}
return subdomainLabelToFqdn(label, zoneName);
}
function dnsRecordNamesMatch(left, right, zoneName) {
return normalizeDnsRecordName(left, zoneName).toLowerCase() === normalizeDnsRecordName(right, zoneName).toLowerCase();
}
// src/parse-fqdn.ts
function fqdnToDisplay(hostname, zoneName) {
@@ -136,6 +159,7 @@ function bindingToFqdn(binding) {
// src/schemas.ts
import { z } from "zod";
var certMonitoringSchema = z.enum(["auto", "required", "skipped"]);
var groupSchema = z.object({
id: z.number(),
name: z.string(),
@@ -180,12 +204,16 @@ var serviceDomainBindingSchema = z.object({
zone_name: z.string(),
hostname: z.string(),
fqdn: z.string(),
record_type: z.enum(["A", "CNAME"]).default("A"),
target_ips: z.array(z.string()).optional(),
target_ip: z.string().nullable().optional(),
target_cname: z.string().nullable().optional(),
sync_status: z.string().nullable()
}).transform((binding) => ({
...binding,
target_ips: binding.target_ips && binding.target_ips.length > 0 ? binding.target_ips : binding.target_ip ? [binding.target_ip] : []
target_ips: binding.target_ips && binding.target_ips.length > 0 ? binding.target_ips : binding.target_ip ? [binding.target_ip] : [],
target_cname: binding.target_cname?.trim() || null,
record_type: binding.target_cname?.trim() ? "CNAME" : binding.record_type ?? "A"
}));
var serviceViewSchema = serviceSchema.extend({
subdomain: z.string().default(""),
@@ -206,6 +234,7 @@ var domainSchema = z.object({
zone_name: z.string(),
cf_zone_id: z.string(),
status: z.string(),
cert_monitoring: certMonitoringSchema.default("auto"),
last_synced_at: z.string().nullable(),
created_at: z.string(),
updated_at: z.string()
@@ -226,10 +255,14 @@ var serviceBindingSchema = z.object({
service_name: z.string(),
service_slug: z.string(),
target_ip: z.string().nullable(),
target_ips: z.array(z.string()).optional(),
sync_status: z.string().nullable(),
created_at: z.string(),
updated_at: z.string()
});
}).transform((binding) => ({
...binding,
target_ips: binding.target_ips && binding.target_ips.length > 0 ? binding.target_ips : binding.target_ip ? [binding.target_ip] : []
}));
var dnsRecordSchema = z.object({
id: z.number(),
domain_id: z.number(),
@@ -268,7 +301,25 @@ var ipv4Schema = z.string().regex(
);
var serviceDomainInputSchema = z.object({
fqdn: z.string().min(1, "\u0423\u043A\u0430\u0436\u0438\u0442\u0435 FQDN"),
target_ips: z.array(ipv4Schema).min(1, "\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u0445\u043E\u0442\u044F \u0431\u044B \u043E\u0434\u0438\u043D IP")
target_ips: z.array(ipv4Schema).optional(),
target_cname: z.string().min(1, "\u0423\u043A\u0430\u0436\u0438\u0442\u0435 CNAME-\u0446\u0435\u043B\u044C").optional()
}).superRefine((data, ctx) => {
const hasIps = (data.target_ips?.length ?? 0) > 0;
const hasCname = Boolean(data.target_cname?.trim());
if (!hasIps && !hasCname) {
ctx.addIssue({
code: "custom",
message: "\u0423\u043A\u0430\u0436\u0438\u0442\u0435 IP \u0438\u043B\u0438 CNAME-\u0446\u0435\u043B\u044C",
path: ["target_ips"]
});
}
if (hasIps && hasCname) {
ctx.addIssue({
code: "custom",
message: "\u0423\u043A\u0430\u0436\u0438\u0442\u0435 \u043B\u0438\u0431\u043E IP, \u043B\u0438\u0431\u043E CNAME-\u0446\u0435\u043B\u044C",
path: ["target_cname"]
});
}
});
var createServiceSchema = z.object({
name: z.string().min(1, "\u0423\u043A\u0430\u0436\u0438\u0442\u0435 \u043D\u0430\u0437\u0432\u0430\u043D\u0438\u0435"),
@@ -309,9 +360,24 @@ var subdomainSchema = z.object({
domain_id: z.number(),
name: z.string(),
fqdn: z.string(),
enabled: z.boolean(),
cert_monitoring: certMonitoringSchema.default("auto"),
created_at: z.string(),
updated_at: z.string()
});
var createSubdomainSchema = z.object({
name: z.string().min(1, "\u0423\u043A\u0430\u0436\u0438\u0442\u0435 \u0438\u043C\u044F \u043F\u043E\u0434\u0434\u043E\u043C\u0435\u043D\u0430")
});
var updateSubdomainSchema = z.object({
name: z.string().min(1, "\u0423\u043A\u0430\u0436\u0438\u0442\u0435 \u0438\u043C\u044F \u043F\u043E\u0434\u0434\u043E\u043C\u0435\u043D\u0430").optional(),
enabled: z.boolean().optional(),
cert_monitoring: certMonitoringSchema.optional()
});
var updateDomainSchema = z.object({
group_id: z.number().nullable().optional(),
status: z.string().optional(),
cert_monitoring: certMonitoringSchema.optional()
});
var updateServiceConfigSchema = z.object({
name: z.string().min(1, "\u0423\u043A\u0430\u0436\u0438\u0442\u0435 \u043D\u0430\u0437\u0432\u0430\u043D\u0438\u0435").optional(),
slug: z.string().min(1, "\u0423\u043A\u0430\u0436\u0438\u0442\u0435 slug").optional(),
@@ -328,9 +394,17 @@ var createServiceGroupSchema = z.object({
var toggleEnabledSchema = z.object({
enabled: z.boolean()
});
var reorderServicesSchema = z.object({
group_id: z.union([z.number(), z.null()]).optional().default(null),
service_ids: z.array(z.number().int().positive()).min(1)
});
export {
CERT_ERROR,
CERT_EXPIRED,
CERT_MONITORING_VALUES,
CERT_MONITOR_AUTO,
CERT_MONITOR_REQUIRED,
CERT_MONITOR_SKIPPED,
CERT_OK,
CERT_UNKNOWN,
CERT_WARNING,
@@ -341,6 +415,7 @@ export {
SYNC_SYNCED,
ValidationError,
bindingToFqdn,
certMonitoringSchema,
certStatusFromExpiry,
certificateSchema,
createDnsRecordSchema,
@@ -350,7 +425,9 @@ export {
createServiceGroupSchema,
createServiceSchema,
createServiceWithConfigSchema,
createSubdomainSchema,
dnsNameToSubdomainLabel,
dnsRecordNamesMatch,
dnsRecordSchema,
domainListItemSchema,
domainSchema,
@@ -359,7 +436,9 @@ export {
groupWithStatsSchema,
isValidIpv4,
loginSchema,
normalizeDnsRecordName,
parseFqdn,
reorderServicesSchema,
serviceBindingSchema,
serviceDomainBindingSchema,
serviceGroupSchema,
@@ -368,10 +447,13 @@ export {
serviceGroupsResponseSchema,
serviceSchema,
serviceViewSchema,
shouldMonitorService,
subdomainLabelToFqdn,
subdomainSchema,
toggleEnabledSchema,
updateDomainGroupSchema,
updateDomainSchema,
updateServiceConfigSchema,
updateSubdomainSchema,
validateDnsRecord
};