PageSourceSearch

https://coach.liminarylife.com/sw-push.js

js liminarylife.com collected 2026-10-05 19:17:29 UTC 3,512 bytes, 101 lines download raw bytes

1/* OverSkill Web Push Service Worker.
2 *
3 * Companion to the SDK's `overskill.push.subscribe()`. Receives `push`
4 * events from the platform's push relay and shows a system notification.
5 *
6 * Lives at /sw-push.js so it has root scope (can show notifications
7 * for any URL on the app's origin). Vite's PWA plugin generates ITS OWN
8 * service worker for offline asset caching — that one lives at /sw.js
9 * by default. We don't want to merge the two: precaching has very
10 * different lifecycle semantics from push, and Workbox's auto-update
11 * model would clobber our push handlers on every deploy.
12 *
13 * If your generated app needs both PWA precaching AND push, both SWs
14 * coexist fine — each owns its own scope. Browsers allow multiple
15 * service workers per origin.
16 */
17
18self.addEventListener('install', () => {
19  // Activate immediately on first install so the user gets push reception
20  // without needing to refresh after subscribe.
21  self.skipWaiting();
22});
23
24self.addEventListener('activate', (event) => {
25  event.waitUntil(self.clients.claim());
26});
27
28self.addEventListener('push', (event) => {
29  if (!event.data) return;
30
31  let payload;
32  try {
33    payload = event.data.json();
34  } catch (err) {
35    payload = { title: 'Notification', body: event.data.text() };
36  }
37
38  const title = payload.title || 'Notification';
39  const options = {
40    body: payload.body,
41    icon: payload.icon || '/icon-192.png',
42    badge: payload.badge || payload.icon || '/icon-192.png',
43    data: {
44      url: payload.url || '/',
45      ...(payload.data || {})
46    }
47  };
48
49  event.waitUntil(self.registration.showNotification(title, options));
50});
51
52self.addEventListener('notificationclick', (event) => {
53  event.notification.close();
54  const targetUrl = event.notification.data?.url || '/';
55
56  // Focus an existing window with the same URL if possible; otherwise
57  // open a new one. Standard "click to deep-link" UX.
58  event.waitUntil(
59    self.clients.matchAll({ type: 'window', includeUncontrolled: true }).then((clientList) => {
60      for (const client of clientList) {
61        if (client.url.endsWith(targetUrl) && 'focus' in client) {
62          return client.focus();
63        }
64      }
65      if (self.clients.openWindow) {
66        return self.clients.openWindow(targetUrl);
67      }
68    })
69  );
70});
71
72;
73// ---- OverSkill push capability ping (#3705) -------------------------
74// The page cannot introspect a service worker's listeners, so a worker
75// that handles push says so out loud. overskill-runtime-sdk's push scope
76// guard uses this to tell "the worker that owns / can receive push" from
77// "the worker that owns / is a bare precache worker" — without it the
78// guard could hand a caller a registration whose push events go nowhere,
79// which is the #3705 bug wearing a different hat.
80self.__overskillPushSw = 1;
81self.addEventListener('message', function (event) {
82  var data = event.data;
83  if (!data || data.type !== 'OVERSKILL_PUSH_SW_PING') return;
84  var reply = { type: 'OVERSKILL_PUSH_SW_PONG', pushSw: self.__overskillPushSw };
85  try {
86    if (event.ports && event.ports[0]) {
87      event.ports[0].postMessage(reply);
88      return;
89    }
90  } catch (err) {
91    // Fall through to the client channel below.
92  }
93  try {
94    if (event.source && typeof event.source.postMessage === 'function') {
95      event.source.postMessage(reply);
96    }
97  } catch (err) {
98    // A page we cannot answer simply times out and treats us as
99    // push-incapable — the safe direction (it registers its own worker).
100  }
101});

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.