@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
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { b as private_env } from './shared-server-DaWdgxVh.js';
|
|
2
|
-
import {
|
|
3
|
-
import { homedir } from 'os';
|
|
4
|
-
import { join } from 'path';
|
|
5
|
-
import { L as LibraryAPNsService } from './library-apns-D8RPINlv.js';
|
|
2
|
+
import { L as LibraryAPNsService } from './library-apns-DMlL1BAg.js';
|
|
6
3
|
import { c as createPendingRequest } from './pending-requests-8rWjrF6d.js';
|
|
7
4
|
import { v as validateAuth } from './auth-DuunT7Cg.js';
|
|
8
5
|
import admin from 'firebase-admin';
|
|
6
|
+
import { m as maskToken } from './device-format-DTgEz4Yr.js';
|
|
7
|
+
import { d as deviceTokenStore } from './device-token-store-Ct7aTeR8.js';
|
|
9
8
|
import { t as toErrorMessage } from './error-DDXB3duW.js';
|
|
10
9
|
import { b as broadcastEvent } from './guest-registry-Dxvd7p-g.js';
|
|
11
10
|
import './super-session-handler-DPyxFgmz.js';
|
|
@@ -14,34 +13,15 @@ import 'child_process';
|
|
|
14
13
|
import 'jsonwebtoken';
|
|
15
14
|
import 'util';
|
|
16
15
|
import 'better-sqlite3';
|
|
16
|
+
import 'fs';
|
|
17
|
+
import 'path';
|
|
17
18
|
import './shooter-home-4f_HkdGI.js';
|
|
19
|
+
import 'os';
|
|
18
20
|
import 'crypto';
|
|
19
21
|
import './registry-D4J_CuzW.js';
|
|
20
22
|
import './qwen-reader-DGfUbKaJ.js';
|
|
21
23
|
import './coordinator-DMU_ADXf.js';
|
|
22
24
|
|
|
23
|
-
const normalize = (value) => {
|
|
24
|
-
const trimmed = value?.trim();
|
|
25
|
-
return trimmed ? trimmed : void 0;
|
|
26
|
-
};
|
|
27
|
-
function readPersistedDeviceToken(platform) {
|
|
28
|
-
const tokensFile = join(homedir(), ".shooter", "device-tokens.json");
|
|
29
|
-
if (!existsSync(tokensFile)) {
|
|
30
|
-
return void 0;
|
|
31
|
-
}
|
|
32
|
-
try {
|
|
33
|
-
const parsed = JSON.parse(readFileSync(tokensFile, "utf-8"));
|
|
34
|
-
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
35
|
-
const value = parsed[platform];
|
|
36
|
-
return typeof value === "string" && value ? value : void 0;
|
|
37
|
-
}
|
|
38
|
-
} catch {
|
|
39
|
-
}
|
|
40
|
-
return void 0;
|
|
41
|
-
}
|
|
42
|
-
function resolveDeviceToken(requestToken, persistedToken, envToken) {
|
|
43
|
-
return normalize(requestToken) ?? normalize(persistedToken) ?? normalize(envToken);
|
|
44
|
-
}
|
|
45
25
|
const MAX_HISTORY = 100;
|
|
46
26
|
const history = [];
|
|
47
27
|
function addNotification(record) {
|
|
@@ -53,42 +33,140 @@ function addNotification(record) {
|
|
|
53
33
|
function getNotifications(limit = 50) {
|
|
54
34
|
return history.slice(0, limit);
|
|
55
35
|
}
|
|
36
|
+
function selectPlatforms(platformFilter) {
|
|
37
|
+
if (platformFilter === "ios") {
|
|
38
|
+
return { doAndroid: false, doIos: true };
|
|
39
|
+
}
|
|
40
|
+
if (platformFilter === "android") {
|
|
41
|
+
return { doAndroid: true, doIos: false };
|
|
42
|
+
}
|
|
43
|
+
return { doAndroid: true, doIos: true };
|
|
44
|
+
}
|
|
45
|
+
function summarizeNotifyDelivery(apns, fcm) {
|
|
46
|
+
const sent = apns.totalSent + fcm.successCount;
|
|
47
|
+
const failed = apns.totalFailed + fcm.failureCount;
|
|
48
|
+
const staleTokens = [...apns.staleTokens, ...fcm.staleTokens];
|
|
49
|
+
const succeededTokens = [
|
|
50
|
+
...apns.results.filter((r) => r.success).map((r) => r.token),
|
|
51
|
+
...fcm.results.filter((r) => r.success).map((r) => r.token)
|
|
52
|
+
];
|
|
53
|
+
return { delivered: sent > 0, failed, sent, staleTokens, succeededTokens };
|
|
54
|
+
}
|
|
55
|
+
const PRUNABLE_FCM_CODES = /* @__PURE__ */ new Set([
|
|
56
|
+
"messaging/registration-token-not-registered"
|
|
57
|
+
]);
|
|
58
|
+
function chunk(items, size) {
|
|
59
|
+
const out = [];
|
|
60
|
+
for (let i = 0; i < items.length; i += size) {
|
|
61
|
+
out.push(items.slice(i, i + size));
|
|
62
|
+
}
|
|
63
|
+
return out;
|
|
64
|
+
}
|
|
65
|
+
function classifyFcmError(code) {
|
|
66
|
+
return code && PRUNABLE_FCM_CODES.has(code) ? "prune" : "keep";
|
|
67
|
+
}
|
|
68
|
+
function summarizeFcmFanOut(outcomes) {
|
|
69
|
+
const results = [];
|
|
70
|
+
const staleTokens = [];
|
|
71
|
+
let successCount = 0;
|
|
72
|
+
let failureCount = 0;
|
|
73
|
+
for (const o of outcomes) {
|
|
74
|
+
if (o.success) {
|
|
75
|
+
successCount += 1;
|
|
76
|
+
} else {
|
|
77
|
+
failureCount += 1;
|
|
78
|
+
if (classifyFcmError(o.errorCode) === "prune") {
|
|
79
|
+
staleTokens.push(o.token);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
results.push({
|
|
83
|
+
error: o.errorCode,
|
|
84
|
+
messageId: o.messageId,
|
|
85
|
+
success: o.success,
|
|
86
|
+
token: o.token
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
return { failureCount, results, staleTokens, successCount };
|
|
90
|
+
}
|
|
56
91
|
let app = null;
|
|
92
|
+
const FCM_MULTICAST_CHUNK = 100;
|
|
57
93
|
function isFCMConfigured() {
|
|
58
94
|
return !!(process.env.FCM_PROJECT_ID && process.env.FCM_CLIENT_EMAIL && process.env.FCM_PRIVATE_KEY);
|
|
59
95
|
}
|
|
60
|
-
async function
|
|
96
|
+
async function sendFCMNotificationMulti(tokens, payload) {
|
|
97
|
+
if (tokens.length === 0) {
|
|
98
|
+
return { failureCount: 0, results: [], staleTokens: [], successCount: 0 };
|
|
99
|
+
}
|
|
100
|
+
let fcmApp;
|
|
61
101
|
try {
|
|
62
|
-
|
|
63
|
-
const message = {
|
|
64
|
-
android: {
|
|
65
|
-
priority: "high",
|
|
66
|
-
// Ensures delivery even in Doze mode
|
|
67
|
-
ttl: 3e5
|
|
68
|
-
// 5 minutes TTL (matches pending request expiry)
|
|
69
|
-
},
|
|
70
|
-
data: {
|
|
71
|
-
body: payload.body || payload.message || "",
|
|
72
|
-
category: payload.category ?? (typeof payload.data?.category === "string" ? payload.data.category : ""),
|
|
73
|
-
project: typeof payload.data?.project === "string" ? payload.data.project : "",
|
|
74
|
-
requestId: typeof payload.data?.requestId === "string" ? payload.data.requestId : "",
|
|
75
|
-
source: typeof payload.data?.source === "string" ? payload.data.source : "",
|
|
76
|
-
subtitle: payload.subtitle ?? "",
|
|
77
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
78
|
-
title: payload.title,
|
|
79
|
-
toolInput: payload.data?.toolInput ? JSON.stringify(payload.data.toolInput) : "",
|
|
80
|
-
toolName: typeof payload.data?.toolName === "string" ? payload.data.toolName : "",
|
|
81
|
-
type: typeof payload.data?.type === "string" ? payload.data.type : ""
|
|
82
|
-
},
|
|
83
|
-
token: deviceToken
|
|
84
|
-
};
|
|
85
|
-
const messageId = await admin.messaging(fcmApp).send(message);
|
|
86
|
-
return { messageId, success: true };
|
|
102
|
+
fcmApp = getApp();
|
|
87
103
|
} catch (error) {
|
|
88
|
-
const
|
|
89
|
-
console.error("[FCM]
|
|
90
|
-
return {
|
|
104
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
105
|
+
console.error("[FCM] multi-send setup failed:", fcmErrorLabel(error));
|
|
106
|
+
return {
|
|
107
|
+
failureCount: tokens.length,
|
|
108
|
+
results: tokens.map((token) => ({ error: msg, messageId: null, success: false, token })),
|
|
109
|
+
staleTokens: [],
|
|
110
|
+
successCount: 0
|
|
111
|
+
};
|
|
91
112
|
}
|
|
113
|
+
const base = buildDataMessage(payload);
|
|
114
|
+
const outcomes = [];
|
|
115
|
+
for (const group of chunk(tokens, FCM_MULTICAST_CHUNK)) {
|
|
116
|
+
try {
|
|
117
|
+
const batch = await admin.messaging(fcmApp).sendEachForMulticast({ ...base, tokens: [...group] });
|
|
118
|
+
batch.responses.forEach((resp, i) => {
|
|
119
|
+
const errorCode = resp.error?.code ?? null;
|
|
120
|
+
if (errorCode === "messaging/invalid-argument") {
|
|
121
|
+
console.error(`[FCM] invalid-argument for token ${maskToken(group[i])}: ${errorCode}`);
|
|
122
|
+
}
|
|
123
|
+
outcomes.push({
|
|
124
|
+
errorCode,
|
|
125
|
+
messageId: resp.messageId ?? null,
|
|
126
|
+
success: resp.success,
|
|
127
|
+
token: group[i]
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
} catch (error) {
|
|
131
|
+
console.error("[FCM] multicast chunk failed:", fcmErrorLabel(error));
|
|
132
|
+
for (const token of group) {
|
|
133
|
+
outcomes.push({ errorCode: null, messageId: null, success: false, token });
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return summarizeFcmFanOut(outcomes);
|
|
138
|
+
}
|
|
139
|
+
function buildDataMessage(payload) {
|
|
140
|
+
return {
|
|
141
|
+
android: {
|
|
142
|
+
priority: "high",
|
|
143
|
+
// Ensures delivery even in Doze mode
|
|
144
|
+
ttl: 3e5
|
|
145
|
+
// 5 minutes TTL (matches pending request expiry)
|
|
146
|
+
},
|
|
147
|
+
data: {
|
|
148
|
+
body: payload.body || payload.message || "",
|
|
149
|
+
category: payload.category ?? (typeof payload.data?.category === "string" ? payload.data.category : ""),
|
|
150
|
+
project: typeof payload.data?.project === "string" ? payload.data.project : "",
|
|
151
|
+
requestId: typeof payload.data?.requestId === "string" ? payload.data.requestId : "",
|
|
152
|
+
source: typeof payload.data?.source === "string" ? payload.data.source : "",
|
|
153
|
+
subtitle: payload.subtitle ?? "",
|
|
154
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
155
|
+
title: payload.title,
|
|
156
|
+
toolInput: payload.data?.toolInput ? JSON.stringify(payload.data.toolInput) : "",
|
|
157
|
+
toolName: typeof payload.data?.toolName === "string" ? payload.data.toolName : "",
|
|
158
|
+
type: typeof payload.data?.type === "string" ? payload.data.type : ""
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
function fcmErrorLabel(error) {
|
|
163
|
+
if (error && typeof error === "object" && "code" in error) {
|
|
164
|
+
const code = error.code;
|
|
165
|
+
if (typeof code === "string" && code.length > 0) {
|
|
166
|
+
return code;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return error instanceof Error ? error.message : String(error);
|
|
92
170
|
}
|
|
93
171
|
function getApp() {
|
|
94
172
|
if (!app) {
|
|
@@ -113,6 +191,57 @@ function getAPNsClient() {
|
|
|
113
191
|
}
|
|
114
192
|
return apnsSingleton;
|
|
115
193
|
}
|
|
194
|
+
const EMPTY_APNS_RESULT = {
|
|
195
|
+
results: [],
|
|
196
|
+
staleTokens: [],
|
|
197
|
+
totalFailed: 0,
|
|
198
|
+
totalSent: 0
|
|
199
|
+
};
|
|
200
|
+
const EMPTY_FCM_RESULT = {
|
|
201
|
+
failureCount: 0,
|
|
202
|
+
results: [],
|
|
203
|
+
staleTokens: [],
|
|
204
|
+
successCount: 0
|
|
205
|
+
};
|
|
206
|
+
function resolveAndroidTokens() {
|
|
207
|
+
const rows = deviceTokenStore.listActive("android");
|
|
208
|
+
if (rows.length > 0) {
|
|
209
|
+
return rows.map((r) => r.token);
|
|
210
|
+
}
|
|
211
|
+
const seed = private_env.ANDROID_DEVICE_TOKEN?.trim();
|
|
212
|
+
return seed ? [seed] : [];
|
|
213
|
+
}
|
|
214
|
+
function resolveIosDevices(override) {
|
|
215
|
+
const appEnv = serverApnEnv();
|
|
216
|
+
if (override) {
|
|
217
|
+
return [syntheticSeedDevice(override, "ios", appEnv)];
|
|
218
|
+
}
|
|
219
|
+
const rows = deviceTokenStore.listActiveForEnv("ios", appEnv);
|
|
220
|
+
if (rows.length > 0) {
|
|
221
|
+
return rows;
|
|
222
|
+
}
|
|
223
|
+
const seed = private_env.DEVICE_TOKEN?.trim();
|
|
224
|
+
return seed ? [syntheticSeedDevice(seed, "ios", appEnv)] : [];
|
|
225
|
+
}
|
|
226
|
+
function serverApnEnv() {
|
|
227
|
+
return private_env.APNS_PRODUCTION === "true" ? "production" : "sandbox";
|
|
228
|
+
}
|
|
229
|
+
function syntheticSeedDevice(token, platform, appEnv) {
|
|
230
|
+
const nowIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
231
|
+
return {
|
|
232
|
+
appEnv,
|
|
233
|
+
bundleId: null,
|
|
234
|
+
deviceId: null,
|
|
235
|
+
failureCount: 0,
|
|
236
|
+
friendlyName: null,
|
|
237
|
+
id: `seed-${platform}`,
|
|
238
|
+
isActive: true,
|
|
239
|
+
lastSeenAt: nowIso,
|
|
240
|
+
platform,
|
|
241
|
+
registeredAt: nowIso,
|
|
242
|
+
token
|
|
243
|
+
};
|
|
244
|
+
}
|
|
116
245
|
const notificationCache = /* @__PURE__ */ new Map();
|
|
117
246
|
const DEDUP_WINDOW = 1e4;
|
|
118
247
|
function broadcastHookEvent(body) {
|
|
@@ -189,6 +318,9 @@ function buildNotificationRecord(id, title, message, status, data, error) {
|
|
|
189
318
|
}
|
|
190
319
|
function intelligentNotificationFilter(title, message, data, waitForResponse = false) {
|
|
191
320
|
const source = data?.source || "unknown";
|
|
321
|
+
if (waitForResponse) {
|
|
322
|
+
return { reason: "Bidirectional request — never filtered", send: true };
|
|
323
|
+
}
|
|
192
324
|
if (isDuplicateNotification(title, message, data, waitForResponse)) {
|
|
193
325
|
return {
|
|
194
326
|
reason: "Duplicate notification within 10-second window",
|
|
@@ -372,138 +504,53 @@ const POST = async ({ request }) => {
|
|
|
372
504
|
...subtitle ? { subtitle } : {},
|
|
373
505
|
title
|
|
374
506
|
};
|
|
375
|
-
const
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
);
|
|
391
|
-
if (!androidToken) {
|
|
392
|
-
return json(
|
|
393
|
-
{
|
|
394
|
-
details: "No Android device token available — set ANDROID_DEVICE_TOKEN, pass deviceToken in the request body, or open the Android app so it can auto-register its FCM token.",
|
|
395
|
-
error: "No device token configured"
|
|
396
|
-
},
|
|
397
|
-
{ status: 500 }
|
|
398
|
-
);
|
|
399
|
-
}
|
|
400
|
-
const fcmResult = await sendFCMNotification(androidToken, payload);
|
|
401
|
-
if (fcmResult.success) {
|
|
402
|
-
recordNotification(title, message, data);
|
|
403
|
-
if (waitForResponse) {
|
|
404
|
-
createPendingRequest(canonicalRequestId, {
|
|
405
|
-
options,
|
|
406
|
-
question: question ?? null,
|
|
407
|
-
responseKind: responseKind ?? "hook",
|
|
408
|
-
sessionId: data?.sessionId || "",
|
|
409
|
-
toolInput: data?.toolInput || {},
|
|
410
|
-
toolName: data?.toolName || ""
|
|
411
|
-
});
|
|
412
|
-
}
|
|
413
|
-
addNotification(buildNotificationRecord(canonicalRequestId, title, message, "sent", data));
|
|
414
|
-
return json({
|
|
415
|
-
message: "Notification sent successfully",
|
|
416
|
-
requestId: canonicalRequestId,
|
|
417
|
-
result: { messageId: fcmResult.messageId },
|
|
418
|
-
success: true,
|
|
419
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
420
|
-
});
|
|
421
|
-
} else {
|
|
422
|
-
console.error(`[notify] FCM delivery failed: ${fcmResult.error}`);
|
|
423
|
-
releaseNotification(title, message, data);
|
|
424
|
-
addNotification(
|
|
425
|
-
buildNotificationRecord(
|
|
426
|
-
canonicalRequestId,
|
|
427
|
-
title,
|
|
428
|
-
message,
|
|
429
|
-
"failed",
|
|
430
|
-
data,
|
|
431
|
-
fcmResult.error
|
|
432
|
-
)
|
|
433
|
-
);
|
|
434
|
-
return json(
|
|
435
|
-
{
|
|
436
|
-
details: fcmResult.error,
|
|
437
|
-
error: "Failed to send notification",
|
|
438
|
-
requestId: canonicalRequestId,
|
|
439
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
440
|
-
},
|
|
441
|
-
{ status: 500 }
|
|
442
|
-
);
|
|
443
|
-
}
|
|
507
|
+
const override = requestDeviceToken?.trim() || void 0;
|
|
508
|
+
const { doAndroid, doIos } = selectPlatforms(private_env.DEVICE_PLATFORM);
|
|
509
|
+
const iosDevices = doIos ? override ? resolveIosDevices(override) : resolveIosDevices() : [];
|
|
510
|
+
const androidTokens = doAndroid ? override ? [override] : resolveAndroidTokens() : [];
|
|
511
|
+
const collapseId = waitForResponse ? canonicalRequestId : void 0;
|
|
512
|
+
const [apnsResult, fcmResult] = await Promise.all([
|
|
513
|
+
iosDevices.length > 0 && apnsClient.isConfigured() ? apnsClient.sendToMany(iosDevices, payload, collapseId) : Promise.resolve(EMPTY_APNS_RESULT),
|
|
514
|
+
androidTokens.length > 0 && isFCMConfigured() ? sendFCMNotificationMulti(androidTokens, payload) : Promise.resolve(EMPTY_FCM_RESULT)
|
|
515
|
+
]);
|
|
516
|
+
const summary = summarizeNotifyDelivery(apnsResult, fcmResult);
|
|
517
|
+
const pruned = !override && summary.staleTokens.length ? deviceTokenStore.pruneByTokens(summary.staleTokens) : 0;
|
|
518
|
+
if (summary.succeededTokens.length > 0) {
|
|
519
|
+
deviceTokenStore.touchLastSeen(summary.succeededTokens);
|
|
520
|
+
}
|
|
521
|
+
if (summary.delivered && summary.failed === 0) {
|
|
522
|
+
recordNotification(title, message, data);
|
|
444
523
|
} else {
|
|
445
|
-
|
|
446
|
-
return json(
|
|
447
|
-
{
|
|
448
|
-
details: "Missing APNS_KEY, APNS_KEY_ID, or APNS_TEAM_ID environment variables",
|
|
449
|
-
error: "APNs client not configured"
|
|
450
|
-
},
|
|
451
|
-
{ status: 500 }
|
|
452
|
-
);
|
|
453
|
-
}
|
|
454
|
-
const deviceToken = resolveDeviceToken(
|
|
455
|
-
requestDeviceToken,
|
|
456
|
-
readPersistedDeviceToken("ios"),
|
|
457
|
-
private_env.DEVICE_TOKEN
|
|
458
|
-
);
|
|
459
|
-
if (!deviceToken) {
|
|
460
|
-
return json(
|
|
461
|
-
{
|
|
462
|
-
details: "No iOS device token available — pass deviceToken in the request body, ensure ~/.shooter/device-tokens.json contains an ios token, or set DEVICE_TOKEN.",
|
|
463
|
-
error: "No device token configured"
|
|
464
|
-
},
|
|
465
|
-
{ status: 500 }
|
|
466
|
-
);
|
|
467
|
-
}
|
|
468
|
-
try {
|
|
469
|
-
const result = await apnsClient.sendNotification(deviceToken, payload);
|
|
470
|
-
recordNotification(title, message, data);
|
|
471
|
-
if (waitForResponse) {
|
|
472
|
-
createPendingRequest(canonicalRequestId, {
|
|
473
|
-
options,
|
|
474
|
-
question: question ?? null,
|
|
475
|
-
responseKind: responseKind ?? "hook",
|
|
476
|
-
sessionId: data?.sessionId || "",
|
|
477
|
-
toolInput: data?.toolInput || {},
|
|
478
|
-
toolName: data?.toolName || ""
|
|
479
|
-
});
|
|
480
|
-
}
|
|
481
|
-
addNotification(buildNotificationRecord(canonicalRequestId, title, message, "sent", data));
|
|
482
|
-
return json({
|
|
483
|
-
message: "Notification sent successfully",
|
|
484
|
-
requestId: canonicalRequestId,
|
|
485
|
-
result,
|
|
486
|
-
success: true,
|
|
487
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
488
|
-
});
|
|
489
|
-
} catch (notificationError) {
|
|
490
|
-
const notifErrMsg = toErrorMessage(notificationError);
|
|
491
|
-
console.error(`[notify] APNs delivery failed: ${notifErrMsg}`);
|
|
492
|
-
releaseNotification(title, message, data);
|
|
493
|
-
addNotification(
|
|
494
|
-
buildNotificationRecord(canonicalRequestId, title, message, "failed", data, notifErrMsg)
|
|
495
|
-
);
|
|
496
|
-
return json(
|
|
497
|
-
{
|
|
498
|
-
details: notifErrMsg,
|
|
499
|
-
error: "Failed to send notification",
|
|
500
|
-
requestId: canonicalRequestId,
|
|
501
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
502
|
-
},
|
|
503
|
-
{ status: 500 }
|
|
504
|
-
);
|
|
505
|
-
}
|
|
524
|
+
releaseNotification(title, message, data);
|
|
506
525
|
}
|
|
526
|
+
if (waitForResponse && summary.delivered) {
|
|
527
|
+
createPendingRequest(canonicalRequestId, {
|
|
528
|
+
options,
|
|
529
|
+
question: question ?? null,
|
|
530
|
+
responseKind: responseKind ?? "hook",
|
|
531
|
+
sessionId: data?.sessionId || "",
|
|
532
|
+
toolInput: data?.toolInput || {},
|
|
533
|
+
toolName: data?.toolName || ""
|
|
534
|
+
});
|
|
535
|
+
}
|
|
536
|
+
addNotification(
|
|
537
|
+
buildNotificationRecord(
|
|
538
|
+
canonicalRequestId,
|
|
539
|
+
title,
|
|
540
|
+
message,
|
|
541
|
+
summary.delivered ? "sent" : "failed",
|
|
542
|
+
data,
|
|
543
|
+
summary.delivered ? null : "No registered device accepted the notification"
|
|
544
|
+
)
|
|
545
|
+
);
|
|
546
|
+
return json({
|
|
547
|
+
failed: summary.failed,
|
|
548
|
+
pruned,
|
|
549
|
+
requestId: canonicalRequestId,
|
|
550
|
+
sent: summary.sent,
|
|
551
|
+
success: summary.delivered,
|
|
552
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
553
|
+
});
|
|
507
554
|
} catch (error) {
|
|
508
555
|
console.error("Notification error:", error);
|
|
509
556
|
return json(
|
|
@@ -531,4 +578,4 @@ const GET = ({ request, url }) => {
|
|
|
531
578
|
};
|
|
532
579
|
|
|
533
580
|
export { GET, POST };
|
|
534
|
-
//# sourceMappingURL=_server.ts-
|
|
581
|
+
//# sourceMappingURL=_server.ts-B7BLxK5u.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_server.ts-B7BLxK5u.js","sources":["../../../.svelte-kit/adapter-node/entries/endpoints/api/notify/_server.ts.js"],"sourcesContent":["import { b as private_env } from \"../../../../chunks/shared-server.js\";\nimport { L as LibraryAPNsService } from \"../../../../chunks/library-apns.js\";\nimport { c as createPendingRequest } from \"../../../../chunks/pending-requests.js\";\nimport { v as validateAuth } from \"../../../../chunks/auth.js\";\nimport admin from \"firebase-admin\";\nimport { m as maskToken } from \"../../../../chunks/device-format.js\";\nimport { d as deviceTokenStore } from \"../../../../chunks/device-token-store.js\";\nimport { t as toErrorMessage } from \"../../../../chunks/error.js\";\nimport { b as broadcastEvent } from \"../../../../chunks/guest-registry.js\";\nimport \"../../../../chunks/super-session-handler.js\";\nimport { json } from \"@sveltejs/kit\";\nconst MAX_HISTORY = 100;\nconst history = [];\nfunction addNotification(record) {\n history.unshift(record);\n if (history.length > MAX_HISTORY) {\n history.length = MAX_HISTORY;\n }\n}\nfunction getNotifications(limit = 50) {\n return history.slice(0, limit);\n}\nfunction selectPlatforms(platformFilter) {\n if (platformFilter === \"ios\") {\n return { doAndroid: false, doIos: true };\n }\n if (platformFilter === \"android\") {\n return { doAndroid: true, doIos: false };\n }\n return { doAndroid: true, doIos: true };\n}\nfunction summarizeNotifyDelivery(apns, fcm) {\n const sent = apns.totalSent + fcm.successCount;\n const failed = apns.totalFailed + fcm.failureCount;\n const staleTokens = [...apns.staleTokens, ...fcm.staleTokens];\n const succeededTokens = [\n ...apns.results.filter((r) => r.success).map((r) => r.token),\n ...fcm.results.filter((r) => r.success).map((r) => r.token)\n ];\n return { delivered: sent > 0, failed, sent, staleTokens, succeededTokens };\n}\nconst PRUNABLE_FCM_CODES = /* @__PURE__ */ new Set([\n \"messaging/registration-token-not-registered\"\n]);\nfunction chunk(items, size) {\n const out = [];\n for (let i = 0; i < items.length; i += size) {\n out.push(items.slice(i, i + size));\n }\n return out;\n}\nfunction classifyFcmError(code) {\n return code && PRUNABLE_FCM_CODES.has(code) ? \"prune\" : \"keep\";\n}\nfunction summarizeFcmFanOut(outcomes) {\n const results = [];\n const staleTokens = [];\n let successCount = 0;\n let failureCount = 0;\n for (const o of outcomes) {\n if (o.success) {\n successCount += 1;\n } else {\n failureCount += 1;\n if (classifyFcmError(o.errorCode) === \"prune\") {\n staleTokens.push(o.token);\n }\n }\n results.push({\n error: o.errorCode,\n messageId: o.messageId,\n success: o.success,\n token: o.token\n });\n }\n return { failureCount, results, staleTokens, successCount };\n}\nlet app = null;\nconst FCM_MULTICAST_CHUNK = 100;\nfunction isFCMConfigured() {\n return !!(process.env.FCM_PROJECT_ID && process.env.FCM_CLIENT_EMAIL && process.env.FCM_PRIVATE_KEY);\n}\nasync function sendFCMNotificationMulti(tokens, payload) {\n if (tokens.length === 0) {\n return { failureCount: 0, results: [], staleTokens: [], successCount: 0 };\n }\n let fcmApp;\n try {\n fcmApp = getApp();\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n console.error(\"[FCM] multi-send setup failed:\", fcmErrorLabel(error));\n return {\n failureCount: tokens.length,\n results: tokens.map((token) => ({ error: msg, messageId: null, success: false, token })),\n staleTokens: [],\n successCount: 0\n };\n }\n const base = buildDataMessage(payload);\n const outcomes = [];\n for (const group of chunk(tokens, FCM_MULTICAST_CHUNK)) {\n try {\n const batch = await admin.messaging(fcmApp).sendEachForMulticast({ ...base, tokens: [...group] });\n batch.responses.forEach((resp, i) => {\n const errorCode = resp.error?.code ?? null;\n if (errorCode === \"messaging/invalid-argument\") {\n console.error(`[FCM] invalid-argument for token ${maskToken(group[i])}: ${errorCode}`);\n }\n outcomes.push({\n errorCode,\n messageId: resp.messageId ?? null,\n success: resp.success,\n token: group[i]\n });\n });\n } catch (error) {\n console.error(\"[FCM] multicast chunk failed:\", fcmErrorLabel(error));\n for (const token of group) {\n outcomes.push({ errorCode: null, messageId: null, success: false, token });\n }\n }\n }\n return summarizeFcmFanOut(outcomes);\n}\nfunction buildDataMessage(payload) {\n return {\n android: {\n priority: \"high\",\n // Ensures delivery even in Doze mode\n ttl: 3e5\n // 5 minutes TTL (matches pending request expiry)\n },\n data: {\n body: payload.body || payload.message || \"\",\n category: payload.category ?? (typeof payload.data?.category === \"string\" ? payload.data.category : \"\"),\n project: typeof payload.data?.project === \"string\" ? payload.data.project : \"\",\n requestId: typeof payload.data?.requestId === \"string\" ? payload.data.requestId : \"\",\n source: typeof payload.data?.source === \"string\" ? payload.data.source : \"\",\n subtitle: payload.subtitle ?? \"\",\n timestamp: (/* @__PURE__ */ new Date()).toISOString(),\n title: payload.title,\n toolInput: payload.data?.toolInput ? JSON.stringify(payload.data.toolInput) : \"\",\n toolName: typeof payload.data?.toolName === \"string\" ? payload.data.toolName : \"\",\n type: typeof payload.data?.type === \"string\" ? payload.data.type : \"\"\n }\n };\n}\nfunction fcmErrorLabel(error) {\n if (error && typeof error === \"object\" && \"code\" in error) {\n const code = error.code;\n if (typeof code === \"string\" && code.length > 0) {\n return code;\n }\n }\n return error instanceof Error ? error.message : String(error);\n}\nfunction getApp() {\n if (!app) {\n const projectId = process.env.FCM_PROJECT_ID;\n const clientEmail = process.env.FCM_CLIENT_EMAIL;\n const privateKey = process.env.FCM_PRIVATE_KEY?.replace(/\\\\n/g, \"\\n\");\n if (!projectId || !clientEmail || !privateKey) {\n throw new Error(\n \"FCM not configured: missing FCM_PROJECT_ID, FCM_CLIENT_EMAIL, or FCM_PRIVATE_KEY\"\n );\n }\n app = admin.initializeApp({\n credential: admin.credential.cert({ clientEmail, privateKey, projectId })\n });\n }\n return app;\n}\nlet apnsSingleton = null;\nfunction getAPNsClient() {\n if (!apnsSingleton) {\n apnsSingleton = new LibraryAPNsService();\n }\n return apnsSingleton;\n}\nconst EMPTY_APNS_RESULT = {\n results: [],\n staleTokens: [],\n totalFailed: 0,\n totalSent: 0\n};\nconst EMPTY_FCM_RESULT = {\n failureCount: 0,\n results: [],\n staleTokens: [],\n successCount: 0\n};\nfunction resolveAndroidTokens() {\n const rows = deviceTokenStore.listActive(\"android\");\n if (rows.length > 0) {\n return rows.map((r) => r.token);\n }\n const seed = private_env.ANDROID_DEVICE_TOKEN?.trim();\n return seed ? [seed] : [];\n}\nfunction resolveIosDevices(override) {\n const appEnv = serverApnEnv();\n if (override) {\n return [syntheticSeedDevice(override, \"ios\", appEnv)];\n }\n const rows = deviceTokenStore.listActiveForEnv(\"ios\", appEnv);\n if (rows.length > 0) {\n return rows;\n }\n const seed = private_env.DEVICE_TOKEN?.trim();\n return seed ? [syntheticSeedDevice(seed, \"ios\", appEnv)] : [];\n}\nfunction serverApnEnv() {\n return private_env.APNS_PRODUCTION === \"true\" ? \"production\" : \"sandbox\";\n}\nfunction syntheticSeedDevice(token, platform, appEnv) {\n const nowIso = (/* @__PURE__ */ new Date()).toISOString();\n return {\n appEnv,\n bundleId: null,\n deviceId: null,\n failureCount: 0,\n friendlyName: null,\n id: `seed-${platform}`,\n isActive: true,\n lastSeenAt: nowIso,\n platform,\n registeredAt: nowIso,\n token\n };\n}\nconst notificationCache = /* @__PURE__ */ new Map();\nconst DEDUP_WINDOW = 1e4;\nfunction broadcastHookEvent(body) {\n const data = body.data ?? {};\n const eventType = typeof data.eventType === \"string\" ? data.eventType : typeof body.eventType === \"string\" ? body.eventType : \"\";\n const tool = typeof data.tool === \"string\" ? data.tool : \"\";\n const terminalId = typeof data.terminalId === \"string\" ? data.terminalId : void 0;\n const sessionId = typeof data.sessionId === \"string\" ? data.sessionId : void 0;\n switch (eventType) {\n case \"error\":\n broadcastEvent({\n error: typeof data.error === \"string\" ? data.error : typeof data.message === \"string\" ? data.message : \"Unknown error\",\n terminalId,\n tool,\n type: \"tool-failed\"\n });\n break;\n case \"idle_input\":\n case \"session.idle\":\n broadcastEvent({\n message: typeof data.message === \"string\" ? data.message : \"\",\n sessionId,\n terminalId,\n type: \"agent-idle\"\n });\n break;\n case \"permission\":\n case \"permission_notification\":\n if (data.requestId && data.toolName) {\n broadcastEvent({\n input: typeof data.toolInput === \"object\" && data.toolInput !== null ? data.toolInput : {},\n requestId: data.requestId,\n tool: data.toolName,\n type: \"permission-requested\"\n });\n }\n break;\n case \"question\":\n broadcastEvent({\n message: typeof data.message === \"string\" ? data.message : \"\",\n sessionId,\n terminalId,\n type: \"agent-question\"\n });\n break;\n case \"tool.after\":\n broadcastEvent({ success: true, terminalId, tool, type: \"tool-completed\" });\n break;\n case \"tool.before\":\n broadcastEvent({\n command: typeof data.command === \"string\" ? data.command : \"\",\n filePath: typeof data.filePath === \"string\" ? data.filePath : typeof data.files === \"string\" ? data.files : \"\",\n terminalId,\n tool,\n type: \"tool-started\"\n });\n break;\n }\n}\nfunction buildNotificationRecord(id, title, message, status, data, error) {\n return {\n category: data?.category ?? null,\n data: data ?? null,\n error: error ?? null,\n id,\n message,\n project: data?.project ?? null,\n source: data?.source ?? null,\n status,\n timestamp: (/* @__PURE__ */ new Date()).toISOString(),\n title,\n tool: data?.tool ?? null\n };\n}\nfunction intelligentNotificationFilter(title, message, data, waitForResponse = false) {\n const source = data?.source || \"unknown\";\n if (waitForResponse) {\n return { reason: \"Bidirectional request — never filtered\", send: true };\n }\n if (isDuplicateNotification(title, message, data, waitForResponse)) {\n return {\n reason: \"Duplicate notification within 10-second window\",\n send: false\n };\n }\n if (source === \"smart-completion-detector\" || source === \"shooter-completion-detector\") {\n return {\n reason: \"Smart completion detector - completion or intervention needed\",\n send: true\n };\n }\n const spamPatterns = [\n /PreToolUse/i,\n // Any PreToolUse notifications\n /PostToolUse/i,\n // Any PostToolUse notifications\n /^(Read|Write|Edit|Bash)\\s+Starting\\s*\\|\\s*\\w+$/i,\n // Only basic tool starting patterns\n /^unknown\\s*\\|\\s*\\w+$/i\n // Only \"unknown | projectname\" exactly\n ];\n const isSpam = spamPatterns.some((pattern) => pattern.test(title) || pattern.test(message));\n if (isSpam) {\n return {\n reason: \"Filtered spam notification from old hook system\",\n send: false\n };\n }\n const importantPatterns = [\n /session complete/i,\n /intervention needed/i,\n /error/i,\n /failed/i,\n /blocked/i,\n /attention/i\n ];\n const isImportant = importantPatterns.some(\n (pattern) => pattern.test(title) || pattern.test(message)\n );\n if (isImportant) {\n return {\n reason: \"Important notification - completion or intervention\",\n send: true\n };\n }\n return {\n reason: \"General notification - allowing by default\",\n send: true\n };\n}\nfunction isDuplicateNotification(title, message, data, waitForResponse = false) {\n if (waitForResponse) {\n return false;\n }\n const dataRecord = data;\n const key = dataRecord?.dedupKey ? dataRecord.dedupKey : `${title}|${message}|${data?.category || \"unknown\"}`;\n const now = Date.now();\n if (notificationCache.has(key)) {\n const lastSent = notificationCache.get(key) ?? 0;\n if (now - lastSent < DEDUP_WINDOW) {\n return true;\n }\n }\n for (const [k, v] of notificationCache.entries()) {\n if (now - v > DEDUP_WINDOW) {\n notificationCache.delete(k);\n }\n }\n notificationCache.set(key, now);\n return false;\n}\nfunction notificationKey(title, message, data) {\n const dataRecord = data;\n return dataRecord?.dedupKey ?? `${title}|${message}|${data?.category || \"unknown\"}`;\n}\nfunction recordNotification(title, message, data) {\n notificationCache.set(notificationKey(title, message, data), Date.now());\n}\nfunction releaseNotification(title, message, data) {\n notificationCache.delete(notificationKey(title, message, data));\n}\nconst POST = async ({ request }) => {\n try {\n const apnsClient = getAPNsClient();\n const authError = validateAuth(request);\n if (authError) {\n return authError;\n }\n const rawBody = await request.json();\n if (!rawBody || typeof rawBody !== \"object\" || Array.isArray(rawBody)) {\n return json({ error: \"Request body must be a JSON object\" }, { status: 400 });\n }\n const body = rawBody;\n const data = body.data;\n const requestDeviceToken = body.deviceToken;\n const message = body.message;\n const title = body.title;\n const subtitle = typeof body.subtitle === \"string\" ? body.subtitle : void 0;\n const skipPush = typeof body.skipPush === \"boolean\" ? body.skipPush : false;\n const waitForResponse = typeof body.waitForResponse === \"boolean\" ? body.waitForResponse : false;\n const forcePush = typeof body.forcePush === \"boolean\" ? body.forcePush : false;\n const notificationCategory = typeof body.notificationCategory === \"string\" && body.notificationCategory.length > 0 ? body.notificationCategory : void 0;\n const question = typeof body.question === \"string\" ? body.question : void 0;\n const options = Array.isArray(body.options) && body.options.every((o) => o && typeof o === \"object\") ? body.options : void 0;\n const responseKindRaw = body.responseKind;\n const responseKind = responseKindRaw === \"hook\" || responseKindRaw === \"pty\" || responseKindRaw === \"info\" ? responseKindRaw : void 0;\n try {\n broadcastHookEvent(body);\n } catch {\n }\n if (!title || typeof title !== \"string\" || !message || typeof message !== \"string\") {\n return json({ error: \"Title and message are required and must be strings\" }, { status: 400 });\n }\n if (requestDeviceToken !== void 0 && typeof requestDeviceToken !== \"string\") {\n return json({ error: \"deviceToken must be a string\" }, { status: 400 });\n }\n const requestId = Math.random().toString(36).substring(2, 15);\n const dataRequestId = typeof data?.requestId === \"string\" ? data.requestId : void 0;\n const canonicalRequestId = dataRequestId || requestId;\n const shouldSendNotification = intelligentNotificationFilter(\n title,\n message,\n data,\n waitForResponse\n );\n if (!shouldSendNotification.send) {\n addNotification(\n buildNotificationRecord(\n canonicalRequestId,\n title,\n message,\n \"filtered\",\n data,\n shouldSendNotification.reason\n )\n );\n return json({\n message: \"Notification filtered (not sent)\",\n reason: shouldSendNotification.reason,\n success: true,\n timestamp: (/* @__PURE__ */ new Date()).toISOString()\n });\n }\n if (skipPush && !forcePush) {\n if (waitForResponse) {\n createPendingRequest(canonicalRequestId, {\n options,\n question: question ?? null,\n responseKind: responseKind ?? \"hook\",\n sessionId: data?.sessionId || \"\",\n toolInput: data?.toolInput || {},\n toolName: data?.toolName || \"\"\n });\n }\n addNotification(buildNotificationRecord(canonicalRequestId, title, message, \"skipped\", data));\n return json({\n message: \"Push skipped (WebSocket clients connected)\",\n requestId: canonicalRequestId,\n success: true,\n timestamp: (/* @__PURE__ */ new Date()).toISOString()\n });\n }\n const payload = {\n badge: 1,\n body: message,\n // notificationCategory wins when explicitly set so plan-mode /\n // elicitation flows can pick CLAUDE_PLAN_APPROVAL / CHOICE_2..4.\n // Falls back to CLAUDE_PERMISSION for the legacy bidirectional\n // permission flow when only waitForResponse is provided.\n category: notificationCategory ?? (waitForResponse ? \"CLAUDE_PERMISSION\" : void 0),\n data: {\n ...data,\n requestId: canonicalRequestId,\n source: \"modern-apns-api\",\n timestamp: (/* @__PURE__ */ new Date()).toISOString(),\n waitForResponse: waitForResponse || false\n },\n message: null,\n sound: \"default\",\n ...subtitle ? { subtitle } : {},\n title\n };\n const override = requestDeviceToken?.trim() || void 0;\n const { doAndroid, doIos } = selectPlatforms(private_env.DEVICE_PLATFORM);\n const iosDevices = doIos ? override ? resolveIosDevices(override) : resolveIosDevices() : [];\n const androidTokens = doAndroid ? override ? [override] : resolveAndroidTokens() : [];\n const collapseId = waitForResponse ? canonicalRequestId : void 0;\n const [apnsResult, fcmResult] = await Promise.all([\n iosDevices.length > 0 && apnsClient.isConfigured() ? apnsClient.sendToMany(iosDevices, payload, collapseId) : Promise.resolve(EMPTY_APNS_RESULT),\n androidTokens.length > 0 && isFCMConfigured() ? sendFCMNotificationMulti(androidTokens, payload) : Promise.resolve(EMPTY_FCM_RESULT)\n ]);\n const summary = summarizeNotifyDelivery(apnsResult, fcmResult);\n const pruned = !override && summary.staleTokens.length ? deviceTokenStore.pruneByTokens(summary.staleTokens) : 0;\n if (summary.succeededTokens.length > 0) {\n deviceTokenStore.touchLastSeen(summary.succeededTokens);\n }\n if (summary.delivered && summary.failed === 0) {\n recordNotification(title, message, data);\n } else {\n releaseNotification(title, message, data);\n }\n if (waitForResponse && summary.delivered) {\n createPendingRequest(canonicalRequestId, {\n options,\n question: question ?? null,\n responseKind: responseKind ?? \"hook\",\n sessionId: data?.sessionId || \"\",\n toolInput: data?.toolInput || {},\n toolName: data?.toolName || \"\"\n });\n }\n addNotification(\n buildNotificationRecord(\n canonicalRequestId,\n title,\n message,\n summary.delivered ? \"sent\" : \"failed\",\n data,\n summary.delivered ? null : \"No registered device accepted the notification\"\n )\n );\n return json({\n failed: summary.failed,\n pruned,\n requestId: canonicalRequestId,\n sent: summary.sent,\n success: summary.delivered,\n timestamp: (/* @__PURE__ */ new Date()).toISOString()\n });\n } catch (error) {\n console.error(\"Notification error:\", error);\n return json(\n {\n details: toErrorMessage(error),\n error: \"Failed to send notification\",\n timestamp: (/* @__PURE__ */ new Date()).toISOString()\n },\n { status: 500 }\n );\n }\n};\nconst GET = ({ request, url }) => {\n const authError = validateAuth(request);\n if (authError) {\n return authError;\n }\n const limit = parseInt(url.searchParams.get(\"limit\") || \"50\");\n const notifications = getNotifications(limit);\n return json({\n count: notifications.length,\n notifications,\n timestamp: (/* @__PURE__ */ new Date()).toISOString()\n });\n};\nexport {\n GET,\n POST\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
import { b as private_env } from './shared-server-DaWdgxVh.js';
|
|
2
|
-
import { L as LibraryAPNsService } from './library-apns-
|
|
2
|
+
import { L as LibraryAPNsService } from './library-apns-DMlL1BAg.js';
|
|
3
3
|
import { v as validateAuth } from './auth-DuunT7Cg.js';
|
|
4
|
+
import { d as deviceTokenStore } from './device-token-store-Ct7aTeR8.js';
|
|
4
5
|
import { j as json } from './index-lhTMmBNn.js';
|
|
5
6
|
import 'child_process';
|
|
6
7
|
import 'jsonwebtoken';
|
|
7
8
|
import 'util';
|
|
8
9
|
import './error-DDXB3duW.js';
|
|
9
10
|
import 'crypto';
|
|
11
|
+
import 'better-sqlite3';
|
|
12
|
+
import 'fs';
|
|
13
|
+
import 'path';
|
|
14
|
+
import './shooter-home-4f_HkdGI.js';
|
|
15
|
+
import 'os';
|
|
10
16
|
|
|
11
17
|
const GET = ({ request }) => {
|
|
12
18
|
const authError = validateAuth(request);
|
|
@@ -14,7 +20,9 @@ const GET = ({ request }) => {
|
|
|
14
20
|
return authError;
|
|
15
21
|
}
|
|
16
22
|
const apnsClient = new LibraryAPNsService();
|
|
17
|
-
const
|
|
23
|
+
const apnsEnv = private_env.APNS_PRODUCTION === "true" ? "production" : "sandbox";
|
|
24
|
+
const iosDevices = deviceTokenStore.listActiveForEnv("ios", apnsEnv);
|
|
25
|
+
const deviceToken = iosDevices[0]?.token ?? private_env.DEVICE_TOKEN?.trim() ?? "";
|
|
18
26
|
return json({
|
|
19
27
|
apns: {
|
|
20
28
|
configured: apnsClient.isConfigured(),
|
|
@@ -31,9 +39,13 @@ const GET = ({ request }) => {
|
|
|
31
39
|
},
|
|
32
40
|
environment: private_env.NODE_ENV || "development",
|
|
33
41
|
hasApiKey: !!private_env.API_KEY,
|
|
42
|
+
registeredDevices: {
|
|
43
|
+
android: deviceTokenStore.listActive("android").length,
|
|
44
|
+
ios: iosDevices.length
|
|
45
|
+
},
|
|
34
46
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
35
47
|
});
|
|
36
48
|
};
|
|
37
49
|
|
|
38
50
|
export { GET };
|
|
39
|
-
//# sourceMappingURL=_server.ts-
|
|
51
|
+
//# sourceMappingURL=_server.ts-BSS8cO80.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_server.ts-BSS8cO80.js","sources":["../../../.svelte-kit/adapter-node/entries/endpoints/api/debug/_server.ts.js"],"sourcesContent":["import { b as private_env } from \"../../../../chunks/shared-server.js\";\nimport { L as LibraryAPNsService } from \"../../../../chunks/library-apns.js\";\nimport { v as validateAuth } from \"../../../../chunks/auth.js\";\nimport { d as deviceTokenStore } from \"../../../../chunks/device-token-store.js\";\nimport { json } from \"@sveltejs/kit\";\nconst GET = ({ request }) => {\n const authError = validateAuth(request);\n if (authError) {\n return authError;\n }\n const apnsClient = new LibraryAPNsService();\n const apnsEnv = private_env.APNS_PRODUCTION === \"true\" ? \"production\" : \"sandbox\";\n const iosDevices = deviceTokenStore.listActiveForEnv(\"ios\", apnsEnv);\n const deviceToken = iosDevices[0]?.token ?? private_env.DEVICE_TOKEN?.trim() ?? \"\";\n return json({\n apns: {\n configured: apnsClient.isConfigured(),\n environment: private_env.APNS_PRODUCTION === \"true\" ? \"production\" : \"sandbox\",\n hasBundleId: !!private_env.APNS_BUNDLE_ID,\n hasKey: !!private_env.APNS_KEY,\n hasKeyId: !!private_env.APNS_KEY_ID,\n hasTeamId: !!private_env.APNS_TEAM_ID\n },\n deviceToken: {\n exists: !!deviceToken,\n length: deviceToken ? deviceToken.length : 0,\n valid: deviceToken ? /^[a-f0-9]{64}$/i.test(deviceToken) : false\n },\n environment: private_env.NODE_ENV || \"development\",\n hasApiKey: !!private_env.API_KEY,\n registeredDevices: {\n android: deviceTokenStore.listActive(\"android\").length,\n ios: iosDevices.length\n },\n timestamp: (/* @__PURE__ */ new Date()).toISOString()\n });\n};\nexport {\n GET\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAKK,MAAC,GAAG,GAAG,CAAC,EAAE,OAAO,EAAE,KAAK;AAC7B,EAAE,MAAM,SAAS,GAAG,YAAY,CAAC,OAAO,CAAC;AACzC,EAAE,IAAI,SAAS,EAAE;AACjB,IAAI,OAAO,SAAS;AACpB,EAAE;AACF,EAAE,MAAM,UAAU,GAAG,IAAI,kBAAkB,EAAE;AAC7C,EAAE,MAAM,OAAO,GAAG,WAAW,CAAC,eAAe,KAAK,MAAM,GAAG,YAAY,GAAG,SAAS;AACnF,EAAE,MAAM,UAAU,GAAG,gBAAgB,CAAC,gBAAgB,CAAC,KAAK,EAAE,OAAO,CAAC;AACtE,EAAE,MAAM,WAAW,GAAG,UAAU,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,WAAW,CAAC,YAAY,EAAE,IAAI,EAAE,IAAI,EAAE;AACpF,EAAE,OAAO,IAAI,CAAC;AACd,IAAI,IAAI,EAAE;AACV,MAAM,UAAU,EAAE,UAAU,CAAC,YAAY,EAAE;AAC3C,MAAM,WAAW,EAAE,WAAW,CAAC,eAAe,KAAK,MAAM,GAAG,YAAY,GAAG,SAAS;AACpF,MAAM,WAAW,EAAE,CAAC,CAAC,WAAW,CAAC,cAAc;AAC/C,MAAM,MAAM,EAAE,CAAC,CAAC,WAAW,CAAC,QAAQ;AACpC,MAAM,QAAQ,EAAE,CAAC,CAAC,WAAW,CAAC,WAAW;AACzC,MAAM,SAAS,EAAE,CAAC,CAAC,WAAW,CAAC;AAC/B,KAAK;AACL,IAAI,WAAW,EAAE;AACjB,MAAM,MAAM,EAAE,CAAC,CAAC,WAAW;AAC3B,MAAM,MAAM,EAAE,WAAW,GAAG,WAAW,CAAC,MAAM,GAAG,CAAC;AAClD,MAAM,KAAK,EAAE,WAAW,GAAG,iBAAiB,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG;AACjE,KAAK;AACL,IAAI,WAAW,EAAE,WAAW,CAAC,QAAQ,IAAI,aAAa;AACtD,IAAI,SAAS,EAAE,CAAC,CAAC,WAAW,CAAC,OAAO;AACpC,IAAI,iBAAiB,EAAE;AACvB,MAAM,OAAO,EAAE,gBAAgB,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,MAAM;AAC5D,MAAM,GAAG,EAAE,UAAU,CAAC;AACtB,KAAK;AACL,IAAI,SAAS,EAAE,iBAAiB,IAAI,IAAI,EAAE,EAAE,WAAW;AACvD,GAAG,CAAC;AACJ;;;;"}
|