73 lines
1.8 KiB
TypeScript
73 lines
1.8 KiB
TypeScript
|
import { CachedZone, DNSRecord, DNSZone, SOARecord } from "../models/interfaces";
|
||
|
import { readZoneFile } from "./reader";
|
||
|
import { DNSRecordType } from "./records";
|
||
|
import { writeZoneFile } from "./writer";
|
||
|
|
||
|
export class DNSCache {
|
||
|
private cached: Record<string, CachedZone> = {};
|
||
|
|
||
|
constructor(private ttl = 1600) {}
|
||
|
|
||
|
has(name: string): boolean {
|
||
|
return this.cached[name] != null;
|
||
|
}
|
||
|
|
||
|
async get(name: string): Promise<CachedZone | null> {
|
||
|
const cached = this.cached[name];
|
||
|
if (!cached) {
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
if (cached.changed.getTime() < new Date().getTime() - this.ttl * 1000) {
|
||
|
return this.load(name, cached.file);
|
||
|
}
|
||
|
|
||
|
return this.cached[name];
|
||
|
}
|
||
|
|
||
|
async set(name: string, zone: CachedZone): Promise<void> {
|
||
|
this.cached[name] = zone;
|
||
|
}
|
||
|
|
||
|
async load(name: string, file: string): Promise<CachedZone> {
|
||
|
const zoneFile = await readZoneFile(file);
|
||
|
const cache = {
|
||
|
name,
|
||
|
file,
|
||
|
zone: zoneFile,
|
||
|
added: new Date(),
|
||
|
changed: new Date()
|
||
|
}
|
||
|
this.cached[name] = cache;
|
||
|
return cache;
|
||
|
}
|
||
|
|
||
|
async save(name: string): Promise<void> {
|
||
|
const zone = await this.get(name);
|
||
|
if (!zone) {
|
||
|
throw new Error('No such cached zone file!');
|
||
|
}
|
||
|
await writeZoneFile(zone.zone, zone.file);
|
||
|
}
|
||
|
|
||
|
async update(name: string, newZone?: CachedZone): Promise<void> {
|
||
|
let zone: CachedZone | null;
|
||
|
if (newZone) {
|
||
|
zone = newZone;
|
||
|
} else {
|
||
|
zone = await this.get(name);
|
||
|
}
|
||
|
|
||
|
if (!zone) {
|
||
|
throw new Error('No such cached zone file!');
|
||
|
}
|
||
|
|
||
|
zone.changed = new Date();
|
||
|
const soa = zone.zone.records.find((record) => record.type === DNSRecordType.SOA) as SOARecord;
|
||
|
soa.serial = Math.floor(Date.now() / 1000);
|
||
|
|
||
|
this.set(name, zone);
|
||
|
return this.save(name);
|
||
|
}
|
||
|
}
|