@pushforge/builder
Version:
A robust, cross-platform Web Push notification library that handles VAPID authentication and payload encryption following the Web Push Protocol standard. Works in Node.js 16+, Browsers, Deno, Bun and Cloudflare Workers.
75 lines (74 loc) • 3.04 kB
JavaScript
import { base64UrlDecodeString, base64UrlEncode } from './base64.js';
/**
* Converts an ArrayBuffer or Uint8Array to a string.
*
* @param {ArrayBuffer | Uint8Array} s - The input array to convert.
* @returns {string} The resulting string representation of the input.
*/
export const stringFromArrayBuffer = (s) => {
let result = '';
for (const code of new Uint8Array(s))
result += String.fromCharCode(code);
return result;
};
/**
* Cross-platform function to decode a Base64 string into a binary string.
* Works in both browser and Node.js environments.
*
* @param {string} base64String - The Base64 encoded string to decode.
* @returns {string} The decoded binary string.
*/
export const base64Decode = (base64String) => {
// Add padding if needed
const paddedBase64 = base64String.padEnd(base64String.length + ((4 - (base64String.length % 4 || 4)) % 4), '=');
// Node.js environment
if (typeof Buffer !== 'undefined') {
return Buffer.from(paddedBase64, 'base64').toString('binary');
}
// Browser environment
if (typeof atob === 'function') {
return atob(paddedBase64);
}
// Pure JavaScript implementation for environments without atob or Buffer
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
let result = '';
let i = 0;
while (i < paddedBase64.length) {
const enc1 = characters.indexOf(paddedBase64.charAt(i++));
const enc2 = characters.indexOf(paddedBase64.charAt(i++));
const enc3 = characters.indexOf(paddedBase64.charAt(i++));
const enc4 = characters.indexOf(paddedBase64.charAt(i++));
const char1 = (enc1 << 2) | (enc2 >> 4);
const char2 = ((enc2 & 15) << 4) | (enc3 >> 2);
const char3 = ((enc3 & 3) << 6) | enc4;
result += String.fromCharCode(char1);
if (enc3 !== 64)
result += String.fromCharCode(char2);
if (enc4 !== 64)
result += String.fromCharCode(char3);
}
return result;
};
/**
* Extracts the public key from a JSON Web Key (JWK) and encodes it in base64 URL format.
*
* @param {JsonWebKey} jwk - The JSON Web Key from which to extract the public key.
* @returns {string} The base64 URL encoded public key.
*/
export const getPublicKeyFromJwk = (jwk) => base64UrlEncode(`\x04${base64Decode(base64UrlDecodeString(jwk.x))}${base64Decode(base64UrlDecodeString(jwk.y))}`);
/**
* Concatenates multiple Uint8Array instances into a single Uint8Array.
*
* @param {Uint8Array[]} arrays - An array of Uint8Array instances to concatenate.
* @returns {Uint8Array} A new Uint8Array containing all the concatenated data.
*/
export const concatTypedArrays = (arrays) => {
const length = arrays.reduce((accumulator, current) => accumulator + current.byteLength, 0);
let index = 0;
const targetArray = new Uint8Array(length);
for (const array of arrays) {
targetArray.set(array, index);
index += array.byteLength;
}
return targetArray;
};