Files
stroblmeandClaude Opus 5 d01a8dad37 Rename Installation to Instance
Follows the portal: the noun is "instance" everywhere the app says it —
UI strings, CLI output, error details, docs and comments. The wire keys
(`instance_id`, `instance_token`) and the hub route this calls move with it.

An existing cloud.json is adopted rather than refused: without the key
alias the dataclass fails to parse, which the caller swallows and reads as
"never enrolled" instead of "reconnect".

`instance_key` on a node type becomes `target_key`. It means the outside
thing a node points at, which is a different sense of the word, and keeping
both would put two meanings of "instance" in one codebase.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015YrQnKV3bnQd4K342y8tKj
2026-08-31 10:12:01 +02:00

46 lines
1.7 KiB
JavaScript

/**
* The service worker, which exists only so a push can arrive when no tab is
* open. There is deliberately no `fetch` handler and nothing is cached: the
* page this app is served from carries a credential and is sent `no-store`,
* so caching it would hand the next visitor somebody else's session.
*
* `registration.scope` is the app's root in both places it runs — `/` on an
* instance of its own, `/i/{id}/` through the portal — which is why the
* push payload does not carry a URL.
*/
self.addEventListener("push", (event) => {
const alert = event.data ? event.data.json() : {}
const scope = new URL(self.registration.scope)
event.waitUntil(
self.registration.showNotification(alert.title || "Fluksio", {
body: alert.body || "",
// Under the portal the icons are the shared bundle's, not this
// instance's path.
icon: scope.pathname.startsWith("/i/")
? "/app-shell/icon-192.png"
: `${scope.pathname}icon-192.png`,
// The same fault repeating replaces its notification rather than
// stacking another one up.
tag: alert.flow || alert.title || "fluksio",
timestamp: Date.now(),
}),
)
})
self.addEventListener("notificationclick", (event) => {
event.notification.close()
const scope = self.registration.scope
event.waitUntil(
self.clients
.matchAll({ type: "window", includeUncontrolled: true })
.then((clients) => {
// A tab on this instance is already open: raise it rather than
// opening a second one.
const open = clients.find((client) => client.url.startsWith(scope))
if (open) return open.focus()
return self.clients.openWindow(scope)
}),
)
})