import { NAuthConfig } from '../interfaces/config.interface'; import { StorageAdapter } from '../interfaces/storage-adapter.interface'; import { NAuthLogger } from '../utils/nauth-logger'; /** * MaxMind GeoIP2 Reader type (optional dependency) * Only available if @maxmind/geoip2-node is installed * * The Reader class has city() and country() methods that return response objects */ type MaxMindReader = { city: (ip: string) => { country?: { isoCode?: string; names?: { en?: string; }; isInEuropeanUnion?: boolean; }; city?: { names?: { en?: string; }; }; subdivisions?: Array<{ names?: { en?: string; }; }>; postal?: { code?: string; }; location?: { latitude?: number; longitude?: number; timeZone?: string; }; continent?: { code?: string; names?: { en?: string; }; }; }; country: (ip: string) => { country?: { isoCode?: string; names?: { en?: string; }; isInEuropeanUnion?: boolean; }; continent?: { code?: string; names?: { en?: string; }; }; }; }; /** * MaxMind library module type (optional peer dependency) * Injected via dependency injection if package is installed */ type MaxMindModule = { Reader: { open: (dbPath: string) => Promise; }; }; /** * GeoLocation Service * * Provides IP geolocation using MaxMind GeoIP2 database files. * Platform-agnostic - works on all platforms where Node.js runs. * * Features: * - IP to country/city lookup from MaxMind .mmdb files * - Distributed locking for database updates (multi-server safe) * - Configurable database path (defaults to system temp directory) * - Graceful degradation if MaxMind not installed * * Requirements: * - @maxmind/geoip2-node peer dependency must be installed * - MaxMind license key and account ID for database downloads * - Storage adapter (for distributed locking) * * @example * ```typescript * // Get geolocation for an IP * const geo = await geoLocationService.getIpGeolocation('8.8.8.8'); * console.log(geo.country); // 'US' * console.log(geo.city); // 'Mountain View' * ``` */ export declare class GeoLocationService { private readonly storageAdapter; private readonly logger?; private readonly config; private readonly dbPath; private readonly maxMindLib; private cityReader; private countryReader; private readonly defaultEditions; private readonly lockKey; private readonly lockTtlSeconds; constructor(nauthConfig: NAuthConfig, storageAdapter: StorageAdapter, maxMindLib?: MaxMindModule | null, logger?: NAuthLogger | undefined); /** * Initialize service on module startup * * - Loads database files if they exist * - Optionally downloads databases if autoDownloadOnStartup is enabled */ onModuleInit(): Promise; /** * Get geolocation information for an IP address * * @param ip - IP address to lookup * @returns Geolocation info with country, city, and coordinates (if available) * * @example * ```typescript * const geo = await geoLocationService.getIpGeolocation('8.8.8.8'); * // { country: 'US', city: 'Mountain View', latitude: 37.386, longitude: -122.0838 } * ``` */ getIpGeolocation(ip: string): Promise<{ country?: string; city?: string; latitude?: number; longitude?: number; }>; /** * Reload MaxMind database files from disk * * Reloads .mmdb files from the configured dbPath without downloading. * Useful when database files are managed externally (e.g., via geoipupdate, * cron jobs, or container volume updates). * * This method will: * - Attempt to load GeoLite2-City.mmdb * - Attempt to load GeoLite2-Country.mmdb * - Replace in-memory database readers with newly loaded ones * - Log warnings if no database files are found * * Safe to call repeatedly - if files haven't changed, it just reloads the same data. * * @example * ```typescript * // After external process updates database files * await geoLocationService.reloadGeoLocationDatabaseFromDisk(); * ``` * * @example * ```typescript * // In a NestJS scheduled job * @Cron('0 0 * * *') * async reloadGeoDb() { * await this.geoLocationService.reloadGeoLocationDatabaseFromDisk(); * } * ``` */ reloadGeoLocationDatabaseFromDisk(): Promise; /** * Update MaxMind GeoIP2 database files * * Downloads the latest database files from MaxMind using distributed locking * to prevent concurrent downloads in multi-server deployments, then reloads * the in-memory database readers. * * Uses storage adapter for distributed locking: * - Lock key: 'maxmind-db-update-lock' * - Lock TTL: 5 minutes (300 seconds) * - Only one server/process can download at a time * * After successful download, the in-memory database readers are automatically * updated to use the new files. * * @throws {NAuthException} If MaxMind credentials are missing or download fails * * @example * ```typescript * // Call this method via cron job for periodic updates * await geoLocationService.updateGeoLocationDatabase(); * ``` */ updateGeoLocationDatabase(): Promise; /** * Ensure database directory exists * * Creates the directory if it doesn't exist. */ private ensureDbDirectoryExists; /** * Load database files from disk * * Loads .mmdb files for City and Country databases if they exist. */ private loadDatabaseFiles; /** * Download a MaxMind database file * * Downloads the specified edition from MaxMind's download API, * extracts the .mmdb file from the tar.gz archive, and saves it. * * Uses Node.js built-in zlib for gzip decompression and implements * basic tar parsing to extract the .mmdb file. * * @param edition - Edition name (e.g., 'GeoLite2-City') * @param accountId - MaxMind account ID * @param licenseKey - MaxMind license key */ private downloadDatabase; /** * Extract .mmdb file from tar.gz archive * * Uses Node.js built-in zlib for gzip decompression and implements * basic tar parsing to find and extract the .mmdb file. * * @param tarGzPath - Path to the .tar.gz file * @param outputPath - Path where .mmdb file should be saved * @param edition - Edition name (to find correct file in archive) */ private extractTarGz; } export {}; //# sourceMappingURL=geo-location.service.d.ts.map