@urateam/cli 0.1.42 → 0.1.44
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/__tests__/config-watcher.test.d.ts +2 -0
- package/dist/__tests__/config-watcher.test.d.ts.map +1 -0
- package/dist/__tests__/config-watcher.test.js +209 -0
- package/dist/__tests__/config-watcher.test.js.map +1 -0
- package/dist/__tests__/tunnel.test.d.ts +2 -0
- package/dist/__tests__/tunnel.test.d.ts.map +1 -0
- package/dist/__tests__/tunnel.test.js +256 -0
- package/dist/__tests__/tunnel.test.js.map +1 -0
- package/dist/commands/start.d.ts.map +1 -1
- package/dist/commands/start.js +186 -3
- package/dist/commands/start.js.map +1 -1
- package/dist/lib/config-watcher.d.ts +91 -0
- package/dist/lib/config-watcher.d.ts.map +1 -0
- package/dist/lib/config-watcher.js +167 -0
- package/dist/lib/config-watcher.js.map +1 -0
- package/dist/lib/tunnel.d.ts +105 -0
- package/dist/lib/tunnel.d.ts.map +1 -0
- package/dist/lib/tunnel.js +245 -0
- package/dist/lib/tunnel.js.map +1 -0
- package/package.json +3 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-watcher.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/config-watcher.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
|
|
2
|
+
import { mkdtempSync, rmSync, writeFileSync, } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { tmpdir } from "node:os";
|
|
5
|
+
import { diffRepos, hashConfig, ConfigWatcher, SAFE_REPO_FIELDS, UNSAFE_REPO_FIELDS, } from "../lib/config-watcher.js";
|
|
6
|
+
function repo(over) {
|
|
7
|
+
return {
|
|
8
|
+
url: "https://github.com/a/x.git",
|
|
9
|
+
path: "/p/x",
|
|
10
|
+
defaultBranch: "main",
|
|
11
|
+
testCommand: "pnpm test",
|
|
12
|
+
buildCommand: "pnpm build",
|
|
13
|
+
...over,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function cfg(repos) {
|
|
17
|
+
return { version: 1, repos };
|
|
18
|
+
}
|
|
19
|
+
describe("diffRepos", () => {
|
|
20
|
+
it("detects added repos", () => {
|
|
21
|
+
const prev = cfg([]);
|
|
22
|
+
const next = cfg([repo({ url: "https://github.com/a/x.git" })]);
|
|
23
|
+
const d = diffRepos(prev, next);
|
|
24
|
+
expect(d.added).toHaveLength(1);
|
|
25
|
+
expect(d.added[0].url).toBe("https://github.com/a/x.git");
|
|
26
|
+
expect(d.removed).toEqual([]);
|
|
27
|
+
expect(d.modifiedSafe).toEqual([]);
|
|
28
|
+
expect(d.modifiedUnsafe).toEqual([]);
|
|
29
|
+
});
|
|
30
|
+
it("detects removed repos", () => {
|
|
31
|
+
const prev = cfg([repo({ url: "https://github.com/a/x.git" })]);
|
|
32
|
+
const next = cfg([]);
|
|
33
|
+
const d = diffRepos(prev, next);
|
|
34
|
+
expect(d.removed).toHaveLength(1);
|
|
35
|
+
expect(d.removed[0].url).toBe("https://github.com/a/x.git");
|
|
36
|
+
expect(d.added).toEqual([]);
|
|
37
|
+
});
|
|
38
|
+
it("detects safe-field modifications and carries prev + next entries", () => {
|
|
39
|
+
const prev = cfg([repo({ testCommand: "pnpm test" })]);
|
|
40
|
+
const next = cfg([repo({ testCommand: "pnpm test --changed" })]);
|
|
41
|
+
const d = diffRepos(prev, next);
|
|
42
|
+
expect(d.modifiedSafe).toHaveLength(1);
|
|
43
|
+
expect(d.modifiedSafe[0].fields).toContain("testCommand");
|
|
44
|
+
expect(d.modifiedSafe[0].prev.testCommand).toBe("pnpm test");
|
|
45
|
+
expect(d.modifiedSafe[0].repo.testCommand).toBe("pnpm test --changed");
|
|
46
|
+
expect(d.modifiedUnsafe).toEqual([]);
|
|
47
|
+
});
|
|
48
|
+
it("detects teamId change (safe) and the diff carries the old teamId for re-keying", () => {
|
|
49
|
+
const prev = cfg([repo({ teamId: "team-old" })]);
|
|
50
|
+
const next = cfg([repo({ teamId: "team-new" })]);
|
|
51
|
+
const d = diffRepos(prev, next);
|
|
52
|
+
expect(d.modifiedSafe).toHaveLength(1);
|
|
53
|
+
expect(d.modifiedSafe[0].fields).toContain("teamId");
|
|
54
|
+
expect(d.modifiedSafe[0].prev.teamId).toBe("team-old");
|
|
55
|
+
expect(d.modifiedSafe[0].repo.teamId).toBe("team-new");
|
|
56
|
+
});
|
|
57
|
+
it("detects unsafe-field modifications (defaultBranch)", () => {
|
|
58
|
+
const prev = cfg([repo({ defaultBranch: "main" })]);
|
|
59
|
+
const next = cfg([repo({ defaultBranch: "master" })]);
|
|
60
|
+
const d = diffRepos(prev, next);
|
|
61
|
+
expect(d.modifiedUnsafe).toHaveLength(1);
|
|
62
|
+
expect(d.modifiedUnsafe[0].fields).toContain("defaultBranch");
|
|
63
|
+
expect(d.modifiedSafe).toEqual([]);
|
|
64
|
+
});
|
|
65
|
+
it("splits safe + unsafe modifications on the same repo", () => {
|
|
66
|
+
const prev = cfg([repo({ defaultBranch: "main", testCommand: "a" })]);
|
|
67
|
+
const next = cfg([repo({ defaultBranch: "develop", testCommand: "b" })]);
|
|
68
|
+
const d = diffRepos(prev, next);
|
|
69
|
+
expect(d.modifiedSafe).toHaveLength(1);
|
|
70
|
+
expect(d.modifiedUnsafe).toHaveLength(1);
|
|
71
|
+
});
|
|
72
|
+
it("returns empty diff when configs are identical", () => {
|
|
73
|
+
const same = cfg([repo({})]);
|
|
74
|
+
const d = diffRepos(same, same);
|
|
75
|
+
expect(d.added).toEqual([]);
|
|
76
|
+
expect(d.removed).toEqual([]);
|
|
77
|
+
expect(d.modifiedSafe).toEqual([]);
|
|
78
|
+
expect(d.modifiedUnsafe).toEqual([]);
|
|
79
|
+
});
|
|
80
|
+
it("classifies SAFE_REPO_FIELDS and UNSAFE_REPO_FIELDS disjointly", () => {
|
|
81
|
+
for (const f of SAFE_REPO_FIELDS) {
|
|
82
|
+
expect(UNSAFE_REPO_FIELDS).not.toContain(f);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
describe("hashConfig", () => {
|
|
87
|
+
it("returns a 64-char hex string", () => {
|
|
88
|
+
expect(hashConfig(cfg([]))).toMatch(/^[0-9a-f]{64}$/);
|
|
89
|
+
});
|
|
90
|
+
it("is deterministic for the same input", () => {
|
|
91
|
+
expect(hashConfig(cfg([repo({})]))).toBe(hashConfig(cfg([repo({})])));
|
|
92
|
+
});
|
|
93
|
+
it("changes when content changes", () => {
|
|
94
|
+
expect(hashConfig(cfg([]))).not.toBe(hashConfig(cfg([repo({})])));
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
describe("ConfigWatcher", () => {
|
|
98
|
+
let tmp;
|
|
99
|
+
let configPath;
|
|
100
|
+
beforeEach(() => {
|
|
101
|
+
tmp = mkdtempSync(join(tmpdir(), "ura-watch-"));
|
|
102
|
+
configPath = join(tmp, "config.json");
|
|
103
|
+
writeFileSync(configPath, JSON.stringify(cfg([])));
|
|
104
|
+
});
|
|
105
|
+
afterEach(() => {
|
|
106
|
+
rmSync(tmp, { recursive: true, force: true });
|
|
107
|
+
});
|
|
108
|
+
it("emits 'applied' with a diff when the reader returns a new config", async () => {
|
|
109
|
+
const initial = cfg([]);
|
|
110
|
+
const after = cfg([repo({ url: "https://github.com/a/x.git" })]);
|
|
111
|
+
// Reader returns the post-change config on every call; the watcher's
|
|
112
|
+
// diff is against its in-memory `initial`, so the first reload emits.
|
|
113
|
+
const reader = vi.fn(() => after);
|
|
114
|
+
const w = new ConfigWatcher(initial, {
|
|
115
|
+
path: configPath,
|
|
116
|
+
debounceMs: 5,
|
|
117
|
+
reader,
|
|
118
|
+
log: () => { },
|
|
119
|
+
});
|
|
120
|
+
const applied = new Promise((resolve) => w.once("applied", resolve));
|
|
121
|
+
w.reloadNow();
|
|
122
|
+
const diff = await applied;
|
|
123
|
+
expect(diff.added).toHaveLength(1);
|
|
124
|
+
expect(diff.added[0].url).toBe("https://github.com/a/x.git");
|
|
125
|
+
// After applying, subsequent same-content reloads should be no-ops.
|
|
126
|
+
const handler = vi.fn();
|
|
127
|
+
w.on("applied", handler);
|
|
128
|
+
w.reloadNow();
|
|
129
|
+
expect(handler).not.toHaveBeenCalled();
|
|
130
|
+
});
|
|
131
|
+
it("emits no 'applied' for a no-op reload", () => {
|
|
132
|
+
const initial = cfg([]);
|
|
133
|
+
const w = new ConfigWatcher(initial, {
|
|
134
|
+
path: configPath,
|
|
135
|
+
reader: () => initial,
|
|
136
|
+
log: () => { },
|
|
137
|
+
});
|
|
138
|
+
const handler = vi.fn();
|
|
139
|
+
w.on("applied", handler);
|
|
140
|
+
w.reloadNow();
|
|
141
|
+
expect(handler).not.toHaveBeenCalled();
|
|
142
|
+
});
|
|
143
|
+
it("emits 'error' and keeps the previous config when the reader throws", () => {
|
|
144
|
+
const initial = cfg([]);
|
|
145
|
+
const reader = vi.fn(() => {
|
|
146
|
+
throw new Error("zod: invalid schema");
|
|
147
|
+
});
|
|
148
|
+
const w = new ConfigWatcher(initial, {
|
|
149
|
+
path: configPath,
|
|
150
|
+
reader,
|
|
151
|
+
log: () => { },
|
|
152
|
+
});
|
|
153
|
+
const handler = vi.fn();
|
|
154
|
+
w.on("error", handler);
|
|
155
|
+
w.reloadNow();
|
|
156
|
+
expect(handler).toHaveBeenCalled();
|
|
157
|
+
expect(w.getCurrent()).toBe(initial);
|
|
158
|
+
});
|
|
159
|
+
it("keeps the previous config when the config file disappears", () => {
|
|
160
|
+
const initial = cfg([]);
|
|
161
|
+
const w = new ConfigWatcher(initial, {
|
|
162
|
+
path: configPath,
|
|
163
|
+
reader: () => null,
|
|
164
|
+
log: () => { },
|
|
165
|
+
});
|
|
166
|
+
w.reloadNow();
|
|
167
|
+
expect(w.getCurrent()).toBe(initial);
|
|
168
|
+
});
|
|
169
|
+
it("debounces 5 rapid scheduleReload calls into exactly one reload", async () => {
|
|
170
|
+
vi.useFakeTimers();
|
|
171
|
+
try {
|
|
172
|
+
const initial = cfg([]);
|
|
173
|
+
const next = cfg([repo({})]);
|
|
174
|
+
const reader = vi.fn(() => next);
|
|
175
|
+
const w = new ConfigWatcher(initial, {
|
|
176
|
+
path: configPath,
|
|
177
|
+
debounceMs: 100,
|
|
178
|
+
reader,
|
|
179
|
+
log: () => { },
|
|
180
|
+
});
|
|
181
|
+
// Don't call start() — fs.watch fires on OS time and can't be driven
|
|
182
|
+
// by fake timers. Instead exercise scheduleReload() directly so the
|
|
183
|
+
// debounce + setTimeout chain runs entirely under our control.
|
|
184
|
+
for (let i = 0; i < 5; i++)
|
|
185
|
+
w.scheduleReload();
|
|
186
|
+
expect(reader).not.toHaveBeenCalled();
|
|
187
|
+
await vi.advanceTimersByTimeAsync(99);
|
|
188
|
+
expect(reader).not.toHaveBeenCalled();
|
|
189
|
+
await vi.advanceTimersByTimeAsync(1);
|
|
190
|
+
expect(reader).toHaveBeenCalledTimes(1);
|
|
191
|
+
}
|
|
192
|
+
finally {
|
|
193
|
+
vi.useRealTimers();
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
it("stop() unwatches and cancels pending debounce timer", () => {
|
|
197
|
+
const initial = cfg([]);
|
|
198
|
+
const w = new ConfigWatcher(initial, {
|
|
199
|
+
path: configPath,
|
|
200
|
+
reader: () => initial,
|
|
201
|
+
log: () => { },
|
|
202
|
+
});
|
|
203
|
+
w.start();
|
|
204
|
+
w.stop();
|
|
205
|
+
// No exceptions; subsequent stop is a no-op.
|
|
206
|
+
expect(() => w.stop()).not.toThrow();
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
//# sourceMappingURL=config-watcher.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-watcher.test.js","sourceRoot":"","sources":["../../src/__tests__/config-watcher.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACzE,OAAO,EACL,WAAW,EACX,MAAM,EACN,aAAa,GACd,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EACL,SAAS,EACT,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,0BAA0B,CAAC;AAMlC,SAAS,IAAI,CAAC,IAA4B;IACxC,OAAO;QACL,GAAG,EAAE,4BAA4B;QACjC,IAAI,EAAE,MAAM;QACZ,aAAa,EAAE,MAAM;QACrB,WAAW,EAAE,WAAW;QACxB,YAAY,EAAE,YAAY;QAC1B,GAAG,IAAI;KACR,CAAC;AACJ,CAAC;AACD,SAAS,GAAG,CAAC,KAAsB;IACjC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC;AAC/B,CAAC;AAED,QAAQ,CAAC,WAAW,EAAE,GAAG,EAAE;IACzB,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAC7B,MAAM,IAAI,GAAG,GAAG,CAAC,EAAE,CAAC,CAAC;QACrB,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,4BAA4B,EAAE,CAAC,CAAC,CAAC,CAAC;QAChE,MAAM,CAAC,GAAG,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAChC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAChC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;QAC3D,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC9B,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACnC,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uBAAuB,EAAE,GAAG,EAAE;QAC/B,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,4BAA4B,EAAE,CAAC,CAAC,CAAC,CAAC;QAChE,MAAM,IAAI,GAAG,GAAG,CAAC,EAAE,CAAC,CAAC;QACrB,MAAM,CAAC,GAAG,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAChC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAClC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;QAC7D,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kEAAkE,EAAE,GAAG,EAAE;QAC1E,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC;QACvD,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,WAAW,EAAE,qBAAqB,EAAE,CAAC,CAAC,CAAC,CAAC;QACjE,MAAM,CAAC,GAAG,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAChC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACvC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAE,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;QAC3D,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAE,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC9D,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAE,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;QACxE,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gFAAgF,EAAE,GAAG,EAAE;QACxF,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC;QACjD,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC;QACjD,MAAM,CAAC,GAAG,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAChC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACvC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAE,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QACtD,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACxD,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;QAC5D,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;QACpD,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,aAAa,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC;QACtD,MAAM,CAAC,GAAG,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAChC,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACzC,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAE,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;QAC/D,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC7D,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,aAAa,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;QACtE,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,aAAa,EAAE,SAAS,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;QACzE,MAAM,CAAC,GAAG,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAChC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACvC,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7B,MAAM,CAAC,GAAG,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAChC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC5B,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC9B,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACnC,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+DAA+D,EAAE,GAAG,EAAE;QACvE,KAAK,MAAM,CAAC,IAAI,gBAAgB,EAAE,CAAC;YACjC,MAAM,CAAC,kBAAkB,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAQ,CAAC,CAAC;QACrD,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;IAC1B,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACxE,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACpE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,IAAI,GAAW,CAAC;IAChB,IAAI,UAAkB,CAAC;IAEvB,UAAU,CAAC,GAAG,EAAE;QACd,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,YAAY,CAAC,CAAC,CAAC;QAChD,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;QACtC,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IACH,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kEAAkE,EAAE,KAAK,IAAI,EAAE;QAChF,MAAM,OAAO,GAAG,GAAG,CAAC,EAAE,CAAC,CAAC;QACxB,MAAM,KAAK,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,4BAA4B,EAAE,CAAC,CAAC,CAAC,CAAC;QACjE,qEAAqE;QACrE,sEAAsE;QACtE,MAAM,MAAM,GAAG,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC;QAClC,MAAM,CAAC,GAAG,IAAI,aAAa,CAAC,OAAO,EAAE;YACnC,IAAI,EAAE,UAAU;YAChB,UAAU,EAAE,CAAC;YACb,MAAM;YACN,GAAG,EAAE,GAAG,EAAE,GAAE,CAAC;SACd,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,OAAO,CAAM,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;QAC1E,CAAC,CAAC,SAAS,EAAE,CAAC;QACd,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC;QAC3B,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACnC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;QAC7D,oEAAoE;QACpE,MAAM,OAAO,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QACxB,CAAC,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QACzB,CAAC,CAAC,SAAS,EAAE,CAAC;QACd,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAC/C,MAAM,OAAO,GAAG,GAAG,CAAC,EAAE,CAAC,CAAC;QACxB,MAAM,CAAC,GAAG,IAAI,aAAa,CAAC,OAAO,EAAE;YACnC,IAAI,EAAE,UAAU;YAChB,MAAM,EAAE,GAAG,EAAE,CAAC,OAAO;YACrB,GAAG,EAAE,GAAG,EAAE,GAAE,CAAC;SACd,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QACxB,CAAC,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QACzB,CAAC,CAAC,SAAS,EAAE,CAAC;QACd,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oEAAoE,EAAE,GAAG,EAAE;QAC5E,MAAM,OAAO,GAAG,GAAG,CAAC,EAAE,CAAC,CAAC;QACxB,MAAM,MAAM,GAAG,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE;YACxB,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,GAAG,IAAI,aAAa,CAAC,OAAO,EAAE;YACnC,IAAI,EAAE,UAAU;YAChB,MAAM;YACN,GAAG,EAAE,GAAG,EAAE,GAAE,CAAC;SACd,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QACxB,CAAC,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACvB,CAAC,CAAC,SAAS,EAAE,CAAC;QACd,MAAM,CAAC,OAAO,CAAC,CAAC,gBAAgB,EAAE,CAAC;QACnC,MAAM,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;QACnE,MAAM,OAAO,GAAG,GAAG,CAAC,EAAE,CAAC,CAAC;QACxB,MAAM,CAAC,GAAG,IAAI,aAAa,CAAC,OAAO,EAAE;YACnC,IAAI,EAAE,UAAU;YAChB,MAAM,EAAE,GAAG,EAAE,CAAC,IAAI;YAClB,GAAG,EAAE,GAAG,EAAE,GAAE,CAAC;SACd,CAAC,CAAC;QACH,CAAC,CAAC,SAAS,EAAE,CAAC;QACd,MAAM,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gEAAgE,EAAE,KAAK,IAAI,EAAE;QAC9E,EAAE,CAAC,aAAa,EAAE,CAAC;QACnB,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,GAAG,CAAC,EAAE,CAAC,CAAC;YACxB,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YAC7B,MAAM,MAAM,GAAG,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;YACjC,MAAM,CAAC,GAAG,IAAI,aAAa,CAAC,OAAO,EAAE;gBACnC,IAAI,EAAE,UAAU;gBAChB,UAAU,EAAE,GAAG;gBACf,MAAM;gBACN,GAAG,EAAE,GAAG,EAAE,GAAE,CAAC;aACd,CAAC,CAAC;YACH,qEAAqE;YACrE,oEAAoE;YACpE,+DAA+D;YAC/D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;gBAAE,CAAC,CAAC,cAAc,EAAE,CAAC;YAC/C,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;YACtC,MAAM,EAAE,CAAC,wBAAwB,CAAC,EAAE,CAAC,CAAC;YACtC,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;YACtC,MAAM,EAAE,CAAC,wBAAwB,CAAC,CAAC,CAAC,CAAC;YACrC,MAAM,CAAC,MAAM,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAC1C,CAAC;gBAAS,CAAC;YACT,EAAE,CAAC,aAAa,EAAE,CAAC;QACrB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC7D,MAAM,OAAO,GAAG,GAAG,CAAC,EAAE,CAAC,CAAC;QACxB,MAAM,CAAC,GAAG,IAAI,aAAa,CAAC,OAAO,EAAE;YACnC,IAAI,EAAE,UAAU;YAChB,MAAM,EAAE,GAAG,EAAE,CAAC,OAAO;YACrB,GAAG,EAAE,GAAG,EAAE,GAAE,CAAC;SACd,CAAC,CAAC;QACH,CAAC,CAAC,KAAK,EAAE,CAAC;QACV,CAAC,CAAC,IAAI,EAAE,CAAC;QACT,6CAA6C;QAC7C,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;IACvC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tunnel.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/tunnel.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from "vitest";
|
|
2
|
+
import { EventEmitter } from "node:events";
|
|
3
|
+
import { Readable } from "node:stream";
|
|
4
|
+
import { TunnelManager, CloudflaredMissingError, } from "../lib/tunnel.js";
|
|
5
|
+
/**
|
|
6
|
+
* Build a mock child-process for cloudflared. We use a real EventEmitter +
|
|
7
|
+
* Readable streams so the `data` / `exit` listeners the TunnelManager
|
|
8
|
+
* attaches behave like the real surface.
|
|
9
|
+
*/
|
|
10
|
+
function makeFakeChild() {
|
|
11
|
+
const stdout = new Readable({ read() { } });
|
|
12
|
+
const stderr = new Readable({ read() { } });
|
|
13
|
+
const child = new EventEmitter();
|
|
14
|
+
child.stdout = stdout;
|
|
15
|
+
child.stderr = stderr;
|
|
16
|
+
child.exitCode = null;
|
|
17
|
+
child.killed = false;
|
|
18
|
+
child.kill = vi.fn((_sig) => {
|
|
19
|
+
child.killed = true;
|
|
20
|
+
return true;
|
|
21
|
+
});
|
|
22
|
+
return {
|
|
23
|
+
child,
|
|
24
|
+
emitStderr: (line) => stderr.push(`${line}\n`),
|
|
25
|
+
emitExit: (code, signal) => {
|
|
26
|
+
child.exitCode = code;
|
|
27
|
+
child.emit("exit", code, signal);
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function makeOpts(overrides = {}) {
|
|
32
|
+
return {
|
|
33
|
+
mode: "cloudflare-quick",
|
|
34
|
+
localPort: 3000,
|
|
35
|
+
initialRestartDelayMs: 10,
|
|
36
|
+
maxRestartDelayMs: 100,
|
|
37
|
+
maxRestartAttempts: 3,
|
|
38
|
+
urlDetectTimeoutMs: 500,
|
|
39
|
+
log: () => { },
|
|
40
|
+
...overrides,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
describe("TunnelManager — cloudflare-quick", () => {
|
|
44
|
+
it("parses the public URL from cloudflared's stderr", async () => {
|
|
45
|
+
const { child, emitStderr } = makeFakeChild();
|
|
46
|
+
const spawnMock = vi.fn(() => child);
|
|
47
|
+
const mgr = new TunnelManager(makeOpts({ spawn: spawnMock }));
|
|
48
|
+
const startPromise = mgr.start();
|
|
49
|
+
// Give the child time to be wired up before pushing the URL.
|
|
50
|
+
setTimeout(() => {
|
|
51
|
+
emitStderr("2025-01-01 INF Starting tunnel");
|
|
52
|
+
emitStderr("2025-01-01 INF +-----------+ Your quick tunnel is up at https://abc123.trycloudflare.com");
|
|
53
|
+
}, 5);
|
|
54
|
+
const result = await startPromise;
|
|
55
|
+
expect(result.publicUrl).toBe("https://abc123.trycloudflare.com");
|
|
56
|
+
expect(result.restartCount).toBe(0);
|
|
57
|
+
expect(spawnMock).toHaveBeenCalledWith("cloudflared", expect.arrayContaining(["tunnel", "--url", "http://localhost:3000"]), expect.any(Object));
|
|
58
|
+
});
|
|
59
|
+
it("times out when no URL appears in stderr", async () => {
|
|
60
|
+
const { child } = makeFakeChild();
|
|
61
|
+
const spawnMock = vi.fn(() => child);
|
|
62
|
+
const mgr = new TunnelManager(makeOpts({ spawn: spawnMock, urlDetectTimeoutMs: 50 }));
|
|
63
|
+
await expect(mgr.start()).rejects.toThrow(/did not see/);
|
|
64
|
+
});
|
|
65
|
+
it("throws CloudflaredMissingError when spawn throws ENOENT", async () => {
|
|
66
|
+
const spawnMock = vi.fn(() => {
|
|
67
|
+
const err = new Error("ENOENT");
|
|
68
|
+
err.code = "ENOENT";
|
|
69
|
+
throw err;
|
|
70
|
+
});
|
|
71
|
+
const mgr = new TunnelManager(makeOpts({ spawn: spawnMock }));
|
|
72
|
+
await expect(mgr.start()).rejects.toBeInstanceOf(CloudflaredMissingError);
|
|
73
|
+
});
|
|
74
|
+
it("throws CloudflaredMissingError when child emits ENOENT", async () => {
|
|
75
|
+
const { child, emitExit } = makeFakeChild();
|
|
76
|
+
const spawnMock = vi.fn(() => child);
|
|
77
|
+
const mgr = new TunnelManager(makeOpts({ spawn: spawnMock, urlDetectTimeoutMs: 500 }));
|
|
78
|
+
const startPromise = mgr.start();
|
|
79
|
+
setTimeout(() => {
|
|
80
|
+
const err = new Error("ENOENT");
|
|
81
|
+
err.code = "ENOENT";
|
|
82
|
+
child.emit("error", err);
|
|
83
|
+
emitExit(127, null);
|
|
84
|
+
}, 5);
|
|
85
|
+
await expect(startPromise).rejects.toBeInstanceOf(CloudflaredMissingError);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
describe("TunnelManager — cloudflare-token", () => {
|
|
89
|
+
it("requires both token and publicUrl", async () => {
|
|
90
|
+
const mgr1 = new TunnelManager(makeOpts({ mode: "cloudflare-token" }));
|
|
91
|
+
await expect(mgr1.start()).rejects.toThrow(/token/);
|
|
92
|
+
const mgr2 = new TunnelManager(makeOpts({ mode: "cloudflare-token", token: "tok" }));
|
|
93
|
+
await expect(mgr2.start()).rejects.toThrow(/publicUrl/);
|
|
94
|
+
});
|
|
95
|
+
it("returns the static publicUrl without waiting for stderr parsing", async () => {
|
|
96
|
+
const { child } = makeFakeChild();
|
|
97
|
+
const spawnMock = vi.fn(() => child);
|
|
98
|
+
const mgr = new TunnelManager(makeOpts({
|
|
99
|
+
mode: "cloudflare-token",
|
|
100
|
+
token: "tok-abc",
|
|
101
|
+
publicUrl: "https://urateam.example.com",
|
|
102
|
+
spawn: spawnMock,
|
|
103
|
+
}));
|
|
104
|
+
const result = await mgr.start();
|
|
105
|
+
expect(result.publicUrl).toBe("https://urateam.example.com");
|
|
106
|
+
expect(spawnMock).toHaveBeenCalledWith("cloudflared", expect.arrayContaining(["tunnel", "run", "--token", "tok-abc"]), expect.any(Object));
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
describe("TunnelManager — restart-on-exit + graceful shutdown", () => {
|
|
110
|
+
it("emits 'stopped' on child exit", async () => {
|
|
111
|
+
const { child, emitStderr, emitExit } = makeFakeChild();
|
|
112
|
+
const spawnMock = vi.fn(() => child);
|
|
113
|
+
const mgr = new TunnelManager(makeOpts({ spawn: spawnMock }));
|
|
114
|
+
const startPromise = mgr.start();
|
|
115
|
+
setTimeout(() => emitStderr("Your quick tunnel is up at https://abc.trycloudflare.com"), 5);
|
|
116
|
+
await startPromise;
|
|
117
|
+
const stopped = new Promise((resolve) => mgr.once("stopped", resolve));
|
|
118
|
+
emitExit(1, null);
|
|
119
|
+
const evt = await stopped;
|
|
120
|
+
expect(evt.exitCode).toBe(1);
|
|
121
|
+
});
|
|
122
|
+
it("restarts after a non-zero exit with exponential backoff", async () => {
|
|
123
|
+
vi.useFakeTimers();
|
|
124
|
+
try {
|
|
125
|
+
const spawnedChildren = [];
|
|
126
|
+
const spawnMock = vi.fn(() => {
|
|
127
|
+
const c = makeFakeChild();
|
|
128
|
+
spawnedChildren.push(c);
|
|
129
|
+
return c.child;
|
|
130
|
+
});
|
|
131
|
+
const mgr = new TunnelManager(makeOpts({
|
|
132
|
+
spawn: spawnMock,
|
|
133
|
+
initialRestartDelayMs: 100,
|
|
134
|
+
maxRestartAttempts: 3,
|
|
135
|
+
urlDetectTimeoutMs: 9999,
|
|
136
|
+
}));
|
|
137
|
+
const startPromise = mgr.start();
|
|
138
|
+
// First child emits URL
|
|
139
|
+
spawnedChildren[0].emitStderr("Your quick tunnel is up at https://a.trycloudflare.com");
|
|
140
|
+
await startPromise;
|
|
141
|
+
// Crash the first child.
|
|
142
|
+
spawnedChildren[0].emitExit(1, null);
|
|
143
|
+
// Allow the backoff timer (100ms) to fire and the second child to spawn.
|
|
144
|
+
await vi.advanceTimersByTimeAsync(100);
|
|
145
|
+
expect(spawnMock).toHaveBeenCalledTimes(2);
|
|
146
|
+
// Crash second child; next backoff is 200ms.
|
|
147
|
+
spawnedChildren[1].emitStderr("Your quick tunnel is up at https://b.trycloudflare.com");
|
|
148
|
+
spawnedChildren[1].emitExit(1, null);
|
|
149
|
+
await vi.advanceTimersByTimeAsync(99);
|
|
150
|
+
expect(spawnMock).toHaveBeenCalledTimes(2); // not yet
|
|
151
|
+
await vi.advanceTimersByTimeAsync(1);
|
|
152
|
+
expect(spawnMock).toHaveBeenCalledTimes(3);
|
|
153
|
+
}
|
|
154
|
+
finally {
|
|
155
|
+
vi.useRealTimers();
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
it("getRestartCount() reflects supervisor restart attempts", async () => {
|
|
159
|
+
vi.useFakeTimers();
|
|
160
|
+
try {
|
|
161
|
+
const spawnedChildren = [];
|
|
162
|
+
const spawnMock = vi.fn(() => {
|
|
163
|
+
const c = makeFakeChild();
|
|
164
|
+
spawnedChildren.push(c);
|
|
165
|
+
return c.child;
|
|
166
|
+
});
|
|
167
|
+
const mgr = new TunnelManager(makeOpts({
|
|
168
|
+
spawn: spawnMock,
|
|
169
|
+
initialRestartDelayMs: 10,
|
|
170
|
+
maxRestartAttempts: 5,
|
|
171
|
+
urlDetectTimeoutMs: 9999,
|
|
172
|
+
}));
|
|
173
|
+
const startPromise = mgr.start();
|
|
174
|
+
spawnedChildren[0].emitStderr("Your quick tunnel is up at https://a.trycloudflare.com");
|
|
175
|
+
await startPromise;
|
|
176
|
+
expect(mgr.getRestartCount()).toBe(0);
|
|
177
|
+
spawnedChildren[0].emitExit(1, null);
|
|
178
|
+
await vi.advanceTimersByTimeAsync(10);
|
|
179
|
+
// Restart-attempt 1 has fired and spawned a new child.
|
|
180
|
+
expect(spawnMock).toHaveBeenCalledTimes(2);
|
|
181
|
+
expect(mgr.getRestartCount()).toBe(1);
|
|
182
|
+
}
|
|
183
|
+
finally {
|
|
184
|
+
vi.useRealTimers();
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
it("gives up after maxRestartAttempts and emits 'error'", async () => {
|
|
188
|
+
vi.useFakeTimers();
|
|
189
|
+
try {
|
|
190
|
+
const spawnedChildren = [];
|
|
191
|
+
const spawnMock = vi.fn(() => {
|
|
192
|
+
const c = makeFakeChild();
|
|
193
|
+
spawnedChildren.push(c);
|
|
194
|
+
return c.child;
|
|
195
|
+
});
|
|
196
|
+
const mgr = new TunnelManager(makeOpts({
|
|
197
|
+
spawn: spawnMock,
|
|
198
|
+
initialRestartDelayMs: 10,
|
|
199
|
+
maxRestartAttempts: 2,
|
|
200
|
+
urlDetectTimeoutMs: 9999,
|
|
201
|
+
}));
|
|
202
|
+
const errored = new Promise((resolve) => mgr.once("error", resolve));
|
|
203
|
+
const startPromise = mgr.start();
|
|
204
|
+
spawnedChildren[0].emitStderr("Your quick tunnel is up at https://a.trycloudflare.com");
|
|
205
|
+
await startPromise;
|
|
206
|
+
// Crash repeatedly past the cap.
|
|
207
|
+
for (let i = 0; i < 5; i++) {
|
|
208
|
+
if (!spawnedChildren[i])
|
|
209
|
+
break;
|
|
210
|
+
spawnedChildren[i].emitExit(1, null);
|
|
211
|
+
await vi.advanceTimersByTimeAsync(1000);
|
|
212
|
+
if (spawnedChildren[i + 1]) {
|
|
213
|
+
spawnedChildren[i + 1].emitStderr(`Your quick tunnel is up at https://x${i}.trycloudflare.com`);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
const err = await errored;
|
|
217
|
+
expect(err.message).toMatch(/giving up/);
|
|
218
|
+
}
|
|
219
|
+
finally {
|
|
220
|
+
vi.useRealTimers();
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
it("stop() SIGTERMs the child and cancels a pending restart", async () => {
|
|
224
|
+
const { child, emitStderr, emitExit } = makeFakeChild();
|
|
225
|
+
const spawnMock = vi.fn(() => child);
|
|
226
|
+
const mgr = new TunnelManager(makeOpts({
|
|
227
|
+
spawn: spawnMock,
|
|
228
|
+
initialRestartDelayMs: 60_000,
|
|
229
|
+
}));
|
|
230
|
+
const startPromise = mgr.start();
|
|
231
|
+
setTimeout(() => emitStderr("Your quick tunnel is up at https://abc.trycloudflare.com"), 5);
|
|
232
|
+
await startPromise;
|
|
233
|
+
// Trigger an exit so a restart-timer is pending.
|
|
234
|
+
emitExit(1, null);
|
|
235
|
+
// Now stop — pending restart must be cancelled.
|
|
236
|
+
const stopPromise = mgr.stop();
|
|
237
|
+
// Stop awaits the child's exit promise; that exit has already fired.
|
|
238
|
+
await stopPromise;
|
|
239
|
+
// After stop, no further spawn calls should happen.
|
|
240
|
+
expect(spawnMock).toHaveBeenCalledTimes(1);
|
|
241
|
+
});
|
|
242
|
+
it("stop() while child is running sends SIGTERM", async () => {
|
|
243
|
+
const { child, emitStderr, emitExit } = makeFakeChild();
|
|
244
|
+
const spawnMock = vi.fn(() => child);
|
|
245
|
+
const mgr = new TunnelManager(makeOpts({ spawn: spawnMock }));
|
|
246
|
+
const startPromise = mgr.start();
|
|
247
|
+
setTimeout(() => emitStderr("Your quick tunnel is up at https://abc.trycloudflare.com"), 5);
|
|
248
|
+
await startPromise;
|
|
249
|
+
const stopPromise = mgr.stop();
|
|
250
|
+
// Mock the child's exit response to SIGTERM.
|
|
251
|
+
setTimeout(() => emitExit(null, "SIGTERM"), 5);
|
|
252
|
+
await stopPromise;
|
|
253
|
+
expect(child.kill).toHaveBeenCalledWith("SIGTERM");
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
//# sourceMappingURL=tunnel.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tunnel.test.js","sourceRoot":"","sources":["../../src/__tests__/tunnel.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAwCpC,eAAO,MAAM,YAAY,SAsqBrB,CAAC"}
|