caterium-app/public/service-worker.js
pavlov346346-source 12ba761af9 Merge production (account center + login redesign) into main
production had diverged from main with 20 unreviewed direct-push
commits never merged back (account center feature, owner-only employee
roles, and a login-screen redesign - the exact "cream login" work that
replaced the old dark table-photo screen). Neither QA nor the
audit fixes on main had ever seen this code.

Conflict resolution:
- service-worker.js: kept production's newer cache-refresh mechanism
  (CRITICAL_FRESH, forceFresh, withAccountCenter, v81 cache name) and
  combined both sides' CORE asset lists (account-center-v1780.js +
  login-signature-v1776.js from production, auth-security-v1774.js +
  order-enhancements-v1775.js from main).
- deploy-timeweb.yml: kept main's version, which already independently
  verifies service-worker.js's sha256 alongside the login/logo files -
  strictly more thorough than production's version of the same check.

Also fixes fallout from production's commits never having been
QA-tested before landing: package.json was bumped to 17.8.0 with
nothing else in the codebase updated to match (reverted to 17.7.3,
matching package-lock.json/release-manifest.json/app-runtime.js, since
no other release artifact actually changed), and three tests
(static-security.mjs, edge-security-v1774.mjs, release-check.mjs) had
hardcoded strings (old PWA cache name, old employee role list) that no
longer matched the code they were checking.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-12 14:36:52 +03:00

61 lines
3.9 KiB
JavaScript

const CACHE='sun-catering-pwa-v81-20260912-account-center-loader';
const VERSION='20260912-account-center-loader';
const CORE=[
'./','./index.html',
`./core/sun-safe.js?v=${VERSION}`,`./core/performance.js?v=${VERSION}`,`./core/account-center-v1780.js?v=${VERSION}`,`./core/login-signature-v1776.js?v=${VERSION}`,`./core/data-layer-v1773.js?v=${VERSION}`,`./core/server-automation-v1770.js?v=${VERSION}`,`./core/hotfix-v1763.js?v=${VERSION}`,`./core/ops-ux-v1762.js?v=${VERSION}`,`./core/ux-fixes-v1764.js?v=${VERSION}`,`./core/pdf-engine.js?v=${VERSION}`,`./core/classic-offer-pdf-v1767.js?v=${VERSION}`,`./core/developer-console-v1768.js?v=${VERSION}`,`./core/offer-workspace-v1769.js?v=${VERSION}`,`./core/auth-security-v1774.js?v=${VERSION}`,`./core/order-enhancements-v1775.js?v=${VERSION}`,`./legacy/bootstrap.js?v=${VERSION}`,`./app-runtime.js?v=${VERSION}`,
'./offer-gallery/001.jpg','./offer-gallery/002.jpg',
'./catalog/001.jpg','./catalog/002.jpg','./catalog/003.jpg',
'./sun-logo.png','./caterium-login-logo.png','./caterium-mark-light.svg','./pwa-icon-192.png','./pwa-icon-512.png','./manifest.webmanifest',
'./offer-templates/thumb-light.jpg','./offer-templates/thumb-editorial-grid.jpg','./offer-templates/thumb-midnight-glass.jpg','./offer-templates/thumb-emerald-gold.jpg'
];
const CRITICAL_FRESH=new Set([
'/core/sun-safe.js',
'/core/performance.js',
'/core/account-center-v1780.js',
'/core/login-signature-v1776.js',
'/core/auth-security-v1774.js',
'/legacy/bootstrap.js',
'/app-runtime.js'
]);
self.addEventListener('install',event=>{
event.waitUntil(caches.open(CACHE).then(cache=>cache.addAll(CORE)).then(()=>self.skipWaiting()));
});
self.addEventListener('activate',event=>{
event.waitUntil(caches.keys().then(keys=>Promise.all(keys.filter(k=>k.startsWith('sun-catering-pwa-')&&k!==CACHE).map(k=>caches.delete(k)))).then(()=>self.clients.claim()));
});
function cachePut(req,res){
if(res&&res.ok){const clone=res.clone();caches.open(CACHE).then(c=>c.put(req,clone)).catch(()=>{});}return res;
}
function networkFirst(req,fallback){
return fetch(req,{cache:'no-store'}).then(res=>cachePut(req,res)).catch(()=>caches.match(req).then(hit=>hit||caches.match(fallback||req)));
}
function forceFresh(req){
const url=new URL(req.url);
url.searchParams.set('__caterium_release',VERSION);
return fetch(url.toString(),{cache:'no-store',credentials:'same-origin'}).then(res=>cachePut(req,res)).catch(()=>caches.match(req));
}
async function withAccountCenter(res){
if(!res)return res;
const type=String(res.headers.get('content-type')||'');
if(!type.includes('text/html'))return res;
const html=await res.text();
if(html.includes('core/account-center-v1780.js'))return new Response(html,{status:res.status,statusText:res.statusText,headers:res.headers});
const tag=`<script src="core/account-center-v1780.js?v=${VERSION}"></script>`;
const out=html.includes('</body>')?html.replace('</body>',`${tag}</body>`):html+tag;
const headers=new Headers(res.headers);headers.set('content-type','text/html; charset=utf-8');headers.set('cache-control','no-store, max-age=0');
return new Response(out,{status:res.status,statusText:res.statusText,headers});
}
self.addEventListener('fetch',event=>{
const req=event.request;if(req.method!=='GET')return;
const url=new URL(req.url);if(url.pathname.startsWith('/api/'))return;
if(req.mode==='navigate'){
event.respondWith(fetch(req,{cache:'no-store'}).then(async res=>{const clone=res.clone();caches.open(CACHE).then(c=>c.put('./index.html',clone)).catch(()=>{});return withAccountCenter(res)}).catch(async()=>withAccountCenter(await caches.match('./index.html'))));return;
}
if(CRITICAL_FRESH.has(url.pathname)){
event.respondWith(forceFresh(req));return;
}
const freshAsset=/\.(?:js|css|webmanifest)$/i.test(url.pathname);
if(freshAsset){event.respondWith(networkFirst(req));return;}
event.respondWith(caches.match(req).then(cached=>cached||fetch(req,{cache:'no-store'}).then(res=>cachePut(req,res))));
});