@privateclaw/privateclaw-relay 0.1.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.
Files changed (42) hide show
  1. package/.env.example +13 -0
  2. package/README.md +86 -0
  3. package/dist/cli-error.d.ts +3 -0
  4. package/dist/cli-error.js +7 -0
  5. package/dist/cli-error.js.map +1 -0
  6. package/dist/cli.d.ts +2 -0
  7. package/dist/cli.js +14 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/config.d.ts +13 -0
  10. package/dist/config.js +36 -0
  11. package/dist/config.js.map +1 -0
  12. package/dist/frame-cache.d.ts +77 -0
  13. package/dist/frame-cache.js +127 -0
  14. package/dist/frame-cache.js.map +1 -0
  15. package/dist/index.d.ts +4 -0
  16. package/dist/index.js +5 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/push-notifier.d.ts +36 -0
  19. package/dist/push-notifier.js +198 -0
  20. package/dist/push-notifier.js.map +1 -0
  21. package/dist/push-registration-store.d.ts +39 -0
  22. package/dist/push-registration-store.js +98 -0
  23. package/dist/push-registration-store.js.map +1 -0
  24. package/dist/relay-cli.d.ts +28 -0
  25. package/dist/relay-cli.js +256 -0
  26. package/dist/relay-cli.js.map +1 -0
  27. package/dist/relay-cluster.d.ts +144 -0
  28. package/dist/relay-cluster.js +436 -0
  29. package/dist/relay-cluster.js.map +1 -0
  30. package/dist/relay-server.d.ts +25 -0
  31. package/dist/relay-server.js +1090 -0
  32. package/dist/relay-server.js.map +1 -0
  33. package/dist/session-store.d.ts +40 -0
  34. package/dist/session-store.js +159 -0
  35. package/dist/session-store.js.map +1 -0
  36. package/dist/tunnel-installer.d.ts +36 -0
  37. package/dist/tunnel-installer.js +402 -0
  38. package/dist/tunnel-installer.js.map +1 -0
  39. package/dist/tunnel.d.ts +35 -0
  40. package/dist/tunnel.js +334 -0
  41. package/dist/tunnel.js.map +1 -0
  42. package/package.json +45 -0
package/dist/tunnel.js ADDED
@@ -0,0 +1,334 @@
1
+ import { spawn } from "node:child_process";
2
+ import { once } from "node:events";
3
+ export class MissingRelayTunnelBinaryError extends Error {
4
+ command;
5
+ hint;
6
+ constructor(command, hint) {
7
+ super(`Could not run the \`${command}\` CLI from PATH because it is missing or not executable. ${hint}`);
8
+ this.command = command;
9
+ this.hint = hint;
10
+ this.name = "MissingRelayTunnelBinaryError";
11
+ }
12
+ }
13
+ const PUBLIC_URL_PATTERN = /https:\/\/[^\s"'`<>]+/gu;
14
+ function formatTunnelCommand(plan) {
15
+ return [plan.command, ...plan.args].join(" ");
16
+ }
17
+ function formatMissingBinaryError(command, hint) {
18
+ return new MissingRelayTunnelBinaryError(command, hint);
19
+ }
20
+ function getMissingBinaryHint(command) {
21
+ return command === "tailscale"
22
+ ? "Install Tailscale and run `tailscale up` before using `--public tailscale`."
23
+ : "Install cloudflared before using `--public cloudflare`.";
24
+ }
25
+ export function isUnavailableTunnelBinaryError(error) {
26
+ const code = error?.code;
27
+ return code === "ENOENT" || code === "EACCES" || code === "EPERM";
28
+ }
29
+ function trimTrailingPunctuation(value) {
30
+ return value.replace(/[),.;:]+$/u, "");
31
+ }
32
+ function emitBufferedLines(buffer, params) {
33
+ const lines = buffer.split(/\r?\n/u);
34
+ const remainder = lines.pop() ?? "";
35
+ for (const line of lines) {
36
+ const trimmed = line.trim();
37
+ if (trimmed !== "") {
38
+ params.onLog?.(`[privateclaw-relay] ${params.prefix} ${trimmed}`);
39
+ }
40
+ }
41
+ return remainder;
42
+ }
43
+ async function runOneShotCommand(params) {
44
+ const spawnCommand = params.spawnCommand ?? spawn;
45
+ const child = spawnCommand(params.plan.command, params.plan.args, {
46
+ stdio: ["ignore", "pipe", "pipe"],
47
+ });
48
+ let stdout = "";
49
+ let stderr = "";
50
+ let stdoutRemainder = "";
51
+ let stderrRemainder = "";
52
+ child.stdout.setEncoding("utf8");
53
+ child.stderr.setEncoding("utf8");
54
+ child.stdout.on("data", (chunk) => {
55
+ stdout += chunk;
56
+ stdoutRemainder = emitBufferedLines(stdoutRemainder + chunk, {
57
+ prefix: params.logPrefix,
58
+ ...(params.onLog ? { onLog: params.onLog } : {}),
59
+ });
60
+ });
61
+ child.stderr.on("data", (chunk) => {
62
+ stderr += chunk;
63
+ stderrRemainder = emitBufferedLines(stderrRemainder + chunk, {
64
+ prefix: params.logPrefix,
65
+ ...(params.onLog ? { onLog: params.onLog } : {}),
66
+ });
67
+ });
68
+ const childError = once(child, "error").then(([error]) => {
69
+ throw error;
70
+ });
71
+ const childClose = once(child, "close").then(([code, signal]) => ({
72
+ code,
73
+ signal,
74
+ }));
75
+ try {
76
+ const { code, signal } = await Promise.race([childError, childClose]);
77
+ if (stdoutRemainder.trim() !== "") {
78
+ params.onLog?.(`[privateclaw-relay] ${params.logPrefix} ${stdoutRemainder.trim()}`);
79
+ }
80
+ if (stderrRemainder.trim() !== "") {
81
+ params.onLog?.(`[privateclaw-relay] ${params.logPrefix} ${stderrRemainder.trim()}`);
82
+ }
83
+ if (code !== 0) {
84
+ const combined = `${stdout}${stderr}`.trim();
85
+ throw new Error(`Command \`${formatTunnelCommand(params.plan)}\` exited with ${code == null ? `signal ${signal ?? "unknown"}` : `code ${code}`}${combined ? `: ${combined}` : "."}`);
86
+ }
87
+ return {
88
+ stdout,
89
+ stderr,
90
+ combined: `${stdout}${stderr}`,
91
+ };
92
+ }
93
+ catch (error) {
94
+ if (isUnavailableTunnelBinaryError(error)) {
95
+ throw formatMissingBinaryError(params.plan.command, getMissingBinaryHint(params.plan.command));
96
+ }
97
+ throw error;
98
+ }
99
+ }
100
+ async function stopPersistentChild(child) {
101
+ if (child.exitCode != null) {
102
+ return;
103
+ }
104
+ child.kill("SIGTERM");
105
+ const timer = setTimeout(() => {
106
+ if (child.exitCode == null) {
107
+ child.kill("SIGKILL");
108
+ }
109
+ }, 5_000);
110
+ try {
111
+ await once(child, "exit");
112
+ }
113
+ finally {
114
+ clearTimeout(timer);
115
+ }
116
+ }
117
+ export function isRelayTunnelProvider(value) {
118
+ return value === "tailscale" || value === "cloudflare";
119
+ }
120
+ function extractPublicUrls(output) {
121
+ const matches = output.match(PUBLIC_URL_PATTERN);
122
+ if (!matches) {
123
+ return [];
124
+ }
125
+ return matches.map((match) => trimTrailingPunctuation(match));
126
+ }
127
+ export function extractRelayTunnelPublicUrl(output) {
128
+ return extractPublicUrls(output)[0];
129
+ }
130
+ export function extractCloudflareQuickTunnelPublicUrl(output) {
131
+ for (const candidate of extractPublicUrls(output)) {
132
+ try {
133
+ const hostname = new URL(candidate).hostname;
134
+ if (hostname === "trycloudflare.com" ||
135
+ hostname.endsWith(".trycloudflare.com")) {
136
+ return candidate;
137
+ }
138
+ }
139
+ catch {
140
+ continue;
141
+ }
142
+ }
143
+ return undefined;
144
+ }
145
+ export function buildRelayTunnelCommand(params) {
146
+ if (params.provider === "tailscale") {
147
+ return {
148
+ command: "tailscale",
149
+ args: ["funnel", "--bg", String(params.localPort)],
150
+ };
151
+ }
152
+ return {
153
+ command: "cloudflared",
154
+ args: ["tunnel", "--url", params.localUrl],
155
+ };
156
+ }
157
+ async function openTailscaleFunnel(params) {
158
+ const statusPlan = {
159
+ command: "tailscale",
160
+ args: ["funnel", "status"],
161
+ };
162
+ const previousStatus = await runOneShotCommand({
163
+ plan: statusPlan,
164
+ logPrefix: "[tailscale]",
165
+ ...(params.onLog ? { onLog: params.onLog } : {}),
166
+ ...(params.spawnCommand ? { spawnCommand: params.spawnCommand } : {}),
167
+ }).catch((error) => {
168
+ if (error instanceof Error &&
169
+ error.message.includes("Could not find the `tailscale` CLI")) {
170
+ throw error;
171
+ }
172
+ return {
173
+ stdout: "",
174
+ stderr: "",
175
+ combined: "",
176
+ };
177
+ });
178
+ const hadExistingPublicUrl = extractRelayTunnelPublicUrl(previousStatus.combined) != null;
179
+ const enablePlan = buildRelayTunnelCommand({
180
+ provider: "tailscale",
181
+ localPort: params.localPort,
182
+ localUrl: params.localUrl,
183
+ });
184
+ const enableResult = await runOneShotCommand({
185
+ plan: enablePlan,
186
+ logPrefix: "[tailscale]",
187
+ ...(params.onLog ? { onLog: params.onLog } : {}),
188
+ ...(params.spawnCommand ? { spawnCommand: params.spawnCommand } : {}),
189
+ });
190
+ const currentStatus = await runOneShotCommand({
191
+ plan: statusPlan,
192
+ logPrefix: "[tailscale]",
193
+ ...(params.onLog ? { onLog: params.onLog } : {}),
194
+ ...(params.spawnCommand ? { spawnCommand: params.spawnCommand } : {}),
195
+ });
196
+ const publicUrl = extractRelayTunnelPublicUrl(currentStatus.combined) ??
197
+ extractRelayTunnelPublicUrl(enableResult.combined);
198
+ return {
199
+ kind: "tailscale",
200
+ ...(publicUrl ? { publicUrl } : {}),
201
+ notes: hadExistingPublicUrl
202
+ ? [
203
+ "Tailscale Funnel was already configured before this run, so the CLI will leave that public endpoint in place on shutdown.",
204
+ ]
205
+ : [
206
+ "The CLI will run `tailscale funnel off` on shutdown to remove the public endpoint it created.",
207
+ ],
208
+ close: async () => {
209
+ if (hadExistingPublicUrl) {
210
+ return;
211
+ }
212
+ try {
213
+ await runOneShotCommand({
214
+ plan: {
215
+ command: "tailscale",
216
+ args: ["funnel", "off"],
217
+ },
218
+ logPrefix: "[tailscale]",
219
+ ...(params.onLog ? { onLog: params.onLog } : {}),
220
+ ...(params.spawnCommand ? { spawnCommand: params.spawnCommand } : {}),
221
+ });
222
+ }
223
+ catch (error) {
224
+ params.onLog?.(`[privateclaw-relay] [tailscale] failed to disable Funnel automatically: ${error instanceof Error ? error.message : String(error)}`);
225
+ }
226
+ },
227
+ };
228
+ }
229
+ async function openCloudflareTunnel(params) {
230
+ const spawnCommand = params.spawnCommand ?? spawn;
231
+ const plan = buildRelayTunnelCommand({
232
+ provider: "cloudflare",
233
+ localPort: params.localPort,
234
+ localUrl: params.localUrl,
235
+ });
236
+ const child = spawnCommand(plan.command, plan.args, {
237
+ stdio: ["ignore", "pipe", "pipe"],
238
+ });
239
+ child.stdout.setEncoding("utf8");
240
+ child.stderr.setEncoding("utf8");
241
+ return new Promise((resolve, reject) => {
242
+ let settled = false;
243
+ let stdout = "";
244
+ let stderr = "";
245
+ let stdoutRemainder = "";
246
+ let stderrRemainder = "";
247
+ const cleanup = () => {
248
+ clearTimeout(timeout);
249
+ child.stdout.removeAllListeners("data");
250
+ child.stderr.removeAllListeners("data");
251
+ child.removeAllListeners("error");
252
+ child.removeAllListeners("close");
253
+ };
254
+ const resolveWithUrl = (publicUrl) => {
255
+ if (settled) {
256
+ return;
257
+ }
258
+ settled = true;
259
+ cleanup();
260
+ resolve({
261
+ kind: "cloudflare",
262
+ ...(publicUrl ? { publicUrl } : {}),
263
+ notes: [
264
+ "Cloudflare quick tunnels are temporary and use a random trycloudflare.com URL.",
265
+ ],
266
+ close: async () => {
267
+ await stopPersistentChild(child);
268
+ },
269
+ });
270
+ };
271
+ const rejectWithError = (error) => {
272
+ if (settled) {
273
+ return;
274
+ }
275
+ settled = true;
276
+ cleanup();
277
+ if (isUnavailableTunnelBinaryError(error)) {
278
+ reject(formatMissingBinaryError("cloudflared", getMissingBinaryHint("cloudflared")));
279
+ return;
280
+ }
281
+ reject(error);
282
+ };
283
+ const handleChunk = (chunk, prefix, target) => {
284
+ if (target === "stdout") {
285
+ stdout += chunk;
286
+ stdoutRemainder = emitBufferedLines(stdoutRemainder + chunk, {
287
+ prefix,
288
+ ...(params.onLog ? { onLog: params.onLog } : {}),
289
+ });
290
+ }
291
+ else {
292
+ stderr += chunk;
293
+ stderrRemainder = emitBufferedLines(stderrRemainder + chunk, {
294
+ prefix,
295
+ ...(params.onLog ? { onLog: params.onLog } : {}),
296
+ });
297
+ }
298
+ const publicUrl = extractCloudflareQuickTunnelPublicUrl(`${stdout}${stderr}`);
299
+ if (publicUrl) {
300
+ if (stdoutRemainder.trim() !== "") {
301
+ params.onLog?.(`[privateclaw-relay] ${prefix} ${stdoutRemainder.trim()}`);
302
+ }
303
+ if (stderrRemainder.trim() !== "") {
304
+ params.onLog?.(`[privateclaw-relay] ${prefix} ${stderrRemainder.trim()}`);
305
+ }
306
+ resolveWithUrl(publicUrl);
307
+ }
308
+ };
309
+ child.stdout.on("data", (chunk) => {
310
+ handleChunk(chunk, "[cloudflare]", "stdout");
311
+ });
312
+ child.stderr.on("data", (chunk) => {
313
+ handleChunk(chunk, "[cloudflare]", "stderr");
314
+ });
315
+ child.once("error", rejectWithError);
316
+ child.once("close", (code, signal) => {
317
+ if (settled) {
318
+ return;
319
+ }
320
+ const combined = `${stdout}${stderr}`.trim();
321
+ rejectWithError(new Error(`Command \`${formatTunnelCommand(plan)}\` exited with ${code == null ? `signal ${signal ?? "unknown"}` : `code ${code}`}${combined ? `: ${combined}` : "."}`));
322
+ });
323
+ const timeout = setTimeout(() => {
324
+ rejectWithError(new Error(`Timed out waiting for Cloudflare Tunnel to report a public URL after running \`${formatTunnelCommand(plan)}\`.`));
325
+ }, 30_000);
326
+ });
327
+ }
328
+ export async function openRelayTunnel(params) {
329
+ if (params.provider === "tailscale") {
330
+ return openTailscaleFunnel(params);
331
+ }
332
+ return openCloudflareTunnel(params);
333
+ }
334
+ //# sourceMappingURL=tunnel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tunnel.js","sourceRoot":"","sources":["../src/tunnel.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "@privateclaw/privateclaw-relay",
3
+ "version": "0.1.0",
4
+ "description": "Blind WebSocket relay for PrivateClaw encrypted sessions with local CLI startup and optional Tailscale Funnel or Cloudflare Tunnel exposure",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "bin": {
9
+ "privateclaw-relay": "dist/cli.js"
10
+ },
11
+ "files": [
12
+ "dist",
13
+ ".env.example",
14
+ "README.md"
15
+ ],
16
+ "license": "MIT",
17
+ "engines": {
18
+ "node": ">=20"
19
+ },
20
+ "scripts": {
21
+ "build": "tsc -p tsconfig.json",
22
+ "dev": "tsx src/cli.ts",
23
+ "start": "node dist/cli.js",
24
+ "prepack": "npm run build",
25
+ "test": "node --import tsx --test src/**/*.test.ts"
26
+ },
27
+ "dependencies": {
28
+ "@privateclaw/protocol": "^0.1.2",
29
+ "ioredis": "^5.8.1",
30
+ "ws": "^8.18.3"
31
+ },
32
+ "publishConfig": {
33
+ "access": "public",
34
+ "registry": "https://registry.npmjs.org"
35
+ },
36
+ "repository": {
37
+ "type": "git",
38
+ "url": "git+https://github.com/topcheer/PrivateClaw.git",
39
+ "directory": "services/relay-server"
40
+ },
41
+ "homepage": "https://github.com/topcheer/PrivateClaw/tree/main/services/relay-server",
42
+ "bugs": {
43
+ "url": "https://github.com/topcheer/PrivateClaw/issues"
44
+ }
45
+ }