feat(webpush): send registration notification

This commit is contained in:
Julien Oculi 2025-05-15 16:05:30 +02:00
parent 385143c859
commit dec614047e
2 changed files with 50 additions and 16 deletions

View file

@ -1,6 +1,6 @@
import { define } from '../../../utils.ts' import { define } from '../../../utils.ts'
import { respondApi } from ':src/utils.ts' import { respondApi } from ':src/utils.ts'
import { subscriptions } from ':src/webpush/mod.ts' import { sendWebPushNotification, subscriptions } from ':src/webpush/mod.ts'
export const handler = define.handlers({ export const handler = define.handlers({
async POST(ctx) { async POST(ctx) {
@ -8,6 +8,14 @@ export const handler = define.handlers({
try { try {
await saveSubscription(subscription) await saveSubscription(subscription)
await sendWebPushNotification(
'Notifications desormais disponible sur votre appareil',
{},
(sub) =>
sub.keys !== undefined && sub.keys.auth === subscription.keys?.auth,
)
return respondApi('success', 'ok') return respondApi('success', 'ok')
} catch (error) { } catch (error) {
console.error('[webpush/subscription]:', error) console.error('[webpush/subscription]:', error)

View file

@ -17,22 +17,48 @@ webpush.setVapidDetails(
vapidKeys.privateKey, vapidKeys.privateKey,
) )
// const itemKey = 'webpush-subscription' export async function sendWebPushNotification(
// setInterval(async () => { title: string,
// const subscriptions = JSON.parse(localStorage.getItem(itemKey) ?? '[]') as PushSubscriptionJSON[] options: Partial<NotificationOptions> = {},
filter: (subscription: PushSubscriptionJSON) => boolean = () => true,
) {
for await (
const { value: subscription, key } of subscriptions.list<
PushSubscriptionJSON
>({ prefix: ['subscription'] })
) {
if (!filter(subscription)) {
continue
}
// for (const subscription of subscriptions) { try {
// try { const payload = { title, options }
// // console.log('PUSH NOTIFICATION', subscription)
// const payload: { title: string, options?: Partial<NotificationOptions> } = { title: `This is a test @ ${new Date().toLocaleTimeString()}` } if (subscription.endpoint === undefined) {
// //@ts-ignore TODO check endpoint is defined throw new TypeError(
// const a = await webpush.sendNotification(subscription, JSON.stringify(payload)) `missing endpoint in subscription : ${JSON.stringify(subscription)}`,
// console.log(a) )
// } catch (error) { }
// console.error(error)
// } const response = await webpush.sendNotification(
// } //@ts-ignore endpoint is defined
// }, 10_000) subscription,
JSON.stringify(payload),
)
// Subscription has expired or is no longer valid
if (response.statusCode === 410 || response.statusCode === 404) {
return subscriptions.delete(key)
}
} catch (error) {
if (error instanceof WebPushError) {
if (error.statusCode === 410 || error.statusCode === 404) return
console.error(error)
}
console.error(error)
}
}
}
function getVapidKeys(): webpush.VapidKeys { function getVapidKeys(): webpush.VapidKeys {
const itemKey = 'webpush-vapid-keys' const itemKey = 'webpush-vapid-keys'