UNPKG

maplibre-gl-js-amplify

Version:

MapLibre Plugin to Support Amplify Geo Integration

137 lines (136 loc) 7.35 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; var _a; Object.defineProperty(exports, "__esModule", { value: true }); exports.createMap = void 0; const core_1 = require("@aws-amplify/core"); const utils_1 = require("@aws-amplify/core/internals/utils"); const geo_1 = require("@aws-amplify/geo"); const maplibre_gl_1 = require("maplibre-gl"); const utils_2 = require("./utils"); /** * An object for encapsulating an Amplify Geo transform request and Amplify credentials * @class AmplifyMapLibreRequest * @param {ICredentials} currentCredentials Amplify credentials used for signing transformRequests * @param {String} region AWS region * @return {AmplifyMapLibreRequest} `this` * */ class AmplifyMapLibreRequest { constructor(currentCredentials, region) { this.refreshCredentials = () => __awaiter(this, void 0, void 0, function* () { try { this.credentials = (yield (0, core_1.fetchAuthSession)()).credentials; } catch (e) { // eslint-disable-next-line no-console console.error(`Failed to refresh credentials: ${e}`); throw e; } }); this.refreshCredentialsWithRetry = () => __awaiter(this, void 0, void 0, function* () { try { const MAX_DELAY_MS = 5 * 60 * 1000; // 5 minutes yield (0, utils_1.jitteredExponentialRetry)(this.refreshCredentials, [], MAX_DELAY_MS); // Refresh credentials on a timer because HubEvents do not trigger on credential refresh currently this.activeTimeout && clearTimeout(this.activeTimeout); // Refresh credentials when expiration time is later than now if (this.credentials.expiration.getTime() > new Date().getTime()) { const expiration = new Date(this.credentials.expiration); const timeout = expiration.getTime() - new Date().getTime() - 10000; // Adds a 10 second buffer time before the next refresh this.activeTimeout = window.setTimeout(this.refreshCredentialsWithRetry, Math.min(timeout, 3600000) // Set timeout to an hour if we somehow don't have a value for timeout ); } } catch (e) { // eslint-disable-next-line no-console console.error(`Failed to refresh credentials: ${e}`); } }); /** * A callback function that can be passed to a maplibre map object that is run before the map makes a request for an external URL. This transform request is used to sign the request with AWS Sigv4 Auth. [https://maplibre.org/maplibre-gl-js-docs/api/map/](https://maplibre.org/maplibre-gl-js-docs/api/map/) * @param {string} url * @param {string} resourceType * @returns {RequestParameters} [https://maplibre.org/maplibre-gl-js-docs/api/properties/#requestparameters](https://maplibre.org/maplibre-gl-js-docs/api/properties/#requestparameters) */ this.transformRequest = (url, resourceType) => { let styleUrl = url; if (resourceType === 'Style' && !url.includes('://')) { if (this.region == undefined) { throw new Error('AWS region for map is undefined. Please verify that the region is set in aws-exports.js or that you are providing an AWS region parameter to createMap'); } styleUrl = `https://maps.geo.${this.region}.amazonaws.com/maps/v0/maps/${url}/style-descriptor`; } const urlObject = new URL(styleUrl); if (urlObject.hostname.endsWith('.amazonaws.com')) { // only sign AWS requests (with the signature as part of the query string) urlObject.searchParams.append('x-amz-user-agent', encodeURIComponent((0, utils_2.urlEncodePeriods)(getAmplifyUserAgentString()))); return { url: utils_1.Signer.signUrl(urlObject.href, { access_key: this.credentials.accessKeyId, secret_key: this.credentials.secretAccessKey, session_token: this.credentials.sessionToken, }), }; } }; this.credentials = currentCredentials; this.region = region; this.activeTimeout = null; this.refreshCredentialsWithRetry(); core_1.Hub.listen('auth', (data) => { switch (data.payload.event) { // This was removed from v6 but will be added back before GA case 'signedIn': case 'signedOut': case 'tokenRefresh': this.refreshCredentialsWithRetry(); break; } }); } } exports.default = AmplifyMapLibreRequest; _a = AmplifyMapLibreRequest; AmplifyMapLibreRequest.createMapLibreMap = (options) => __awaiter(void 0, void 0, void 0, function* () { const { region, mapConstructor = maplibre_gl_1.Map } = options, maplibreOption = __rest(options, ["region", "mapConstructor"]); const defaultMap = geo_1.Geo.getDefaultMap(); const amplifyRequest = new AmplifyMapLibreRequest((yield (0, core_1.fetchAuthSession)()).credentials, region || defaultMap.region); const transformRequest = amplifyRequest.transformRequest; const map = new mapConstructor(Object.assign(Object.assign({}, maplibreOption), { style: options.style || defaultMap.mapName, // Amplify uses the name of the map in the maplibre style field, transformRequest })); return map; }); const createMap = (options) => __awaiter(void 0, void 0, void 0, function* () { return AmplifyMapLibreRequest.createMapLibreMap(options); }); exports.createMap = createMap; // TODO - Delete this and import from @aws-amplify/core when it is released function getAmplifyUserAgentString() { const userAgent = (0, utils_1.getAmplifyUserAgent)(); if (userAgent && typeof userAgent === 'object') { return userAgent .map(([agentKey, agentValue]) => `${agentKey}/${agentValue}`) .join(' '); } return userAgent; }