PageSourceSearch

https://vervecode.dev/push-sw.js

js vervecode.dev collected 2026-10-09 17:40:11 UTC 2,687 bytes, 91 lines download raw bytes

1/* Browser-only worker: no fetch handler, no article caching. */
2self.addEventListener('install', () => self.skipWaiting());
3self.addEventListener('activate', (event) =>
4  event.waitUntil(self.clients.claim()),
5);
6function claim(id) {
7  return new Promise((resolve, reject) => {
8    const request = indexedDB.open('vervecode-push', 1);
9    request.onupgradeneeded = () =>
10      request.result.createObjectStore('seen', { keyPath: 'id' });
11    request.onerror = () => reject(request.error);
12    request.onsuccess = () => {
13      const db = request.result;
14      const tx = db.transaction('seen', 'readwrite');
15      let fresh = false;
16      const store = tx.objectStore('seen');
17      const get = store.get(id);
18      get.onsuccess = () => {
19        if (!get.result) {
20          store.add({ id, at: Date.now() });
21          fresh = true;
22        }
23      };
24      tx.oncomplete = () => {
25        db.close();
26        resolve(fresh);
27      };
28      tx.onerror = () => {
29        db.close();
30        reject(tx.error);
31      };
32    };
33  });
34}
35self.addEventListener('push', (event) => {
36  event.waitUntil(
37    (async () => {
38      let data;
39      try {
40        data = event.data.json();
41      } catch {
42        return;
43      }
44      if (
45        !data ||
46        typeof data.id !== 'string' ||
47        data.id.length > 64 ||
48        typeof data.title !== 'string' ||
49        typeof data.body !== 'string' ||
50        !Number.isFinite(data.expires) ||
51        data.expires <= Date.now()
52      )
53        return;
54      if (
55        typeof data.path !== 'string' ||
56        !data.path.startsWith('/') ||
57        data.path.startsWith('//') ||
58        /[\\?#]/.test(data.path)
59      )
60        return;
61      const url = new URL(data.path, self.location.origin);
62      if (url.origin !== self.location.origin || !(await claim(data.id)))
63        return;
64      await self.registration.showNotification(data.title.slice(0, 100), {
65        body: data.body.slice(0, 160),
66        tag: `vervecode-${data.id}`,
67        renotify: false,
68        data: { url: url.href, id: data.id },
69      });
70    })(),
71  );
72});
73self.addEventListener('notificationclick', (event) => {
74  event.notification.close();
75  event.waitUntil(
76    (async () => {
77      const url = new URL(
78        event.notification.data?.url || '/',
79        self.location.origin,
80      );
81      if (url.origin !== self.location.origin) return;
82      const windows = await self.clients.matchAll({
83        type: 'window',
84        includeUncontrolled: true,
85      });
86      const existing = windows.find((client) => client.url === url.href);
87      if (existing) await existing.focus();
88      else await self.clients.openWindow(url.href);
89    })(),
90  );
91});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.