From 7ceaf69651d50f3aed2ed1c48964d14f0e702995 Mon Sep 17 00:00:00 2001 From: Daniel Salazar Date: Thu, 29 Oct 2026 20:10:27 -0700 Subject: [PATCH] docs(notifications): import push-sw.js from the root of js.puter.com (#4405) The worker is published next to puter.js at https://js.puter.com/push-sw.js. Docs and the worker's own header now point there. The js subdomain serves /push-sw.js for self-hosted setups and keeps /v2/push-sw.js as an alias. --- .../static/StaticAssetsController.test.ts | 14 ++++++++----- .../static/StaticAssetsController.ts | 21 ++++++++++--------- src/docs/src/Notifications/onPush.md | 4 ++-- src/docs/src/Notifications/push.md | 2 +- src/docs/src/recipes/push-when-closed.md | 4 ++-- src/puter-js/src/push-sw.js | 4 ++-- 6 files changed, 27 insertions(+), 22 deletions(-) diff --git a/src/backend/controllers/static/StaticAssetsController.test.ts b/src/backend/controllers/static/StaticAssetsController.test.ts index 5ac117b5b..5b1853c34 100644 --- a/src/backend/controllers/static/StaticAssetsController.test.ts +++ b/src/backend/controllers/static/StaticAssetsController.test.ts @@ -152,9 +152,11 @@ describe('StaticAssetsController client_libs_root', () => { const sentPutility = await callGetHandler(router, '/putility/v1'); expect(sentPutility).toEqual({ filename: 'putility.js/v1.js', root }); - expect(findRoute(router, 'get', '/v2/push-sw.js')?.options.subdomain).toBe('js'); - const sentWorker = await callGetHandler(router, '/v2/push-sw.js'); - expect(sentWorker).toEqual({ filename: 'puter.js/push-sw.js', root }); + for (const route of ['/push-sw.js', '/v2/push-sw.js']) { + expect(findRoute(router, 'get', route)?.options.subdomain).toBe('js'); + const sentWorker = await callGetHandler(router, route); + expect(sentWorker).toEqual({ filename: 'puter.js/push-sw.js', root }); + } }); it('does not register the client_libs routes when the root is unset', () => { @@ -191,8 +193,10 @@ describe('StaticAssetsController puterjs_root', () => { const bareV1 = await callGetHandler(router, '/v1'); expect(bareV1.filename).toBe('puter.js'); - const worker = await callGetHandler(router, '/v2/push-sw.js'); - expect(worker).toEqual({ filename: 'push-sw.js', root }); + for (const route of ['/push-sw.js', '/v2/push-sw.js']) { + const worker = await callGetHandler(router, route); + expect(worker).toEqual({ filename: 'push-sw.js', root }); + } }); it('serves puter.dev.js when present (dev webpack build)', async () => { diff --git a/src/backend/controllers/static/StaticAssetsController.ts b/src/backend/controllers/static/StaticAssetsController.ts index 27d03dd02..256ebd5d3 100644 --- a/src/backend/controllers/static/StaticAssetsController.ts +++ b/src/backend/controllers/static/StaticAssetsController.ts @@ -26,7 +26,7 @@ import type { PuterRouter } from '../../core/http/PuterRouter'; /** * Static asset routes. * - * /puter.js/v1, /puter.js/v2 → any subdomain /v1, /v2, /v2/push-sw.js, + * /puter.js/v1, /puter.js/v2 → any subdomain /v1, /v2, /push-sw.js, * /putility/v1 → js subdomain /sdk/* → root subdomain — puter-js bundle * /dist/_, /src/_, /assets/* → root subdomain * @@ -55,9 +55,12 @@ export class StaticAssetsController extends PuterController { router.get('/putility/v1', { subdomain: 'js' }, (_req, res) => { res.sendFile('putility.js/v1.js', { root }); }); - router.get('/v2/push-sw.js', { subdomain: 'js' }, (_req, res) => { - res.sendFile('puter.js/push-sw.js', { root }); - }); + // `/v2/push-sw.js` is the path older docs gave. + for (const route of ['/push-sw.js', '/v2/push-sw.js']) { + router.get(route, { subdomain: 'js' }, (_req, res) => { + res.sendFile('puter.js/push-sw.js', { root }); + }); + } } // puter-js SDK mount. GUI loads it at `/sdk/puter.dev.js`; the @@ -103,13 +106,11 @@ export class StaticAssetsController extends PuterController { router.get('/v2', { subdomain: 'js' }, (_req, res) => { res.sendFile(puterJsFile, { root: puterjsRoot }); }); - router.get( - '/v2/push-sw.js', - { subdomain: 'js' }, - (_req, res) => { + for (const route of ['/push-sw.js', '/v2/push-sw.js']) { + router.get(route, { subdomain: 'js' }, (_req, res) => { res.sendFile('push-sw.js', { root: puterjsRoot }); - }, - ); + }); + } } } diff --git a/src/docs/src/Notifications/onPush.md b/src/docs/src/Notifications/onPush.md index 917cb4d52..1885c1ccf 100644 --- a/src/docs/src/Notifications/onPush.md +++ b/src/docs/src/Notifications/onPush.md @@ -11,7 +11,7 @@ Puter picks the route. A page tells Puter on its own when it receives a notifica On a website, pushes reach your own origin, so your site has to serve a service worker that loads Puter's push script. Put this in `/puter-sw.js` at the root of your site: ```js -importScripts('https://js.puter.com/v2/push-sw.js'); +importScripts('https://js.puter.com/push-sw.js'); ``` If your site already has a service worker, add that line to it instead and pass its path as `serviceWorker`. Inside the Puter desktop, pushes go through Puter itself and no worker is needed. @@ -53,7 +53,7 @@ On a website, the handler is saved as source and run again in your service worke A handler that needs more, such as imported code, can be registered in the worker itself, where it wins over the saved one: ```js -importScripts('https://js.puter.com/v2/push-sw.js', '/my-formatting.js'); +importScripts('https://js.puter.com/push-sw.js', '/my-formatting.js'); puterPush.onPush('chat', (n) => ({ title: formatTitle(n) })); ``` diff --git a/src/docs/src/Notifications/push.md b/src/docs/src/Notifications/push.md index 7aa5343e0..aed27b62a 100644 --- a/src/docs/src/Notifications/push.md +++ b/src/docs/src/Notifications/push.md @@ -17,7 +17,7 @@ On a website, pushes arrive on your own domain through a small service worker, a Put this file at the root of your site, as `/puter-sw.js`: ```js -importScripts('https://js.puter.com/v2/push-sw.js'); +importScripts('https://js.puter.com/push-sw.js'); ``` If your site already has a service worker, add that line to it and pass its path as `serviceWorker` to [`onPush()`](/Notifications/onPush/) and [`enable()`](/Notifications/enable/). diff --git a/src/docs/src/recipes/push-when-closed.md b/src/docs/src/recipes/push-when-closed.md index 5cebbdc63..c9ca7aad8 100644 --- a/src/docs/src/recipes/push-when-closed.md +++ b/src/docs/src/recipes/push-when-closed.md @@ -14,7 +14,7 @@ This recipe sets that up for a website on its own domain. An app inside the Pute Pushes arrive on your own domain through a service worker. Put this file at the root of your site, as `/puter-sw.js`: ```js -importScripts('https://js.puter.com/v2/push-sw.js'); +importScripts('https://js.puter.com/push-sw.js'); ``` If your site already has a service worker, add that line to it and pass its path as `serviceWorker` in the calls below. @@ -81,7 +81,7 @@ Push services can read `data`, so put IDs in it and fetch the rest. For a notifi The worker, at `/puter-sw.js`: ```js -importScripts('https://js.puter.com/v2/push-sw.js'); +importScripts('https://js.puter.com/push-sw.js'); ``` The page: diff --git a/src/puter-js/src/push-sw.js b/src/puter-js/src/push-sw.js index 04cb146f7..06d855d6f 100644 --- a/src/puter-js/src/push-sw.js +++ b/src/puter-js/src/push-sw.js @@ -1,8 +1,8 @@ // Puter push notifications on an app's own origin, served at -// https://js.puter.com/v2/push-sw.js. The app serves a worker (default +// https://js.puter.com/push-sw.js. The app serves a worker (default // `/puter-sw.js`) that contains: // -// importScripts('https://js.puter.com/v2/push-sw.js'); +// importScripts('https://js.puter.com/push-sw.js'); // // It shows each Puter push, running the handler the page saved with // `puter.notifications.onPush(key, handler)`, and routes taps back to the app.