codeharbor 0.1.5 → 0.1.7
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 +27 -0
- package/dist/cli.js +345 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -64,6 +64,30 @@ curl -fsSL https://raw.githubusercontent.com/biglone/CodeHarbor/main/scripts/ins
|
|
|
64
64
|
--matrix-access-token 'your-token'
|
|
65
65
|
```
|
|
66
66
|
|
|
67
|
+
Install first, then enable systemd service with one command:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
sudo "$(command -v codeharbor)" service install
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Install + enable main and admin services:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
sudo "$(command -v codeharbor)" service install --with-admin
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Restart installed service(s):
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
sudo "$(command -v codeharbor)" service restart --with-admin
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Remove installed services:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
sudo "$(command -v codeharbor)" service uninstall --with-admin
|
|
89
|
+
```
|
|
90
|
+
|
|
67
91
|
Enable Admin service at install time:
|
|
68
92
|
|
|
69
93
|
```bash
|
|
@@ -229,6 +253,9 @@ It documents:
|
|
|
229
253
|
- `codeharbor start`: start service
|
|
230
254
|
- `codeharbor doctor`: check `codex` and Matrix connectivity
|
|
231
255
|
- `codeharbor admin serve`: start admin UI + config API server
|
|
256
|
+
- `codeharbor service install`: install/enable systemd unit(s) after npm install (supports `--with-admin`)
|
|
257
|
+
- `codeharbor service restart`: restart installed systemd unit(s) (supports `--with-admin`)
|
|
258
|
+
- `codeharbor service uninstall`: remove installed systemd unit(s) (supports `--with-admin`)
|
|
232
259
|
- `codeharbor config export`: export current config snapshot as JSON
|
|
233
260
|
- `codeharbor config import <file>`: import config snapshot JSON (supports `--dry-run`)
|
|
234
261
|
- `npm run changelog:check`: validate `CHANGELOG.md` has notes for current package version
|
package/dist/cli.js
CHANGED
|
@@ -24,8 +24,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
24
24
|
));
|
|
25
25
|
|
|
26
26
|
// src/cli.ts
|
|
27
|
-
var
|
|
28
|
-
var
|
|
27
|
+
var import_node_fs11 = __toESM(require("fs"));
|
|
28
|
+
var import_node_path12 = __toESM(require("path"));
|
|
29
29
|
var import_commander = require("commander");
|
|
30
30
|
|
|
31
31
|
// src/app.ts
|
|
@@ -4934,6 +4934,274 @@ function resolveUserRuntimeHome(env = process.env) {
|
|
|
4934
4934
|
return import_node_path10.default.resolve(home, USER_RUNTIME_HOME_DIR);
|
|
4935
4935
|
}
|
|
4936
4936
|
|
|
4937
|
+
// src/service-manager.ts
|
|
4938
|
+
var import_node_child_process5 = require("child_process");
|
|
4939
|
+
var import_node_fs10 = __toESM(require("fs"));
|
|
4940
|
+
var import_node_os3 = __toESM(require("os"));
|
|
4941
|
+
var import_node_path11 = __toESM(require("path"));
|
|
4942
|
+
var SYSTEMD_DIR = "/etc/systemd/system";
|
|
4943
|
+
var MAIN_SERVICE_NAME = "codeharbor.service";
|
|
4944
|
+
var ADMIN_SERVICE_NAME = "codeharbor-admin.service";
|
|
4945
|
+
function resolveDefaultRunUser(env = process.env) {
|
|
4946
|
+
const sudoUser = env.SUDO_USER?.trim();
|
|
4947
|
+
if (sudoUser) {
|
|
4948
|
+
return sudoUser;
|
|
4949
|
+
}
|
|
4950
|
+
const user = env.USER?.trim();
|
|
4951
|
+
if (user) {
|
|
4952
|
+
return user;
|
|
4953
|
+
}
|
|
4954
|
+
try {
|
|
4955
|
+
return import_node_os3.default.userInfo().username;
|
|
4956
|
+
} catch {
|
|
4957
|
+
return "root";
|
|
4958
|
+
}
|
|
4959
|
+
}
|
|
4960
|
+
function resolveRuntimeHomeForUser(runUser, env = process.env, explicitRuntimeHome) {
|
|
4961
|
+
const configuredRuntimeHome = explicitRuntimeHome?.trim() || env[RUNTIME_HOME_ENV_KEY]?.trim();
|
|
4962
|
+
if (configuredRuntimeHome) {
|
|
4963
|
+
return import_node_path11.default.resolve(configuredRuntimeHome);
|
|
4964
|
+
}
|
|
4965
|
+
const userHome = resolveUserHome(runUser);
|
|
4966
|
+
if (userHome) {
|
|
4967
|
+
return import_node_path11.default.resolve(userHome, USER_RUNTIME_HOME_DIR);
|
|
4968
|
+
}
|
|
4969
|
+
return import_node_path11.default.resolve(import_node_os3.default.homedir(), USER_RUNTIME_HOME_DIR);
|
|
4970
|
+
}
|
|
4971
|
+
function buildMainServiceUnit(options) {
|
|
4972
|
+
validateUnitOptions(options);
|
|
4973
|
+
const runtimeHome2 = import_node_path11.default.resolve(options.runtimeHome);
|
|
4974
|
+
return [
|
|
4975
|
+
"[Unit]",
|
|
4976
|
+
"Description=CodeHarbor main service",
|
|
4977
|
+
"After=network-online.target",
|
|
4978
|
+
"Wants=network-online.target",
|
|
4979
|
+
"",
|
|
4980
|
+
"[Service]",
|
|
4981
|
+
"Type=simple",
|
|
4982
|
+
`User=${options.runUser}`,
|
|
4983
|
+
`WorkingDirectory=${runtimeHome2}`,
|
|
4984
|
+
`Environment=CODEHARBOR_HOME=${runtimeHome2}`,
|
|
4985
|
+
`ExecStart=${import_node_path11.default.resolve(options.nodeBinPath)} ${import_node_path11.default.resolve(options.cliScriptPath)} start`,
|
|
4986
|
+
"Restart=always",
|
|
4987
|
+
"RestartSec=3",
|
|
4988
|
+
"NoNewPrivileges=true",
|
|
4989
|
+
"PrivateTmp=true",
|
|
4990
|
+
"ProtectSystem=full",
|
|
4991
|
+
"ProtectHome=true",
|
|
4992
|
+
`ReadWritePaths=${runtimeHome2}`,
|
|
4993
|
+
"",
|
|
4994
|
+
"[Install]",
|
|
4995
|
+
"WantedBy=multi-user.target",
|
|
4996
|
+
""
|
|
4997
|
+
].join("\n");
|
|
4998
|
+
}
|
|
4999
|
+
function buildAdminServiceUnit(options) {
|
|
5000
|
+
validateUnitOptions(options);
|
|
5001
|
+
const runtimeHome2 = import_node_path11.default.resolve(options.runtimeHome);
|
|
5002
|
+
return [
|
|
5003
|
+
"[Unit]",
|
|
5004
|
+
"Description=CodeHarbor admin service",
|
|
5005
|
+
"After=network-online.target",
|
|
5006
|
+
"Wants=network-online.target",
|
|
5007
|
+
"",
|
|
5008
|
+
"[Service]",
|
|
5009
|
+
"Type=simple",
|
|
5010
|
+
`User=${options.runUser}`,
|
|
5011
|
+
`WorkingDirectory=${runtimeHome2}`,
|
|
5012
|
+
`Environment=CODEHARBOR_HOME=${runtimeHome2}`,
|
|
5013
|
+
`ExecStart=${import_node_path11.default.resolve(options.nodeBinPath)} ${import_node_path11.default.resolve(options.cliScriptPath)} admin serve`,
|
|
5014
|
+
"Restart=always",
|
|
5015
|
+
"RestartSec=3",
|
|
5016
|
+
"NoNewPrivileges=true",
|
|
5017
|
+
"PrivateTmp=true",
|
|
5018
|
+
"ProtectSystem=full",
|
|
5019
|
+
"ProtectHome=true",
|
|
5020
|
+
`ReadWritePaths=${runtimeHome2}`,
|
|
5021
|
+
"",
|
|
5022
|
+
"[Install]",
|
|
5023
|
+
"WantedBy=multi-user.target",
|
|
5024
|
+
""
|
|
5025
|
+
].join("\n");
|
|
5026
|
+
}
|
|
5027
|
+
function installSystemdServices(options) {
|
|
5028
|
+
assertLinuxWithSystemd();
|
|
5029
|
+
assertRootPrivileges();
|
|
5030
|
+
const output = options.output ?? process.stdout;
|
|
5031
|
+
const runUser = options.runUser.trim();
|
|
5032
|
+
const runtimeHome2 = import_node_path11.default.resolve(options.runtimeHome);
|
|
5033
|
+
validateSimpleValue(runUser, "runUser");
|
|
5034
|
+
validateSimpleValue(runtimeHome2, "runtimeHome");
|
|
5035
|
+
validateSimpleValue(options.nodeBinPath, "nodeBinPath");
|
|
5036
|
+
validateSimpleValue(options.cliScriptPath, "cliScriptPath");
|
|
5037
|
+
ensureUserExists(runUser);
|
|
5038
|
+
const runGroup = resolveUserGroup(runUser);
|
|
5039
|
+
import_node_fs10.default.mkdirSync(runtimeHome2, { recursive: true });
|
|
5040
|
+
runCommand("chown", ["-R", `${runUser}:${runGroup}`, runtimeHome2]);
|
|
5041
|
+
const mainPath = import_node_path11.default.join(SYSTEMD_DIR, MAIN_SERVICE_NAME);
|
|
5042
|
+
const adminPath = import_node_path11.default.join(SYSTEMD_DIR, ADMIN_SERVICE_NAME);
|
|
5043
|
+
const unitOptions = {
|
|
5044
|
+
runUser,
|
|
5045
|
+
runtimeHome: runtimeHome2,
|
|
5046
|
+
nodeBinPath: options.nodeBinPath,
|
|
5047
|
+
cliScriptPath: options.cliScriptPath
|
|
5048
|
+
};
|
|
5049
|
+
import_node_fs10.default.writeFileSync(mainPath, buildMainServiceUnit(unitOptions), "utf8");
|
|
5050
|
+
if (options.installAdmin) {
|
|
5051
|
+
import_node_fs10.default.writeFileSync(adminPath, buildAdminServiceUnit(unitOptions), "utf8");
|
|
5052
|
+
}
|
|
5053
|
+
runSystemctl(["daemon-reload"]);
|
|
5054
|
+
if (options.startNow) {
|
|
5055
|
+
runSystemctl(["enable", "--now", MAIN_SERVICE_NAME]);
|
|
5056
|
+
if (options.installAdmin) {
|
|
5057
|
+
runSystemctl(["enable", "--now", ADMIN_SERVICE_NAME]);
|
|
5058
|
+
}
|
|
5059
|
+
} else {
|
|
5060
|
+
runSystemctl(["enable", MAIN_SERVICE_NAME]);
|
|
5061
|
+
if (options.installAdmin) {
|
|
5062
|
+
runSystemctl(["enable", ADMIN_SERVICE_NAME]);
|
|
5063
|
+
}
|
|
5064
|
+
}
|
|
5065
|
+
output.write(`Installed systemd unit: ${mainPath}
|
|
5066
|
+
`);
|
|
5067
|
+
if (options.installAdmin) {
|
|
5068
|
+
output.write(`Installed systemd unit: ${adminPath}
|
|
5069
|
+
`);
|
|
5070
|
+
}
|
|
5071
|
+
output.write("Done. Check status with: systemctl status codeharbor --no-pager\n");
|
|
5072
|
+
}
|
|
5073
|
+
function uninstallSystemdServices(options) {
|
|
5074
|
+
assertLinuxWithSystemd();
|
|
5075
|
+
assertRootPrivileges();
|
|
5076
|
+
const output = options.output ?? process.stdout;
|
|
5077
|
+
const mainPath = import_node_path11.default.join(SYSTEMD_DIR, MAIN_SERVICE_NAME);
|
|
5078
|
+
const adminPath = import_node_path11.default.join(SYSTEMD_DIR, ADMIN_SERVICE_NAME);
|
|
5079
|
+
stopAndDisableIfPresent(MAIN_SERVICE_NAME);
|
|
5080
|
+
if (import_node_fs10.default.existsSync(mainPath)) {
|
|
5081
|
+
import_node_fs10.default.unlinkSync(mainPath);
|
|
5082
|
+
}
|
|
5083
|
+
if (options.removeAdmin) {
|
|
5084
|
+
stopAndDisableIfPresent(ADMIN_SERVICE_NAME);
|
|
5085
|
+
if (import_node_fs10.default.existsSync(adminPath)) {
|
|
5086
|
+
import_node_fs10.default.unlinkSync(adminPath);
|
|
5087
|
+
}
|
|
5088
|
+
}
|
|
5089
|
+
runSystemctl(["daemon-reload"]);
|
|
5090
|
+
runSystemctlIgnoreFailure(["reset-failed"]);
|
|
5091
|
+
output.write(`Removed systemd unit: ${mainPath}
|
|
5092
|
+
`);
|
|
5093
|
+
if (options.removeAdmin) {
|
|
5094
|
+
output.write(`Removed systemd unit: ${adminPath}
|
|
5095
|
+
`);
|
|
5096
|
+
}
|
|
5097
|
+
output.write("Done.\n");
|
|
5098
|
+
}
|
|
5099
|
+
function restartSystemdServices(options) {
|
|
5100
|
+
assertLinuxWithSystemd();
|
|
5101
|
+
assertRootPrivileges();
|
|
5102
|
+
const output = options.output ?? process.stdout;
|
|
5103
|
+
runSystemctl(["restart", MAIN_SERVICE_NAME]);
|
|
5104
|
+
output.write(`Restarted service: ${MAIN_SERVICE_NAME}
|
|
5105
|
+
`);
|
|
5106
|
+
if (options.restartAdmin) {
|
|
5107
|
+
runSystemctl(["restart", ADMIN_SERVICE_NAME]);
|
|
5108
|
+
output.write(`Restarted service: ${ADMIN_SERVICE_NAME}
|
|
5109
|
+
`);
|
|
5110
|
+
}
|
|
5111
|
+
output.write("Done.\n");
|
|
5112
|
+
}
|
|
5113
|
+
function resolveUserHome(runUser) {
|
|
5114
|
+
try {
|
|
5115
|
+
const passwdRaw = import_node_fs10.default.readFileSync("/etc/passwd", "utf8");
|
|
5116
|
+
const line = passwdRaw.split(/\r?\n/).find((item) => item.startsWith(`${runUser}:`));
|
|
5117
|
+
if (!line) {
|
|
5118
|
+
return null;
|
|
5119
|
+
}
|
|
5120
|
+
const fields = line.split(":");
|
|
5121
|
+
return fields[5] ? fields[5].trim() : null;
|
|
5122
|
+
} catch {
|
|
5123
|
+
return null;
|
|
5124
|
+
}
|
|
5125
|
+
}
|
|
5126
|
+
function validateUnitOptions(options) {
|
|
5127
|
+
validateSimpleValue(options.runUser, "runUser");
|
|
5128
|
+
validateSimpleValue(options.runtimeHome, "runtimeHome");
|
|
5129
|
+
validateSimpleValue(options.nodeBinPath, "nodeBinPath");
|
|
5130
|
+
validateSimpleValue(options.cliScriptPath, "cliScriptPath");
|
|
5131
|
+
}
|
|
5132
|
+
function validateSimpleValue(value, key) {
|
|
5133
|
+
if (!value.trim()) {
|
|
5134
|
+
throw new Error(`${key} cannot be empty.`);
|
|
5135
|
+
}
|
|
5136
|
+
if (/[\r\n]/.test(value)) {
|
|
5137
|
+
throw new Error(`${key} contains invalid newline characters.`);
|
|
5138
|
+
}
|
|
5139
|
+
}
|
|
5140
|
+
function assertLinuxWithSystemd() {
|
|
5141
|
+
if (process.platform !== "linux") {
|
|
5142
|
+
throw new Error("Systemd service install only supports Linux.");
|
|
5143
|
+
}
|
|
5144
|
+
try {
|
|
5145
|
+
(0, import_node_child_process5.execFileSync)("systemctl", ["--version"], { stdio: "ignore" });
|
|
5146
|
+
} catch {
|
|
5147
|
+
throw new Error("systemctl is required but not found.");
|
|
5148
|
+
}
|
|
5149
|
+
}
|
|
5150
|
+
function assertRootPrivileges() {
|
|
5151
|
+
if (typeof process.getuid !== "function") {
|
|
5152
|
+
return;
|
|
5153
|
+
}
|
|
5154
|
+
if (process.getuid() !== 0) {
|
|
5155
|
+
throw new Error("Root privileges are required. Run with sudo.");
|
|
5156
|
+
}
|
|
5157
|
+
}
|
|
5158
|
+
function ensureUserExists(runUser) {
|
|
5159
|
+
runCommand("id", ["-u", runUser]);
|
|
5160
|
+
}
|
|
5161
|
+
function resolveUserGroup(runUser) {
|
|
5162
|
+
return runCommand("id", ["-gn", runUser]).trim();
|
|
5163
|
+
}
|
|
5164
|
+
function runSystemctl(args) {
|
|
5165
|
+
runCommand("systemctl", args);
|
|
5166
|
+
}
|
|
5167
|
+
function stopAndDisableIfPresent(unitName) {
|
|
5168
|
+
runSystemctlIgnoreFailure(["disable", "--now", unitName]);
|
|
5169
|
+
}
|
|
5170
|
+
function runSystemctlIgnoreFailure(args) {
|
|
5171
|
+
try {
|
|
5172
|
+
runCommand("systemctl", args);
|
|
5173
|
+
} catch {
|
|
5174
|
+
}
|
|
5175
|
+
}
|
|
5176
|
+
function runCommand(file, args) {
|
|
5177
|
+
try {
|
|
5178
|
+
return (0, import_node_child_process5.execFileSync)(file, args, {
|
|
5179
|
+
encoding: "utf8",
|
|
5180
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
5181
|
+
});
|
|
5182
|
+
} catch (error) {
|
|
5183
|
+
throw new Error(formatCommandError(file, args, error), { cause: error });
|
|
5184
|
+
}
|
|
5185
|
+
}
|
|
5186
|
+
function formatCommandError(file, args, error) {
|
|
5187
|
+
const command = `${file} ${args.join(" ")}`.trim();
|
|
5188
|
+
if (error && typeof error === "object") {
|
|
5189
|
+
const maybeError = error;
|
|
5190
|
+
const stderr = bufferToTrimmedString(maybeError.stderr);
|
|
5191
|
+
const stdout = bufferToTrimmedString(maybeError.stdout);
|
|
5192
|
+
const details = stderr || stdout || maybeError.message || "command failed";
|
|
5193
|
+
return `Command failed: ${command}. ${details}`;
|
|
5194
|
+
}
|
|
5195
|
+
return `Command failed: ${command}. ${String(error)}`;
|
|
5196
|
+
}
|
|
5197
|
+
function bufferToTrimmedString(value) {
|
|
5198
|
+
if (!value) {
|
|
5199
|
+
return "";
|
|
5200
|
+
}
|
|
5201
|
+
const text = typeof value === "string" ? value : value.toString("utf8");
|
|
5202
|
+
return text.trim();
|
|
5203
|
+
}
|
|
5204
|
+
|
|
4937
5205
|
// src/cli.ts
|
|
4938
5206
|
var runtimeHome = null;
|
|
4939
5207
|
var cliVersion = resolveCliVersion();
|
|
@@ -4974,6 +5242,7 @@ program.command("doctor").description("Check codex and matrix connectivity").act
|
|
|
4974
5242
|
});
|
|
4975
5243
|
var admin = program.command("admin").description("Admin utilities");
|
|
4976
5244
|
var configCommand = program.command("config").description("Config snapshot utilities");
|
|
5245
|
+
var serviceCommand = program.command("service").description("Systemd service management");
|
|
4977
5246
|
admin.command("serve").description("Start admin config API server").option("--host <host>", "override admin bind host").option("--port <port>", "override admin bind port").option(
|
|
4978
5247
|
"--allow-insecure-no-token",
|
|
4979
5248
|
"allow serving admin API without ADMIN_TOKEN on non-loopback host (not recommended)"
|
|
@@ -5031,6 +5300,69 @@ configCommand.command("import").description("Import config snapshot from JSON").
|
|
|
5031
5300
|
process.exitCode = 1;
|
|
5032
5301
|
}
|
|
5033
5302
|
});
|
|
5303
|
+
serviceCommand.command("install").description("Install and enable codeharbor systemd service (requires root)").option("--run-user <user>", "service user (default: sudo user or current user)").option("--runtime-home <path>", "runtime home used as CODEHARBOR_HOME").option("--with-admin", "also install codeharbor-admin.service").option("--no-start", "enable service without starting immediately").action((options) => {
|
|
5304
|
+
try {
|
|
5305
|
+
const runUser = options.runUser?.trim() || resolveDefaultRunUser();
|
|
5306
|
+
const runtimeHomePath = resolveRuntimeHomeForUser(runUser, process.env, options.runtimeHome);
|
|
5307
|
+
installSystemdServices({
|
|
5308
|
+
runUser,
|
|
5309
|
+
runtimeHome: runtimeHomePath,
|
|
5310
|
+
nodeBinPath: process.execPath,
|
|
5311
|
+
cliScriptPath: resolveCliScriptPath(),
|
|
5312
|
+
installAdmin: options.withAdmin ?? false,
|
|
5313
|
+
startNow: options.start ?? true
|
|
5314
|
+
});
|
|
5315
|
+
} catch (error) {
|
|
5316
|
+
process.stderr.write(`Service install failed: ${formatError3(error)}
|
|
5317
|
+
`);
|
|
5318
|
+
process.stderr.write(
|
|
5319
|
+
[
|
|
5320
|
+
"Hint: run with sudo and absolute CLI path, for example:",
|
|
5321
|
+
' sudo "$(command -v codeharbor)" service install --with-admin',
|
|
5322
|
+
" (remove --with-admin if you only want the main service)",
|
|
5323
|
+
""
|
|
5324
|
+
].join("\n")
|
|
5325
|
+
);
|
|
5326
|
+
process.exitCode = 1;
|
|
5327
|
+
}
|
|
5328
|
+
});
|
|
5329
|
+
serviceCommand.command("uninstall").description("Remove codeharbor systemd service (requires root)").option("--with-admin", "also remove codeharbor-admin.service").action((options) => {
|
|
5330
|
+
try {
|
|
5331
|
+
uninstallSystemdServices({
|
|
5332
|
+
removeAdmin: options.withAdmin ?? false
|
|
5333
|
+
});
|
|
5334
|
+
} catch (error) {
|
|
5335
|
+
process.stderr.write(`Service uninstall failed: ${formatError3(error)}
|
|
5336
|
+
`);
|
|
5337
|
+
process.stderr.write(
|
|
5338
|
+
[
|
|
5339
|
+
"Hint: run with sudo and absolute CLI path, for example:",
|
|
5340
|
+
' sudo "$(command -v codeharbor)" service uninstall --with-admin',
|
|
5341
|
+
""
|
|
5342
|
+
].join("\n")
|
|
5343
|
+
);
|
|
5344
|
+
process.exitCode = 1;
|
|
5345
|
+
}
|
|
5346
|
+
});
|
|
5347
|
+
serviceCommand.command("restart").description("Restart installed codeharbor systemd service (requires root)").option("--with-admin", "also restart codeharbor-admin.service").action((options) => {
|
|
5348
|
+
try {
|
|
5349
|
+
restartSystemdServices({
|
|
5350
|
+
restartAdmin: options.withAdmin ?? false
|
|
5351
|
+
});
|
|
5352
|
+
} catch (error) {
|
|
5353
|
+
process.stderr.write(`Service restart failed: ${formatError3(error)}
|
|
5354
|
+
`);
|
|
5355
|
+
process.stderr.write(
|
|
5356
|
+
[
|
|
5357
|
+
"Hint: run with sudo and absolute CLI path, for example:",
|
|
5358
|
+
' sudo "$(command -v codeharbor)" service restart --with-admin',
|
|
5359
|
+
" (remove --with-admin if you only want the main service)",
|
|
5360
|
+
""
|
|
5361
|
+
].join("\n")
|
|
5362
|
+
);
|
|
5363
|
+
process.exitCode = 1;
|
|
5364
|
+
}
|
|
5365
|
+
});
|
|
5034
5366
|
if (process.argv.length <= 2) {
|
|
5035
5367
|
process.argv.push("start");
|
|
5036
5368
|
}
|
|
@@ -5062,7 +5394,7 @@ function ensureRuntimeHomeOrExit() {
|
|
|
5062
5394
|
}
|
|
5063
5395
|
const home = resolveRuntimeHome();
|
|
5064
5396
|
try {
|
|
5065
|
-
|
|
5397
|
+
import_node_fs11.default.mkdirSync(home, { recursive: true });
|
|
5066
5398
|
} catch (error) {
|
|
5067
5399
|
const message = error instanceof Error ? error.message : String(error);
|
|
5068
5400
|
process.stderr.write(`Runtime setup failed: cannot create ${home}. ${message}
|
|
@@ -5077,7 +5409,7 @@ function ensureRuntimeHomeOrExit() {
|
|
|
5077
5409
|
`);
|
|
5078
5410
|
process.exit(1);
|
|
5079
5411
|
}
|
|
5080
|
-
loadEnvFromFile(
|
|
5412
|
+
loadEnvFromFile(import_node_path12.default.resolve(home, ".env"));
|
|
5081
5413
|
runtimeHome = home;
|
|
5082
5414
|
return runtimeHome;
|
|
5083
5415
|
}
|
|
@@ -5092,14 +5424,21 @@ function parsePortOption(raw, fallback) {
|
|
|
5092
5424
|
}
|
|
5093
5425
|
function resolveCliVersion() {
|
|
5094
5426
|
try {
|
|
5095
|
-
const packagePath =
|
|
5096
|
-
const content =
|
|
5427
|
+
const packagePath = import_node_path12.default.resolve(__dirname, "..", "package.json");
|
|
5428
|
+
const content = import_node_fs11.default.readFileSync(packagePath, "utf8");
|
|
5097
5429
|
const parsed = JSON.parse(content);
|
|
5098
5430
|
return typeof parsed.version === "string" && parsed.version.trim() ? parsed.version : "0.0.0";
|
|
5099
5431
|
} catch {
|
|
5100
5432
|
return "0.0.0";
|
|
5101
5433
|
}
|
|
5102
5434
|
}
|
|
5435
|
+
function resolveCliScriptPath() {
|
|
5436
|
+
const argvPath = process.argv[1];
|
|
5437
|
+
if (argvPath && argvPath.trim()) {
|
|
5438
|
+
return import_node_path12.default.resolve(argvPath);
|
|
5439
|
+
}
|
|
5440
|
+
return import_node_path12.default.resolve(__dirname, "cli.js");
|
|
5441
|
+
}
|
|
5103
5442
|
function formatError3(error) {
|
|
5104
5443
|
if (error instanceof Error) {
|
|
5105
5444
|
return error.message;
|