sleev 0.0.13 → 0.0.15
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/README.md +9 -8
- package/bin/sleev.js +84 -0
- package/package.json +37 -55
- package/postinstall.mjs +66 -0
- package/dist/auth/browser.d.ts +0 -12
- package/dist/auth/browser.js +0 -89
- package/dist/auth/browser.js.map +0 -1
- package/dist/auth/firebase-tokens.d.ts +0 -39
- package/dist/auth/firebase-tokens.js +0 -173
- package/dist/auth/firebase-tokens.js.map +0 -1
- package/dist/auth/firebase.d.ts +0 -17
- package/dist/auth/firebase.js +0 -55
- package/dist/auth/firebase.js.map +0 -1
- package/dist/auth/login.d.ts +0 -22
- package/dist/auth/login.js +0 -58
- package/dist/auth/login.js.map +0 -1
- package/dist/auth/loopback.d.ts +0 -19
- package/dist/auth/loopback.js +0 -204
- package/dist/auth/loopback.js.map +0 -1
- package/dist/auth/schema.d.ts +0 -26
- package/dist/auth/schema.js +0 -88
- package/dist/auth/schema.js.map +0 -1
- package/dist/auth/token.d.ts +0 -19
- package/dist/auth/token.js +0 -53
- package/dist/auth/token.js.map +0 -1
- package/dist/auth/verify.d.ts +0 -6
- package/dist/auth/verify.js +0 -22
- package/dist/auth/verify.js.map +0 -1
- package/dist/cli.d.ts +0 -8
- package/dist/cli.js +0 -255
- package/dist/cli.js.map +0 -1
- package/dist/config/paths.d.ts +0 -12
- package/dist/config/paths.js +0 -34
- package/dist/config/paths.js.map +0 -1
- package/dist/config/store.d.ts +0 -63
- package/dist/config/store.js +0 -270
- package/dist/config/store.js.map +0 -1
- package/dist/control/local-installations.d.ts +0 -13
- package/dist/control/local-installations.js +0 -37
- package/dist/control/local-installations.js.map +0 -1
- package/dist/daemon/config.d.ts +0 -10
- package/dist/daemon/config.js +0 -52
- package/dist/daemon/config.js.map +0 -1
- package/dist/daemon/controller.d.ts +0 -29
- package/dist/daemon/controller.js +0 -34
- package/dist/daemon/controller.js.map +0 -1
- package/dist/daemon/health.d.ts +0 -8
- package/dist/daemon/health.js +0 -47
- package/dist/daemon/health.js.map +0 -1
- package/dist/daemon/start.d.ts +0 -5
- package/dist/daemon/start.js +0 -24
- package/dist/daemon/start.js.map +0 -1
- package/dist/daemon/systemd.d.ts +0 -35
- package/dist/daemon/systemd.js +0 -181
- package/dist/daemon/systemd.js.map +0 -1
- package/dist/gateway/acquire.d.ts +0 -14
- package/dist/gateway/acquire.js +0 -112
- package/dist/gateway/acquire.js.map +0 -1
- package/dist/gateway/manifest.d.ts +0 -26
- package/dist/gateway/manifest.js +0 -98
- package/dist/gateway/manifest.js.map +0 -1
- package/dist/gateway/platform.d.ts +0 -5
- package/dist/gateway/platform.js +0 -27
- package/dist/gateway/platform.js.map +0 -1
- package/dist/harness/claude.d.ts +0 -8
- package/dist/harness/claude.js +0 -151
- package/dist/harness/claude.js.map +0 -1
- package/dist/harness/codex.d.ts +0 -10
- package/dist/harness/codex.js +0 -213
- package/dist/harness/codex.js.map +0 -1
- package/dist/harness/index.d.ts +0 -13
- package/dist/harness/index.js +0 -63
- package/dist/harness/index.js.map +0 -1
- package/dist/harness/opencode-config.d.ts +0 -8
- package/dist/harness/opencode-config.js +0 -301
- package/dist/harness/opencode-config.js.map +0 -1
- package/dist/harness/opencode.d.ts +0 -14
- package/dist/harness/opencode.js +0 -50
- package/dist/harness/opencode.js.map +0 -1
- package/dist/harness/providers.d.ts +0 -8
- package/dist/harness/providers.js +0 -30
- package/dist/harness/providers.js.map +0 -1
- package/dist/harness/types.d.ts +0 -14
- package/dist/harness/types.js +0 -2
- package/dist/harness/types.js.map +0 -1
- package/dist/product.d.ts +0 -12
- package/dist/product.js +0 -70
- package/dist/product.js.map +0 -1
- package/dist/tui/clipboard.d.ts +0 -1
- package/dist/tui/clipboard.js +0 -48
- package/dist/tui/clipboard.js.map +0 -1
- package/dist/tui/openTuiApp.d.ts +0 -1
- package/dist/tui/openTuiApp.js +0 -1436
- package/dist/tui/openTuiApp.js.map +0 -1
- package/dist/tui/pages/flow-screen.d.ts +0 -50
- package/dist/tui/pages/flow-screen.js +0 -435
- package/dist/tui/pages/flow-screen.js.map +0 -1
- package/dist/tui/pages/footer.d.ts +0 -7
- package/dist/tui/pages/footer.js +0 -14
- package/dist/tui/pages/footer.js.map +0 -1
- package/dist/tui/pages/home-screen.d.ts +0 -19
- package/dist/tui/pages/home-screen.js +0 -89
- package/dist/tui/pages/home-screen.js.map +0 -1
- package/dist/tui/pages/index.d.ts +0 -17
- package/dist/tui/pages/index.js +0 -11
- package/dist/tui/pages/index.js.map +0 -1
- package/dist/tui/pages/local-setup-screen.d.ts +0 -23
- package/dist/tui/pages/local-setup-screen.js +0 -134
- package/dist/tui/pages/local-setup-screen.js.map +0 -1
- package/dist/tui/pages/location-card.d.ts +0 -19
- package/dist/tui/pages/location-card.js +0 -116
- package/dist/tui/pages/location-card.js.map +0 -1
- package/dist/tui/pages/menu-screen.d.ts +0 -24
- package/dist/tui/pages/menu-screen.js +0 -117
- package/dist/tui/pages/menu-screen.js.map +0 -1
- package/dist/tui/pages/session-grid.d.ts +0 -23
- package/dist/tui/pages/session-grid.js +0 -552
- package/dist/tui/pages/session-grid.js.map +0 -1
- package/dist/tui/pages/setup-screen.d.ts +0 -15
- package/dist/tui/pages/setup-screen.js +0 -80
- package/dist/tui/pages/setup-screen.js.map +0 -1
- package/dist/tui/pages/terminal-log.d.ts +0 -14
- package/dist/tui/pages/terminal-log.js +0 -104
- package/dist/tui/pages/terminal-log.js.map +0 -1
- package/dist/tui/pages/welcome-screen.d.ts +0 -16
- package/dist/tui/pages/welcome-screen.js +0 -80
- package/dist/tui/pages/welcome-screen.js.map +0 -1
- package/dist/tui/saved-tokens.d.ts +0 -10
- package/dist/tui/saved-tokens.js +0 -104
- package/dist/tui/saved-tokens.js.map +0 -1
- package/dist/tui/theme.d.ts +0 -25
- package/dist/tui/theme.js +0 -27
- package/dist/tui/theme.js.map +0 -1
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { FirebaseTokenManager } from "../auth/firebase-tokens.js";
|
|
2
|
-
export type CreatedLocalInstallation = {
|
|
3
|
-
installationId: string;
|
|
4
|
-
accountId: string;
|
|
5
|
-
credential: string;
|
|
6
|
-
controlUrl: string;
|
|
7
|
-
};
|
|
8
|
-
export type CreateLocalInstallationOptions = {
|
|
9
|
-
label?: string | null;
|
|
10
|
-
manager?: FirebaseTokenManager;
|
|
11
|
-
fetchImpl?: typeof fetch;
|
|
12
|
-
};
|
|
13
|
-
export declare function createLocalInstallation(options?: CreateLocalInstallationOptions): Promise<CreatedLocalInstallation>;
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
// Creates a local installation in control after Firebase sign-in (when the
|
|
2
|
-
// user selects local mode) and returns the credential the installed-local
|
|
3
|
-
// daemon will use for usage uploads.
|
|
4
|
-
import { FirebaseTokenManager } from "../auth/firebase-tokens.js";
|
|
5
|
-
import { apiOrigin } from "../product.js";
|
|
6
|
-
export async function createLocalInstallation(options = {}) {
|
|
7
|
-
const manager = options.manager ?? new FirebaseTokenManager();
|
|
8
|
-
const fetchImpl = options.fetchImpl ?? fetch;
|
|
9
|
-
const controlUrl = apiOrigin();
|
|
10
|
-
const idToken = await manager.getIdToken();
|
|
11
|
-
const response = await fetchImpl(`${controlUrl}/api/local/installations`, {
|
|
12
|
-
method: "POST",
|
|
13
|
-
headers: {
|
|
14
|
-
authorization: `Bearer ${idToken}`,
|
|
15
|
-
"content-type": "application/json",
|
|
16
|
-
},
|
|
17
|
-
body: JSON.stringify({ label: options.label ?? null }),
|
|
18
|
-
});
|
|
19
|
-
if (!response.ok) {
|
|
20
|
-
throw new Error(`Control rejected local installation creation (HTTP ${response.status}).`);
|
|
21
|
-
}
|
|
22
|
-
const body = (await response.json().catch(() => null));
|
|
23
|
-
if (!body ||
|
|
24
|
-
typeof body.installation_id !== "string" ||
|
|
25
|
-
typeof body.account_id !== "string" ||
|
|
26
|
-
typeof body.credential !== "string" ||
|
|
27
|
-
!body.credential.startsWith("slv_inst_")) {
|
|
28
|
-
throw new Error("Control returned an unexpected local installation body.");
|
|
29
|
-
}
|
|
30
|
-
return {
|
|
31
|
-
installationId: body.installation_id,
|
|
32
|
-
accountId: body.account_id,
|
|
33
|
-
credential: body.credential,
|
|
34
|
-
controlUrl,
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
//# sourceMappingURL=local-installations.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"local-installations.js","sourceRoot":"","sources":["../../src/control/local-installations.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,0EAA0E;AAC1E,qCAAqC;AACrC,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAe1C,MAAM,CAAC,KAAK,UAAU,uBAAuB,CACzC,UAA0C,EAAE;IAE5C,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,IAAI,oBAAoB,EAAE,CAAC;IAC9D,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,KAAK,CAAC;IAC7C,MAAM,UAAU,GAAG,SAAS,EAAE,CAAC;IAC/B,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,EAAE,CAAC;IAE3C,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,GAAG,UAAU,0BAA0B,EAAE;QACtE,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACL,aAAa,EAAE,UAAU,OAAO,EAAE;YAClC,cAAc,EAAE,kBAAkB;SACrC;QACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,IAAI,EAAE,CAAC;KACzD,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CACX,sDAAsD,QAAQ,CAAC,MAAM,IAAI,CAC5E,CAAC;IACN,CAAC;IAED,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAI7C,CAAC;IAET,IACI,CAAC,IAAI;QACL,OAAO,IAAI,CAAC,eAAe,KAAK,QAAQ;QACxC,OAAO,IAAI,CAAC,UAAU,KAAK,QAAQ;QACnC,OAAO,IAAI,CAAC,UAAU,KAAK,QAAQ;QACnC,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,WAAW,CAAC,EAC1C,CAAC;QACC,MAAM,IAAI,KAAK,CACX,yDAAyD,CAC5D,CAAC;IACN,CAAC;IAED,OAAO;QACH,cAAc,EAAE,IAAI,CAAC,eAAe;QACpC,SAAS,EAAE,IAAI,CAAC,UAAU;QAC1B,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,UAAU;KACb,CAAC;AACN,CAAC"}
|
package/dist/daemon/config.d.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import type { SleevedConfig } from "../config/store.js";
|
|
2
|
-
export type GatewayConfig = {
|
|
3
|
-
account_id: string;
|
|
4
|
-
installation_id: string;
|
|
5
|
-
credential: string;
|
|
6
|
-
control_url: string;
|
|
7
|
-
};
|
|
8
|
-
export declare function buildGatewayConfig(config: SleevedConfig): GatewayConfig | null;
|
|
9
|
-
export declare function writeGatewayConfig(config: SleevedConfig): Promise<string>;
|
|
10
|
-
export declare function clearGatewayConfig(): Promise<void>;
|
package/dist/daemon/config.js
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
// Bridges the credential sleeved persists into the JSON file the gateway
|
|
2
|
-
// daemon reads at startup (its InstalledLocalConfig). The two sides use
|
|
3
|
-
// different shapes: sleeved stores camelCase `localInstallation` plus the
|
|
4
|
-
// account id under `auth`, while the daemon expects a flat snake_case
|
|
5
|
-
// document. This module is the producer; the gateway is the consumer.
|
|
6
|
-
import fs from "node:fs/promises";
|
|
7
|
-
import path from "node:path";
|
|
8
|
-
import { resolveSleevedPaths } from "../config/paths.js";
|
|
9
|
-
// Returns the daemon config, or null when sleeved is not in a state that can
|
|
10
|
-
// configure the daemon (signed out, or local installation not provisioned).
|
|
11
|
-
export function buildGatewayConfig(config) {
|
|
12
|
-
const accountId = config.auth.accountId;
|
|
13
|
-
const local = config.localInstallation;
|
|
14
|
-
if (!config.auth.signedIn || !accountId || !local) {
|
|
15
|
-
return null;
|
|
16
|
-
}
|
|
17
|
-
return {
|
|
18
|
-
account_id: accountId,
|
|
19
|
-
installation_id: local.installationId,
|
|
20
|
-
credential: local.credential,
|
|
21
|
-
control_url: local.controlUrl,
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
// Writes the daemon config file (0600) and returns its path. Throws if the
|
|
25
|
-
// config is not materializable — callers should only start the daemon when
|
|
26
|
-
// buildGatewayConfig would succeed.
|
|
27
|
-
export async function writeGatewayConfig(config) {
|
|
28
|
-
const gateway = buildGatewayConfig(config);
|
|
29
|
-
if (gateway === null) {
|
|
30
|
-
throw new Error("Cannot write gateway config: not signed in or local installation missing.");
|
|
31
|
-
}
|
|
32
|
-
const paths = resolveSleevedPaths();
|
|
33
|
-
await fs.mkdir(path.dirname(paths.gatewayConfigFile), { recursive: true });
|
|
34
|
-
await fs.writeFile(paths.gatewayConfigFile, `${JSON.stringify(gateway, null, 2)}\n`, { mode: 0o600 });
|
|
35
|
-
return paths.gatewayConfigFile;
|
|
36
|
-
}
|
|
37
|
-
// Removes the daemon config file (used on sign-out / teardown). Absent file
|
|
38
|
-
// is not an error.
|
|
39
|
-
export async function clearGatewayConfig() {
|
|
40
|
-
const paths = resolveSleevedPaths();
|
|
41
|
-
try {
|
|
42
|
-
await fs.unlink(paths.gatewayConfigFile);
|
|
43
|
-
}
|
|
44
|
-
catch (error) {
|
|
45
|
-
if (!(error instanceof Error &&
|
|
46
|
-
"code" in error &&
|
|
47
|
-
error.code === "ENOENT")) {
|
|
48
|
-
throw error;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
//# sourceMappingURL=config.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/daemon/config.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,wEAAwE;AACxE,0EAA0E;AAC1E,sEAAsE;AACtE,sEAAsE;AACtE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAWzD,6EAA6E;AAC7E,4EAA4E;AAC5E,MAAM,UAAU,kBAAkB,CAC9B,MAAqB;IAErB,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC;IACxC,MAAM,KAAK,GAAG,MAAM,CAAC,iBAAiB,CAAC;IACvC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,SAAS,IAAI,CAAC,KAAK,EAAE,CAAC;QAChD,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,OAAO;QACH,UAAU,EAAE,SAAS;QACrB,eAAe,EAAE,KAAK,CAAC,cAAc;QACrC,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,WAAW,EAAE,KAAK,CAAC,UAAU;KAChC,CAAC;AACN,CAAC;AAED,2EAA2E;AAC3E,2EAA2E;AAC3E,oCAAoC;AACpC,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACpC,MAAqB;IAErB,MAAM,OAAO,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAC3C,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CACX,2EAA2E,CAC9E,CAAC;IACN,CAAC;IACD,MAAM,KAAK,GAAG,mBAAmB,EAAE,CAAC;IACpC,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3E,MAAM,EAAE,CAAC,SAAS,CACd,KAAK,CAAC,iBAAiB,EACvB,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EACvC,EAAE,IAAI,EAAE,KAAK,EAAE,CAClB,CAAC;IACF,OAAO,KAAK,CAAC,iBAAiB,CAAC;AACnC,CAAC;AAED,4EAA4E;AAC5E,mBAAmB;AACnB,MAAM,CAAC,KAAK,UAAU,kBAAkB;IACpC,MAAM,KAAK,GAAG,mBAAmB,EAAE,CAAC;IACpC,IAAI,CAAC;QACD,MAAM,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;IAC7C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,IACI,CAAC,CACG,KAAK,YAAY,KAAK;YACtB,MAAM,IAAI,KAAK;YACd,KAA+B,CAAC,IAAI,KAAK,QAAQ,CACrD,EACH,CAAC;YACC,MAAM,KAAK,CAAC;QAChB,CAAC;IACL,CAAC;AACL,CAAC"}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import type { SleevedConfig } from "../config/store.js";
|
|
2
|
-
export type DaemonBackend = "systemd";
|
|
3
|
-
export type DaemonStatus = {
|
|
4
|
-
backend: DaemonBackend;
|
|
5
|
-
running: boolean;
|
|
6
|
-
healthy: boolean;
|
|
7
|
-
configured: boolean | null;
|
|
8
|
-
version: string | null;
|
|
9
|
-
pid: number | null;
|
|
10
|
-
address: string;
|
|
11
|
-
detail: string | null;
|
|
12
|
-
};
|
|
13
|
-
export interface DaemonController {
|
|
14
|
-
readonly backend: DaemonBackend;
|
|
15
|
-
start(): Promise<DaemonStatus>;
|
|
16
|
-
stop(): Promise<DaemonStatus>;
|
|
17
|
-
restart(): Promise<DaemonStatus>;
|
|
18
|
-
status(): Promise<DaemonStatus>;
|
|
19
|
-
teardown(): Promise<void>;
|
|
20
|
-
}
|
|
21
|
-
export declare class UnsupportedDaemonEnvironmentError extends Error {
|
|
22
|
-
constructor(message: string);
|
|
23
|
-
}
|
|
24
|
-
export type ControllerDeps = {
|
|
25
|
-
platform?: NodeJS.Platform;
|
|
26
|
-
env?: NodeJS.ProcessEnv;
|
|
27
|
-
systemctlAvailable?: boolean;
|
|
28
|
-
};
|
|
29
|
-
export declare function createController(config: SleevedConfig, deps?: ControllerDeps): Promise<DaemonController>;
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
// One interface over the daemon's lifecycle. The only compliant backend
|
|
2
|
-
// today is systemd --user (Linux): it survives reboot and is supervised
|
|
3
|
-
// without the CLI running. Environments that can't meet that contract fail
|
|
4
|
-
// loudly rather than degrading to a non-persistent process — a daemon that
|
|
5
|
-
// silently dies on reboot is worse than a clear error. macOS (launchd) and
|
|
6
|
-
// Windows (service) are future backends behind this same seam.
|
|
7
|
-
import os from "node:os";
|
|
8
|
-
// Thrown when the host can't run a compliant (reboot-persistent,
|
|
9
|
-
// supervised) daemon. Callers surface this; they must not fall back to an
|
|
10
|
-
// unsupervised process.
|
|
11
|
-
export class UnsupportedDaemonEnvironmentError extends Error {
|
|
12
|
-
constructor(message) {
|
|
13
|
-
super(message);
|
|
14
|
-
this.name = "UnsupportedDaemonEnvironmentError";
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
export async function createController(config, deps = {}) {
|
|
18
|
-
const platform = deps.platform ?? os.platform();
|
|
19
|
-
const env = deps.env ?? process.env;
|
|
20
|
-
if (platform !== "linux") {
|
|
21
|
-
throw new UnsupportedDaemonEnvironmentError(`The Sleeve gateway daemon is only supported on Linux ` +
|
|
22
|
-
`(systemd --user) right now; detected ${platform}. ` +
|
|
23
|
-
`macOS and Windows support is planned.`);
|
|
24
|
-
}
|
|
25
|
-
const { SystemdUserController, systemctlAvailable } = await import("./systemd.js");
|
|
26
|
-
const available = deps.systemctlAvailable ?? (await systemctlAvailable());
|
|
27
|
-
if (!available) {
|
|
28
|
-
throw new UnsupportedDaemonEnvironmentError("The Sleeve gateway daemon requires a systemd --user session " +
|
|
29
|
-
"(systemctl --user unavailable). A persistent, supervised " +
|
|
30
|
-
"daemon cannot be guaranteed without it.");
|
|
31
|
-
}
|
|
32
|
-
return new SystemdUserController(config, env);
|
|
33
|
-
}
|
|
34
|
-
//# sourceMappingURL=controller.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"controller.js","sourceRoot":"","sources":["../../src/daemon/controller.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,wEAAwE;AACxE,2EAA2E;AAC3E,2EAA2E;AAC3E,2EAA2E;AAC3E,+DAA+D;AAC/D,OAAO,EAAE,MAAM,SAAS,CAAC;AAoCzB,iEAAiE;AACjE,0EAA0E;AAC1E,wBAAwB;AACxB,MAAM,OAAO,iCAAkC,SAAQ,KAAK;IACxD,YAAY,OAAe;QACvB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,mCAAmC,CAAC;IACpD,CAAC;CACJ;AASD,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAClC,MAAqB,EACrB,OAAuB,EAAE;IAEzB,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC,QAAQ,EAAE,CAAC;IAChD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;IAEpC,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACvB,MAAM,IAAI,iCAAiC,CACvC,uDAAuD;YACnD,wCAAwC,QAAQ,IAAI;YACpD,uCAAuC,CAC9C,CAAC;IACN,CAAC;IAED,MAAM,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,GAC/C,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;IACjC,MAAM,SAAS,GAAG,IAAI,CAAC,kBAAkB,IAAI,CAAC,MAAM,kBAAkB,EAAE,CAAC,CAAC;IAC1E,IAAI,CAAC,SAAS,EAAE,CAAC;QACb,MAAM,IAAI,iCAAiC,CACvC,8DAA8D;YAC1D,2DAA2D;YAC3D,yCAAyC,CAChD,CAAC;IACN,CAAC;IACD,OAAO,IAAI,qBAAqB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAClD,CAAC"}
|
package/dist/daemon/health.d.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
export type DaemonHealth = {
|
|
2
|
-
ok: boolean;
|
|
3
|
-
mode: string;
|
|
4
|
-
configured: boolean | null;
|
|
5
|
-
version: string | null;
|
|
6
|
-
};
|
|
7
|
-
export declare function probeHealth(host: string, port: number, timeoutMs?: number, fetchImpl?: typeof fetch): Promise<DaemonHealth | null>;
|
|
8
|
-
export declare function isProcessAlive(pid: number): boolean;
|
package/dist/daemon/health.js
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
// GETs /__sleeve_local/health. Returns null on any failure (down,
|
|
2
|
-
// unreachable, timeout, non-200, garbage) — callers treat null as
|
|
3
|
-
// "not running / not ours".
|
|
4
|
-
export async function probeHealth(host, port, timeoutMs = 1500, fetchImpl = fetch) {
|
|
5
|
-
const controller = new AbortController();
|
|
6
|
-
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
7
|
-
try {
|
|
8
|
-
const response = await fetchImpl(`http://${host}:${port}/__sleeve_local/health`, { signal: controller.signal });
|
|
9
|
-
if (!response.ok)
|
|
10
|
-
return null;
|
|
11
|
-
const body = (await response.json().catch(() => null));
|
|
12
|
-
if (!body || body.ok !== true)
|
|
13
|
-
return null;
|
|
14
|
-
return {
|
|
15
|
-
ok: true,
|
|
16
|
-
mode: typeof body.mode === "string" ? body.mode : "",
|
|
17
|
-
configured: typeof body.configured === "boolean" ? body.configured : null,
|
|
18
|
-
version: typeof body.version === "string" ? body.version : null,
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
catch {
|
|
22
|
-
return null;
|
|
23
|
-
}
|
|
24
|
-
finally {
|
|
25
|
-
clearTimeout(timer);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
// True if a process with this pid exists and is signalable by us.
|
|
29
|
-
// `kill(pid, 0)` sends no signal; it only performs the existence/permission
|
|
30
|
-
// check. EPERM means it exists but is owned by someone else (still alive).
|
|
31
|
-
export function isProcessAlive(pid) {
|
|
32
|
-
if (!Number.isInteger(pid) || pid <= 0)
|
|
33
|
-
return false;
|
|
34
|
-
try {
|
|
35
|
-
process.kill(pid, 0);
|
|
36
|
-
return true;
|
|
37
|
-
}
|
|
38
|
-
catch (error) {
|
|
39
|
-
if (error instanceof Error &&
|
|
40
|
-
"code" in error &&
|
|
41
|
-
error.code === "EPERM") {
|
|
42
|
-
return true;
|
|
43
|
-
}
|
|
44
|
-
return false;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
//# sourceMappingURL=health.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/daemon/health.ts"],"names":[],"mappings":"AAUA,kEAAkE;AAClE,kEAAkE;AAClE,4BAA4B;AAC5B,MAAM,CAAC,KAAK,UAAU,WAAW,CAC7B,IAAY,EACZ,IAAY,EACZ,SAAS,GAAG,IAAI,EAChB,YAA0B,KAAK;IAE/B,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,SAAS,CAAC,CAAC;IAC9D,IAAI,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,SAAS,CAC5B,UAAU,IAAI,IAAI,IAAI,wBAAwB,EAC9C,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,CAChC,CAAC;QACF,IAAI,CAAC,QAAQ,CAAC,EAAE;YAAE,OAAO,IAAI,CAAC;QAC9B,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAK7C,CAAC;QACT,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,EAAE,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QAC3C,OAAO;YACH,EAAE,EAAE,IAAI;YACR,IAAI,EAAE,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;YACpD,UAAU,EACN,OAAO,IAAI,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI;YACjE,OAAO,EAAE,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI;SAClE,CAAC;IACN,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,IAAI,CAAC;IAChB,CAAC;YAAS,CAAC;QACP,YAAY,CAAC,KAAK,CAAC,CAAC;IACxB,CAAC;AACL,CAAC;AAED,kEAAkE;AAClE,4EAA4E;AAC5E,2EAA2E;AAC3E,MAAM,UAAU,cAAc,CAAC,GAAW;IACtC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IACrD,IAAI,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACrB,OAAO,IAAI,CAAC;IAChB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,IACI,KAAK,YAAY,KAAK;YACtB,MAAM,IAAI,KAAK;YACd,KAA+B,CAAC,IAAI,KAAK,OAAO,EACnD,CAAC;YACC,OAAO,IAAI,CAAC;QAChB,CAAC;QACD,OAAO,KAAK,CAAC;IACjB,CAAC;AACL,CAAC"}
|
package/dist/daemon/start.d.ts
DELETED
package/dist/daemon/start.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
// Raised when no gateway executable is configured. Binary acquisition will
|
|
2
|
-
// set SLEEVE_GATEWAY_BIN to the installed daemon; until then a developer
|
|
3
|
-
// sets it by hand. The CLI deliberately never runs the gateway from a
|
|
4
|
-
// source checkout.
|
|
5
|
-
export class GatewayBinaryNotConfiguredError extends Error {
|
|
6
|
-
constructor() {
|
|
7
|
-
super("No gateway binary available. Run `sleeved gateway install` " +
|
|
8
|
-
"(or set SLEEVE_GATEWAY_BIN to an explicit binary for dev).");
|
|
9
|
-
this.name = "GatewayBinaryNotConfiguredError";
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
// Resolves which gateway executable to launch: an explicit
|
|
13
|
-
// SLEEVE_GATEWAY_BIN (dev override) wins, else the acquired binary recorded
|
|
14
|
-
// in config. Throws if neither is available.
|
|
15
|
-
export function resolveGatewayBinary(config, env = process.env) {
|
|
16
|
-
const override = env.SLEEVE_GATEWAY_BIN?.trim();
|
|
17
|
-
if (override)
|
|
18
|
-
return override;
|
|
19
|
-
const installed = config.gateway?.binPath;
|
|
20
|
-
if (installed)
|
|
21
|
-
return installed;
|
|
22
|
-
throw new GatewayBinaryNotConfiguredError();
|
|
23
|
-
}
|
|
24
|
-
//# sourceMappingURL=start.js.map
|
package/dist/daemon/start.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"start.js","sourceRoot":"","sources":["../../src/daemon/start.ts"],"names":[],"mappings":"AAIA,2EAA2E;AAC3E,yEAAyE;AACzE,sEAAsE;AACtE,mBAAmB;AACnB,MAAM,OAAO,+BAAgC,SAAQ,KAAK;IACtD;QACI,KAAK,CACD,6DAA6D;YACzD,4DAA4D,CACnE,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,iCAAiC,CAAC;IAClD,CAAC;CACJ;AAED,2DAA2D;AAC3D,4EAA4E;AAC5E,6CAA6C;AAC7C,MAAM,UAAU,oBAAoB,CAChC,MAAqB,EACrB,MAAyB,OAAO,CAAC,GAAG;IAEpC,MAAM,QAAQ,GAAG,GAAG,CAAC,kBAAkB,EAAE,IAAI,EAAE,CAAC;IAChD,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC9B,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1C,IAAI,SAAS;QAAE,OAAO,SAAS,CAAC;IAChC,MAAM,IAAI,+BAA+B,EAAE,CAAC;AAChD,CAAC"}
|
package/dist/daemon/systemd.d.ts
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import type { SleevedConfig } from "../config/store.js";
|
|
2
|
-
import type { DaemonController, DaemonStatus } from "./controller.js";
|
|
3
|
-
export type CommandResult = {
|
|
4
|
-
code: number;
|
|
5
|
-
stdout: string;
|
|
6
|
-
stderr: string;
|
|
7
|
-
};
|
|
8
|
-
export type CommandRunner = (cmd: string, args: string[]) => Promise<CommandResult>;
|
|
9
|
-
export declare function systemctlAvailable(run?: CommandRunner): Promise<boolean>;
|
|
10
|
-
export declare function renderUnit(binPath: string, configPath: string, host: string, port: number): string;
|
|
11
|
-
export type SystemdDeps = {
|
|
12
|
-
run?: CommandRunner;
|
|
13
|
-
fetchImpl?: typeof fetch;
|
|
14
|
-
sleep?: (ms: number) => Promise<void>;
|
|
15
|
-
readinessTimeoutMs?: number;
|
|
16
|
-
};
|
|
17
|
-
export declare class SystemdUserController implements DaemonController {
|
|
18
|
-
readonly backend: "systemd";
|
|
19
|
-
private readonly config;
|
|
20
|
-
private readonly env;
|
|
21
|
-
private readonly run;
|
|
22
|
-
private readonly fetchImpl;
|
|
23
|
-
private readonly sleep;
|
|
24
|
-
private readonly readinessTimeoutMs;
|
|
25
|
-
constructor(config: SleevedConfig, env?: NodeJS.ProcessEnv, deps?: SystemdDeps);
|
|
26
|
-
private get address();
|
|
27
|
-
private sc;
|
|
28
|
-
private install;
|
|
29
|
-
private waitHealthy;
|
|
30
|
-
start(): Promise<DaemonStatus>;
|
|
31
|
-
stop(): Promise<DaemonStatus>;
|
|
32
|
-
restart(): Promise<DaemonStatus>;
|
|
33
|
-
status(): Promise<DaemonStatus>;
|
|
34
|
-
teardown(): Promise<void>;
|
|
35
|
-
}
|
package/dist/daemon/systemd.js
DELETED
|
@@ -1,181 +0,0 @@
|
|
|
1
|
-
// systemd --user backend (Linux): the daemon runs as a user service that
|
|
2
|
-
// starts on login and (with linger) on boot, supervised without sleeved.
|
|
3
|
-
// This is the product path on Linux.
|
|
4
|
-
import { spawn } from "node:child_process";
|
|
5
|
-
import fs from "node:fs/promises";
|
|
6
|
-
import os from "node:os";
|
|
7
|
-
import path from "node:path";
|
|
8
|
-
import { writeGatewayConfig } from "./config.js";
|
|
9
|
-
import { probeHealth } from "./health.js";
|
|
10
|
-
import { resolveGatewayBinary } from "./start.js";
|
|
11
|
-
const UNIT_NAME = "sleeve-gateway.service";
|
|
12
|
-
const defaultRun = (cmd, args) => new Promise((resolve) => {
|
|
13
|
-
const child = spawn(cmd, args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
14
|
-
let stdout = "";
|
|
15
|
-
let stderr = "";
|
|
16
|
-
child.stdout?.on("data", (d) => (stdout += d.toString()));
|
|
17
|
-
child.stderr?.on("data", (d) => (stderr += d.toString()));
|
|
18
|
-
child.once("error", () => resolve({ code: 127, stdout, stderr: "spawn failed" }));
|
|
19
|
-
child.once("exit", (code) => resolve({ code: code ?? 1, stdout, stderr }));
|
|
20
|
-
});
|
|
21
|
-
export async function systemctlAvailable(run = defaultRun) {
|
|
22
|
-
if (os.platform() !== "linux")
|
|
23
|
-
return false;
|
|
24
|
-
const { code } = await run("systemctl", ["--user", "--version"]);
|
|
25
|
-
return code === 0;
|
|
26
|
-
}
|
|
27
|
-
function userUnitPath(env) {
|
|
28
|
-
const base = env.XDG_CONFIG_HOME?.trim() || path.join(os.homedir(), ".config");
|
|
29
|
-
return path.join(base, "systemd", "user", UNIT_NAME);
|
|
30
|
-
}
|
|
31
|
-
// Pure: the unit file content. Paths are quoted so spaces survive systemd's
|
|
32
|
-
// ExecStart tokenisation.
|
|
33
|
-
export function renderUnit(binPath, configPath, host, port) {
|
|
34
|
-
const exec = [
|
|
35
|
-
q(binPath),
|
|
36
|
-
"--local-installation",
|
|
37
|
-
"--config",
|
|
38
|
-
q(configPath),
|
|
39
|
-
"--host",
|
|
40
|
-
host,
|
|
41
|
-
"--port",
|
|
42
|
-
String(port),
|
|
43
|
-
].join(" ");
|
|
44
|
-
return [
|
|
45
|
-
"[Unit]",
|
|
46
|
-
"Description=Sleeve local gateway",
|
|
47
|
-
"After=network-online.target",
|
|
48
|
-
"Wants=network-online.target",
|
|
49
|
-
"",
|
|
50
|
-
"[Service]",
|
|
51
|
-
"Type=simple",
|
|
52
|
-
`ExecStart=${exec}`,
|
|
53
|
-
"Restart=on-failure",
|
|
54
|
-
"RestartSec=2",
|
|
55
|
-
"",
|
|
56
|
-
"[Install]",
|
|
57
|
-
"WantedBy=default.target",
|
|
58
|
-
"",
|
|
59
|
-
].join("\n");
|
|
60
|
-
}
|
|
61
|
-
function q(value) {
|
|
62
|
-
return `"${value.replace(/"/g, '\\"')}"`;
|
|
63
|
-
}
|
|
64
|
-
const defaultSleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
65
|
-
export class SystemdUserController {
|
|
66
|
-
backend = "systemd";
|
|
67
|
-
config;
|
|
68
|
-
env;
|
|
69
|
-
run;
|
|
70
|
-
fetchImpl;
|
|
71
|
-
sleep;
|
|
72
|
-
readinessTimeoutMs;
|
|
73
|
-
constructor(config, env = process.env, deps = {}) {
|
|
74
|
-
this.config = config;
|
|
75
|
-
this.env = env;
|
|
76
|
-
this.run = deps.run ?? defaultRun;
|
|
77
|
-
this.fetchImpl = deps.fetchImpl ?? fetch;
|
|
78
|
-
this.sleep = deps.sleep ?? defaultSleep;
|
|
79
|
-
this.readinessTimeoutMs = deps.readinessTimeoutMs ?? 10_000;
|
|
80
|
-
}
|
|
81
|
-
get address() {
|
|
82
|
-
return `http://${this.config.proxy.host}:${this.config.proxy.port}`;
|
|
83
|
-
}
|
|
84
|
-
async sc(args) {
|
|
85
|
-
return this.run("systemctl", ["--user", ...args]);
|
|
86
|
-
}
|
|
87
|
-
// Writes the unit + the gateway config, then reloads systemd. The unit
|
|
88
|
-
// is regenerated every time so a changed binary path/port is picked up.
|
|
89
|
-
async install() {
|
|
90
|
-
const binPath = resolveGatewayBinary(this.config, this.env);
|
|
91
|
-
const configPath = await writeGatewayConfig(this.config);
|
|
92
|
-
const unitPath = userUnitPath(this.env);
|
|
93
|
-
await fs.mkdir(path.dirname(unitPath), { recursive: true });
|
|
94
|
-
await fs.writeFile(unitPath, renderUnit(binPath, configPath, this.config.proxy.host, this.config.proxy.port), { mode: 0o644 });
|
|
95
|
-
await this.sc(["daemon-reload"]);
|
|
96
|
-
}
|
|
97
|
-
async waitHealthy() {
|
|
98
|
-
const deadline = Date.now() + this.readinessTimeoutMs;
|
|
99
|
-
while (Date.now() < deadline) {
|
|
100
|
-
await this.sleep(250);
|
|
101
|
-
const health = await probeHealth(this.config.proxy.host, this.config.proxy.port, 1000, this.fetchImpl);
|
|
102
|
-
if (health)
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
105
|
-
const { stdout } = await this.sc(["is-active", UNIT_NAME]).catch(() => ({ stdout: "", code: 1, stderr: "" }));
|
|
106
|
-
throw new Error(`Gateway service did not become healthy within ` +
|
|
107
|
-
`${this.readinessTimeoutMs}ms (unit ${stdout.trim() || "inactive"}).`);
|
|
108
|
-
}
|
|
109
|
-
async start() {
|
|
110
|
-
const existing = await this.status();
|
|
111
|
-
if (existing.healthy)
|
|
112
|
-
return existing;
|
|
113
|
-
await this.install();
|
|
114
|
-
// enable --now: start immediately and on every login. Linger lets
|
|
115
|
-
// it also start at boot before any login; best-effort because it
|
|
116
|
-
// can require elevated privileges.
|
|
117
|
-
const enabled = await this.sc(["enable", "--now", UNIT_NAME]);
|
|
118
|
-
if (enabled.code !== 0) {
|
|
119
|
-
throw new Error(`systemctl --user enable --now failed: ${enabled.stderr.trim()}`);
|
|
120
|
-
}
|
|
121
|
-
await this.run("loginctl", [
|
|
122
|
-
"enable-linger",
|
|
123
|
-
os.userInfo().username,
|
|
124
|
-
]).catch(() => undefined);
|
|
125
|
-
await this.waitHealthy();
|
|
126
|
-
return this.status();
|
|
127
|
-
}
|
|
128
|
-
async stop() {
|
|
129
|
-
await this.sc(["stop", UNIT_NAME]);
|
|
130
|
-
return this.status();
|
|
131
|
-
}
|
|
132
|
-
async restart() {
|
|
133
|
-
// Reinstall first so a changed config/binary/port is applied.
|
|
134
|
-
await this.install();
|
|
135
|
-
const r = await this.sc(["restart", UNIT_NAME]);
|
|
136
|
-
if (r.code !== 0) {
|
|
137
|
-
throw new Error(`systemctl --user restart failed: ${r.stderr.trim()}`);
|
|
138
|
-
}
|
|
139
|
-
await this.waitHealthy();
|
|
140
|
-
return this.status();
|
|
141
|
-
}
|
|
142
|
-
async status() {
|
|
143
|
-
const active = await this.sc(["is-active", UNIT_NAME]);
|
|
144
|
-
const running = active.stdout.trim() === "active";
|
|
145
|
-
const health = await probeHealth(this.config.proxy.host, this.config.proxy.port, 1500, this.fetchImpl);
|
|
146
|
-
let pid = null;
|
|
147
|
-
const show = await this.sc([
|
|
148
|
-
"show",
|
|
149
|
-
"-p",
|
|
150
|
-
"MainPID",
|
|
151
|
-
"--value",
|
|
152
|
-
UNIT_NAME,
|
|
153
|
-
]);
|
|
154
|
-
const parsed = Number.parseInt(show.stdout.trim(), 10);
|
|
155
|
-
if (Number.isInteger(parsed) && parsed > 0)
|
|
156
|
-
pid = parsed;
|
|
157
|
-
return {
|
|
158
|
-
backend: this.backend,
|
|
159
|
-
running: running || health !== null,
|
|
160
|
-
healthy: health !== null,
|
|
161
|
-
configured: health?.configured ?? null,
|
|
162
|
-
version: health?.version ?? null,
|
|
163
|
-
pid,
|
|
164
|
-
address: this.address,
|
|
165
|
-
detail: health !== null
|
|
166
|
-
? null
|
|
167
|
-
: `unit ${active.stdout.trim() || "inactive"}`,
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
async teardown() {
|
|
171
|
-
await this.sc(["disable", "--now", UNIT_NAME]);
|
|
172
|
-
try {
|
|
173
|
-
await fs.unlink(userUnitPath(this.env));
|
|
174
|
-
}
|
|
175
|
-
catch {
|
|
176
|
-
/* already gone */
|
|
177
|
-
}
|
|
178
|
-
await this.sc(["daemon-reload"]);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
//# sourceMappingURL=systemd.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"systemd.js","sourceRoot":"","sources":["../../src/daemon/systemd.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { type GatewayPlatform } from "./platform.js";
|
|
2
|
-
export type InstalledGateway = {
|
|
3
|
-
binPath: string;
|
|
4
|
-
version: string;
|
|
5
|
-
platform: GatewayPlatform;
|
|
6
|
-
};
|
|
7
|
-
export type AcquireDeps = {
|
|
8
|
-
fetchImpl?: typeof fetch;
|
|
9
|
-
extract?: (archive: string, destDir: string, kind: "tar.gz" | "zip") => Promise<void>;
|
|
10
|
-
currentVersion?: string | null;
|
|
11
|
-
platform?: GatewayPlatform;
|
|
12
|
-
env?: NodeJS.ProcessEnv;
|
|
13
|
-
};
|
|
14
|
-
export declare function acquireGateway(deps?: AcquireDeps): Promise<InstalledGateway>;
|
package/dist/gateway/acquire.js
DELETED
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
// Downloads, verifies, and installs the packaged gateway binary the channel
|
|
2
|
-
// manifest points at. The CLI never builds from source; this is how the
|
|
3
|
-
// `SLEEVE_GATEWAY_BIN`-shaped seam gets populated for real users.
|
|
4
|
-
import { createHash } from "node:crypto";
|
|
5
|
-
import { spawn } from "node:child_process";
|
|
6
|
-
import fs from "node:fs/promises";
|
|
7
|
-
import os from "node:os";
|
|
8
|
-
import path from "node:path";
|
|
9
|
-
import { resolveSleevedPaths } from "../config/paths.js";
|
|
10
|
-
import { archivedBinaryCandidates, archiveExtension, currentPlatformKey, installedBinaryName, } from "./platform.js";
|
|
11
|
-
import { resolveLatestRelease, } from "./manifest.js";
|
|
12
|
-
function gatewayInstallDir(version) {
|
|
13
|
-
return path.join(resolveSleevedPaths().dataDir, "gateway", version);
|
|
14
|
-
}
|
|
15
|
-
async function pathExists(p) {
|
|
16
|
-
try {
|
|
17
|
-
await fs.access(p);
|
|
18
|
-
return true;
|
|
19
|
-
}
|
|
20
|
-
catch {
|
|
21
|
-
return false;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
async function defaultExtract(archive, destDir, _kind) {
|
|
25
|
-
// `tar` extracts both gzip tarballs and (via libarchive/bsdtar, present
|
|
26
|
-
// on macOS and Windows 10+) zips. Linux ships GNU tar but only ever
|
|
27
|
-
// receives .tar.gz, so this is safe across the three built targets.
|
|
28
|
-
//
|
|
29
|
-
// Defense-in-depth: the archive is integrity-pinned upstream, but it is
|
|
30
|
-
// still attacker-influenced if the manifest is compromised. GNU tar (and
|
|
31
|
-
// bsdtar) already strip a leading `/` and refuse `..` members by default,
|
|
32
|
-
// so extraction cannot escape destDir without an explicit -P/--absolute-
|
|
33
|
-
// names; we never pass one. (An earlier `--no-absolute-filenames` flag
|
|
34
|
-
// was not a real GNU tar option — tar rejected it with exit 64 before
|
|
35
|
-
// extracting anything.)
|
|
36
|
-
await new Promise((resolve, reject) => {
|
|
37
|
-
const child = spawn("tar", ["-xf", archive, "-C", destDir], {
|
|
38
|
-
stdio: "ignore",
|
|
39
|
-
});
|
|
40
|
-
child.once("error", reject);
|
|
41
|
-
child.once("exit", (code) => code === 0
|
|
42
|
-
? resolve()
|
|
43
|
-
: reject(new Error(`tar exited with code ${code ?? "null"}`)));
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
function sha256(buffer) {
|
|
47
|
-
return createHash("sha256").update(buffer).digest("hex");
|
|
48
|
-
}
|
|
49
|
-
// Resolves latest, and unless it's already installed, downloads + verifies +
|
|
50
|
-
// installs it. Returns the path the daemon should be launched from.
|
|
51
|
-
export async function acquireGateway(deps = {}) {
|
|
52
|
-
const fetchImpl = deps.fetchImpl ?? fetch;
|
|
53
|
-
const extract = deps.extract ?? defaultExtract;
|
|
54
|
-
const platform = deps.platform ?? currentPlatformKey();
|
|
55
|
-
const release = await resolveLatestRelease({
|
|
56
|
-
fetchImpl,
|
|
57
|
-
platform,
|
|
58
|
-
env: deps.env,
|
|
59
|
-
});
|
|
60
|
-
const binPath = path.join(gatewayInstallDir(release.version), installedBinaryName(platform));
|
|
61
|
-
// Skip when the resolved version is already installed and present.
|
|
62
|
-
if (deps.currentVersion === release.version &&
|
|
63
|
-
(await pathExists(binPath))) {
|
|
64
|
-
return { binPath, version: release.version, platform };
|
|
65
|
-
}
|
|
66
|
-
await installArtifact(release.artifact, {
|
|
67
|
-
fetchImpl,
|
|
68
|
-
extract,
|
|
69
|
-
archiveKind: archiveExtension(platform),
|
|
70
|
-
archivedNames: archivedBinaryCandidates(platform),
|
|
71
|
-
binPath,
|
|
72
|
-
});
|
|
73
|
-
return { binPath, version: release.version, platform };
|
|
74
|
-
}
|
|
75
|
-
async function installArtifact(artifact, opts) {
|
|
76
|
-
const response = await opts.fetchImpl(artifact.url);
|
|
77
|
-
if (!response.ok) {
|
|
78
|
-
throw new Error(`Failed to download gateway binary (${artifact.url}): HTTP ${response.status}.`);
|
|
79
|
-
}
|
|
80
|
-
const buffer = Buffer.from(await response.arrayBuffer());
|
|
81
|
-
if (buffer.byteLength !== artifact.size) {
|
|
82
|
-
throw new Error(`Downloaded gateway archive size ${buffer.byteLength} != expected ${artifact.size}.`);
|
|
83
|
-
}
|
|
84
|
-
const digest = sha256(buffer);
|
|
85
|
-
if (digest !== artifact.sha256) {
|
|
86
|
-
throw new Error(`Downloaded gateway archive sha256 mismatch (got ${digest}).`);
|
|
87
|
-
}
|
|
88
|
-
const work = await fs.mkdtemp(path.join(os.tmpdir(), "sleeve-gw-"));
|
|
89
|
-
try {
|
|
90
|
-
const archivePath = path.join(work, `archive.${opts.archiveKind === "zip" ? "zip" : "tar.gz"}`);
|
|
91
|
-
await fs.writeFile(archivePath, buffer);
|
|
92
|
-
await opts.extract(archivePath, work, opts.archiveKind);
|
|
93
|
-
let extracted = null;
|
|
94
|
-
for (const name of opts.archivedNames) {
|
|
95
|
-
const candidate = path.join(work, name);
|
|
96
|
-
if (await pathExists(candidate)) {
|
|
97
|
-
extracted = candidate;
|
|
98
|
-
break;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
if (extracted === null) {
|
|
102
|
-
throw new Error(`Gateway archive did not contain any of: ${opts.archivedNames.join(", ")}.`);
|
|
103
|
-
}
|
|
104
|
-
await fs.mkdir(path.dirname(opts.binPath), { recursive: true });
|
|
105
|
-
await fs.copyFile(extracted, opts.binPath);
|
|
106
|
-
await fs.chmod(opts.binPath, 0o755);
|
|
107
|
-
}
|
|
108
|
-
finally {
|
|
109
|
-
await fs.rm(work, { recursive: true, force: true });
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
//# sourceMappingURL=acquire.js.map
|