@ebowwa/seedinstallation 0.2.4 → 0.4.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/dist/sudo.js CHANGED
@@ -1,235 +1,136 @@
1
- /**
2
- * Composable sudo command runner for local and remote (SSH) contexts.
3
- * Supports arbitrary commands, package installs, file writes, and service management.
4
- */
5
- import { spawn } from "child_process";
6
- // ---------------------------------------------------------------------------
7
- // Core: run a command with sudo
8
- // ---------------------------------------------------------------------------
9
- /** Run an arbitrary command with sudo. */
10
- export async function sudo(cmd, opts) {
11
- const parts = Array.isArray(cmd) ? cmd : cmd.split(/\s+/);
12
- const envPrefix = opts.env
13
- ? Object.entries(opts.env).map(([k, v]) => `${k}=${shellEscape(v)}`)
14
- : [];
15
- const sudoCmd = ["sudo", ...envPrefix, ...parts];
16
- return exec(sudoCmd, opts);
17
- }
18
- const installCmd = {
19
- apt: ["apt-get", "install", "-y"],
20
- dnf: ["dnf", "install", "-y"],
21
- apk: ["apk", "add", "--no-cache"],
22
- };
23
- const updateCmd = {
24
- apt: ["apt-get", "update", "-qq"],
25
- dnf: ["dnf", "check-update"],
26
- apk: ["apk", "update"],
27
- };
28
- /** Install one or more system packages. */
29
- export async function pkgInstall(packages, opts) {
30
- const pm = opts.pm ?? "apt";
31
- const envOverride = {
32
- ...opts.env,
33
- ...(opts.nonInteractive !== false ? { DEBIAN_FRONTEND: "noninteractive" } : {}),
34
- };
35
- // Update package index first
36
- await sudo(updateCmd[pm], { ...opts, env: envOverride, quiet: true });
37
- return sudo([...installCmd[pm], ...packages], {
38
- ...opts,
39
- env: envOverride,
1
+ var __defProp = Object.defineProperty;
2
+ var __export = (target, all) => {
3
+ for (var name in all)
4
+ __defProp(target, name, {
5
+ get: all[name],
6
+ enumerable: true,
7
+ configurable: true,
8
+ set: (newValue) => all[name] = () => newValue
40
9
  });
10
+ };
11
+ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
12
+
13
+ // sudo.ts
14
+ var exports_sudo = {};
15
+ __export(exports_sudo, {
16
+ writeFile: () => writeFile,
17
+ sudo: () => sudo,
18
+ serviceEnable: () => serviceEnable,
19
+ service: () => service,
20
+ pkgInstall: () => pkgInstall,
21
+ exec: () => exec
22
+ });
23
+ async function sudo(cmd, opts) {
24
+ const parts = Array.isArray(cmd) ? cmd : cmd.split(/\s+/);
25
+ const envPrefix = opts.env ? Object.entries(opts.env).map(([k, v]) => `${k}=${shellEscape(v)}`) : [];
26
+ const sudoCmd = ["sudo", ...envPrefix, ...parts];
27
+ return exec(sudoCmd, opts);
41
28
  }
42
- /** Write content to a privileged file path using tee. */
43
- export async function writeFile(path, content, opts) {
44
- const op = opts.append ? "-a" : "";
45
- const teeCmd = `tee ${op} ${shellEscape(path)}`.trim();
46
- // Pipe content through sudo tee
47
- const result = await execPipe(content, ["sudo", teeCmd], opts);
48
- if (result.ok && opts.mode) {
49
- await sudo(["chmod", opts.mode, path], opts);
50
- }
51
- if (result.ok && opts.owner) {
52
- await sudo(["chown", opts.owner, path], opts);
53
- }
54
- return result;
29
+ async function pkgInstall(packages, opts) {
30
+ const pm = opts.pm ?? "apt";
31
+ const envOverride = {
32
+ ...opts.env,
33
+ ...opts.nonInteractive !== false ? { DEBIAN_FRONTEND: "noninteractive" } : {}
34
+ };
35
+ await sudo(updateCmd[pm], { ...opts, env: envOverride, quiet: true });
36
+ return sudo([...installCmd[pm], ...packages], {
37
+ ...opts,
38
+ env: envOverride
39
+ });
55
40
  }
56
- /** Manage a systemd service. */
57
- export async function service(name, action, opts) {
58
- return sudo(["systemctl", action, name], opts);
41
+ async function writeFile(path, content, opts) {
42
+ const op = opts.append ? "-a" : "";
43
+ const teeCmd = `tee ${op} ${shellEscape(path)}`.trim();
44
+ const result = await execPipe(content, ["sudo", teeCmd], opts);
45
+ if (result.ok && opts.mode) {
46
+ await sudo(["chmod", opts.mode, path], opts);
47
+ }
48
+ if (result.ok && opts.owner) {
49
+ await sudo(["chown", opts.owner, path], opts);
50
+ }
51
+ return result;
59
52
  }
60
- /** Enable and start a service in one call. */
61
- export async function serviceEnable(name, opts) {
62
- return sudo(["systemctl", "enable", "--now", name], opts);
53
+ async function service(name, action, opts) {
54
+ return sudo(["systemctl", action, name], opts);
55
+ }
56
+ async function serviceEnable(name, opts) {
57
+ return sudo(["systemctl", "enable", "--now", name], opts);
63
58
  }
64
- // ---------------------------------------------------------------------------
65
- // Internals
66
- // ---------------------------------------------------------------------------
67
59
  function buildSshPrefix(ctx) {
68
- const parts = ["ssh", "-F", "/dev/null", "-o", "StrictHostKeyChecking=no", "-o", "UserKnownHostsFile=/dev/null"];
69
- if (ctx.keyPath)
70
- parts.push("-i", ctx.keyPath);
71
- else if (ctx.key)
72
- parts.push("-i", ctx.key);
73
- if (ctx.port)
74
- parts.push("-p", String(ctx.port));
75
- parts.push(`${ctx.user ?? "root"}@${ctx.host}`);
76
- return parts;
60
+ const parts = ["ssh", "-F", "/dev/null", "-o", "StrictHostKeyChecking=no", "-o", "UserKnownHostsFile=/dev/null"];
61
+ if (ctx.keyPath)
62
+ parts.push("-i", ctx.keyPath);
63
+ else if (ctx.key)
64
+ parts.push("-i", ctx.key);
65
+ if (ctx.port)
66
+ parts.push("-p", String(ctx.port));
67
+ parts.push(`${ctx.user ?? "root"}@${ctx.host}`);
68
+ return parts;
77
69
  }
78
- export async function exec(args, opts) {
79
- const finalArgs = opts.context.type === "ssh"
80
- ? [...buildSshPrefix(opts.context), args.map(shellEscape).join(" ")]
81
- : args;
82
- return new Promise((resolve, reject) => {
83
- const timeout = opts.timeout ?? 30_000;
84
- let timer;
85
- const spawnArgs = finalArgs[0].includes(" ")
86
- ? ["sh", "-c", finalArgs.join(" ")]
87
- : finalArgs;
88
- const proc = spawn(spawnArgs[0], spawnArgs.slice(1), {
89
- stdio: ["ignore", "pipe", "pipe"],
90
- });
91
- let stdout = "";
92
- let stderr = "";
93
- proc.stdout?.on("data", (data) => {
94
- stdout += data.toString();
95
- });
96
- proc.stderr?.on("data", (data) => {
97
- stderr += data.toString();
98
- });
99
- if (timeout) {
100
- timer = setTimeout(() => {
101
- proc.kill();
102
- resolve({
103
- stdout: opts.quiet ? "" : stdout,
104
- stderr: stderr + "\nCommand timed out",
105
- exitCode: 124,
106
- ok: false,
107
- });
108
- }, timeout);
109
- }
110
- proc.on("close", (code) => {
111
- if (timer)
112
- clearTimeout(timer);
113
- resolve({
114
- stdout: opts.quiet ? "" : stdout,
115
- stderr,
116
- exitCode: code ?? 0,
117
- ok: code === 0,
118
- });
119
- });
120
- proc.on("error", (err) => {
121
- if (timer)
122
- clearTimeout(timer);
123
- reject(new Error(`Command failed: ${err.message}`));
124
- });
125
- });
70
+ async function exec(args, opts) {
71
+ const finalArgs = opts.context.type === "ssh" ? [...buildSshPrefix(opts.context), args.map(shellEscape).join(" ")] : args;
72
+ const proc = Bun.spawn(finalArgs, {
73
+ stdout: "pipe",
74
+ stderr: "pipe",
75
+ timeout: opts.timeout ?? 30000
76
+ });
77
+ const exitCode = await proc.exited;
78
+ const stdout = opts.quiet ? "" : await new Response(proc.stdout).text();
79
+ const stderr = await new Response(proc.stderr).text();
80
+ return { stdout, stderr, exitCode, ok: exitCode === 0 };
126
81
  }
127
82
  async function execPipe(input, args, opts) {
128
- if (opts.context.type === "ssh") {
129
- // Over SSH: echo content | ssh user@host 'sudo tee /path'
130
- const sshPrefix = buildSshPrefix(opts.context);
131
- const remoteCmd = args.join(" ");
132
- const fullArgs = [...sshPrefix, remoteCmd];
133
- return new Promise((resolve, reject) => {
134
- const timeout = opts.timeout ?? 30_000;
135
- let timer;
136
- const spawnArgs = fullArgs[0].includes(" ")
137
- ? ["sh", "-c", fullArgs.join(" ")]
138
- : fullArgs;
139
- const proc = spawn(spawnArgs[0], spawnArgs.slice(1), {
140
- stdio: ["pipe", "pipe", "pipe"],
141
- });
142
- // Write input to stdin
143
- if (proc.stdin) {
144
- proc.stdin.write(input);
145
- proc.stdin.end();
146
- }
147
- let stdout = "";
148
- let stderr = "";
149
- proc.stdout?.on("data", (data) => {
150
- stdout += data.toString();
151
- });
152
- proc.stderr?.on("data", (data) => {
153
- stderr += data.toString();
154
- });
155
- if (timeout) {
156
- timer = setTimeout(() => {
157
- proc.kill();
158
- resolve({
159
- stdout: opts.quiet ? "" : stdout,
160
- stderr: stderr + "\nCommand timed out",
161
- exitCode: 124,
162
- ok: false,
163
- });
164
- }, timeout);
165
- }
166
- proc.on("close", (code) => {
167
- if (timer)
168
- clearTimeout(timer);
169
- resolve({
170
- stdout: opts.quiet ? "" : stdout,
171
- stderr,
172
- exitCode: code ?? 0,
173
- ok: code === 0,
174
- });
175
- });
176
- proc.on("error", (err) => {
177
- if (timer)
178
- clearTimeout(timer);
179
- reject(new Error(`Command failed: ${err.message}`));
180
- });
181
- });
182
- }
183
- // Local: pipe through shell
184
- return new Promise((resolve, reject) => {
185
- const timeout = opts.timeout ?? 30_000;
186
- let timer;
187
- const proc = spawn("sh", ["-c", args.join(" ")], {
188
- stdio: ["pipe", "pipe", "pipe"],
189
- });
190
- // Write input to stdin
191
- if (proc.stdin) {
192
- proc.stdin.write(input);
193
- proc.stdin.end();
194
- }
195
- let stdout = "";
196
- let stderr = "";
197
- proc.stdout?.on("data", (data) => {
198
- stdout += data.toString();
199
- });
200
- proc.stderr?.on("data", (data) => {
201
- stderr += data.toString();
202
- });
203
- if (timeout) {
204
- timer = setTimeout(() => {
205
- proc.kill();
206
- resolve({
207
- stdout: opts.quiet ? "" : stdout,
208
- stderr: stderr + "\nCommand timed out",
209
- exitCode: 124,
210
- ok: false,
211
- });
212
- }, timeout);
213
- }
214
- proc.on("close", (code) => {
215
- if (timer)
216
- clearTimeout(timer);
217
- resolve({
218
- stdout: opts.quiet ? "" : stdout,
219
- stderr,
220
- exitCode: code ?? 0,
221
- ok: code === 0,
222
- });
223
- });
224
- proc.on("error", (err) => {
225
- if (timer)
226
- clearTimeout(timer);
227
- reject(new Error(`Command failed: ${err.message}`));
228
- });
83
+ if (opts.context.type === "ssh") {
84
+ const sshPrefix = buildSshPrefix(opts.context);
85
+ const remoteCmd = args.join(" ");
86
+ const fullArgs = [...sshPrefix, remoteCmd];
87
+ const proc2 = Bun.spawn(fullArgs, {
88
+ stdin: new TextEncoder().encode(input),
89
+ stdout: "pipe",
90
+ stderr: "pipe",
91
+ timeout: opts.timeout ?? 30000
229
92
  });
93
+ const exitCode2 = await proc2.exited;
94
+ const stdout2 = opts.quiet ? "" : await new Response(proc2.stdout).text();
95
+ const stderr2 = await new Response(proc2.stderr).text();
96
+ return { stdout: stdout2, stderr: stderr2, exitCode: exitCode2, ok: exitCode2 === 0 };
97
+ }
98
+ const proc = Bun.spawn(["sh", "-c", args.join(" ")], {
99
+ stdin: new TextEncoder().encode(input),
100
+ stdout: "pipe",
101
+ stderr: "pipe",
102
+ timeout: opts.timeout ?? 30000
103
+ });
104
+ const exitCode = await proc.exited;
105
+ const stdout = opts.quiet ? "" : await new Response(proc.stdout).text();
106
+ const stderr = await new Response(proc.stderr).text();
107
+ return { stdout, stderr, exitCode, ok: exitCode === 0 };
230
108
  }
231
109
  function shellEscape(s) {
232
- if (/^[a-zA-Z0-9._\-\/=:@]+$/.test(s))
233
- return s;
234
- return `'${s.replace(/'/g, "'\\''")}'`;
110
+ if (/^[a-zA-Z0-9._\-\/=:@]+$/.test(s))
111
+ return s;
112
+ return `'${s.replace(/'/g, "'\\''")}'`;
235
113
  }
114
+ var installCmd, updateCmd;
115
+ var init_sudo = __esm(() => {
116
+ installCmd = {
117
+ apt: ["apt-get", "install", "-y"],
118
+ dnf: ["dnf", "install", "-y"],
119
+ apk: ["apk", "add", "--no-cache"]
120
+ };
121
+ updateCmd = {
122
+ apt: ["apt-get", "update", "-qq"],
123
+ dnf: ["dnf", "check-update"],
124
+ apk: ["apk", "update"]
125
+ };
126
+ });
127
+ init_sudo();
128
+
129
+ export {
130
+ writeFile,
131
+ sudo,
132
+ serviceEnable,
133
+ service,
134
+ pkgInstall,
135
+ exec
136
+ };
package/dist/systemd.d.ts CHANGED
@@ -1,8 +1,105 @@
1
1
  /**
2
- * Systemd service unit creation and management.
2
+ * Systemd service unit creation and management with security hardening.
3
+ *
4
+ * @example Creating a secure web service
5
+ * ```typescript
6
+ * import { createServiceUnit, SECURITY_PRESETS, enableAndStartService } from "@ebowwa/seedinstallation/systemd";
7
+ *
8
+ * const webService = await createServiceUnit("my-api", {
9
+ * description: "My API Service",
10
+ * workingDirectory: "/opt/my-api",
11
+ * execStart: "/usr/bin/node /opt/my-api/index.js",
12
+ * user: "api-user",
13
+ * ...SECURITY_PRESETS.network,
14
+ * readWritePaths: ["/var/log/my-api", "/var/lib/my-api"],
15
+ * environment: {
16
+ * NODE_ENV: "production",
17
+ * PORT: "8911",
18
+ * },
19
+ * context: sudoContext,
20
+ * });
21
+ *
22
+ * await enableAndStartService("my-api", { context: sudoContext });
23
+ * ```
24
+ *
25
+ * @example Creating a service with custom security
26
+ * ```typescript
27
+ * const customService = await createServiceUnit("custom-agent", {
28
+ * description: "Custom Agent",
29
+ * workingDirectory: "/opt/agent",
30
+ * execStart: "/usr/bin/node /opt/agent/index.js",
31
+ * user: "agent",
32
+ * // Apply strict security but relax some options
33
+ * ...SECURITY_PRESETS.strict,
34
+ * // Allow specific directory for agent data
35
+ * readWritePaths: ["/var/lib/agent", "/var/log/agent"],
36
+ * // Allow network communication
37
+ * restrictAddressFamilies: ["AF_UNIX", "AF_INET", "AF_INET6"],
38
+ * // Allow binding to privileged ports
39
+ * capabilityBoundingSet: ["CAP_NET_BIND_SERVICE"],
40
+ * ambientCapabilities: ["CAP_NET_BIND_SERVICE"],
41
+ * context: sudoContext,
42
+ * });
43
+ * ```
44
+ *
45
+ * @example Creating a development service with minimal security
46
+ * ```typescript
47
+ * const devService = await createServiceUnit("dev-service", {
48
+ * description: "Development Service",
49
+ * workingDirectory: "/home/dev/project",
50
+ * execStart: "npm run dev",
51
+ * user: "dev",
52
+ * ...SECURITY_PRESETS.minimal,
53
+ * // Allow full home directory access for development
54
+ * readWritePaths: ["/home/dev"],
55
+ * context: sudoContext,
56
+ * });
57
+ * ```
58
+ *
3
59
  * Works with both local and SSH contexts via ExecContext from sudo.ts.
4
60
  */
5
- import type { SudoOptions, ExecResult } from "./sudo.js";
61
+ import type { SudoOptions, ExecResult } from "./sudo";
62
+ /**
63
+ * Result of systemd availability check
64
+ */
65
+ export interface SystemdCheckResult {
66
+ /** Whether systemd is available on this system */
67
+ available: boolean;
68
+ /** Reason why systemd is not available (undefined if available) */
69
+ reason?: "not_found" | "not_running" | "no_permission" | "unknown";
70
+ /** Human-readable message */
71
+ message: string;
72
+ }
73
+ /**
74
+ * Check if systemd is available on the system.
75
+ *
76
+ * Detection methods (tried in order):
77
+ * 1. Check if systemctl command exists
78
+ * 2. Check if /run/systemd/system directory exists
79
+ * 3. Try running systemctl --version
80
+ *
81
+ * Results are cached after first call.
82
+ *
83
+ * @param opts - Optional execution context (defaults to local if not provided)
84
+ *
85
+ * @example Skip systemd operations on non-systemd systems
86
+ * ```typescript
87
+ * import { hasSystemd, createServiceUnit } from "@ebowwa/seedinstallation/systemd";
88
+ *
89
+ * if (!(await hasSystemd()).available) {
90
+ * console.log("Running in container/without systemd - skipping service creation");
91
+ * // Run process directly instead
92
+ * } else {
93
+ * await createServiceUnit("my-service", { ... });
94
+ * }
95
+ * ```
96
+ */
97
+ export declare function hasSystemd(opts?: SudoOptions): Promise<SystemdCheckResult>;
98
+ /**
99
+ * Clear the systemd detection cache.
100
+ * Useful for testing or when system state may have changed.
101
+ */
102
+ export declare function clearSystemdCache(): void;
6
103
  export interface ServiceUnitOptions {
7
104
  /** Service description */
8
105
  description: string;
@@ -40,6 +137,52 @@ export interface ServiceUnitOptions {
40
137
  nice?: number;
41
138
  /** Additional unit file sections (e.g. [Install], [Unit] extras) */
42
139
  extras?: string;
140
+ /** Prevent the process and its children from gaining new privileges via execve */
141
+ noNewPrivileges?: boolean;
142
+ /** Mount /tmp and /var/tmp as private, empty directories */
143
+ privateTmp?: boolean;
144
+ /** Make the file system hierarchy read-only (strict = full read-only except /var, /etc, /home) */
145
+ protectSystem?: "strict" | "full" | "yes";
146
+ /** Mount /home and /root read-only or as tmpfs (true = read-only) */
147
+ protectHome?: boolean | "read-only" | "tmpfs";
148
+ /** Paths that should be mounted read-only (default: all paths except readWritePaths) */
149
+ readOnlyPaths?: string[];
150
+ /** Paths that should be writable (whitelist approach for security) */
151
+ readWritePaths?: string[];
152
+ /** Restrict real-time scheduling access */
153
+ restrictRealtime?: boolean;
154
+ /** Deny writing to memory/execute permissions (prevents JIT compilation, W^X) */
155
+ memoryDenyWriteExecute?: boolean;
156
+ /** Make kernel tunables (sysctl, /proc/sys, /sys) read-only */
157
+ protectKernelTunables?: boolean;
158
+ /** Prevent kernel module loading/unloading */
159
+ protectKernelModules?: boolean;
160
+ /** Prevent access to cgroups filesystem */
161
+ protectControlGroups?: boolean;
162
+ /** Restrict address families (e.g., ["AF_UNIX", "AF_INET", "AF_INET6"]) */
163
+ restrictAddressFamilies?: string[];
164
+ /** Create device node whitelist (empty = no device access) */
165
+ deviceAllow?: string[];
166
+ /** Make device nodes read-only */
167
+ devicePolicy?: "auto" | "closed" | "strict";
168
+ /** Restrict system call access (systemd 241+) */
169
+ systemCallFilter?: string[];
170
+ /** Restrict filesystem namespaces */
171
+ restrictNamespaces?: boolean | string[];
172
+ /** Set personality (e.g., "x86-64") */
173
+ personality?: string;
174
+ /** Lock personality with syscalls */
175
+ lockPersonality?: boolean;
176
+ /** Remove CAP_SYS_* capabilities */
177
+ removeCapability?: string[];
178
+ /** Bounding set to drop capabilities */
179
+ capabilityBoundingSet?: string[];
180
+ /** Ambient capabilities to keep */
181
+ ambientCapabilities?: string[];
182
+ /** Private devices namespace (/dev whitelist) */
183
+ privateDevices?: boolean;
184
+ /** Mount /usr read-only */
185
+ protectKernelLogs?: boolean;
43
186
  }
44
187
  export interface ServiceResult extends ExecResult {
45
188
  /** Path to the unit file */
@@ -104,7 +247,7 @@ export declare function serviceExists(name: string, opts: SudoOptions): Promise<
104
247
  /**
105
248
  * Get service logs via journalctl.
106
249
  */
107
- export declare function getServiceLogs(name: string, opts: SudoOptions & {
250
+ export declare function getServiceLogs(name: string, opts?: SudoOptions & {
108
251
  /** Number of lines to show (default: 100) */
109
252
  lines?: number;
110
253
  /** Follow logs */
@@ -112,3 +255,64 @@ export declare function getServiceLogs(name: string, opts: SudoOptions & {
112
255
  /** Show logs since timestamp */
113
256
  since?: string;
114
257
  }): Promise<string>;
258
+ /**
259
+ * Security hardening presets for systemd services.
260
+ * Apply these using spread syntax: { ...SECURITY_PRESETS.strict, ...customOptions }
261
+ */
262
+ export declare const SECURITY_PRESETS: Record<string, Partial<ServiceUnitOptions>>;
263
+ /**
264
+ * Helper to merge security preset with custom options.
265
+ * Custom options override preset values.
266
+ */
267
+ export declare function withSecurityPreset(preset: keyof typeof SECURITY_PRESETS, customOptions: ServiceUnitOptions): ServiceUnitOptions;
268
+ /**
269
+ * Options for safe systemd operations
270
+ */
271
+ export interface SafeSystemdOptions {
272
+ /** Whether to throw error if systemd is not available (default: true) */
273
+ requireSystemd?: boolean;
274
+ /** Callback to run when systemd is not available */
275
+ onNoSystemd?: (check: SystemdCheckResult) => void | Promise<void>;
276
+ /** Execution context (defaults to local if not provided) */
277
+ context?: SudoOptions["context"];
278
+ /** Environment variables */
279
+ env?: Record<string, string>;
280
+ /** Timeout in ms */
281
+ timeout?: number;
282
+ /** Suppress output */
283
+ quiet?: boolean;
284
+ }
285
+ /**
286
+ * Safely execute a systemd operation with automatic detection.
287
+ *
288
+ * If systemd is not available, either:
289
+ * - Throws an error (if requireSystemd = true, default)
290
+ * - Calls onNoSystemd callback (if provided)
291
+ * - Returns undefined gracefully
292
+ *
293
+ * @example
294
+ * ```typescript
295
+ * import { safeSystemd, createServiceUnit } from "@ebowwa/seedinstallation/systemd";
296
+ *
297
+ * // Will throw if no systemd
298
+ * await safeSystemd(async () => {
299
+ * await createServiceUnit("my-service", { ... });
300
+ * });
301
+ *
302
+ * // Will skip gracefully if no systemd
303
+ * await safeSystemd(
304
+ * async () => {
305
+ * await createServiceUnit("my-service", { ... });
306
+ * },
307
+ * {
308
+ * requireSystemd: false,
309
+ * onNoSystemd: async (check) => {
310
+ * console.log(`No systemd: ${check.message}`);
311
+ * // Run process directly instead
312
+ * },
313
+ * }
314
+ * );
315
+ * ```
316
+ */
317
+ export declare function safeSystemd<T>(operation: () => Promise<T>, options?: SafeSystemdOptions): Promise<T | undefined>;
318
+ //# sourceMappingURL=systemd.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"systemd.d.ts","sourceRoot":"","sources":["../systemd.ts"],"names":[],"mappings":"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"}