import { mkdirSync, renameSync, writeFileSync } from "node:fs" import path from "node:path" import type { DnsRecord } from "./db" import { env } from "./env" const HEADER = "# Generated by dnsmasq-admin — 请勿手动编辑,每次「应用并重启」都会覆盖此文件" /** * dnsmasq's `address=/domain/ip` already answers for the domain *and* every subdomain, so * there is no need for a separate wildcard syntax. */ export function renderRecord(record: DnsRecord): string { return record.type === "A" ? `address=/${record.domain}/${record.value}` : `cname=${record.domain},${record.value}` } export function renderConfig(records: DnsRecord[]): string { const lines = records .filter((record) => record.enabled) .map(renderRecord) if (lines.length === 0) { return `${HEADER}\n\n# 当前没有启用的记录\n` } return `${HEADER}\n\n${lines.join("\n")}\n` } /** * Regenerate the managed config file for the given records. * * Written to a sibling temp file first and then renamed, so dnsmasq can never read a * half-written file. */ export async function writeManagedConfig(records: DnsRecord[]): Promise<{ path: string recordCount: number }> { const dir = path.dirname(env.confPath) mkdirSync(dir, { recursive: true }) const content = renderConfig(records) const tempPath = `${env.confPath}.${process.pid}.tmp` writeFileSync(tempPath, content, "utf8") renameSync(tempPath, env.confPath) return { path: env.confPath, recordCount: records.filter((record) => record.enabled).length, } }