web_lib

Common web application libraries
git clone https://radroots.dev/git/web_lib.git
Log | Files | Refs | LICENSE

commit bad79af3f3f239832d673b248c43343b78e19e34
parent 5e34e8c3d8421b571943aec66200880a96ce8d4c
Author: triesap <137732411+triesap@users.noreply.github.com>
Date:   Mon, 28 Oct 2024 13:37:13 +0000

geocoder: edit geocoder add class interface and methods

Diffstat:
Mgeocoder/src/geocoder.ts | 78+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
Dgeocoder/src/global.d.ts | 6------
Mgeocoder/src/types.ts | 24++++++++++++++++++++++++
Mgeocoder/src/utils.ts | 79+++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
4 files changed, 146 insertions(+), 41 deletions(-)

diff --git a/geocoder/src/geocoder.ts b/geocoder/src/geocoder.ts @@ -1,11 +1,11 @@ -import { err_msg, type ErrorMessage, type GeolocationCoordinatesPoint, type ResultsList } from "@radroots/utils"; +import { err_msg, ResultObj, type ErrorMessage, type GeolocationCoordinatesPoint, type ResultsList } from "@radroots/utils"; import type { Database } from "sql.js"; -import type { GeocoderDegreeOffset, GeocoderErrorMessage, GeocoderReverseResult } from "./types"; -import { parse_geocode_reverse_result } from "./utils"; +import type { GeocoderErrorMessage, GeocoderReverseResult, IGeocoder, IGeocoderCountryCenter, IGeocoderCountryListResult, IGeocoderReverse } from "./types"; +import { parse_geocode_country_center_result, parse_geocode_country_list_result, parse_geocode_reverse_result } from "./utils"; const KM_PER_DEGREE_LATITUDE = 111; -export class Geocoder { +export class Geocoder implements IGeocoder { private _db: Database | null = null; private _database_name: string; @@ -28,13 +28,7 @@ export class Geocoder { }; } - - - public async reverse(opts: { - point: GeolocationCoordinatesPoint; - degree_offset?: GeocoderDegreeOffset; - limit?: number | false; - }): Promise<ResultsList<GeocoderReverseResult> | ErrorMessage<GeocoderErrorMessage>> { + public async reverse(opts: IGeocoderReverse): Promise<ResultsList<GeocoderReverseResult> | ErrorMessage<GeocoderErrorMessage>> { try { if (!this._db) return err_msg(`*-db`); const limit = typeof opts.limit === `boolean` ? `` : opts.limit ? Math.round(opts.limit) : `1`; @@ -58,4 +52,63 @@ export class Geocoder { return err_msg(`*`); }; } -} -\ No newline at end of file + + public async country(opts: IGeocoderCountryCenter): Promise<ResultsList<GeocoderReverseResult> | ErrorMessage<GeocoderErrorMessage>> { + try { + if (!this._db) return err_msg(`*-db`); + const query = `SELECT * FROM geonames WHERE country_id = $id;` + const stmt = this._db.prepare(query); + if (!stmt) return err_msg(`*-statement`); + const $id = opts.country_id + stmt.bind({ $id }); + const results: GeocoderReverseResult[] = []; + while (stmt.step()) { + const result = parse_geocode_reverse_result(stmt.getAsObject()); + if (result) results.push(result); + }; + return { results }; + } catch (e) { + console.log(`Error: Geocoder reverse `, e); + return err_msg(`*`); + }; + } + + public async country_list(): Promise<ResultsList<IGeocoderCountryListResult> | ErrorMessage<GeocoderErrorMessage>> { + try { + if (!this._db) return err_msg(`*-db`); + const query = `SELECT country_id, country_name, AVG(latitude) AS latitude_c, AVG(longitude) AS longitude_c FROM geonames GROUP BY country_id;` + const stmt = this._db.prepare(query); + if (!stmt) return err_msg(`*-statement`); + const results: IGeocoderCountryListResult[] = []; + while (stmt.step()) { + const result = parse_geocode_country_list_result(stmt.getAsObject()); + if (result) results.push(result); + }; + return { results }; + } catch (e) { + console.log(`Error: Geocoder reverse `, e); + return err_msg(`*`); + }; + } + + + public async country_center(opts: IGeocoderCountryCenter): Promise<ResultObj<GeolocationCoordinatesPoint> | ErrorMessage<GeocoderErrorMessage>> { + try { + if (!this._db) return err_msg(`*-db`); + const query = `SELECT AVG(latitude) AS latitude_c, AVG(longitude) AS longitude_c FROM geonames WHERE country_id = $id;`; + const stmt = this._db.prepare(query); + if (!stmt) return err_msg(`*-statement`); + const $id = opts.country_id + stmt.bind({ $id }); + while (stmt.step()) { + const result = parse_geocode_country_center_result(stmt.getAsObject()); + if (result) return { result }; + }; + return err_msg(`*-result`); + } catch (e) { + console.log(`Error: Geocoder reverse `, e); + return err_msg(`*`); + }; + } +} + diff --git a/geocoder/src/global.d.ts b/geocoder/src/global.d.ts @@ -1,6 +0,0 @@ -declare module 'jshashes' { - export class SHA256 { - b64(input: string): string; - b64_hmac(key: string, input: string): string; - } -} diff --git a/geocoder/src/types.ts b/geocoder/src/types.ts @@ -1,4 +1,7 @@ +import type { ErrorMessage, GeolocationCoordinatesPoint, ResultObj, ResultsList } from "@radroots/utils"; + export type GeocoderErrorMessage = + | `*-result` | `*-statement` | `*-db` | `*` @@ -15,3 +18,23 @@ export type GeocoderReverseResult = { }; export type GeocoderDegreeOffset = 0.5 | 1.0 | 1.5 | 2.0 | 2.5 | 3 + +export type IGeocoderReverse = { + point: GeolocationCoordinatesPoint; + degree_offset?: GeocoderDegreeOffset; + limit?: number | false; +}; + +export type IGeocoderCountryCenter = { + country_id: string; +}; + +export type IGeocoderCountryListResult = GeolocationCoordinatesPoint & { country_id: string; country: string }; + +export type IGeocoder = { + connect(): Promise<true | ErrorMessage<GeocoderErrorMessage>>; + reverse(opts: IGeocoderReverse): Promise<ResultsList<GeocoderReverseResult> | ErrorMessage<GeocoderErrorMessage>>; + country(opts: IGeocoderCountryCenter): Promise<ResultsList<GeocoderReverseResult> | ErrorMessage<GeocoderErrorMessage>>; + country_list(): Promise<ResultsList<IGeocoderCountryListResult> | ErrorMessage<GeocoderErrorMessage>>; + country_center(opts: IGeocoderCountryCenter): Promise<ResultObj<GeolocationCoordinatesPoint> | ErrorMessage<GeocoderErrorMessage>> +} +\ No newline at end of file diff --git a/geocoder/src/utils.ts b/geocoder/src/utils.ts @@ -1,29 +1,63 @@ -import type { GeocoderReverseResult } from "./types"; +import type { GeolocationCoordinatesPoint } from "@radroots/utils"; +import type { GeocoderReverseResult, IGeocoderCountryListResult } from "./types"; export const parse_geocode_reverse_result = (obj: any): GeocoderReverseResult | undefined => { - if (typeof obj !== 'object' || !obj) return undefined; + if (typeof obj !== `object` || !obj) return undefined; const { id, name, admin1_id, admin1_name, country_id, country_name, latitude, longitude } = obj; if ( - typeof id !== `number` || - typeof name !== `string` || - typeof admin1_id !== `string` || - typeof admin1_name !== `string` || - typeof country_id !== `string` || - typeof country_name !== `string` || - typeof latitude !== `number` || - typeof longitude !== `number` + typeof id === `number` && + typeof name === `string` && + (typeof admin1_id === `string` || typeof admin1_id === `number`) && + typeof admin1_name === `string` && + typeof country_id === `string` && + typeof country_name === `string` && + typeof latitude === `number` && + typeof longitude === `number` ) { - return undefined; + return { + id, + name, + admin1_id, + admin1_name, + country_id, + country_name, + latitude, + longitude + }; } - const result: GeocoderReverseResult = { - id, - name, - admin1_id, - admin1_name, - country_id, - country_name, - latitude, - longitude - }; - return result; + return undefined; }; + +export const parse_geocode_country_list_result = (obj: any): IGeocoderCountryListResult | undefined => { + if (typeof obj !== `object` || !obj) return undefined; + const { country_id, country_name: country, latitude_c: lat, longitude_c: lng } = obj; + if ( + typeof country_id === `string` && + typeof country === `string` && + typeof lat === `number` && + typeof lng === `number` + ) { + return { + country_id, + country, + lat, + lng + }; + } + return undefined; +}; + +export const parse_geocode_country_center_result = (obj: any): GeolocationCoordinatesPoint | undefined => { + if (typeof obj !== `object` || !obj) return undefined; + const { latitude_c: lat, longitude_c: lng } = obj; + if ( + typeof lat === `number` && + typeof lng === `number` + ) { + return { + lat, + lng + }; + } + return undefined; +}; +\ No newline at end of file