magalh 1.0.16 → 1.0.18

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.
Files changed (3) hide show
  1. package/bin/mgl.js +75 -207
  2. package/msh.js +1 -1
  3. package/package.json +1 -1
package/bin/mgl.js CHANGED
@@ -26,15 +26,6 @@ function warn(message) {
26
26
  console.warn(`[magalh] ${message}`);
27
27
  }
28
28
 
29
- function fail(message, exitCode = 1) {
30
- try {
31
- process.stderr.write(`[magalh] ${message}\n`);
32
- } catch {
33
- console.error(`[magalh] ${message}`);
34
- }
35
- process.exit(exitCode);
36
- }
37
-
38
29
  function isRootOnLinux() {
39
30
  return typeof process.getuid === "function" && process.getuid() === 0;
40
31
  }
@@ -51,13 +42,17 @@ function isWindowsAdminLike() {
51
42
  }
52
43
  }
53
44
 
54
- function fileExists(filePath) {
55
- try {
56
- fs.accessSync(filePath, fs.constants.F_OK);
57
- return true;
58
- } catch {
59
- return false;
60
- }
45
+ function printHelp() {
46
+ process.stdout.write(
47
+ [
48
+ "magalh - Magala Media Server",
49
+ "",
50
+ "Usage:",
51
+ " magalh [--help]",
52
+ " magalh --install-service",
53
+ "",
54
+ ].join("\n"),
55
+ );
61
56
  }
62
57
 
63
58
  function runCommand(command, commandArgs, options = {}) {
@@ -67,11 +62,10 @@ function runCommand(command, commandArgs, options = {}) {
67
62
  });
68
63
  }
69
64
 
70
- function runCommandQuiet(command, commandArgs, options = {}) {
65
+ function safeRunCommand(command, commandArgs, options = {}) {
71
66
  try {
72
67
  return execFileSync(command, commandArgs, {
73
68
  stdio: "pipe",
74
- encoding: "utf8",
75
69
  ...options,
76
70
  });
77
71
  } catch {
@@ -79,45 +73,26 @@ function runCommandQuiet(command, commandArgs, options = {}) {
79
73
  }
80
74
  }
81
75
 
82
- function printHelp() {
83
- process.stdout.write(
84
- [
85
- "magalh - Magala Media Server",
86
- "",
87
- "Usage:",
88
- " magalh",
89
- " magalh --help",
90
- " magalh --install-service",
91
- " magalh --uninstall-service",
92
- " magalh --service-status",
93
- "",
94
- "Notes:",
95
- " - The server starts normally with: magalh",
96
- " - Service installation is explicit only; it is never done automatically.",
97
- "",
98
- ].join("\n"),
99
- );
100
- }
101
-
102
- function getCliBin() {
103
- return path.join(rootDir, "bin", "mgl.js");
104
- }
105
-
106
- function getLinuxServiceFile() {
107
- return `/etc/systemd/system/${SERVICE_NAME}.service`;
108
- }
76
+ function installLinuxService() {
77
+ if (!isRootOnLinux()) {
78
+ log(
79
+ "Skipping systemd setup (not running as root).\n" +
80
+ " To install manually: sudo npm install -g magalh",
81
+ );
82
+ return;
83
+ }
109
84
 
110
- function ensureEntryFileExists() {
111
- if (!fileExists(entryFile)) {
112
- fail(`Entry file not found: ${entryFile}`);
85
+ const systemdDir = "/etc/systemd/system";
86
+ if (!fs.existsSync(systemdDir)) {
87
+ log("Skipping systemd setup (systemd not found).");
88
+ return;
113
89
  }
114
- }
115
90
 
116
- function getLinuxServiceContent() {
91
+ const serviceFile = path.join(systemdDir, `${SERVICE_NAME}.service`);
117
92
  const nodeBin = process.execPath;
118
- const cliBin = getCliBin();
93
+ const cliBin = path.join(rootDir, "bin", "mgl.js");
119
94
 
120
- return [
95
+ const serviceContent = [
121
96
  "[Unit]",
122
97
  `Description=${SERVICE_DISPLAY_NAME}`,
123
98
  "After=network-online.target",
@@ -137,37 +112,10 @@ function getLinuxServiceContent() {
137
112
  "WantedBy=multi-user.target",
138
113
  "",
139
114
  ].join("\n");
140
- }
141
-
142
- function isLinuxServiceInstalled() {
143
- return fileExists(getLinuxServiceFile());
144
- }
145
-
146
- function isWindowsServiceInstalled() {
147
- const out = runCommandQuiet("sc", ["query", SERVICE_NAME]);
148
- return typeof out === "string" && out.includes("SERVICE_NAME");
149
- }
150
-
151
- function installLinuxService() {
152
- if (!isRootOnLinux()) {
153
- fail("Linux service installation requires root. Run: sudo magalh --install-service");
154
- }
155
-
156
- const systemdDir = "/etc/systemd/system";
157
- if (!fileExists(systemdDir)) {
158
- fail("systemd directory not found. Service install is not supported on this Linux system.");
159
- }
160
-
161
- const cliBin = getCliBin();
162
- if (!fileExists(cliBin)) {
163
- fail(`CLI file not found: ${cliBin}`);
164
- }
165
-
166
- const serviceFile = getLinuxServiceFile();
167
- const content = getLinuxServiceContent();
168
115
 
169
116
  try {
170
- fs.writeFileSync(serviceFile, content, { mode: 0o644 });
117
+ fs.writeFileSync(serviceFile, serviceContent, { mode: 0o644 });
118
+
171
119
  log(`Service file written -> ${serviceFile}`);
172
120
 
173
121
  runCommand("systemctl", ["daemon-reload"]);
@@ -180,66 +128,26 @@ function installLinuxService() {
180
128
  ` Logs : journalctl -u ${SERVICE_NAME} -f`,
181
129
  );
182
130
  } catch (error) {
183
- fail(`Linux service installation failed: ${error.message || String(error)}`);
184
- }
185
- }
186
-
187
- function uninstallLinuxService() {
188
- if (!isRootOnLinux()) {
189
- fail("Linux service removal requires root. Run: sudo magalh --uninstall-service");
190
- }
191
-
192
- const serviceFile = getLinuxServiceFile();
193
-
194
- try {
195
- runCommandQuiet("systemctl", ["stop", SERVICE_NAME]);
196
- runCommandQuiet("systemctl", ["disable", SERVICE_NAME]);
197
-
198
- if (fileExists(serviceFile)) {
199
- fs.unlinkSync(serviceFile);
200
- log(`Removed service file -> ${serviceFile}`);
201
- } else {
202
- log("Service file does not exist. Nothing to remove.");
203
- }
204
-
205
- runCommand("systemctl", ["daemon-reload"]);
206
- log("Linux service removed.");
207
- } catch (error) {
208
- fail(`Linux service removal failed: ${error.message || String(error)}`);
209
- }
210
- }
211
-
212
- function printLinuxServiceStatus() {
213
- if (!isLinuxServiceInstalled()) {
214
- log("Linux service is not installed.");
215
- process.exit(0);
216
- }
217
-
218
- log(`Linux service file exists -> ${getLinuxServiceFile()}`);
219
- const status = runCommandQuiet("systemctl", ["status", SERVICE_NAME, "--no-pager"]);
220
- if (status) {
221
- process.stdout.write(`${status}\n`);
222
- } else {
223
- warn("Could not read systemd status output.");
131
+ warn(`Warning: systemd setup failed: ${error.message || String(error)}`);
224
132
  }
225
133
  }
226
134
 
227
135
  function installWindowsService() {
228
136
  if (!isWindowsAdminLike()) {
229
- fail("Windows service installation requires Administrator privileges.");
230
- }
231
-
232
- const cliBin = getCliBin();
233
- if (!fileExists(cliBin)) {
234
- fail(`CLI file not found: ${cliBin}`);
137
+ log(
138
+ "Skipping Windows service setup (not running as Administrator).\n" +
139
+ " To install manually: run npm install -g magalh as Administrator.",
140
+ );
141
+ return;
235
142
  }
236
143
 
237
144
  const nodeBin = process.execPath;
145
+ const cliBin = path.join(rootDir, "bin", "mgl.js");
238
146
  const binPath = `"${nodeBin}" "${cliBin}"`;
239
147
 
240
148
  try {
241
- runCommandQuiet("sc", ["stop", SERVICE_NAME]);
242
- runCommandQuiet("sc", ["delete", SERVICE_NAME]);
149
+ safeRunCommand("sc", ["stop", SERVICE_NAME]);
150
+ safeRunCommand("sc", ["delete", SERVICE_NAME]);
243
151
 
244
152
  runCommand("sc", [
245
153
  "create",
@@ -276,83 +184,21 @@ function installWindowsService() {
276
184
  " Logs : Event Viewer -> Windows Logs -> Application",
277
185
  );
278
186
  } catch (error) {
279
- fail(`Windows service installation failed: ${error.message || String(error)}`);
280
- }
281
- }
282
-
283
- function uninstallWindowsService() {
284
- if (!isWindowsAdminLike()) {
285
- fail("Windows service removal requires Administrator privileges.");
286
- }
287
-
288
- try {
289
- runCommandQuiet("sc", ["stop", SERVICE_NAME]);
290
- runCommandQuiet("sc", ["delete", SERVICE_NAME]);
291
- log("Windows service removed.");
292
- } catch (error) {
293
- fail(`Windows service removal failed: ${error.message || String(error)}`);
294
- }
295
- }
296
-
297
- function printWindowsServiceStatus() {
298
- if (!isWindowsServiceInstalled()) {
299
- log("Windows service is not installed.");
300
- process.exit(0);
301
- }
302
-
303
- const status = runCommandQuiet("sc", ["query", SERVICE_NAME]);
304
- if (status) {
305
- process.stdout.write(`${status}\n`);
306
- } else {
307
- warn("Could not read Windows service status output.");
187
+ warn(`Warning: Windows service setup failed: ${error.message || String(error)}`);
308
188
  }
309
189
  }
310
190
 
311
191
  function installService() {
312
192
  if (process.platform === "linux") {
313
193
  installLinuxService();
314
- return;
315
- }
316
-
317
- if (process.platform === "win32") {
194
+ } else if (process.platform === "win32") {
318
195
  installWindowsService();
319
- return;
320
- }
321
-
322
- fail(`Service installation is not supported on platform: ${process.platform}`);
323
- }
324
-
325
- function uninstallService() {
326
- if (process.platform === "linux") {
327
- uninstallLinuxService();
328
- return;
329
- }
330
-
331
- if (process.platform === "win32") {
332
- uninstallWindowsService();
333
- return;
334
- }
335
-
336
- fail(`Service removal is not supported on platform: ${process.platform}`);
337
- }
338
-
339
- function printServiceStatus() {
340
- if (process.platform === "linux") {
341
- printLinuxServiceStatus();
342
- return;
343
- }
344
-
345
- if (process.platform === "win32") {
346
- printWindowsServiceStatus();
347
- return;
196
+ } else {
197
+ log(`Service install is not supported on platform: ${process.platform}`);
348
198
  }
349
-
350
- log(`Service status is not supported on platform: ${process.platform}`);
351
199
  }
352
200
 
353
201
  function startMainProcess() {
354
- ensureEntryFileExists();
355
-
356
202
  const child = spawn(process.execPath, [entryFile, ...args], {
357
203
  cwd: rootDir,
358
204
  env: process.env,
@@ -364,13 +210,44 @@ function startMainProcess() {
364
210
  if (signal) {
365
211
  process.exit(1);
366
212
  }
213
+ process.exit(typeof code === "number" ? code : 0);
367
214
  });
368
215
 
369
216
  child.on("error", (error) => {
370
- fail(`Failed to start msh: ${error.message || String(error)}`);
217
+ try {
218
+ process.stderr.write(
219
+ `Failed to start msh: ${error.message || String(error)}\n`,
220
+ );
221
+ } catch {
222
+ }
223
+ process.exit(1);
371
224
  });
372
225
  }
373
226
 
227
+ function isWindowsServiceInstalled() {
228
+ try {
229
+ const out = execFileSync("sc", ["query", SERVICE_NAME], { stdio: "pipe" }).toString();
230
+ return out.includes("SERVICE_NAME");
231
+ } catch {
232
+ return false;
233
+ }
234
+ }
235
+
236
+ function autoInstallServiceIfNeeded() {
237
+ if (process.platform === "linux") {
238
+ const serviceFile = `/etc/systemd/system/${SERVICE_NAME}.service`;
239
+ if (!fs.existsSync(serviceFile)) {
240
+ log("Service not found, attempting auto-install...");
241
+ installLinuxService();
242
+ }
243
+ } else if (process.platform === "win32") {
244
+ if (!isWindowsServiceInstalled()) {
245
+ log("Service not found, attempting auto-install...");
246
+ installWindowsService();
247
+ }
248
+ }
249
+ }
250
+
374
251
  function main() {
375
252
  if (hasArg("--help") || hasArg("-h")) {
376
253
  printHelp();
@@ -382,16 +259,7 @@ function main() {
382
259
  process.exit(0);
383
260
  }
384
261
 
385
- if (hasArg("--uninstall-service")) {
386
- uninstallService();
387
- process.exit(0);
388
- }
389
-
390
- if (hasArg("--service-status")) {
391
- printServiceStatus();
392
- process.exit(0);
393
- }
394
-
262
+ autoInstallServiceIfNeeded();
395
263
  startMainProcess();
396
264
  }
397
265