@phigon/observer 8.0.1 → 8.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.
- package/LICENSE +202 -0
- package/NOTICE +8 -0
- package/README.md +333 -303
- package/THIRD_PARTY_NOTICES.md +610 -0
- package/dist/bin/guardian-runner-darwin-amd64 +0 -0
- package/dist/bin/guardian-runner-darwin-arm64 +0 -0
- package/dist/bin/guardian-runner-linux-amd64 +0 -0
- package/dist/bin/guardian-runner-linux-arm64 +0 -0
- package/dist/bin/guardian-runner-windows-amd64.exe +0 -0
- package/dist/bin/guardian-runner-windows-arm64.exe +0 -0
- package/dist/src/action-policy.d.ts +0 -0
- package/dist/src/action-policy.d.ts.map +0 -0
- package/dist/src/action-policy.js +0 -0
- package/dist/src/action-policy.js.map +0 -0
- package/dist/src/activity/adapters/claude.d.ts +0 -0
- package/dist/src/activity/adapters/claude.d.ts.map +0 -0
- package/dist/src/activity/adapters/claude.js +0 -0
- package/dist/src/activity/adapters/claude.js.map +0 -0
- package/dist/src/activity/adapters/codex.d.ts +0 -0
- package/dist/src/activity/adapters/codex.d.ts.map +0 -0
- package/dist/src/activity/adapters/codex.js +0 -0
- package/dist/src/activity/adapters/codex.js.map +0 -0
- package/dist/src/activity/adapters/copilot.d.ts +0 -0
- package/dist/src/activity/adapters/copilot.d.ts.map +0 -0
- package/dist/src/activity/adapters/copilot.js +0 -0
- package/dist/src/activity/adapters/copilot.js.map +0 -0
- package/dist/src/activity/adapters/generic.d.ts +0 -0
- package/dist/src/activity/adapters/generic.d.ts.map +0 -0
- package/dist/src/activity/adapters/generic.js +0 -0
- package/dist/src/activity/adapters/generic.js.map +0 -0
- package/dist/src/activity/adapters/hermes.d.ts +0 -0
- package/dist/src/activity/adapters/hermes.d.ts.map +0 -0
- package/dist/src/activity/adapters/hermes.js +0 -0
- package/dist/src/activity/adapters/hermes.js.map +0 -0
- package/dist/src/activity/adapters/openai-compatible.d.ts +0 -0
- package/dist/src/activity/adapters/openai-compatible.d.ts.map +0 -0
- package/dist/src/activity/adapters/openai-compatible.js +0 -0
- package/dist/src/activity/adapters/openai-compatible.js.map +0 -0
- package/dist/src/activity/adapters/openclaw.d.ts +0 -0
- package/dist/src/activity/adapters/openclaw.d.ts.map +0 -0
- package/dist/src/activity/adapters/openclaw.js +0 -0
- package/dist/src/activity/adapters/openclaw.js.map +0 -0
- package/dist/src/activity/adapters/opencode.d.ts +0 -0
- package/dist/src/activity/adapters/opencode.d.ts.map +0 -0
- package/dist/src/activity/adapters/opencode.js +0 -0
- package/dist/src/activity/adapters/opencode.js.map +0 -0
- package/dist/src/activity/bridges.d.ts +0 -0
- package/dist/src/activity/bridges.d.ts.map +0 -0
- package/dist/src/activity/bridges.js +0 -0
- package/dist/src/activity/bridges.js.map +0 -0
- package/dist/src/activity/collector.d.ts +0 -0
- package/dist/src/activity/collector.d.ts.map +0 -0
- package/dist/src/activity/collector.js +0 -0
- package/dist/src/activity/collector.js.map +0 -0
- package/dist/src/activity/index.d.ts +0 -0
- package/dist/src/activity/index.d.ts.map +0 -0
- package/dist/src/activity/index.js +0 -0
- package/dist/src/activity/index.js.map +0 -0
- package/dist/src/activity/ingest.d.ts +0 -0
- package/dist/src/activity/ingest.d.ts.map +0 -0
- package/dist/src/activity/ingest.js +0 -0
- package/dist/src/activity/ingest.js.map +0 -0
- package/dist/src/activity/native-capabilities.d.ts +0 -0
- package/dist/src/activity/native-capabilities.d.ts.map +0 -0
- package/dist/src/activity/native-capabilities.js +0 -0
- package/dist/src/activity/native-capabilities.js.map +0 -0
- package/dist/src/activity/normalize.d.ts +0 -0
- package/dist/src/activity/normalize.d.ts.map +0 -0
- package/dist/src/activity/normalize.js +0 -0
- package/dist/src/activity/normalize.js.map +0 -0
- package/dist/src/activity/opencode-sqlite-source.d.ts +0 -0
- package/dist/src/activity/opencode-sqlite-source.d.ts.map +0 -0
- package/dist/src/activity/opencode-sqlite-source.js +0 -0
- package/dist/src/activity/opencode-sqlite-source.js.map +0 -0
- package/dist/src/activity/policy.d.ts +0 -0
- package/dist/src/activity/policy.d.ts.map +1 -1
- package/dist/src/activity/policy.js +2 -13
- package/dist/src/activity/policy.js.map +1 -1
- package/dist/src/activity/record.d.ts +0 -0
- package/dist/src/activity/record.d.ts.map +0 -0
- package/dist/src/activity/record.js +0 -0
- package/dist/src/activity/record.js.map +0 -0
- package/dist/src/activity/source-reader.d.ts +0 -0
- package/dist/src/activity/source-reader.d.ts.map +0 -0
- package/dist/src/activity/source-reader.js +0 -0
- package/dist/src/activity/source-reader.js.map +0 -0
- package/dist/src/activity/types.d.ts +0 -0
- package/dist/src/activity/types.d.ts.map +0 -0
- package/dist/src/activity/types.js +0 -0
- package/dist/src/activity/types.js.map +0 -0
- package/dist/src/agent-action-executor.d.ts +1 -0
- package/dist/src/agent-action-executor.d.ts.map +1 -1
- package/dist/src/agent-action-executor.js +7 -2
- package/dist/src/agent-action-executor.js.map +1 -1
- package/dist/src/agentic-guardian.d.ts +0 -0
- package/dist/src/agentic-guardian.d.ts.map +0 -0
- package/dist/src/agentic-guardian.js +0 -0
- package/dist/src/agentic-guardian.js.map +0 -0
- package/dist/src/atomic-replace.d.ts +0 -0
- package/dist/src/atomic-replace.d.ts.map +0 -0
- package/dist/src/atomic-replace.js +0 -0
- package/dist/src/atomic-replace.js.map +0 -0
- package/dist/src/cli.d.ts +0 -0
- package/dist/src/cli.d.ts.map +1 -1
- package/dist/src/cli.js +50 -4
- package/dist/src/cli.js.map +1 -1
- package/dist/src/config.d.ts +2 -0
- package/dist/src/config.d.ts.map +1 -1
- package/dist/src/config.js +6 -1
- package/dist/src/config.js.map +1 -1
- package/dist/src/connection-config.d.ts +3 -0
- package/dist/src/connection-config.d.ts.map +1 -0
- package/dist/src/connection-config.js +24 -0
- package/dist/src/connection-config.js.map +1 -0
- package/dist/src/content-redaction.d.ts +3 -0
- package/dist/src/content-redaction.d.ts.map +1 -0
- package/dist/src/content-redaction.js +12 -0
- package/dist/src/content-redaction.js.map +1 -0
- package/dist/src/credential-store.d.ts +1 -0
- package/dist/src/credential-store.d.ts.map +1 -1
- package/dist/src/credential-store.js +11 -1
- package/dist/src/credential-store.js.map +1 -1
- package/dist/src/custom-agent-registry.d.ts +0 -0
- package/dist/src/custom-agent-registry.d.ts.map +0 -0
- package/dist/src/custom-agent-registry.js +0 -0
- package/dist/src/custom-agent-registry.js.map +0 -0
- package/dist/src/discovery/adapters/claude.d.ts +0 -0
- package/dist/src/discovery/adapters/claude.d.ts.map +0 -0
- package/dist/src/discovery/adapters/claude.js +0 -0
- package/dist/src/discovery/adapters/claude.js.map +0 -0
- package/dist/src/discovery/adapters/codex.d.ts +0 -0
- package/dist/src/discovery/adapters/codex.d.ts.map +0 -0
- package/dist/src/discovery/adapters/codex.js +0 -0
- package/dist/src/discovery/adapters/codex.js.map +0 -0
- package/dist/src/discovery/adapters/custom.d.ts +0 -0
- package/dist/src/discovery/adapters/custom.d.ts.map +0 -0
- package/dist/src/discovery/adapters/custom.js +0 -0
- package/dist/src/discovery/adapters/custom.js.map +0 -0
- package/dist/src/discovery/adapters/generic.d.ts +0 -0
- package/dist/src/discovery/adapters/generic.d.ts.map +0 -0
- package/dist/src/discovery/adapters/generic.js +0 -0
- package/dist/src/discovery/adapters/generic.js.map +0 -0
- package/dist/src/discovery/adapters/hermes.d.ts +0 -0
- package/dist/src/discovery/adapters/hermes.d.ts.map +0 -0
- package/dist/src/discovery/adapters/hermes.js +0 -0
- package/dist/src/discovery/adapters/hermes.js.map +0 -0
- package/dist/src/discovery/adapters/openclaw.d.ts +0 -0
- package/dist/src/discovery/adapters/openclaw.d.ts.map +0 -0
- package/dist/src/discovery/adapters/openclaw.js +0 -0
- package/dist/src/discovery/adapters/openclaw.js.map +0 -0
- package/dist/src/discovery/engine.d.ts +0 -0
- package/dist/src/discovery/engine.d.ts.map +0 -0
- package/dist/src/discovery/engine.js +0 -0
- package/dist/src/discovery/engine.js.map +0 -0
- package/dist/src/discovery/evidence.d.ts +0 -0
- package/dist/src/discovery/evidence.d.ts.map +0 -0
- package/dist/src/discovery/evidence.js +0 -0
- package/dist/src/discovery/evidence.js.map +0 -0
- package/dist/src/discovery/index.d.ts +0 -0
- package/dist/src/discovery/index.d.ts.map +0 -0
- package/dist/src/discovery/index.js +0 -0
- package/dist/src/discovery/index.js.map +0 -0
- package/dist/src/discovery/known-agent.d.ts +0 -0
- package/dist/src/discovery/known-agent.d.ts.map +0 -0
- package/dist/src/discovery/known-agent.js +0 -0
- package/dist/src/discovery/known-agent.js.map +0 -0
- package/dist/src/discovery/process-identity.d.ts +0 -0
- package/dist/src/discovery/process-identity.d.ts.map +0 -0
- package/dist/src/discovery/process-identity.js +0 -0
- package/dist/src/discovery/process-identity.js.map +0 -0
- package/dist/src/discovery/system-evidence.d.ts +0 -0
- package/dist/src/discovery/system-evidence.d.ts.map +0 -0
- package/dist/src/discovery/system-evidence.js +0 -0
- package/dist/src/discovery/system-evidence.js.map +0 -0
- package/dist/src/discovery/types.d.ts +0 -0
- package/dist/src/discovery/types.d.ts.map +0 -0
- package/dist/src/discovery/types.js +0 -0
- package/dist/src/discovery/types.js.map +0 -0
- package/dist/src/event-queue.d.ts +0 -0
- package/dist/src/event-queue.d.ts.map +0 -0
- package/dist/src/event-queue.js +0 -0
- package/dist/src/event-queue.js.map +0 -0
- package/dist/src/event-spool.d.ts +0 -0
- package/dist/src/event-spool.d.ts.map +0 -0
- package/dist/src/event-spool.js +0 -0
- package/dist/src/event-spool.js.map +0 -0
- package/dist/src/generated/phigon/v1/action_pb.d.ts +0 -0
- package/dist/src/generated/phigon/v1/action_pb.d.ts.map +1 -1
- package/dist/src/generated/phigon/v1/action_pb.js +1 -1
- package/dist/src/generated/phigon/v1/action_pb.js.map +1 -1
- package/dist/src/generated/phigon/v1/common_pb.d.ts +0 -0
- package/dist/src/generated/phigon/v1/common_pb.d.ts.map +1 -1
- package/dist/src/generated/phigon/v1/common_pb.js +1 -1
- package/dist/src/generated/phigon/v1/common_pb.js.map +1 -1
- package/dist/src/generated/phigon/v1/history_sync_pb.d.ts +0 -0
- package/dist/src/generated/phigon/v1/history_sync_pb.d.ts.map +1 -1
- package/dist/src/generated/phigon/v1/history_sync_pb.js +1 -1
- package/dist/src/generated/phigon/v1/history_sync_pb.js.map +1 -1
- package/dist/src/generated/phigon/v1/identity_pb.d.ts +0 -0
- package/dist/src/generated/phigon/v1/identity_pb.d.ts.map +1 -1
- package/dist/src/generated/phigon/v1/identity_pb.js +1 -1
- package/dist/src/generated/phigon/v1/identity_pb.js.map +1 -1
- package/dist/src/generated/phigon/v1/observer_service_pb.d.ts +0 -0
- package/dist/src/generated/phigon/v1/observer_service_pb.d.ts.map +1 -1
- package/dist/src/generated/phigon/v1/observer_service_pb.js +1 -1
- package/dist/src/generated/phigon/v1/observer_service_pb.js.map +1 -1
- package/dist/src/generated/phigon/v1/policy_pb.d.ts +0 -0
- package/dist/src/generated/phigon/v1/policy_pb.d.ts.map +1 -1
- package/dist/src/generated/phigon/v1/policy_pb.js +1 -1
- package/dist/src/generated/phigon/v1/policy_pb.js.map +1 -1
- package/dist/src/generated/phigon/v1/supervision_pb.d.ts +0 -0
- package/dist/src/generated/phigon/v1/supervision_pb.d.ts.map +1 -1
- package/dist/src/generated/phigon/v1/supervision_pb.js +1 -1
- package/dist/src/generated/phigon/v1/supervision_pb.js.map +1 -1
- package/dist/src/generated/phigon/v1/telemetry_pb.d.ts +0 -0
- package/dist/src/generated/phigon/v1/telemetry_pb.d.ts.map +1 -1
- package/dist/src/generated/phigon/v1/telemetry_pb.js +1 -1
- package/dist/src/generated/phigon/v1/telemetry_pb.js.map +1 -1
- package/dist/src/guardian-containment.d.ts +1 -1
- package/dist/src/guardian-containment.d.ts.map +1 -1
- package/dist/src/guardian-containment.js +1 -1
- package/dist/src/guardian-containment.js.map +1 -1
- package/dist/src/guardian-decision-journal.d.ts +0 -0
- package/dist/src/guardian-decision-journal.d.ts.map +0 -0
- package/dist/src/guardian-decision-journal.js +0 -0
- package/dist/src/guardian-decision-journal.js.map +0 -0
- package/dist/src/guardian-execution-manifest.d.ts +0 -0
- package/dist/src/guardian-execution-manifest.d.ts.map +0 -0
- package/dist/src/guardian-execution-manifest.js +0 -0
- package/dist/src/guardian-execution-manifest.js.map +0 -0
- package/dist/src/guardian-hosted-client.d.ts +0 -0
- package/dist/src/guardian-hosted-client.d.ts.map +0 -0
- package/dist/src/guardian-hosted-client.js +0 -0
- package/dist/src/guardian-hosted-client.js.map +0 -0
- package/dist/src/guardian-managed-exec.d.ts +0 -0
- package/dist/src/guardian-managed-exec.d.ts.map +0 -0
- package/dist/src/guardian-managed-exec.js +0 -0
- package/dist/src/guardian-managed-exec.js.map +0 -0
- package/dist/src/guardian-model-bridge.d.ts +0 -0
- package/dist/src/guardian-model-bridge.d.ts.map +0 -0
- package/dist/src/guardian-model-bridge.js +0 -0
- package/dist/src/guardian-model-bridge.js.map +0 -0
- package/dist/src/guardian-native.d.ts +0 -0
- package/dist/src/guardian-native.d.ts.map +0 -0
- package/dist/src/guardian-native.js +0 -0
- package/dist/src/guardian-native.js.map +0 -0
- package/dist/src/guardian-process-monitor.d.ts +3 -1
- package/dist/src/guardian-process-monitor.d.ts.map +1 -1
- package/dist/src/guardian-process-monitor.js +56 -8
- package/dist/src/guardian-process-monitor.js.map +1 -1
- package/dist/src/health.d.ts +0 -0
- package/dist/src/health.d.ts.map +0 -0
- package/dist/src/health.js +0 -0
- package/dist/src/health.js.map +0 -0
- package/dist/src/historical-identity-store.d.ts +0 -0
- package/dist/src/historical-identity-store.d.ts.map +0 -0
- package/dist/src/historical-identity-store.js +0 -0
- package/dist/src/historical-identity-store.js.map +0 -0
- package/dist/src/index.d.ts +0 -0
- package/dist/src/index.d.ts.map +0 -0
- package/dist/src/index.js +0 -0
- package/dist/src/index.js.map +0 -0
- package/dist/src/installation.d.ts +0 -0
- package/dist/src/installation.d.ts.map +0 -0
- package/dist/src/installation.js +0 -0
- package/dist/src/installation.js.map +0 -0
- package/dist/src/machine-command-executor.d.ts +4 -0
- package/dist/src/machine-command-executor.d.ts.map +1 -1
- package/dist/src/machine-command-executor.js +34 -6
- package/dist/src/machine-command-executor.js.map +1 -1
- package/dist/src/pair.d.ts +0 -0
- package/dist/src/pair.d.ts.map +1 -1
- package/dist/src/pair.js +10 -1
- package/dist/src/pair.js.map +1 -1
- package/dist/src/remove-machine.d.ts +0 -0
- package/dist/src/remove-machine.d.ts.map +0 -0
- package/dist/src/remove-machine.js +0 -0
- package/dist/src/remove-machine.js.map +0 -0
- package/dist/src/stream-client.d.ts +3 -1
- package/dist/src/stream-client.d.ts.map +1 -1
- package/dist/src/stream-client.js +46 -5
- package/dist/src/stream-client.js.map +1 -1
- package/dist/src/stream-state.d.ts +0 -0
- package/dist/src/stream-state.d.ts.map +0 -0
- package/dist/src/stream-state.js +0 -0
- package/dist/src/stream-state.js.map +0 -0
- package/dist/src/update.d.ts +15 -0
- package/dist/src/update.d.ts.map +1 -0
- package/dist/src/update.js +87 -0
- package/dist/src/update.js.map +1 -0
- package/dist/src/windows-process.d.ts +1 -1
- package/dist/src/windows-process.d.ts.map +1 -1
- package/dist/src/windows-process.js +3 -2
- package/dist/src/windows-process.js.map +1 -1
- package/package.json +83 -78
- package/scripts/install.mjs +308 -308
- package/scripts/managed-service.mjs +0 -0
- package/scripts/verify-guardian-release.mjs +0 -0
- package/scripts/windows-app-control.mjs +0 -0
package/scripts/install.mjs
CHANGED
|
@@ -1,308 +1,308 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import { createHash } from "node:crypto";
|
|
4
|
-
import { statSync } from "node:fs";
|
|
5
|
-
import {
|
|
6
|
-
lstat,
|
|
7
|
-
mkdir,
|
|
8
|
-
readFile,
|
|
9
|
-
rename,
|
|
10
|
-
rm,
|
|
11
|
-
symlink,
|
|
12
|
-
} from "node:fs/promises";
|
|
13
|
-
import { homedir, platform } from "node:os";
|
|
14
|
-
import { basename, dirname, isAbsolute, join, resolve } from "node:path";
|
|
15
|
-
import { spawnSync } from "node:child_process";
|
|
16
|
-
import { fileURLToPath } from "node:url";
|
|
17
|
-
|
|
18
|
-
const packageName = "@phigon/observer";
|
|
19
|
-
const legacyPackageName = "phigon-observer";
|
|
20
|
-
const safeVersion = /^[0-9A-Za-z][0-9A-Za-z.+-]{0,63}$/u;
|
|
21
|
-
const sha256Pattern = /^[a-f0-9]{64}$/u;
|
|
22
|
-
|
|
23
|
-
if (process.argv[1] &&
|
|
24
|
-
process.exitCode = await main(process.argv.slice(2));
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Keep the published installer self-contained. Windows .cmd launchers require
|
|
28
|
-
// a shell; invoking npm's JS entry point keeps paths as individual arguments.
|
|
29
|
-
export function npmCommand(arguments_) {
|
|
30
|
-
if (process.platform !== "win32") return { command: "npm", arguments: arguments_ };
|
|
31
|
-
const candidates = [
|
|
32
|
-
process.env.npm_execpath,
|
|
33
|
-
join(dirname(process.execPath), "node_modules", "npm", "bin", "npm-cli.js"),
|
|
34
|
-
];
|
|
35
|
-
for (const candidate of candidates) {
|
|
36
|
-
if (!candidate || !isAbsolute(candidate) || basename(candidate).toLowerCase() !== "npm-cli.js") continue;
|
|
37
|
-
try {
|
|
38
|
-
if (statSync(candidate).isFile()) return { command: process.execPath, arguments: [candidate, ...arguments_] };
|
|
39
|
-
} catch { /* Try the Node installation's bundled npm. */ }
|
|
40
|
-
}
|
|
41
|
-
throw new Error("Cannot find npm-cli.js. Use a Node installation with npm, or run this installer through npm.");
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
async function main(argv) {
|
|
45
|
-
const [command, ...args] = argv;
|
|
46
|
-
try {
|
|
47
|
-
if (command === "install") {
|
|
48
|
-
await install(parseOptions(args));
|
|
49
|
-
return 0;
|
|
50
|
-
}
|
|
51
|
-
if (command === "rollback") {
|
|
52
|
-
await rollback(parseOptions(args));
|
|
53
|
-
return 0;
|
|
54
|
-
}
|
|
55
|
-
if (command === "status") {
|
|
56
|
-
await status(parseOptions(args));
|
|
57
|
-
return 0;
|
|
58
|
-
}
|
|
59
|
-
process.stderr.write(help());
|
|
60
|
-
return 2;
|
|
61
|
-
} catch (error) {
|
|
62
|
-
const message = error instanceof Error ? error.message : "Unknown error.";
|
|
63
|
-
process.stderr.write(`Observer installation failed: ${message}\n`);
|
|
64
|
-
return 1;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
async function install(options) {
|
|
69
|
-
const version = required(options, "version");
|
|
70
|
-
const artifactValue = required(options, "artifact");
|
|
71
|
-
const expectedSHA = required(options, "sha256").toLowerCase();
|
|
72
|
-
if (!safeVersion.test(version)) throw new Error("Invalid release version.");
|
|
73
|
-
if (!sha256Pattern.test(expectedSHA)) {
|
|
74
|
-
throw new Error("--sha256 must be a lowercase SHA-256 digest.");
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
const prefix = installPrefix(options);
|
|
78
|
-
const versions = join(prefix, "versions");
|
|
79
|
-
const staging = join(versions, `.${version}.${process.pid}.staging`);
|
|
80
|
-
const destination = join(versions, version);
|
|
81
|
-
const artifact = await acquireArtifact(artifactValue, prefix);
|
|
82
|
-
const actualSHA = await digestFile(artifact.path);
|
|
83
|
-
if (actualSHA !== expectedSHA) {
|
|
84
|
-
await artifact.cleanup();
|
|
85
|
-
throw new Error(
|
|
86
|
-
`Checksum mismatch for ${basename(artifact.path)}: expected ${expectedSHA}, received ${actualSHA}.`,
|
|
87
|
-
);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
await mkdir(versions, { recursive: true, mode: 0o700 });
|
|
91
|
-
await rm(staging, { recursive: true, force: true });
|
|
92
|
-
const npm = npmCommand([
|
|
93
|
-
"install",
|
|
94
|
-
"--global",
|
|
95
|
-
"--prefix",
|
|
96
|
-
staging,
|
|
97
|
-
"--ignore-scripts",
|
|
98
|
-
"--no-audit",
|
|
99
|
-
"--no-fund",
|
|
100
|
-
artifact.path,
|
|
101
|
-
]);
|
|
102
|
-
const result = spawnSync(
|
|
103
|
-
npm.command,
|
|
104
|
-
npm.arguments,
|
|
105
|
-
{
|
|
106
|
-
stdio: "inherit",
|
|
107
|
-
windowsHide: true,
|
|
108
|
-
shell: false,
|
|
109
|
-
},
|
|
110
|
-
);
|
|
111
|
-
await artifact.cleanup();
|
|
112
|
-
if (result.error) throw result.error;
|
|
113
|
-
if (result.status !== 0) {
|
|
114
|
-
await rm(staging, { recursive: true, force: true });
|
|
115
|
-
throw new Error(`npm exited with status ${result.status ?? "unknown"}.`);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const installedPackage = packageManifestPath(staging);
|
|
119
|
-
const manifest = JSON.parse(await readFile(installedPackage, "utf8"));
|
|
120
|
-
if (manifest.name !== packageName || manifest.version !== version) {
|
|
121
|
-
await rm(staging, { recursive: true, force: true });
|
|
122
|
-
throw new Error(
|
|
123
|
-
`Artifact identity ${String(manifest.name)}@${String(manifest.version)} does not match ${packageName}@${version}.`,
|
|
124
|
-
);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
await rm(destination, { recursive: true, force: true });
|
|
128
|
-
await rename(staging, destination);
|
|
129
|
-
await activate(prefix, destination);
|
|
130
|
-
process.stdout.write(
|
|
131
|
-
`Installed ${packageName}@${version} at ${destination}.\n` +
|
|
132
|
-
`Add ${join(prefix, "current", binDirectory())} to PATH.\n`,
|
|
133
|
-
);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
async function activate(prefix, destination) {
|
|
137
|
-
const current = join(prefix, "current");
|
|
138
|
-
const previous = join(prefix, "previous");
|
|
139
|
-
const next = join(prefix, `.current.${process.pid}`);
|
|
140
|
-
await rm(next, { recursive: true, force: true });
|
|
141
|
-
await symlink(
|
|
142
|
-
relativeLinkTarget(prefix, destination),
|
|
143
|
-
next,
|
|
144
|
-
platform() === "win32" ? "junction" : "dir",
|
|
145
|
-
);
|
|
146
|
-
if (await exists(current)) {
|
|
147
|
-
await rm(previous, { recursive: true, force: true });
|
|
148
|
-
await rename(current, previous);
|
|
149
|
-
}
|
|
150
|
-
try {
|
|
151
|
-
await rename(next, current);
|
|
152
|
-
} catch (error) {
|
|
153
|
-
if (await exists(previous)) await rename(previous, current);
|
|
154
|
-
throw error;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
async function rollback(options) {
|
|
159
|
-
const prefix = installPrefix(options);
|
|
160
|
-
const current = join(prefix, "current");
|
|
161
|
-
const previous = join(prefix, "previous");
|
|
162
|
-
if (!(await exists(current)) || !(await exists(previous))) {
|
|
163
|
-
throw new Error("No reversible previous observer installation exists.");
|
|
164
|
-
}
|
|
165
|
-
const swap = join(prefix, `.rollback.${process.pid}`);
|
|
166
|
-
await rename(current, swap);
|
|
167
|
-
try {
|
|
168
|
-
await rename(previous, current);
|
|
169
|
-
await rename(swap, previous);
|
|
170
|
-
} catch (error) {
|
|
171
|
-
if (await exists(swap) && !(await exists(current))) {
|
|
172
|
-
await rename(swap, current);
|
|
173
|
-
}
|
|
174
|
-
throw error;
|
|
175
|
-
}
|
|
176
|
-
process.stdout.write(`Rolled back to ${await activeVersion(prefix)}.\n`);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
async function status(options) {
|
|
180
|
-
const prefix = installPrefix(options);
|
|
181
|
-
process.stdout.write(
|
|
182
|
-
`${JSON.stringify(
|
|
183
|
-
{
|
|
184
|
-
prefix,
|
|
185
|
-
activeVersion: await activeVersion(prefix),
|
|
186
|
-
rollbackAvailable: await exists(join(prefix, "previous")),
|
|
187
|
-
},
|
|
188
|
-
null,
|
|
189
|
-
2,
|
|
190
|
-
)}\n`,
|
|
191
|
-
);
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
async function activeVersion(prefix) {
|
|
195
|
-
// Existing versioned installs retain the old package path after migration.
|
|
196
|
-
for (const name of [packageName, legacyPackageName]) {
|
|
197
|
-
try {
|
|
198
|
-
const manifest = JSON.parse(await readFile(packageManifestPath(join(prefix, "current"), name), "utf8"));
|
|
199
|
-
if (manifest.name === name && typeof manifest.version === "string") return manifest.version;
|
|
200
|
-
} catch { /* Try the legacy package path retained for rollback. */ }
|
|
201
|
-
}
|
|
202
|
-
return null;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
async function acquireArtifact(value, prefix) {
|
|
206
|
-
if (/^https:\/\//u.test(value)) {
|
|
207
|
-
const response = await fetch(value, {
|
|
208
|
-
redirect: "error",
|
|
209
|
-
signal: AbortSignal.timeout(30_000),
|
|
210
|
-
});
|
|
211
|
-
if (!response.ok) {
|
|
212
|
-
throw new Error(`Artifact download returned HTTP ${response.status}.`);
|
|
213
|
-
}
|
|
214
|
-
const downloadDirectory = join(prefix, ".downloads");
|
|
215
|
-
await mkdir(downloadDirectory, { recursive: true, mode: 0o700 });
|
|
216
|
-
const path = join(downloadDirectory, `observer-${process.pid}.tgz`);
|
|
217
|
-
const bytes = new Uint8Array(await response.arrayBuffer());
|
|
218
|
-
const { writeFile } = await import("node:fs/promises");
|
|
219
|
-
await writeFile(path, bytes, { mode: 0o600, flag: "wx" });
|
|
220
|
-
return {
|
|
221
|
-
path,
|
|
222
|
-
cleanup: async () => rm(path, { force: true }),
|
|
223
|
-
};
|
|
224
|
-
}
|
|
225
|
-
if (!isAbsolute(value) && /^[a-z][a-z0-9+.-]*:/iu.test(value)) {
|
|
226
|
-
throw new Error("Only HTTPS downloads and local artifact paths are allowed.");
|
|
227
|
-
}
|
|
228
|
-
const path = resolve(value);
|
|
229
|
-
await lstat(path);
|
|
230
|
-
return { path, cleanup: async () => undefined };
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
async function digestFile(path) {
|
|
234
|
-
const hash = createHash("sha256");
|
|
235
|
-
hash.update(await readFile(path));
|
|
236
|
-
return hash.digest("hex");
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
function parseOptions(args) {
|
|
240
|
-
const options = new Map();
|
|
241
|
-
for (let index = 0; index < args.length; index++) {
|
|
242
|
-
const name = args[index];
|
|
243
|
-
if (!name?.startsWith("--")) throw new Error(`Unexpected argument: ${name}`);
|
|
244
|
-
const value = args[index + 1];
|
|
245
|
-
if (!value || value.startsWith("--")) {
|
|
246
|
-
throw new Error(`${name} requires a value.`);
|
|
247
|
-
}
|
|
248
|
-
options.set(name.slice(2), value);
|
|
249
|
-
index++;
|
|
250
|
-
}
|
|
251
|
-
return options;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
function required(options, name) {
|
|
255
|
-
const value = options.get(name)?.trim();
|
|
256
|
-
if (!value) throw new Error(`--${name} is required.`);
|
|
257
|
-
return value;
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
function installPrefix(options) {
|
|
261
|
-
const value = options.get("prefix")?.trim();
|
|
262
|
-
return resolve(value || join(homedir(), ".phigon", "observer-install"));
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
function binDirectory() {
|
|
266
|
-
return platform() === "win32" ? "" : "bin";
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
function packageManifestPath(prefix, name = packageName) {
|
|
270
|
-
return join(
|
|
271
|
-
prefix,
|
|
272
|
-
...(platform() === "win32" ? [] : ["lib"]),
|
|
273
|
-
"node_modules",
|
|
274
|
-
name,
|
|
275
|
-
"package.json",
|
|
276
|
-
);
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
function relativeLinkTarget(prefix, destination) {
|
|
280
|
-
if (platform() === "win32") return destination;
|
|
281
|
-
return join("versions", basename(destination));
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
async function exists(path) {
|
|
285
|
-
try {
|
|
286
|
-
await lstat(path);
|
|
287
|
-
return true;
|
|
288
|
-
} catch (error) {
|
|
289
|
-
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
290
|
-
return false;
|
|
291
|
-
}
|
|
292
|
-
throw error;
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
function help() {
|
|
297
|
-
return [
|
|
298
|
-
"Phigon observer installer",
|
|
299
|
-
"",
|
|
300
|
-
"Install or upgrade:",
|
|
301
|
-
" node install.mjs install --artifact <path|https-url> --sha256 <digest> --version <version> [--prefix <directory>]",
|
|
302
|
-
"Rollback:",
|
|
303
|
-
" node install.mjs rollback [--prefix <directory>]",
|
|
304
|
-
"Status:",
|
|
305
|
-
" node install.mjs status [--prefix <directory>]",
|
|
306
|
-
"",
|
|
307
|
-
].join("\n");
|
|
308
|
-
}
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { createHash } from "node:crypto";
|
|
4
|
+
import { realpathSync, statSync } from "node:fs";
|
|
5
|
+
import {
|
|
6
|
+
lstat,
|
|
7
|
+
mkdir,
|
|
8
|
+
readFile,
|
|
9
|
+
rename,
|
|
10
|
+
rm,
|
|
11
|
+
symlink,
|
|
12
|
+
} from "node:fs/promises";
|
|
13
|
+
import { homedir, platform } from "node:os";
|
|
14
|
+
import { basename, dirname, isAbsolute, join, resolve } from "node:path";
|
|
15
|
+
import { spawnSync } from "node:child_process";
|
|
16
|
+
import { fileURLToPath } from "node:url";
|
|
17
|
+
|
|
18
|
+
const packageName = "@phigon/observer";
|
|
19
|
+
const legacyPackageName = "phigon-observer";
|
|
20
|
+
const safeVersion = /^[0-9A-Za-z][0-9A-Za-z.+-]{0,63}$/u;
|
|
21
|
+
const sha256Pattern = /^[a-f0-9]{64}$/u;
|
|
22
|
+
|
|
23
|
+
if (process.argv[1] && realpathSync(process.argv[1]) === realpathSync(fileURLToPath(import.meta.url))) {
|
|
24
|
+
process.exitCode = await main(process.argv.slice(2));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Keep the published installer self-contained. Windows .cmd launchers require
|
|
28
|
+
// a shell; invoking npm's JS entry point keeps paths as individual arguments.
|
|
29
|
+
export function npmCommand(arguments_) {
|
|
30
|
+
if (process.platform !== "win32") return { command: "npm", arguments: arguments_ };
|
|
31
|
+
const candidates = [
|
|
32
|
+
process.env.npm_execpath,
|
|
33
|
+
join(dirname(process.execPath), "node_modules", "npm", "bin", "npm-cli.js"),
|
|
34
|
+
];
|
|
35
|
+
for (const candidate of candidates) {
|
|
36
|
+
if (!candidate || !isAbsolute(candidate) || basename(candidate).toLowerCase() !== "npm-cli.js") continue;
|
|
37
|
+
try {
|
|
38
|
+
if (statSync(candidate).isFile()) return { command: process.execPath, arguments: [candidate, ...arguments_] };
|
|
39
|
+
} catch { /* Try the Node installation's bundled npm. */ }
|
|
40
|
+
}
|
|
41
|
+
throw new Error("Cannot find npm-cli.js. Use a Node installation with npm, or run this installer through npm.");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async function main(argv) {
|
|
45
|
+
const [command, ...args] = argv;
|
|
46
|
+
try {
|
|
47
|
+
if (command === "install") {
|
|
48
|
+
await install(parseOptions(args));
|
|
49
|
+
return 0;
|
|
50
|
+
}
|
|
51
|
+
if (command === "rollback") {
|
|
52
|
+
await rollback(parseOptions(args));
|
|
53
|
+
return 0;
|
|
54
|
+
}
|
|
55
|
+
if (command === "status") {
|
|
56
|
+
await status(parseOptions(args));
|
|
57
|
+
return 0;
|
|
58
|
+
}
|
|
59
|
+
process.stderr.write(help());
|
|
60
|
+
return 2;
|
|
61
|
+
} catch (error) {
|
|
62
|
+
const message = error instanceof Error ? error.message : "Unknown error.";
|
|
63
|
+
process.stderr.write(`Observer installation failed: ${message}\n`);
|
|
64
|
+
return 1;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async function install(options) {
|
|
69
|
+
const version = required(options, "version");
|
|
70
|
+
const artifactValue = required(options, "artifact");
|
|
71
|
+
const expectedSHA = required(options, "sha256").toLowerCase();
|
|
72
|
+
if (!safeVersion.test(version)) throw new Error("Invalid release version.");
|
|
73
|
+
if (!sha256Pattern.test(expectedSHA)) {
|
|
74
|
+
throw new Error("--sha256 must be a lowercase SHA-256 digest.");
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const prefix = installPrefix(options);
|
|
78
|
+
const versions = join(prefix, "versions");
|
|
79
|
+
const staging = join(versions, `.${version}.${process.pid}.staging`);
|
|
80
|
+
const destination = join(versions, version);
|
|
81
|
+
const artifact = await acquireArtifact(artifactValue, prefix);
|
|
82
|
+
const actualSHA = await digestFile(artifact.path);
|
|
83
|
+
if (actualSHA !== expectedSHA) {
|
|
84
|
+
await artifact.cleanup();
|
|
85
|
+
throw new Error(
|
|
86
|
+
`Checksum mismatch for ${basename(artifact.path)}: expected ${expectedSHA}, received ${actualSHA}.`,
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
await mkdir(versions, { recursive: true, mode: 0o700 });
|
|
91
|
+
await rm(staging, { recursive: true, force: true });
|
|
92
|
+
const npm = npmCommand([
|
|
93
|
+
"install",
|
|
94
|
+
"--global",
|
|
95
|
+
"--prefix",
|
|
96
|
+
staging,
|
|
97
|
+
"--ignore-scripts",
|
|
98
|
+
"--no-audit",
|
|
99
|
+
"--no-fund",
|
|
100
|
+
artifact.path,
|
|
101
|
+
]);
|
|
102
|
+
const result = spawnSync(
|
|
103
|
+
npm.command,
|
|
104
|
+
npm.arguments,
|
|
105
|
+
{
|
|
106
|
+
stdio: "inherit",
|
|
107
|
+
windowsHide: true,
|
|
108
|
+
shell: false,
|
|
109
|
+
},
|
|
110
|
+
);
|
|
111
|
+
await artifact.cleanup();
|
|
112
|
+
if (result.error) throw result.error;
|
|
113
|
+
if (result.status !== 0) {
|
|
114
|
+
await rm(staging, { recursive: true, force: true });
|
|
115
|
+
throw new Error(`npm exited with status ${result.status ?? "unknown"}.`);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const installedPackage = packageManifestPath(staging);
|
|
119
|
+
const manifest = JSON.parse(await readFile(installedPackage, "utf8"));
|
|
120
|
+
if (manifest.name !== packageName || manifest.version !== version) {
|
|
121
|
+
await rm(staging, { recursive: true, force: true });
|
|
122
|
+
throw new Error(
|
|
123
|
+
`Artifact identity ${String(manifest.name)}@${String(manifest.version)} does not match ${packageName}@${version}.`,
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
await rm(destination, { recursive: true, force: true });
|
|
128
|
+
await rename(staging, destination);
|
|
129
|
+
await activate(prefix, destination);
|
|
130
|
+
process.stdout.write(
|
|
131
|
+
`Installed ${packageName}@${version} at ${destination}.\n` +
|
|
132
|
+
`Add ${join(prefix, "current", binDirectory())} to PATH.\n`,
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
async function activate(prefix, destination) {
|
|
137
|
+
const current = join(prefix, "current");
|
|
138
|
+
const previous = join(prefix, "previous");
|
|
139
|
+
const next = join(prefix, `.current.${process.pid}`);
|
|
140
|
+
await rm(next, { recursive: true, force: true });
|
|
141
|
+
await symlink(
|
|
142
|
+
relativeLinkTarget(prefix, destination),
|
|
143
|
+
next,
|
|
144
|
+
platform() === "win32" ? "junction" : "dir",
|
|
145
|
+
);
|
|
146
|
+
if (await exists(current)) {
|
|
147
|
+
await rm(previous, { recursive: true, force: true });
|
|
148
|
+
await rename(current, previous);
|
|
149
|
+
}
|
|
150
|
+
try {
|
|
151
|
+
await rename(next, current);
|
|
152
|
+
} catch (error) {
|
|
153
|
+
if (await exists(previous)) await rename(previous, current);
|
|
154
|
+
throw error;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
async function rollback(options) {
|
|
159
|
+
const prefix = installPrefix(options);
|
|
160
|
+
const current = join(prefix, "current");
|
|
161
|
+
const previous = join(prefix, "previous");
|
|
162
|
+
if (!(await exists(current)) || !(await exists(previous))) {
|
|
163
|
+
throw new Error("No reversible previous observer installation exists.");
|
|
164
|
+
}
|
|
165
|
+
const swap = join(prefix, `.rollback.${process.pid}`);
|
|
166
|
+
await rename(current, swap);
|
|
167
|
+
try {
|
|
168
|
+
await rename(previous, current);
|
|
169
|
+
await rename(swap, previous);
|
|
170
|
+
} catch (error) {
|
|
171
|
+
if (await exists(swap) && !(await exists(current))) {
|
|
172
|
+
await rename(swap, current);
|
|
173
|
+
}
|
|
174
|
+
throw error;
|
|
175
|
+
}
|
|
176
|
+
process.stdout.write(`Rolled back to ${await activeVersion(prefix)}.\n`);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
async function status(options) {
|
|
180
|
+
const prefix = installPrefix(options);
|
|
181
|
+
process.stdout.write(
|
|
182
|
+
`${JSON.stringify(
|
|
183
|
+
{
|
|
184
|
+
prefix,
|
|
185
|
+
activeVersion: await activeVersion(prefix),
|
|
186
|
+
rollbackAvailable: await exists(join(prefix, "previous")),
|
|
187
|
+
},
|
|
188
|
+
null,
|
|
189
|
+
2,
|
|
190
|
+
)}\n`,
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
async function activeVersion(prefix) {
|
|
195
|
+
// Existing versioned installs retain the old package path after migration.
|
|
196
|
+
for (const name of [packageName, legacyPackageName]) {
|
|
197
|
+
try {
|
|
198
|
+
const manifest = JSON.parse(await readFile(packageManifestPath(join(prefix, "current"), name), "utf8"));
|
|
199
|
+
if (manifest.name === name && typeof manifest.version === "string") return manifest.version;
|
|
200
|
+
} catch { /* Try the legacy package path retained for rollback. */ }
|
|
201
|
+
}
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
async function acquireArtifact(value, prefix) {
|
|
206
|
+
if (/^https:\/\//u.test(value)) {
|
|
207
|
+
const response = await fetch(value, {
|
|
208
|
+
redirect: "error",
|
|
209
|
+
signal: AbortSignal.timeout(30_000),
|
|
210
|
+
});
|
|
211
|
+
if (!response.ok) {
|
|
212
|
+
throw new Error(`Artifact download returned HTTP ${response.status}.`);
|
|
213
|
+
}
|
|
214
|
+
const downloadDirectory = join(prefix, ".downloads");
|
|
215
|
+
await mkdir(downloadDirectory, { recursive: true, mode: 0o700 });
|
|
216
|
+
const path = join(downloadDirectory, `observer-${process.pid}.tgz`);
|
|
217
|
+
const bytes = new Uint8Array(await response.arrayBuffer());
|
|
218
|
+
const { writeFile } = await import("node:fs/promises");
|
|
219
|
+
await writeFile(path, bytes, { mode: 0o600, flag: "wx" });
|
|
220
|
+
return {
|
|
221
|
+
path,
|
|
222
|
+
cleanup: async () => rm(path, { force: true }),
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
if (!isAbsolute(value) && /^[a-z][a-z0-9+.-]*:/iu.test(value)) {
|
|
226
|
+
throw new Error("Only HTTPS downloads and local artifact paths are allowed.");
|
|
227
|
+
}
|
|
228
|
+
const path = resolve(value);
|
|
229
|
+
await lstat(path);
|
|
230
|
+
return { path, cleanup: async () => undefined };
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
async function digestFile(path) {
|
|
234
|
+
const hash = createHash("sha256");
|
|
235
|
+
hash.update(await readFile(path));
|
|
236
|
+
return hash.digest("hex");
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function parseOptions(args) {
|
|
240
|
+
const options = new Map();
|
|
241
|
+
for (let index = 0; index < args.length; index++) {
|
|
242
|
+
const name = args[index];
|
|
243
|
+
if (!name?.startsWith("--")) throw new Error(`Unexpected argument: ${name}`);
|
|
244
|
+
const value = args[index + 1];
|
|
245
|
+
if (!value || value.startsWith("--")) {
|
|
246
|
+
throw new Error(`${name} requires a value.`);
|
|
247
|
+
}
|
|
248
|
+
options.set(name.slice(2), value);
|
|
249
|
+
index++;
|
|
250
|
+
}
|
|
251
|
+
return options;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function required(options, name) {
|
|
255
|
+
const value = options.get(name)?.trim();
|
|
256
|
+
if (!value) throw new Error(`--${name} is required.`);
|
|
257
|
+
return value;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function installPrefix(options) {
|
|
261
|
+
const value = options.get("prefix")?.trim();
|
|
262
|
+
return resolve(value || join(homedir(), ".phigon", "observer-install"));
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function binDirectory() {
|
|
266
|
+
return platform() === "win32" ? "" : "bin";
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
function packageManifestPath(prefix, name = packageName) {
|
|
270
|
+
return join(
|
|
271
|
+
prefix,
|
|
272
|
+
...(platform() === "win32" ? [] : ["lib"]),
|
|
273
|
+
"node_modules",
|
|
274
|
+
name,
|
|
275
|
+
"package.json",
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function relativeLinkTarget(prefix, destination) {
|
|
280
|
+
if (platform() === "win32") return destination;
|
|
281
|
+
return join("versions", basename(destination));
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
async function exists(path) {
|
|
285
|
+
try {
|
|
286
|
+
await lstat(path);
|
|
287
|
+
return true;
|
|
288
|
+
} catch (error) {
|
|
289
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
290
|
+
return false;
|
|
291
|
+
}
|
|
292
|
+
throw error;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
function help() {
|
|
297
|
+
return [
|
|
298
|
+
"Phigon observer installer",
|
|
299
|
+
"",
|
|
300
|
+
"Install or upgrade:",
|
|
301
|
+
" node install.mjs install --artifact <path|https-url> --sha256 <digest> --version <version> [--prefix <directory>]",
|
|
302
|
+
"Rollback:",
|
|
303
|
+
" node install.mjs rollback [--prefix <directory>]",
|
|
304
|
+
"Status:",
|
|
305
|
+
" node install.mjs status [--prefix <directory>]",
|
|
306
|
+
"",
|
|
307
|
+
].join("\n");
|
|
308
|
+
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|