/*__ESM_BODY_START__*/
(function initUxfRestCacheMSW () {
	const POLARIS_CACHE = 'polaris-cache';
	const RESP_OBJECT_STORE_KEY = 'POLARIS_API_POST_CACHE_OBJECT_STORE';
	const CONFIG_DATA_OBJECT_STORE_KEY = 'POLARIS_SW_CONFIG_DATA_OBJECT_STORE';
	const USER_PREF_LANG_HEADER = 'Now-User-Pref-Lang-Code';
	const VERSION_NUMBER = 2;
	const defaultLangCode  = 'en';
	const INDEXED_DB_NAME = 'POLARIS_CACHE';
	const SERVICE_WORKER = self.serviceWorkerTypes.POLARIS_SW_CACHE_UXF_REST;
	let dbRequest;
	let db;
	let processRequestQueueTimeoutId;

	const mcpRequestQueue = [];
	const MCP_STORE = 'macroponents';
	const SUBROUTES_STORE = 'subroutes';
	const mcpStores = [MCP_STORE, SUBROUTES_STORE];
	let localCachePromise = Promise.resolve({});
	let localConfigPromise = Promise.resolve({
		referrerScope: '/now/',
		cacheEnabled: true,
		setTimeoutDelay: 5000,
		cacheableRequests: {
			'/api/now/uxframework/macroponent_drivers': {
				methods: ['POST'],
				ttl: 300000
			},
			'/api/now/uxframework/component_drivers': {
				methods: ['POST'],
				ttl: 300000
			}
		}
	});
	let msgChannelPort;

	function cleanupDb() {
		db = null;
		dbRequest = null;
		console.log('Closing Database!');
	}

	async function openDb() {
		return new Promise((resolve) => {
			if (db)
				resolve(db);
			dbRequest = indexedDB.open(INDEXED_DB_NAME, VERSION_NUMBER);
			dbRequest.onupgradeneeded = (event) => {
				db = event.target.result;
				db.onclose = () => cleanupDb();
				if(!db.objectStoreNames.contains(RESP_OBJECT_STORE_KEY))
					db.createObjectStore(RESP_OBJECT_STORE_KEY, {keyPath: 'serializedRequest'});
				if(!db.objectStoreNames.contains(CONFIG_DATA_OBJECT_STORE_KEY))
					db.createObjectStore(CONFIG_DATA_OBJECT_STORE_KEY, {keyPath: 'key'});
				for (let i=0; i<mcpStores.length; i++) {
					if(!db.objectStoreNames.contains(mcpStores[i])) {
						db.createObjectStore(mcpStores[i]);
					}
				}
				resolve(db);
			};
			dbRequest.onsuccess = (event) => {
				db = event.target.result;
				db.onclose = () => cleanupDb();
				resolve(db);
			};
		});
	}

	const getKey = (id, userPrefLangCode) => {
		return `${id}-${userPrefLangCode}`;
	};

	async function getItem(store, id, userPrefLangCode) {
		if (!db)
			db = await openDb();
		return new Promise((resolve,reject) => {
			const objStore = db.transaction(store, 'readwrite').objectStore(store);
			const key = getKey(id, userPrefLangCode);
			const getRequest = objStore.get(key);
			getRequest.onsuccess = (e) => {
				resolve(e.target.result);
			};
			getRequest.onerror = () => {
				console.error('*** Get failed for Key: ' + key);
				reject();
			};
		});
	}

	async function putItem(store, item, id, userPrefLangCode) {
		if (!db)
			db = await openDb();
		return new Promise((resolve,reject) => {
			const objStore = db.transaction(store, 'readwrite').objectStore(store);
			const key = getKey(id, userPrefLangCode);
			const putRequest = objStore.put(item, key);
			putRequest.onsuccess = () => {
				self.mark({cacheName: `${INDEXED_DB_NAME}:${store}:${key}`, serviceWorker: SERVICE_WORKER, type: self.markTypes.PUT_INDEXED_DB});
				resolve();
			};
			putRequest.onerror = () => {
				self.mark({cacheName: `${INDEXED_DB_NAME}:${store}:${key}`, serviceWorker: SERVICE_WORKER, type: self.markTypes.PUT_INDEXED_DB_FAILED});
				console.error('*** Put failed for Key: ' + key);
				reject();
			};
		});
	}

	async function deleteItem(store, id, userPrefLangCode) {
		if (!db)
			db = await openDb();
		return new Promise((resolve,reject) => {
			const objStore = db.transaction(store, 'readwrite').objectStore(store);
			const key = getKey(id, userPrefLangCode);
			const deleteRequest = objStore.delete(key);
			deleteRequest.onsuccess = () => {
				self.mark({cacheName: `${INDEXED_DB_NAME}:${store}:${key}`, serviceWorker: SERVICE_WORKER, type: self.markTypes.DELETE_INDEXED_DB});
				resolve();
			};
			deleteRequest.onerror = () => {
				self.mark({cacheName: `${INDEXED_DB_NAME}:${store}:${key}`, serviceWorker: SERVICE_WORKER, type: self.markTypes.DELETE_INDEXED_DB_FAILED});
				console.error('*** Delete failed for Key: ' + key);
				reject();
			};
		});
	}

	async function get(storeObj, keys) {
		return Promise.all(
			keys.map(
				(key) =>
					new Promise((resolve, reject) => {
						const request = storeObj.get(key);
						request.onsuccess = ({ target: { result } }) => resolve(result);
						request.onerror = ({ target: { error } }) => reject(error);
					})
			)
		).then((values) =>
			keys.reduce(
				(result, key, index) => ((result[key] = values[index]), result),
				{}
			)
		);
	}

	const isEqual = (obj1, obj2) => {
		if (obj1 === obj2)
			return true;

		let props1 = Object.getOwnPropertyNames(obj1);
		let props2 = Object.getOwnPropertyNames(obj2);
		if (props1.length !== props2.length) {
			return false;
		}
		for (let i = 0; i < props1.length; i++) {
			let prop = props1[i];
			let bothAreObjects = typeof(obj1[prop]) === 'object' && typeof(obj2[prop]) === 'object';
			if ((!bothAreObjects && (obj1[prop] !== obj2[prop])) ||
			(bothAreObjects && !isEqual(obj1[prop], obj2[prop]))) {
				return false;
			}
		}
		return true;
	};

	async function shouldPageReload(mcpMap){
		if (!mcpMap || Object.keys(mcpMap).length === 0)
			return new Promise((resolve) => resolve(false));
		if (!db)
			db = await openDb();
		const mcpObjStore = db.transaction(MCP_STORE, 'readwrite').objectStore(MCP_STORE);
		const dbValueMap = await get(mcpObjStore, Object.keys(mcpMap));
		const subroutesObjStore = db.transaction(SUBROUTES_STORE, 'readwrite').objectStore(SUBROUTES_STORE);
		const subrouteKeys = Object.values(mcpMap).map(mcpdata => mcpdata.subroutesKey);
		const subrouteMap = await get(subroutesObjStore, subrouteKeys);
		const mcpKeys = ['presources', 'sysProps', 'userPrefs'];

		return new Promise((resolve,reject) => {
			let shouldReload = false;
			for (let mcpId in mcpMap) {
				let dbValue = dbValueMap[mcpId];
				let subrouteValue = subrouteMap[mcpMap[mcpId].subroutesKey];
				if (!dbValue || !subrouteValue)
					continue;

				let mcpData = mcpMap[mcpId].data;
				let dbValueData = dbValue.data;
				let subrouteData = subrouteMap[mcpMap[mcpId].subroutesKey].data;
				// compare cache buster keys and subroutes
				if ( (mcpMap[mcpId].cacheBuster !== dbValue.cacheBuster) || (!isEqual(mcpData.subroutes, subrouteData)) ) {
					console.log('Mismatch of cacheBuster or subroutes');
					shouldReload = true;
					break;
				}

				// compare all other keys such as sysprops, presources and userprefs
				for (let key in mcpKeys){
					if (!isEqual(mcpData[mcpKeys[key]], dbValueData[mcpKeys[key]])){
						console.log('Mismatch for key: ', mcpKeys[key]);
						shouldReload = true;
						break;
					}
				}
			}
			resolve(shouldReload);
		});
	}

	async function getAll(mcpIds, pageContextId, ttl, userPrefLangCode) {
		let results = [];
		let allMcpIdSet = new Set([...mcpIds]);
		const forLoop = async _ => {
			let processingMCPsQueue = [...mcpIds];
			while (processingMCPsQueue.length > 0) {
				const mcpId = processingMCPsQueue.shift();
				const mcpValue = await getItem(MCP_STORE, mcpId, userPrefLangCode);
				if (!mcpValue)
					break;

				if (Date.now() - mcpValue.timestamp > ttl) {
					console.log('*** Cache expired for MCP ID: ' + mcpValue.data.sysId + ' Timestamp: ' + mcpValue.timestamp);
					break; // break early if entry expired
				}
				const subroutesValue = await getItem(SUBROUTES_STORE, buildSubrouteKey(mcpId, pageContextId), userPrefLangCode);
				if (!subroutesValue)
					break;
				results.push({ ...mcpValue.data, subroutes: subroutesValue.data });
				const dependentMcpList = mcpValue.data.dependentMCPIds || [];
				for (const dependentMCPId of dependentMcpList) {
					if (allMcpIdSet.has(dependentMCPId))
						continue;

					allMcpIdSet.add(dependentMCPId);
					processingMCPsQueue.push(dependentMCPId);
				}
			}
		};
		await forLoop();
		return new Promise((resolve, reject) => {
			if (results.length === allMcpIdSet.size) {
				resolve(results);
			}
			else {
				resolve();
			}
		});
	}

	async function putAll(response, request){
		const result = response.result;
		if (!result)
			return;
		const requestJson = await request.json();
		const pageContextId = requestJson.pageContextId || '';
		const userPrefLangCode = request.headers.get(USER_PREF_LANG_HEADER)|| defaultLangCode;
		const {ttl} = await getRequestCacheConfig(request.url);
		let mcpMap = {};
		result.map((res) => mcpMap[res.sysId] = {'cacheBuster': getCacheBustKey(res),
			'data':res,
			'subroutesKey': buildSubrouteKey(res.sysId, pageContextId)});
		const shouldReload = await shouldPageReload(mcpMap);
		if (shouldReload) {
			console.log('Clearing the cache and sending message to client');
			await clearCache();
			if (msgChannelPort)
				msgChannelPort.postMessage({type: 'POLARIS_RELOAD_PAGE', payload: {shouldReload}});
			return shouldReload;
		}

		const forLoop = async _ => {
			for (let i = 0; i < result.length; i++) {
				const timestamp = Date.now();
				const cacheBuster = getCacheBustKey(result[i]);
				const mcpId = result[i].sysId;
				const mcpValue = {
					data: result[i],
					timestamp,
					cacheBuster
				};
				await putItem(MCP_STORE, mcpValue, mcpId, userPrefLangCode);

				const subroutesValue = {
					data: result[i].subroutes,
					timestamp,
					cacheBuster
				};
				const subroutesKey = buildSubrouteKey(mcpId, pageContextId);
				await putItem(SUBROUTES_STORE, subroutesValue, subroutesKey, userPrefLangCode);
				setTimeout(() => {
					deleteItem(MCP_STORE, mcpId, userPrefLangCode);
					deleteItem(SUBROUTES_STORE, subroutesKey, userPrefLangCode);
				}, ttl);
			}
		};
		await forLoop();
	}

	const getCacheBustKey = (res) => {
		const link = res.staticContentUrl ? res.staticContentUrl : res.clientCacheableContentUrl;

		if (!link)
			return '';
		return link.split('uxpcb=')[1];
	};

	const buildSubrouteKey = (mcpId, pageContextId) => {
		return mcpId + '~' + pageContextId;
	};

	async function getCachedMCPData(event){
		const requestJson = await event.request.clone().json();
		const mcpIds = requestJson.macroponentSysIds || [];
		const userPrefLangCode = event.request.headers.get(USER_PREF_LANG_HEADER)|| defaultLangCode;
		const pageContextId = requestJson.pageContextId || '';
		const {ttl} = await getRequestCacheConfig(event.request.clone().url);
		return getAll(mcpIds, pageContextId, ttl, userPrefLangCode);
	}

	async function buildCachedResponse(event){
		const result = await getCachedMCPData(event);
		return new Promise((resolve, reject) => {
			if (result) {
				resolve(new Response(JSON.stringify({result}), {
					headers: {
						'Content-Type': 'application/json',
					},
				}));
			}
			else {
				resolve();
			}
		});
	}

	const setConfigValue = (key, value) => {
		if (key === 'config') localConfigPromise = Promise.resolve(value);
		queueMicrotask(async () => {
			if (!db)
				db = await openDb();
			db
				.transaction([CONFIG_DATA_OBJECT_STORE_KEY], 'readwrite')
				.objectStore(CONFIG_DATA_OBJECT_STORE_KEY)
				.put({ key, value });
		}
		);
	};

	const responseCache = {
		async get(request) {
			const serializedRequest = await createRequestKey(request.clone());

			const cache = await localCachePromise;
			const result = cache[serializedRequest];
			if (!result) {
				if (!db)
					db = await openDb();
				const dbRequest = db
					.transaction([RESP_OBJECT_STORE_KEY], 'readwrite')
					.objectStore(RESP_OBJECT_STORE_KEY)
					.get(serializedRequest);

				return new Promise((resolve) => {
					dbRequest.onsuccess = async (event) => {
						if (!event.target.result) return resolve(null);

						const {serializedResponse, ts} = event.target.result;
						const {ttl} = await getRequestCacheConfig(request.url);
						resolve(
							Date.now() - ts < ttl
								? new Response(serializedResponse.body, serializedResponse)
								: null
						);
					};
					dbRequest.onerror = () => resolve(null);
				});
			}

			const {serializedResponse, ts} = result;
			const {ttl} = await getRequestCacheConfig(request.url);
			return Date.now() - ts < ttl
				? new Response(serializedResponse.body, serializedResponse)
				: null;
		},
		async put(request, response) {
			const serializedRequest = await createRequestKey(request.clone());
			const serializedResponse = await serializeResponse(response.clone());

			const localCache = await localCachePromise;
			localCache[serializedRequest] = {
				serializedRequest,
				serializedResponse,
				ts: Date.now()
			};

			queueMicrotask(async () => {
				const value = {
					serializedRequest,
					serializedResponse,
					ts: Date.now()
				};
				if (!db)
					db = await openDb();

				db.transaction([RESP_OBJECT_STORE_KEY], 'readwrite')
					.objectStore(RESP_OBJECT_STORE_KEY)
					.put(value);
			});
		},
		async delete(request) {
			const serializedRequest = await createRequestKey(request.clone());

			delete (await localCachePromise)[serializedRequest];

			queueMicrotask(async () => {
				if (!db)
					db = await openDb();
				const dbRequest = db
					.transaction([RESP_OBJECT_STORE_KEY], 'readwrite')
					.objectStore(RESP_OBJECT_STORE_KEY)
					.delete(serializedRequest);

				return new Promise((resolve) => {
					dbRequest.onsuccess = async (event) => {
						if (!event.target.result) return resolve(null);
					};
					dbRequest.onerror = () => resolve(null);
				});
			});
		}
	};

	const clearStore = async (store) => {
		if (!db)
			db = await openDb();
		return new Promise((resolve) => {
			const clearRequest = db.transaction(store, 'readwrite')
				.objectStore(store)
				.clear();
			clearRequest.onsuccess = () => {
				self.mark({cacheName: `${INDEXED_DB_NAME}:${store}`, serviceWorker: SERVICE_WORKER, type: self.markTypes.CLEAR_INDEXED_DB});
				resolve();
			};
			clearRequest.onerror = () => {
				self.mark({cacheName: `${INDEXED_DB_NAME}:${store}`, serviceWorker: SERVICE_WORKER, type: self.markTypes.CLEAR_INDEXED_DB_FAILED});
				console.error('*** Clear failed for store: ' + store);
				resolve();
			};
		});
	};

	const clearCache = async () => {
		localCachePromise = Promise.resolve({});

		caches.delete(POLARIS_CACHE);
		self.mark({serviceWorker: SERVICE_WORKER, type: self.markTypes.DELETE_CACHE});
		await clearStore(RESP_OBJECT_STORE_KEY);

		for (let i=0; i<mcpStores.length; i++) {
			await clearStore(mcpStores[i]);
		}
	};

	const getConfig = () => {
		return new Promise(async (resolve) => { // eslint-disable-line no-async-promise-executor
			if (localConfigPromise) return resolve(await localConfigPromise);
			if (!db)
				db = await openDb();
			const dbRequest = db
				.transaction([CONFIG_DATA_OBJECT_STORE_KEY], 'readwrite')
				.objectStore(CONFIG_DATA_OBJECT_STORE_KEY)
				.get('config');

			dbRequest.onsuccess = (event) => {
				if (!event.target.result) return resolve(null);
				if (!event.target.result.value.cacheEnabled) return resolve(null);

				resolve(event.target.result.value);
			};

			dbRequest.onerror = () => resolve(null);
		});
	};

	const getRequestCacheConfig = async (url) => {
		const config = await localConfigPromise;
		if (!config) return null;

		for (const k in config.cacheableRequests) {
			if (url.includes(k)) {
				return config.cacheableRequests[k];
			}
		}

		return null;
	};

	const isRequestCacheable = async (request) => {
		const config = await localConfigPromise;
		if (config && !config.cacheEnabled) return Promise.resolve(false);

		const requestCacheConfig = await getRequestCacheConfig(request.url);
		if (!requestCacheConfig || !config) return Promise.resolve(false);

		if (!new URL(request.referrer).pathname.startsWith(config.referrerScope))
			return Promise.resolve(false);

		return Promise.resolve(
			!requestCacheConfig.methods ||
			requestCacheConfig.methods.includes(request.method)
		);
	};

	const createRequestKey = async (request) => {
		return JSON.stringify(await serializeRequest(request.clone()));
	};

	const serializeHeaders = (headers) => {
		const serialized = {};
		for (const entry of headers.entries()) serialized[entry[0]] = entry[1];

		return serialized;
	};

	const serializeResponse = async (response) => {
		const serialized = {
			headers: serializeHeaders(response.headers),
			status: response.status,
			statusText: response.statusText
		};

		return response
			.clone()
			.text()
			.then(function(body) {
				serialized.body = body;
				return Promise.resolve(serialized);
			});
	};

	const serializeRequest = (request) => {
		const {url, method, mode, credentials, cache, redirect} = request;

		const serialized = {
			url,
			headers: {},
			method,
			mode,
			credentials,
			cache,
			redirect
		};

		if (method !== 'GET' && method !== 'HEAD') {
			return request
				.clone()
				.text()
				.then((body) => {
					serialized.body = body;
					return Promise.resolve(serialized);
				});
		}

		return Promise.resolve(serialized);
	};

	const getCachedResponse = async (request) => {
		if (!(await isRequestCacheable(request))) return Promise.resolve(null);
		if (request.method === 'POST')
			return await responseCache.get(request.clone());

		return await caches.open(POLARIS_CACHE).then((cache) => cache.match(request));
	};

	const cacheResponse = async (request, response) => {
		if (request.method === 'POST')
			return responseCache.put(request.clone(), response.clone());

		const {ttl} = await getRequestCacheConfig(request.url);
		const cache = await caches.open(POLARIS_CACHE);
		cache.put(request, response.clone());
		setTimeout(() => {
			cache.delete(request);
			self.mark({ event: {request}, serviceWorker: SERVICE_WORKER, type: self.markTypes.DELETE_CACHE_KEY});
		}, ttl);
	};

	async function getLocalCache() {
		if (!db)
			db = await openDb();
		const dbRequest = db
			.transaction([RESP_OBJECT_STORE_KEY], 'readwrite')
			.objectStore(RESP_OBJECT_STORE_KEY)
			.getAll();

		return new Promise((resolve) => {
			dbRequest.onsuccess = async (event) => {
				if (!event.target.result) return resolve(null);

				return resolve(
					event.target.result.reduce((a, v) => {
						if (!v.serializedRequest) return a;

						return {
							...a,
							[v.serializedRequest]: v
						};
					}, {})
				);
			};
			dbRequest.onerror = () => resolve(null);
		});
	}

	function primeLocalCache() {
		localConfigPromise = getConfig();
		localCachePromise = getLocalCache();
	}

	async function createMCPRequest(request) {
		const reqJson = await request.clone().json();
		const newRequestJson = {...reqJson, 'macroponentSkipSet':[]};

		return new Request(request.url, {
			body:JSON.stringify(newRequestJson),
			headers:request.headers,
			method:request.method,
			mode:'same-origin',
			credentials:request.credentials,
			cache:request.cache,
			redirect:request.redirect,
			referrer:request.referrer,
		});
	}

	async function processMCPRequestQueue() {
		while (mcpRequestQueue.length) {
			const fn = mcpRequestQueue.shift();
			const shouldReload = await fn();
			if (shouldReload)
				mcpRequestQueue.length = 0;
		}
	}

	const shouldRespond = event => {
		const isTargetUrl = /\/api\/now\/uxframework\/component_drivers$/.test(event.request.url);
		const isUIBReferrer = /\/now\/build\/ui\/(.+)$/.test(event.request.referrer);
		const isMCPUrl = /\/api\/now\/uxframework\/macroponent_drivers$/.test(event.request.url);
		const isPostMethod = event.request.method === 'POST';
		return (isTargetUrl || (isMCPUrl && !isUIBReferrer)) && isPostMethod;
	};

	self.handleFallbackResponse && self.handleFallbackResponse(shouldRespond);

	self.addEventListener('fetch', (event) => {
		if(!shouldRespond(event))
			return;
		const startTime = self.mark({event, serviceWorker: SERVICE_WORKER, type: self.markTypes.INIT});
		const isMCPUrl = /\/api\/now\/uxframework\/macroponent_drivers$/.test(event.request.url);
		if (!db)
			openDb().then(()=>console.log('Initializing Database!'));

		if (isMCPUrl) {
			event.respondWith(async function() {
				const isCacheable = await isRequestCacheable(event.request.clone());
				if (!isCacheable) {
					self.mark({event, serviceWorker: SERVICE_WORKER, type: self.markTypes.FETCH, startTime});
					return fetch(event.request);
				}

				const cachedResponseProm =  await buildCachedResponse(event);
				const mcpRequest = await createMCPRequest(event.request.clone());
				const config = await localConfigPromise;
				if (cachedResponseProm) {
					self.queueMicrotask(async () => {
						mcpRequestQueue.push(async () => {
							try {
								const networkResponse = await fetch(mcpRequest);
								// Cache only valid responses
								if (networkResponse.status === 200) {
									const networkResponseJson = await networkResponse.clone().json();
									return putAll(networkResponseJson, event.request.clone());
								}
							}
							catch(e) {
								self.mark({event: {request: mcpRequest}, error: e, serviceWorker: SERVICE_WORKER, type: self.markTypes.EXCEPTION});
								console.warn('Failed to fetch: ' + e);
							}
						});
						clearTimeout(processRequestQueueTimeoutId);
						processRequestQueueTimeoutId = setTimeout(() => processMCPRequestQueue(), config.setTimeoutDelay);
					});
					self.mark({event, response: cachedResponseProm, serviceWorker: SERVICE_WORKER, type: self.markTypes.CACHE, startTime});
					return cachedResponseProm;
				}
				try {
					const networkResponse = await fetch(mcpRequest);
					const networkResponseClone = await networkResponse.clone();
					// Cache only valid responses
					if (networkResponseClone.status === 200)
						self.queueMicrotask(async () => {
							const networkResponseJson = await networkResponseClone.json();
							return putAll(networkResponseJson, event.request.clone());
						});
					self.mark({event, response: networkResponse, serviceWorker: SERVICE_WORKER, type: self.markTypes.FETCH_RETURN_CACHE, startTime});
					return networkResponse;
				}
				catch (e) {
					self.mark({event, error: e, serviceWorker: SERVICE_WORKER, type: self.markTypes.EXCEPTION, startTime});
					console.warn('Failed to fetch: ' + e);
				}

			}());
		}
		else {
			event.respondWith(
				(async function() {
					const cachedResponse = await getCachedResponse(event.request.clone());
					const response = cachedResponse || await fetch(event.request.clone());
					const isCacheable = await isRequestCacheable(event.request.clone());
					if (isCacheable) {
						cacheResponse(event.request.clone(), response.clone());
						self.mark({ event, serviceWorker: SERVICE_WORKER, type: cachedResponse ? self.markTypes.CACHE : self.markTypes.FETCH_CACHE_RETURN, startTime});
					}
					else
						self.mark({ event, serviceWorker: SERVICE_WORKER, type: self.markTypes.FETCH_RETURN, startTime});
					return response;
				})()
			);
		}
	});

	const eventTypes = {
		POLARIS_CLEAR_CACHE: 'POLARIS_CLEAR_SW_CACHE',
		POLARIS_CONFIGURE_SW_CACHE: 'POLARIS_CONFIGURE_SW',
		POLARIS_MSG_CHANNEL_INIT_PORT: 'POLARIS_MSG_CHANNEL_INIT_PORT'
	};

	self.addEventListener('message', (event) => {
		if (!db)
			openDb().then(()=>console.log('Initializing Database!'));
		switch (event.data.type) {
			case eventTypes.POLARIS_CLEAR_CACHE:
				clearCache().then(() => console.log('Cache cleared'));
				break;
			case eventTypes.POLARIS_CONFIGURE_SW_CACHE:
				setConfigValue('config', event.data.payload);
				primeLocalCache();
				break;
			case eventTypes.POLARIS_MSG_CHANNEL_INIT_PORT:
				msgChannelPort = event.ports[0];
				break;
		}
	});
}());

/*__ESM_BODY_END__*/