larvitgeodata
Version:
Geo data, primarily ISO territories, languages etc. Data fetched mostly from CLDR.
339 lines (253 loc) • 8.96 kB
JavaScript
;
const EventEmitter = require('events').EventEmitter;
const {DbMigration} = require('larvitdbmigration');
const {Log} = require('larvitutils');
const async = require('async');
class Geodata {
constructor(options) {
this.options = options || {};
if (!this.options.db) throw new Error('Required option db is missing');
if (!this.options.log) {
this.options.log = new Log();
}
this.log = this.options.log;
this.db = this.options.db;
this.dbChecked = false;
this.eventEmitter = new EventEmitter();
this.labelLang = 'eng';
this.log.debug('larvitgeodata: index.js - Waiting for dbmigration()');
}
async ready() {
if (this.dbChecked) {
return;
}
const dbMigrationOptions = {};
dbMigrationOptions.dbType = this.options.dbType || 'mariadb';
dbMigrationOptions.dbDriver = this.db;
dbMigrationOptions.tableName = this.options.tableName || 'geo_db_version';
dbMigrationOptions.migrationScriptPath = this.options.migrationScriptPath || __dirname + '/dbmigration';
dbMigrationOptions.log = this.log;
const dbMigration = new DbMigration(dbMigrationOptions);
await dbMigration.run();
this.dbChecked = true;
};
async getCounties(options) {
const dbFields = [];
if (!options || !options.iso_3166_1_alpha_3) throw new Error('Required option "iso_3166_1_alpha_3" not set');
let sql = 'SELECT * FROM `geo_counties` WHERE `iso_3166_1_alpha_3` = ?';
dbFields.push(options.iso_3166_1_alpha_3);
if (options.orderBy === 'code') {
sql += ' ORDER BY `code`';
} else if (options.orderBy === 'label') {
sql += ' ORDER BY `label`';
}
const {rows} = await this.db.query(sql, dbFields);
const counties = [];
for (let i = 0; rows[i] !== undefined; i++) {
counties.push({
iso_3166_1_alpha_3: rows[i].iso_3166_1_alpha_3,
label: rows[i].label,
code: rows[i].code,
});
}
if (options.includeMunicipalities === true) {
const tasks = [];
for (let i = 0; counties[i] !== undefined; i++) {
tasks.push(async () => {
const result = await this.getMunicipalities({iso_3166_1_alpha_3: options.iso_3166_1_alpha_3, county_label: counties[i].label});
counties[i].municipalities = result;
});
}
await async.parallel(tasks);
}
return counties;
}
async getCurrencies(options) {
const dbFields = [];
let sql;
// Just currency codes
if (!options || (!options.descriptions && !options.labelLang)) {
sql = 'SELECT iso_4217 FROM `geo_currencies`';
} else {
if (options.descriptions && !options.labelLang) {
sql = 'SELECT * FROM `geo_currencies`';
}
if (options.labelLang && !options.descriptions) {
sql = 'SELECT c.iso_4217, cl.symbol, cl.displayName FROM `geo_currencies` c JOIN `geo_currencylables` cl on c.iso_4217 = cl.iso_4217 WHERE cl.langIso639_1 = ?';
dbFields.push(options.labelLang);
}
if (options.descriptions && options.labelLang) {
sql = 'SELECT c.iso_4217, c.description, cl.symbol, cl.displayName FROM `geo_currencies` c JOIN `geo_currencylables` cl on c.iso_4217 = cl.iso_4217 WHERE cl.langIso639_1 = ?';
dbFields.push(options.labelLang);
}
}
await this.ready();
const {rows} = await this.db.query(sql, dbFields);
return rows;
};
async getLanguages(options) {
const dbFields = [];
options = options || {};
if (options.gotIso639_1 === undefined) options.gotIso639_1 = true;
if (options.labelLang === undefined) options.labelLang = this.labelLang;
if (options.scope === undefined) options.scope = 'individual';
if (options.type === undefined) options.type = 'living';
if (options.iso639_3 !== undefined && options.iso639_3 !== false && !(options.iso639_3 instanceof Array)) {
options.iso639_3 = [options.iso639_3];
}
if (options.iso639_1 !== undefined && options.iso639_1 !== false && !(options.iso639_1 instanceof Array)) {
options.iso639_1 = [options.iso639_1];
}
let sql = 'SELECT langs.*, labels.label FROM geo_langs langs LEFT JOIN geo_langlabels labels ON labels.langIso639_3 = langs.iso639_3 ';
if (options.labelLang !== false && options.labelLang !== undefined && options.labelLang !== false) {
sql += ' AND labels.labelIso639_3 = ?';
dbFields.push(options.labelLang);
}
sql += ' WHERE 1 = 1';
if (options.scope !== false) {
sql += ' AND langs.scope = ?';
dbFields.push(options.scope);
}
if (options.type !== false) {
sql += ' AND langs.type = ?';
dbFields.push(options.type);
}
if (options.gotIso639_1 === false) {
sql += ' AND langs.iso639_1 IS NULL';
} else if (options.gotIso639_1 === true) {
sql += ' AND langs.iso639_1 IS NOT NULL';
}
if (options.iso639_1 !== undefined) {
sql += ' AND langs.iso639_1 IN (';
for (let i = 0; options.iso639_1[i] !== undefined; i++) {
sql += '?,';
dbFields.push(options.iso639_1[i]);
}
sql = sql.substring(0, sql.length - 1) + ')';
}
if (options.iso639_3 !== undefined) {
sql += ' AND langs.iso639_3 IN (';
for (let i = 0; options.iso639_3[i] !== undefined; i++) {
sql += '?,';
dbFields.push(options.iso639_3[i]);
}
sql = sql.substring(0, sql.length - 1) + ')';
}
sql += ' ORDER BY labels.label, langs.iso639_3';
await this.ready();
const {rows} = await this.db.query(sql, dbFields);
return rows;
};
async getMunicipalities(options) {
const dbFields = [];
if (!options || !options.iso_3166_1_alpha_3) throw new Error('Required option "iso_3166_1_alpha_3" not set');
let sql = 'SELECT * FROM geo_municipalities WHERE iso_3166_1_alpha_3 = ?';
dbFields.push(options.iso_3166_1_alpha_3);
if (options.county_label) {
sql += ' AND county_label = ?';
dbFields.push(options.county_label);
}
if (options.orderBy === 'code') {
sql += ' ORDER BY code';
} else if (options.orderBy === 'label') {
sql += ' ORDER BY label';
}
const {rows} = await this.db.query(sql, dbFields);
let municiaplities = [];
for (let i = 0; rows[i] !== undefined; i++) {
municiaplities.push({
iso_3166_1_alpha_3: rows[i].iso_3166_1_alpha_3,
county_label: rows[i].county_label,
label: rows[i].label,
code: rows[i].code,
});
}
return municiaplities;
};
async getRegionForTerritory(territoryCode) {
const tasks = [];
let regionsTerritory = null;
let regionRegions = null;
let regions = null;
tasks.push(async () => {
const {rows} = await this.db.query('SELECT * FROM geo_regions');
regions = rows;
});
tasks.push(async () => {
const {rows} = await this.db.query('SELECT * FROM geo_regions_territory WHERE contains = ?', [String(territoryCode)]);
regionsTerritory = rows;
});
tasks.push(async () => {
const {rows} = await this.db.query('SELECT * FROM geo_regions_region');
regionRegions = rows;
});
await async.parallel(tasks);
const result = [];
function getParents(regionId) {
const rr = regionRegions.find(function (item) { return item.contains === regionId; });
if (rr === undefined) {
return false;
} else {
const pr = regions.find(function (item) { return item.id === rr.id; });
const parentsParent = getParents(pr.id);
if (parentsParent) {
pr.parent = parentsParent;
}
return pr;
}
};
for (let rt of regionsTerritory) {
const region = regions.find(function (r) { return r.id === rt.id; });
if (region === undefined) {
continue;
} else {
const tp = getParents(region.id);
if (tp) {
region.parent = tp;
}
result.push(region);
}
}
return result;
};
async getTerritories(options) {
const dbFields = [];
options = options || {};
if (options.labelLang === undefined) {
options.labelLang = this.labelLang;
}
let sql = 'SELECT territories.*, labels.label FROM geo_territories territories LEFT JOIN geo_territorylabels labels ON labels.terIso3166_1_alpha_2 = territories.iso3166_1_alpha_2 ';
if (options.labelLang !== false && options.labelLang !== undefined) {
sql += ' AND labels.labelIso639_3 = ?';
dbFields.push(options.labelLang);
}
sql += ' WHERE 1 = 1';
for (let key of ['iso3166_1_num', 'iso3166_1_alpha_2', 'iso3166_1_alpha_3']) {
if (options[key] === undefined) {
continue;
} else if (!(options[key] instanceof Array)) {
options[key] = [options[key]];
}
if (options[key].length === 0) {
sql += ' AND 1 = 2';
continue;
}
sql += ' AND territories.' + key + ' IN (';
for (let i = 0; options[key][i] !== undefined; i++) {
sql += '?,';
dbFields.push(options[key][i]);
}
sql = sql.substring(0, sql.length - 1) + ')';
}
if (options.collate && options.collate !== '') {
sql += ' ORDER BY labels.label COLLATE ?, territories.iso3166_1_alpha_2';
dbFields.push(options.collate);
} else {
sql += ' ORDER BY labels.label, territories.iso3166_1_alpha_2';
}
await this.ready();
const {rows} = await this.db.query(sql, dbFields);
return rows;
};
}
exports = module.exports = Geodata;