{"version":3,"file":"create-push-handler.cjs","names":[],"sources":["../../src/sw/create-push-handler.ts"],"sourcesContent":["/**\n * Service-worker context helpers for handling `push` and `notificationclick`\n * events. Import these inside your own `sw.ts` — they expect to run in the\n * service-worker global scope, not in the main thread.\n *\n * @example\n *   /// <reference lib=\"webworker\" />\n *   import { installPushHandler, installNotificationClickHandler } from \"tempest-react-sdk\";\n *\n *   installPushHandler({ defaultIcon: \"/icons/Logo.png\" });\n *   installNotificationClickHandler();\n */\n\ninterface SwGlobal {\n    registration: {\n        showNotification(title: string, options?: NotificationOptions): Promise<void>;\n    };\n    clients: {\n        matchAll(options: { type: \"window\"; includeUncontrolled?: boolean }): Promise<\n            {\n                url: string;\n                focused: boolean;\n                focus(): Promise<unknown>;\n                navigate(url: string): Promise<unknown>;\n            }[]\n        >;\n        openWindow(url: string): Promise<unknown>;\n    };\n    addEventListener(\n        type: \"push\",\n        listener: (event: {\n            data: { json(): unknown; text(): string } | null;\n            waitUntil(promise: Promise<unknown>): void;\n        }) => void,\n    ): void;\n    addEventListener(\n        type: \"notificationclick\",\n        listener: (event: {\n            notification: { close(): void; data?: unknown };\n            waitUntil(promise: Promise<unknown>): void;\n        }) => void,\n    ): void;\n    skipWaiting(): Promise<void>;\n}\n\nfunction getSwScope(): SwGlobal {\n    return globalThis as unknown as SwGlobal;\n}\n\nexport interface PushPayload {\n    title?: string;\n    body?: string;\n    icon?: string;\n    badge?: string;\n    image?: string;\n    tag?: string;\n    url?: string;\n    /** Arbitrary extra data forwarded to `event.notification.data`. */\n    data?: Record<string, unknown>;\n}\n\nexport interface InstallPushHandlerOptions {\n    /** Title used when the payload omits one. */\n    defaultTitle?: string;\n    /** Icon used when the payload omits one. */\n    defaultIcon?: string;\n    /** Badge image (mobile). */\n    defaultBadge?: string;\n    /**\n     * Transform the raw payload before showing the notification. Return `null`\n     * to suppress the notification entirely (e.g. silent pings).\n     */\n    transform?: (payload: PushPayload) => PushPayload | null;\n}\n\n/**\n * Install a `push` event listener that parses the payload as JSON (with a\n * plain-text fallback) and shows a notification.\n */\nexport function installPushHandler(options: InstallPushHandlerOptions = {}): void {\n    const sw = getSwScope();\n    const { defaultTitle = \"Notificação\", defaultIcon, defaultBadge, transform } = options;\n\n    sw.addEventListener(\"push\", (event) => {\n        if (!event.data) return;\n\n        let raw: PushPayload;\n        try {\n            raw = event.data.json() as PushPayload;\n        } catch {\n            raw = { title: defaultTitle, body: event.data.text() };\n        }\n\n        const payload = transform ? transform(raw) : raw;\n        if (!payload) return;\n\n        const title = payload.title ?? defaultTitle;\n        const notification: NotificationOptions & { image?: string } = {\n            body: payload.body,\n            icon: payload.icon ?? defaultIcon,\n            badge: payload.badge ?? defaultBadge,\n            image: payload.image,\n            tag: payload.tag,\n            data: { url: payload.url ?? \"/\", ...(payload.data ?? {}) },\n        };\n\n        event.waitUntil(sw.registration.showNotification(title, notification));\n    });\n}\n\nexport interface InstallNotificationClickHandlerOptions {\n    /** Resolve the destination URL from the notification data. Default: `data.url`. */\n    resolveUrl?: (data: unknown) => string;\n}\n\n/**\n * Install a `notificationclick` handler that focuses an existing client when\n * possible and falls back to opening a new window.\n */\nexport function installNotificationClickHandler(\n    options: InstallNotificationClickHandlerOptions = {},\n): void {\n    const sw = getSwScope();\n    const resolveUrl =\n        options.resolveUrl ??\n        ((data: unknown) => {\n            if (typeof data === \"string\") return data;\n            if (data && typeof data === \"object\" && \"url\" in data) {\n                const url = (data as Record<string, unknown>).url;\n                return typeof url === \"string\" ? url : \"/\";\n            }\n            return \"/\";\n        });\n\n    sw.addEventListener(\"notificationclick\", (event) => {\n        event.notification.close();\n        const target = resolveUrl(event.notification.data);\n\n        event.waitUntil(\n            (async () => {\n                const clients = await sw.clients.matchAll({\n                    type: \"window\",\n                    includeUncontrolled: true,\n                });\n                for (const client of clients) {\n                    if (client.url.includes(target)) {\n                        return client.focus();\n                    }\n                }\n                return sw.clients.openWindow(target);\n            })(),\n        );\n    });\n}\n\n/**\n * Install a `message` listener that activates a waiting worker when the host\n * app sends `{ type: \"SKIP_WAITING\" }`.\n */\nexport function installSkipWaitingListener(): void {\n    const sw = getSwScope() as SwGlobal & {\n        addEventListener(\n            type: \"message\",\n            listener: (event: { data?: { type?: string } }) => void,\n        ): void;\n    };\n    sw.addEventListener(\"message\", (event) => {\n        if (event.data?.type === \"SKIP_WAITING\") {\n            void sw.skipWaiting();\n        }\n    });\n}\n"],"mappings":"AA6CA,SAAS,GAAuB,CAC5B,OAAO,UACX,CAgCA,SAAgB,EAAmB,EAAqC,CAAC,EAAS,CAC9E,IAAM,EAAK,EAAW,EAChB,CAAE,eAAe,cAAe,cAAa,eAAc,aAAc,EAE/E,EAAG,iBAAiB,OAAS,GAAU,CACnC,GAAI,CAAC,EAAM,KAAM,OAEjB,IAAI,EACJ,GAAI,CACA,EAAM,EAAM,KAAK,KAAK,CAC1B,MAAQ,CACJ,EAAM,CAAE,MAAO,EAAc,KAAM,EAAM,KAAK,KAAK,CAAE,CACzD,CAEA,IAAM,EAAU,EAAY,EAAU,CAAG,EAAI,EAC7C,GAAI,CAAC,EAAS,OAEd,IAAM,EAAQ,EAAQ,OAAS,EACzB,EAAyD,CAC3D,KAAM,EAAQ,KACd,KAAM,EAAQ,MAAQ,EACtB,MAAO,EAAQ,OAAS,EACxB,MAAO,EAAQ,MACf,IAAK,EAAQ,IACb,KAAM,CAAE,IAAK,EAAQ,KAAO,IAAK,GAAI,EAAQ,MAAQ,CAAC,CAAG,CAC7D,EAEA,EAAM,UAAU,EAAG,aAAa,iBAAiB,EAAO,CAAY,CAAC,CACzE,CAAC,CACL,CAWA,SAAgB,EACZ,EAAkD,CAAC,EAC/C,CACJ,IAAM,EAAK,EAAW,EAChB,EACF,EAAQ,aACN,GAAkB,CAChB,GAAI,OAAO,GAAS,SAAU,OAAO,EACrC,GAAI,GAAQ,OAAO,GAAS,UAAY,QAAS,EAAM,CACnD,IAAM,EAAO,EAAiC,IAC9C,OAAO,OAAO,GAAQ,SAAW,EAAM,GAC3C,CACA,MAAO,GACX,GAEJ,EAAG,iBAAiB,oBAAsB,GAAU,CAChD,EAAM,aAAa,MAAM,EACzB,IAAM,EAAS,EAAW,EAAM,aAAa,IAAI,EAEjD,EAAM,WACD,SAAY,CACT,IAAM,EAAU,MAAM,EAAG,QAAQ,SAAS,CACtC,KAAM,SACN,oBAAqB,EACzB,CAAC,EACD,IAAK,IAAM,KAAU,EACjB,GAAI,EAAO,IAAI,SAAS,CAAM,EAC1B,OAAO,EAAO,MAAM,EAG5B,OAAO,EAAG,QAAQ,WAAW,CAAM,CACvC,EAAA,CAAG,CACP,CACJ,CAAC,CACL,CAMA,SAAgB,GAAmC,CAC/C,IAAM,EAAK,EAAW,EAMtB,EAAG,iBAAiB,UAAY,GAAU,CAClC,EAAM,MAAM,OAAS,gBACrB,EAAQ,YAAY,CAE5B,CAAC,CACL"}