unitup 0.0.8 → 0.0.10
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 +398 -171
- package/docs/index.html +531 -0
- package/index.d.ts +204 -134
- package/package.json +4 -1
- package/src/cli.js +393 -90
- package/src/doctor.js +73 -14
- package/src/index.js +32 -1
- package/src/runtimes/bun.js +46 -0
- package/src/runtimes/common.js +73 -0
- package/src/runtimes/deno.js +46 -0
- package/src/runtimes/elixir.js +46 -0
- package/src/runtimes/go.js +46 -0
- package/src/runtimes/index.js +155 -0
- package/src/runtimes/native.js +38 -0
- package/src/runtimes/node.js +57 -0
- package/src/runtimes/php.js +46 -0
- package/src/runtimes/python.js +46 -0
- package/src/runtimes/ruby.js +46 -0
- package/src/runtimes/shell.js +46 -0
- package/src/systemd.js +349 -25
- package/src/unit.js +72 -22
- package/src/utils.js +220 -0
package/index.d.ts
CHANGED
|
@@ -1,23 +1,44 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* unitup -
|
|
2
|
+
* unitup - Systemd user service manager for any executable & runtime
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { ChildProcess } from 'node:child_process';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* Options for creating/adding a
|
|
8
|
+
* Options for creating/adding a systemd user service.
|
|
9
9
|
*/
|
|
10
10
|
export interface CreateServiceOptions {
|
|
11
11
|
/**
|
|
12
|
-
* Name of the service (e.g., 'api' or '
|
|
12
|
+
* Name of the service (e.g., 'api' or 'worker').
|
|
13
13
|
* Safe characters: lowercase letters, numbers, hyphens, underscores.
|
|
14
14
|
*/
|
|
15
15
|
name: string;
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
*
|
|
18
|
+
* Optional group name (e.g. 'myproject').
|
|
19
|
+
* @default 'default'
|
|
19
20
|
*/
|
|
20
|
-
|
|
21
|
+
group?: string;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Target runtime name (e.g. 'node', 'python', 'ruby', 'php', 'bun', 'deno', 'shell', 'go', 'elixir', 'native').
|
|
25
|
+
*/
|
|
26
|
+
runtime?: string;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Runtime-specific flags/arguments passed before script (e.g. ['--allow-net'] for Deno or ['-S', '0.0.0.0:8080'] for PHP).
|
|
30
|
+
*/
|
|
31
|
+
runtimeArgs?: string[];
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Explicit executable command binary path (bypasses runtime auto-detection).
|
|
35
|
+
*/
|
|
36
|
+
command?: string;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Absolute or relative path to the target script file.
|
|
40
|
+
*/
|
|
41
|
+
script?: string;
|
|
21
42
|
|
|
22
43
|
/**
|
|
23
44
|
* Working directory path for the service execution (defaults to script directory).
|
|
@@ -25,7 +46,7 @@ export interface CreateServiceOptions {
|
|
|
25
46
|
cwd?: string;
|
|
26
47
|
|
|
27
48
|
/**
|
|
28
|
-
* Absolute path to explicit Node.js executable binary (
|
|
49
|
+
* Absolute path to explicit Node.js executable binary (legacy support).
|
|
29
50
|
*/
|
|
30
51
|
nodePath?: string;
|
|
31
52
|
|
|
@@ -46,7 +67,7 @@ export interface CreateServiceOptions {
|
|
|
46
67
|
restart?: string;
|
|
47
68
|
|
|
48
69
|
/**
|
|
49
|
-
* Positional arguments to pass to the script execution line.
|
|
70
|
+
* Positional arguments to pass to the script/command execution line.
|
|
50
71
|
*/
|
|
51
72
|
args?: string[];
|
|
52
73
|
|
|
@@ -55,6 +76,47 @@ export interface CreateServiceOptions {
|
|
|
55
76
|
* @default false
|
|
56
77
|
*/
|
|
57
78
|
start?: boolean;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Soft memory limit directive (e.g. '400M').
|
|
82
|
+
*/
|
|
83
|
+
memoryHigh?: string;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Hard memory limit directive (e.g. '512M').
|
|
87
|
+
*/
|
|
88
|
+
memoryMax?: string;
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Swap memory limit directive (e.g. '256M').
|
|
92
|
+
*/
|
|
93
|
+
memorySwapMax?: string;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Options for setting or resetting service memory limits.
|
|
98
|
+
*/
|
|
99
|
+
export interface ServiceLimitsOptions {
|
|
100
|
+
/**
|
|
101
|
+
* Soft memory limit directive (e.g. '400M').
|
|
102
|
+
*/
|
|
103
|
+
memoryHigh?: string;
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Hard memory limit directive (e.g. '512M').
|
|
107
|
+
*/
|
|
108
|
+
memoryMax?: string;
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Swap memory limit directive (e.g. '256M').
|
|
112
|
+
*/
|
|
113
|
+
memorySwapMax?: string;
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Resets all memory limits back to defaults/infinity.
|
|
117
|
+
* @default false
|
|
118
|
+
*/
|
|
119
|
+
resetMemory?: boolean;
|
|
58
120
|
}
|
|
59
121
|
|
|
60
122
|
/**
|
|
@@ -134,6 +196,21 @@ export interface ServiceStatus {
|
|
|
134
196
|
*/
|
|
135
197
|
startedRaw?: string;
|
|
136
198
|
|
|
199
|
+
/**
|
|
200
|
+
* Executable command path.
|
|
201
|
+
*/
|
|
202
|
+
command: string;
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Command arguments string.
|
|
206
|
+
*/
|
|
207
|
+
arguments: string;
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Array of command arguments.
|
|
211
|
+
*/
|
|
212
|
+
args: string[];
|
|
213
|
+
|
|
137
214
|
/**
|
|
138
215
|
* Path to target script parsed from unit file.
|
|
139
216
|
*/
|
|
@@ -155,58 +232,115 @@ export interface ListServiceItem {
|
|
|
155
232
|
name: string;
|
|
156
233
|
|
|
157
234
|
/**
|
|
158
|
-
*
|
|
235
|
+
* Runtime name.
|
|
159
236
|
*/
|
|
160
|
-
|
|
237
|
+
runtime: string;
|
|
161
238
|
|
|
162
239
|
/**
|
|
163
|
-
*
|
|
240
|
+
* Group name.
|
|
164
241
|
*/
|
|
165
|
-
|
|
166
|
-
}
|
|
242
|
+
group: string;
|
|
167
243
|
|
|
168
|
-
/**
|
|
169
|
-
* Diagnostic results for Node.js runtime environment.
|
|
170
|
-
*/
|
|
171
|
-
export interface NodeDiagnostics {
|
|
172
244
|
/**
|
|
173
|
-
*
|
|
245
|
+
* Status overview ('running', 'stopped', 'failed', etc.).
|
|
174
246
|
*/
|
|
175
|
-
|
|
247
|
+
status: string;
|
|
176
248
|
|
|
177
249
|
/**
|
|
178
|
-
*
|
|
250
|
+
* Enabled status ('yes' or 'no').
|
|
179
251
|
*/
|
|
180
|
-
|
|
252
|
+
enabled: string;
|
|
181
253
|
|
|
182
254
|
/**
|
|
183
|
-
*
|
|
255
|
+
* Main PID or '-'.
|
|
184
256
|
*/
|
|
185
|
-
|
|
257
|
+
pid: string;
|
|
186
258
|
|
|
187
259
|
/**
|
|
188
|
-
*
|
|
260
|
+
* Command summary (e.g. 'node server.js' or 'python3 worker.py').
|
|
189
261
|
*/
|
|
190
|
-
|
|
262
|
+
command: string;
|
|
191
263
|
|
|
192
264
|
/**
|
|
193
|
-
*
|
|
265
|
+
* Formatted uptime string.
|
|
194
266
|
*/
|
|
195
|
-
|
|
267
|
+
uptime: string;
|
|
196
268
|
|
|
197
269
|
/**
|
|
198
|
-
*
|
|
270
|
+
* Restart count.
|
|
199
271
|
*/
|
|
200
|
-
|
|
272
|
+
restarts: string;
|
|
273
|
+
}
|
|
201
274
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
275
|
+
/**
|
|
276
|
+
* App metadata saved in ~/.config/unitup/apps/<name>.json.
|
|
277
|
+
*/
|
|
278
|
+
export interface AppMetadata {
|
|
279
|
+
name: string;
|
|
280
|
+
unit: string;
|
|
281
|
+
runtime?: string;
|
|
282
|
+
command?: string;
|
|
283
|
+
args?: string[];
|
|
284
|
+
group: string;
|
|
285
|
+
script: string;
|
|
286
|
+
cwd: string;
|
|
287
|
+
node: string;
|
|
288
|
+
}
|
|
206
289
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
290
|
+
/**
|
|
291
|
+
* Detailed application inspection summary (unitup inspect).
|
|
292
|
+
*/
|
|
293
|
+
export interface InspectInfo {
|
|
294
|
+
name: string;
|
|
295
|
+
runtime: string;
|
|
296
|
+
unit: string;
|
|
297
|
+
unitPath: string;
|
|
298
|
+
group: string;
|
|
299
|
+
status: string;
|
|
300
|
+
activeState: string;
|
|
301
|
+
subState: string;
|
|
302
|
+
command: string;
|
|
303
|
+
arguments: string;
|
|
304
|
+
args: string[];
|
|
305
|
+
cwd: string;
|
|
306
|
+
pid: string;
|
|
307
|
+
restarts: string;
|
|
308
|
+
started: string;
|
|
309
|
+
|
|
310
|
+
memory?: string;
|
|
311
|
+
memoryPeak?: string;
|
|
312
|
+
memoryHigh?: string;
|
|
313
|
+
memoryMax?: string;
|
|
314
|
+
memorySwapMax?: string;
|
|
315
|
+
|
|
316
|
+
// Legacy compatibility fields
|
|
317
|
+
script?: string;
|
|
318
|
+
node?: string;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Failed service failure report item (unitup failures).
|
|
323
|
+
*/
|
|
324
|
+
export interface FailureItem {
|
|
325
|
+
name: string;
|
|
326
|
+
group: string;
|
|
327
|
+
status: string;
|
|
328
|
+
exitCode: string;
|
|
329
|
+
restarts: string;
|
|
330
|
+
uptime: string;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Diagnostic results for Node.js runtime environment.
|
|
335
|
+
*/
|
|
336
|
+
export interface NodeDiagnostics {
|
|
337
|
+
found: boolean;
|
|
338
|
+
executable: boolean;
|
|
339
|
+
execPath: string;
|
|
340
|
+
whichPath: string;
|
|
341
|
+
version: string;
|
|
342
|
+
inPath: boolean;
|
|
343
|
+
error: string | null;
|
|
210
344
|
solution: string | null;
|
|
211
345
|
}
|
|
212
346
|
|
|
@@ -214,59 +348,21 @@ export interface NodeDiagnostics {
|
|
|
214
348
|
* Diagnostic report object from unitup doctor.
|
|
215
349
|
*/
|
|
216
350
|
export interface DoctorInfo {
|
|
217
|
-
/**
|
|
218
|
-
* True if OS is Linux.
|
|
219
|
-
*/
|
|
220
351
|
linux: boolean;
|
|
221
|
-
|
|
222
|
-
/**
|
|
223
|
-
* True if systemctl binary is found in PATH.
|
|
224
|
-
*/
|
|
225
352
|
systemctl: boolean;
|
|
226
|
-
|
|
227
|
-
/**
|
|
228
|
-
* True if systemd is running as PID 1.
|
|
229
|
-
*/
|
|
230
353
|
systemdRunning: boolean;
|
|
231
|
-
|
|
232
|
-
/**
|
|
233
|
-
* True if systemd user session bus is accessible.
|
|
234
|
-
*/
|
|
235
354
|
userSystemdAvailable: boolean;
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
355
|
+
cgroupV2?: boolean;
|
|
356
|
+
memoryController?: boolean;
|
|
357
|
+
memoryMaxSupported?: boolean;
|
|
358
|
+
memorySwapMaxSupported?: boolean;
|
|
240
359
|
nodeDiag: NodeDiagnostics;
|
|
241
|
-
|
|
242
|
-
/**
|
|
243
|
-
* Resolved Node.js executable path.
|
|
244
|
-
*/
|
|
245
360
|
nodePath: string;
|
|
246
|
-
|
|
247
|
-
/**
|
|
248
|
-
* Node.js version string.
|
|
249
|
-
*/
|
|
250
361
|
nodeVersion: string;
|
|
251
|
-
|
|
252
|
-
/**
|
|
253
|
-
* Systemd user unit directory path.
|
|
254
|
-
*/
|
|
362
|
+
runtimes: Record<string, string | null>;
|
|
255
363
|
unitDir: string;
|
|
256
|
-
|
|
257
|
-
/**
|
|
258
|
-
* True if unit directory is writable.
|
|
259
|
-
*/
|
|
260
364
|
unitDirWritable: boolean;
|
|
261
|
-
|
|
262
|
-
/**
|
|
263
|
-
* True if user lingering is enabled (loginctl enable-linger).
|
|
264
|
-
*/
|
|
265
365
|
lingering: boolean;
|
|
266
|
-
|
|
267
|
-
/**
|
|
268
|
-
* Current OS username.
|
|
269
|
-
*/
|
|
270
366
|
username: string;
|
|
271
367
|
}
|
|
272
368
|
|
|
@@ -274,14 +370,7 @@ export interface DoctorInfo {
|
|
|
274
370
|
* Result returned when creating/adding a new unitup service.
|
|
275
371
|
*/
|
|
276
372
|
export interface AddServiceResult {
|
|
277
|
-
/**
|
|
278
|
-
* Cleaned service name.
|
|
279
|
-
*/
|
|
280
373
|
name: string;
|
|
281
|
-
|
|
282
|
-
/**
|
|
283
|
-
* Path to created unit file.
|
|
284
|
-
*/
|
|
285
374
|
unitPath: string;
|
|
286
375
|
}
|
|
287
376
|
|
|
@@ -289,9 +378,14 @@ export interface AddServiceResult {
|
|
|
289
378
|
* Parsed systemd unit file content metadata.
|
|
290
379
|
*/
|
|
291
380
|
export interface ParsedUnitContent {
|
|
381
|
+
command?: string;
|
|
382
|
+
args?: string[];
|
|
292
383
|
script?: string;
|
|
293
384
|
cwd?: string;
|
|
294
385
|
restart?: string;
|
|
386
|
+
memoryHigh?: string;
|
|
387
|
+
memoryMax?: string;
|
|
388
|
+
memorySwapMax?: string;
|
|
295
389
|
}
|
|
296
390
|
|
|
297
391
|
/**
|
|
@@ -307,58 +401,36 @@ export type CommandRunnerFn = (
|
|
|
307
401
|
// Programmatic API Function Declarations
|
|
308
402
|
// ---------------------------------------------------------------------------
|
|
309
403
|
|
|
310
|
-
/**
|
|
311
|
-
* Creates and writes a systemd user service unit file, then reloads the systemd daemon.
|
|
312
|
-
*/
|
|
313
404
|
export function createService(options: CreateServiceOptions): Promise<AddServiceResult>;
|
|
314
405
|
export function addService(options: CreateServiceOptions): Promise<AddServiceResult>;
|
|
315
|
-
|
|
316
|
-
/**
|
|
317
|
-
* Starts a systemd user service unit.
|
|
318
|
-
* @param name Service name (e.g. 'api')
|
|
319
|
-
* @param enable If true, enables the service on boot (--enable)
|
|
320
|
-
*/
|
|
321
406
|
export function startService(name: string, enable?: boolean): Promise<boolean>;
|
|
322
|
-
|
|
323
|
-
/**
|
|
324
|
-
* Stops a running systemd user service unit.
|
|
325
|
-
*/
|
|
326
407
|
export function stopService(name: string): Promise<boolean>;
|
|
327
|
-
|
|
328
|
-
/**
|
|
329
|
-
* Restarts a systemd user service unit.
|
|
330
|
-
*/
|
|
331
408
|
export function restartService(name: string): Promise<boolean>;
|
|
332
|
-
|
|
333
|
-
/**
|
|
334
|
-
* Stops, disables, and deletes a systemd user service unit file, then reloads daemon.
|
|
335
|
-
*/
|
|
336
409
|
export function removeService(name: string): Promise<boolean>;
|
|
337
|
-
|
|
338
|
-
/**
|
|
339
|
-
* Retrieves compact parsed status information for a service.
|
|
340
|
-
*/
|
|
341
410
|
export function getServiceStatus(name: string): Promise<ServiceStatus>;
|
|
342
|
-
|
|
343
|
-
/**
|
|
344
|
-
* Retrieves raw string output of systemctl --user status.
|
|
345
|
-
*/
|
|
346
411
|
export function getServiceStatusRaw(name: string): Promise<string>;
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
export function
|
|
352
|
-
|
|
353
|
-
/**
|
|
354
|
-
* Fetches or streams journalctl logs for a service.
|
|
355
|
-
*/
|
|
412
|
+
export function listServices(options?: { group?: string }): Promise<ListServiceItem[]>;
|
|
413
|
+
export function inspectService(name: string): Promise<InspectInfo>;
|
|
414
|
+
export function getServiceFailures(): Promise<FailureItem[]>;
|
|
415
|
+
export function getServicesByGroup(groupName: string): Promise<string[]>;
|
|
416
|
+
export function setServiceLimits(name: string, options?: ServiceLimitsOptions): Promise<InspectInfo>;
|
|
417
|
+
export function executeJournalctlMaintenance(action: string, options?: Record<string, unknown>): Promise<string>;
|
|
356
418
|
export function getServiceLogs(name: string, options?: LogOptions): Promise<string | ChildProcess>;
|
|
357
419
|
|
|
358
|
-
//
|
|
359
|
-
|
|
360
|
-
|
|
420
|
+
// Validation & Formatting Helpers
|
|
421
|
+
export function validateMemorySize(val: string | number, paramName?: string): string;
|
|
422
|
+
export function formatMemoryBytes(bytes: number | string): string;
|
|
361
423
|
|
|
424
|
+
// Runtime Helpers
|
|
425
|
+
export function detectRuntime(filepath: string): string;
|
|
426
|
+
export function resolveRuntimeConfig(options: CreateServiceOptions): Promise<{
|
|
427
|
+
command: string;
|
|
428
|
+
args: string[];
|
|
429
|
+
runtime: string;
|
|
430
|
+
version: string;
|
|
431
|
+
}>;
|
|
432
|
+
|
|
433
|
+
// Diagnostics & Doctor
|
|
362
434
|
export function isSystemdAvailable(): Promise<boolean>;
|
|
363
435
|
export function isSystemctlAvailable(): Promise<boolean>;
|
|
364
436
|
export function isLinux(): boolean;
|
|
@@ -369,10 +441,7 @@ export function checkNodeDiagnostics(customNodePath?: string): Promise<NodeDiagn
|
|
|
369
441
|
export function findNodeExecutable(customPath?: string): Promise<string | null>;
|
|
370
442
|
export function getDoctorInfo(): Promise<DoctorInfo>;
|
|
371
443
|
|
|
372
|
-
//
|
|
373
|
-
// Unit File & Path Helpers
|
|
374
|
-
// ---------------------------------------------------------------------------
|
|
375
|
-
|
|
444
|
+
// Path & Unit Helpers
|
|
376
445
|
export function getUserUnitDir(): string;
|
|
377
446
|
export function getUnitPath(name: string): string;
|
|
378
447
|
export function unitFileExists(name: string): boolean;
|
|
@@ -380,10 +449,11 @@ export function parseUnitContent(content: string): ParsedUnitContent;
|
|
|
380
449
|
export function sanitizeServiceName(name: string): string;
|
|
381
450
|
export function getUnitFilename(name: string): string;
|
|
382
451
|
export function getServiceNameFromUnit(unitFilename: string): string;
|
|
452
|
+
export function readAppMetadata(name: string): AppMetadata | null;
|
|
453
|
+
export function getAppMetadataPath(name: string): string;
|
|
454
|
+
export function getAppsDir(): string;
|
|
455
|
+
export function getUnitupDir(): string;
|
|
383
456
|
|
|
384
|
-
//
|
|
385
|
-
// Runner Override Helpers for Testing
|
|
386
|
-
// ---------------------------------------------------------------------------
|
|
387
|
-
|
|
457
|
+
// Testing Mock Helpers
|
|
388
458
|
export function setCommandRunner(runner: CommandRunnerFn): void;
|
|
389
459
|
export function resetCommandRunner(): void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "unitup",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.10",
|
|
4
4
|
"description": "Minimal systemd user service wrapper for Node.js scripts",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"types": "./index.d.ts",
|
|
@@ -11,6 +11,9 @@
|
|
|
11
11
|
"scripts": {
|
|
12
12
|
"test": "node --test test/*.test.js"
|
|
13
13
|
},
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"typescript": "^5.7.3"
|
|
16
|
+
},
|
|
14
17
|
"keywords": [
|
|
15
18
|
"systemd",
|
|
16
19
|
"service",
|