UNPKG

s2maps-gpu

Version:

S2 Maps GPU - An open source, high-performance, and GPU-accelerated map engine for rendering large-scale, interactive maps.

132 lines (131 loc) 4.69 kB
import { adjustURL } from 'util/index.js'; /** * Session Manager * * Keep up to date with API keys and session tokens */ export default class Session { analytics; sessionKeys = {}; // [mapID]: session workers = []; currWorker = 0; totalWorkers = 0; sessionPromise; /** * Load a style via a URL, sending off analytics and utilizing the apiKey if needed * @param mapID - the id of the map * @param analytics - basic analytics about the GPU and screen dimensions * @param apiKey - the api key if needed */ loadStyle(mapID, analytics, apiKey) { this.analytics = analytics; this.sessionKeys[mapID] = { apiKey }; } /** * Load a worker * @param _messagePort - unused * @param postPort - the port for a worker to send session messages to * @param id - the id of the worker */ loadWorker(_messagePort, postPort, id) { this.totalWorkers++; this.workers[id] = postPort; } /** * Request a worker to process data * @returns the port for the worker */ requestWorker() { const worker = this.workers[this.currWorker]; this.currWorker++; if (this.currWorker >= this.totalWorkers) this.currWorker = 0; return worker; } /** * Check if the map has an API key * @param mapID - the id of the map * @returns true if the map has an API key */ hasAPIKey(mapID) { return this.sessionKeys[mapID]?.apiKey !== undefined; } /** * Request a style from the server * @param mapID - the id of the map * @param style - the style url * @param urlMap - the url map to properly modify and resolve urls */ async requestStyle(mapID, style, urlMap) { // grab the auth token const Authorization = await this.requestSessionToken(mapID); if (Authorization === undefined) return; // fetch the style const json = await fetch(adjustURL(style, urlMap), { headers: { Authorization } }) .then(async (res) => { if (res.status !== 200) return null; return await res.json(); }) .catch((err) => { console.error(err); return null; }); // send style back to map if (json !== null) postMessage({ type: 'setStyle', mapID, style: json, ignorePosition: false }); } /** * Request a session token from the server to start fetching data * @param mapID - the id of the map * @returns the session token if available and/or successful */ async requestSessionToken(mapID) { const failed = 'failed'; const mapSessionKey = this.sessionKeys[mapID]; // if there is no apiKey, then the map doesn't requre a session token if (mapSessionKey === undefined) return undefined; // check if the token is already fresh const { apiKey, token, exp } = mapSessionKey; if (apiKey === undefined) return failed; if (exp !== undefined && token !== undefined && exp - new Date().getTime() > 0) return token; const { gpu, context, language, width, height } = this.analytics ?? {}; // grab a new token if (this.sessionPromise === undefined) { // TODO: use urlMap to adjust the URL this.sessionPromise = fetch(adjustURL('apiURL://session'), { method: 'POST', body: JSON.stringify({ apiKey, gpu, context, language, width, height }), headers: { 'Content-Type': 'application/json' }, }) .then(async (res) => { if (res.status !== 200 && res.status !== 206) return undefined; return await res.json(); }) .then((t) => { if (t === undefined) return undefined; const expDate = new Date(); expDate.setSeconds(expDate.getSeconds() + t.maxAge); return { token: t.token, exp: expDate.getTime() }; }) .catch((err) => { console.error(err); return undefined; }); } const sessionKey = await this.sessionPromise; this.sessionPromise = undefined; // store the new key, exp, and return the key to use if (sessionKey === undefined) return failed; mapSessionKey.token = sessionKey.token; mapSessionKey.exp = sessionKey.exp; return mapSessionKey.token ?? failed; } }