systemd-ts 0.3.0 → 0.3.2
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 +61 -0
- package/dist/index-DeNBLyGA.d.mts +1613 -0
- package/dist/index.d.mts +2 -1612
- package/dist/index.mjs +1 -1609
- package/dist/main-BXq7TQdg.mjs +1612 -0
- package/dist/main-BXq7TQdg.mjs.map +1 -0
- package/dist/test.d.mts +30 -1
- package/dist/test.mjs +95 -16
- package/dist/test.mjs.map +1 -0
- package/package.json +4 -3
- package/src/main/errors.ts +348 -0
- package/src/main/executable.ts +175 -0
- package/src/main/index.ts +76 -0
- package/src/main/internal.ts +406 -0
- package/src/main/notify.ts +67 -0
- package/src/main/systemctl.ts +326 -0
- package/src/main/systemd-service.ts +80 -0
- package/src/main/systemd-timer.ts +80 -0
- package/src/main/systemd.ts +991 -0
- package/src/main/types.ts +1231 -0
- package/src/test/harness.ts +106 -0
- package/src/test/host.ts +676 -0
- package/src/test/index.ts +17 -0
- package/src/test/sandbox.ts +94 -0
- package/src/test/systemd-container.Dockerfile +30 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Systemd,
|
|
3
|
+
type CommandExecutionOptions,
|
|
4
|
+
type CommandExecutor,
|
|
5
|
+
type CommandOutput,
|
|
6
|
+
} from "../main/index.ts";
|
|
7
|
+
|
|
8
|
+
import { runGuestCommand, runIsolatedGuestCommand } from "./host.ts";
|
|
9
|
+
import { useCurrentTestSandbox } from "./sandbox.ts";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Creates a command executor that runs argv-style commands inside the current
|
|
13
|
+
* test host guest shell.
|
|
14
|
+
*/
|
|
15
|
+
export function createGuestCommandExecutor(
|
|
16
|
+
runCommand: (script: string) => Promise<string>,
|
|
17
|
+
): CommandExecutor {
|
|
18
|
+
return async (
|
|
19
|
+
command: string,
|
|
20
|
+
args: readonly string[],
|
|
21
|
+
options: CommandExecutionOptions = {},
|
|
22
|
+
): Promise<CommandOutput> => {
|
|
23
|
+
try {
|
|
24
|
+
const stdout = await runCommand(buildGuestCommand(command, args, options));
|
|
25
|
+
return {
|
|
26
|
+
stderr: ``,
|
|
27
|
+
stdout,
|
|
28
|
+
};
|
|
29
|
+
} catch (cause) {
|
|
30
|
+
throw enrichGuestCommandError(cause);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Executor that reuses the warm guest shell for fast sandbox-backed tests.
|
|
37
|
+
*/
|
|
38
|
+
export const guestCommandExecutor = createGuestCommandExecutor(runGuestCommand);
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Executor that runs each guest command in a fresh isolated guest shell.
|
|
42
|
+
*/
|
|
43
|
+
export const isolatedGuestCommandExecutor = createGuestCommandExecutor(runIsolatedGuestCommand);
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Creates a `Systemd` instance scoped to the active test sandbox and backed by
|
|
47
|
+
* the warm guest-shell executor.
|
|
48
|
+
*/
|
|
49
|
+
export function sandboxSystemd(): Systemd {
|
|
50
|
+
const sandbox = useCurrentTestSandbox();
|
|
51
|
+
return new Systemd({
|
|
52
|
+
executor: guestCommandExecutor,
|
|
53
|
+
linkUnits: true,
|
|
54
|
+
scope: `user`,
|
|
55
|
+
unitDir: sandbox.linkedUnitDir,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Creates a `Systemd` instance scoped to the active test sandbox and backed by
|
|
61
|
+
* a fresh guest shell per command.
|
|
62
|
+
*/
|
|
63
|
+
export function isolatedSandboxSystemd(): Systemd {
|
|
64
|
+
const sandbox = useCurrentTestSandbox();
|
|
65
|
+
return new Systemd({
|
|
66
|
+
executor: isolatedGuestCommandExecutor,
|
|
67
|
+
linkUnits: true,
|
|
68
|
+
scope: `user`,
|
|
69
|
+
unitDir: sandbox.linkedUnitDir,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function buildGuestCommand(
|
|
74
|
+
command: string,
|
|
75
|
+
args: readonly string[],
|
|
76
|
+
options: CommandExecutionOptions,
|
|
77
|
+
): string {
|
|
78
|
+
const envArgs =
|
|
79
|
+
options.env === undefined
|
|
80
|
+
? []
|
|
81
|
+
: Object.entries(options.env).flatMap(([key, value]) =>
|
|
82
|
+
value === undefined ? [`-u`, key] : [`${key}=${value}`],
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
return [`env`, ...envArgs, command, ...args].map((part) => shellQuote(part)).join(` `);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function enrichGuestCommandError(cause: unknown): Error {
|
|
89
|
+
if (cause instanceof Error) {
|
|
90
|
+
return Object.assign(cause, {
|
|
91
|
+
code: 1,
|
|
92
|
+
stderr: ``,
|
|
93
|
+
stdout: cause.message,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return Object.assign(new Error(`Guest command failed`), {
|
|
98
|
+
code: 1,
|
|
99
|
+
stderr: ``,
|
|
100
|
+
stdout: ``,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function shellQuote(value: string): string {
|
|
105
|
+
return `'${value.replaceAll(`'`, `'\\''`)}'`;
|
|
106
|
+
}
|