pushkit
Version:
Everything you need to enable Web Push Notification in your Node.JS web application. Uses the browser's delivery channel to send push notification(Free of cost), which means no extra third-party service (except for the browser's own delivery channel). Wor
111 lines (110 loc) • 3.49 kB
JavaScript
/// <reference types="./index" />
const _log = (msg) => console.log(msg);
function toUint8Array(base64String) {
const padding = '='.repeat((4 - base64String.length % 4) % 4);
const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/');
const rawData = window.atob(base64);
const outputArray = new Uint8Array(rawData.length);
for (let i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i);
}
return outputArray;
}
function getSubStatus(reg){
return new Promise((resolve,reject)=>{
try{
reg.pushManager.getSubscription()
.then(sub=>{
if(sub === null) return reject(null);
else return resolve(sub);
})
.catch(reject);
}
catch(e){
reject(null);
}
})
}
function requestPushSubscription(reg,key){
return new Promise((resolve,reject)=>{
let applicationServerKey = toUint8Array(key);
try{
reg.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey
}).then(resolve).catch(reject);
}
catch(e){
reject(e);
}
})
}
/**
* @type {import('./index')}
*/
function PushKit(publicKey, verbose = false){
if(!publicKey || typeof publicKey !== "string") throw new Error("Public key must be a valid VAPT key");
this.supported = true;
this.subscribed = false;
this.key = publicKey;
this.reg = null;
this.sub = null;
this.granted = false;
if(window.Notification && "permission" in window.Notification) this.granted = (window.Notification.permission === "granted");
if (!('serviceWorker' in navigator) || !('PushManager' in window)) this.supported = false;
this._initRegistrationInternal = (swRegistration) =>{
if(!swRegistration) throw new Error("Service worker registration object required as argument");
return new Promise(resolve=>{
if(this.supported === false) return resolve(null);
this.reg = swRegistration;
getSubStatus(this.reg).then(sub=>{
this.sub = sub;
this.subscribed = true;
this.granted = true;
if(verbose) _log("Already Push Subscribed");
return resolve(this.sub);
}).catch(e=>{
if(verbose) _log(e);
requestPushSubscription(this.reg,this.key).then(sub=>{
this.sub = sub;
this.subscribed = true;
this.granted = true;
if(verbose) _log("Freshly Push Subscribed");
return resolve(this.sub);
}).catch(e=>{
if(verbose) _log(e);
return resolve(null);
})
})
})
}
this.handleRegistration = (swRegistration, verbose = false)=>{
return new Promise(resolve=>{
if(window.Notification && "requestPermission" in window.Notification){
verbose && console.info("Using window.Notification API");
if(window.Notification.permission === "granted") return this._initRegistrationInternal(swRegistration, verbose).then(resolve);
const _handle = permission => {
if(permission === "granted") return this._initRegistrationInternal(swRegistration, verbose).then(resolve);
else{
verbose && console.error("Notification permission denied");
resolve(null);
}
}
const _catch = err => {
verbose && console.error("Failed to request notification permission", err);
return reject(null);
}
try{
window.Notification.requestPermission().then(_handle).catch(_catch);
}
catch(e){
return window.Notification.requestPermission(_handle);
}
}
else{
return this._initRegistrationInternal(swRegistration, verbose).then(resolve);
}
});
}
}
export {PushKit}