@paperbits/common
Version:
Paperbits common components.
63 lines (53 loc) • 2.53 kB
text/typescript
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;
}
}