mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-23 04:06:43 +02:00
New project with 22+ browser games and AI game generation capabilities: - Astro PWA web app with game catalog and player - NestJS backend with AI game generator (Gemini, Claude, GPT-4o) - Community game submission via GitHub API - postMessage integration for score tracking - PWA support with offline capabilities 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
170 lines
No EOL
4 KiB
JavaScript
170 lines
No EOL
4 KiB
JavaScript
const CACHE_NAME = 'mana-games-v1';
|
|
const OFFLINE_URL = '/offline.html';
|
|
|
|
// Assets, die immer gecacht werden sollen
|
|
const STATIC_CACHE_URLS = [
|
|
'/',
|
|
'/offline.html',
|
|
'/favicon.svg',
|
|
'/manifest.json'
|
|
];
|
|
|
|
// Cache-Strategien für verschiedene Ressourcen
|
|
const CACHE_STRATEGIES = {
|
|
// Netzwerk zuerst, dann Cache (für HTML)
|
|
networkFirst: [
|
|
/\/$/,
|
|
/\.html$/,
|
|
/\.astro$/
|
|
],
|
|
// Cache zuerst, dann Netzwerk (für Assets)
|
|
cacheFirst: [
|
|
/\.css$/,
|
|
/\.js$/,
|
|
/\.woff2?$/,
|
|
/\.ttf$/,
|
|
/\.otf$/,
|
|
/\.svg$/,
|
|
/\.png$/,
|
|
/\.jpg$/,
|
|
/\.jpeg$/,
|
|
/\.webp$/,
|
|
/\.ico$/
|
|
],
|
|
// Nur Netzwerk (für API-Calls)
|
|
networkOnly: [
|
|
/\/api\//,
|
|
/\.json$/
|
|
]
|
|
};
|
|
|
|
// Service Worker Installation
|
|
self.addEventListener('install', event => {
|
|
event.waitUntil(
|
|
caches.open(CACHE_NAME)
|
|
.then(cache => {
|
|
console.log('Service Worker: Caching static assets');
|
|
return cache.addAll(STATIC_CACHE_URLS);
|
|
})
|
|
.then(() => self.skipWaiting())
|
|
);
|
|
});
|
|
|
|
// Service Worker Aktivierung
|
|
self.addEventListener('activate', event => {
|
|
event.waitUntil(
|
|
caches.keys()
|
|
.then(cacheNames => {
|
|
return Promise.all(
|
|
cacheNames
|
|
.filter(cacheName => cacheName !== CACHE_NAME)
|
|
.map(cacheName => caches.delete(cacheName))
|
|
);
|
|
})
|
|
.then(() => self.clients.claim())
|
|
);
|
|
});
|
|
|
|
// Fetch-Event Handler
|
|
self.addEventListener('fetch', event => {
|
|
const { request } = event;
|
|
const url = new URL(request.url);
|
|
|
|
// Ignoriere Chrome Extension Requests
|
|
if (url.protocol === 'chrome-extension:') {
|
|
return;
|
|
}
|
|
|
|
// Bestimme die Cache-Strategie
|
|
const strategy = getStrategy(url.pathname);
|
|
|
|
if (strategy === 'networkFirst') {
|
|
event.respondWith(networkFirst(request));
|
|
} else if (strategy === 'cacheFirst') {
|
|
event.respondWith(cacheFirst(request));
|
|
} else if (strategy === 'networkOnly') {
|
|
event.respondWith(networkOnly(request));
|
|
} else {
|
|
// Standard: Network First
|
|
event.respondWith(networkFirst(request));
|
|
}
|
|
});
|
|
|
|
// Cache-Strategien Implementierung
|
|
async function networkFirst(request) {
|
|
try {
|
|
const networkResponse = await fetch(request);
|
|
if (networkResponse.ok) {
|
|
const cache = await caches.open(CACHE_NAME);
|
|
cache.put(request, networkResponse.clone());
|
|
}
|
|
return networkResponse;
|
|
} catch (error) {
|
|
const cachedResponse = await caches.match(request);
|
|
if (cachedResponse) {
|
|
return cachedResponse;
|
|
}
|
|
|
|
// Wenn es eine Navigation ist und wir offline sind, zeige die Offline-Seite
|
|
if (request.mode === 'navigate') {
|
|
const offlineResponse = await caches.match(OFFLINE_URL);
|
|
if (offlineResponse) {
|
|
return offlineResponse;
|
|
}
|
|
}
|
|
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
async function cacheFirst(request) {
|
|
const cachedResponse = await caches.match(request);
|
|
if (cachedResponse) {
|
|
return cachedResponse;
|
|
}
|
|
|
|
try {
|
|
const networkResponse = await fetch(request);
|
|
if (networkResponse.ok) {
|
|
const cache = await caches.open(CACHE_NAME);
|
|
cache.put(request, networkResponse.clone());
|
|
}
|
|
return networkResponse;
|
|
} catch (error) {
|
|
console.error('Fetch failed:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
async function networkOnly(request) {
|
|
return fetch(request);
|
|
}
|
|
|
|
// Hilfsfunktion zur Bestimmung der Cache-Strategie
|
|
function getStrategy(pathname) {
|
|
for (const [strategy, patterns] of Object.entries(CACHE_STRATEGIES)) {
|
|
if (patterns.some(pattern => pattern.test(pathname))) {
|
|
return strategy;
|
|
}
|
|
}
|
|
return 'networkFirst';
|
|
}
|
|
|
|
// Message Handler für Cache-Updates
|
|
self.addEventListener('message', event => {
|
|
if (event.data && event.data.type === 'SKIP_WAITING') {
|
|
self.skipWaiting();
|
|
}
|
|
|
|
if (event.data && event.data.type === 'CACHE_GAME') {
|
|
const gameUrl = event.data.url;
|
|
caches.open(CACHE_NAME)
|
|
.then(cache => cache.add(gameUrl))
|
|
.then(() => {
|
|
event.ports[0].postMessage({ cached: true });
|
|
})
|
|
.catch(error => {
|
|
event.ports[0].postMessage({ cached: false, error: error.message });
|
|
});
|
|
}
|
|
}); |