UNPKG

@paperbits/common

Version:
63 lines (53 loc) 2.53 kB
import { Loader, LoaderOptions } from "@googlemaps/js-api-loader"; import { Geolocation, GeocodingService } from "./"; export class GoogleGeocodingService implements GeocodingService { private initPromise: Promise<any>; private geocoder: google.maps.Geocoder; constructor(private readonly googleMapsApiKey: string) { this.geocode = this.geocode.bind(this); this.initialize(); } public initialize(): Promise<void> { if (this.initPromise) { return this.initPromise; } this.initPromise = this.loadGoogleApi(); return this.initPromise; } private async loadGoogleApi(): Promise<void> { const options: Partial<LoaderOptions> = {/* todo */ }; const loader = new Loader({ apiKey: this.googleMapsApiKey, ...options }); const google = await loader.load(); this.geocoder = new google.maps.Geocoder(); } private geocode(request: google.maps.GeocoderRequest): Promise<google.maps.LatLng> { return new Promise<google.maps.LatLng>((resolve, reject) => { this.geocoder.geocode(request, (results: google.maps.GeocoderResult[], status) => { switch (status) { case google.maps.GeocoderStatus.OK: const position = results[0].geometry.location; resolve(position); break; case google.maps.GeocoderStatus.REQUEST_DENIED: reject(`Could not geocode specified location. This wesbite or API key is not allowed to use geocoder.`); break; case google.maps.GeocoderStatus.OVER_QUERY_LIMIT: reject(`Could not geocode specified location. Request limit exceeded.`); break; default: reject(`Could not geocode specified location.`); } }); }); } public async addressToGeolocation(address: string): Promise<Geolocation> { if (!this.googleMapsApiKey) { throw new Error(`Google Maps API key not specified.`); } await this.initialize(); const request: google.maps.GeocoderRequest = { address: address }; const response = await this.geocode(request); const result = { address: address, lat: response.lat(), lng: response.lng() }; return result; } }