import jwt from "jsonwebtoken"; interface APNsUrl { fullUrl: string; path: string; host: string; } class AppleNotificationSender { private apnsToken: string | undefined = undefined; private _lastRefreshedTimeMs: number | undefined = undefined; private lastReloadedTimeForAPNsIsTooRecent() { const thirtyMinutesMs = 1800000; return this._lastRefreshedTimeMs && Date.now() - this._lastRefreshedTimeMs < thirtyMinutesMs; } private reloadAPNsTokenIfTimePassed() { if (this.lastReloadedTimeForAPNsIsTooRecent()) { return; } const keyId = process.env.APNS_KEY_ID; const teamId = process.env.APNS_TEAM_ID; const privateKeyBase64 = process.env.APNS_PRIVATE_KEY; if (!privateKeyBase64) return; const privateKey = Buffer.from(privateKeyBase64, 'base64').toString('utf-8'); const tokenHeader = { alg: "ES256", "kid": keyId, }; const nowMs = Date.now(); const claimsPayload = { "iss": teamId, "iat": Math.ceil(nowMs / 1000), // APNs requires number of seconds since Epoch }; this.apnsToken = jwt.sign(claimsPayload, privateKey, { algorithm: "ES256", header: tokenHeader }); this._lastRefreshedTimeMs = nowMs; } public sendNotificationImmediately(notification: any) { // TODO Send the notification } public static getAPNsFullUrlToUse(deviceId: string): APNsUrl { // Construct the fetch request const devBaseUrl = "https://api.development.push.apple.com" const prodBaseUrl = "https://api.push.apple.com" let hostToUse = devBaseUrl; if (process.env.APNS_IS_PRODUCTION === "1") { hostToUse = prodBaseUrl; } const path = "/3/device/" + deviceId; const fullUrl = hostToUse + path; const constructedObject = { fullUrl, host: hostToUse, path, } return constructedObject; } }