mirror of
https://github.com/getpaseo/paseo.git
synced 2026-10-23 17:52:49 +00:00
* feat: add remote daemon self-update from client
Adds a daemon.update.request RPC that lets the client trigger a remote
daemon update over WebSocket. The daemon runs npm update -g @getpaseo/cli,
reports progress via daemon_update_progress status events, then restarts
through the supervisor to load the new code.
New feature flag server_info.features.daemonSelfUpdate gates the UI.
The UpdateDaemonCard appears on the host settings page when the daemon
supports self-update and the app/daemon versions differ.
* fix: clean up progress subscription on unmount, use typed phase cast
Address Greptile review:
- P1: store unsubscribe ref and clean up on component unmount to prevent
listener leak during in-flight update
- P2: use DaemonUpdateProgressStatusPayload type instead of { phase?: string }
* fix: use npm install@latest and global concurrency guard
Address Greptile review:
- npm update -g can silently exit 0 without resolving major-version
gaps; switch to npm install -g @getpaseo/cli@latest
- Move daemonUpdateInProgress from per-session instance to module-level
variable so concurrent clients share the same guard
* feat(daemon): harden remote self-update
Probe the global npm CLI install before updating, keep request handling in a daemon self-update session controller, and emit scoped daemon.update.progress messages.
* test(daemon): make self-update paths platform-stable
---------
Co-authored-by: Mohamed Boudra <boudra.moha@gmail.com>
37 lines
1.5 KiB
TypeScript
37 lines
1.5 KiB
TypeScript
import { describe, expect, test } from "vitest";
|
|
|
|
import { areEquivalentPaths, createPathEquivalenceMatcher, isPathInsideRoot } from "./path.js";
|
|
|
|
describe("path equivalence", () => {
|
|
test.each([
|
|
["C:/Users/Administrator/GhostFactory", "C:\\Users\\Administrator\\GhostFactory"],
|
|
["d:\\Projects\\paseo", "D:\\Projects\\paseo"],
|
|
["C:\\Users\\Administrator\\GhostFactory\\", "C:\\Users\\Administrator\\GhostFactory"],
|
|
[String.raw`\\?\C:\Users\Administrator\GhostFactory`, "C:\\Users\\Administrator\\GhostFactory"],
|
|
[String.raw`\\?\UNC\server\share\GhostFactory`, String.raw`\\server\share\GhostFactory`],
|
|
])("matches Windows-equivalent cwd forms", (left, right) => {
|
|
expect(areEquivalentPaths(left, right)).toBe(true);
|
|
expect(createPathEquivalenceMatcher(left)(right)).toBe(true);
|
|
});
|
|
|
|
test("keeps POSIX path casing significant", () => {
|
|
expect(
|
|
areEquivalentPaths("/Users/Administrator/GhostFactory", "/users/administrator/ghostfactory"),
|
|
).toBe(false);
|
|
});
|
|
|
|
test("checks POSIX root containment without prefix false positives", () => {
|
|
expect(isPathInsideRoot("/opt/paseo", "/opt/paseo/node_modules/@getpaseo/server")).toBe(true);
|
|
expect(isPathInsideRoot("/opt/paseo", "/opt/paseo-other")).toBe(false);
|
|
});
|
|
|
|
test("checks Windows root containment case-insensitively", () => {
|
|
expect(
|
|
isPathInsideRoot("C:\\Paseo\\node_modules", "c:/paseo/node_modules/@getpaseo/server"),
|
|
).toBe(true);
|
|
expect(isPathInsideRoot("C:\\Paseo\\node_modules", "C:\\Paseo\\node_modules-other")).toBe(
|
|
false,
|
|
);
|
|
});
|
|
});
|