agent-comms 8.15.26 → 9.0.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-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/dist/bridges/user/web/actions.d.ts +0 -8
- package/dist/bridges/user/web/actions.d.ts.map +1 -1
- package/dist/bridges/user/web/actions.js +0 -35
- package/dist/bridges/user/web/actions.js.map +1 -1
- package/dist/bridges/user/web/contract.d.ts +0 -19
- package/dist/bridges/user/web/contract.d.ts.map +1 -1
- package/dist/bridges/user/web/contract.js +0 -16
- package/dist/bridges/user/web/contract.js.map +1 -1
- package/dist/bridges/user/web/dist/bundle.js +1 -1
- package/dist/bridges/user/web/dist/mesh-worker.js +4 -4
- package/dist/bridges/user/web/dist/sw.js +1 -1
- package/dist/bridges/user/web/frontend/dispatch-action.d.ts +1 -1
- package/dist/bridges/user/web/frontend/dispatch-action.d.ts.map +1 -1
- package/dist/bridges/user/web/frontend/dispatch-action.js +0 -26
- package/dist/bridges/user/web/frontend/dispatch-action.js.map +1 -1
- package/dist/bridges/user/web/frontend/mesh-worker.d.ts.map +1 -1
- package/dist/bridges/user/web/frontend/mesh-worker.js +0 -6
- package/dist/bridges/user/web/frontend/mesh-worker.js.map +1 -1
- package/dist/bridges/user/web/frontend/sw.d.ts +1 -4
- package/dist/bridges/user/web/frontend/sw.d.ts.map +1 -1
- package/dist/bridges/user/web/frontend/sw.js +1 -54
- package/dist/bridges/user/web/frontend/sw.js.map +1 -1
- package/dist/bridges/user/web/frontend/tab-contract.d.ts +0 -19
- package/dist/bridges/user/web/frontend/tab-contract.d.ts.map +1 -1
- package/dist/bridges/user/web/router.d.ts +0 -21
- package/dist/bridges/user/web/router.d.ts.map +1 -1
- package/dist/bridges/user/web/router.js +1 -3
- package/dist/bridges/user/web/router.js.map +1 -1
- package/dist/bridges/user/web/server.d.ts +0 -2
- package/dist/bridges/user/web/server.d.ts.map +1 -1
- package/dist/bridges/user/web/server.js +2 -36
- package/dist/bridges/user/web/server.js.map +1 -1
- package/dist/bridges/user/web/test/contract.unit.test.js +3 -3
- package/dist/bridges/user/web/test/contract.unit.test.js.map +1 -1
- package/dist/bridges/user/web/test/web-server-unbuilt-frontend.integration.test.js +2 -2
- package/dist/bridges/user/web/test/web-server-unbuilt-frontend.integration.test.js.map +1 -1
- package/dist/bridges/user/web/test/web-server.integration.test.js +10 -0
- package/dist/bridges/user/web/test/web-server.integration.test.js.map +1 -1
- package/dist/core/index.d.ts +0 -4
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +0 -2
- package/dist/core/index.js.map +1 -1
- package/package.json +1 -1
- package/src/bridges/user/web/actions.ts +0 -43
- package/src/bridges/user/web/contract.ts +0 -22
- package/src/bridges/user/web/dist/bundle.js +1 -1
- package/src/bridges/user/web/dist/mesh-worker.js +4 -4
- package/src/bridges/user/web/dist/sw.js +1 -1
- package/src/bridges/user/web/router.ts +0 -12
- package/src/bridges/user/web/server.ts +2 -41
- package/src/core/index.ts +0 -4
- package/dist/core/push-manager.d.ts +0 -40
- package/dist/core/push-manager.d.ts.map +0 -1
- package/dist/core/push-manager.js +0 -60
- package/dist/core/push-manager.js.map +0 -1
- package/dist/core/vapid.d.ts +0 -22
- package/dist/core/vapid.d.ts.map +0 -1
- package/dist/core/vapid.js +0 -54
- package/dist/core/vapid.js.map +0 -1
- package/dist/core/web-push.d.ts +0 -37
- package/dist/core/web-push.d.ts.map +0 -1
- package/dist/core/web-push.js +0 -216
- package/dist/core/web-push.js.map +0 -1
- package/src/core/push-manager.ts +0 -76
- package/src/core/vapid.ts +0 -81
- package/src/core/web-push.ts +0 -322
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(){var e=`agent-comms-v1`,t=[{"revision":"
|
|
1
|
+
(function(){var e=`agent-comms-v1`,t=[{"revision":"194357f4b022a304e068ddaeeb4cf799","url":"mesh-worker.js"},{"revision":"f1ee3afb8c9e8f0d7315fd93d6457316","url":"index.html"},{"revision":"f1e3596f5e09029800e9862a7cb9335a","url":"bundle.js"}].map(e=>e.url);self.addEventListener(`install`,n=>{n.waitUntil(self.caches.open(e).then(async e=>e.addAll(t)).then(async()=>self.skipWaiting()))}),self.addEventListener(`activate`,t=>{t.waitUntil(self.caches.keys().then(async t=>Promise.all(t.filter(t=>t!==e).map(async e=>self.caches.delete(e)))))});var n=200,r=300;function i(e,t){return e.method===`GET`&&t.status>=n&&t.status<r}self.addEventListener(`fetch`,t=>{if(new URL(t.request.url).pathname.startsWith(`/api/`)){t.respondWith(fetch(t.request).then(n=>{if(i(t.request,n)){let r=n.clone();self.caches.open(e).then(async e=>e.put(t.request,r))}return n}).catch(async()=>self.caches.open(e).then(async e=>e.match(t.request)).then(e=>e??new Response(`Offline`,{status:503}))));return}t.respondWith(self.caches.open(e).then(async e=>e.match(t.request)).then(async n=>n||fetch(t.request).then(n=>{if(i(t.request,n)){let r=n.clone();self.caches.open(e).then(async e=>e.put(t.request,r))}return n})))})})();
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { implement } from "@orpc/server";
|
|
8
|
-
import type { PushManager } from "../../../core/push-manager.js";
|
|
9
8
|
import type { ChatController } from "../controller.js";
|
|
10
9
|
import {
|
|
11
10
|
createRoomAction,
|
|
@@ -18,8 +17,6 @@ import {
|
|
|
18
17
|
leaveRoomAction,
|
|
19
18
|
listAgentsAction,
|
|
20
19
|
listRoomsAction,
|
|
21
|
-
pushSubscribeAction,
|
|
22
|
-
pushUnsubscribeAction,
|
|
23
20
|
readRoomAction,
|
|
24
21
|
renameAgentAction,
|
|
25
22
|
sendAction,
|
|
@@ -37,7 +34,6 @@ import {
|
|
|
37
34
|
export interface MeshRouterContext {
|
|
38
35
|
controller: ChatController;
|
|
39
36
|
publisher: MeshEventPublisher;
|
|
40
|
-
pushManager: PushManager | undefined;
|
|
41
37
|
}
|
|
42
38
|
|
|
43
39
|
/** Drops deliveryQueues -- mesh-internal replay state for offline agents, not something a browser tab needs to see -- from a MeshStore snapshot before it goes out as a state_sync event. */
|
|
@@ -110,14 +106,6 @@ export const meshRouter = {
|
|
|
110
106
|
renameAgentAction(context.controller, input),
|
|
111
107
|
),
|
|
112
108
|
|
|
113
|
-
pushSubscribe: impl.pushSubscribe.handler(({ context, input }) =>
|
|
114
|
-
pushSubscribeAction(context.controller, context.pushManager, input),
|
|
115
|
-
),
|
|
116
|
-
|
|
117
|
-
pushUnsubscribe: impl.pushUnsubscribe.handler(({ context, input }) =>
|
|
118
|
-
pushUnsubscribeAction(context.controller, context.pushManager, input),
|
|
119
|
-
),
|
|
120
|
-
|
|
121
109
|
getRoomMessages: impl.getRoomMessages.handler(async ({ context, input }) =>
|
|
122
110
|
getRoomMessagesRead(context.controller, input),
|
|
123
111
|
),
|
|
@@ -12,7 +12,6 @@ import * as http from "node:http";
|
|
|
12
12
|
import { fileURLToPath } from "node:url";
|
|
13
13
|
import { WebSocketServer } from "ws";
|
|
14
14
|
import { RPCHandler } from "@orpc/server/websocket";
|
|
15
|
-
import { PushManager } from "../../../core/push-manager.js";
|
|
16
15
|
import { ChatController } from "../controller.js";
|
|
17
16
|
import type { MeshStore } from "../../../core/mesh-store.js";
|
|
18
17
|
import { CommsError } from "../../../core/store.js";
|
|
@@ -98,19 +97,6 @@ function frontendOrUnavailable(
|
|
|
98
97
|
}
|
|
99
98
|
}
|
|
100
99
|
|
|
101
|
-
// ---------------------------------------------------------------------------
|
|
102
|
-
// Active handles — needed so HTTP handlers can reach the PushManager
|
|
103
|
-
// ---------------------------------------------------------------------------
|
|
104
|
-
|
|
105
|
-
const activeHandles = new Set<WebServerHandle>();
|
|
106
|
-
|
|
107
|
-
function findHandle(controller: ChatController): WebServerHandle | undefined {
|
|
108
|
-
for (const handle of activeHandles) {
|
|
109
|
-
if (handle.controller === controller) return handle;
|
|
110
|
-
}
|
|
111
|
-
return undefined;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
100
|
// ---------------------------------------------------------------------------
|
|
115
101
|
// Types
|
|
116
102
|
// ---------------------------------------------------------------------------
|
|
@@ -119,7 +105,6 @@ export interface WebServerHandle {
|
|
|
119
105
|
server: http.Server;
|
|
120
106
|
controller: ChatController;
|
|
121
107
|
wss: WebSocketServer;
|
|
122
|
-
pushManager: PushManager;
|
|
123
108
|
publisher: MeshEventPublisher;
|
|
124
109
|
/** The address the server is bound to: loopback unless the operator opted into LAN reachability (AGENT_COMMS_WEB_HOST). */
|
|
125
110
|
host: string;
|
|
@@ -232,7 +217,6 @@ export async function createWebServer(options?: {
|
|
|
232
217
|
handleRequest(req, res, controller, webConsoleDist);
|
|
233
218
|
});
|
|
234
219
|
|
|
235
|
-
const pushManager = new PushManager();
|
|
236
220
|
const publisher = new MeshEventPublisher();
|
|
237
221
|
ensurePatchListener(controller.meshStore, publisher);
|
|
238
222
|
controller.on("message", (event: DeliveryEvent) => {
|
|
@@ -265,7 +249,7 @@ export async function createWebServer(options?: {
|
|
|
265
249
|
|
|
266
250
|
wss.on("connection", (ws) => {
|
|
267
251
|
// RPCHandler.upgrade() wants a DOM-shaped WebSocket (addEventListener's overload set), which "ws"'s own type declarations don't structurally satisfy (its addEventListener options param is narrower than DOM's) -- .message()/.close() accept the looser { send } shape "ws" does satisfy, and are the documented manual equivalent to .upgrade().
|
|
268
|
-
const context = { controller, publisher
|
|
252
|
+
const context = { controller, publisher };
|
|
269
253
|
ws.on("message", (data, isBinary) => {
|
|
270
254
|
// "ws" types incoming data as Buffer | ArrayBuffer | Buffer[] regardless of frame type; normalise to a real Buffer first so both branches below have a type they can trust rather than calling .toString()/Uint8Array.from() on a union that could be an ArrayBuffer.
|
|
271
255
|
const raw = Array.isArray(data) ? Buffer.concat(data) : data;
|
|
@@ -296,7 +280,7 @@ export async function createWebServer(options?: {
|
|
|
296
280
|
}
|
|
297
281
|
});
|
|
298
282
|
|
|
299
|
-
return { server, controller, wss,
|
|
283
|
+
return { server, controller, wss, publisher, host, accessToken };
|
|
300
284
|
}
|
|
301
285
|
|
|
302
286
|
function requestOf(req: http.IncomingMessage): {
|
|
@@ -375,25 +359,12 @@ function announceLanAccess(
|
|
|
375
359
|
});
|
|
376
360
|
}
|
|
377
361
|
|
|
378
|
-
class HandleRef {
|
|
379
|
-
constructor(public readonly handle: WebServerHandle) {
|
|
380
|
-
activeHandles.add(handle);
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
dispose(): void {
|
|
384
|
-
activeHandles.delete(this.handle);
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
|
|
388
362
|
// ---------------------------------------------------------------------------
|
|
389
363
|
// Standalone mode — `npx agent-comms chat`
|
|
390
364
|
// ---------------------------------------------------------------------------
|
|
391
365
|
|
|
392
366
|
export async function runWeb(userName: string, port = 0): Promise<void> {
|
|
393
367
|
const handle = await createWebServer({ port });
|
|
394
|
-
// Keep handle alive for cleanup — variable is intentionally unused
|
|
395
|
-
new HandleRef(handle);
|
|
396
|
-
|
|
397
368
|
handle.server.on("listening", () => {
|
|
398
369
|
console.log(
|
|
399
370
|
`Connected as ${userName} (user) [${handle.controller.agentId}]`,
|
|
@@ -515,16 +486,6 @@ function handleRequest(
|
|
|
515
486
|
}
|
|
516
487
|
}
|
|
517
488
|
|
|
518
|
-
// VAPID public key for push subscription
|
|
519
|
-
if (url.pathname === "/api/push/vapid-key" && req.method === "GET") {
|
|
520
|
-
// Lazy-initialise PushManager on first request — this endpoint
|
|
521
|
-
// is only hit from the frontend when push is supported.
|
|
522
|
-
const handle = findHandle(controller);
|
|
523
|
-
const key = handle?.pushManager.getPublicKey() ?? "";
|
|
524
|
-
json(res, { publicKey: key });
|
|
525
|
-
return;
|
|
526
|
-
}
|
|
527
|
-
|
|
528
489
|
// API routes
|
|
529
490
|
if (url.pathname === "/api/agents" && req.method === "GET") {
|
|
530
491
|
void (async () => {
|
package/src/core/index.ts
CHANGED
|
@@ -45,10 +45,6 @@ export {
|
|
|
45
45
|
MCP_TOOL_PARAMS,
|
|
46
46
|
} from "./bridge.js";
|
|
47
47
|
export type { RegistrationResult } from "./bridge.js";
|
|
48
|
-
export { generateVapidKeys } from "./vapid.js";
|
|
49
|
-
export type { VapidKeys } from "./vapid.js";
|
|
50
|
-
export { PushManager } from "./push-manager.js";
|
|
51
|
-
export type { PushSubscription, PushPayload } from "./web-push.js";
|
|
52
48
|
export { DiscoveryManager } from "./discovery.js";
|
|
53
49
|
export type {
|
|
54
50
|
DiscoveredMesh,
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Push subscription manager — tracks browser push subscriptions and
|
|
3
|
-
* dispatches Web Push notifications when agents are offline.
|
|
4
|
-
*
|
|
5
|
-
* The PushManager is a standalone module — MeshStore doesn't know about it.
|
|
6
|
-
* The web server bridge checks whether the target agent's WebSocket is
|
|
7
|
-
* disconnected and falls back to push when a subscription exists.
|
|
8
|
-
*/
|
|
9
|
-
import { type PushSubscription, type PushPayload } from "./web-push.js";
|
|
10
|
-
export declare class PushManager {
|
|
11
|
-
private readonly vapidKeys;
|
|
12
|
-
private readonly subject;
|
|
13
|
-
private readonly subscriptions;
|
|
14
|
-
constructor(subject?: string);
|
|
15
|
-
/**
|
|
16
|
-
* Register a push subscription for a given agent ID.
|
|
17
|
-
* Overwrites any existing subscription for the same agent.
|
|
18
|
-
*/
|
|
19
|
-
addSubscription(agentId: string, subscription: PushSubscription): void;
|
|
20
|
-
/**
|
|
21
|
-
* Remove a push subscription.
|
|
22
|
-
*/
|
|
23
|
-
removeSubscription(agentId: string): void;
|
|
24
|
-
/**
|
|
25
|
-
* Check whether a push subscription exists for the given agent.
|
|
26
|
-
*/
|
|
27
|
-
hasSubscription(agentId: string): boolean;
|
|
28
|
-
/**
|
|
29
|
-
* Send a push notification to a subscribed agent.
|
|
30
|
-
*
|
|
31
|
-
* No-ops silently if no subscription exists — callers should check
|
|
32
|
-
* hasSubscription() first if they need to distinguish the two cases.
|
|
33
|
-
*/
|
|
34
|
-
sendPush(agentId: string, payload: Readonly<PushPayload>): Promise<void>;
|
|
35
|
-
/**
|
|
36
|
-
* Get the VAPID public key for the PWA to use in `pushManager.subscribe()`.
|
|
37
|
-
*/
|
|
38
|
-
getPublicKey(): string;
|
|
39
|
-
}
|
|
40
|
-
//# sourceMappingURL=push-manager.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"push-manager.d.ts","sourceRoot":"","sources":["../../src/core/push-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,WAAW,EACjB,MAAM,eAAe,CAAC;AAMvB,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAY;IACtC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAuC;gBAEzD,OAAO,SAAiC;IAKpD;;;OAGG;IACH,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,gBAAgB,GAAG,IAAI;IAItE;;OAEG;IACH,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAIzC;;OAEG;IACH,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAIzC;;;;;OAKG;IACG,QAAQ,CACZ,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,QAAQ,CAAC,WAAW,CAAC,GAC7B,OAAO,CAAC,IAAI,CAAC;IAOhB;;OAEG;IACH,YAAY,IAAI,MAAM;CAGvB"}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Push subscription manager — tracks browser push subscriptions and
|
|
3
|
-
* dispatches Web Push notifications when agents are offline.
|
|
4
|
-
*
|
|
5
|
-
* The PushManager is a standalone module — MeshStore doesn't know about it.
|
|
6
|
-
* The web server bridge checks whether the target agent's WebSocket is
|
|
7
|
-
* disconnected and falls back to push when a subscription exists.
|
|
8
|
-
*/
|
|
9
|
-
import { generateVapidKeys } from "./vapid.js";
|
|
10
|
-
import { sendWebPush, } from "./web-push.js";
|
|
11
|
-
// ---------------------------------------------------------------------------
|
|
12
|
-
// PushManager
|
|
13
|
-
// ---------------------------------------------------------------------------
|
|
14
|
-
export class PushManager {
|
|
15
|
-
vapidKeys;
|
|
16
|
-
subject;
|
|
17
|
-
subscriptions = new Map();
|
|
18
|
-
constructor(subject = "mailto:agent-comms@localhost") {
|
|
19
|
-
this.vapidKeys = generateVapidKeys();
|
|
20
|
-
this.subject = subject;
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Register a push subscription for a given agent ID.
|
|
24
|
-
* Overwrites any existing subscription for the same agent.
|
|
25
|
-
*/
|
|
26
|
-
addSubscription(agentId, subscription) {
|
|
27
|
-
this.subscriptions.set(agentId, subscription);
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Remove a push subscription.
|
|
31
|
-
*/
|
|
32
|
-
removeSubscription(agentId) {
|
|
33
|
-
this.subscriptions.delete(agentId);
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Check whether a push subscription exists for the given agent.
|
|
37
|
-
*/
|
|
38
|
-
hasSubscription(agentId) {
|
|
39
|
-
return this.subscriptions.has(agentId);
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Send a push notification to a subscribed agent.
|
|
43
|
-
*
|
|
44
|
-
* No-ops silently if no subscription exists — callers should check
|
|
45
|
-
* hasSubscription() first if they need to distinguish the two cases.
|
|
46
|
-
*/
|
|
47
|
-
async sendPush(agentId, payload) {
|
|
48
|
-
const subscription = this.subscriptions.get(agentId);
|
|
49
|
-
if (!subscription)
|
|
50
|
-
return;
|
|
51
|
-
await sendWebPush(subscription, payload, this.vapidKeys, this.subject);
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Get the VAPID public key for the PWA to use in `pushManager.subscribe()`.
|
|
55
|
-
*/
|
|
56
|
-
getPublicKey() {
|
|
57
|
-
return this.vapidKeys.publicKey;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
//# sourceMappingURL=push-manager.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"push-manager.js","sourceRoot":"","sources":["../../src/core/push-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EACL,WAAW,GAGZ,MAAM,eAAe,CAAC;AAEvB,8EAA8E;AAC9E,cAAc;AACd,8EAA8E;AAE9E,MAAM,OAAO,WAAW;IACL,SAAS,CAAY;IACrB,OAAO,CAAS;IAChB,aAAa,GAAG,IAAI,GAAG,EAA4B,CAAC;IAErE,YAAY,OAAO,GAAG,8BAA8B;QAClD,IAAI,CAAC,SAAS,GAAG,iBAAiB,EAAE,CAAC;QACrC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED;;;OAGG;IACH,eAAe,CAAC,OAAe,EAAE,YAA8B;QAC7D,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;IAChD,CAAC;IAED;;OAEG;IACH,kBAAkB,CAAC,OAAe;QAChC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACrC,CAAC;IAED;;OAEG;IACH,eAAe,CAAC,OAAe;QAC7B,OAAO,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACzC,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,QAAQ,CACZ,OAAe,EACf,OAA8B;QAE9B,MAAM,YAAY,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACrD,IAAI,CAAC,YAAY;YAAE,OAAO;QAE1B,MAAM,WAAW,CAAC,YAAY,EAAE,OAAO,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IACzE,CAAC;IAED;;OAEG;IACH,YAAY;QACV,OAAO,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC;IAClC,CAAC;CACF"}
|
package/dist/core/vapid.d.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* VAPID key generation for Web Push (RFC 8292).
|
|
3
|
-
*
|
|
4
|
-
* Generates a P-256 EC key pair once per process lifetime and caches it
|
|
5
|
-
* in memory. The public key is shared with the PWA client so it can
|
|
6
|
-
* create push subscriptions; the private key signs push requests.
|
|
7
|
-
*/
|
|
8
|
-
export interface VapidKeys {
|
|
9
|
-
/** Base64url-encoded uncompressed P-256 public key (65 bytes). */
|
|
10
|
-
publicKey: string;
|
|
11
|
-
/** Base64url-encoded P-256 private key (32 bytes). */
|
|
12
|
-
privateKey: string;
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* Generate or return cached VAPID keys.
|
|
16
|
-
*
|
|
17
|
-
* Uses Node.js `crypto.generateKeyPairSync` with P-256, extracts the
|
|
18
|
-
* raw 65-byte uncompressed public point and the 32-byte private scalar,
|
|
19
|
-
* and base64url-encodes both per RFC 8291.
|
|
20
|
-
*/
|
|
21
|
-
export declare function generateVapidKeys(): VapidKeys;
|
|
22
|
-
//# sourceMappingURL=vapid.d.ts.map
|
package/dist/core/vapid.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"vapid.d.ts","sourceRoot":"","sources":["../../src/core/vapid.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAQH,MAAM,WAAW,SAAS;IACxB,kEAAkE;IAClE,SAAS,EAAE,MAAM,CAAC;IAClB,sDAAsD;IACtD,UAAU,EAAE,MAAM,CAAC;CACpB;AAkBD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,IAAI,SAAS,CA4B7C"}
|
package/dist/core/vapid.js
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* VAPID key generation for Web Push (RFC 8292).
|
|
3
|
-
*
|
|
4
|
-
* Generates a P-256 EC key pair once per process lifetime and caches it
|
|
5
|
-
* in memory. The public key is shared with the PWA client so it can
|
|
6
|
-
* create push subscriptions; the private key signs push requests.
|
|
7
|
-
*/
|
|
8
|
-
import * as crypto from "node:crypto";
|
|
9
|
-
// ---------------------------------------------------------------------------
|
|
10
|
-
// Cached singleton
|
|
11
|
-
// ---------------------------------------------------------------------------
|
|
12
|
-
let cachedKeys;
|
|
13
|
-
/** Length in bytes of an uncompressed P-256 public key point (0x04 prefix + 32-byte X + 32-byte Y). */
|
|
14
|
-
const P256_PUBLIC_KEY_BYTES = 65;
|
|
15
|
-
/** Length in bytes of a P-256 private scalar. */
|
|
16
|
-
const P256_PRIVATE_KEY_BYTES = 32;
|
|
17
|
-
// ---------------------------------------------------------------------------
|
|
18
|
-
// Implementation
|
|
19
|
-
// ---------------------------------------------------------------------------
|
|
20
|
-
/**
|
|
21
|
-
* Generate or return cached VAPID keys.
|
|
22
|
-
*
|
|
23
|
-
* Uses Node.js `crypto.generateKeyPairSync` with P-256, extracts the
|
|
24
|
-
* raw 65-byte uncompressed public point and the 32-byte private scalar,
|
|
25
|
-
* and base64url-encodes both per RFC 8291.
|
|
26
|
-
*/
|
|
27
|
-
export function generateVapidKeys() {
|
|
28
|
-
if (cachedKeys)
|
|
29
|
-
return cachedKeys;
|
|
30
|
-
const { publicKey, privateKey } = crypto.generateKeyPairSync("ec", {
|
|
31
|
-
namedCurve: "P-256",
|
|
32
|
-
});
|
|
33
|
-
// Export public key as raw DER, extract the 65-byte uncompressed point.
|
|
34
|
-
// SPKI DER for P-256 has a 26-byte header before the 65-byte point.
|
|
35
|
-
const pubDer = publicKey.export({ type: "spki", format: "der" });
|
|
36
|
-
const publicKeyBuffer = pubDer.subarray(pubDer.length - P256_PUBLIC_KEY_BYTES);
|
|
37
|
-
// Export private key as PKCS8 DER, extract the 32-byte private scalar.
|
|
38
|
-
// PKCS8 DER for P-256 has a 39-byte header before the 32-byte scalar.
|
|
39
|
-
// The scalar is the last 32 bytes (after the leading zero pad byte).
|
|
40
|
-
const privDer = privateKey.export({ type: "pkcs8", format: "der" });
|
|
41
|
-
const privateKeyBuffer = privDer.subarray(privDer.length - P256_PRIVATE_KEY_BYTES);
|
|
42
|
-
cachedKeys = {
|
|
43
|
-
publicKey: base64url(publicKeyBuffer),
|
|
44
|
-
privateKey: base64url(privateKeyBuffer),
|
|
45
|
-
};
|
|
46
|
-
return cachedKeys;
|
|
47
|
-
}
|
|
48
|
-
// ---------------------------------------------------------------------------
|
|
49
|
-
// Helpers
|
|
50
|
-
// ---------------------------------------------------------------------------
|
|
51
|
-
function base64url(buffer) {
|
|
52
|
-
return buffer.toString("base64url");
|
|
53
|
-
}
|
|
54
|
-
//# sourceMappingURL=vapid.js.map
|
package/dist/core/vapid.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"vapid.js","sourceRoot":"","sources":["../../src/core/vapid.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AAatC,8EAA8E;AAC9E,mBAAmB;AACnB,8EAA8E;AAE9E,IAAI,UAAiC,CAAC;AAEtC,uGAAuG;AACvG,MAAM,qBAAqB,GAAG,EAAE,CAAC;AAEjC,iDAAiD;AACjD,MAAM,sBAAsB,GAAG,EAAE,CAAC;AAElC,8EAA8E;AAC9E,iBAAiB;AACjB,8EAA8E;AAE9E;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB;IAC/B,IAAI,UAAU;QAAE,OAAO,UAAU,CAAC;IAElC,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,MAAM,CAAC,mBAAmB,CAAC,IAAI,EAAE;QACjE,UAAU,EAAE,OAAO;KACpB,CAAC,CAAC;IAEH,wEAAwE;IACxE,oEAAoE;IACpE,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IACjE,MAAM,eAAe,GAAG,MAAM,CAAC,QAAQ,CACrC,MAAM,CAAC,MAAM,GAAG,qBAAqB,CACtC,CAAC;IAEF,uEAAuE;IACvE,sEAAsE;IACtE,qEAAqE;IACrE,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IACpE,MAAM,gBAAgB,GAAG,OAAO,CAAC,QAAQ,CACvC,OAAO,CAAC,MAAM,GAAG,sBAAsB,CACxC,CAAC;IAEF,UAAU,GAAG;QACX,SAAS,EAAE,SAAS,CAAC,eAAe,CAAC;QACrC,UAAU,EAAE,SAAS,CAAC,gBAAgB,CAAC;KACxC,CAAC;IAEF,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E,SAAS,SAAS,CAAC,MAAc;IAC/B,OAAO,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AACtC,CAAC"}
|
package/dist/core/web-push.d.ts
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Web Push encryption and VAPID JWT signing (RFC 8291 + RFC 8292).
|
|
3
|
-
*
|
|
4
|
-
* Implements the Web Push protocol using only Node.js built-in `crypto`
|
|
5
|
-
* and `https` — no external dependencies.
|
|
6
|
-
*
|
|
7
|
-
* Encryption flow (RFC 8291):
|
|
8
|
-
* 1. Derive a shared ECDH secret from the subscription's p256dh key
|
|
9
|
-
* 2. HKDF-derive the encryption key and nonce from the shared secret + auth
|
|
10
|
-
* 3. Encrypt the payload with AES-128-GCM
|
|
11
|
-
* 4. Prepend the sender's public key (65 bytes) to the ciphertext
|
|
12
|
-
*
|
|
13
|
-
* VAPID signing (RFC 8292):
|
|
14
|
-
* 1. Build a JWT with sub, exp, and aud claims
|
|
15
|
-
* 2. Sign with ES256 (ECDSA + P-256 + SHA-256)
|
|
16
|
-
* 3. Append the public key and token to the Crypto-Key header
|
|
17
|
-
*/
|
|
18
|
-
import type { VapidKeys } from "./vapid.js";
|
|
19
|
-
export interface PushSubscription {
|
|
20
|
-
endpoint: string;
|
|
21
|
-
keys: {
|
|
22
|
-
p256dh: string;
|
|
23
|
-
auth: string;
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
export interface PushPayload {
|
|
27
|
-
title: string;
|
|
28
|
-
body: string;
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Send a Web Push notification.
|
|
32
|
-
*
|
|
33
|
-
* Encrypts the payload per RFC 8291, signs with VAPID per RFC 8292,
|
|
34
|
-
* and POSTs to the push service endpoint.
|
|
35
|
-
*/
|
|
36
|
-
export declare function sendWebPush(subscription: PushSubscription, payload: Readonly<PushPayload>, vapidKeys: Readonly<VapidKeys>, subject: string): Promise<void>;
|
|
37
|
-
//# sourceMappingURL=web-push.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"web-push.d.ts","sourceRoot":"","sources":["../../src/core/web-push.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAOH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAM5C,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CACxC;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AA0BD;;;;;GAKG;AACH,wBAAsB,WAAW,CAC/B,YAAY,EAAE,gBAAgB,EAC9B,OAAO,EAAE,QAAQ,CAAC,WAAW,CAAC,EAC9B,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC,EAC9B,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAmBf"}
|
package/dist/core/web-push.js
DELETED
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Web Push encryption and VAPID JWT signing (RFC 8291 + RFC 8292).
|
|
3
|
-
*
|
|
4
|
-
* Implements the Web Push protocol using only Node.js built-in `crypto`
|
|
5
|
-
* and `https` — no external dependencies.
|
|
6
|
-
*
|
|
7
|
-
* Encryption flow (RFC 8291):
|
|
8
|
-
* 1. Derive a shared ECDH secret from the subscription's p256dh key
|
|
9
|
-
* 2. HKDF-derive the encryption key and nonce from the shared secret + auth
|
|
10
|
-
* 3. Encrypt the payload with AES-128-GCM
|
|
11
|
-
* 4. Prepend the sender's public key (65 bytes) to the ciphertext
|
|
12
|
-
*
|
|
13
|
-
* VAPID signing (RFC 8292):
|
|
14
|
-
* 1. Build a JWT with sub, exp, and aud claims
|
|
15
|
-
* 2. Sign with ES256 (ECDSA + P-256 + SHA-256)
|
|
16
|
-
* 3. Append the public key and token to the Crypto-Key header
|
|
17
|
-
*/
|
|
18
|
-
import * as crypto from "node:crypto";
|
|
19
|
-
import * as https from "node:https";
|
|
20
|
-
import * as http from "node:http";
|
|
21
|
-
import { URL } from "node:url";
|
|
22
|
-
// ---------------------------------------------------------------------------
|
|
23
|
-
// Constants
|
|
24
|
-
// ---------------------------------------------------------------------------
|
|
25
|
-
const CONTENT_ENCODING = "aes128gcm";
|
|
26
|
-
const KEY_LENGTH = 16;
|
|
27
|
-
const NONCE_LENGTH = 12;
|
|
28
|
-
const SALT_LENGTH = 16;
|
|
29
|
-
const MAX_PAYLOAD_SIZE = 4078;
|
|
30
|
-
const EC_UNCOMPRESSED_POINT_LENGTH = 65;
|
|
31
|
-
const RECORD_SIZE = 4096;
|
|
32
|
-
const RECORD_SIZE_FIELD_LENGTH = 4;
|
|
33
|
-
const VAPID_JWT_EXPIRY_HOURS = 12;
|
|
34
|
-
const MINUTES_PER_HOUR = 60;
|
|
35
|
-
const SECONDS_PER_MINUTE = 60;
|
|
36
|
-
const MS_PER_SECOND = 1000;
|
|
37
|
-
const HTTPS_DEFAULT_PORT = 443;
|
|
38
|
-
const HTTP_DEFAULT_PORT = 80;
|
|
39
|
-
const HTTP_STATUS_OK_MIN = 200;
|
|
40
|
-
const HTTP_STATUS_OK_MAX = 299;
|
|
41
|
-
// ---------------------------------------------------------------------------
|
|
42
|
-
// Public API
|
|
43
|
-
// ---------------------------------------------------------------------------
|
|
44
|
-
/**
|
|
45
|
-
* Send a Web Push notification.
|
|
46
|
-
*
|
|
47
|
-
* Encrypts the payload per RFC 8291, signs with VAPID per RFC 8292,
|
|
48
|
-
* and POSTs to the push service endpoint.
|
|
49
|
-
*/
|
|
50
|
-
export async function sendWebPush(subscription, payload, vapidKeys, subject) {
|
|
51
|
-
const plaintext = JSON.stringify(payload);
|
|
52
|
-
const plaintextBuf = Buffer.from(plaintext, "utf-8");
|
|
53
|
-
if (plaintextBuf.length > MAX_PAYLOAD_SIZE) {
|
|
54
|
-
throw new Error(`Payload too large: ${String(plaintextBuf.length)} bytes (max ${String(MAX_PAYLOAD_SIZE)})`);
|
|
55
|
-
}
|
|
56
|
-
const encrypted = encrypt(plaintextBuf, subscription.keys);
|
|
57
|
-
const headers = buildHeaders(encrypted, subscription.endpoint, vapidKeys, subject);
|
|
58
|
-
await post(subscription.endpoint, headers, encrypted);
|
|
59
|
-
}
|
|
60
|
-
// ---------------------------------------------------------------------------
|
|
61
|
-
// Encryption (RFC 8291)
|
|
62
|
-
// ---------------------------------------------------------------------------
|
|
63
|
-
function encrypt(plaintext, keys) {
|
|
64
|
-
// Decode the subscription's p256dh and auth keys
|
|
65
|
-
const recipientPubKey = base64urlDecode(keys.p256dh);
|
|
66
|
-
const authKey = base64urlDecode(keys.auth);
|
|
67
|
-
// Generate an ephemeral ECDH key pair for this message
|
|
68
|
-
const ecdh = crypto.generateKeyPairSync("ec", { namedCurve: "P-256" });
|
|
69
|
-
const senderPrivateKey = crypto.createPrivateKey({
|
|
70
|
-
key: ecdh.privateKey.export({ type: "pkcs8", format: "der" }),
|
|
71
|
-
format: "der",
|
|
72
|
-
type: "pkcs8",
|
|
73
|
-
});
|
|
74
|
-
const senderPublicDer = ecdh.publicKey.export({
|
|
75
|
-
type: "spki",
|
|
76
|
-
format: "der",
|
|
77
|
-
});
|
|
78
|
-
const senderPublicKey = senderPublicDer.subarray(senderPublicDer.length - EC_UNCOMPRESSED_POINT_LENGTH);
|
|
79
|
-
// Derive the shared secret via ECDH
|
|
80
|
-
const sharedSecret = crypto.diffieHellman({
|
|
81
|
-
privateKey: senderPrivateKey,
|
|
82
|
-
publicKey: crypto.createPublicKey({
|
|
83
|
-
key: concat(Buffer.from("3059301306072a8648ce3d020106082a8648ce3d030107034200", "hex"), recipientPubKey),
|
|
84
|
-
format: "der",
|
|
85
|
-
type: "spki",
|
|
86
|
-
}),
|
|
87
|
-
});
|
|
88
|
-
// Derive the pseudo-random key (PRK) using HKDF with auth
|
|
89
|
-
const prk = hkdfExtract(authKey, sharedSecret);
|
|
90
|
-
// Derive the encryption key and nonce
|
|
91
|
-
const keyInfo = concat(Buffer.from("Content-Encoding: aes128gcm\0", "utf-8"), senderPublicKey);
|
|
92
|
-
const nonceInfo = Buffer.from("Content-Encoding: nonce\0", "utf-8");
|
|
93
|
-
const encryptionKey = hkdfExpand(prk, keyInfo, KEY_LENGTH);
|
|
94
|
-
const nonce = hkdfExpand(prk, nonceInfo, NONCE_LENGTH);
|
|
95
|
-
// Generate a random salt
|
|
96
|
-
const salt = crypto.randomBytes(SALT_LENGTH);
|
|
97
|
-
// Pad the plaintext: plaintext + 2-byte padding delimiter (0x02 0x00 for no padding)
|
|
98
|
-
// RFC 8291 §4: record is plaintext || 0x02 || padding zeros
|
|
99
|
-
const padded = concat(plaintext, Buffer.from([0x02]));
|
|
100
|
-
// Encrypt with AES-128-GCM
|
|
101
|
-
const cipher = crypto.createCipheriv("aes-128-gcm", encryptionKey, nonce);
|
|
102
|
-
const ciphertext = cipher.update(padded);
|
|
103
|
-
const authTag = cipher.getAuthTag();
|
|
104
|
-
// RFC 8291 §4: salt (16) || rs (4, big-endian, 4096) || sender pubkey (65) || ciphertext || tag
|
|
105
|
-
const rs = Buffer.alloc(RECORD_SIZE_FIELD_LENGTH);
|
|
106
|
-
rs.writeUInt32BE(RECORD_SIZE);
|
|
107
|
-
return concat(salt, rs, senderPublicKey, ciphertext, authTag);
|
|
108
|
-
}
|
|
109
|
-
// ---------------------------------------------------------------------------
|
|
110
|
-
// HKDF helpers
|
|
111
|
-
// ---------------------------------------------------------------------------
|
|
112
|
-
function hkdfExtract(salt, ikm) {
|
|
113
|
-
const hmac = crypto.createHmac("sha256", salt);
|
|
114
|
-
hmac.update(ikm);
|
|
115
|
-
return hmac.digest();
|
|
116
|
-
}
|
|
117
|
-
function hkdfExpand(prk, info, length) {
|
|
118
|
-
const hmac = crypto.createHmac("sha256", prk);
|
|
119
|
-
hmac.update(concat(info, Buffer.from([0x01])));
|
|
120
|
-
const t = hmac.digest();
|
|
121
|
-
return t.subarray(0, length);
|
|
122
|
-
}
|
|
123
|
-
// ---------------------------------------------------------------------------
|
|
124
|
-
// VAPID JWT signing (RFC 8292)
|
|
125
|
-
// ---------------------------------------------------------------------------
|
|
126
|
-
function buildVapidJwt(audience, vapidKeys, subject) {
|
|
127
|
-
const header = base64url(Buffer.from('{"alg":"ES256","typ":"JWT"}', "utf-8"));
|
|
128
|
-
const exp = Math.floor(Date.now() / MS_PER_SECOND) +
|
|
129
|
-
VAPID_JWT_EXPIRY_HOURS * MINUTES_PER_HOUR * SECONDS_PER_MINUTE;
|
|
130
|
-
const claims = JSON.stringify({ aud: audience, exp, sub: subject });
|
|
131
|
-
const payload = base64url(Buffer.from(claims, "utf-8"));
|
|
132
|
-
const signInput = `${header}.${payload}`;
|
|
133
|
-
// Reconstruct the private key from the raw 32-byte scalar
|
|
134
|
-
// P-256 PKCS8 DER wrapper: 39 bytes header + 32 bytes scalar (with 0x00 prefix)
|
|
135
|
-
const privScalar = base64urlDecode(vapidKeys.privateKey);
|
|
136
|
-
// Build the EC private key in SEC1 DER format
|
|
137
|
-
const sec1Der = concat(Buffer.from("30770201010420", "hex"), privScalar, Buffer.from("a00a06082a8648ce3d030107a14403420004", "hex"), base64urlDecode(vapidKeys.publicKey));
|
|
138
|
-
const privateKey = crypto.createPrivateKey({
|
|
139
|
-
key: sec1Der,
|
|
140
|
-
format: "der",
|
|
141
|
-
type: "sec1",
|
|
142
|
-
});
|
|
143
|
-
const signature = crypto.sign("sha256", Buffer.from(signInput), privateKey);
|
|
144
|
-
// ECDSA signature is a DER-encoded SEQUENCE of two INTEGERs.
|
|
145
|
-
// Web Push requires base64url encoding of the raw DER.
|
|
146
|
-
const sigB64 = base64url(signature);
|
|
147
|
-
return `${signInput}.${sigB64}`;
|
|
148
|
-
}
|
|
149
|
-
// ---------------------------------------------------------------------------
|
|
150
|
-
// HTTP headers
|
|
151
|
-
// ---------------------------------------------------------------------------
|
|
152
|
-
function buildHeaders(encrypted, endpoint, vapidKeys, subject) {
|
|
153
|
-
const audience = new URL(endpoint).origin;
|
|
154
|
-
const jwt = buildVapidJwt(audience, vapidKeys, subject);
|
|
155
|
-
return {
|
|
156
|
-
"Content-Type": "application/octet-stream",
|
|
157
|
-
"Content-Encoding": CONTENT_ENCODING,
|
|
158
|
-
"Content-Length": String(encrypted.length),
|
|
159
|
-
Authorization: `vapid t=${jwt}, k=${vapidKeys.publicKey}`,
|
|
160
|
-
TTL: "86400",
|
|
161
|
-
Urgency: "high",
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
// ---------------------------------------------------------------------------
|
|
165
|
-
// HTTP POST
|
|
166
|
-
// ---------------------------------------------------------------------------
|
|
167
|
-
async function post(endpoint, headers, body) {
|
|
168
|
-
return new Promise((resolve, reject) => {
|
|
169
|
-
const url = new URL(endpoint);
|
|
170
|
-
const isHttps = url.protocol === "https:";
|
|
171
|
-
const mod = isHttps ? https : http;
|
|
172
|
-
const port = url.port !== ""
|
|
173
|
-
? url.port
|
|
174
|
-
: String(isHttps ? HTTPS_DEFAULT_PORT : HTTP_DEFAULT_PORT);
|
|
175
|
-
const req = mod.request({
|
|
176
|
-
hostname: url.hostname,
|
|
177
|
-
port,
|
|
178
|
-
path: url.pathname + url.search,
|
|
179
|
-
method: "POST",
|
|
180
|
-
headers,
|
|
181
|
-
}, (res) => {
|
|
182
|
-
// Drain the response body
|
|
183
|
-
const chunks = [];
|
|
184
|
-
res.on("data", (chunk) => {
|
|
185
|
-
chunks.push(chunk);
|
|
186
|
-
});
|
|
187
|
-
res.on("end", () => {
|
|
188
|
-
if (res.statusCode !== undefined &&
|
|
189
|
-
(res.statusCode < HTTP_STATUS_OK_MIN ||
|
|
190
|
-
res.statusCode > HTTP_STATUS_OK_MAX)) {
|
|
191
|
-
const responseBody = Buffer.concat(chunks).toString("utf-8");
|
|
192
|
-
reject(new Error(`Push service returned ${String(res.statusCode)}: ${responseBody}`));
|
|
193
|
-
}
|
|
194
|
-
else {
|
|
195
|
-
resolve();
|
|
196
|
-
}
|
|
197
|
-
});
|
|
198
|
-
});
|
|
199
|
-
req.on("error", reject);
|
|
200
|
-
req.write(body);
|
|
201
|
-
req.end();
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
// ---------------------------------------------------------------------------
|
|
205
|
-
// Utilities
|
|
206
|
-
// ---------------------------------------------------------------------------
|
|
207
|
-
function base64urlDecode(input) {
|
|
208
|
-
return Buffer.from(input, "base64url");
|
|
209
|
-
}
|
|
210
|
-
function base64url(input) {
|
|
211
|
-
return input.toString("base64url");
|
|
212
|
-
}
|
|
213
|
-
function concat(...buffers) {
|
|
214
|
-
return Buffer.concat(buffers);
|
|
215
|
-
}
|
|
216
|
-
//# sourceMappingURL=web-push.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"web-push.js","sourceRoot":"","sources":["../../src/core/web-push.ts"],"names":[],"mappings":"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"}
|