- sistemato timeout corto
- corretto errori sulla generazione del PDF - corretto alcune directory - corretto fs.promise - corretto CORS !
This commit is contained in:
@@ -3,12 +3,15 @@
|
||||
/* global workbox */
|
||||
/* global cfgenv */
|
||||
|
||||
const VITE_APP_VERSION = "1.2.42";
|
||||
const VITE_APP_VERSION = '1.2.44';
|
||||
|
||||
// Costanti di configurazione
|
||||
const DYNAMIC_CACHE = 'dynamic-cache-v2';
|
||||
const baseUrl = self.location.origin;
|
||||
|
||||
const CACHE_VERSION = VITE_APP_VERSION;
|
||||
const CACHE_PREFIX = self.location.hostname || 'app';
|
||||
|
||||
function extractDomain(url) {
|
||||
return url.replace(/^https?:\/\//, '');
|
||||
}
|
||||
@@ -32,38 +35,30 @@ console.log('API_DOMAIN', API_DOMAIN);
|
||||
|
||||
const CACHE_NAME = 'pwa-cache-' + VITE_APP_VERSION; // Nome della cache
|
||||
|
||||
importScripts('workbox/workbox-sw.js')
|
||||
importScripts('workbox/workbox-sw.js');
|
||||
|
||||
import { clientsClaim } from 'workbox-core'
|
||||
import { clientsClaim } from 'workbox-core';
|
||||
import { precacheAndRoute, cleanupOutdatedCaches, createHandlerBoundToURL } from 'workbox-precaching';
|
||||
import { registerRoute, NavigationRoute } from 'workbox-routing';
|
||||
import { setCacheNameDetails } from 'workbox-core';
|
||||
import {
|
||||
NetworkOnly,
|
||||
NetworkFirst,
|
||||
StaleWhileRevalidate,
|
||||
CacheFirst,
|
||||
} from 'workbox-strategies';
|
||||
import { NetworkOnly, NetworkFirst, StaleWhileRevalidate, CacheFirst } from 'workbox-strategies';
|
||||
|
||||
import { CacheableResponsePlugin } from 'workbox-cacheable-response';
|
||||
import { ExpirationPlugin } from 'workbox-expiration';
|
||||
|
||||
const debug = false; //process.env.NODE_ENV !== 'production';
|
||||
const debug = false; //process.env.NODE_ENV !== 'production';
|
||||
|
||||
if (workbox) {
|
||||
|
||||
// Imposta configurazione prima di tutto
|
||||
workbox.setConfig({ debug });
|
||||
|
||||
workbox.loadModule('workbox-strategies');
|
||||
|
||||
console.log('Workbox ESISTE ✅ ');
|
||||
|
||||
} else {
|
||||
console.error('Workbox NON CARICATO ! ❌');
|
||||
}
|
||||
|
||||
|
||||
setCacheNameDetails({
|
||||
prefix: self.location.hostname,
|
||||
suffix: 'v2',
|
||||
@@ -71,7 +66,7 @@ setCacheNameDetails({
|
||||
runtime: 'runtime',
|
||||
});
|
||||
|
||||
const precacheList = (self.__WB_MANIFEST || []).filter(entry => {
|
||||
const precacheList = (self.__WB_MANIFEST || []).filter((entry) => {
|
||||
// Esclude tutto ciò che si trova nella cartella 'upload'
|
||||
if (entry.url.includes('/upload/')) {
|
||||
return false;
|
||||
@@ -82,13 +77,12 @@ const precacheList = (self.__WB_MANIFEST || []).filter(entry => {
|
||||
// Precache solo i file filtrati
|
||||
precacheAndRoute(precacheList);
|
||||
|
||||
cleanupOutdatedCaches()
|
||||
|
||||
cleanupOutdatedCaches();
|
||||
|
||||
// Installazione del Service Worker
|
||||
self.addEventListener('install', () => {
|
||||
console.log('[Service Worker] Installing ...');
|
||||
self.skipWaiting()
|
||||
self.skipWaiting();
|
||||
clientsClaim();
|
||||
});
|
||||
|
||||
@@ -98,15 +92,12 @@ self.addEventListener('activate', (event) => {
|
||||
event.waitUntil(
|
||||
caches.keys().then((cacheNames) => {
|
||||
return Promise.all(
|
||||
cacheNames
|
||||
.filter(name => name !== CACHE_NAME && name !== DYNAMIC_CACHE)
|
||||
.map((name) => caches.delete(name))
|
||||
cacheNames.filter((name) => name !== CACHE_NAME && name !== DYNAMIC_CACHE).map((name) => caches.delete(name))
|
||||
);
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
console.log(' [ VER-' + VITE_APP_VERSION + ' ] _---------________------ PAO: this is my custom service worker: ');
|
||||
|
||||
try {
|
||||
@@ -121,7 +112,6 @@ let ISTEST = self.location.hostname.startsWith('test');
|
||||
let ISLOCALE = self.location.hostname.startsWith('localhost');
|
||||
console.log('SW- app ver ' + VITE_APP_VERSION);
|
||||
|
||||
|
||||
// Function helpers
|
||||
async function writeData(table, data) {
|
||||
console.log('writeData', table, data);
|
||||
@@ -141,8 +131,6 @@ async function deleteItemFromData(table, id) {
|
||||
}
|
||||
|
||||
if (workbox) {
|
||||
|
||||
|
||||
/*if (process.env.MODE !== 'ssr' || process.env.PROD) {
|
||||
registerRoute(
|
||||
new NavigationRoute(
|
||||
@@ -152,101 +140,76 @@ if (workbox) {
|
||||
)
|
||||
}*/
|
||||
|
||||
// Gestione richieste statiche
|
||||
// Static assets (JS, CSS, Fonts) - CacheFirst: caricamento rapidissimo
|
||||
registerRoute(
|
||||
({ request }) => request.destination === 'document' || request.destination === 'script' || request.destination === 'style',
|
||||
new StaleWhileRevalidate({ cacheName: CACHE_NAME })
|
||||
);
|
||||
|
||||
// Cache strategy registrations
|
||||
registerRoute(
|
||||
new RegExp(/\.(?:png|gif|jpg|jpeg)$/),
|
||||
({ request }) => ['script', 'style', 'font'].includes(request.destination),
|
||||
new CacheFirst({
|
||||
cacheName: `images-upload-${VITE_APP_VERSION}`,
|
||||
cacheName: `${CACHE_PREFIX}-static-assets-${CACHE_VERSION}`,
|
||||
plugins: [
|
||||
new CacheableResponsePlugin({ statuses: [200] }),
|
||||
new ExpirationPlugin({ maxEntries: 60, maxAgeSeconds: 30 * 24 * 60 * 60 }), // 30 Days
|
||||
new CacheableResponsePlugin({ statuses: [0, 200] }),
|
||||
new ExpirationPlugin({ maxEntries: 50, maxAgeSeconds: 30 * 24 * 60 * 60 }), // 30 giorni
|
||||
],
|
||||
})
|
||||
);
|
||||
|
||||
// Immagini - CacheFirst con scadenza e limite
|
||||
registerRoute(
|
||||
new RegExp(/\.(?:svg)$/),
|
||||
({ request }) => request.destination === 'image',
|
||||
new CacheFirst({
|
||||
cacheName: `svg-${VITE_APP_VERSION}`,
|
||||
cacheName: `${CACHE_PREFIX}-images-${CACHE_VERSION}`,
|
||||
plugins: [
|
||||
new CacheableResponsePlugin({ statuses: [200] }),
|
||||
new ExpirationPlugin({ maxEntries: 60, maxAgeSeconds: 30 * 24 * 60 * 60 }), // 30 Days
|
||||
new CacheableResponsePlugin({ statuses: [0, 200] }),
|
||||
new ExpirationPlugin({ maxEntries: 60, maxAgeSeconds: 30 * 24 * 60 * 60 }), // 30 giorni
|
||||
],
|
||||
})
|
||||
);
|
||||
|
||||
// Google Fonts - StaleWhileRevalidate per aggiornamenti trasparenti
|
||||
registerRoute(
|
||||
new RegExp(/.*(?:googleapis|gstatic)\.com.*$/),
|
||||
/^https:\/\/fonts\.(?:googleapis|gstatic)\.com/,
|
||||
new StaleWhileRevalidate({
|
||||
cacheName: `google-fonts-${VITE_APP_VERSION}`,
|
||||
plugins: [
|
||||
new CacheableResponsePlugin({ statuses: [200] }),
|
||||
new ExpirationPlugin({ maxEntries: 30 }),
|
||||
],
|
||||
cacheName: `${CACHE_PREFIX}-google-fonts-${CACHE_VERSION}`,
|
||||
plugins: [new CacheableResponsePlugin({ statuses: [0, 200] }), new ExpirationPlugin({ maxEntries: 30 })],
|
||||
})
|
||||
);
|
||||
|
||||
/*registerRoute(
|
||||
new RegExp('^/myicons/.*$'), // Corrisponde a percorsi come "/icons/miaicona.ico"
|
||||
new CacheFirst({
|
||||
cacheName: `icon-cache-${VITE_APP_VERSION}`,
|
||||
plugins: [
|
||||
new CacheableResponsePlugin({ statuses: [200] }),
|
||||
new ExpirationPlugin({ maxAgeSeconds: 30 * 24 * 60 * 60 }), // 30 Days
|
||||
],
|
||||
})
|
||||
);*/
|
||||
|
||||
// HTML documents - NetworkFirst: garantisce contenuti aggiornati e fallback cache
|
||||
registerRoute(
|
||||
new RegExp(/\.(?:js|css|font)$/),
|
||||
new StaleWhileRevalidate({
|
||||
cacheName: `js-css-fonts-${VITE_APP_VERSION}`,
|
||||
({ request }) => request.destination === 'document',
|
||||
new NetworkFirst({
|
||||
cacheName: `${CACHE_PREFIX}-html-cache-${CACHE_VERSION}`,
|
||||
networkTimeoutSeconds: 5, // timeout rapido
|
||||
plugins: [
|
||||
new CacheableResponsePlugin({ statuses: [200] }),
|
||||
new CacheableResponsePlugin({ statuses: [0, 200] }),
|
||||
new ExpirationPlugin({ maxEntries: 20, maxAgeSeconds: 24 * 60 * 60 }), // 1 giorno
|
||||
],
|
||||
})
|
||||
);
|
||||
|
||||
// Gestione API
|
||||
// API calls - NetworkFirst con fallback cache e timeout veloce
|
||||
registerRoute(
|
||||
({ url }) => url.hostname === API_DOMAIN,
|
||||
new NetworkFirst({ fetchOptions: { credentials: 'include' } })
|
||||
new NetworkFirst({
|
||||
cacheName: `${CACHE_PREFIX}-api-cache-${CACHE_VERSION}`,
|
||||
networkTimeoutSeconds: 5,
|
||||
fetchOptions: { credentials: 'include' },
|
||||
plugins: [
|
||||
new CacheableResponsePlugin({ statuses: [0, 200] }),
|
||||
new ExpirationPlugin({ maxEntries: 50, maxAgeSeconds: 5 * 60 }), // 5 minuti
|
||||
],
|
||||
})
|
||||
);
|
||||
|
||||
/*registerRoute(
|
||||
(routeData) => routeData.event.request.headers.get('accept').includes('text/html'),
|
||||
async (args) => {
|
||||
let response = await caches.match(args.event.request);
|
||||
if (response) return response;
|
||||
|
||||
try {
|
||||
response = await fetch(args.event.request);
|
||||
const cache = await caches.open('dynamic');
|
||||
cache.put(args.event.request.url, response.clone());
|
||||
return response;
|
||||
} catch (err) {
|
||||
return caches.match('/offline');
|
||||
}
|
||||
}
|
||||
);*/
|
||||
|
||||
registerRoute(new RegExp('/admin/'), new NetworkOnly());
|
||||
|
||||
function generateUUID() {
|
||||
return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
|
||||
(c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
|
||||
return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c) =>
|
||||
(c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))).toString(16)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
const syncStore = {};
|
||||
self.addEventListener('message', event => {
|
||||
self.addEventListener('message', (event) => {
|
||||
if (event.data && (event.data.type === 'SKIP_WAITING' || event.data.action === 'skipWaiting')) {
|
||||
self.skipWaiting();
|
||||
}
|
||||
@@ -259,8 +222,6 @@ if (workbox) {
|
||||
console.log(event.data);
|
||||
});
|
||||
|
||||
|
||||
|
||||
// Funzione per gestire richieste API
|
||||
async function handleApiRequest(request) {
|
||||
try {
|
||||
@@ -269,10 +230,13 @@ if (workbox) {
|
||||
// Se la risposta non è valida, restituisci un errore personalizzato
|
||||
if (!response.ok) {
|
||||
console.warn('[SW] API Response Error:', response.status, response.statusText);
|
||||
return new Response(JSON.stringify({
|
||||
error: 'API error',
|
||||
message: `❌ Invalid response from API: ${response.status} ${response.statusText}`,
|
||||
}), { status: response.status, headers: { 'Content-Type': 'application/json' } });
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
error: 'API error',
|
||||
message: `❌ Invalid response from API: ${response.status} ${response.statusText}`,
|
||||
}),
|
||||
{ status: response.status, headers: { 'Content-Type': 'application/json' } }
|
||||
);
|
||||
}
|
||||
|
||||
return response;
|
||||
@@ -280,10 +244,13 @@ if (workbox) {
|
||||
console.error('[Service Worker] API request error ❌:', error);
|
||||
|
||||
// Restituisci una risposta di errore personalizzata
|
||||
return new Response(JSON.stringify({
|
||||
error: 'Network error',
|
||||
message: '❌ Unable to fetch from API: ' + error.message,
|
||||
}), { status: 503, headers: { 'Content-Type': 'application/json' } });
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
error: 'Network error',
|
||||
message: '❌ Unable to fetch from API: ' + error.message,
|
||||
}),
|
||||
{ status: 503, headers: { 'Content-Type': 'application/json' } }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -314,9 +281,11 @@ if (workbox) {
|
||||
const cachedResponse = await cache.match(request);
|
||||
if (cachedResponse) {
|
||||
// Aggiorna in background mentre restituisci la risposta in cache
|
||||
event.waitUntil(fetchAndCache(request).catch((error) => {
|
||||
console.error('[SW] Background fetch and cache error ❌:', error);
|
||||
}));
|
||||
event.waitUntil(
|
||||
fetchAndCache(request).catch((error) => {
|
||||
console.error('[SW] Background fetch and cache error ❌:', error);
|
||||
})
|
||||
);
|
||||
return cachedResponse;
|
||||
}
|
||||
|
||||
@@ -327,10 +296,13 @@ if (workbox) {
|
||||
console.error('[SW] Cache miss and network error ❌:', error);
|
||||
|
||||
// Restituisci una risposta di fallback personalizzata
|
||||
return new Response(JSON.stringify({
|
||||
error: 'Network error',
|
||||
message: 'Unable to fetch resource from network or cache.',
|
||||
}), { status: 503, headers: { 'Content-Type': 'application/json' } });
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
error: 'Network error',
|
||||
message: 'Unable to fetch resource from network or cache.',
|
||||
}),
|
||||
{ status: 503, headers: { 'Content-Type': 'application/json' } }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -339,7 +311,6 @@ if (workbox) {
|
||||
const { request } = event;
|
||||
const url = new URL(request.url);
|
||||
try {
|
||||
|
||||
// Ignora richieste non gestibili
|
||||
if (request.method !== 'GET' || url.protocol !== 'https:') {
|
||||
return;
|
||||
@@ -352,13 +323,13 @@ if (workbox) {
|
||||
|
||||
// Gestione richieste API
|
||||
if (url.hostname === API_DOMAIN) {
|
||||
if (debug) console.log('E\' una RICHIESTA API!');
|
||||
if (debug) console.log("E' una RICHIESTA API!");
|
||||
event.respondWith(handleApiRequest(request));
|
||||
return;
|
||||
}
|
||||
|
||||
// Gestione risorse statiche e altre richieste
|
||||
if (debug) console.log('E\' una RICHIESTA statica...');
|
||||
if (debug) console.log("E' una RICHIESTA statica...");
|
||||
event.respondWith(cacheWithStaleWhileRevalidate(request, event));
|
||||
} catch (error) {
|
||||
console.error('[Service Worker] Fetch error ❌:', error);
|
||||
@@ -366,12 +337,12 @@ if (workbox) {
|
||||
});
|
||||
|
||||
// Gestione degli errori non catturati
|
||||
self.addEventListener('unhandledrejection', event => {
|
||||
self.addEventListener('unhandledrejection', (event) => {
|
||||
console.error('[Service Worker] Unhandled rejection ❌:', event.reason);
|
||||
});
|
||||
|
||||
// Gestione degli errori globali
|
||||
self.addEventListener('error', event => {
|
||||
self.addEventListener('error', (event) => {
|
||||
console.error('[Service Worker] Global error ❌:', event.error);
|
||||
});
|
||||
|
||||
@@ -382,8 +353,7 @@ if (workbox) {
|
||||
// console.log('Request mode:', request.mode);
|
||||
// }
|
||||
|
||||
|
||||
self.addEventListener('sync', event => {
|
||||
self.addEventListener('sync', (event) => {
|
||||
console.log('[Service Worker V5] Background syncing', event);
|
||||
|
||||
let mystrparam = event.tag;
|
||||
@@ -401,7 +371,7 @@ if (workbox) {
|
||||
headers.append('x-refrtok', refreshToken);
|
||||
|
||||
event.waitUntil(
|
||||
readAllData(table).then(alldata => {
|
||||
readAllData(table).then((alldata) => {
|
||||
const myrecs = [...alldata];
|
||||
let errorfromserver = false;
|
||||
|
||||
@@ -420,11 +390,12 @@ if (workbox) {
|
||||
cache: 'no-cache',
|
||||
mode: 'cors',
|
||||
body: JSON.stringify(rec),
|
||||
}).then(() => {
|
||||
deleteItemFromData(table, rec._id);
|
||||
deleteItemFromData('swmsg', mystrparam);
|
||||
})
|
||||
.catch(err => {
|
||||
.then(() => {
|
||||
deleteItemFromData(table, rec._id);
|
||||
deleteItemFromData('swmsg', mystrparam);
|
||||
})
|
||||
.catch((err) => {
|
||||
if (err.message === 'Failed to fetch') {
|
||||
errorfromserver = true;
|
||||
}
|
||||
@@ -461,7 +432,7 @@ if (workbox) {
|
||||
self.clients.openWindow(notification.data.url);
|
||||
}
|
||||
notification.close();
|
||||
}),
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user