UNPKG

node-iplocate

Version:

Find geolocation data from IP addresses (e.g. city, country, timezone) using the IPLocate.io API

154 lines (151 loc) 4.63 kB
import { isValidIp } from 'ip-utils'; // src/errors.ts var IPLocateError = class extends Error { constructor(message) { super(message); this.name = "IPLocateError"; } }; var InvalidIPError = class extends IPLocateError { constructor(ip) { super(`Invalid IP address: ${ip}`); this.name = "InvalidIPError"; } }; var AuthenticationError = class extends IPLocateError { constructor(message = "Invalid API key") { super(message); this.name = "AuthenticationError"; } }; var NotFoundError = class extends IPLocateError { constructor(message = "IP address not found") { super(message); this.name = "NotFoundError"; } }; var RateLimitError = class extends IPLocateError { constructor(message = "Rate limit exceeded. Upgrade your plan at https://iplocate.io/account") { super(message); this.name = "RateLimitError"; } }; var APIError = class extends IPLocateError { constructor(message, statusCode) { super(message); this.name = "APIError"; this.statusCode = statusCode; } }; // src/utils.ts function encodeIP(ip) { return encodeURIComponent(ip); } var DEFAULT_BASE_URL = "https://iplocate.io/api"; var DEFAULT_TIMEOUT = 5e3; var IPLocate = class { /** * Create a new IPLocate client * @param apiKey Your IPLocate API key * @param options Configuration options */ constructor(apiKey, options = {}) { if (!apiKey || typeof apiKey !== "string") { throw new IPLocateError("API key is required"); } this.apiKey = apiKey; this.baseUrl = options.baseUrl?.replace(/\/$/, "") || DEFAULT_BASE_URL; this.timeout = options.timeout || DEFAULT_TIMEOUT; this.httpClientOptions = options.httpClientOptions || {}; } /** * Look up geolocation and threat intelligence data for an IP address * @param ip The IP address to look up * @returns Promise resolving to lookup response */ async lookup(ip) { if (!isValidIp(ip)) { throw new InvalidIPError(ip); } const endpoint = `${this.baseUrl}/lookup/${encodeIP(ip)}`; return this.makeRequest(endpoint); } /** * Look up geolocation and threat intelligence data for the client's current IP address * @returns Promise resolving to lookup response */ async lookupSelf() { const endpoint = `${this.baseUrl}/lookup/`; return this.makeRequest(endpoint); } /** * Make HTTP request to the IPLocate API * @param endpoint The API endpoint URL * @returns Promise resolving to lookup response */ async makeRequest(endpoint) { const url = new URL(endpoint); url.searchParams.set("apikey", this.apiKey); const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), this.timeout); try { const response = await fetch(url.toString(), { method: "GET", ...this.httpClientOptions, headers: { "Accept": "application/json", "User-Agent": "node-iplocate/2.0.1", ...this.httpClientOptions.headers }, signal: controller.signal }); clearTimeout(timeoutId); if (!response.ok) { await this.handleErrorResponse(response); } const data = await response.json(); return data; } catch (error) { clearTimeout(timeoutId); if (error instanceof IPLocateError) { throw error; } if (error instanceof Error) { if (error.name === "AbortError") { throw new IPLocateError(`Request timeout after ${this.timeout}ms`); } throw new IPLocateError(`Request failed: ${error.message}`); } throw new IPLocateError("Unknown error occurred"); } } /** * Handle error responses from the API * @param response The fetch response object */ async handleErrorResponse(response) { let errorMessage = `HTTP ${response.status}: ${response.statusText}`; try { const errorData = await response.json(); if (errorData.error) { errorMessage = errorData.error; } } catch { } switch (response.status) { case 400: throw new InvalidIPError(errorMessage); case 403: throw new AuthenticationError(errorMessage); case 404: throw new NotFoundError(errorMessage); case 429: throw new RateLimitError(errorMessage); default: throw new APIError(errorMessage, response.status); } } }; export { APIError, AuthenticationError, IPLocate, IPLocateError, InvalidIPError, NotFoundError, RateLimitError, IPLocate as default }; //# sourceMappingURL=index.mjs.map //# sourceMappingURL=index.mjs.map