const CACHE_NAME = 'notes2-{{ .VERSION }}' const CACHED_ASSETS = [ '/', '/notes2', '/offline', '/css/{{ .VERSION }}/main.css', '/css/{{ .VERSION }}/markdown.css', '/css/{{ .VERSION }}/notes2.css', '/css/{{ .VERSION }}/theme.css', '/images/{{ .VERSION }}/collapsed.svg', '/images/{{ .VERSION }}/expanded.svg', '/images/{{ .VERSION }}/icon_markdown_hollow.svg', '/images/{{ .VERSION }}/icon_markdown.svg', '/images/{{ .VERSION }}/icon_refresh.svg', '/images/{{ .VERSION }}/icon_save_disabled.svg', '/images/{{ .VERSION }}/icon_search.svg', '/images/{{ .VERSION }}/leaf.svg', '/images/{{ .VERSION }}/logo.svg', '/js/{{ .VERSION }}/api.mjs', '/js/{{ .VERSION }}/app.mjs', '/js/{{ .VERSION }}/checklist.mjs', '/js/{{ .VERSION }}/crypto.mjs', '/js/{{ .VERSION }}/key.mjs', '/js/{{ .VERSION }}/lib/custom_html_element.mjs', '/js/{{ .VERSION }}/lib/fullcalendar.min.js', '/js/{{ .VERSION }}/lib/node_modules/marked/lib/marked.esm.js', '/js/{{ .VERSION }}/lib/node_modules/marked/marked.min.js', '/js/{{ .VERSION }}/lib/node_modules/marked-token-position/lib/index.esm.js', '/js/{{ .VERSION }}/lib/sjcl.js', '/js/{{ .VERSION }}/marked_position.mjs', '/js/{{ .VERSION }}/mbus.mjs', '/js/{{ .VERSION }}/node.mjs', '/js/{{ .VERSION }}/node_store.mjs', '/js/{{ .VERSION }}/notes2.mjs', '/js/{{ .VERSION }}/sync.mjs', '/js/{{ .VERSION }}/tree.mjs', ] async function precache() { const cache = await caches.open(CACHE_NAME) return cache.addAll(CACHED_ASSETS) } async function fetchAsset(event) { try { const cache = await caches.open(CACHE_NAME) const match = await cache.match(event.request) if (match !== undefined) { // ----------------------------------------------- // This page is precached - return it immediately. // ----------------------------------------------- //console.log('From cache', event.request.url) return match } else { // --------------------------------------------------------------- // Not in cache - send it for an online request/browser cache hit. // --------------------------------------------------------------- console.log('From network', event.request.url) const resp = await fetch(event.request) // This will trigger on an HTTP error such as 502. if (!resp.ok) { console.log('HTTP error', resp.status) // When JSON is expected, return that instead of the offline HTML page. return await offline(event, `${resp.status} ${resp.statusText}`) } return resp } } catch (e) { // An error here is something like a DNS problem, not a regular HTTP problem. console.log('Network error', e, event.request.url) return await offline(event, e) } } async function offline(event, errText) { if (event.request.headers.get('X-JSON')) { return new Response('{ "OK": false, "Error": "Network is offline"}', { headers: { 'Content-Type': 'application/json' } }) } const cache = await caches.open(CACHE_NAME) const offline = await cache.match('/offline') let body = await offline.text() body = body.replace('||ERROR||', errText) return new Response(body, { headers: { 'Content-Type': 'text/html' } }) } async function cleanupCache() { const keys = await caches.keys() const keysToDelete = keys.map(key => { if (key !== CACHE_NAME) return caches.delete(key) }) return Promise.all(keysToDelete) } self.addEventListener('install', event => { console.log('SERVICE WORKER: install') self.skipWaiting() event.waitUntil(precache()) }) self.addEventListener('activate', event => { console.log('SERVICE WORKER: activate') self.clients.claim() event.waitUntil(cleanupCache()) }) self.addEventListener('fetch', event => { //console.log('SERVICE WORKER: fetch', event.request.url) event.respondWith(fetchAsset(event)) })