UNPKG

geocoder-dadata

Version:

Dadata geocoder API client that supports caching and is written purely on typescript

102 lines (101 loc) 4.18 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Geocoder = void 0; const node_fetch_1 = __importDefault(require("node-fetch")); const pace_keeper_1 = require("pace-keeper"); const ENV_API_URL = 'DADATA_API_URL'; const ENV_API_TOKEN = 'DADATA_API_TOKEN'; const ENV_API_SECRET = 'DADATA_API_SECRET'; const PACE_INTERVAL = 1000; const PACE_LIMIT = 5; const DEFAULT_API_URL = "https://cleaner.dadata.ru/api/v1/clean/address"; const CACHE = {}; class Geocoder { constructor({ api_token, api_secret, api_url, pace_limit, cached } = { cached: true }) { Object.defineProperty(this, 'API_TOKEN', { enumerable: false, writable: false, value: api_token || process.env[ENV_API_TOKEN] }); Object.defineProperty(this, 'API_SECRET', { enumerable: false, writable: false, value: api_secret || process.env[ENV_API_SECRET] }); this.API_URL = api_url || process.env[ENV_API_URL] || DEFAULT_API_URL; this.pace = new pace_keeper_1.Pacekeeper({ interval: PACE_INTERVAL, pace: pace_limit || PACE_LIMIT, parse_429: true }); this.cached = cached === undefined ? true : !!cached; } geocode(query) { if (!query) return Promise.resolve(build_error({ status: 0, statusText: 'empty query' })); if (typeof query === 'string') query = [query]; if (!Array.isArray(query)) return Promise.resolve(build_error({ status: 0, statusText: 'bad query' })); query = query.filter(i => i && typeof i === 'string'); if (query.length < 1) return Promise.resolve(build_error({ status: 0, statusText: 'empty query' })); let key = Array.isArray(query) ? query.sort().join(';') : query; let body = JSON.stringify(query); let headers = { "Content-Type": 'application/json', "Authorization": `Token ${this.API_TOKEN}`, "X-Secret": `${this.API_SECRET}` }; if (this.cached) { let cached = CACHE[key.toLowerCase()]; if (cached) return Promise.resolve(cached); } return this.pace .submit(() => node_fetch_1.default(this.API_URL, { headers, body, method: 'POST' })).promise .then(res => typeof (res === null || res === void 0 ? void 0 : res.json) === 'function' ? res.json().then(build_result(res, this.cached, key)) : build_error(res)); } } exports.Geocoder = Geocoder; exports.default = Geocoder; function build_result(res, cache = false, key = '') { return function (body) { let result = new GeoResult({ status: { code: res.status, message: res.statusText }, results: body }); if (cache && key && typeof key === 'string') { CACHE[key] = result; } return result; }; } function build_error(res) { return new GeoResult({ status: { code: res === null || res === void 0 ? void 0 : res.status, message: res === null || res === void 0 ? void 0 : res.statusText } }); } class GeoResult { constructor(data) { Object.assign(this, data); } get total_results() { return Array.isArray(this.results) ? this.results.length : 0; } get ok() { var _a; return ((_a = this.status) === null || _a === void 0 ? void 0 : _a.code) === 200 && (this.total_results ? this.total_results > 0 : false); } get geo() { return this.ok && Array.isArray(this.results) && this.results.length > 0 ? { lat: this.results[0].geo_lat || void 0, lng: this.results[0].geo_lon || void 0 } : { lat: void 0, lng: void 0 }; } get address() { return this.ok && Array.isArray(this.results) && this.results.length > 0 ? this.results[0].result : ''; } }