utils.ts (3445B)
1 import type { GeolocationPoint } from "@radroots/geo"; 2 import { parse_route_path, resolve_route_path } from "@radroots/utils"; 3 import type { GeocoderReverseResult, IGeocoderCountryListResult } from "./types.js"; 4 5 export const DEFAULT_GEOCODER_DATABASE_FILE = `geonames.db`; 6 export const DEFAULT_GEOCODER_DATABASE_PATH = `https://assets.radroots.org/data/geonames/geonames-1.0.db`; 7 const GEOCODER_DATABASE_FILE_EXTS = [`.db`]; 8 9 export type GeocoderDatabaseRoute = { 10 base_path: string; 11 file_name: string | null; 12 query: string; 13 hash: string; 14 }; 15 16 const is_geocoder_database_file = (segment: string): boolean => { 17 const lower_segment = segment.toLowerCase(); 18 return GEOCODER_DATABASE_FILE_EXTS.some((ext) => lower_segment.endsWith(ext)); 19 }; 20 21 export const parse_geocoder_database_route = (database_path: string): GeocoderDatabaseRoute => { 22 const { path, query, hash } = parse_route_path(database_path); 23 const trimmed_path = path.endsWith(`/`) ? path.slice(0, -1) : path; 24 const last_slash = trimmed_path.lastIndexOf(`/`); 25 const last_segment = last_slash >= 0 ? trimmed_path.slice(last_slash + 1) : trimmed_path; 26 const file_name = is_geocoder_database_file(last_segment) ? last_segment : null; 27 const base_path = file_name && last_slash >= 0 ? trimmed_path.slice(0, last_slash) : trimmed_path; 28 return { base_path, file_name, query, hash }; 29 }; 30 31 export const resolve_geocoder_database_path = (database_path?: string): string => 32 resolve_route_path( 33 database_path, 34 DEFAULT_GEOCODER_DATABASE_FILE, 35 DEFAULT_GEOCODER_DATABASE_PATH, 36 GEOCODER_DATABASE_FILE_EXTS 37 ); 38 39 export const parse_geocode_reverse_result = (obj: any): GeocoderReverseResult | undefined => { 40 if (typeof obj !== `object` || !obj) return undefined; 41 const { id, name, admin1_id, admin1_name, country_id, country_name, latitude, longitude } = obj; 42 if ( 43 typeof id === `number` && 44 typeof name === `string` && 45 (typeof admin1_id === `string` || typeof admin1_id === `number`) && 46 typeof admin1_name === `string` && 47 typeof country_id === `string` && 48 typeof country_name === `string` && 49 typeof latitude === `number` && 50 typeof longitude === `number` 51 ) { 52 return { 53 id, 54 name, 55 admin1_id, 56 admin1_name, 57 country_id, 58 country_name, 59 latitude, 60 longitude 61 }; 62 } 63 return undefined; 64 }; 65 66 export const parse_geocode_country_list_result = (obj: any): IGeocoderCountryListResult | undefined => { 67 if (typeof obj !== `object` || !obj) return undefined; 68 const { country_id, country_name: country, latitude_c: lat, longitude_c: lng } = obj; 69 if ( 70 typeof country_id === `string` && 71 typeof country === `string` && 72 typeof lat === `number` && 73 typeof lng === `number` 74 ) { 75 return { 76 country_id, 77 country, 78 lat, 79 lng 80 }; 81 } 82 return undefined; 83 }; 84 85 export const parse_geocode_country_center_result = (obj: any): GeolocationPoint | undefined => { 86 if (typeof obj !== `object` || !obj) return undefined; 87 const { latitude_c: lat, longitude_c: lng } = obj; 88 if ( 89 typeof lat === `number` && 90 typeof lng === `number` 91 ) { 92 return { 93 lat, 94 lng 95 }; 96 } 97 return undefined; 98 };