import { Route53Client } from '@aws-sdk/client-route-53'; let route53ClientInstance: Route53Client | null = null; /** * Check if AWS Route 53 credentials are configured. */ export function isRoute53Configured(): boolean { return !!(process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY); } /** * Get or create the Route 53 client singleton instance. * * Intentionally does NOT pass an explicit `credentials` option — omitting it * lets @aws-sdk/credential-provider-node's default credential chain read * AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY / AWS_SESSION_TOKEN from * process.env automatically (fromEnv() is first in the chain). This is * exactly how Bitwarden Secrets Manager (`bws run`) injects credentials at * the docker-entrypoint.sh layer. Do NOT "fix" this by adding an explicit * credentials object — see 24-RESEARCH.md Pitfall 1. */ export function getRoute53Client(): Route53Client { if (!route53ClientInstance) { if (!isRoute53Configured()) { throw new Error( 'AWS credentials missing. Please set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY (and AWS_REGION) environment variables.' ); } // Route 53 is a global service but the SDK still requires a signing // region; us-east-1 is the conventional default AWS's own CLI/console use. route53ClientInstance = new Route53Client({ region: process.env.AWS_REGION || 'us-east-1', }); console.log('Route 53 client initialized'); } return route53ClientInstance; } /** * Reset the singleton instance (useful for testing). */ export function resetRoute53Client(): void { route53ClientInstance = null; }