@hienlh/ppm 0.4.3 → 0.4.5
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/CHANGELOG.md +5 -3
- package/package.json +1 -1
- package/src/cli/commands/stop.ts +8 -0
- package/src/server/index.ts +12 -0
- package/src/services/tunnel.service.ts +5 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## [0.4.
|
|
3
|
+
## [0.4.5] - 2026-03-17
|
|
4
4
|
|
|
5
5
|
### Fixed
|
|
6
|
-
-
|
|
7
|
-
-
|
|
6
|
+
- Windows: graceful shutdown — Ctrl+C kills cloudflared + releases port
|
|
7
|
+
- Windows: `ppm stop` kills orphan cloudflared.exe via taskkill
|
|
8
|
+
- Windows: cloudflared tunnel uses 127.0.0.1 instead of localhost (IPv6 mismatch)
|
|
9
|
+
- npm package size reduced from 79MB to ~580KB
|
|
8
10
|
|
|
9
11
|
## [0.4.2] - 2026-03-17
|
|
10
12
|
|
package/package.json
CHANGED
package/src/cli/commands/stop.ts
CHANGED
|
@@ -45,6 +45,14 @@ export async function stopServer() {
|
|
|
45
45
|
// Kill tunnel process (independent from server)
|
|
46
46
|
if (tunnelPid) killPid(tunnelPid, "tunnel");
|
|
47
47
|
|
|
48
|
+
// Windows fallback: kill orphan cloudflared processes spawned by PPM
|
|
49
|
+
if (process.platform === "win32") {
|
|
50
|
+
try {
|
|
51
|
+
const cfPath = resolve(homedir(), ".ppm", "bin", "cloudflared.exe");
|
|
52
|
+
Bun.spawnSync(["taskkill", "/F", "/IM", "cloudflared.exe"], { stdout: "ignore", stderr: "ignore" });
|
|
53
|
+
} catch {}
|
|
54
|
+
}
|
|
55
|
+
|
|
48
56
|
cleanup();
|
|
49
57
|
console.log("PPM stopped.");
|
|
50
58
|
}
|
package/src/server/index.ts
CHANGED
|
@@ -415,6 +415,18 @@ export async function startServer(options: {
|
|
|
415
415
|
console.log(` Token: ${configService.get("auth").token}`);
|
|
416
416
|
}
|
|
417
417
|
console.log();
|
|
418
|
+
|
|
419
|
+
// Graceful shutdown — stop server + tunnel on exit (especially important on Windows)
|
|
420
|
+
const shutdown = () => {
|
|
421
|
+
try { server.stop(true); } catch {}
|
|
422
|
+
try {
|
|
423
|
+
// Dynamic import to avoid circular — tunnel may not be loaded
|
|
424
|
+
import("../services/tunnel.service.ts").then(({ tunnelService }) => tunnelService.stopTunnel()).catch(() => {});
|
|
425
|
+
} catch {}
|
|
426
|
+
};
|
|
427
|
+
process.on("SIGINT", () => { shutdown(); process.exit(0); });
|
|
428
|
+
process.on("SIGTERM", () => { shutdown(); process.exit(0); });
|
|
429
|
+
process.on("exit", shutdown);
|
|
418
430
|
}
|
|
419
431
|
|
|
420
432
|
// Internal entry point for daemon child process
|
|
@@ -20,7 +20,7 @@ class TunnelService {
|
|
|
20
20
|
const bin = await ensureCloudflared();
|
|
21
21
|
|
|
22
22
|
const proc = Bun.spawn(
|
|
23
|
-
[bin, "tunnel", "--url", `http://
|
|
23
|
+
[bin, "tunnel", "--url", `http://127.0.0.1:${port}`],
|
|
24
24
|
{ stderr: "pipe", stdout: "ignore", stdin: "ignore" },
|
|
25
25
|
);
|
|
26
26
|
this.childProcess = proc;
|
|
@@ -29,10 +29,13 @@ class TunnelService {
|
|
|
29
29
|
if (this.cleanupHandler) {
|
|
30
30
|
process.off("SIGINT", this.cleanupHandler);
|
|
31
31
|
process.off("SIGTERM", this.cleanupHandler);
|
|
32
|
+
process.off("exit", this.cleanupHandler);
|
|
32
33
|
}
|
|
33
34
|
this.cleanupHandler = () => this.stopTunnel();
|
|
34
35
|
process.on("SIGINT", this.cleanupHandler);
|
|
35
36
|
process.on("SIGTERM", this.cleanupHandler);
|
|
37
|
+
// Windows: SIGINT/SIGTERM may not fire on Ctrl+C — use 'exit' as fallback
|
|
38
|
+
process.on("exit", this.cleanupHandler);
|
|
36
39
|
|
|
37
40
|
// Read stderr to find tunnel URL, then keep draining to avoid SIGPIPE
|
|
38
41
|
const reader = proc.stderr.getReader();
|
|
@@ -81,6 +84,7 @@ class TunnelService {
|
|
|
81
84
|
if (this.cleanupHandler) {
|
|
82
85
|
process.off("SIGINT", this.cleanupHandler);
|
|
83
86
|
process.off("SIGTERM", this.cleanupHandler);
|
|
87
|
+
process.off("exit", this.cleanupHandler);
|
|
84
88
|
this.cleanupHandler = null;
|
|
85
89
|
}
|
|
86
90
|
if (this.childProcess) {
|