UNPKG

@linkedmink/node-route53-dynamic-dns

Version:

Background process that updates AWS Route 53 DNS address records whenever the public IP of the hosting environment changes

77 lines 3.15 kB
import EventEmitter from "node:events"; import { setInterval } from "node:timers/promises"; import { IpNotFoundError, publicIpv4, publicIpv6 } from "public-ip"; import { MINIMUM_IP_RETRIEVE_TIMEOUT_MS, MINIMUM_IP_RETRIEVE_UPDATE_DIFF_MS, } from "../constants/behavior.mjs"; import { PublicIpEvent } from "../constants/events.mjs"; import { loggerForModuleUrl } from "../environment/logger.mjs"; import { formatError } from "../functions/format.mjs"; export class PublicIpClient extends EventEmitter { updateIntervalMs; ipRetrieveTimeout; isIpV6Enabled; logger = loggerForModuleUrl(import.meta.url); constructor(updateIntervalMs, ipRetrieveTimeout, isIpV6Enabled) { super(); this.updateIntervalMs = updateIntervalMs; this.ipRetrieveTimeout = ipRetrieveTimeout; this.isIpV6Enabled = isIpV6Enabled; if (this.ipRetrieveTimeout < MINIMUM_IP_RETRIEVE_TIMEOUT_MS) { throw new Error(`ipRetrieveTimeout must be at least: ${MINIMUM_IP_RETRIEVE_TIMEOUT_MS}ms`); } // Don't allow getting the IP again while a retrieval is possibly in progress const updateIntervalMinimumMs = MINIMUM_IP_RETRIEVE_TIMEOUT_MS + MINIMUM_IP_RETRIEVE_UPDATE_DIFF_MS; if (this.updateIntervalMs < updateIntervalMinimumMs) { throw new Error(`updateIntervalMs must be at least: ${MINIMUM_IP_RETRIEVE_UPDATE_DIFF_MS}ms more than ipRetrieveTimeout(${MINIMUM_IP_RETRIEVE_TIMEOUT_MS}ms)`); } } start = async () => { await this.updatePublicIpState(); for await (const _ of setInterval(this.updateIntervalMs)) { await this.updatePublicIpState(); } }; updatePublicIpState = async () => { this.logger.debug("Getting latest public IP"); const [ipV4, ipV6] = await Promise.all([this.getPublicIpV4(), this.getPublicIpV6()]); const state = { publicIpAddresses: { v4: ipV4, v6: ipV6, }, lastPublicIpDateTime: new Date(), }; this.logger.info(`Emitting public IPs to check: v4=${ipV4}, v6=${ipV6}`); this.emit(PublicIpEvent.Retrieved, state); return state; }; getPublicIpV4 = async () => { try { return await publicIpv4({ timeout: this.ipRetrieveTimeout }); } catch (error) { this.logIpError(error, "V4"); return null; } }; getPublicIpV6 = async () => { if (!this.isIpV6Enabled) { return null; } try { return await publicIpv6({ timeout: this.ipRetrieveTimeout }); } catch (error) { this.logIpError(error, "V6"); return null; } }; logIpError = (error, version) => { if (error instanceof IpNotFoundError) { this.logger.verbose(`Could not determine IP ${version}. It may not be assigned, or this may indicate another problem (no internet access, etc.)`); } else { this.logger.error(formatError(error)); } }; } //# sourceMappingURL=public-ip-event-emitter.mjs.map