From 4daa099b22dbec1564572079ba3b28d82369e0a4 Mon Sep 17 00:00:00 2001 From: ayoayco Date: Fri, 16 Aug 2024 08:47:31 +0200 Subject: [PATCH] feat: create logger; update cached articles on load --- src/components/Library.astro | 30 ++++++++++++++------ src/consts.ts | 2 +- src/pages/index.astro | 1 - src/sw.js | 49 ++++++++++++++++++++------------ src/utils/logger.mjs | 54 ++++++++++++++++++++++++++++++++++++ 5 files changed, 108 insertions(+), 28 deletions(-) create mode 100644 src/utils/logger.mjs diff --git a/src/components/Library.astro b/src/components/Library.astro index 882e521..a4e303b 100644 --- a/src/components/Library.astro +++ b/src/components/Library.astro @@ -17,7 +17,9 @@ export interface Props { import type { AppConfig } from '../pages/index.astro'; import { getPostCard, renderPost } from '../utils/library' import { cozify } from '../utils/sanitizer'; + import { logError, logInfo } from '../utils/logger.mjs'; const cache = await caches.open('cozy-reader'); + const baseUrl = window.location.origin; let url= new URL(window.location.href); // only cached unencoded url param const urlParam = url.searchParams.get('url') @@ -26,16 +28,15 @@ export interface Props { } const { skipSave } = deserialize('preferences'); const { routerOutlet } = deserialize('app-config'); - const includesAppURL = urlParam?.includes(window.location.origin) + const includesAppURL = urlParam?.includes(baseUrl) ?? false; try { - const responseFromNetwork = await fetch (url); - if (responseFromNetwork && !skipSave && !includesAppURL) { - console.info('[cozy-reader]: adding one to cache', url.pathname) - await cache.put(url, responseFromNetwork); + if (url.href.slice(0, url.href.length - 1) !== baseUrl && !skipSave && !includesAppURL) { + logInfo('adding one to cache', {context: 'cozy-reader', data: url}) + await cache.add(url); } } catch(error) { - console.error('[cozy-reader]: ', error) + logError('ERR', {context: 'cozy-reader', data: error}) } const cachedRequests = (await cache.keys()) @@ -44,7 +45,7 @@ export interface Props { const urlParam = urlObj.searchParams.get('url'); return urlObj.search !== '' - && !urlParam?.startsWith(window.location.origin) + && !urlParam?.startsWith(baseUrl) && urlParam !== '' && urlParam !== 'null'; }); @@ -63,9 +64,19 @@ export interface Props { let responseText; const fullResponse = await cache.match(url) + + try { + const responseFromNetwork = await fetch(url, {method: 'GET'}); + if (responseFromNetwork && url.slice(0, url.length - 1) !== baseUrl && !skipSave && !includesAppURL) { + logInfo('updating cached', {context: 'cozy-reader', data: url}) + await cache.put(url, responseFromNetwork); + } + } catch(error) { + logError('failed to update cached', {context: 'cozy-reader', data: {url, error}}) + } + fullResponse?.text().then(async data => { responseText = data; - const { baseUrl } = deserialize('app-config'); const cleanedResponse = await cozify(responseText, baseUrl) const html = document.createElement('html'); html.innerHTML = cleanedResponse; @@ -82,6 +93,7 @@ export interface Props { e.preventDefault(); localStorage.setItem('scrollPosition', window.scrollY.toString()); scrollTo(0,0); + logInfo('using cached response', {context: 'cozy-reader', data: url}) renderPost(cleanedResponse, url, routerOutlet) } const item = document.createElement('li'); @@ -105,8 +117,8 @@ export interface Props { const fullResponse = await cache.match(url) fullResponse?.text().then(async (data) => { const responseText = data; - const { baseUrl } = deserialize('app-config'); const cleanedResponse = await cozify(responseText, baseUrl); + logInfo('using cached response', {context: 'cozy-reader', data: url}) renderPost(cleanedResponse, url, routerOutlet, true); if (isHome) { const scrollPosition = localStorage.getItem('scrollPosition'); diff --git a/src/consts.ts b/src/consts.ts index a49563c..f810a6a 100644 --- a/src/consts.ts +++ b/src/consts.ts @@ -4,4 +4,4 @@ export const SITE_AUTHOR_MASTODON = 'https://social.ayco.io/@ayo'; export const SITE_PROJECT_REPO = 'https://github.com/ayoayco/Cozy'; export const SITE_DESCRIPTION = 'The Web is Yours.'; -export const VERSION = 'Purple-Pizza'; +export const VERSION = 'Purple-Pizza'; \ No newline at end of file diff --git a/src/pages/index.astro b/src/pages/index.astro index 5f9dc60..1cbafa7 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -11,7 +11,6 @@ export const prerender = false; const appConfig = { routerOutlet: 'router-outlet', - baseUrl: Astro.url.origin }; export type AppConfig = typeof appConfig; diff --git a/src/sw.js b/src/sw.js index 19a10fe..adca1cf 100644 --- a/src/sw.js +++ b/src/sw.js @@ -4,20 +4,35 @@ * @see https://ayco.io/n/@ayco/astro-sw */ const cacheName = `${__prefix ?? 'app'}-v${__version ?? '000'}` +// const forceLogging = true; + +/** + * TODO: remove this once astro-sw allows importing utils + */ +function logInfo(message, {context, force, data} = {}) { + context = context !== '' + ? `[${context}]: ` + : '' + + if (force || isDev) { + console.info(`!!! ${context}${message}`, data ?? ''); + } +} + const addResourcesToCache = async (resources) => { const cache = await caches.open(cacheName); - console.log('[cozy-sw]: adding resources to cache...', resources) + logInfo('adding resources to cache...', { force: forceLogging, context: 'cozy-sw', data: resources }) await cache.addAll(resources); }; const putInCache = async (request, response) => { const cache = await caches.open(cacheName); - console.log('[cozy-sw]: adding one response to cache...', request.url) + logInfo('adding one response to cache...', { force: forceLogging, context: 'cozy-sw', data: request.url }) // if exists, replace const keys = await cache.keys(); - if(keys.includes(request)) { + if (keys.includes(request)) { cache.delete(request); } @@ -26,7 +41,7 @@ const putInCache = async (request, response) => { const cacheAndRevalidate = async ({ request, preloadResponsePromise, fallbackUrl }) => { - + const cache = await caches.open(cacheName); // Try get the resource from the cache @@ -35,21 +50,21 @@ const cacheAndRevalidate = async ({ request, preloadResponsePromise, fallbackUrl // get network response for revalidation of stale assets const responseFromNetwork = await fetch(request.clone()); if (responseFromNetwork) { - console.info('[cozy-sw]: fetched updated assets', responseFromNetwork.url); + logInfo('updated cached resource...', { force: forceLogging, context: 'cozy-sw', data: responseFromNetwork.url }) putInCache(request, responseFromNetwork.clone()); } if (responseFromCache) { - console.info('[cozy-sw]: using cached response', responseFromCache.url); + logInfo('using cached response...', { force: forceLogging, context: 'cozy-sw', data: responseFromCache.url }) return responseFromCache; - } else{ - console.info('[cozy-sw]: using network response', responseFromNetwork.url); + } else { + logInfo('using network response...', { force: forceLogging, context: 'cozy-sw', data: responseFromNetwork.url }) return responseFromNetwork; } - } catch(error) { - console.info('[cozy-sw]: failed to fetch updated assets', request.url); + } catch (error) { + logInfo('failed to fetch updated resource', { force: forceLogging, context: 'cozy-sw', data: request.url }) if (responseFromCache) { - console.info('[cozy-sw]: using cached response', responseFromCache.url); + logInfo('using cached response', { force: forceLogging, context: 'cozy-sw', data: responseFromCache.url }) return responseFromCache; } } @@ -63,18 +78,18 @@ const cacheAndRevalidate = async ({ request, preloadResponsePromise, fallbackUrl const preloadResponse = await preloadResponsePromise; if (preloadResponse) { putInCache(request, preloadResponse.clone()); - console.info('[cozy-sw]: using preload response', preloadResponse.url); + logInfo('using preload response', { force: forceLogging, context: 'cozy-sw', data: preloadResponse.url }) return preloadResponse; } try { // Try to get the resource from the network for 5 seconds - const responseFromNetwork = await fetch(request.clone(), {signal: AbortSignal.timeout(5000)}); + const responseFromNetwork = await fetch(request.clone(), { signal: AbortSignal.timeout(5000) }); // response may be used only once // we need to save clone to put one copy in cache // and serve second one putInCache(request, responseFromNetwork.clone()); - console.info('[cozy-sw]: using network response', responseFromNetwork.url); + logInfo('using network response', { force: forceLogging, context: 'cozy-sw', data: responseFromNetwork.url }) return responseFromNetwork; } catch (error) { @@ -82,7 +97,7 @@ const cacheAndRevalidate = async ({ request, preloadResponsePromise, fallbackUrl // Try the fallback const fallbackResponse = await cache.match(fallbackUrl); if (fallbackResponse) { - console.info('[cozy-sw]: using fallback cached response', fallbackResponse.url); + logInfo('using fallback cached response...', { force: forceLogging, context: 'cozy-sw', data: fallbackResponse.url }) return fallbackResponse; } @@ -104,12 +119,12 @@ const enableNavigationPreload = async () => { }; self.addEventListener('activate', (event) => { - console.log('[cozy-sw]: activating...', event) + logInfo('activating service worker...', { force: forceLogging, context: 'cozy-sw' }) event.waitUntil(enableNavigationPreload()); }); self.addEventListener('install', (event) => { - console.log('[cozy-sw]: installing...', event) + logInfo('installing service worker...', { force: forceLogging, context: 'cozy-sw' }) event.waitUntil( addResourcesToCache([ ...(__assets ?? []) diff --git a/src/utils/logger.mjs b/src/utils/logger.mjs new file mode 100644 index 0000000..25f9342 --- /dev/null +++ b/src/utils/logger.mjs @@ -0,0 +1,54 @@ +// @ts-check + +const isDev = import.meta.env.DEV; + +/** + * @typedef {{ + * force?: true + * context?: string, + * data?: any + * }} LogOptions + */ + + +/** + * @param {string} message + * @param {LogOptions} options + */ +export function logMessage(message, {context, force, data} = {}) { + context = context !== '' + ? `[${context}]: ` + : '' + + if (force || isDev) { + console.log(`!!! ${context}${message}`, data ?? ''); + } +} + +/** + * @param {string} message + * @param {LogOptions} options + */ +export function logInfo(message, {context, force, data} = {}) { + context = context !== '' + ? `[${context}]: ` + : '' + + if (force || isDev) { + console.info(`!!! ${context}${message}`, data ?? ''); + } +} + +/** + * @param {string} message + * @param {LogOptions} options + */ +export function logError(message, {context, force, data} = {}) { + context = context !== '' + ? `[${context}]: ` + : '' + + if (force || isDev) { + console.error(`!!! ${context}${message}`, data ?? ''); + } +} \ No newline at end of file