Files
Autoparts-DB/pos/static/pwa/sw.js
consultoria-as 29174c9108 fix(pos): fix proxy Content-Type forwarding and SW auth caching
Proxy was using resp.raw.headers (urllib3) which could miss Content-Type;
switched to resp.headers. SW now skips /pos/api/auth/ to prevent stale
token caching, scopes fetch to /pos/ only, and bumps cache to v2.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 02:13:36 +00:00

151 lines
4.6 KiB
JavaScript

// /home/Autopartes/pos/static/pwa/sw.js
// Nexus POS — Service Worker v1
const CACHE_NAME = 'nexus-pos-v2';
const APP_SHELL = [
'/pos/login',
'/pos/sale',
'/pos/catalog',
'/pos/inventory',
'/pos/customers',
'/pos/invoicing',
'/pos/accounting',
'/pos/dashboard',
'/pos/config',
'/pos/reports',
'/pos/static/css/tokens.css',
'/pos/static/css/common.css',
'/pos/static/js/app-init.js',
'/pos/static/js/sidebar.js',
'/pos/static/js/login.js',
'/pos/static/js/pos.js',
'/pos/static/js/catalog.js',
'/pos/static/js/inventory.js',
'/pos/static/js/customers.js',
'/pos/static/js/invoicing.js',
'/pos/static/js/accounting.js',
'/pos/static/js/dashboard.js',
'/pos/static/js/config.js',
'/pos/static/js/reports.js',
'/pos/static/js/offline-banner.js',
'/pos/static/js/sync-engine.js',
'/pos/static/pwa/manifest.json',
'/pos/static/pwa/icon-192.png',
'/pos/static/pwa/icon-512.png'
];
// ─── Install: pre-cache app shell ────────────────────────────────
self.addEventListener('install', function (event) {
event.waitUntil(
caches.open(CACHE_NAME).then(function (cache) {
return cache.addAll(APP_SHELL);
}).then(function () {
return self.skipWaiting();
})
);
});
// ─── Activate: purge old caches ──────────────────────────────────
self.addEventListener('activate', function (event) {
event.waitUntil(
caches.keys().then(function (names) {
return Promise.all(
names.filter(function (n) { return n !== CACHE_NAME; })
.map(function (n) { return caches.delete(n); })
);
}).then(function () {
return self.clients.claim();
})
);
});
// ─── Fetch strategy ──────────────────────────────────────────────
self.addEventListener('fetch', function (event) {
var url = new URL(event.request.url);
// Only handle requests within /pos/ scope
if (url.pathname.indexOf('/pos/') === -1) {
return;
}
// Never cache auth endpoints — tokens must always come from the server
if (url.pathname.indexOf('/pos/api/auth/') !== -1) {
return;
}
// Don't cache login page — always fetch fresh to avoid stale redirects
if (url.pathname === '/pos/login' || url.pathname === '/pos/login/') {
event.respondWith(networkFirst(event.request));
return;
}
// API calls → network-first
if (url.pathname.indexOf('/pos/api/') !== -1) {
event.respondWith(networkFirst(event.request));
return;
}
// Everything else → cache-first
event.respondWith(cacheFirst(event.request));
});
function cacheFirst(request) {
return caches.match(request).then(function (cached) {
if (cached) {
// Update cache in background
fetch(request).then(function (response) {
if (response && response.status === 200) {
caches.open(CACHE_NAME).then(function (cache) {
cache.put(request, response);
});
}
}).catch(function () { /* offline, ignore */ });
return cached;
}
return fetch(request).then(function (response) {
if (response && response.status === 200) {
var clone = response.clone();
caches.open(CACHE_NAME).then(function (cache) {
cache.put(request, clone);
});
}
return response;
});
});
}
function networkFirst(request) {
return fetch(request).then(function (response) {
if (response && response.status === 200) {
var clone = response.clone();
caches.open(CACHE_NAME).then(function (cache) {
cache.put(request, clone);
});
}
return response;
}).catch(function () {
return caches.match(request);
});
}
// ─── Background Sync ─────────────────────────────────────────────
self.addEventListener('sync', function (event) {
if (event.tag === 'nexus-pos-sync') {
event.respondWith && event.waitUntil(
self.clients.matchAll().then(function (clients) {
clients.forEach(function (client) {
client.postMessage({ type: 'SYNC_REQUESTED' });
});
})
);
}
});
// ─── Message handler ─────────────────────────────────────────────
self.addEventListener('message', function (event) {
if (event.data && event.data.type === 'SKIP_WAITING') {
self.skipWaiting();
}
});