Files
evse-backend/src/services/push.service.js
2026-01-10 18:39:55 +00:00

57 lines
1.5 KiB
JavaScript
Executable File

// src/services/push.service.js
const webpush = require('web-push');
const config = require('../config');
const pushRepo = require('../repositories/push.repo');
const hasVapid = !!config.vapid.publicKey && !!config.vapid.privateKey;
if (!hasVapid) {
console.warn('[Push] VAPID keys não definidas. Push desativado.');
} else {
webpush.setVapidDetails(config.vapid.subject, config.vapid.publicKey, config.vapid.privateKey);
}
async function sendWithRetry(subscription, message, tries = 2) {
try {
return await webpush.sendNotification(subscription, message);
} catch (err) {
const code = err?.statusCode;
if ((code === 429 || code >= 500) && tries > 1) {
await new Promise((r) => setTimeout(r, 1000));
return sendWithRetry(subscription, message, tries - 1);
}
throw err;
}
}
async function sendPushToUser(userId, payload) {
if (!hasVapid) return;
const subs = await pushRepo.listByUser(userId);
if (!subs.length) return;
const message = JSON.stringify(payload);
await Promise.allSettled(
subs.map(async (s) => {
const subscription = {
endpoint: s.endpoint,
keys: { p256dh: s.p256dh, auth: s.auth },
};
try {
await sendWithRetry(subscription, message);
} catch (err) {
const code = err?.statusCode;
if (code === 404 || code === 410) {
await pushRepo.deleteById(s.id);
} else {
console.error('[Push] erro ao enviar:', err.message);
}
}
})
);
}
module.exports = { sendPushToUser };