46 lines
2.0 KiB
JavaScript
46 lines
2.0 KiB
JavaScript
|
|
// Web Push (background / closed-tab / mobile notifications). Fully optional:
|
||
|
|
// - if the `web-push` package isn't installed, or VAPID env keys aren't set,
|
||
|
|
// isEnabled() is false and every call is a silent no-op (the app is unaffected).
|
||
|
|
// Configure in production by setting:
|
||
|
|
// VAPID_PUBLIC_KEY, VAPID_PRIVATE_KEY, VAPID_SUBJECT (e.g. mailto:admin@bizgaze.com)
|
||
|
|
// Generate a key pair once with: npx web-push generate-vapid-keys
|
||
|
|
const R = require('./repos');
|
||
|
|
|
||
|
|
let webpush = null;
|
||
|
|
try { webpush = require('web-push'); } catch (_) { /* package not installed -> push disabled */ }
|
||
|
|
|
||
|
|
const PUBLIC = process.env.VAPID_PUBLIC_KEY || '';
|
||
|
|
const PRIVATE = process.env.VAPID_PRIVATE_KEY || '';
|
||
|
|
const SUBJECT = process.env.VAPID_SUBJECT || 'mailto:support@bizgaze.com';
|
||
|
|
|
||
|
|
let ready = false;
|
||
|
|
if (webpush && PUBLIC && PRIVATE) {
|
||
|
|
try { webpush.setVapidDetails(SUBJECT, PUBLIC, PRIVATE); ready = true; }
|
||
|
|
catch (e) { console.warn('[push] invalid VAPID config:', e.message); }
|
||
|
|
}
|
||
|
|
if (!ready) console.log('[push] Web Push disabled (set web-push + VAPID_PUBLIC_KEY/VAPID_PRIVATE_KEY to enable).');
|
||
|
|
|
||
|
|
function isEnabled() { return ready; }
|
||
|
|
function publicKey() { return ready ? PUBLIC : ''; }
|
||
|
|
|
||
|
|
// Fire-and-forget push to every device the user has subscribed. Dead subscriptions
|
||
|
|
// (410 Gone / 404) are pruned. Never throws.
|
||
|
|
async function sendToUser(userId, payload) {
|
||
|
|
if (!ready) return;
|
||
|
|
let subs = [];
|
||
|
|
try { subs = R.pushSubs.byUser(userId); } catch (_) { return; }
|
||
|
|
const data = JSON.stringify(payload || {});
|
||
|
|
for (const s of subs) {
|
||
|
|
const sub = { endpoint: s.endpoint, keys: { p256dh: s.p256dh, auth: s.auth } };
|
||
|
|
try {
|
||
|
|
await webpush.sendNotification(sub, data, { TTL: 600 });
|
||
|
|
} catch (err) {
|
||
|
|
const code = err && err.statusCode;
|
||
|
|
if (code === 404 || code === 410) { try { R.pushSubs.removeByEndpoint(s.endpoint); } catch (_) {} }
|
||
|
|
// other errors (network, 4xx) are ignored — push is best-effort
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
module.exports = { isEnabled, publicKey, sendToUser };
|