@juspay/shooter 1.24.2 → 1.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/hooks/notifier.cjs +32 -4
- package/build/client/_app/immutable/assets/{4.D4EDSN4H.css → 4.ChO_hlLs.css} +1 -1
- package/build/client/_app/immutable/assets/4.ChO_hlLs.css.br +0 -0
- package/build/client/_app/immutable/assets/4.ChO_hlLs.css.gz +0 -0
- package/build/client/_app/immutable/chunks/{BBuzUXZ9.js → BstJSK2K.js} +1 -1
- package/build/client/_app/immutable/chunks/BstJSK2K.js.br +0 -0
- package/build/client/_app/immutable/chunks/BstJSK2K.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{Dqmsaccg.js → DINqYbXU.js} +1 -1
- package/build/client/_app/immutable/chunks/DINqYbXU.js.br +0 -0
- package/build/client/_app/immutable/chunks/DINqYbXU.js.gz +0 -0
- package/build/client/_app/immutable/chunks/ssAhjWfF.js +3 -0
- package/build/client/_app/immutable/chunks/ssAhjWfF.js.br +0 -0
- package/build/client/_app/immutable/chunks/ssAhjWfF.js.gz +0 -0
- package/build/client/_app/immutable/entry/{app.Bu4nq_bk.js → app.BPK9s2o5.js} +2 -2
- package/build/client/_app/immutable/entry/app.BPK9s2o5.js.br +0 -0
- package/build/client/_app/immutable/entry/app.BPK9s2o5.js.gz +0 -0
- package/build/client/_app/immutable/entry/start.DFPHuGE3.js +1 -0
- package/build/client/_app/immutable/entry/start.DFPHuGE3.js.br +2 -0
- package/build/client/_app/immutable/entry/start.DFPHuGE3.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{0.CnSSjKHX.js → 0.BEbzRcwm.js} +1 -1
- package/build/client/_app/immutable/nodes/0.BEbzRcwm.js.br +0 -0
- package/build/client/_app/immutable/nodes/0.BEbzRcwm.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{1.D_5wZINa.js → 1.C_V0SOr9.js} +1 -1
- package/build/client/_app/immutable/nodes/1.C_V0SOr9.js.br +0 -0
- package/build/client/_app/immutable/nodes/1.C_V0SOr9.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{10.C_B2eMms.js → 10.6V-37_Rl.js} +1 -1
- package/build/client/_app/immutable/nodes/10.6V-37_Rl.js.br +0 -0
- package/build/client/_app/immutable/nodes/10.6V-37_Rl.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{11.DUKnn5ja.js → 11.Lzf-KC6L.js} +1 -1
- package/build/client/_app/immutable/nodes/11.Lzf-KC6L.js.br +0 -0
- package/build/client/_app/immutable/nodes/11.Lzf-KC6L.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{2.C37CZKYv.js → 2.Cl2dMP2L.js} +1 -1
- package/build/client/_app/immutable/nodes/2.Cl2dMP2L.js.br +0 -0
- package/build/client/_app/immutable/nodes/2.Cl2dMP2L.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{3.C48G514u.js → 3.CuX2eSna.js} +1 -1
- package/build/client/_app/immutable/nodes/3.CuX2eSna.js.br +0 -0
- package/build/client/_app/immutable/nodes/3.CuX2eSna.js.gz +0 -0
- package/build/client/_app/immutable/nodes/4.2DvqoOaB.js +17 -0
- package/build/client/_app/immutable/nodes/4.2DvqoOaB.js.br +0 -0
- package/build/client/_app/immutable/nodes/4.2DvqoOaB.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{6.DGlutNk6.js → 6.C7e6zQyP.js} +1 -1
- package/build/client/_app/immutable/nodes/6.C7e6zQyP.js.br +0 -0
- package/build/client/_app/immutable/nodes/6.C7e6zQyP.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{7.BXAYsEHF.js → 7.1ygvNTnO.js} +1 -1
- package/build/client/_app/immutable/nodes/7.1ygvNTnO.js.br +0 -0
- package/build/client/_app/immutable/nodes/7.1ygvNTnO.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{8.D-SxCq24.js → 8.CBVmgOk0.js} +1 -1
- package/build/client/_app/immutable/nodes/8.CBVmgOk0.js.br +0 -0
- package/build/client/_app/immutable/nodes/8.CBVmgOk0.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{9.Bek2YR4U.js → 9.B-_ZFZhj.js} +1 -1
- package/build/client/_app/immutable/nodes/9.B-_ZFZhj.js.br +0 -0
- package/build/client/_app/immutable/nodes/9.B-_ZFZhj.js.gz +0 -0
- package/build/client/_app/version.json +1 -1
- package/build/client/_app/version.json.br +0 -0
- package/build/client/_app/version.json.gz +0 -0
- package/build/server/chunks/{0-ByOnI9Md.js → 0-BHU07xt9.js} +2 -2
- package/build/server/chunks/{0-ByOnI9Md.js.map → 0-BHU07xt9.js.map} +1 -1
- package/build/server/chunks/{1-DcJwehLu.js → 1-OVOd8GUH.js} +2 -2
- package/build/server/chunks/{1-DcJwehLu.js.map → 1-OVOd8GUH.js.map} +1 -1
- package/build/server/chunks/{10-B5bdfDfK.js → 10-CRHtvb_u.js} +2 -2
- package/build/server/chunks/{10-B5bdfDfK.js.map → 10-CRHtvb_u.js.map} +1 -1
- package/build/server/chunks/{11-DOJ9j7KC.js → 11-CdSex9j1.js} +2 -2
- package/build/server/chunks/{11-DOJ9j7KC.js.map → 11-CdSex9j1.js.map} +1 -1
- package/build/server/chunks/{2-BY0LGSMl.js → 2-bb78aIZ6.js} +2 -2
- package/build/server/chunks/{2-BY0LGSMl.js.map → 2-bb78aIZ6.js.map} +1 -1
- package/build/server/chunks/{3-DEa6RtDT.js → 3-CsTC6Lrn.js} +2 -2
- package/build/server/chunks/{3-DEa6RtDT.js.map → 3-CsTC6Lrn.js.map} +1 -1
- package/build/server/chunks/{4-w2W_T8ax.js → 4-DTTu8_Gr.js} +4 -4
- package/build/server/chunks/{4-w2W_T8ax.js.map → 4-DTTu8_Gr.js.map} +1 -1
- package/build/server/chunks/{6-DoTu6ygH.js → 6-BUgQGB_4.js} +2 -2
- package/build/server/chunks/{6-DoTu6ygH.js.map → 6-BUgQGB_4.js.map} +1 -1
- package/build/server/chunks/{7-CYQ9V6d4.js → 7-CsQZnkcG.js} +2 -2
- package/build/server/chunks/{7-CYQ9V6d4.js.map → 7-CsQZnkcG.js.map} +1 -1
- package/build/server/chunks/{8-DMwmCD5X.js → 8-DcIuPdyW.js} +2 -2
- package/build/server/chunks/{8-DMwmCD5X.js.map → 8-DcIuPdyW.js.map} +1 -1
- package/build/server/chunks/{9-CNmPa2Jo.js → 9-D8bkM1uj.js} +2 -2
- package/build/server/chunks/{9-CNmPa2Jo.js.map → 9-D8bkM1uj.js.map} +1 -1
- package/build/server/chunks/{_page.svelte-DDE2nChH.js → _page.svelte-BBbaKwNz.js} +101 -27
- package/build/server/chunks/_page.svelte-BBbaKwNz.js.map +1 -0
- package/build/server/chunks/{_server.ts-DfscXcFe.js → _server.ts-B7BLxK5u.js} +233 -186
- package/build/server/chunks/_server.ts-B7BLxK5u.js.map +1 -0
- package/build/server/chunks/{_server.ts-EJVmhLtg.js → _server.ts-BSS8cO80.js} +15 -3
- package/build/server/chunks/_server.ts-BSS8cO80.js.map +1 -0
- package/build/server/chunks/_server.ts-DNTxPoxO.js +115 -0
- package/build/server/chunks/_server.ts-DNTxPoxO.js.map +1 -0
- package/build/server/chunks/{_server.ts-D9_hkPQ6.js → _server.ts-DUb7fbuW.js} +17 -3
- package/build/server/chunks/_server.ts-DUb7fbuW.js.map +1 -0
- package/build/server/chunks/{_server.ts-v7TaT83B.js → _server.ts-FdKi8RwL.js} +7 -3
- package/build/server/chunks/_server.ts-FdKi8RwL.js.map +1 -0
- package/build/server/chunks/device-format-DTgEz4Yr.js +29 -0
- package/build/server/chunks/device-format-DTgEz4Yr.js.map +1 -0
- package/build/server/chunks/device-token-store-Ct7aTeR8.js +259 -0
- package/build/server/chunks/device-token-store-Ct7aTeR8.js.map +1 -0
- package/build/server/chunks/{library-apns-D8RPINlv.js → library-apns-DMlL1BAg.js} +158 -26
- package/build/server/chunks/library-apns-DMlL1BAg.js.map +1 -0
- package/build/server/index.js +1 -1
- package/build/server/index.js.map +1 -1
- package/build/server/manifest.js +17 -17
- package/build/server/manifest.js.map +1 -1
- package/package.json +2 -2
- package/server.ts +15 -1
- package/src/app.d.ts +4 -0
- package/src/lib/modules/server/apn/apns-classify.ts +103 -0
- package/src/lib/modules/server/apn/library-apns.ts +151 -35
- package/src/lib/modules/server/apn/notify-fanout.ts +40 -0
- package/src/lib/modules/server/fcm/fcm-classify.ts +61 -0
- package/src/lib/modules/server/fcm/fcm-service.ts +128 -29
- package/src/lib/modules/server/push/device-format.ts +42 -0
- package/src/lib/modules/server/push/device-token-store.ts +354 -0
- package/src/lib/types/apn.ts +4 -0
- package/src/lib/types/device.ts +156 -0
- package/src/lib/types/index.ts +1 -0
- package/src/routes/api/debug/+server.ts +13 -1
- package/src/routes/api/device-token/+server.ts +122 -37
- package/src/routes/api/health/+server.ts +16 -2
- package/src/routes/api/notify/+server.ts +175 -168
- package/src/routes/api/qr-config/+server.ts +9 -2
- package/src/routes/config/+page.svelte +182 -44
- package/build/client/_app/immutable/assets/4.D4EDSN4H.css.br +0 -0
- package/build/client/_app/immutable/assets/4.D4EDSN4H.css.gz +0 -0
- package/build/client/_app/immutable/chunks/BBuzUXZ9.js.br +0 -0
- package/build/client/_app/immutable/chunks/BBuzUXZ9.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BPIV28L3.js +0 -3
- package/build/client/_app/immutable/chunks/BPIV28L3.js.br +0 -0
- package/build/client/_app/immutable/chunks/BPIV28L3.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Dqmsaccg.js.br +0 -0
- package/build/client/_app/immutable/chunks/Dqmsaccg.js.gz +0 -0
- package/build/client/_app/immutable/entry/app.Bu4nq_bk.js.br +0 -0
- package/build/client/_app/immutable/entry/app.Bu4nq_bk.js.gz +0 -0
- package/build/client/_app/immutable/entry/start.CbpzR6Gp.js +0 -1
- package/build/client/_app/immutable/entry/start.CbpzR6Gp.js.br +0 -2
- package/build/client/_app/immutable/entry/start.CbpzR6Gp.js.gz +0 -0
- package/build/client/_app/immutable/nodes/0.CnSSjKHX.js.br +0 -0
- package/build/client/_app/immutable/nodes/0.CnSSjKHX.js.gz +0 -0
- package/build/client/_app/immutable/nodes/1.D_5wZINa.js.br +0 -0
- package/build/client/_app/immutable/nodes/1.D_5wZINa.js.gz +0 -0
- package/build/client/_app/immutable/nodes/10.C_B2eMms.js.br +0 -0
- package/build/client/_app/immutable/nodes/10.C_B2eMms.js.gz +0 -0
- package/build/client/_app/immutable/nodes/11.DUKnn5ja.js.br +0 -0
- package/build/client/_app/immutable/nodes/11.DUKnn5ja.js.gz +0 -0
- package/build/client/_app/immutable/nodes/2.C37CZKYv.js.br +0 -0
- package/build/client/_app/immutable/nodes/2.C37CZKYv.js.gz +0 -0
- package/build/client/_app/immutable/nodes/3.C48G514u.js.br +0 -0
- package/build/client/_app/immutable/nodes/3.C48G514u.js.gz +0 -0
- package/build/client/_app/immutable/nodes/4.C9fv_m2R.js +0 -16
- package/build/client/_app/immutable/nodes/4.C9fv_m2R.js.br +0 -0
- package/build/client/_app/immutable/nodes/4.C9fv_m2R.js.gz +0 -0
- package/build/client/_app/immutable/nodes/6.DGlutNk6.js.br +0 -0
- package/build/client/_app/immutable/nodes/6.DGlutNk6.js.gz +0 -0
- package/build/client/_app/immutable/nodes/7.BXAYsEHF.js.br +0 -0
- package/build/client/_app/immutable/nodes/7.BXAYsEHF.js.gz +0 -0
- package/build/client/_app/immutable/nodes/8.D-SxCq24.js.br +0 -0
- package/build/client/_app/immutable/nodes/8.D-SxCq24.js.gz +0 -0
- package/build/client/_app/immutable/nodes/9.Bek2YR4U.js.br +0 -0
- package/build/client/_app/immutable/nodes/9.Bek2YR4U.js.gz +0 -0
- package/build/server/chunks/_page.svelte-DDE2nChH.js.map +0 -1
- package/build/server/chunks/_server.ts-D2RS8TFd.js +0 -72
- package/build/server/chunks/_server.ts-D2RS8TFd.js.map +0 -1
- package/build/server/chunks/_server.ts-D9_hkPQ6.js.map +0 -1
- package/build/server/chunks/_server.ts-DfscXcFe.js.map +0 -1
- package/build/server/chunks/_server.ts-EJVmhLtg.js.map +0 -1
- package/build/server/chunks/_server.ts-v7TaT83B.js.map +0 -1
- package/build/server/chunks/library-apns-D8RPINlv.js.map +0 -1
|
@@ -4,6 +4,60 @@ import jwt from 'jsonwebtoken';
|
|
|
4
4
|
import { promisify } from 'util';
|
|
5
5
|
import { t as toErrorMessage } from './error-DDXB3duW.js';
|
|
6
6
|
|
|
7
|
+
const UNCONDITIONAL_STALE_REASONS = /* @__PURE__ */ new Set([
|
|
8
|
+
"DeviceTokenNotForTopic",
|
|
9
|
+
// token belongs to a different bundle id
|
|
10
|
+
"Unregistered"
|
|
11
|
+
// 410 — guarded by the re-registration timestamp check below
|
|
12
|
+
]);
|
|
13
|
+
function classifyApnsReason(httpStatus, reason, storedAppEnv, serverAppEnv) {
|
|
14
|
+
if (httpStatus === 200) {
|
|
15
|
+
return "sent";
|
|
16
|
+
}
|
|
17
|
+
if (reason === "TopicDisallowed") {
|
|
18
|
+
return "transient_error";
|
|
19
|
+
}
|
|
20
|
+
if (reason === "BadDeviceToken") {
|
|
21
|
+
return storedAppEnv === serverAppEnv ? "stale_token" : "transient_error";
|
|
22
|
+
}
|
|
23
|
+
if (reason && UNCONDITIONAL_STALE_REASONS.has(reason)) {
|
|
24
|
+
return "stale_token";
|
|
25
|
+
}
|
|
26
|
+
return "transient_error";
|
|
27
|
+
}
|
|
28
|
+
function summarizeApnsFanOut(outcomes, serverAppEnv) {
|
|
29
|
+
const results = [];
|
|
30
|
+
const staleTokens = [];
|
|
31
|
+
let totalSent = 0;
|
|
32
|
+
let totalFailed = 0;
|
|
33
|
+
for (const o of outcomes) {
|
|
34
|
+
let disposition = classifyApnsReason(o.httpStatus, o.reason, o.appEnv, serverAppEnv);
|
|
35
|
+
if (disposition === "stale_token" && o.reason === "Unregistered" && o.timestampMs > 0) {
|
|
36
|
+
const registeredMs = Date.parse(o.registeredAt);
|
|
37
|
+
if (!Number.isNaN(registeredMs) && registeredMs > o.timestampMs) {
|
|
38
|
+
disposition = "transient_error";
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const success = o.httpStatus === 200;
|
|
42
|
+
if (success) {
|
|
43
|
+
totalSent += 1;
|
|
44
|
+
} else {
|
|
45
|
+
totalFailed += 1;
|
|
46
|
+
}
|
|
47
|
+
if (disposition === "stale_token") {
|
|
48
|
+
staleTokens.push(o.token);
|
|
49
|
+
}
|
|
50
|
+
results.push({
|
|
51
|
+
disposition,
|
|
52
|
+
httpStatus: o.httpStatus,
|
|
53
|
+
reason: o.reason,
|
|
54
|
+
success,
|
|
55
|
+
timestampMs: o.timestampMs,
|
|
56
|
+
token: o.token
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
return { results, staleTokens, totalFailed, totalSent };
|
|
60
|
+
}
|
|
7
61
|
const APNS_MAX_BYTES = 3900;
|
|
8
62
|
const ELLIPSIS = "…";
|
|
9
63
|
function fitApnsPayload(body, maxBytes = APNS_MAX_BYTES) {
|
|
@@ -40,6 +94,7 @@ const APNS_HOST_PROD = "api.push.apple.com";
|
|
|
40
94
|
const APNS_HOST_SANDBOX = "api.sandbox.push.apple.com";
|
|
41
95
|
const JWT_REFRESH_INTERVAL_MS = 30 * 60 * 1e3;
|
|
42
96
|
const REQUEST_TIMEOUT_SECONDS = 15;
|
|
97
|
+
const MAX_APNS_CONCURRENCY = 20;
|
|
43
98
|
class LibraryAPNsService {
|
|
44
99
|
bundleId;
|
|
45
100
|
cachedJwt = null;
|
|
@@ -94,24 +149,7 @@ class LibraryAPNsService {
|
|
|
94
149
|
if (!deviceToken || !payload) {
|
|
95
150
|
throw new Error("Device token and payload are required");
|
|
96
151
|
}
|
|
97
|
-
|
|
98
|
-
alert: {
|
|
99
|
-
body: payload.body ?? payload.message ?? "",
|
|
100
|
-
title: payload.title,
|
|
101
|
-
...payload.subtitle ? { subtitle: payload.subtitle } : {}
|
|
102
|
-
},
|
|
103
|
-
badge: payload.badge ?? 1,
|
|
104
|
-
sound: payload.sound ?? "default"
|
|
105
|
-
};
|
|
106
|
-
if (payload.category) {
|
|
107
|
-
aps.category = payload.category;
|
|
108
|
-
}
|
|
109
|
-
const body = { aps };
|
|
110
|
-
if (payload.data) {
|
|
111
|
-
const { aps: _ignoredAps, ...customData } = payload.data;
|
|
112
|
-
Object.assign(body, customData);
|
|
113
|
-
}
|
|
114
|
-
return this.deliver(deviceToken, body, "alert", "10");
|
|
152
|
+
return this.deliver(deviceToken, this.buildAlertBody(payload), "alert", "10");
|
|
115
153
|
}
|
|
116
154
|
/**
|
|
117
155
|
* Send a SILENT (content-available) background push to wake a backgrounded app without
|
|
@@ -133,13 +171,85 @@ class LibraryAPNsService {
|
|
|
133
171
|
}
|
|
134
172
|
return this.deliver(deviceToken, body, "background", "5");
|
|
135
173
|
}
|
|
174
|
+
/**
|
|
175
|
+
* Fan out one alert push to many devices concurrently. Fits + serializes the
|
|
176
|
+
* payload once and captures the JWT once (so no call uses a mid-fan-out
|
|
177
|
+
* expired token), then classifies/aggregates results and returns the set of
|
|
178
|
+
* stale tokens for the caller to prune.
|
|
179
|
+
*/
|
|
180
|
+
async sendToMany(devices, payload, collapseId) {
|
|
181
|
+
if (!this.configured) {
|
|
182
|
+
throw new Error("APNs service not configured properly");
|
|
183
|
+
}
|
|
184
|
+
if (devices.length === 0) {
|
|
185
|
+
return { results: [], staleTokens: [], totalFailed: 0, totalSent: 0 };
|
|
186
|
+
}
|
|
187
|
+
const serverAppEnv = this.host === APNS_HOST_PROD ? "production" : "sandbox";
|
|
188
|
+
const bodyJson = JSON.stringify(fitApnsPayload(this.buildAlertBody(payload)));
|
|
189
|
+
const jwtToken = this.getJwt();
|
|
190
|
+
const outcomes = await mapLimit(
|
|
191
|
+
devices,
|
|
192
|
+
MAX_APNS_CONCURRENCY,
|
|
193
|
+
async (device) => {
|
|
194
|
+
const res = await this.deliverPreSerialized(
|
|
195
|
+
device.token,
|
|
196
|
+
bodyJson,
|
|
197
|
+
"alert",
|
|
198
|
+
"10",
|
|
199
|
+
jwtToken,
|
|
200
|
+
collapseId
|
|
201
|
+
);
|
|
202
|
+
return {
|
|
203
|
+
appEnv: device.appEnv,
|
|
204
|
+
httpStatus: res.httpStatus ?? 0,
|
|
205
|
+
reason: res.error ?? null,
|
|
206
|
+
registeredAt: device.registeredAt,
|
|
207
|
+
timestampMs: res.timestampMs ?? 0,
|
|
208
|
+
token: device.token
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
);
|
|
212
|
+
return summarizeApnsFanOut(outcomes, serverAppEnv);
|
|
213
|
+
}
|
|
136
214
|
shutdown() {
|
|
137
215
|
}
|
|
138
|
-
/**
|
|
216
|
+
/** Build the APNs `{ aps, ...customData }` body for an alert push. */
|
|
217
|
+
buildAlertBody(payload) {
|
|
218
|
+
const aps = {
|
|
219
|
+
alert: {
|
|
220
|
+
body: payload.body ?? payload.message ?? "",
|
|
221
|
+
title: payload.title,
|
|
222
|
+
...payload.subtitle ? { subtitle: payload.subtitle } : {}
|
|
223
|
+
},
|
|
224
|
+
badge: payload.badge ?? 1,
|
|
225
|
+
sound: payload.sound ?? "default"
|
|
226
|
+
};
|
|
227
|
+
if (payload.category) {
|
|
228
|
+
aps.category = payload.category;
|
|
229
|
+
}
|
|
230
|
+
const body = { aps };
|
|
231
|
+
if (payload.data) {
|
|
232
|
+
const { aps: _ignoredAps, ...customData } = payload.data;
|
|
233
|
+
Object.assign(body, customData);
|
|
234
|
+
}
|
|
235
|
+
return body;
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Shared curl/HTTP-2 delivery. Fits + serializes the body and signs a JWT,
|
|
239
|
+
* then delegates to deliverPreSerialized. `pushType` is 'alert' | 'background'.
|
|
240
|
+
*/
|
|
139
241
|
async deliver(deviceToken, body, pushType, priority) {
|
|
140
242
|
const bodyJson = JSON.stringify(fitApnsPayload(body));
|
|
141
|
-
|
|
243
|
+
return this.deliverPreSerialized(deviceToken, bodyJson, pushType, priority, this.getJwt());
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Curl/HTTP-2 delivery from a pre-serialized body + pre-captured JWT — the hot
|
|
247
|
+
* path for sendToMany (no per-token fit or JWT sign). Returns httpStatus and,
|
|
248
|
+
* on a 410, the parsed Unregistered timestamp (ms) for the prune guard.
|
|
249
|
+
*/
|
|
250
|
+
async deliverPreSerialized(deviceToken, bodyJson, pushType, priority, jwtToken, collapseId) {
|
|
142
251
|
const url = `https://${this.host}/3/device/${deviceToken}`;
|
|
252
|
+
const safeCollapseId = collapseId ? collapseId.replace(/[^\x20-\x7E]/g, "").slice(0, 64) || void 0 : void 0;
|
|
143
253
|
const args = [
|
|
144
254
|
"-sS",
|
|
145
255
|
"--http2",
|
|
@@ -157,6 +267,7 @@ class LibraryAPNsService {
|
|
|
157
267
|
`apns-push-type: ${pushType}`,
|
|
158
268
|
"-H",
|
|
159
269
|
`apns-priority: ${priority}`,
|
|
270
|
+
...safeCollapseId ? ["-H", `apns-collapse-id: ${safeCollapseId}`] : [],
|
|
160
271
|
"-d",
|
|
161
272
|
bodyJson,
|
|
162
273
|
"-w",
|
|
@@ -172,22 +283,29 @@ class LibraryAPNsService {
|
|
|
172
283
|
const status = statusMatch ? parseInt(statusMatch[1], 10) : 0;
|
|
173
284
|
const bodyText = stdout.replace(/\n?__SHOOTER_HTTP_STATUS__:\d+\n?$/, "").trim();
|
|
174
285
|
if (status === 200) {
|
|
175
|
-
return { failed: 0, sent: 1, success: true };
|
|
286
|
+
return { failed: 0, httpStatus: 200, sent: 1, success: true };
|
|
176
287
|
}
|
|
177
288
|
let reason = bodyText;
|
|
289
|
+
let timestampMs;
|
|
178
290
|
try {
|
|
179
291
|
const parsed = JSON.parse(bodyText);
|
|
180
|
-
if (parsed && typeof parsed === "object"
|
|
181
|
-
|
|
292
|
+
if (parsed && typeof parsed === "object") {
|
|
293
|
+
const obj = parsed;
|
|
294
|
+
if (typeof obj.reason === "string") {
|
|
295
|
+
reason = obj.reason;
|
|
296
|
+
}
|
|
297
|
+
if (typeof obj.timestamp === "number") {
|
|
298
|
+
timestampMs = obj.timestamp < 1e12 ? obj.timestamp * 1e3 : obj.timestamp;
|
|
299
|
+
}
|
|
182
300
|
}
|
|
183
301
|
} catch {
|
|
184
302
|
}
|
|
185
303
|
console.error(`[apns] Delivery failed (status=${status}): ${reason}`);
|
|
186
|
-
return { error: reason, failed: 1, sent: 0, success: false };
|
|
304
|
+
return { error: reason, failed: 1, httpStatus: status, sent: 0, success: false, timestampMs };
|
|
187
305
|
} catch (err) {
|
|
188
306
|
const msg = toErrorMessage(err).replace(/bearer\s+[A-Za-z0-9._-]+/gi, "bearer [REDACTED]").replace(/device\/[A-Fa-f0-9]+/g, "device/[REDACTED]");
|
|
189
307
|
console.error(`[apns] curl transport error: ${msg}`);
|
|
190
|
-
return { error: msg, failed: 1, sent: 0, success: false };
|
|
308
|
+
return { error: msg, failed: 1, httpStatus: 0, sent: 0, success: false };
|
|
191
309
|
}
|
|
192
310
|
}
|
|
193
311
|
getJwt() {
|
|
@@ -207,6 +325,20 @@ class LibraryAPNsService {
|
|
|
207
325
|
return token;
|
|
208
326
|
}
|
|
209
327
|
}
|
|
328
|
+
async function mapLimit(items, limit, fn) {
|
|
329
|
+
const results = new Array(items.length);
|
|
330
|
+
let next = 0;
|
|
331
|
+
const worker = async () => {
|
|
332
|
+
while (next < items.length) {
|
|
333
|
+
const idx = next;
|
|
334
|
+
next += 1;
|
|
335
|
+
results[idx] = await fn(items[idx]);
|
|
336
|
+
}
|
|
337
|
+
};
|
|
338
|
+
const workerCount = Math.min(limit, items.length);
|
|
339
|
+
await Promise.all(Array.from({ length: workerCount }, () => worker()));
|
|
340
|
+
return results;
|
|
341
|
+
}
|
|
210
342
|
|
|
211
343
|
export { LibraryAPNsService as L };
|
|
212
|
-
//# sourceMappingURL=library-apns-
|
|
344
|
+
//# sourceMappingURL=library-apns-DMlL1BAg.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"library-apns-DMlL1BAg.js","sources":["../../../.svelte-kit/adapter-node/chunks/library-apns.js"],"sourcesContent":["import { b as private_env } from \"./shared-server.js\";\nimport { execFile, execFileSync } from \"child_process\";\nimport jwt from \"jsonwebtoken\";\nimport { promisify } from \"util\";\nimport { t as toErrorMessage } from \"./error.js\";\nconst UNCONDITIONAL_STALE_REASONS = /* @__PURE__ */ new Set([\n \"DeviceTokenNotForTopic\",\n // token belongs to a different bundle id\n \"Unregistered\"\n // 410 — guarded by the re-registration timestamp check below\n]);\nfunction classifyApnsReason(httpStatus, reason, storedAppEnv, serverAppEnv) {\n if (httpStatus === 200) {\n return \"sent\";\n }\n if (reason === \"TopicDisallowed\") {\n return \"transient_error\";\n }\n if (reason === \"BadDeviceToken\") {\n return storedAppEnv === serverAppEnv ? \"stale_token\" : \"transient_error\";\n }\n if (reason && UNCONDITIONAL_STALE_REASONS.has(reason)) {\n return \"stale_token\";\n }\n return \"transient_error\";\n}\nfunction summarizeApnsFanOut(outcomes, serverAppEnv) {\n const results = [];\n const staleTokens = [];\n let totalSent = 0;\n let totalFailed = 0;\n for (const o of outcomes) {\n let disposition = classifyApnsReason(o.httpStatus, o.reason, o.appEnv, serverAppEnv);\n if (disposition === \"stale_token\" && o.reason === \"Unregistered\" && o.timestampMs > 0) {\n const registeredMs = Date.parse(o.registeredAt);\n if (!Number.isNaN(registeredMs) && registeredMs > o.timestampMs) {\n disposition = \"transient_error\";\n }\n }\n const success = o.httpStatus === 200;\n if (success) {\n totalSent += 1;\n } else {\n totalFailed += 1;\n }\n if (disposition === \"stale_token\") {\n staleTokens.push(o.token);\n }\n results.push({\n disposition,\n httpStatus: o.httpStatus,\n reason: o.reason,\n success,\n timestampMs: o.timestampMs,\n token: o.token\n });\n }\n return { results, staleTokens, totalFailed, totalSent };\n}\nconst APNS_MAX_BYTES = 3900;\nconst ELLIPSIS = \"…\";\nfunction fitApnsPayload(body, maxBytes = APNS_MAX_BYTES) {\n if (payloadBytes(body) <= maxBytes) {\n return body;\n }\n const aps = body.aps;\n const alert = aps?.alert;\n if (!alert) {\n return body;\n }\n for (const field of [\"body\", \"subtitle\"]) {\n if (payloadBytes(body) <= maxBytes) {\n break;\n }\n const value = alert[field];\n if (typeof value !== \"string\" || value.length === 0) {\n continue;\n }\n let text = value;\n while (payloadBytes(body) > maxBytes && text.length > 0) {\n const cut = Math.max(1, Math.ceil(text.length * 0.12));\n text = text.slice(0, text.length - cut);\n alert[field] = text.length > 0 ? text + ELLIPSIS : void 0;\n }\n }\n return body;\n}\nfunction payloadBytes(body) {\n return Buffer.byteLength(JSON.stringify(body), \"utf8\");\n}\nconst execFileAsync = promisify(execFile);\nconst APNS_HOST_PROD = \"api.push.apple.com\";\nconst APNS_HOST_SANDBOX = \"api.sandbox.push.apple.com\";\nconst JWT_REFRESH_INTERVAL_MS = 30 * 60 * 1e3;\nconst REQUEST_TIMEOUT_SECONDS = 15;\nconst MAX_APNS_CONCURRENCY = 20;\nclass LibraryAPNsService {\n bundleId;\n cachedJwt = null;\n cachedJwtAt = 0;\n configured = false;\n host = \"\";\n keyId;\n privateKey;\n teamId;\n constructor() {\n this.keyId = private_env.APNS_KEY_ID;\n this.teamId = private_env.APNS_TEAM_ID;\n this.bundleId = private_env.APNS_BUNDLE_ID;\n this.privateKey = private_env.APNS_KEY;\n if (!this.keyId || !this.teamId || !this.bundleId || !this.privateKey) {\n console.error(\n \"[apns] Missing required configuration (APNS_KEY_ID, APNS_TEAM_ID, APNS_BUNDLE_ID, or APNS_KEY)\"\n );\n this.configured = false;\n return;\n }\n const production = private_env.APNS_PRODUCTION === \"true\";\n this.host = production ? APNS_HOST_PROD : APNS_HOST_SANDBOX;\n try {\n execFileSync(\"curl\", [\"--version\"], { stdio: \"ignore\" });\n } catch (error) {\n console.error(\n \"[apns] curl binary not found — install curl to enable APNs delivery:\",\n toErrorMessage(error)\n );\n this.configured = false;\n return;\n }\n try {\n this.getJwt();\n this.configured = true;\n console.log(\n `[apns] Provider initialized (${production ? \"production\" : \"sandbox\"} mode, curl transport)`\n );\n } catch (error) {\n console.error(\"[apns] Failed to initialize:\", toErrorMessage(error));\n this.configured = false;\n }\n }\n isConfigured() {\n return this.configured;\n }\n async sendNotification(deviceToken, payload) {\n if (!this.configured) {\n throw new Error(\"APNs service not configured properly\");\n }\n if (!deviceToken || !payload) {\n throw new Error(\"Device token and payload are required\");\n }\n return this.deliver(deviceToken, this.buildAlertBody(payload), \"alert\", \"10\");\n }\n /**\n * Send a SILENT (content-available) background push to wake a backgrounded app without\n * showing an alert — used to wake the phone-resident agent loop so it can run a burst.\n * Uses apns-push-type:background + apns-priority:5 (required by APNs for silent pushes).\n * iOS throttles these (a few per hour); delivery is best-effort.\n */\n async sendSilentNotification(deviceToken, data) {\n if (!this.configured) {\n throw new Error(\"APNs service not configured properly\");\n }\n if (!deviceToken) {\n throw new Error(\"Device token is required\");\n }\n const body = { aps: { \"content-available\": 1 } };\n if (data) {\n const { aps: _ignoredAps, ...customData } = data;\n Object.assign(body, customData);\n }\n return this.deliver(deviceToken, body, \"background\", \"5\");\n }\n /**\n * Fan out one alert push to many devices concurrently. Fits + serializes the\n * payload once and captures the JWT once (so no call uses a mid-fan-out\n * expired token), then classifies/aggregates results and returns the set of\n * stale tokens for the caller to prune.\n */\n async sendToMany(devices, payload, collapseId) {\n if (!this.configured) {\n throw new Error(\"APNs service not configured properly\");\n }\n if (devices.length === 0) {\n return { results: [], staleTokens: [], totalFailed: 0, totalSent: 0 };\n }\n const serverAppEnv = this.host === APNS_HOST_PROD ? \"production\" : \"sandbox\";\n const bodyJson = JSON.stringify(fitApnsPayload(this.buildAlertBody(payload)));\n const jwtToken = this.getJwt();\n const outcomes = await mapLimit(\n devices,\n MAX_APNS_CONCURRENCY,\n async (device) => {\n const res = await this.deliverPreSerialized(\n device.token,\n bodyJson,\n \"alert\",\n \"10\",\n jwtToken,\n collapseId\n );\n return {\n appEnv: device.appEnv,\n httpStatus: res.httpStatus ?? 0,\n reason: res.error ?? null,\n registeredAt: device.registeredAt,\n timestampMs: res.timestampMs ?? 0,\n token: device.token\n };\n }\n );\n return summarizeApnsFanOut(outcomes, serverAppEnv);\n }\n shutdown() {\n }\n /** Build the APNs `{ aps, ...customData }` body for an alert push. */\n buildAlertBody(payload) {\n const aps = {\n alert: {\n body: payload.body ?? payload.message ?? \"\",\n title: payload.title,\n ...payload.subtitle ? { subtitle: payload.subtitle } : {}\n },\n badge: payload.badge ?? 1,\n sound: payload.sound ?? \"default\"\n };\n if (payload.category) {\n aps.category = payload.category;\n }\n const body = { aps };\n if (payload.data) {\n const { aps: _ignoredAps, ...customData } = payload.data;\n Object.assign(body, customData);\n }\n return body;\n }\n /**\n * Shared curl/HTTP-2 delivery. Fits + serializes the body and signs a JWT,\n * then delegates to deliverPreSerialized. `pushType` is 'alert' | 'background'.\n */\n async deliver(deviceToken, body, pushType, priority) {\n const bodyJson = JSON.stringify(fitApnsPayload(body));\n return this.deliverPreSerialized(deviceToken, bodyJson, pushType, priority, this.getJwt());\n }\n /**\n * Curl/HTTP-2 delivery from a pre-serialized body + pre-captured JWT — the hot\n * path for sendToMany (no per-token fit or JWT sign). Returns httpStatus and,\n * on a 410, the parsed Unregistered timestamp (ms) for the prune guard.\n */\n async deliverPreSerialized(deviceToken, bodyJson, pushType, priority, jwtToken, collapseId) {\n const url = `https://${this.host}/3/device/${deviceToken}`;\n const safeCollapseId = collapseId ? collapseId.replace(/[^\\x20-\\x7E]/g, \"\").slice(0, 64) || void 0 : void 0;\n const args = [\n \"-sS\",\n \"--http2\",\n \"--max-time\",\n String(REQUEST_TIMEOUT_SECONDS),\n \"-X\",\n \"POST\",\n \"-H\",\n \"content-type: application/json\",\n \"-H\",\n `apns-topic: ${this.bundleId}`,\n \"-H\",\n `authorization: bearer ${jwtToken}`,\n \"-H\",\n `apns-push-type: ${pushType}`,\n \"-H\",\n `apns-priority: ${priority}`,\n ...safeCollapseId ? [\"-H\", `apns-collapse-id: ${safeCollapseId}`] : [],\n \"-d\",\n bodyJson,\n \"-w\",\n \"\\n__SHOOTER_HTTP_STATUS__:%{http_code}\\n\",\n url\n ];\n try {\n const { stdout } = await execFileAsync(\"curl\", args, {\n maxBuffer: 1024 * 1024,\n timeout: (REQUEST_TIMEOUT_SECONDS + 5) * 1e3\n });\n const statusMatch = /__SHOOTER_HTTP_STATUS__:(\\d+)/.exec(stdout);\n const status = statusMatch ? parseInt(statusMatch[1], 10) : 0;\n const bodyText = stdout.replace(/\\n?__SHOOTER_HTTP_STATUS__:\\d+\\n?$/, \"\").trim();\n if (status === 200) {\n return { failed: 0, httpStatus: 200, sent: 1, success: true };\n }\n let reason = bodyText;\n let timestampMs;\n try {\n const parsed = JSON.parse(bodyText);\n if (parsed && typeof parsed === \"object\") {\n const obj = parsed;\n if (typeof obj.reason === \"string\") {\n reason = obj.reason;\n }\n if (typeof obj.timestamp === \"number\") {\n timestampMs = obj.timestamp < 1e12 ? obj.timestamp * 1e3 : obj.timestamp;\n }\n }\n } catch {\n }\n console.error(`[apns] Delivery failed (status=${status}): ${reason}`);\n return { error: reason, failed: 1, httpStatus: status, sent: 0, success: false, timestampMs };\n } catch (err) {\n const msg = toErrorMessage(err).replace(/bearer\\s+[A-Za-z0-9._-]+/gi, \"bearer [REDACTED]\").replace(/device\\/[A-Fa-f0-9]+/g, \"device/[REDACTED]\");\n console.error(`[apns] curl transport error: ${msg}`);\n return { error: msg, failed: 1, httpStatus: 0, sent: 0, success: false };\n }\n }\n getJwt() {\n const now = Date.now();\n if (this.cachedJwt && now - this.cachedJwtAt < JWT_REFRESH_INTERVAL_MS) {\n return this.cachedJwt;\n }\n if (!this.privateKey || !this.keyId || !this.teamId) {\n throw new Error(\"APNs credentials missing\");\n }\n const token = jwt.sign({ iat: Math.floor(now / 1e3), iss: this.teamId }, this.privateKey, {\n algorithm: \"ES256\",\n header: { alg: \"ES256\", kid: this.keyId }\n });\n this.cachedJwt = token;\n this.cachedJwtAt = now;\n return token;\n }\n}\nasync function mapLimit(items, limit, fn) {\n const results = new Array(items.length);\n let next = 0;\n const worker = async () => {\n while (next < items.length) {\n const idx = next;\n next += 1;\n results[idx] = await fn(items[idx]);\n }\n };\n const workerCount = Math.min(limit, items.length);\n await Promise.all(Array.from({ length: workerCount }, () => worker()));\n return results;\n}\nexport {\n LibraryAPNsService as L\n};\n"],"names":[],"mappings":"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"}
|
package/build/server/index.js
CHANGED
|
@@ -1351,7 +1351,7 @@ const options = {
|
|
|
1351
1351
|
<div class="error">
|
|
1352
1352
|
<span class="status">` + status + '</span>\n <div class="message">\n <h1>' + message + "</h1>\n </div>\n </div>\n </body>\n</html>\n"
|
|
1353
1353
|
},
|
|
1354
|
-
version_hash: "
|
|
1354
|
+
version_hash: "1f9h0ew"
|
|
1355
1355
|
};
|
|
1356
1356
|
async function get_hooks() {
|
|
1357
1357
|
let handle;
|