@waiaas/push-relay 2.9.0-rc.8 → 2.9.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/dist/bin.d.ts.map +1 -1
- package/dist/bin.js +39 -8
- package/dist/bin.js.map +1 -1
- package/dist/message-router.d.ts +15 -0
- package/dist/message-router.d.ts.map +1 -0
- package/dist/message-router.js +32 -0
- package/dist/message-router.js.map +1 -0
- package/dist/registry/device-registry.d.ts +8 -1
- package/dist/registry/device-registry.d.ts.map +1 -1
- package/dist/registry/device-registry.js +69 -3
- package/dist/registry/device-registry.js.map +1 -1
- package/dist/registry/device-routes.d.ts +2 -0
- package/dist/registry/device-routes.d.ts.map +1 -1
- package/dist/registry/device-routes.js +23 -5
- package/dist/registry/device-routes.js.map +1 -1
- package/dist/server.d.ts +2 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +2 -2
- package/dist/server.js.map +1 -1
- package/dist/subscriber/message-parser.d.ts +8 -0
- package/dist/subscriber/message-parser.d.ts.map +1 -1
- package/dist/subscriber/message-parser.js.map +1 -1
- package/dist/subscriber/ntfy-subscriber.d.ts +18 -1
- package/dist/subscriber/ntfy-subscriber.d.ts.map +1 -1
- package/dist/subscriber/ntfy-subscriber.js +142 -35
- package/dist/subscriber/ntfy-subscriber.js.map +1 -1
- package/package.json +2 -2
package/dist/bin.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bin.d.ts","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"bin.d.ts","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AAkBA,eAAO,MAAM,OAAO,EAAE,MAAoB,CAAC"}
|
package/dist/bin.js
CHANGED
|
@@ -9,6 +9,7 @@ import { PushwooshProvider } from './providers/pushwoosh-provider.js';
|
|
|
9
9
|
import { FcmProvider } from './providers/fcm-provider.js';
|
|
10
10
|
import { ConfigurablePayloadTransformer } from './transformer/payload-transformer.js';
|
|
11
11
|
import { createServer } from './server.js';
|
|
12
|
+
import { routeByTopic } from './message-router.js';
|
|
12
13
|
const require = createRequire(import.meta.url);
|
|
13
14
|
const pkg = require('../package.json');
|
|
14
15
|
export const VERSION = pkg.version;
|
|
@@ -53,16 +54,32 @@ async function main() {
|
|
|
53
54
|
notifyTopicPrefix: config.relay.notify_topic_prefix,
|
|
54
55
|
walletNames: config.relay.wallet_names,
|
|
55
56
|
transformer,
|
|
56
|
-
onMessage: async (walletName, payload) => {
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
onMessage: async (walletName, payload, topic) => {
|
|
58
|
+
console.log(`[push-relay] Received ${payload.category} for wallet "${walletName}" on topic "${topic}" (title=${payload.title ?? 'none'})`);
|
|
59
|
+
const route = routeByTopic(walletName, topic, config.relay.sign_topic_prefix, config.relay.notify_topic_prefix, (token) => registry.getBySubscriptionToken(token));
|
|
60
|
+
if (route.action === 'skip_base') {
|
|
61
|
+
console.log(`[push-relay] Base topic "${topic}" — skipping push (no broadcast)`);
|
|
59
62
|
return;
|
|
60
|
-
const result = await provider.send(tokens, payload);
|
|
61
|
-
if (result.invalidTokens.length > 0) {
|
|
62
|
-
registry.removeTokens(result.invalidTokens);
|
|
63
|
-
console.log(`[push-relay] Removed ${result.invalidTokens.length} invalid token(s)`);
|
|
64
63
|
}
|
|
65
|
-
|
|
64
|
+
if (route.action === 'skip_unknown') {
|
|
65
|
+
console.log(`[push-relay] Cannot extract subscriptionToken from topic "${topic}", skipping`);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (route.action === 'skip_no_device') {
|
|
69
|
+
console.log(`[push-relay] No device found for subscriptionToken "${route.subscriptionToken}", skipping`);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
try {
|
|
73
|
+
const result = await provider.send([route.device.pushToken], payload);
|
|
74
|
+
if (result.invalidTokens.length > 0) {
|
|
75
|
+
registry.removeTokens(result.invalidTokens);
|
|
76
|
+
console.log(`[push-relay] Removed ${result.invalidTokens.length} invalid token(s)`);
|
|
77
|
+
}
|
|
78
|
+
console.log(`[push-relay] ${payload.category} → ${walletName} (device=${route.subscriptionToken}): sent=${result.sent}, failed=${result.failed}`);
|
|
79
|
+
}
|
|
80
|
+
catch (sendErr) {
|
|
81
|
+
console.error(`[push-relay] Failed to send push to ${walletName} (device=${route.subscriptionToken}):`, sendErr.message);
|
|
82
|
+
}
|
|
66
83
|
},
|
|
67
84
|
onError: (err) => {
|
|
68
85
|
console.error('[push-relay] Error:', err.message);
|
|
@@ -71,6 +88,18 @@ async function main() {
|
|
|
71
88
|
// Start ntfy subscription
|
|
72
89
|
subscriber.start();
|
|
73
90
|
console.log(`[push-relay] Subscribing to ${config.relay.wallet_names.length} wallet(s): ${config.relay.wallet_names.join(', ')}`);
|
|
91
|
+
// Restore subscription-token-based topics from DB
|
|
92
|
+
const devices = registry.listAll();
|
|
93
|
+
let restoredTopics = 0;
|
|
94
|
+
for (const device of devices) {
|
|
95
|
+
if (device.subscriptionToken) {
|
|
96
|
+
subscriber.addTopics(device.walletName, `${config.relay.sign_topic_prefix}-${device.walletName}-${device.subscriptionToken}`, `${config.relay.notify_topic_prefix}-${device.walletName}-${device.subscriptionToken}`);
|
|
97
|
+
restoredTopics++;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (restoredTopics > 0) {
|
|
101
|
+
console.log(`[push-relay] Restored ${restoredTopics} device topic(s) from DB`);
|
|
102
|
+
}
|
|
74
103
|
// Create and start HTTP server
|
|
75
104
|
const app = createServer({
|
|
76
105
|
registry,
|
|
@@ -78,6 +107,8 @@ async function main() {
|
|
|
78
107
|
provider,
|
|
79
108
|
apiKey: config.relay.server.api_key,
|
|
80
109
|
ntfyServer: config.relay.ntfy_server,
|
|
110
|
+
signTopicPrefix: config.relay.sign_topic_prefix,
|
|
111
|
+
notifyTopicPrefix: config.relay.notify_topic_prefix,
|
|
81
112
|
version: VERSION,
|
|
82
113
|
});
|
|
83
114
|
const server = serve({
|
package/dist/bin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAE1D,OAAO,EAAE,8BAA8B,EAAE,MAAM,sCAAsC,CAAC;AAEtF,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { DeviceRecord } from './registry/device-registry.js';
|
|
2
|
+
export interface TopicRoutingResult {
|
|
3
|
+
action: 'skip_base' | 'skip_unknown' | 'skip_no_device' | 'unicast';
|
|
4
|
+
subscriptionToken?: string;
|
|
5
|
+
device?: DeviceRecord;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Determine routing for an incoming ntfy message based on its topic.
|
|
9
|
+
*
|
|
10
|
+
* - Base topics (waiaas-sign-{wallet}, waiaas-notify-{wallet}) → skip (no broadcast)
|
|
11
|
+
* - Device topics (waiaas-sign-{wallet}-{token}) → unicast to the matching device
|
|
12
|
+
* - Unknown topic format → skip
|
|
13
|
+
*/
|
|
14
|
+
export declare function routeByTopic(walletName: string, topic: string, signTopicPrefix: string, notifyTopicPrefix: string, getDevice: (subscriptionToken: string) => DeviceRecord | null): TopicRoutingResult;
|
|
15
|
+
//# sourceMappingURL=message-router.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-router.d.ts","sourceRoot":"","sources":["../src/message-router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAElE,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,WAAW,GAAG,cAAc,GAAG,gBAAgB,GAAG,SAAS,CAAC;IACpE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,EACb,eAAe,EAAE,MAAM,EACvB,iBAAiB,EAAE,MAAM,EACzB,SAAS,EAAE,CAAC,iBAAiB,EAAE,MAAM,KAAK,YAAY,GAAG,IAAI,GAC5D,kBAAkB,CA2BpB"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Determine routing for an incoming ntfy message based on its topic.
|
|
3
|
+
*
|
|
4
|
+
* - Base topics (waiaas-sign-{wallet}, waiaas-notify-{wallet}) → skip (no broadcast)
|
|
5
|
+
* - Device topics (waiaas-sign-{wallet}-{token}) → unicast to the matching device
|
|
6
|
+
* - Unknown topic format → skip
|
|
7
|
+
*/
|
|
8
|
+
export function routeByTopic(walletName, topic, signTopicPrefix, notifyTopicPrefix, getDevice) {
|
|
9
|
+
const signBase = `${signTopicPrefix}-${walletName}`;
|
|
10
|
+
const notifyBase = `${notifyTopicPrefix}-${walletName}`;
|
|
11
|
+
// Skip base topics — no broadcast
|
|
12
|
+
if (topic === signBase || topic === notifyBase) {
|
|
13
|
+
return { action: 'skip_base' };
|
|
14
|
+
}
|
|
15
|
+
// Extract subscriptionToken from device topic suffix
|
|
16
|
+
let subscriptionToken;
|
|
17
|
+
if (topic.startsWith(`${signBase}-`)) {
|
|
18
|
+
subscriptionToken = topic.slice(signBase.length + 1);
|
|
19
|
+
}
|
|
20
|
+
else if (topic.startsWith(`${notifyBase}-`)) {
|
|
21
|
+
subscriptionToken = topic.slice(notifyBase.length + 1);
|
|
22
|
+
}
|
|
23
|
+
if (!subscriptionToken) {
|
|
24
|
+
return { action: 'skip_unknown' };
|
|
25
|
+
}
|
|
26
|
+
const device = getDevice(subscriptionToken);
|
|
27
|
+
if (!device) {
|
|
28
|
+
return { action: 'skip_no_device', subscriptionToken };
|
|
29
|
+
}
|
|
30
|
+
return { action: 'unicast', subscriptionToken, device };
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=message-router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-router.js","sourceRoot":"","sources":["../src/message-router.ts"],"names":[],"mappings":"AAQA;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAC1B,UAAkB,EAClB,KAAa,EACb,eAAuB,EACvB,iBAAyB,EACzB,SAA6D;IAE7D,MAAM,QAAQ,GAAG,GAAG,eAAe,IAAI,UAAU,EAAE,CAAC;IACpD,MAAM,UAAU,GAAG,GAAG,iBAAiB,IAAI,UAAU,EAAE,CAAC;IAExD,kCAAkC;IAClC,IAAI,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,UAAU,EAAE,CAAC;QAC/C,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IACjC,CAAC;IAED,qDAAqD;IACrD,IAAI,iBAAqC,CAAC;IAC1C,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,QAAQ,GAAG,CAAC,EAAE,CAAC;QACrC,iBAAiB,GAAG,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACvD,CAAC;SAAM,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,UAAU,GAAG,CAAC,EAAE,CAAC;QAC9C,iBAAiB,GAAG,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACzD,CAAC;IAED,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACvB,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;IACpC,CAAC;IAED,MAAM,MAAM,GAAG,SAAS,CAAC,iBAAiB,CAAC,CAAC;IAC5C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,CAAC;IACzD,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,EAAE,CAAC;AAC1D,CAAC"}
|
|
@@ -2,6 +2,7 @@ export interface DeviceRecord {
|
|
|
2
2
|
pushToken: string;
|
|
3
3
|
walletName: string;
|
|
4
4
|
platform: 'ios' | 'android';
|
|
5
|
+
subscriptionToken: string | null;
|
|
5
6
|
createdAt: number;
|
|
6
7
|
updatedAt: number;
|
|
7
8
|
}
|
|
@@ -9,10 +10,16 @@ export declare class DeviceRegistry {
|
|
|
9
10
|
private readonly db;
|
|
10
11
|
constructor(dbPath: string);
|
|
11
12
|
private init;
|
|
12
|
-
register(walletName: string, pushToken: string, platform: 'ios' | 'android'):
|
|
13
|
+
register(walletName: string, pushToken: string, platform: 'ios' | 'android'): {
|
|
14
|
+
subscriptionToken: string;
|
|
15
|
+
};
|
|
16
|
+
getSubscriptionToken(pushToken: string): string | null;
|
|
13
17
|
unregister(pushToken: string): boolean;
|
|
14
18
|
getTokensByWalletName(walletName: string): string[];
|
|
15
19
|
removeTokens(tokens: string[]): void;
|
|
20
|
+
getByPushToken(pushToken: string): DeviceRecord | null;
|
|
21
|
+
getBySubscriptionToken(token: string): DeviceRecord | null;
|
|
22
|
+
listAll(): DeviceRecord[];
|
|
16
23
|
count(): number;
|
|
17
24
|
close(): void;
|
|
18
25
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"device-registry.d.ts","sourceRoot":"","sources":["../../src/registry/device-registry.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"device-registry.d.ts","sourceRoot":"","sources":["../../src/registry/device-registry.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,KAAK,GAAG,SAAS,CAAC;IAC5B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAoB;gBAE3B,MAAM,EAAE,MAAM;IAO1B,OAAO,CAAC,IAAI;IAuBZ,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,GAAG,SAAS,GAAG;QAAE,iBAAiB,EAAE,MAAM,CAAA;KAAE;IAkB3G,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAMtD,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAKtC,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE;IAOnD,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI;IAMpC,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI;IAmBtD,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI;IAmB1D,OAAO,IAAI,YAAY,EAAE;IAkBzB,KAAK,IAAI,MAAM;IAKf,KAAK,IAAI,IAAI;CAGd"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import Database from 'better-sqlite3';
|
|
2
|
+
import { randomBytes } from 'node:crypto';
|
|
2
3
|
export class DeviceRegistry {
|
|
3
4
|
db;
|
|
4
5
|
constructor(dbPath) {
|
|
@@ -13,6 +14,7 @@ export class DeviceRegistry {
|
|
|
13
14
|
push_token TEXT PRIMARY KEY,
|
|
14
15
|
wallet_name TEXT NOT NULL,
|
|
15
16
|
platform TEXT NOT NULL CHECK (platform IN ('ios', 'android')),
|
|
17
|
+
subscription_token TEXT,
|
|
16
18
|
created_at INTEGER NOT NULL DEFAULT (unixepoch()),
|
|
17
19
|
updated_at INTEGER NOT NULL DEFAULT (unixepoch())
|
|
18
20
|
)
|
|
@@ -20,17 +22,35 @@ export class DeviceRegistry {
|
|
|
20
22
|
this.db.exec(`
|
|
21
23
|
CREATE INDEX IF NOT EXISTS idx_devices_wallet_name ON devices(wallet_name)
|
|
22
24
|
`);
|
|
25
|
+
// Migration: add subscription_token column if missing (existing DBs)
|
|
26
|
+
// SQLite does not allow UNIQUE constraint in ALTER TABLE ADD COLUMN
|
|
27
|
+
const cols = this.db.prepare("PRAGMA table_info('devices')").all().map(c => c.name);
|
|
28
|
+
if (!cols.includes('subscription_token')) {
|
|
29
|
+
this.db.exec(`ALTER TABLE devices ADD COLUMN subscription_token TEXT`);
|
|
30
|
+
}
|
|
31
|
+
this.db.exec(`CREATE UNIQUE INDEX IF NOT EXISTS idx_devices_subscription_token ON devices(subscription_token)`);
|
|
23
32
|
}
|
|
24
33
|
register(walletName, pushToken, platform) {
|
|
25
34
|
const now = Math.floor(Date.now() / 1000);
|
|
35
|
+
const newToken = randomBytes(4).toString('hex');
|
|
26
36
|
this.db.prepare(`
|
|
27
|
-
INSERT INTO devices (push_token, wallet_name, platform, created_at, updated_at)
|
|
28
|
-
VALUES (?, ?, ?, ?, ?)
|
|
37
|
+
INSERT INTO devices (push_token, wallet_name, platform, subscription_token, created_at, updated_at)
|
|
38
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
29
39
|
ON CONFLICT(push_token) DO UPDATE SET
|
|
30
40
|
wallet_name = excluded.wallet_name,
|
|
31
41
|
platform = excluded.platform,
|
|
42
|
+
subscription_token = COALESCE(devices.subscription_token, excluded.subscription_token),
|
|
32
43
|
updated_at = excluded.updated_at
|
|
33
|
-
`).run(pushToken, walletName, platform, now, now);
|
|
44
|
+
`).run(pushToken, walletName, platform, newToken, now, now);
|
|
45
|
+
// Retrieve the actual token (may be the existing one on conflict)
|
|
46
|
+
const row = this.db.prepare('SELECT subscription_token FROM devices WHERE push_token = ?')
|
|
47
|
+
.get(pushToken);
|
|
48
|
+
return { subscriptionToken: row.subscription_token };
|
|
49
|
+
}
|
|
50
|
+
getSubscriptionToken(pushToken) {
|
|
51
|
+
const row = this.db.prepare('SELECT subscription_token FROM devices WHERE push_token = ?')
|
|
52
|
+
.get(pushToken);
|
|
53
|
+
return row?.subscription_token ?? null;
|
|
34
54
|
}
|
|
35
55
|
unregister(pushToken) {
|
|
36
56
|
const result = this.db.prepare('DELETE FROM devices WHERE push_token = ?').run(pushToken);
|
|
@@ -48,6 +68,52 @@ export class DeviceRegistry {
|
|
|
48
68
|
const placeholders = tokens.map(() => '?').join(',');
|
|
49
69
|
this.db.prepare(`DELETE FROM devices WHERE push_token IN (${placeholders})`).run(...tokens);
|
|
50
70
|
}
|
|
71
|
+
getByPushToken(pushToken) {
|
|
72
|
+
const row = this.db.prepare(`
|
|
73
|
+
SELECT push_token, wallet_name, platform, subscription_token, created_at, updated_at
|
|
74
|
+
FROM devices WHERE push_token = ?
|
|
75
|
+
`).get(pushToken);
|
|
76
|
+
if (!row)
|
|
77
|
+
return null;
|
|
78
|
+
return {
|
|
79
|
+
pushToken: row.push_token,
|
|
80
|
+
walletName: row.wallet_name,
|
|
81
|
+
platform: row.platform,
|
|
82
|
+
subscriptionToken: row.subscription_token,
|
|
83
|
+
createdAt: row.created_at,
|
|
84
|
+
updatedAt: row.updated_at,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
getBySubscriptionToken(token) {
|
|
88
|
+
const row = this.db.prepare(`
|
|
89
|
+
SELECT push_token, wallet_name, platform, subscription_token, created_at, updated_at
|
|
90
|
+
FROM devices WHERE subscription_token = ?
|
|
91
|
+
`).get(token);
|
|
92
|
+
if (!row)
|
|
93
|
+
return null;
|
|
94
|
+
return {
|
|
95
|
+
pushToken: row.push_token,
|
|
96
|
+
walletName: row.wallet_name,
|
|
97
|
+
platform: row.platform,
|
|
98
|
+
subscriptionToken: row.subscription_token,
|
|
99
|
+
createdAt: row.created_at,
|
|
100
|
+
updatedAt: row.updated_at,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
listAll() {
|
|
104
|
+
const rows = this.db.prepare(`
|
|
105
|
+
SELECT push_token, wallet_name, platform, subscription_token, created_at, updated_at
|
|
106
|
+
FROM devices
|
|
107
|
+
`).all();
|
|
108
|
+
return rows.map((row) => ({
|
|
109
|
+
pushToken: row.push_token,
|
|
110
|
+
walletName: row.wallet_name,
|
|
111
|
+
platform: row.platform,
|
|
112
|
+
subscriptionToken: row.subscription_token,
|
|
113
|
+
createdAt: row.created_at,
|
|
114
|
+
updatedAt: row.updated_at,
|
|
115
|
+
}));
|
|
116
|
+
}
|
|
51
117
|
count() {
|
|
52
118
|
const row = this.db.prepare('SELECT COUNT(*) as count FROM devices').get();
|
|
53
119
|
return row.count;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"device-registry.js","sourceRoot":"","sources":["../../src/registry/device-registry.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"device-registry.js","sourceRoot":"","sources":["../../src/registry/device-registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,6 +6,8 @@ export interface DeviceRoutesOpts {
|
|
|
6
6
|
registry: DeviceRegistry;
|
|
7
7
|
subscriber: NtfySubscriber;
|
|
8
8
|
provider: IPushProvider;
|
|
9
|
+
signTopicPrefix: string;
|
|
10
|
+
notifyTopicPrefix: string;
|
|
9
11
|
version?: string;
|
|
10
12
|
}
|
|
11
13
|
export declare function createDeviceRoutes(opts: DeviceRoutesOpts): Hono;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"device-routes.d.ts","sourceRoot":"","sources":["../../src/registry/device-routes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAQnE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,cAAc,CAAC;IACzB,UAAU,EAAE,cAAc,CAAC;IAC3B,QAAQ,EAAE,aAAa,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,gBAAgB,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"device-routes.d.ts","sourceRoot":"","sources":["../../src/registry/device-routes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAQnE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,cAAc,CAAC;IACzB,UAAU,EAAE,cAAc,CAAC;IAC3B,QAAQ,EAAE,aAAa,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,gBAAgB,GAAG,IAAI,CA6E/D"}
|
|
@@ -7,7 +7,7 @@ const DeviceRegistrationSchema = z.object({
|
|
|
7
7
|
});
|
|
8
8
|
export function createDeviceRoutes(opts) {
|
|
9
9
|
const app = new Hono();
|
|
10
|
-
const { registry, subscriber, provider, version } = opts;
|
|
10
|
+
const { registry, subscriber, provider, signTopicPrefix, notifyTopicPrefix, version } = opts;
|
|
11
11
|
// POST /devices — register device token
|
|
12
12
|
app.post('/devices', async (c) => {
|
|
13
13
|
const body = await c.req.json();
|
|
@@ -16,16 +16,34 @@ export function createDeviceRoutes(opts) {
|
|
|
16
16
|
return c.json({ error: 'Invalid request', details: parsed.error.issues }, 400);
|
|
17
17
|
}
|
|
18
18
|
const { walletName, pushToken, platform } = parsed.data;
|
|
19
|
-
registry.register(walletName, pushToken, platform);
|
|
20
|
-
|
|
19
|
+
const result = registry.register(walletName, pushToken, platform);
|
|
20
|
+
const token = result.subscriptionToken;
|
|
21
|
+
// Dynamically subscribe to subscription-token-based topics
|
|
22
|
+
subscriber.addTopics(walletName, `${signTopicPrefix}-${walletName}-${token}`, `${notifyTopicPrefix}-${walletName}-${token}`);
|
|
23
|
+
return c.json({ status: 'registered', subscription_token: token }, 201);
|
|
24
|
+
});
|
|
25
|
+
// GET /devices/:token/subscription-token — get subscription token for a device
|
|
26
|
+
app.get('/devices/:token/subscription-token', (c) => {
|
|
27
|
+
const token = c.req.param('token');
|
|
28
|
+
const subToken = registry.getSubscriptionToken(token);
|
|
29
|
+
if (subToken === null) {
|
|
30
|
+
return c.json({ error: 'Device not found' }, 404);
|
|
31
|
+
}
|
|
32
|
+
return c.json({ subscription_token: subToken });
|
|
21
33
|
});
|
|
22
34
|
// DELETE /devices/:token — unregister device token
|
|
23
35
|
app.delete('/devices/:token', (c) => {
|
|
24
|
-
const
|
|
25
|
-
|
|
36
|
+
const pushToken = c.req.param('token');
|
|
37
|
+
// Look up device before deletion to get topic info
|
|
38
|
+
const device = registry.getByPushToken(pushToken);
|
|
39
|
+
const removed = registry.unregister(pushToken);
|
|
26
40
|
if (!removed) {
|
|
27
41
|
return c.json({ error: 'Token not found' }, 404);
|
|
28
42
|
}
|
|
43
|
+
// Dynamically unsubscribe from subscription-token-based topics
|
|
44
|
+
if (device?.subscriptionToken) {
|
|
45
|
+
subscriber.removeTopics(`${signTopicPrefix}-${device.walletName}-${device.subscriptionToken}`, `${notifyTopicPrefix}-${device.walletName}-${device.subscriptionToken}`);
|
|
46
|
+
}
|
|
29
47
|
return c.body(null, 204);
|
|
30
48
|
});
|
|
31
49
|
// GET /health — health check
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"device-routes.js","sourceRoot":"","sources":["../../src/registry/device-routes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,MAAM,wBAAwB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5B,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;CACrC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"device-routes.js","sourceRoot":"","sources":["../../src/registry/device-routes.ts"],"names":[],"mappings":"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"}
|
package/dist/server.d.ts
CHANGED
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAI5B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AACpE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAElE,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,cAAc,CAAC;IACzB,UAAU,EAAE,cAAc,CAAC;IAC3B,QAAQ,EAAE,aAAa,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAkBnD"}
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAI5B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AACpE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAElE,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,cAAc,CAAC;IACzB,UAAU,EAAE,cAAc,CAAC;IAC3B,QAAQ,EAAE,aAAa,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAkBnD"}
|
package/dist/server.js
CHANGED
|
@@ -4,9 +4,9 @@ import { createDeviceRoutes } from './registry/device-routes.js';
|
|
|
4
4
|
import { createSignResponseRoutes } from './relay/sign-response-routes.js';
|
|
5
5
|
export function createServer(opts) {
|
|
6
6
|
const app = new Hono();
|
|
7
|
-
const { registry, subscriber, provider, apiKey, ntfyServer, version } = opts;
|
|
7
|
+
const { registry, subscriber, provider, apiKey, ntfyServer, signTopicPrefix, notifyTopicPrefix, version } = opts;
|
|
8
8
|
// Health check is public
|
|
9
|
-
const deviceRoutes = createDeviceRoutes({ registry, subscriber, provider, version });
|
|
9
|
+
const deviceRoutes = createDeviceRoutes({ registry, subscriber, provider, signTopicPrefix, notifyTopicPrefix, version });
|
|
10
10
|
// Sign response relay (public — wallet apps call this without API key)
|
|
11
11
|
const signResponseRoutes = createSignResponseRoutes({ ntfyServer });
|
|
12
12
|
// Apply API key auth to device registration/deletion endpoints only
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAgB3E,MAAM,UAAU,YAAY,CAAC,IAAgB;IAC3C,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IACvB,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,eAAe,EAAE,iBAAiB,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAEjH,yBAAyB;IACzB,MAAM,YAAY,GAAG,kBAAkB,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,eAAe,EAAE,iBAAiB,EAAE,OAAO,EAAE,CAAC,CAAC;IAEzH,uEAAuE;IACvE,MAAM,kBAAkB,GAAG,wBAAwB,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC;IAEpE,oEAAoE;IACpE,GAAG,CAAC,GAAG,CAAC,YAAY,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;IAC1C,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;IAEzC,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IAC7B,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,kBAAkB,CAAC,CAAC;IAEnC,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -12,6 +12,14 @@ export interface ParsedNtfyMessage {
|
|
|
12
12
|
title?: string;
|
|
13
13
|
priority?: number;
|
|
14
14
|
tags?: string[];
|
|
15
|
+
/** Present when message exceeds ntfy size limit and is auto-converted to file attachment. */
|
|
16
|
+
attachment?: {
|
|
17
|
+
name: string;
|
|
18
|
+
type: string;
|
|
19
|
+
size: number;
|
|
20
|
+
expires: number;
|
|
21
|
+
url: string;
|
|
22
|
+
};
|
|
15
23
|
}
|
|
16
24
|
export declare function determineMessageType(topic: string, signPrefix: string, notifyPrefix: string): 'sign_request' | 'notification' | null;
|
|
17
25
|
export declare function mapPriority(ntfyPriority: number | undefined): 'high' | 'normal';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message-parser.d.ts","sourceRoot":"","sources":["../../src/subscriber/message-parser.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAErE,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,QAAQ,EAAE,cAAc,GAAG,cAAc,CAAC;IAC1C,QAAQ,EAAE,MAAM,GAAG,QAAQ,CAAC;CAC7B;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"message-parser.d.ts","sourceRoot":"","sources":["../../src/subscriber/message-parser.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAErE,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,QAAQ,EAAE,cAAc,GAAG,cAAc,CAAC;IAC1C,QAAQ,EAAE,MAAM,GAAG,QAAQ,CAAC;CAC7B;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,6FAA6F;IAC7F,UAAU,CAAC,EAAE;QACX,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,GAAG,EAAE,MAAM,CAAC;KACb,CAAC;CACH;AAED,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,GACnB,cAAc,GAAG,cAAc,GAAG,IAAI,CAIxC;AAED,wBAAgB,WAAW,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,QAAQ,CAE/E;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,CAI7D;AAED,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,mBAAmB,CAI7E;AAED,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,iBAAiB,EAC1B,IAAI,EAAE,cAAc,GAAG,cAAc,GACpC,WAAW,CAwBb"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message-parser.js","sourceRoot":"","sources":["../../src/subscriber/message-parser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"message-parser.js","sourceRoot":"","sources":["../../src/subscriber/message-parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,13 +5,20 @@ export interface NtfySubscriberOpts {
|
|
|
5
5
|
signTopicPrefix: string;
|
|
6
6
|
notifyTopicPrefix: string;
|
|
7
7
|
walletNames: string[];
|
|
8
|
-
onMessage: (walletName: string, payload: PushPayload) => Promise<void>;
|
|
8
|
+
onMessage: (walletName: string, payload: PushPayload, topic: string) => Promise<void>;
|
|
9
9
|
onError?: (error: Error) => void;
|
|
10
10
|
transformer?: IPayloadTransformer;
|
|
11
|
+
/** Per-wallet topic overrides (key: walletName). When set, uses these topics instead of prefix pattern. */
|
|
12
|
+
topicOverrides?: Map<string, {
|
|
13
|
+
signTopic: string;
|
|
14
|
+
notifyTopic: string;
|
|
15
|
+
}>;
|
|
11
16
|
}
|
|
12
17
|
export declare class NtfySubscriber {
|
|
13
18
|
private readonly opts;
|
|
14
19
|
private readonly abortControllers;
|
|
20
|
+
/** Reverse mapping: topic → walletName */
|
|
21
|
+
private readonly topicWalletMap;
|
|
15
22
|
private readonly transformer?;
|
|
16
23
|
private _connected;
|
|
17
24
|
private _topicCount;
|
|
@@ -19,9 +26,19 @@ export declare class NtfySubscriber {
|
|
|
19
26
|
get connected(): boolean;
|
|
20
27
|
get topicCount(): number;
|
|
21
28
|
start(): void;
|
|
29
|
+
/** Dynamically add topics for a wallet (e.g. on device registration). */
|
|
30
|
+
addTopics(walletName: string, signTopic: string, notifyTopic: string): void;
|
|
31
|
+
/** Dynamically remove topics (e.g. on device unregistration). */
|
|
32
|
+
removeTopics(signTopic: string, notifyTopic: string): void;
|
|
22
33
|
stop(): Promise<void>;
|
|
23
34
|
private subscribeTopic;
|
|
24
35
|
private connectSse;
|
|
36
|
+
/**
|
|
37
|
+
* Download ntfy file attachment and process as normal message.
|
|
38
|
+
* When message payload exceeds ntfy's size limit (~4KB), ntfy auto-converts
|
|
39
|
+
* to a file attachment. The attachment contains the original request JSON body.
|
|
40
|
+
*/
|
|
41
|
+
private fetchAttachmentAndProcess;
|
|
25
42
|
private delay;
|
|
26
43
|
}
|
|
27
44
|
//# sourceMappingURL=ntfy-subscriber.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ntfy-subscriber.d.ts","sourceRoot":"","sources":["../../src/subscriber/ntfy-subscriber.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAqB,MAAM,qBAAqB,CAAC;AAE1E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uCAAuC,CAAC;
|
|
1
|
+
{"version":3,"file":"ntfy-subscriber.d.ts","sourceRoot":"","sources":["../../src/subscriber/ntfy-subscriber.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAqB,MAAM,qBAAqB,CAAC;AAE1E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uCAAuC,CAAC;AASjF,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,SAAS,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtF,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,WAAW,CAAC,EAAE,mBAAmB,CAAC;IAClC,2GAA2G;IAC3G,cAAc,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC1E;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAqB;IAC1C,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAsC;IACvE,0CAA0C;IAC1C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA6B;IAC5D,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAsB;IACnD,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,WAAW,CAAK;gBAEZ,IAAI,EAAE,kBAAkB;IAKpC,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED,KAAK,IAAI,IAAI;IAab,yEAAyE;IACzE,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI;IAW3E,iEAAiE;IACjE,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI;IAepD,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAS3B,OAAO,CAAC,cAAc;YAOR,UAAU;IAyHxB;;;;OAIG;YACW,yBAAyB;IA2CvC,OAAO,CAAC,KAAK;CAQd"}
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import { buildPushPayload, determineMessageType } from './message-parser.js';
|
|
2
|
+
import { get as httpsGet } from 'node:https';
|
|
3
|
+
import { get as httpGet } from 'node:http';
|
|
4
|
+
import { createUnzip, createBrotliDecompress } from 'node:zlib';
|
|
2
5
|
const MAX_RECONNECT_DELAY_MS = 60_000;
|
|
3
6
|
const INITIAL_RECONNECT_DELAY_MS = 1_000;
|
|
4
7
|
export class NtfySubscriber {
|
|
5
8
|
opts;
|
|
6
9
|
abortControllers = new Map();
|
|
10
|
+
/** Reverse mapping: topic → walletName */
|
|
11
|
+
topicWalletMap = new Map();
|
|
7
12
|
transformer;
|
|
8
13
|
_connected = false;
|
|
9
14
|
_topicCount = 0;
|
|
@@ -19,24 +24,53 @@ export class NtfySubscriber {
|
|
|
19
24
|
}
|
|
20
25
|
start() {
|
|
21
26
|
for (const walletName of this.opts.walletNames) {
|
|
22
|
-
const
|
|
23
|
-
const
|
|
27
|
+
const override = this.opts.topicOverrides?.get(walletName);
|
|
28
|
+
const signTopic = override?.signTopic ?? `${this.opts.signTopicPrefix}-${walletName}`;
|
|
29
|
+
const notifyTopic = override?.notifyTopic ?? `${this.opts.notifyTopicPrefix}-${walletName}`;
|
|
24
30
|
this.subscribeTopic(signTopic, walletName);
|
|
25
31
|
this.subscribeTopic(notifyTopic, walletName);
|
|
26
32
|
}
|
|
27
33
|
this._topicCount = this.opts.walletNames.length * 2;
|
|
28
34
|
this._connected = true;
|
|
29
35
|
}
|
|
36
|
+
/** Dynamically add topics for a wallet (e.g. on device registration). */
|
|
37
|
+
addTopics(walletName, signTopic, notifyTopic) {
|
|
38
|
+
if (!this.abortControllers.has(signTopic)) {
|
|
39
|
+
this.subscribeTopic(signTopic, walletName);
|
|
40
|
+
this._topicCount++;
|
|
41
|
+
}
|
|
42
|
+
if (!this.abortControllers.has(notifyTopic)) {
|
|
43
|
+
this.subscribeTopic(notifyTopic, walletName);
|
|
44
|
+
this._topicCount++;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/** Dynamically remove topics (e.g. on device unregistration). */
|
|
48
|
+
removeTopics(signTopic, notifyTopic) {
|
|
49
|
+
if (this.abortControllers.has(signTopic)) {
|
|
50
|
+
this.abortControllers.get(signTopic).abort();
|
|
51
|
+
this.abortControllers.delete(signTopic);
|
|
52
|
+
this.topicWalletMap.delete(signTopic);
|
|
53
|
+
this._topicCount--;
|
|
54
|
+
}
|
|
55
|
+
if (this.abortControllers.has(notifyTopic)) {
|
|
56
|
+
this.abortControllers.get(notifyTopic).abort();
|
|
57
|
+
this.abortControllers.delete(notifyTopic);
|
|
58
|
+
this.topicWalletMap.delete(notifyTopic);
|
|
59
|
+
this._topicCount--;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
30
62
|
async stop() {
|
|
31
63
|
this._connected = false;
|
|
32
64
|
for (const [, controller] of this.abortControllers) {
|
|
33
65
|
controller.abort();
|
|
34
66
|
}
|
|
35
67
|
this.abortControllers.clear();
|
|
68
|
+
this.topicWalletMap.clear();
|
|
36
69
|
}
|
|
37
70
|
subscribeTopic(topic, walletName) {
|
|
38
71
|
const controller = new AbortController();
|
|
39
72
|
this.abortControllers.set(topic, controller);
|
|
73
|
+
this.topicWalletMap.set(topic, walletName);
|
|
40
74
|
void this.connectSse(topic, walletName, controller, INITIAL_RECONNECT_DELAY_MS);
|
|
41
75
|
}
|
|
42
76
|
async connectSse(topic, walletName, controller, reconnectDelay) {
|
|
@@ -44,47 +78,83 @@ export class NtfySubscriber {
|
|
|
44
78
|
return;
|
|
45
79
|
try {
|
|
46
80
|
const url = `${this.opts.ntfyServer}/${topic}/sse`;
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
81
|
+
const isHttps = url.startsWith('https');
|
|
82
|
+
const getter = isHttps ? httpsGet : httpGet;
|
|
83
|
+
const res = await new Promise((resolve, reject) => {
|
|
84
|
+
const req = getter(url, {
|
|
85
|
+
headers: {
|
|
86
|
+
'Accept': 'text/event-stream',
|
|
87
|
+
'Accept-Encoding': 'identity',
|
|
88
|
+
},
|
|
89
|
+
}, resolve);
|
|
90
|
+
req.on('error', reject);
|
|
91
|
+
controller.signal.addEventListener('abort', () => req.destroy(), { once: true });
|
|
92
|
+
});
|
|
93
|
+
if (!res.statusCode || res.statusCode < 200 || res.statusCode >= 300) {
|
|
94
|
+
res.resume(); // Drain
|
|
95
|
+
throw new Error(`SSE connection failed for ${topic}: HTTP ${String(res.statusCode)}`);
|
|
50
96
|
}
|
|
51
97
|
// Reset reconnect delay on successful connection
|
|
52
98
|
const nextDelay = INITIAL_RECONNECT_DELAY_MS;
|
|
53
|
-
|
|
54
|
-
|
|
99
|
+
// Explicit decompression based on Content-Encoding header.
|
|
100
|
+
// node:http does NOT auto-decompress, giving us full control.
|
|
101
|
+
const encoding = res.headers['content-encoding'];
|
|
102
|
+
let dataStream = res;
|
|
103
|
+
if (encoding === 'gzip' || encoding === 'x-gzip' || encoding === 'deflate') {
|
|
104
|
+
dataStream = res.pipe(createUnzip());
|
|
105
|
+
}
|
|
106
|
+
else if (encoding === 'br') {
|
|
107
|
+
dataStream = res.pipe(createBrotliDecompress());
|
|
108
|
+
}
|
|
109
|
+
// Wire abort to destroy streams
|
|
110
|
+
controller.signal.addEventListener('abort', () => {
|
|
111
|
+
res.destroy();
|
|
112
|
+
}, { once: true });
|
|
113
|
+
// SSE line-based parsing via Node.js Readable events
|
|
55
114
|
let buffer = '';
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
continue;
|
|
66
|
-
const dataStr = line.slice(6).trim();
|
|
67
|
-
if (!dataStr)
|
|
68
|
-
continue;
|
|
69
|
-
try {
|
|
70
|
-
const ntfyMsg = JSON.parse(dataStr);
|
|
71
|
-
if (!ntfyMsg.message)
|
|
115
|
+
await new Promise((resolve, reject) => {
|
|
116
|
+
dataStream.on('data', (chunk) => {
|
|
117
|
+
if (controller.signal.aborted)
|
|
118
|
+
return;
|
|
119
|
+
buffer += chunk.toString('utf-8');
|
|
120
|
+
const lines = buffer.split('\n');
|
|
121
|
+
buffer = lines.pop() ?? '';
|
|
122
|
+
for (const line of lines) {
|
|
123
|
+
if (!line.startsWith('data: '))
|
|
72
124
|
continue;
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
if (!type)
|
|
125
|
+
const dataStr = line.slice(6).trim();
|
|
126
|
+
if (!dataStr)
|
|
76
127
|
continue;
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
128
|
+
try {
|
|
129
|
+
const ntfyMsg = JSON.parse(dataStr);
|
|
130
|
+
if (!ntfyMsg.message)
|
|
131
|
+
continue;
|
|
132
|
+
// ntfy converts messages exceeding size limit to file attachments.
|
|
133
|
+
// Download the attachment to recover the original message. (#243)
|
|
134
|
+
if (ntfyMsg.attachment?.url) {
|
|
135
|
+
void this.fetchAttachmentAndProcess(ntfyMsg, walletName, topic);
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
const effectiveTopic = ntfyMsg.topic ?? topic;
|
|
139
|
+
const type = determineMessageType(effectiveTopic, this.opts.signTopicPrefix, this.opts.notifyTopicPrefix);
|
|
140
|
+
if (!type)
|
|
141
|
+
continue;
|
|
142
|
+
let payload = buildPushPayload(ntfyMsg, type);
|
|
143
|
+
if (this.transformer) {
|
|
144
|
+
payload = this.transformer.transform(payload);
|
|
145
|
+
}
|
|
146
|
+
void this.opts.onMessage(walletName, payload, effectiveTopic);
|
|
147
|
+
}
|
|
148
|
+
catch (err) {
|
|
149
|
+
this.opts.onError?.(err instanceof Error ? err : new Error(String(err)));
|
|
80
150
|
}
|
|
81
|
-
await this.opts.onMessage(walletName, payload);
|
|
82
|
-
}
|
|
83
|
-
catch (err) {
|
|
84
|
-
this.opts.onError?.(err instanceof Error ? err : new Error(String(err)));
|
|
85
151
|
}
|
|
86
|
-
}
|
|
87
|
-
|
|
152
|
+
});
|
|
153
|
+
dataStream.on('end', () => resolve());
|
|
154
|
+
dataStream.on('error', (err) => reject(err));
|
|
155
|
+
// Also resolve if the original response ends/closes
|
|
156
|
+
res.on('close', () => resolve());
|
|
157
|
+
});
|
|
88
158
|
// Stream ended normally — reconnect
|
|
89
159
|
if (!controller.signal.aborted) {
|
|
90
160
|
await this.delay(nextDelay);
|
|
@@ -101,6 +171,43 @@ export class NtfySubscriber {
|
|
|
101
171
|
return this.connectSse(topic, walletName, controller, nextDelay);
|
|
102
172
|
}
|
|
103
173
|
}
|
|
174
|
+
/**
|
|
175
|
+
* Download ntfy file attachment and process as normal message.
|
|
176
|
+
* When message payload exceeds ntfy's size limit (~4KB), ntfy auto-converts
|
|
177
|
+
* to a file attachment. The attachment contains the original request JSON body.
|
|
178
|
+
*/
|
|
179
|
+
async fetchAttachmentAndProcess(ntfyMsg, walletName, topic) {
|
|
180
|
+
try {
|
|
181
|
+
const res = await fetch(ntfyMsg.attachment.url);
|
|
182
|
+
if (!res.ok) {
|
|
183
|
+
throw new Error(`Attachment download failed: HTTP ${String(res.status)}`);
|
|
184
|
+
}
|
|
185
|
+
const body = await res.json();
|
|
186
|
+
// The attachment contains the original ntfy request JSON body.
|
|
187
|
+
// Extract the encoded message field from it.
|
|
188
|
+
if (typeof body.message === 'string') {
|
|
189
|
+
ntfyMsg.message = body.message;
|
|
190
|
+
}
|
|
191
|
+
if (typeof body.title === 'string' && !ntfyMsg.title) {
|
|
192
|
+
ntfyMsg.title = body.title;
|
|
193
|
+
}
|
|
194
|
+
if (typeof body.priority === 'number' && !ntfyMsg.priority) {
|
|
195
|
+
ntfyMsg.priority = body.priority;
|
|
196
|
+
}
|
|
197
|
+
const effectiveTopic = ntfyMsg.topic ?? topic;
|
|
198
|
+
const type = determineMessageType(effectiveTopic, this.opts.signTopicPrefix, this.opts.notifyTopicPrefix);
|
|
199
|
+
if (!type)
|
|
200
|
+
return;
|
|
201
|
+
let payload = buildPushPayload(ntfyMsg, type);
|
|
202
|
+
if (this.transformer) {
|
|
203
|
+
payload = this.transformer.transform(payload);
|
|
204
|
+
}
|
|
205
|
+
await this.opts.onMessage(walletName, payload, effectiveTopic);
|
|
206
|
+
}
|
|
207
|
+
catch (err) {
|
|
208
|
+
this.opts.onError?.(err instanceof Error ? err : new Error(String(err)));
|
|
209
|
+
}
|
|
210
|
+
}
|
|
104
211
|
delay(ms) {
|
|
105
212
|
return new Promise((resolve) => {
|
|
106
213
|
const timer = setTimeout(resolve, ms);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ntfy-subscriber.js","sourceRoot":"","sources":["../../src/subscriber/ntfy-subscriber.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"ntfy-subscriber.js","sourceRoot":"","sources":["../../src/subscriber/ntfy-subscriber.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@waiaas/push-relay",
|
|
3
|
-
"version": "2.9.0
|
|
3
|
+
"version": "2.9.0",
|
|
4
4
|
"description": "WAIaaS Push Relay Server - bridge ntfy topics to push notification services (Pushwoosh, FCM)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"hono": "^4.5.0",
|
|
42
42
|
"smol-toml": "^1.3.0",
|
|
43
43
|
"zod": "^3.24.0",
|
|
44
|
-
"@waiaas/core": "2.9.0
|
|
44
|
+
"@waiaas/core": "2.9.0"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@types/better-sqlite3": "^7.6.8",
|