import type { SecretsStore } from '../secrets/index.js'; import { type NatDdnsStatus, type NatDdnsSettings } from '../types.js'; import type { DdnsProvider } from './index.js'; /** Outcome of a single DDNS update attempt. */ export interface DdnsUpdateOutcome { attempted: boolean; ok: boolean; ip: string | null; error: string | null; at: Date; } export interface DdnsUpdaterOptions { /** Current DDNS settings (provider, hostname, externally-managed flag). */ settings: NatDdnsSettings; /** Backing credential store. */ secrets: SecretsStore; /** Returns the most recently observed external IP (null when unknown). */ getExternalIp: () => string | null; /** Fetch override for tests. */ fetch?: typeof fetch; /** Provider resolver override (tests can inject fakes). */ resolveProvider?: (providerId: string) => DdnsProvider; /** Clock override for tests. */ now?: () => Date; /** Timer overrides for tests. */ setInterval?: (fn: () => void, ms: number) => NodeJS.Timeout; clearInterval?: (h: NodeJS.Timeout) => void; } /** * DDNS update loop. * * Lifecycle: * - `start()`: if a provider is configured AND not externally managed, runs * an immediate update, then schedules `setInterval(intervalMs)`. * - On each tick: re-evaluates the IP. If unchanged from the last successful * update, no provider call. If changed, calls `provider.update`. Errors * are recorded but the timer keeps ticking. * - `stop()`: clears the timer. Idempotent. * - `updateSettings(...)`: swap in new settings, re-starting if needed. * - `forceUpdate()`: bypass the unchanged-IP check (used by `testReachability`). */ export declare class DdnsUpdater { private settings; private readonly secrets; private readonly getExternalIp; private readonly fetchImpl; private readonly resolveProvider; private readonly nowFn; private readonly setIntervalFn; private readonly clearIntervalFn; private timer; private lastPushedIp; private lastOutcome; private started; constructor(opts: DdnsUpdaterOptions); /** Current status (for the NatService snapshot). */ getStatus(): NatDdnsStatus; start(): Promise; stop(): void; /** Replace settings; restart the loop with the new configuration. */ updateSettings(next: NatDdnsSettings): Promise; /** Force an immediate update, bypassing the unchanged-IP skip. */ forceUpdate(): Promise; private shouldUpdate; private scheduleNext; private runOnce; private loadConfig; }