@jamiexiongr/panda-hub 0.1.7 → 0.1.8
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/chunk-AEQMWH7D.mjs +4076 -0
- package/dist/{chunk-JBN6ZR6W.mjs → chunk-WFHIGEWQ.mjs} +11476 -24350
- package/dist/{chunk-D2AAEM52.mjs → chunk-YPDN7Z3X.mjs} +4 -3
- package/dist/cli.mjs +3 -2
- package/dist/hub-web-push-KM4VOXLQ.mjs +157 -0
- package/dist/index.mjs +3 -2
- package/dist/src-MV7FXZYF.mjs +1375 -0
- package/package.json +3 -2
- package/dist/src-J33JUYSS.mjs +0 -92
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
resolveTailscalePublicationMode,
|
|
6
6
|
resolveTailscaleServePort,
|
|
7
7
|
startPandaSessionService
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-WFHIGEWQ.mjs";
|
|
9
9
|
|
|
10
10
|
// release/panda-hub/src/index.ts
|
|
11
11
|
import fs from "fs";
|
|
@@ -15,14 +15,15 @@ import { fileURLToPath } from "url";
|
|
|
15
15
|
// release/panda-hub/package.json
|
|
16
16
|
var package_default = {
|
|
17
17
|
name: "@jamiexiongr/panda-hub",
|
|
18
|
-
version: "0.1.
|
|
18
|
+
version: "0.1.8",
|
|
19
19
|
type: "module",
|
|
20
20
|
private: false,
|
|
21
21
|
description: "Panda hub runtime",
|
|
22
22
|
dependencies: {
|
|
23
23
|
"@fastify/cors": "^10.0.2",
|
|
24
24
|
"@fastify/websocket": "^11.0.2",
|
|
25
|
-
fastify: "^5.2.1"
|
|
25
|
+
fastify: "^5.2.1",
|
|
26
|
+
"web-push": "^3.6.7"
|
|
26
27
|
},
|
|
27
28
|
bin: {
|
|
28
29
|
"panda-hub": "./bin/panda-hub.cjs"
|
package/dist/cli.mjs
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
startJamiexiongrHub
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-YPDN7Z3X.mjs";
|
|
4
4
|
import {
|
|
5
5
|
resolveTailscalePublicationMode
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-WFHIGEWQ.mjs";
|
|
7
|
+
import "./chunk-AEQMWH7D.mjs";
|
|
7
8
|
|
|
8
9
|
// release/panda-hub/src/cli.ts
|
|
9
10
|
void startJamiexiongrHub({
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import {
|
|
2
|
+
external_exports
|
|
3
|
+
} from "./chunk-AEQMWH7D.mjs";
|
|
4
|
+
|
|
5
|
+
// packages/provider-codex/src/hub-web-push.ts
|
|
6
|
+
import fs from "fs/promises";
|
|
7
|
+
import path from "path";
|
|
8
|
+
import webpush from "web-push";
|
|
9
|
+
var storedVapidConfigSchema = external_exports.object({
|
|
10
|
+
version: external_exports.literal(1),
|
|
11
|
+
public_key: external_exports.string(),
|
|
12
|
+
private_key: external_exports.string(),
|
|
13
|
+
subject: external_exports.string(),
|
|
14
|
+
created_at: external_exports.string(),
|
|
15
|
+
updated_at: external_exports.string()
|
|
16
|
+
});
|
|
17
|
+
var isoNow = () => (/* @__PURE__ */ new Date()).toISOString();
|
|
18
|
+
var normalizeSubject = (value) => {
|
|
19
|
+
const trimmed = value?.trim() ?? "";
|
|
20
|
+
if (trimmed) {
|
|
21
|
+
return trimmed;
|
|
22
|
+
}
|
|
23
|
+
return "mailto:panda@localhost";
|
|
24
|
+
};
|
|
25
|
+
var loadStoredVapidConfig = async (storageFilePath) => {
|
|
26
|
+
try {
|
|
27
|
+
const raw = await fs.readFile(storageFilePath, "utf8");
|
|
28
|
+
return storedVapidConfigSchema.parse(JSON.parse(raw));
|
|
29
|
+
} catch (error) {
|
|
30
|
+
if (error?.code === "ENOENT") {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
throw error;
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
var writeStoredVapidConfig = async (storageFilePath, config) => {
|
|
37
|
+
await fs.mkdir(path.dirname(storageFilePath), { recursive: true });
|
|
38
|
+
await fs.writeFile(storageFilePath, JSON.stringify(config, null, 2), "utf8");
|
|
39
|
+
};
|
|
40
|
+
var resolveVapidConfig = async (options) => {
|
|
41
|
+
const configuredPublicKey = options.publicKey?.trim() ?? "";
|
|
42
|
+
const configuredPrivateKey = options.privateKey?.trim() ?? "";
|
|
43
|
+
const subject = normalizeSubject(options.subject);
|
|
44
|
+
if (configuredPublicKey || configuredPrivateKey) {
|
|
45
|
+
if (!configuredPublicKey || !configuredPrivateKey) {
|
|
46
|
+
return {
|
|
47
|
+
publicConfig: {
|
|
48
|
+
supported: false,
|
|
49
|
+
vapid_public_key: null,
|
|
50
|
+
subject: subject ?? null,
|
|
51
|
+
reason: "PANDA_WEB_PUSH_PUBLIC_KEY and PANDA_WEB_PUSH_PRIVATE_KEY must both be set."
|
|
52
|
+
},
|
|
53
|
+
privateKey: null
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
publicConfig: {
|
|
58
|
+
supported: true,
|
|
59
|
+
vapid_public_key: configuredPublicKey,
|
|
60
|
+
subject,
|
|
61
|
+
reason: null
|
|
62
|
+
},
|
|
63
|
+
privateKey: configuredPrivateKey
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
const stored = await loadStoredVapidConfig(options.storageFilePath);
|
|
67
|
+
if (stored) {
|
|
68
|
+
return {
|
|
69
|
+
publicConfig: {
|
|
70
|
+
supported: true,
|
|
71
|
+
vapid_public_key: stored.public_key,
|
|
72
|
+
subject: stored.subject,
|
|
73
|
+
reason: null
|
|
74
|
+
},
|
|
75
|
+
privateKey: stored.private_key
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
const generated = webpush.generateVAPIDKeys();
|
|
79
|
+
const now = isoNow();
|
|
80
|
+
const persisted = storedVapidConfigSchema.parse({
|
|
81
|
+
version: 1,
|
|
82
|
+
public_key: generated.publicKey,
|
|
83
|
+
private_key: generated.privateKey,
|
|
84
|
+
subject,
|
|
85
|
+
created_at: now,
|
|
86
|
+
updated_at: now
|
|
87
|
+
});
|
|
88
|
+
await writeStoredVapidConfig(options.storageFilePath, persisted);
|
|
89
|
+
options.logger?.info?.(
|
|
90
|
+
{ storageFilePath: options.storageFilePath },
|
|
91
|
+
"Generated persistent Panda Web Push VAPID keys."
|
|
92
|
+
);
|
|
93
|
+
return {
|
|
94
|
+
publicConfig: {
|
|
95
|
+
supported: true,
|
|
96
|
+
vapid_public_key: persisted.public_key,
|
|
97
|
+
subject: persisted.subject,
|
|
98
|
+
reason: null
|
|
99
|
+
},
|
|
100
|
+
privateKey: persisted.private_key
|
|
101
|
+
};
|
|
102
|
+
};
|
|
103
|
+
var createHubWebPushNotifier = async (options) => {
|
|
104
|
+
const resolved = await resolveVapidConfig(options);
|
|
105
|
+
if (!resolved.publicConfig.supported || !resolved.publicConfig.vapid_public_key || !resolved.privateKey) {
|
|
106
|
+
return {
|
|
107
|
+
publicConfig: resolved.publicConfig,
|
|
108
|
+
async sendNotification() {
|
|
109
|
+
return {
|
|
110
|
+
ok: false,
|
|
111
|
+
statusCode: null,
|
|
112
|
+
shouldRemove: false,
|
|
113
|
+
message: "Hub Web Push is not configured."
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
webpush.setVapidDetails(
|
|
119
|
+
resolved.publicConfig.subject ?? normalizeSubject(options.subject),
|
|
120
|
+
resolved.publicConfig.vapid_public_key,
|
|
121
|
+
resolved.privateKey
|
|
122
|
+
);
|
|
123
|
+
return {
|
|
124
|
+
publicConfig: resolved.publicConfig,
|
|
125
|
+
async sendNotification(subscription, payload) {
|
|
126
|
+
try {
|
|
127
|
+
await webpush.sendNotification(
|
|
128
|
+
subscription,
|
|
129
|
+
JSON.stringify({
|
|
130
|
+
title: payload.title,
|
|
131
|
+
body: payload.body,
|
|
132
|
+
url: payload.url,
|
|
133
|
+
tag: payload.tag,
|
|
134
|
+
sessionId: payload.sessionId ?? null
|
|
135
|
+
}),
|
|
136
|
+
{
|
|
137
|
+
TTL: 60,
|
|
138
|
+
urgency: "high",
|
|
139
|
+
topic: payload.tag.slice(0, 32)
|
|
140
|
+
}
|
|
141
|
+
);
|
|
142
|
+
return { ok: true, statusCode: 201, shouldRemove: false };
|
|
143
|
+
} catch (error) {
|
|
144
|
+
const statusCode = typeof error === "object" && error !== null && "statusCode" in error && typeof error.statusCode === "number" ? error.statusCode : null;
|
|
145
|
+
return {
|
|
146
|
+
ok: false,
|
|
147
|
+
statusCode,
|
|
148
|
+
shouldRemove: statusCode === 404 || statusCode === 410,
|
|
149
|
+
message: error instanceof Error ? error.message : String(error)
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
};
|
|
155
|
+
export {
|
|
156
|
+
createHubWebPushNotifier
|
|
157
|
+
};
|
package/dist/index.mjs
CHANGED