// @bun
var{defineProperty:G,getOwnPropertyNames:y,getOwnPropertyDescriptor:C}=Object,l=Object.prototype.hasOwnProperty;function h(j){return this[j]}var z=(j)=>{var q=(J??=new WeakMap).get(j),K;if(q)return q;if(q=G({},"__esModule",{value:!0}),j&&typeof j==="object"||typeof j==="function"){for(var Q of y(j))if(!l.call(q,Q))G(q,Q,{get:h.bind(j,Q),enumerable:!(K=C(j,Q))||K.enumerable})}return J.set(j,q),q},J;var u=(j)=>j;function f(j,q){this[j]=u.bind(null,q)}var R=(j,q)=>{for(var K in q)G(j,K,{get:q[K],enumerable:!0,configurable:!0,set:f.bind(q,K)})};var H=(j,q)=>()=>(j&&(q=j(j=0)),q);import V from"fs";import F from"path";function c(j){let q=0;for(let K=0;K<j.length;K++){let Q=j[K];q=(q<<5)-q+Q,q=q&q}return Math.abs(q).toString(16).padStart(8,"0")}function p(j,q){let K=F.basename(j);for(let Q of q)if(Q.startsWith("*.")){let Z=Q.slice(1);if(K.endsWith(Z))return!0}else if(Q.includes("*")){let Z=new RegExp(`^${Q.replace(/\*/g,".*")}$`);if(Z.test(K)||Z.test(j))return!0}else if(K===Q||j.includes(Q))return!0;return!1}function s(j,q,K){let Q=F.extname(j).toLowerCase(),Z=g[Q],X=(K.maxFileSizeKB||500)*1024;if(q>X)return!1;if(K.exclude&&p(j,K.exclude))return!1;if(K.include&&K.include.length>0){for(let Y of K.include)if(Y.startsWith("*.")){if(j.endsWith(Y.slice(1)))return!0}else if(j.includes(Y))return!0}if(Z&&K[Z]===!0)return!0;if(!Z)return!1;return!1}function N(j,q,K,Q){let Z=V.readdirSync(j,{withFileTypes:!0});for(let X of Z){let Y=F.join(j,X.name);if(X.isDirectory()){if(["node_modules",".git",".stx"].includes(X.name))continue;N(Y,q,K,Q)}else if(X.isFile()){let B=V.statSync(Y),L=F.relative(q,Y);if(s(L,B.size,K)){let $=V.readFileSync(Y),O=c($),U=`/${L.replace(/\\/g,"/")}`;Q.push({url:U,revision:O,size:B.size})}}}}function _(j,q){let K=q.pwa?.precache,Q=[];if(!K?.enabled)return{entries:[],totalSize:0,fileCount:0};if(!V.existsSync(j))return{entries:[],totalSize:0,fileCount:0};N(j,j,K,Q),Q.sort((X,Y)=>X.url.localeCompare(Y.url));let Z=Q.reduce((X,Y)=>X+Y.size,0);return{entries:Q,totalSize:Z,fileCount:Q.length}}function A(j){if(j.entries.length===0)return"[]";return`[
${j.entries.map((K)=>`  { url: '${K.url}', revision: '${K.revision}' }`).join(`,
`)}
]`}function E(j){if(j<1024)return`${j} B`;if(j<1048576)return`${(j/1024).toFixed(1)} KB`;return`${(j/1048576).toFixed(2)} MB`}var g;var T=H(()=>{g={".html":"includeHtml",".htm":"includeHtml",".js":"includeJs",".mjs":"includeJs",".css":"includeCss",".png":"includeImages",".jpg":"includeImages",".jpeg":"includeImages",".gif":"includeImages",".webp":"includeImages",".svg":"includeImages",".ico":"includeImages",".woff":"includeFonts",".woff2":"includeFonts",".ttf":"includeFonts",".eot":"includeFonts",".otf":"includeFonts"}});function r(j){let q={"cache-first":{className:"CacheFirst",importFrom:"workbox-strategies"},"network-first":{className:"NetworkFirst",importFrom:"workbox-strategies"},"stale-while-revalidate":{className:"StaleWhileRevalidate",importFrom:"workbox-strategies"},"network-only":{className:"NetworkOnly",importFrom:"workbox-strategies"},"cache-only":{className:"CacheOnly",importFrom:"workbox-strategies"}};return q[j]||q["network-first"]}function I(j){return r(j).className}function M(j){let q=j.pwa;if(!q?.enabled)return"";let K=q.routes||[],Q=q.cacheStorage,Z=[];for(let X of K){let Y=I(X.strategy),B=[];if(X.maxAgeSeconds||X.maxEntries||Q?.maxEntries){let $=X.maxEntries||Q?.maxEntries||100,O=X.maxAgeSeconds||(Q?.maxAge?Q.maxAge*24*60*60:void 0);B.push(`new ExpirationPlugin({
      maxEntries: ${$},
      ${O?`maxAgeSeconds: ${O},`:""}
      purgeOnQuotaError: true,
    })`)}if(X.strategy==="network-first"||X.strategy==="stale-while-revalidate")B.push(`new CacheableResponsePlugin({
      statuses: [0, 200],
    })`);let L=i(X.pattern);Z.push(`
// ${X.pattern}
registerRoute(
  ${L},
  new ${Y}({
    cacheName: '${X.cacheName||o(X.pattern)}',
    ${B.length>0?`plugins: [
      ${B.join(`,
      `)}
    ],`:""}
  })
);`)}return Z.join(`
`)}function i(j){if(j.startsWith("*.")){let q=j.slice(2);return`({ request }) => request.destination === '${n(q)}'`}if(j.endsWith("/**"))return`({ url }) => url.pathname.startsWith('${j.slice(0,-3)}')`;if(j.endsWith("/*")){let q=j.slice(0,-2);return`({ url }) => url.pathname.startsWith('${q}') && !url.pathname.slice(${q.length+1}).includes('/')`}if(j.includes("*")&&!j.startsWith("*")){let[q,K]=j.split("*");return`({ url }) => url.pathname.startsWith('${q}') && url.pathname.endsWith('${K}')`}if(j==="/"||!j.includes("*"))return`({ url }) => url.pathname === '${j}'`;return`new RegExp('${t(j).replace(/\\\*/g,".*")}')`}function n(j){return{js:"script",mjs:"script",css:"style",html:"document",htm:"document",png:"image",jpg:"image",jpeg:"image",gif:"image",svg:"image",webp:"image",avif:"image",ico:"image",woff:"font",woff2:"font",ttf:"font",eot:"font",otf:"font"}[j.toLowerCase()]||"empty"}function o(j){return"stx-"+j.replace(/[^\w]/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"").toLowerCase().slice(0,30)+"-cache"}function t(j){return j.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var S={};R(S,{isWorkboxEnabled:()=>k,getServiceWorkerGenerator:()=>Qj,generateWorkboxServiceWorker:()=>W,generateWorkboxConfig:()=>v});function v(j,q){let K=j.pwa;if(!K?.enabled)return{mode:"generate",modules:[],skipWaiting:!0,clientsClaim:!0};let Q=K.serviceWorker||{},Z=K.routes||[],X=[{name:"workbox-precaching",exports:["precacheAndRoute","cleanupOutdatedCaches"]},{name:"workbox-routing",exports:["registerRoute","NavigationRoute","setDefaultHandler"]}],Y=new Set;for(let $ of Z)Y.add(I($.strategy));if(Y.size>0)X.push({name:"workbox-strategies",exports:Array.from(Y)});if(Z.some(($)=>$.maxAgeSeconds||$.maxEntries)||K.cacheStorage)X.push({name:"workbox-expiration",exports:["ExpirationPlugin"]});if(Z.some(($)=>$.strategy==="network-first"||$.strategy==="stale-while-revalidate"))X.push({name:"workbox-cacheable-response",exports:["CacheableResponsePlugin"]});if(K.backgroundSync?.enabled)X.push({name:"workbox-background-sync",exports:["BackgroundSyncPlugin","Queue"]});if(Q.navigationPreload)X.push({name:"workbox-navigation-preload",exports:["enable"]});let L=q?_(q,j):void 0;return{mode:"generate",modules:X,precacheManifest:L?.entries,skipWaiting:Q.skipWaiting??!0,clientsClaim:Q.clientsClaim??!0,offlineFallback:K.offline?.enabled?"/offline.html":void 0,navigationPreload:Q.navigationPreload??!1,cacheVersion:Q.cacheVersion||"1.0.0"}}function W(j,q){let K=j.pwa;if(!K?.enabled)return"";let Q=v(j,q),Z=K.serviceWorker||{},X=K.push,Y=K.backgroundSync,B=q?_(q,j):null,L=B?A(B):"[]",$=e(Q.modules),O=M(j);return`/**
 * Service Worker - Generated by stx with Workbox
 * Cache Version: ${Q.cacheVersion}
 *
 * This service worker uses Google's Workbox library for robust caching.
 * https://developers.google.com/web/tools/workbox
 *
 * Features:
 * - Precaching with automatic revision management
 * - Runtime caching with multiple strategies
 * - Offline fallback support
 * - Push notifications: ${X?.enabled?"enabled":"disabled"}
 * - Background sync: ${Y?.enabled?"enabled":"disabled"}
 */

// Import Workbox modules from CDN
importScripts('https://storage.googleapis.com/workbox-cdn/releases/7.0.0/workbox-sw.js');

// Disable Workbox logging in production
workbox.setConfig({ debug: true });

// Extract modules from workbox global
${$}

const CACHE_VERSION = '${Q.cacheVersion}';
const OFFLINE_PAGE = '${Q.offlineFallback||"/offline.html"}';

// ============================================================================
// Precaching
// ============================================================================

// Clean up outdated caches from previous versions
cleanupOutdatedCaches();

// Precache static assets
// The manifest is injected during build or defined below
const PRECACHE_MANIFEST = ${L};

// Add essential assets
PRECACHE_MANIFEST.push(
  { url: '/', revision: CACHE_VERSION },
  { url: '/manifest.json', revision: CACHE_VERSION },
  ${Q.offlineFallback?`{ url: '${Q.offlineFallback}', revision: CACHE_VERSION },`:""}
);

// Precache and route all manifest entries
precacheAndRoute(PRECACHE_MANIFEST);

// ============================================================================
// Navigation Preload
// ============================================================================

${Q.navigationPreload?`// Enable navigation preload for faster page loads
enable();`:"// Navigation preload disabled"}

// ============================================================================
// Runtime Caching
// ============================================================================

${O}

// ============================================================================
// Offline Fallback
// ============================================================================

${Q.offlineFallback?`
// Set up offline fallback for navigation requests
const navigationRoute = new NavigationRoute(
  new NetworkFirst({
    cacheName: 'stx-pages-cache',
    plugins: [
      new CacheableResponsePlugin({ statuses: [0, 200] }),
    ],
  }),
  {
    // Return offline page when navigation fails
    async allowedHandler(request) {
      try {
        const response = await this.handle(request);
        return response;
      }
catch (error) {
        const cache = await caches.open('stx-offline-cache');
        return cache.match(OFFLINE_PAGE) || new Response('You are offline', {
          status: 503,
          statusText: 'Service Unavailable',
        });
      }
    },
  }
);
registerRoute(navigationRoute);
`:"// No offline fallback configured"}

// Default handler for unmatched requests
setDefaultHandler(new NetworkFirst({
  cacheName: 'stx-default-cache',
  plugins: [
    new CacheableResponsePlugin({ statuses: [0, 200] }),
    new ExpirationPlugin({ maxEntries: 100, maxAgeSeconds: 60 * 60 * 24 }), // 1 day
  ],
}));

// ============================================================================
// Service Worker Lifecycle
// ============================================================================

${Q.skipWaiting?`// Skip waiting - activate immediately
self.skipWaiting();`:"// Manual skipWaiting - user must trigger update"}

${Q.clientsClaim?`// Claim clients - take control immediately
self.addEventListener('activate', () => {
  self.clients.claim();
});`:"// Manual clients claim"}

// ============================================================================
// Message Handling
// ============================================================================

self.addEventListener('message', (event) => {
  const { type, payload } = event.data || {};

  switch (type) {
    case 'SKIP_WAITING':
      self.skipWaiting();
      break;

    case 'GET_VERSION':
      event.source?.postMessage({ type: 'VERSION', payload: CACHE_VERSION });
      break;

    case 'CACHE_URLS':
      if (Array.isArray(payload)) {
        event.waitUntil(
          caches.open('stx-dynamic-cache').then(cache => cache.addAll(payload))
        );
      }
      break;

    case 'CLEAR_CACHE':
      event.waitUntil(
        caches.keys().then(names =>
          Promise.all(names.map(name => caches.delete(name)))
        )
      );
      break;
  }
});

${X?.enabled?qj(X):"// Push notifications disabled"}

${Y?.enabled?Kj(Y):"// Background sync disabled"}

console.log('[Workbox SW] Service Worker loaded - Version:', CACHE_VERSION);
`}function e(j){let q=[];for(let K of j){let Q=K.name.replace("workbox-","");q.push(`const { ${K.exports.join(", ")} } = workbox.${jj(Q)};`)}return q.join(`
`)}function jj(j){return j.replace(/-([a-z])/g,(q,K)=>K.toUpperCase())}function qj(j){return`
// ============================================================================
// Push Notifications
// ============================================================================

const PUSH_CONFIG = {
  defaultIcon: '${j?.defaultIcon||"/pwa-icons/icon-192x192.png"}',
  defaultBadge: '${j?.defaultBadge||"/pwa-icons/icon-72x72.png"}',
};

self.addEventListener('push', (event) => {
  console.log('[Workbox SW] Push notification received');

  let data = {
    title: 'Notification',
    body: 'You have a new notification',
    icon: PUSH_CONFIG.defaultIcon,
    badge: PUSH_CONFIG.defaultBadge,
  };

  if (event.data) {
    try {
      const payload = event.data.json();
      data = { ...data, ...payload };
    }
catch {
      data.body = event.data.text();
    }
  }

  const options = {
    body: data.body,
    icon: data.icon || PUSH_CONFIG.defaultIcon,
    badge: data.badge || PUSH_CONFIG.defaultBadge,
    vibrate: data.vibrate || [100, 50, 100],
    data: {
      url: data.url || '/',
      ...data.data,
    },
    actions: data.actions || [],
    tag: data.tag,
    renotify: data.renotify || false,
    requireInteraction: data.requireInteraction || false,
  };

  event.waitUntil(
    self.registration.showNotification(data.title, options)
  );
});

self.addEventListener('notificationclick', (event) => {
  console.log('[Workbox SW] Notification clicked');
  event.notification.close();

  const url = event.notification.data?.url || '/';

  event.waitUntil(
    clients.matchAll({ type: 'window', includeUncontrolled: true }).then(windowClients => {
      for (const client of windowClients) {
        if (client.url === url && 'focus' in client) {
          return client.focus();
        }
      }
      if (clients.openWindow) {
        return clients.openWindow(url);
      }
    })
  );
});
`}function Kj(j){return`
// ============================================================================
// Background Sync
// ============================================================================

const syncQueue = new Queue('${j?.queueName||"stx-sync-queue"}', {
  maxRetentionTime: ${j?.maxRetentionMinutes||1440}, // minutes
  onSync: async ({ queue }) => {
    let entry;
    while ((entry = await queue.shiftRequest())) {
      try {
        await fetch(entry.request.clone());
        console.log('[Workbox SW] Sync succeeded:', entry.request.url);

        // Notify clients
        const allClients = await self.clients.matchAll();
        allClients.forEach(client => {
          client.postMessage({
            type: 'SYNC_COMPLETE',
            url: entry.request.url,
            success: true,
          });
        });
      }
catch (error) {
        console.log('[Workbox SW] Sync failed, re-queuing:', entry.request.url);
        await queue.unshiftRequest(entry);
        throw error;
      }
    }
  },
});

// Register routes that should use background sync
${j?.endpoints?.map((q)=>`
registerRoute(
  ({ url }) => url.pathname.startsWith('${q}'),
  new NetworkOnly({
    plugins: [
      new BackgroundSyncPlugin('${j?.queueName||"stx-sync-queue"}', {
        maxRetentionTime: ${j?.maxRetentionMinutes||1440},
      }),
    ],
  }),
  'POST'
);`).join(`
`)||"// No background sync endpoints configured"}

// Handle form sync messages
self.addEventListener('message', (event) => {
  if (event.data?.type === 'REGISTER_FORM_SYNC') {
    const { action, method, data } = event.data.payload;

    const request = new Request(action, {
      method: method || 'POST',
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
      body: new URLSearchParams(data).toString(),
    });

    event.waitUntil(syncQueue.pushRequest({ request }));
  }
});
`}function k(j){return j.pwa?.enabled===!0&&j.pwa?.serviceWorker?.useWorkbox===!0}function Qj(j){if(k(j))return W;let{generateServiceWorker:q}=(w(),z(P));return q}var D=H(()=>{T()});var P={};R(P,{isWorkboxEnabled:()=>x,getServiceWorkerFileName:()=>Zj,generateServiceWorkerAuto:()=>$j,generateServiceWorker:()=>b});function b(j,q){let K=j.pwa;if(!K?.enabled)return"";let Q=K.serviceWorker||{},Z=K.routes||[],X=Q.cacheVersion||"1.0.0",Y=K.offline,B=Y?.page?"/offline.html":"/offline.html",L=K.push,$=K.backgroundSync,O=K.cacheStorage,U=q?_(q,j):null,d=U?A(U):"[]",m=["/","/manifest.json",...Y?.enabled?[B]:[],...Y?.precacheAssets||[]];return`/**
 * Service Worker - Auto-generated by stx
 * Cache Version: ${X}
 *
 * This service worker implements configurable caching strategies:
 * - cache-first: Serve from cache, fall back to network
 * - network-first: Try network, fall back to cache
 * - stale-while-revalidate: Serve cached, update in background
 * - network-only: Always fetch from network
 * - cache-only: Only serve from cache
 *
 * Additional features:
 * - Push notifications: ${L?.enabled?"enabled":"disabled"}
 * - Background sync: ${$?.enabled?"enabled":"disabled"}
 * - Cache limits: ${O?.maxSize?`${E(O.maxSize*1024*1024)}`:"unlimited"}
 */

const CACHE_VERSION = '${X}';
const CACHE_NAME = 'stx-pwa-v' + CACHE_VERSION;
const OFFLINE_PAGE = '${B}';

// Assets to precache on install
const PRECACHE_ASSETS = ${JSON.stringify(m,null,2)};

// Auto-generated precache manifest from build output
const BUILD_PRECACHE_MANIFEST = ${d};

// Route caching strategies
const ROUTE_STRATEGIES = ${JSON.stringify(Z,null,2)};

// Routes to exclude from caching
const EXCLUDED_ROUTES = ${JSON.stringify(Q.excludeRoutes||[],null,2)};

// Cache storage configuration
const CACHE_CONFIG = {
  maxSize: ${O?.maxSize||0} * 1024 * 1024, // Convert MB to bytes
  maxAge: ${O?.maxAge||0} * 24 * 60 * 60 * 1000, // Convert days to ms
  maxEntries: ${O?.maxEntries||0},
  purgeStrategy: '${O?.purgeStrategy||"lru"}',
};

// Background sync configuration
const SYNC_CONFIG = {
  enabled: ${$?.enabled||!1},
  queueName: '${$?.queueName||"stx-sync-queue"}',
  maxRetries: ${$?.maxRetries||3},
  minInterval: ${$?.minInterval||1000},
};

// Push notification configuration
const PUSH_CONFIG = {
  enabled: ${L?.enabled||!1},
  defaultIcon: '${L?.defaultIcon||"/pwa-icons/icon-192x192.png"}',
  defaultBadge: '${L?.defaultBadge||"/pwa-icons/icon-72x72.png"}',
};

/**
 * Install event - precache essential assets
 */
self.addEventListener('install', (event) => {
  console.log('[SW] Installing service worker...');
  ${Q.skipWaiting?"self.skipWaiting();":""}

  event.waitUntil(
    caches.open(CACHE_NAME).then(async (cache) => {
      // Combine manual precache assets with auto-generated manifest
      const allAssets = [...PRECACHE_ASSETS];

      // Add build precache manifest entries
      for (const entry of BUILD_PRECACHE_MANIFEST) {
        if (!allAssets.includes(entry.url)) {
          allAssets.push(entry.url);
        }
      }

      console.log('[SW] Precaching assets:', allAssets.length);

      // Cache assets one by one to handle failures gracefully
      const results = await Promise.allSettled(
        allAssets.map(async (url) => {
          try {
            const response = await fetch(url);
            if (response.ok) {
              await cache.put(url, response);
              return { url, success: true };
            }
            return { url, success: false, reason: response.status };
          }
catch (error) {
            return { url, success: false, reason: error.message };
          }
        })
      );

      const failed = results.filter(r => r.status === 'rejected' || (r.status === 'fulfilled' && !r.value.success));
      if (failed.length > 0) {
        console.warn('[SW] Failed to precache some assets:', failed.length);
      }
    })
  );
});

/**
 * Activate event - clean up old caches
 */
self.addEventListener('activate', (event) => {
  console.log('[SW] Activating service worker...');
  ${Q.clientsClaim?"self.clients.claim();":""}

  event.waitUntil(
    (async () => {
      // Clean up old caches
      const cacheNames = await caches.keys();
      await Promise.all(
        cacheNames
          .filter((name) => name.startsWith('stx-pwa-') && name !== CACHE_NAME)
          .map((name) => {
            console.log('[SW] Deleting old cache:', name);
            return caches.delete(name);
          })
      );

      // Enforce cache storage limits
      if (CACHE_CONFIG.maxSize > 0 || CACHE_CONFIG.maxEntries > 0) {
        await enforceCacheLimits();
      }
    })()
  );
});

/**
 * Fetch event - apply caching strategies
 */
self.addEventListener('fetch', (event) => {
  const { request } = event;
  const url = new URL(request.url);

  // Only handle GET requests
  if (request.method !== 'GET') {
    return;
  }

  // Skip cross-origin requests
  if (url.origin !== location.origin) {
    return;
  }

  // Skip excluded routes
  if (isExcludedRoute(url.pathname)) {
    return;
  }

  // Find matching strategy and apply
  const routeConfig = getRouteConfig(url.pathname);
  event.respondWith(applyStrategy(request, routeConfig));
});

/**
 * Message event - handle messages from main thread
 */
self.addEventListener('message', (event) => {
  const { type, payload } = event.data || {};

  switch (type) {
    case 'SKIP_WAITING':
      console.log('[SW] Received SKIP_WAITING message');
      self.skipWaiting();
      break;

    case 'CACHE_URLS':
      if (Array.isArray(payload)) {
        event.waitUntil(
          caches.open(CACHE_NAME).then((cache) => cache.addAll(payload))
        );
      }
      break;

    case 'CLEAR_CACHE':
      event.waitUntil(
        caches.keys().then((names) =>
          Promise.all(names.map((name) => caches.delete(name)))
        )
      );
      break;

    case 'GET_CACHE_SIZE':
      event.waitUntil(
        getCacheSize().then((size) => {
          event.source?.postMessage({ type: 'CACHE_SIZE', payload: size });
        })
      );
      break;
  }
});

${L?.enabled?Xj():"// Push notifications disabled"}

${$?.enabled?Yj():"// Background sync disabled"}

/**
 * Check if a route should be excluded from caching
 */
function isExcludedRoute(pathname) {
  return EXCLUDED_ROUTES.some((pattern) => matchPattern(pathname, pattern));
}

/**
 * Match a path against a glob pattern
 * Supports: *.ext, /path/*, /path/**, exact matches
 */
function matchPattern(path, pattern) {
  // Handle file extension patterns like *.js, *.css
  if (pattern.startsWith('*.')) {
    return path.endsWith(pattern.slice(1));
  }

  // Handle patterns ending with /**
  if (pattern.endsWith('/**')) {
    const prefix = pattern.slice(0, -3);
    return path.startsWith(prefix);
  }

  // Handle patterns ending with /*
  if (pattern.endsWith('/*')) {
    const prefix = pattern.slice(0, -2);
    if (!path.startsWith(prefix)) return false;
    const rest = path.slice(prefix.length);
    return rest.length > 0 && !rest.slice(1).includes('/');
  }

  // Handle patterns with * in the middle
  if (pattern.includes('*')) {
    const parts = pattern.split('*');
    if (parts.length === 2) {
      return path.startsWith(parts[0]) && path.endsWith(parts[1]);
    }
  }

  // Exact match
  return path === pattern;
}

/**
 * Get the cache configuration for a given path
 */
function getRouteConfig(pathname) {
  for (const route of ROUTE_STRATEGIES) {
    if (matchPattern(pathname, route.pattern)) {
      return route;
    }
  }
  // Default to network-first for unmatched routes
  return { strategy: 'network-first' };
}

/**
 * Apply the appropriate caching strategy
 */
async function applyStrategy(request, routeConfig) {
  const { strategy, cacheName, maxAgeSeconds, maxEntries } = routeConfig;
  const cache = await caches.open(cacheName || CACHE_NAME);

  switch (strategy) {
    case 'cache-first':
      return cacheFirst(request, cache, maxAgeSeconds);

    case 'network-first':
      return networkFirst(request, cache);

    case 'stale-while-revalidate':
      return staleWhileRevalidate(request, cache);

    case 'network-only':
      return networkOnly(request);

    case 'cache-only':
      return cacheOnly(request, cache);

    default:
      return networkFirst(request, cache);
  }
}

/**
 * Cache-first strategy
 * Serve from cache if available, otherwise fetch from network
 */
async function cacheFirst(request, cache, maxAge) {
  const cached = await cache.match(request);

  if (cached) {
    // Check if cache is still valid (if maxAge is set)
    if (maxAge) {
      const cachedDate = cached.headers.get('sw-cache-date');
      if (cachedDate) {
        const age = (Date.now() - new Date(cachedDate).getTime()) / 1000;
        if (age > maxAge) {
          // Cache expired, fetch fresh
          return fetchAndCache(request, cache);
        }
      }
    }
    return cached;
  }

  return fetchAndCache(request, cache);
}

/**
 * Network-first strategy
 * Try network first, fall back to cache if offline
 */
async function networkFirst(request, cache) {
  try {
    const response = await fetch(request);
    if (response.ok) {
      const cloned = response.clone();
      cache.put(request, cloned);
    }
    return response;
  }
catch (error) {
    const cached = await cache.match(request);
    if (cached) {
      return cached;
    }
    return offlineResponse(request);
  }
}

/**
 * Stale-while-revalidate strategy
 * Serve cached immediately, update cache in background
 */
async function staleWhileRevalidate(request, cache) {
  const cached = await cache.match(request);

  // Fetch in background to update cache
  const fetchPromise = fetch(request)
    .then((response) => {
      if (response.ok) {
        cache.put(request, response.clone());
      }
      return response;
    })
    .catch(() => null);

  // Return cached immediately if available, otherwise wait for fetch
  if (cached) {
    return cached;
  }

  const response = await fetchPromise;
  return response || offlineResponse(request);
}

/**
 * Network-only strategy
 * Always fetch from network, no caching
 */
async function networkOnly(request) {
  try {
    return await fetch(request);
  }
catch (error) {
    return offlineResponse(request);
  }
}

/**
 * Cache-only strategy
 * Only serve from cache, never fetch
 */
async function cacheOnly(request, cache) {
  const cached = await cache.match(request);
  return cached || offlineResponse(request);
}

/**
 * Fetch and cache a request
 */
async function fetchAndCache(request, cache) {
  try {
    const response = await fetch(request);
    if (response.ok) {
      // Add cache timestamp header
      const headers = new Headers(response.headers);
      headers.set('sw-cache-date', new Date().toISOString());

      const cachedResponse = new Response(response.clone().body, {
        status: response.status,
        statusText: response.statusText,
        headers,
      });

      cache.put(request, cachedResponse);
    }
    return response;
  }
catch (error) {
    return offlineResponse(request);
  }
}

/**
 * Generate offline response
 */
async function offlineResponse(request) {
  // For navigation requests, return offline page
  if (request.mode === 'navigate') {
    const cache = await caches.open(CACHE_NAME);
    const offlinePage = await cache.match(OFFLINE_PAGE);
    if (offlinePage) {
      return offlinePage;
    }
  }

  // Return a basic offline response
  return new Response('You are offline', {
    status: 503,
    statusText: 'Service Unavailable',
    headers: {
      'Content-Type': 'text/plain',
    },
  });
}

/**
 * Get total cache size
 */
async function getCacheSize() {
  let totalSize = 0;
  const cacheNames = await caches.keys();

  for (const cacheName of cacheNames) {
    const cache = await caches.open(cacheName);
    const keys = await cache.keys();

    for (const request of keys) {
      const response = await cache.match(request);
      if (response) {
        const blob = await response.clone().blob();
        totalSize += blob.size;
      }
    }
  }

  return totalSize;
}

/**
 * Enforce cache storage limits
 */
async function enforceCacheLimits() {
  const cache = await caches.open(CACHE_NAME);
  const keys = await cache.keys();

  // Get cache entries with metadata
  const entries = [];
  for (const request of keys) {
    const response = await cache.match(request);
    if (response) {
      const blob = await response.clone().blob();
      const cachedDate = response.headers.get('sw-cache-date');
      entries.push({
        request,
        size: blob.size,
        date: cachedDate ? new Date(cachedDate) : new Date(),
      });
    }
  }

  // Check total size limit
  if (CACHE_CONFIG.maxSize > 0) {
    const totalSize = entries.reduce((sum, e) => sum + e.size, 0);

    if (totalSize > CACHE_CONFIG.maxSize) {
      console.log('[SW] Cache size exceeded, purging...');
      await purgeCache(entries, cache, CACHE_CONFIG.maxSize);
    }
  }

  // Check max entries limit
  if (CACHE_CONFIG.maxEntries > 0 && entries.length > CACHE_CONFIG.maxEntries) {
    console.log('[SW] Cache entries exceeded, purging...');
    await purgeByEntryCount(entries, cache, CACHE_CONFIG.maxEntries);
  }

  // Check max age limit
  if (CACHE_CONFIG.maxAge > 0) {
    const now = Date.now();
    const expiredEntries = entries.filter(e => (now - e.date.getTime()) > CACHE_CONFIG.maxAge);

    for (const entry of expiredEntries) {
      console.log('[SW] Removing expired cache entry:', entry.request.url);
      await cache.delete(entry.request);
    }
  }
}

/**
 * Purge cache to meet size limit
 */
async function purgeCache(entries, cache, maxSize) {
  // Sort by purge strategy
  const sorted = [...entries];

  switch (CACHE_CONFIG.purgeStrategy) {
    case 'lru':
      // Least Recently Used - remove oldest first
      sorted.sort((a, b) => a.date.getTime() - b.date.getTime());
      break;
    case 'fifo':
      // First In First Out - same as lru for our purposes
      sorted.sort((a, b) => a.date.getTime() - b.date.getTime());
      break;
    case 'lfu':
      // Least Frequently Used - we don't track frequency, use size as proxy
      sorted.sort((a, b) => b.size - a.size);
      break;
    default:
      sorted.sort((a, b) => a.date.getTime() - b.date.getTime());
  }

  let currentSize = entries.reduce((sum, e) => sum + e.size, 0);

  for (const entry of sorted) {
    if (currentSize <= maxSize * 0.8) { // Keep 80% buffer
      break;
    }

    // Don't delete essential assets
    const url = entry.request.url;
    if (PRECACHE_ASSETS.some(asset => url.endsWith(asset))) {
      continue;
    }

    console.log('[SW] Purging cache entry:', url);
    await cache.delete(entry.request);
    currentSize -= entry.size;
  }
}

/**
 * Purge cache by entry count
 */
async function purgeByEntryCount(entries, cache, maxEntries) {
  const sorted = [...entries].sort((a, b) => a.date.getTime() - b.date.getTime());
  const toRemove = sorted.slice(0, entries.length - maxEntries);

  for (const entry of toRemove) {
    // Don't delete essential assets
    const url = entry.request.url;
    if (PRECACHE_ASSETS.some(asset => url.endsWith(asset))) {
      continue;
    }

    await cache.delete(entry.request);
  }
}

console.log('[SW] Service Worker loaded - Version:', CACHE_VERSION);
`}function Xj(){return`
/**
 * Push event - handle incoming push notifications
 */
self.addEventListener('push', (event) => {
  console.log('[SW] Push notification received');

  let data = {
    title: 'Notification',
    body: 'You have a new notification',
    icon: PUSH_CONFIG.defaultIcon,
    badge: PUSH_CONFIG.defaultBadge,
  };

  if (event.data) {
    try {
      const payload = event.data.json();
      data = { ...data, ...payload };
    }
catch {
      data.body = event.data.text();
    }
  }

  const options = {
    body: data.body,
    icon: data.icon || PUSH_CONFIG.defaultIcon,
    badge: data.badge || PUSH_CONFIG.defaultBadge,
    vibrate: data.vibrate || [100, 50, 100],
    data: {
      url: data.url || '/',
      ...data.data,
    },
    actions: data.actions || [],
    tag: data.tag,
    renotify: data.renotify || false,
    requireInteraction: data.requireInteraction || false,
    silent: data.silent || false,
  };

  event.waitUntil(
    self.registration.showNotification(data.title, options)
  );
});

/**
 * Notification click event - handle notification interactions
 */
self.addEventListener('notificationclick', (event) => {
  console.log('[SW] Notification clicked:', event.action);
  event.notification.close();

  const url = event.notification.data?.url || '/';

  event.waitUntil(
    clients.matchAll({ type: 'window', includeUncontrolled: true }).then((windowClients) => {
      // Check if there's already a window open with this URL
      for (const client of windowClients) {
        if (client.url === url && 'focus' in client) {
          return client.focus();
        }
      }
      // Open a new window
      if (clients.openWindow) {
        return clients.openWindow(url);
      }
    })
  );
});

/**
 * Notification close event
 */
self.addEventListener('notificationclose', (event) => {
  console.log('[SW] Notification closed');

  // Track notification dismissal if needed
  const data = event.notification.data;
  if (data?.trackDismiss) {
    // Could send analytics here
  }
});
`}function Yj(){return`
/**
 * Background sync queue storage (IndexedDB)
 */
const SYNC_STORE = 'stx-sync-store';
let syncDb = null;

async function getSyncDb() {
  if (syncDb) return syncDb;

  return new Promise((resolve, reject) => {
    const request = indexedDB.open(SYNC_STORE, 1);

    request.onerror = () => reject(request.error);
    request.onsuccess = () => {
      syncDb = request.result;
      resolve(syncDb);
    };

    request.onupgradeneeded = (event) => {
      const db = event.target.result;
      if (!db.objectStoreNames.contains('queue')) {
        db.createObjectStore('queue', { keyPath: 'id', autoIncrement: true });
      }
    };
  });
}

/**
 * Add request to sync queue
 */
async function addToSyncQueue(request) {
  const db = await getSyncDb();
  const tx = db.transaction('queue', 'readwrite');
  const store = tx.objectStore('queue');

  const data = {
    url: request.url,
    method: request.method,
    headers: Object.fromEntries(request.headers.entries()),
    body: await request.clone().text(),
    timestamp: Date.now(),
    retries: 0,
  };

  return new Promise((resolve, reject) => {
    const req = store.add(data);
    req.onsuccess = () => resolve(req.result);
    req.onerror = () => reject(req.error);
  });
}

/**
 * Get all pending sync requests
 */
async function getPendingSyncRequests() {
  const db = await getSyncDb();
  const tx = db.transaction('queue', 'readonly');
  const store = tx.objectStore('queue');

  return new Promise((resolve, reject) => {
    const req = store.getAll();
    req.onsuccess = () => resolve(req.result);
    req.onerror = () => reject(req.error);
  });
}

/**
 * Remove request from sync queue
 */
async function removeSyncRequest(id) {
  const db = await getSyncDb();
  const tx = db.transaction('queue', 'readwrite');
  const store = tx.objectStore('queue');

  return new Promise((resolve, reject) => {
    const req = store.delete(id);
    req.onsuccess = () => resolve();
    req.onerror = () => reject(req.error);
  });
}

/**
 * Update sync request retry count
 */
async function updateSyncRetries(id, retries) {
  const db = await getSyncDb();
  const tx = db.transaction('queue', 'readwrite');
  const store = tx.objectStore('queue');

  const req = store.get(id);
  req.onsuccess = () => {
    const data = req.result;
    if (data) {
      data.retries = retries;
      store.put(data);
    }
  };
}

/**
 * Sync event - process queued requests when online
 */
self.addEventListener('sync', (event) => {
  console.log('[SW] Sync event:', event.tag);

  if (event.tag === SYNC_CONFIG.queueName || event.tag === 'stx-form-sync') {
    event.waitUntil(processBackgroundSync());
  }
});

/**
 * Process all queued sync requests
 */
async function processBackgroundSync() {
  console.log('[SW] Processing background sync queue');

  const requests = await getPendingSyncRequests();
  console.log('[SW] Pending sync requests:', requests.length);

  for (const request of requests) {
    if (request.retries >= SYNC_CONFIG.maxRetries) {
      console.log('[SW] Max retries reached, removing:', request.url);
      await removeSyncRequest(request.id);
      continue;
    }

    try {
      const response = await fetch(request.url, {
        method: request.method,
        headers: request.headers,
        body: request.method !== 'GET' ? request.body : undefined,
      });

      if (response.ok) {
        console.log('[SW] Sync succeeded:', request.url);
        await removeSyncRequest(request.id);

        // Notify clients of successful sync
        const clients = await self.clients.matchAll();
        clients.forEach(client => {
          client.postMessage({
            type: 'SYNC_COMPLETE',
            url: request.url,
            success: true,
          });
        });
      }
else {
        throw new Error('Response not ok: ' + response.status);
      }
    }
catch (error) {
      console.log('[SW] Sync failed, will retry:', request.url, error.message);
      await updateSyncRetries(request.id, request.retries + 1);
    }
  }
}

/**
 * Register a form for background sync
 * Called from main thread via message
 */
async function registerFormSync(formData) {
  // Store form data in IndexedDB
  await addToSyncQueue({
    url: formData.action,
    method: formData.method || 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    clone: () => ({ text: async () => new URLSearchParams(formData.data).toString() }),
  });

  // Register for background sync
  await self.registration.sync.register(SYNC_CONFIG.queueName);
}

// Listen for form sync requests
self.addEventListener('message', (event) => {
  if (event.data?.type === 'REGISTER_FORM_SYNC') {
    event.waitUntil(registerFormSync(event.data.payload));
  }
});
`}function Zj(j){return j.pwa?.serviceWorker?.fileName||"sw.js"}function x(j){return j.pwa?.enabled===!0&&j.pwa?.serviceWorker?.useWorkbox===!0}function $j(j,q){if(!j.pwa?.enabled)return"";if(x(j)){let{generateWorkboxServiceWorker:K}=(D(),z(S));return K(j,q)}return b(j,q)}var w=H(()=>{T()});w();export{x as isWorkboxEnabled,Zj as getServiceWorkerFileName,$j as generateServiceWorkerAuto,b as generateServiceWorker};
