unitup 0.1.4 → 0.2.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/index.d.ts CHANGED
@@ -1,11 +1,12 @@
1
1
  /**
2
- * unitup - Systemd user service manager for any executable & runtime
2
+ * unitup - Cross-platform native background service manager (systemd, launchd, Windows Services)
3
3
  */
4
4
 
5
- import { ChildProcess } from 'node:child_process';
5
+ import type { ChildProcess } from 'node:child_process';
6
+ import type { EventEmitter } from 'node:events';
6
7
 
7
8
  /**
8
- * Options for creating/adding a systemd user service.
9
+ * Options for creating/adding/installing a service.
9
10
  */
10
11
  export interface CreateServiceOptions {
11
12
  /**
@@ -14,6 +15,16 @@ export interface CreateServiceOptions {
14
15
  */
15
16
  name: string;
16
17
 
18
+ /**
19
+ * Optional display name (used on Windows/macOS where supported).
20
+ */
21
+ displayName?: string;
22
+
23
+ /**
24
+ * Optional service description.
25
+ */
26
+ description?: string;
27
+
17
28
  /**
18
29
  * Optional group name (e.g. 'myproject').
19
30
  * @default 'default'
@@ -26,7 +37,7 @@ export interface CreateServiceOptions {
26
37
  runtime?: string;
27
38
 
28
39
  /**
29
- * Runtime-specific flags/arguments passed before script (e.g. ['--allow-net'] for Deno or ['-S', '0.0.0.0:8080'] for PHP).
40
+ * Runtime-specific flags/arguments passed before script.
30
41
  */
31
42
  runtimeArgs?: string[];
32
43
 
@@ -51,20 +62,28 @@ export interface CreateServiceOptions {
51
62
  nodePath?: string;
52
63
 
53
64
  /**
54
- * Key-value map of environment variables to inject into the systemd unit.
65
+ * Key-value map of environment variables to inject.
55
66
  */
56
67
  env?: Record<string, string>;
57
68
 
58
69
  /**
59
- * Path to an environment file (adds EnvironmentFile=... directive).
70
+ * Path to an environment file.
60
71
  */
61
72
  envFile?: string;
62
73
 
63
74
  /**
64
- * Systemd restart policy directive (e.g., 'on-failure', 'always', 'no', 'on-abnormal').
75
+ * Restart policy string (e.g., 'on-failure', 'always', 'no') or object.
65
76
  * @default 'on-failure'
66
77
  */
67
- restart?: string;
78
+ restart?:
79
+ | string
80
+ | {
81
+ enabled?: boolean;
82
+ policy?: string;
83
+ delay?: number;
84
+ maxRetries?: number | null;
85
+ resetAfter?: number | null;
86
+ };
68
87
 
69
88
  /**
70
89
  * Positional arguments to pass to the script/command execution line.
@@ -84,30 +103,25 @@ export interface CreateServiceOptions {
84
103
  force?: boolean;
85
104
 
86
105
  /**
87
- * Soft memory limit directive (e.g. '400M').
88
- */
89
- memoryHigh?: string;
90
-
91
- /**
92
- * Hard memory limit directive (e.g. '512M').
106
+ * Install as system-wide daemon (LaunchDaemons on macOS, root systemd on Linux).
107
+ * @default false
93
108
  */
94
- memoryMax?: string;
109
+ system?: boolean;
95
110
 
96
111
  /**
97
- * Swap memory limit directive (e.g. '256M').
112
+ * Graceful shutdown timeout in milliseconds before force killing child.
113
+ * @default 10000
98
114
  */
99
- memorySwapMax?: string;
115
+ shutdownTimeout?: number;
100
116
 
101
117
  /**
102
- * Default memory limit fallback or request marker (defaults to '1G').
118
+ * Custom log paths.
103
119
  */
104
- defaultMemory?: string | boolean;
105
- }
120
+ logs?: {
121
+ stdout?: string;
122
+ stderr?: string;
123
+ };
106
124
 
107
- /**
108
- * Options for setting or resetting service memory limits.
109
- */
110
- export interface ServiceLimitsOptions {
111
125
  /**
112
126
  * Soft memory limit directive (e.g. '400M').
113
127
  */
@@ -124,215 +138,167 @@ export interface ServiceLimitsOptions {
124
138
  memorySwapMax?: string;
125
139
 
126
140
  /**
127
- * Resets all memory limits back to defaults/infinity.
128
- * @default false
141
+ * Default memory limit fallback or request marker (defaults to '1G').
129
142
  */
130
- resetMemory?: boolean;
143
+ defaultMemory?: string | boolean;
131
144
  }
132
145
 
133
- /**
134
- * Options for retrieving journalctl log output.
135
- */
136
- export interface LogOptions {
137
- /**
138
- * Live streaming follow mode (-f).
139
- * @default false
140
- */
141
- follow?: boolean;
142
-
143
- /**
144
- * Number of journal log lines to return (-n).
145
- * @default 100
146
- */
147
- lines?: number;
146
+ export interface InstallServiceOptions extends CreateServiceOptions {}
148
147
 
149
- /**
150
- * Raw unformatted console output (-o cat) without systemd metadata prefix.
151
- * @default false
152
- */
153
- cat?: boolean;
148
+ export interface NormalizedServiceConfig {
149
+ name: string;
150
+ displayName: string;
151
+ description: string;
152
+ runtime: string;
153
+ command: string;
154
+ args: string[];
155
+ script?: string;
156
+ cwd: string;
157
+ env: Record<string, string>;
158
+ envFile?: string;
159
+ autostart: boolean;
160
+ restart: {
161
+ enabled: boolean;
162
+ policy: string;
163
+ delay: number;
164
+ maxRetries?: number | null;
165
+ resetAfter?: number | null;
166
+ };
167
+ logs: {
168
+ stdout: string;
169
+ stderr: string;
170
+ };
171
+ group: string;
172
+ system: boolean;
173
+ shutdownTimeout: number;
174
+ resources: {
175
+ memoryHigh?: string;
176
+ memoryMax?: string;
177
+ memorySwapMax?: string;
178
+ };
179
+ raw?: Record<string, unknown>;
180
+ }
154
181
 
155
- /**
156
- * Journalctl output mode (e.g. 'cat', 'short', 'json').
157
- */
158
- output?: string;
182
+ export interface PlatformCapabilities {
183
+ serviceManager: 'systemd' | 'launchd' | 'windows' | 'none';
184
+ supports: {
185
+ install: boolean;
186
+ uninstall: boolean;
187
+ start: boolean;
188
+ stop: boolean;
189
+ restart: boolean;
190
+ enable: boolean;
191
+ disable: boolean;
192
+ status: boolean;
193
+ logs: boolean;
194
+ restartPolicy: boolean;
195
+ userServices: boolean;
196
+ systemServices: boolean;
197
+ memoryLimits: boolean;
198
+ schedule: boolean;
199
+ };
159
200
  }
160
201
 
161
- /**
162
- * Parsed compact service status summary.
163
- */
164
202
  export interface ServiceStatus {
165
- /**
166
- * Clean service name (e.g. 'api').
167
- */
168
203
  name: string;
169
-
170
- /**
171
- * Full systemd unit filename (e.g. 'unitup-api.service').
172
- */
173
- unitFile: string;
174
-
175
- /**
176
- * Status overview ('running', 'stopped', 'failed', 'exited', etc.).
177
- */
204
+ installed: boolean;
205
+ state: 'running' | 'stopped' | 'starting' | 'stopping' | 'failed' | 'scheduled' | 'unknown' | string;
178
206
  status: string;
179
-
180
- /**
181
- * Raw ActiveState string from systemctl show.
182
- */
183
- activeState: string;
184
-
185
- /**
186
- * Raw SubState string from systemctl show.
187
- */
188
- subState: string;
189
-
190
- /**
191
- * Main Process ID (PID) of the service, or '-' if stopped.
192
- */
207
+ enabled: boolean | string;
193
208
  pid: string;
194
-
195
- /**
196
- * Total number of restarts recorded by systemd.
197
- */
198
- restarts: string;
199
-
200
- /**
201
- * Relative formatted uptime/started string (e.g. '12 minutes ago').
202
- */
209
+ restarts: string | number;
203
210
  started: string;
204
-
205
- /**
206
- * Raw timestamp from systemctl show.
207
- */
208
- startedRaw?: string;
209
-
210
- /**
211
- * Executable command path.
212
- */
211
+ startedRaw?: string | null;
213
212
  command: string;
214
-
215
- /**
216
- * Command arguments string.
217
- */
218
213
  arguments: string;
219
-
220
- /**
221
- * Array of command arguments.
222
- */
223
214
  args: string[];
224
-
225
- /**
226
- * Path to target script parsed from unit file.
227
- */
228
- script: string;
229
-
230
- /**
231
- * Working directory parsed from unit file.
232
- */
215
+ script?: string;
233
216
  cwd: string;
217
+ unitFile?: string;
218
+ unitPath?: string;
219
+ platform: 'linux' | 'darwin' | 'win32' | string;
220
+ manager: 'systemd' | 'launchd' | 'windows' | string;
221
+ memory?: string;
222
+ memoryPeak?: string;
223
+ memoryHigh?: string;
224
+ memoryMax?: string;
225
+ memorySwapMax?: string;
226
+ details?: Record<string, unknown>;
234
227
  }
235
228
 
236
- /**
237
- * Service item in list overview.
238
- */
239
- export interface ListServiceItem {
240
- /**
241
- * Service name.
242
- */
243
- name: string;
244
-
245
- /**
246
- * Runtime name.
247
- */
248
- runtime: string;
249
-
250
- /**
251
- * Group name.
252
- */
253
- group: string;
254
-
255
- /**
256
- * Status overview ('running', 'stopped', 'failed', etc.).
257
- */
258
- status: string;
259
-
260
- /**
261
- * Enabled status ('yes' or 'no').
262
- */
263
- enabled: string;
264
-
265
- /**
266
- * Main PID or '-'.
267
- */
268
- pid: string;
269
-
270
- /**
271
- * Command summary (e.g. 'node server.js' or 'python3 worker.py').
272
- */
273
- command: string;
274
-
275
- /**
276
- * Formatted uptime string.
277
- */
278
- uptime: string;
279
-
280
- /**
281
- * Restart count.
282
- */
283
- restarts: string;
229
+ export interface LogOptions {
230
+ follow?: boolean;
231
+ lines?: number;
232
+ cat?: boolean;
233
+ output?: string;
234
+ since?: string;
235
+ until?: string;
236
+ priority?: string;
237
+ grep?: string;
238
+ boot?: boolean;
239
+ json?: boolean;
240
+ diskUsage?: boolean;
241
+ system?: boolean;
284
242
  }
285
243
 
286
- /**
287
- * App metadata saved in ~/.config/unitup/apps/<name>.json.
288
- */
289
244
  export interface AppMetadata {
290
- name: string;
291
- unit: string;
292
- runtime?: string;
293
- command?: string;
294
- args?: string[];
295
- group: string;
296
- script: string;
297
- cwd: string;
298
- node: string;
299
- }
300
-
301
- /**
302
- * Detailed application inspection summary (unitup inspect).
303
- */
304
- export interface InspectInfo {
305
245
  name: string;
306
246
  runtime: string;
307
- unit: string;
308
- unitPath: string;
309
- group: string;
310
- status: string;
311
- activeState: string;
312
- subState: string;
313
247
  command: string;
314
- arguments: string;
315
248
  args: string[];
316
249
  cwd: string;
317
- pid: string;
318
- restarts: string;
319
- started: string;
250
+ group?: string;
251
+ script?: string;
252
+ pid?: string;
253
+ restarts?: string;
254
+ started?: string;
255
+ logs?: {
256
+ stdout?: string;
257
+ stderr?: string;
258
+ };
259
+ resources?: {
260
+ memoryHigh?: string;
261
+ memoryMax?: string;
262
+ memorySwapMax?: string;
263
+ };
264
+ [key: string]: unknown;
265
+ }
320
266
 
321
- memory?: string;
322
- memoryPeak?: string;
323
- memoryHigh?: string;
324
- memoryMax?: string;
325
- memorySwapMax?: string;
267
+ export interface DoctorInfo {
268
+ platform: string;
269
+ systemdAvailable: boolean;
270
+ systemctlAvailable: boolean;
271
+ linux: boolean;
272
+ systemdRunning: boolean;
273
+ userSystemdAvailable: boolean;
274
+ lingering: boolean;
275
+ nodePath: string | null;
276
+ nodeVersion: string | null;
277
+ nodeValid: boolean;
278
+ username: string;
279
+ unitDir: string;
280
+ unitDirWritable: boolean;
281
+ [key: string]: unknown;
282
+ }
326
283
 
327
- // Legacy compatibility fields
328
- script?: string;
329
- node?: string;
284
+ export interface ListServiceItem {
285
+ name: string;
286
+ status: string;
287
+ enabled?: boolean | string;
288
+ pid?: string;
289
+ command?: string;
290
+ [key: string]: unknown;
330
291
  }
331
292
 
332
- /**
333
- * Failed service failure report item (unitup failures).
334
- */
335
- export interface FailureItem {
293
+ export interface NodeDiagnostics {
294
+ found: boolean;
295
+ path: string | null;
296
+ version: string | null;
297
+ valid: boolean;
298
+ error?: string;
299
+ }
300
+
301
+ export interface ServiceFailure {
336
302
  name: string;
337
303
  group: string;
338
304
  status: string;
@@ -341,137 +307,163 @@ export interface FailureItem {
341
307
  uptime: string;
342
308
  }
343
309
 
344
- /**
345
- * Diagnostic results for Node.js runtime environment.
346
- */
347
- export interface NodeDiagnostics {
348
- found: boolean;
349
- executable: boolean;
350
- execPath: string;
351
- whichPath: string;
352
- version: string;
353
- inPath: boolean;
354
- error: string | null;
355
- solution: string | null;
310
+ // Error Classes
311
+ export class UnitupError extends Error {
312
+ code: string;
356
313
  }
357
-
358
- /**
359
- * Diagnostic report object from unitup doctor.
360
- */
361
- export interface DoctorInfo {
362
- linux: boolean;
363
- systemctl: boolean;
364
- systemdRunning: boolean;
365
- userSystemdAvailable: boolean;
366
- cgroupV2?: boolean;
367
- memoryController?: boolean;
368
- memoryMaxSupported?: boolean;
369
- memorySwapMaxSupported?: boolean;
370
- nodeDiag: NodeDiagnostics;
371
- nodePath: string;
372
- nodeVersion: string;
373
- runtimes: Record<string, string | null>;
374
- unitDir: string;
375
- unitDirWritable: boolean;
376
- lingering: boolean;
377
- username: string;
314
+ export class UnsupportedPlatformError extends UnitupError {
315
+ platform: string;
378
316
  }
379
-
380
- /**
381
- * Result returned when creating/adding a new unitup service.
382
- */
383
- export interface AddServiceResult {
384
- name: string;
385
- unitPath: string;
317
+ export class ServiceNotFoundError extends UnitupError {
318
+ serviceName: string;
319
+ }
320
+ export class ServiceAlreadyExistsError extends UnitupError {
321
+ serviceName: string;
322
+ }
323
+ export class PermissionRequiredError extends UnitupError {
324
+ action?: string;
325
+ }
326
+ export class ServiceStartError extends UnitupError {
327
+ serviceName: string;
328
+ reason?: string;
329
+ }
330
+ export class ServiceStopError extends UnitupError {
331
+ serviceName: string;
332
+ reason?: string;
333
+ }
334
+ export class InvalidServiceConfigError extends UnitupError {
335
+ field?: string;
336
+ }
337
+ export class ExecutableNotFoundError extends UnitupError {
338
+ executable: string;
386
339
  }
387
340
 
388
- /**
389
- * Parsed systemd unit file content metadata.
390
- */
391
- export interface ParsedUnitContent {
392
- command?: string;
393
- args?: string[];
394
- script?: string;
395
- cwd?: string;
396
- restart?: string;
397
- memoryHigh?: string;
398
- memoryMax?: string;
399
- memorySwapMax?: string;
341
+ // Adapters
342
+ export abstract class ServiceAdapter {
343
+ constructor(options?: Record<string, unknown>);
344
+ readonly name: string;
345
+ readonly capabilities: PlatformCapabilities;
346
+ abstract generateService(config: NormalizedServiceConfig): string | Record<string, unknown>;
347
+ abstract install(
348
+ config: NormalizedServiceConfig,
349
+ options?: Record<string, unknown>
350
+ ): Promise<{ name: string; unitPath?: string; serviceName?: string }>;
351
+ abstract uninstall(name: string, options?: Record<string, unknown>): Promise<boolean>;
352
+ abstract start(name: string, options?: Record<string, unknown>): Promise<boolean>;
353
+ abstract stop(name: string, options?: Record<string, unknown>): Promise<boolean>;
354
+ abstract restart(name: string, options?: Record<string, unknown>): Promise<boolean>;
355
+ abstract enable(name: string, options?: Record<string, unknown>): Promise<boolean>;
356
+ abstract disable(name: string, options?: Record<string, unknown>): Promise<boolean>;
357
+ abstract status(name: string, options?: Record<string, unknown>): Promise<ServiceStatus>;
358
+ abstract inspect(name: string, options?: Record<string, unknown>): Promise<Record<string, unknown>>;
359
+ abstract logs(name: string, options?: LogOptions): Promise<string | EventEmitter | ChildProcess>;
360
+ abstract list(options?: { group?: string }): Promise<Array<Record<string, unknown>>>;
361
+ abstract isInstalled(name: string, options?: Record<string, unknown>): Promise<boolean> | boolean;
362
+ abstract failures(options?: Record<string, unknown>): Promise<ServiceFailure[]>;
400
363
  }
401
364
 
402
- /**
403
- * Command runner function definition used for internal mocking.
404
- */
405
- export type CommandRunnerFn = (
406
- cmd: string,
407
- args: string[],
408
- opts?: Record<string, unknown>
409
- ) => Promise<{ stdout: string; stderr: string; code: number }>;
365
+ export class LinuxAdapter extends ServiceAdapter {}
366
+ export class MacOSAdapter extends ServiceAdapter {}
367
+ export class WindowsAdapter extends ServiceAdapter {}
368
+ export class WindowsServiceHost {
369
+ constructor(config?: Record<string, unknown>);
370
+ start(): void;
371
+ stop(timeout?: number): Promise<void>;
372
+ }
410
373
 
411
- // ---------------------------------------------------------------------------
412
- // Programmatic API Function Declarations
413
- // ---------------------------------------------------------------------------
374
+ export class ServiceManager {
375
+ constructor(opts?: { platform?: string; adapter?: ServiceAdapter });
376
+ readonly capabilities: PlatformCapabilities;
377
+ generate(rawOpts?: CreateServiceOptions): Promise<string | Record<string, unknown>>;
378
+ install(rawOpts: CreateServiceOptions): Promise<{ name: string; unitPath?: string; serviceName?: string }>;
379
+ uninstall(name: string, options?: { force?: boolean; system?: boolean }): Promise<boolean>;
380
+ start(name: string, options?: { enable?: boolean; system?: boolean }): Promise<boolean>;
381
+ stop(name: string, options?: { system?: boolean }): Promise<boolean>;
382
+ restart(name: string, options?: { system?: boolean }): Promise<boolean>;
383
+ enable(name: string, options?: { system?: boolean }): Promise<boolean>;
384
+ disable(name: string, options?: { system?: boolean }): Promise<boolean>;
385
+ status(name: string, options?: { system?: boolean }): Promise<ServiceStatus>;
386
+ inspect(name: string, options?: { system?: boolean }): Promise<Record<string, unknown>>;
387
+ logs(name: string, options?: LogOptions): Promise<string | EventEmitter | ChildProcess>;
388
+ list(options?: { group?: string }): Promise<Array<Record<string, unknown>>>;
389
+ failures(options?: Record<string, unknown>): Promise<ServiceFailure[]>;
390
+ isInstalled(name: string, options?: Record<string, unknown>): Promise<boolean> | boolean;
391
+ }
414
392
 
415
- export function createService(options: CreateServiceOptions): Promise<AddServiceResult>;
416
- export function addService(options: CreateServiceOptions): Promise<AddServiceResult>;
393
+ export const defaultManager: ServiceManager;
394
+
395
+ // Unified API functions
396
+ export function install(options: CreateServiceOptions): Promise<{ name: string; unitPath?: string }>;
397
+ export function uninstall(name: string, options?: { force?: boolean; system?: boolean }): Promise<boolean>;
398
+ export function start(name: string, options?: { enable?: boolean; system?: boolean }): Promise<boolean>;
399
+ export function stop(name: string, options?: { system?: boolean }): Promise<boolean>;
400
+ export function restart(name: string, options?: { system?: boolean }): Promise<boolean>;
401
+ export function status(name: string, options?: { system?: boolean }): Promise<ServiceStatus>;
402
+ export function list(options?: { group?: string }): Promise<Array<Record<string, unknown>>>;
403
+ export function inspect(name: string, options?: { system?: boolean }): Promise<Record<string, unknown>>;
404
+ export function logs(name: string, options?: LogOptions): Promise<string | EventEmitter | ChildProcess>;
405
+ export function enable(name: string, options?: { system?: boolean }): Promise<boolean>;
406
+ export function disable(name: string, options?: { system?: boolean }): Promise<boolean>;
407
+ export function platform(targetPlatform?: string): PlatformCapabilities;
408
+
409
+ export function getAdapter(platform?: string, options?: Record<string, unknown>): ServiceAdapter;
410
+ export function getPlatformCapabilities(platform?: string): PlatformCapabilities;
411
+ export function normalizeServiceConfig(rawOpts?: Record<string, unknown>): Promise<NormalizedServiceConfig>;
412
+ export function resolveExecutable(binaryName: string, opts?: { cwd?: string; pathEnv?: string }): string | null;
413
+ export function readServiceLogs(filePaths: string | string[], options?: LogOptions): Promise<string | EventEmitter>;
414
+
415
+ // Backward-compatible API
416
+ export function createService(options: CreateServiceOptions): Promise<{ name: string; unitPath: string }>;
417
+ export function addService(options: CreateServiceOptions): Promise<{ name: string; unitPath: string }>;
417
418
  export function startService(name: string, enable?: boolean): Promise<boolean>;
418
419
  export function stopService(name: string): Promise<boolean>;
419
420
  export function restartService(name: string): Promise<boolean>;
420
- export function removeService(name: string, options?: { force?: boolean } | boolean): Promise<boolean>;
421
+ export function removeService(name: string, options?: boolean | { force?: boolean }): Promise<boolean>;
421
422
  export function getServiceStatus(name: string): Promise<ServiceStatus>;
422
423
  export function getServiceStatusRaw(name: string): Promise<string>;
423
- export function listServices(options?: { group?: string }): Promise<ListServiceItem[]>;
424
- export function inspectService(name: string): Promise<InspectInfo>;
425
- export function getServiceFailures(): Promise<FailureItem[]>;
424
+ export function listServices(filterOpts?: { group?: string }): Promise<ListServiceItem[]>;
425
+ export function inspectService(name: string): Promise<Record<string, unknown>>;
426
+ export function getServiceFailures(): Promise<ServiceFailure[]>;
426
427
  export function getServicesByGroup(groupName: string): Promise<string[]>;
427
- export function setServiceLimits(name: string, options?: ServiceLimitsOptions): Promise<InspectInfo>;
428
- export function getServiceMemoryUsage(name: string): Promise<{
429
- name: string;
430
- group: string;
431
- type: string;
432
- status: string;
433
- pid: string;
434
- memoryBytes: number;
435
- memory: string;
436
- memoryPeak: string;
437
- memoryHigh: string;
438
- memoryMax: string;
439
- memorySwapMax: string;
440
- }>;
441
- export function getAllServicesMemoryUsage(options?: { group?: string }): Promise<{
442
- items: Array<{
443
- name: string;
444
- group: string;
445
- type: string;
446
- status: string;
447
- pid: string;
448
- memory: string;
449
- memoryPeak: string;
450
- memoryMax: string;
451
- memoryHigh: string;
452
- memoryBytes: number;
453
- }>;
454
- totalBytes: number;
455
- totalMemory: string;
456
- runningCount: number;
457
- }>;
458
- export function executeJournalctlMaintenance(action: string, options?: Record<string, unknown>): Promise<string>;
459
- export function getServiceLogs(name: string, options?: LogOptions): Promise<string | ChildProcess>;
460
-
461
- // Validation & Formatting Helpers
462
- export function validateMemorySize(val: string | number, paramName?: string): string;
428
+ export function setServiceLimits(name: string, options?: Record<string, unknown>): Promise<Record<string, unknown>>;
429
+ export function getServiceMemoryUsage(name: string): Promise<Record<string, unknown>>;
430
+ export function getAllServicesMemoryUsage(opts?: { group?: string }): Promise<Record<string, unknown>>;
431
+ export function executeJournalctlMaintenance(action: string, opts?: Record<string, unknown>): Promise<string>;
432
+ export function getServiceLogs(name: string, opts?: LogOptions): Promise<string | ChildProcess>;
433
+ export function runJournalctlLogs(name: string, opts?: LogOptions): Promise<string | ChildProcess>;
434
+
435
+ // Runtimes & Helpers
436
+ export function detectRuntime(filepath: string, opts?: Record<string, unknown>): string;
437
+ export function resolveRuntimeConfig(
438
+ opts?: Record<string, unknown>
439
+ ): Promise<{ command: string; args: string[]; runtime: string; version: string }>;
440
+ export function sanitizeServiceName(name: string): string;
441
+ export function formatTable(
442
+ data: Array<Record<string, unknown>>,
443
+ columns: Array<{ key: string; label: string }>
444
+ ): string;
463
445
  export function formatMemoryBytes(bytes: number | string): string;
446
+ export function validateMemorySize(val: string | number, paramName?: string): string;
447
+ export function validateDuration(val: string | number, paramName?: string): string;
464
448
 
465
- // Runtime Helpers
466
- export function detectRuntime(filepath: string): string;
467
- export function resolveRuntimeConfig(options: CreateServiceOptions): Promise<{
468
- command: string;
469
- args: string[];
470
- runtime: string;
471
- version: string;
472
- }>;
449
+ // Config helpers
450
+ export function findProjectConfig(dirPath?: string): string | null;
451
+ export function readProjectConfig(filePathOrDir?: string): Record<string, unknown> | null;
452
+ export function saveProjectConfig(dirPathOrFile?: string, config?: Record<string, unknown>): string;
453
+ export function readAppMetadata(name: string): AppMetadata | null;
454
+ export function getAppMetadataPath(name: string): string;
455
+ export function getAppsDir(): string;
456
+ export function getUnitupDir(): string;
457
+ export function readGlobalConfig(): Record<string, unknown>;
458
+ export function saveGlobalConfig(config: Record<string, unknown>): Record<string, unknown>;
459
+ export function getConfigFilepath(): string;
460
+ export function resolveEffectiveMemoryLimits(opts?: Record<string, unknown>): {
461
+ memoryHigh?: string;
462
+ memoryMax?: string;
463
+ memorySwapMax?: string;
464
+ };
473
465
 
474
- // Diagnostics & Doctor
466
+ // Doctor & Diagnostics
475
467
  export function isSystemdAvailable(): Promise<boolean>;
476
468
  export function isSystemctlAvailable(): Promise<boolean>;
477
469
  export function isLinux(): boolean;
@@ -481,147 +473,46 @@ export function checkUserLinger(): Promise<boolean>;
481
473
  export function checkNodeDiagnostics(customNodePath?: string): Promise<NodeDiagnostics>;
482
474
  export function findNodeExecutable(customPath?: string): Promise<string | null>;
483
475
  export function getDoctorInfo(): Promise<DoctorInfo>;
476
+ export function runDoctor(): Promise<DoctorInfo>;
484
477
 
485
- export interface ProjectConfig {
486
- name?: string;
487
- group?: string;
488
- script?: string;
489
- command?: string;
490
- runtime?: string;
491
- runtimeArgs?: string[];
492
- args?: string[];
493
- env?: Record<string, string>;
494
- envFile?: string;
495
- restart?: string;
496
- resources?: {
497
- memoryHigh?: string;
498
- memoryMax?: string;
499
- memorySwapMax?: string;
500
- };
501
- memoryHigh?: string;
502
- memoryMax?: string;
503
- memorySwapMax?: string;
504
- }
505
-
506
- export function findProjectConfig(dirPath?: string): string | null;
507
- export function readProjectConfig(filePathOrDir?: string): ProjectConfig | null;
508
- export function saveProjectConfig(dirPathOrFile?: string, config?: ProjectConfig): string;
478
+ // Testing runner overrides
479
+ export type CommandRunnerFn = (
480
+ cmd: string,
481
+ args: string[],
482
+ opts?: Record<string, unknown>
483
+ ) => Promise<{ stdout: string; stderr: string; code: number }>;
484
+ export function setCommandRunner(runner: CommandRunnerFn): void;
485
+ export function resetCommandRunner(): void;
486
+ export function runCommand(
487
+ cmd: string,
488
+ args: string[],
489
+ opts?: Record<string, unknown>
490
+ ): Promise<{ stdout: string; stderr: string; code: number }>;
509
491
 
510
- // Path & Unit Helpers
492
+ // Unit / Plist helpers
511
493
  export function getUserUnitDir(): string;
512
494
  export function getUnitPath(name: string): string;
513
495
  export function unitFileExists(name: string): boolean;
514
- export function parseUnitContent(content: string): ParsedUnitContent;
515
- export function sanitizeServiceName(name: string): string;
496
+ export function parseUnitContent(content: string): Record<string, unknown>;
516
497
  export function getUnitFilename(name: string): string;
498
+ export function getTimerFilename(name: string): string;
517
499
  export function getServiceNameFromUnit(unitFilename: string): string;
518
- export function readAppMetadata(name: string): AppMetadata | null;
519
- export function getAppMetadataPath(name: string): string;
520
- export function getAppsDir(): string;
521
- export function getUnitupDir(): string;
522
-
523
- // Testing Mock Helpers
524
- export function setCommandRunner(runner: CommandRunnerFn): void;
525
- export function resetCommandRunner(): void;
526
-
527
- // ---------------------------------------------------------------------------
528
- // Schedule Management API
529
- // ---------------------------------------------------------------------------
530
-
531
- export interface CreateScheduleOptions {
532
- name?: string;
533
- script?: string;
534
- command?: string;
535
- runtime?: string;
536
- args?: string[];
537
- runtimeArgs?: string[];
538
- cwd?: string;
539
- env?: Record<string, string> | string[];
540
- envFile?: string;
541
- group?: string;
542
- memoryHigh?: string;
543
- memoryMax?: string;
544
- memorySwapMax?: string;
545
- defaultMemory?: string | boolean;
546
- every?: string;
547
- calendar?: string;
548
- onBoot?: string;
549
- onActive?: string;
550
- randomDelay?: string;
551
- persistent?: boolean;
552
- start?: boolean;
553
- enable?: boolean;
554
- }
555
-
556
- export interface ScheduleMetadata {
557
- name: string;
558
- group: string;
559
- type: string;
560
- runtime: string;
561
- command: string;
562
- args: string[];
563
- cwd: string;
564
- schedule: {
565
- every: string | null;
566
- calendar: string | null;
567
- onBoot: string | null;
568
- onActive: string | null;
569
- persistent: boolean;
570
- randomDelay: string | null;
571
- };
572
- serviceUnit: string;
573
- timerUnit: string;
574
- }
575
-
576
- export interface ScheduleStatus {
577
- name: string;
578
- group: string;
579
- schedule: string;
580
- nextRun: string;
581
- lastRun: string;
582
- status: string;
583
- activeState: string;
584
- subState: string;
585
- unitFileState: string;
586
- serviceActiveState: string;
587
- metadata?: ScheduleMetadata | null;
588
- serviceUnit: string;
589
- timerUnit: string;
590
- }
591
-
592
- export interface CreateScheduleResult {
593
- name: string;
594
- group: string;
595
- type: string;
596
- runtime: string;
597
- command: string;
598
- args: string[];
599
- cwd: string;
600
- schedule: Record<string, unknown>;
601
- serviceUnit: string;
602
- timerUnit: string;
603
- servicePath: string;
604
- timerPath: string;
605
- }
500
+ export function generateTimerContent(opts: Record<string, unknown>): string;
501
+ export function generateScheduleServiceContent(opts: Record<string, unknown>): string;
502
+ export function getTimerPath(name: string): string;
503
+ export function timerFileExists(name: string): boolean;
606
504
 
607
- export function createSchedule(options: CreateScheduleOptions): Promise<CreateScheduleResult>;
608
- export function listSchedules(group?: string): Promise<ScheduleStatus[]>;
609
- export function getScheduleStatus(name: string): Promise<ScheduleStatus>;
505
+ // Schedules
506
+ export function createSchedule(options: Record<string, unknown>): Promise<Record<string, unknown>>;
507
+ export function listSchedules(group?: string): Promise<Array<Record<string, unknown>>>;
508
+ export function getScheduleStatus(name: string): Promise<Record<string, unknown>>;
610
509
  export function runSchedule(name: string): Promise<boolean>;
611
510
  export function enableSchedule(name: string): Promise<boolean>;
612
511
  export function disableSchedule(name: string): Promise<boolean>;
613
512
  export function removeSchedule(name: string, options?: { force?: boolean }): Promise<boolean>;
614
513
  export function validateCalendar(expression: string): Promise<{ valid: boolean; error?: string; warning?: string }>;
615
- export function validateDuration(val: string | number, paramName?: string): string;
616
- export function getTimerFilename(name: string): string;
617
- export function getTimerPath(name: string): string;
618
- export function timerFileExists(name: string): boolean;
619
- export function readScheduleMetadata(name: string): ScheduleMetadata | null;
514
+ export function readScheduleMetadata(name: string): Record<string, unknown> | null;
620
515
  export function getScheduleMetadataPath(name: string): string;
621
516
  export function getSchedulesDir(): string;
622
- export function readGlobalConfig(): Record<string, unknown>;
623
- export function saveGlobalConfig(config: Record<string, unknown>): Record<string, unknown>;
624
- export function getConfigFilepath(): string;
625
- export function resolveEffectiveMemoryLimits(opts?: Record<string, unknown>): { memoryHigh?: string; memoryMax?: string; memorySwapMax?: string };
626
-
627
517
 
518
+ export default defaultManager;