UNPKG

@googlemaps/google-maps-services-js

Version:

Node.js client library for Google Maps API Web Services

175 lines (151 loc) 4.72 kB
/** * Copyright 2020 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { LatLng, LatLngBounds, LatLngLiteral } from "./common"; import { encodePath } from "./util"; import { createSignature } from "@googlemaps/url-signature"; import queryString from "query-string"; const qs = queryString.stringify; const separator = "|"; export function latLngToString(o: LatLng) { if (typeof o === "string") { return o; } else if (Array.isArray(o) && o.length === 2) { // no transformation } else if ("lat" in o && "lng" in o) { o = [o.lat, o.lng]; } else if ("latitude" in o && "longitude" in o) { o = [o.latitude, o.longitude]; } else { throw new TypeError(); } return o .map((x) => { return x.toString(); }) .join(","); } export function enableAddressDescriptorToString(o: boolean) { if (typeof o === "string") { return o; } else if (o == true) { return "True"; } else { return "False"; } } export function objectToString(o: string | object): string { if (typeof o === "string") { return o; } else { const keys = Object.keys(o); keys.sort(); return keys.map((k) => k + ":" + o[k]).join(separator); } } export function latLngBoundsToString(latLngBounds: string | LatLngBounds) { if (typeof latLngBounds === "string") { return latLngBounds; } else { return ( latLngToString(latLngBounds.southwest) + separator + latLngToString(latLngBounds.northeast) ); } } export function toLatLngLiteral(o: LatLng): LatLngLiteral { if (typeof o === "string") { const parts = o.split(",").map(Number); return { lat: parts[0], lng: parts[1] }; } else if (Array.isArray(o) && o.length === 2) { const parts = o.map(Number); return { lat: parts[0], lng: parts[1] }; } else if ("lat" in o && "lng" in o) { return o; } else if ("latitude" in o && "longitude" in o) { return { lat: o.latitude, lng: o.longitude }; } else { throw new TypeError(); } } export function latLngArrayToStringMaybeEncoded(o: string | LatLng[]): string { if (typeof o === "string") { return o; } const concatenated = o.map(latLngToString).join(separator); const encoded = `enc:${encodePath(o.map(toLatLngLiteral))}`; if (encoded.length < concatenated.length) { return encoded; } return concatenated; } export type serializerFunction = (any) => string | number | boolean; export type serializerFormat = { [key: string]: serializerFunction }; export function serializer( format: serializerFormat, baseUrl: string, queryStringOptions: object = { arrayFormat: "separator", arrayFormatSeparator: separator, } ) { // eslint-disable-next-line @typescript-eslint/no-explicit-any return (params: Record<string, any>) => { // avoid mutating params const serializedParams = { ...params }; for (const key of Object.keys(format)) { if (key in serializedParams) { serializedParams[key] = format[key](serializedParams[key]); } } if ( "client_id" in serializedParams && "client_secret" in serializedParams ) { // Special case to handle premium plan signature return createPremiumPlanQueryString( serializedParams, queryStringOptions, baseUrl ); } return qs(serializedParams, queryStringOptions); }; } export function toTimestamp(o: "now" | number | Date): number | "now" { if (o === "now") { return o; } if (o instanceof Date) { return Math.round(Number(o) / 1000); } return o; } export function createPremiumPlanQueryString( serializedParams: { [key: string]: string }, queryStringOptions: object, baseUrl: string ): string { serializedParams.client = serializedParams.client_id; const clientSecret = serializedParams.client_secret; delete serializedParams.client_id; delete serializedParams.client_secret; const partialQueryString = qs(serializedParams, queryStringOptions); const unsignedUrl = `${baseUrl}?${partialQueryString}`; const signature = createSignature(unsignedUrl, clientSecret); // The signature must come last return `${partialQueryString}&signature=${signature}`; }