geocoder-dadata
Version:
Dadata geocoder API client that supports caching and is written purely on typescript
102 lines (101 loc) • 4.18 kB
JavaScript
;
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 : '';
}
}