@jonathanyee/devtunnel-ctl 0.0.0-stage → 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 (49) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +281 -2
  3. package/dist/auth.d.ts +23 -0
  4. package/dist/auth.js +150 -0
  5. package/dist/auth.js.map +1 -0
  6. package/dist/cli.d.ts +3 -0
  7. package/dist/cli.js +206 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/config.d.ts +22 -0
  10. package/dist/config.js +94 -0
  11. package/dist/config.js.map +1 -0
  12. package/dist/core.d.ts +16 -0
  13. package/dist/core.js +112 -0
  14. package/dist/core.js.map +1 -0
  15. package/dist/daemon.d.ts +31 -0
  16. package/dist/daemon.js +153 -0
  17. package/dist/daemon.js.map +1 -0
  18. package/dist/forwarding.d.ts +15 -0
  19. package/dist/forwarding.js +87 -0
  20. package/dist/forwarding.js.map +1 -0
  21. package/dist/launchd.d.ts +10 -0
  22. package/dist/launchd.js +131 -0
  23. package/dist/launchd.js.map +1 -0
  24. package/dist/lock.d.ts +10 -0
  25. package/dist/lock.js +110 -0
  26. package/dist/lock.js.map +1 -0
  27. package/dist/log.d.ts +26 -0
  28. package/dist/log.js +67 -0
  29. package/dist/log.js.map +1 -0
  30. package/dist/main.d.ts +2 -0
  31. package/dist/main.js +5 -0
  32. package/dist/main.js.map +1 -0
  33. package/dist/paths.d.ts +4 -0
  34. package/dist/paths.js +39 -0
  35. package/dist/paths.js.map +1 -0
  36. package/dist/probe.d.ts +1 -0
  37. package/dist/probe.js +45 -0
  38. package/dist/probe.js.map +1 -0
  39. package/dist/recovery.d.ts +77 -0
  40. package/dist/recovery.js +265 -0
  41. package/dist/recovery.js.map +1 -0
  42. package/dist/rpc.d.ts +30 -0
  43. package/dist/rpc.js +208 -0
  44. package/dist/rpc.js.map +1 -0
  45. package/dist/sdk-transport.d.ts +29 -0
  46. package/dist/sdk-transport.js +239 -0
  47. package/dist/sdk-transport.js.map +1 -0
  48. package/npm-shrinkwrap.json +809 -0
  49. package/package.json +31 -4
package/dist/log.js ADDED
@@ -0,0 +1,67 @@
1
+ import { open, rename, lstat } from 'node:fs/promises';
2
+ import { constants } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ import { Fault, redact } from "./core.js";
5
+ import { privateDir, privatePath } from "./paths.js";
6
+ export class Log {
7
+ dir;
8
+ maxBytes;
9
+ pending = 0;
10
+ tail = Promise.resolve();
11
+ sequence = 0;
12
+ recent = [];
13
+ constructor(dir, maxBytes = 262144) { this.dir = dir; this.maxBytes = maxBytes; }
14
+ async init() { await privateDir(this.dir); }
15
+ write(entry) {
16
+ if (this.pending >= 256)
17
+ return Promise.reject(new Fault('internal', 'Log backlog limit exceeded.'));
18
+ const line = JSON.stringify({ time: new Date().toISOString(), event: redact(entry.event),
19
+ ...(entry.profile ? { profile: redact(entry.profile) } : {}),
20
+ ...(entry.state ? { state: redact(entry.state) } : {}),
21
+ ...(entry.message ? { message: redact(entry.message).slice(0, 256) } : {}),
22
+ ...(entry.attempt !== undefined ? { attempt: entry.attempt } : {}),
23
+ ...(entry.relayConnected !== undefined ? { relayConnected: entry.relayConnected } : {}),
24
+ ...(entry.lastHealthyAt !== undefined ? { lastHealthyAt: entry.lastHealthyAt } : {}),
25
+ ...(entry.nextRetryAt !== undefined ? { nextRetryAt: entry.nextRetryAt } : {}),
26
+ }) + '\n';
27
+ if (Buffer.byteLength(line) > this.maxBytes)
28
+ return Promise.reject(new Fault('internal', 'Log entry exceeds disk bound.'));
29
+ this.pending++;
30
+ this.tail = this.tail.then(async () => {
31
+ const path = join(this.dir, 'service.log'), previous = path + '.1';
32
+ let size = 0;
33
+ try {
34
+ await privatePath(path);
35
+ size = (await lstat(path)).size;
36
+ }
37
+ catch (error) {
38
+ if (!(error instanceof Error && 'code' in error && error.code === 'ENOENT'))
39
+ throw error;
40
+ }
41
+ if (size + Buffer.byteLength(line) > this.maxBytes) {
42
+ try {
43
+ await privatePath(previous);
44
+ }
45
+ catch (error) {
46
+ if (!(error instanceof Error && 'code' in error && error.code === 'ENOENT'))
47
+ throw error;
48
+ }
49
+ await rename(path, previous);
50
+ }
51
+ const file = await open(path, constants.O_APPEND | constants.O_CREAT | constants.O_WRONLY | constants.O_NOFOLLOW, 0o600);
52
+ try {
53
+ await file.writeFile(line);
54
+ }
55
+ finally {
56
+ await file.close();
57
+ }
58
+ this.recent.push({ sequence: ++this.sequence, line: line.trimEnd() });
59
+ if (this.recent.length > 128)
60
+ this.recent.shift();
61
+ }).finally(() => { this.pending--; });
62
+ return this.tail;
63
+ }
64
+ flush() { return this.tail; }
65
+ snapshot() { return this.recent.map(entry => ({ ...entry })); }
66
+ }
67
+ //# sourceMappingURL=log.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log.js","sourceRoot":"","sources":["../src/log.ts"],"names":[],"mappings":"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"}
package/dist/main.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/main.js ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ import { fileURLToPath } from 'node:url';
3
+ import { cli, report } from "./cli.js";
4
+ await cli(process.argv.slice(2), fileURLToPath(import.meta.url)).catch(report);
5
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAEvC,MAAM,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare function stateDir(input?: string): string;
2
+ export declare function executable(path: string): Promise<string>;
3
+ export declare function privatePath(path: string, directory?: boolean): Promise<void>;
4
+ export declare function privateDir(path: string): Promise<void>;
package/dist/paths.js ADDED
@@ -0,0 +1,39 @@
1
+ import { homedir } from 'node:os';
2
+ import { join, resolve } from 'node:path';
3
+ import { lstat, mkdir, chmod, realpath, access, stat } from 'node:fs/promises';
4
+ import { constants } from 'node:fs';
5
+ import { Fault } from "./core.js";
6
+ export function stateDir(input) {
7
+ return input ? resolve(input) : join(homedir(), '.devtunnel-ctl');
8
+ }
9
+ export async function executable(path) {
10
+ try {
11
+ const resolved = await realpath(path);
12
+ await access(resolved, constants.X_OK);
13
+ if (!(await stat(resolved)).isFile())
14
+ throw new Fault('invalid-config');
15
+ return resolved;
16
+ }
17
+ catch {
18
+ throw new Fault('invalid-config', 'Configured executable is missing or not executable. Check its absolute path.');
19
+ }
20
+ }
21
+ export async function privatePath(path, directory = false) {
22
+ const info = await lstat(path);
23
+ if (info.isSymbolicLink() || (directory ? !info.isDirectory() : !info.isFile()) ||
24
+ info.uid !== process.getuid?.() || (info.mode & 0o077) !== 0) {
25
+ throw new Fault('invalid-config', 'State must be private, owned by this user, and not a symlink.');
26
+ }
27
+ }
28
+ export async function privateDir(path) {
29
+ try {
30
+ await mkdir(path, { mode: 0o700 });
31
+ await chmod(path, 0o700);
32
+ }
33
+ catch (error) {
34
+ if (!(error instanceof Error && 'code' in error && error.code === 'EEXIST'))
35
+ throw error;
36
+ }
37
+ await privatePath(path, true);
38
+ }
39
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC/E,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAElC,MAAM,UAAU,QAAQ,CAAC,KAAc;IACrC,OAAO,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,gBAAgB,CAAC,CAAC;AACpE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAY;IAC3C,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC;QACtC,MAAM,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;QACvC,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC;QACxE,OAAO,QAAQ,CAAC;IAClB,CAAC;IAAC,MAAM,CAAC;QAAC,MAAM,IAAI,KAAK,CAAC,gBAAgB,EAAE,8EAA8E,CAAC,CAAC;IAAC,CAAC;AAChI,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAY,EAAE,SAAS,GAAG,KAAK;IAC/D,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QAC3E,IAAI,CAAC,GAAG,KAAK,OAAO,CAAC,MAAM,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QACjE,MAAM,IAAI,KAAK,CAAC,gBAAgB,EAAE,+DAA+D,CAAC,CAAC;IACrG,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAY;IAC3C,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACnC,MAAM,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,CAAC,KAAK,YAAY,KAAK,IAAI,MAAM,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC;YAAE,MAAM,KAAK,CAAC;IAC3F,CAAC;IACD,MAAM,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AAChC,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function probeSsh(port: number, signal?: AbortSignal, timeoutMs?: number): Promise<void>;
package/dist/probe.js ADDED
@@ -0,0 +1,45 @@
1
+ import net from 'node:net';
2
+ import { bounded, Fault } from "./core.js";
3
+ export async function probeSsh(port, signal, timeoutMs = 3000) {
4
+ return bounded(inner => new Promise((resolve, reject) => {
5
+ const socket = net.connect({ port, host: '127.0.0.1' });
6
+ let text = '', done = false;
7
+ const abort = () => finish(new Fault('aborted'));
8
+ const finish = (error) => {
9
+ if (done)
10
+ return;
11
+ done = true;
12
+ inner.removeEventListener('abort', abort);
13
+ socket.destroy();
14
+ if (error)
15
+ reject(error);
16
+ else
17
+ resolve();
18
+ };
19
+ inner.addEventListener('abort', abort, { once: true });
20
+ if (inner.aborted) {
21
+ abort();
22
+ return;
23
+ }
24
+ socket.on('error', () => finish(new Fault('remote-unavailable')));
25
+ socket.on('close', () => { if (!done)
26
+ finish(new Fault('remote-unavailable')); });
27
+ socket.on('data', (chunk) => {
28
+ text += chunk.toString('ascii');
29
+ if (text.length > 4096) {
30
+ finish(new Fault('remote-unavailable'));
31
+ return;
32
+ }
33
+ const lines = text.split('\n');
34
+ for (const line of lines.slice(0, -1)) {
35
+ if (/^SSH-(2\.0|1\.99)-[!-~]+(?: .*)?\r?$/.test(line) && line.length <= 255) {
36
+ finish();
37
+ return;
38
+ }
39
+ }
40
+ if (lines.length > 8)
41
+ finish(new Fault('remote-unavailable'));
42
+ });
43
+ }), timeoutMs, signal);
44
+ }
45
+ //# sourceMappingURL=probe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"probe.js","sourceRoot":"","sources":["../src/probe.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,UAAU,CAAC;AAC3B,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAE3C,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,IAAY,EAAE,MAAoB,EAAE,SAAS,GAAG,IAAI;IACjF,OAAO,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC5D,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC;QACxD,IAAI,IAAI,GAAG,EAAE,EAAE,IAAI,GAAG,KAAK,CAAC;QAC5B,MAAM,KAAK,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;QACjD,MAAM,MAAM,GAAG,CAAC,KAAa,EAAE,EAAE;YAC/B,IAAI,IAAI;gBAAE,OAAO;YACjB,IAAI,GAAG,IAAI,CAAC;YACZ,KAAK,CAAC,mBAAmB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YAC1C,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,IAAI,KAAK;gBAAE,MAAM,CAAC,KAAK,CAAC,CAAC;;gBAAM,OAAO,EAAE,CAAC;QAC3C,CAAC,CAAC;QACF,KAAK,CAAC,gBAAgB,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACvD,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YAAC,KAAK,EAAE,CAAC;YAAC,OAAO;QAAC,CAAC;QACvC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC;QAClE,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,IAAI;YAAE,MAAM,CAAC,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAClF,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;YAClC,IAAI,IAAI,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YAChC,IAAI,IAAI,CAAC,MAAM,GAAG,IAAI,EAAE,CAAC;gBAAC,MAAM,CAAC,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC,CAAC;gBAAC,OAAO;YAAC,CAAC;YAC5E,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC/B,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACtC,IAAI,sCAAsC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC;oBAAC,MAAM,EAAE,CAAC;oBAAC,OAAO;gBAAC,CAAC;YACpG,CAAC;YACD,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;gBAAE,MAAM,CAAC,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC,CAAC;QAChE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;AACzB,CAAC"}
@@ -0,0 +1,77 @@
1
+ import type { Profile } from './config.ts';
2
+ import type { Transport } from './sdk-transport.ts';
3
+ import type { OpenStream } from './forwarding.ts';
4
+ import type { Clock, FaultCode } from './core.ts';
5
+ export type State = 'paused' | 'connecting' | 'healthy' | 'reconnecting' | FaultCode;
6
+ export interface Status {
7
+ name: string;
8
+ state: State;
9
+ localPort: number;
10
+ remotePort: number;
11
+ tunnelId: string;
12
+ clusterId?: string;
13
+ paused: boolean;
14
+ relayConnected: boolean;
15
+ attempt: number;
16
+ lastHealthyAt?: number;
17
+ nextRetryAt?: number;
18
+ cause?: {
19
+ code: FaultCode;
20
+ message: string;
21
+ };
22
+ }
23
+ interface Listener {
24
+ listen(): Promise<void>;
25
+ close(): Promise<void>;
26
+ setTarget(target: OpenStream | undefined): void;
27
+ }
28
+ interface Dependencies {
29
+ transport: Transport;
30
+ forwarder: Listener;
31
+ probe(signal: AbortSignal): Promise<void>;
32
+ log(status: Status): void;
33
+ clock?: Clock;
34
+ random?: () => number;
35
+ }
36
+ export declare class Recovery {
37
+ readonly profile: Profile;
38
+ private readonly deps;
39
+ private readonly timer;
40
+ private readonly random;
41
+ private session;
42
+ private sessionLife;
43
+ private active;
44
+ private serial;
45
+ private generation;
46
+ private cancelTick;
47
+ private running;
48
+ private listening;
49
+ private state;
50
+ private attempts;
51
+ private remoteFailures;
52
+ private lastHealthyAt;
53
+ private nextCheck;
54
+ private nextRetry;
55
+ private lastTick;
56
+ private graceUntil;
57
+ private fault;
58
+ constructor(profile: Profile, deps: Dependencies);
59
+ status(): Status;
60
+ private transition;
61
+ start(): void;
62
+ private tick;
63
+ private begin;
64
+ private connect;
65
+ private check;
66
+ private probe;
67
+ private healthy;
68
+ private fail;
69
+ private onEvent;
70
+ private dispose;
71
+ private retire;
72
+ reconnect(): void;
73
+ pause(): Promise<void>;
74
+ resume(): void;
75
+ stop(): Promise<void>;
76
+ }
77
+ export {};
@@ -0,0 +1,265 @@
1
+ import { clock as realClock, bounded, Fault, safeFault } from "./core.js";
2
+ export class Recovery {
3
+ profile;
4
+ deps;
5
+ timer;
6
+ random;
7
+ session;
8
+ sessionLife;
9
+ active;
10
+ serial = 0;
11
+ generation = 0;
12
+ cancelTick;
13
+ running = false;
14
+ listening = false;
15
+ state = 'connecting';
16
+ attempts = 0;
17
+ remoteFailures = 0;
18
+ lastHealthyAt;
19
+ nextCheck = 0;
20
+ nextRetry = 0;
21
+ lastTick = 0;
22
+ graceUntil = 0;
23
+ fault;
24
+ constructor(profile, deps) {
25
+ this.profile = { ...profile };
26
+ this.deps = deps;
27
+ this.timer = deps.clock ?? realClock;
28
+ this.random = deps.random ?? Math.random;
29
+ this.state = profile.paused ? 'paused' : 'connecting';
30
+ }
31
+ status() {
32
+ return { name: this.profile.name, tunnelId: this.profile.tunnelId,
33
+ ...(this.profile.clusterId ? { clusterId: this.profile.clusterId } : {}),
34
+ localPort: this.profile.localPort, remotePort: this.profile.remotePort, state: this.state,
35
+ paused: this.profile.paused, relayConnected: this.session?.connected ?? false, attempt: this.attempts,
36
+ ...(this.lastHealthyAt !== undefined ? { lastHealthyAt: this.lastHealthyAt } : {}),
37
+ ...(this.nextRetry > 0 && Number.isFinite(this.nextRetry) ? { nextRetryAt: this.nextRetry } : {}),
38
+ ...(this.fault ? { cause: { code: this.fault.code, message: this.fault.message } } : {}) };
39
+ }
40
+ transition(state, fault) {
41
+ const changed = state !== this.state || fault?.code !== this.fault?.code;
42
+ this.state = state;
43
+ this.fault = fault;
44
+ if (changed)
45
+ this.deps.log(this.status());
46
+ }
47
+ start() {
48
+ if (this.running)
49
+ return;
50
+ this.running = true;
51
+ this.lastTick = this.timer.now();
52
+ this.tick();
53
+ }
54
+ tick = () => {
55
+ if (!this.running)
56
+ return;
57
+ const now = this.timer.now(), gap = now - this.lastTick;
58
+ this.lastTick = now;
59
+ if (gap > 15000 && !this.profile.paused) {
60
+ this.nextCheck = now;
61
+ if (this.state !== 'login-required' && this.state !== 'access-denied' && this.state !== 'invalid-config' &&
62
+ this.state !== 'throttled')
63
+ this.nextRetry = Math.min(this.nextRetry, now);
64
+ }
65
+ if (!this.profile.paused && !this.active) {
66
+ if (this.session) {
67
+ if (this.graceUntil && now >= this.graceUntil && !this.session.connected) {
68
+ this.fail(new Fault('retrying'));
69
+ }
70
+ else if (now >= this.nextCheck && (!this.graceUntil || this.session.connected))
71
+ this.check();
72
+ }
73
+ else if (now >= this.nextRetry)
74
+ this.connect();
75
+ }
76
+ this.cancelTick = this.timer.later(1000, this.tick);
77
+ };
78
+ begin(action) {
79
+ this.active?.controller.abort();
80
+ const controller = new AbortController(), id = ++this.serial;
81
+ this.active = { id, controller };
82
+ const valid = () => this.active?.id === id && !controller.signal.aborted &&
83
+ this.running && !this.profile.paused;
84
+ void action(controller.signal, valid).catch(error => {
85
+ if (valid())
86
+ this.fail(safeFault(error));
87
+ }).finally(() => { if (this.active?.id === id)
88
+ this.active = undefined; });
89
+ }
90
+ connect() {
91
+ this.begin(async (signal, valid) => {
92
+ await this.retire();
93
+ if (!valid())
94
+ return;
95
+ if (!this.listening) {
96
+ await bounded(() => this.deps.forwarder.listen(), 1000, signal, () => this.deps.forwarder.close(), this.timer);
97
+ this.listening = true;
98
+ }
99
+ this.transition('connecting');
100
+ const life = new AbortController();
101
+ this.sessionLife = life;
102
+ const abort = () => life.abort();
103
+ signal.addEventListener('abort', abort, { once: true });
104
+ const generation = ++this.generation;
105
+ let session;
106
+ try {
107
+ session = await bounded(inner => this.deps.transport.connect(this.profile, AbortSignal.any([inner, life.signal]), event => { if (generation === this.generation && !life.signal.aborted)
108
+ this.onEvent(event); }), 25000, signal, late => this.dispose(late), this.timer);
109
+ }
110
+ finally {
111
+ signal.removeEventListener('abort', abort);
112
+ }
113
+ if (!valid()) {
114
+ life.abort();
115
+ await this.dispose(session);
116
+ return;
117
+ }
118
+ this.session = session;
119
+ this.remoteFailures = 0;
120
+ this.deps.forwarder.setTarget(openSignal => {
121
+ if (!session.connected || generation !== this.generation || life.signal.aborted)
122
+ return Promise.reject(new Fault('retrying'));
123
+ return session.open(openSignal);
124
+ });
125
+ await this.probe(signal);
126
+ if (valid())
127
+ this.healthy();
128
+ });
129
+ }
130
+ check() {
131
+ this.begin(async (signal, valid) => {
132
+ await this.probe(signal);
133
+ if (valid())
134
+ this.healthy();
135
+ });
136
+ }
137
+ probe(signal) {
138
+ return bounded(inner => this.deps.probe(inner), 3000, signal, undefined, this.timer);
139
+ }
140
+ healthy() {
141
+ this.lastHealthyAt = this.timer.now();
142
+ this.nextCheck = this.timer.now() + 10000;
143
+ this.nextRetry = 0;
144
+ this.attempts = 0;
145
+ this.remoteFailures = 0;
146
+ this.graceUntil = 0;
147
+ this.transition('healthy');
148
+ }
149
+ fail(fault) {
150
+ if (!this.running || this.profile.paused)
151
+ return;
152
+ const now = this.timer.now();
153
+ if (this.session && this.session.connected && ++this.remoteFailures < 2 &&
154
+ ['remote-unavailable', 'timeout', 'retrying'].includes(fault.code)) {
155
+ this.nextCheck = now + 5000;
156
+ this.transition('remote-unavailable', new Fault('remote-unavailable', 'Tunnel: connected; SSH: no response. Check remote SSH/WSL.'));
157
+ return;
158
+ }
159
+ this.attempts++;
160
+ const backoff = Math.min(15000, 1000 * 2 ** Math.min(this.attempts - 1, 5));
161
+ this.nextRetry = now + Math.max(fault.retryAfterMs, Math.round(backoff * (0.5 + this.random() * 0.5)));
162
+ if (fault.code === 'login-required' || fault.code === 'access-denied' || fault.code === 'invalid-config') {
163
+ this.nextRetry = Infinity;
164
+ }
165
+ const state = fault.code === 'timeout' ? 'retrying' : fault.code;
166
+ this.transition(state, fault);
167
+ this.graceUntil = 0;
168
+ // Disposal is bounded and detached from the next generation's authority.
169
+ const old = this.session;
170
+ this.session = undefined;
171
+ this.generation++;
172
+ this.sessionLife?.abort();
173
+ this.sessionLife = undefined;
174
+ this.deps.forwarder.setTarget(undefined);
175
+ if (old)
176
+ void this.dispose(old).catch(error => this.deps.log({ ...this.status(),
177
+ cause: { code: safeFault(error).code, message: 'Client teardown exceeded its bound; its generation is cancelled.' } }));
178
+ }
179
+ onEvent(event) {
180
+ if (!this.running || this.profile.paused || !this.session)
181
+ return;
182
+ if (event.fault && ((event.kind === 'relay' && !event.connected &&
183
+ ['access-denied', 'login-required', 'invalid-config', 'throttled'].includes(event.fault.code)) ||
184
+ (event.kind === 'retry' && event.fault.code === 'throttled'))) {
185
+ this.active?.controller.abort();
186
+ this.active = undefined;
187
+ this.fail(event.fault);
188
+ return;
189
+ }
190
+ if (event.kind === 'relay') {
191
+ if (event.connected) {
192
+ this.nextCheck = this.timer.now();
193
+ this.graceUntil = 0;
194
+ }
195
+ else {
196
+ if (!this.graceUntil)
197
+ this.graceUntil = this.timer.now() + 8000;
198
+ this.transition('reconnecting', event.fault);
199
+ }
200
+ }
201
+ else if (event.kind === 'keepalive-failed')
202
+ this.nextCheck = this.timer.now();
203
+ }
204
+ dispose(session) {
205
+ return bounded(() => session.dispose(), 1000, undefined, undefined, this.timer);
206
+ }
207
+ async retire() {
208
+ this.generation++;
209
+ this.sessionLife?.abort();
210
+ this.sessionLife = undefined;
211
+ const old = this.session;
212
+ this.session = undefined;
213
+ this.deps.forwarder.setTarget(undefined);
214
+ if (old) {
215
+ try {
216
+ await this.dispose(old);
217
+ }
218
+ catch (error) {
219
+ this.deps.log({ ...this.status(), cause: { code: safeFault(error).code,
220
+ message: 'Client teardown exceeded its bound; its generation is cancelled.' } });
221
+ }
222
+ }
223
+ }
224
+ reconnect() {
225
+ if (this.profile.paused || !this.running)
226
+ return;
227
+ if (this.state === 'throttled' && this.nextRetry > this.timer.now())
228
+ return;
229
+ this.active?.controller.abort();
230
+ this.active = undefined;
231
+ this.attempts = 0;
232
+ this.nextRetry = 0;
233
+ this.graceUntil = 0;
234
+ this.connect();
235
+ }
236
+ async pause() {
237
+ this.profile.paused = true;
238
+ this.active?.controller.abort();
239
+ this.active = undefined;
240
+ this.transition('paused');
241
+ await this.retire();
242
+ await bounded(() => this.deps.forwarder.close(), 1000, undefined, undefined, this.timer);
243
+ this.listening = false;
244
+ }
245
+ resume() {
246
+ if (!this.profile.paused)
247
+ return;
248
+ this.profile.paused = false;
249
+ this.nextRetry = 0;
250
+ this.nextCheck = 0;
251
+ this.graceUntil = 0;
252
+ this.attempts = 0;
253
+ if (!this.running)
254
+ this.start();
255
+ else
256
+ this.connect();
257
+ }
258
+ async stop() {
259
+ this.running = false;
260
+ this.cancelTick?.();
261
+ this.cancelTick = undefined;
262
+ await this.pause();
263
+ }
264
+ }
265
+ //# sourceMappingURL=recovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recovery.js","sourceRoot":"","sources":["../src/recovery.ts"],"names":[],"mappings":"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"}
package/dist/rpc.d.ts ADDED
@@ -0,0 +1,30 @@
1
+ import { Fault } from './core.ts';
2
+ import type { Profile } from './config.ts';
3
+ export type Request = {
4
+ v: 1;
5
+ command: 'status';
6
+ } | {
7
+ v: 1;
8
+ command: 'logs';
9
+ } | {
10
+ v: 1;
11
+ command: 'add';
12
+ profile: Profile;
13
+ } | {
14
+ v: 1;
15
+ command: 'pause' | 'resume' | 'reconnect';
16
+ name: string;
17
+ };
18
+ export declare class RpcServer {
19
+ private readonly path;
20
+ private readonly handler;
21
+ private readonly log;
22
+ private server;
23
+ private inode;
24
+ private readonly sockets;
25
+ constructor(path: string, handler: (request: Request) => Promise<unknown>, log: (fault: Fault) => void);
26
+ listen(): Promise<void>;
27
+ private accept;
28
+ close(): Promise<void>;
29
+ }
30
+ export declare function request(path: string, value: unknown, timeoutMs?: number): Promise<unknown>;