nomoreide 0.1.84 → 0.1.86

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.
@@ -0,0 +1,33 @@
1
+ export interface DockerStatus {
2
+ available: boolean;
3
+ version?: string;
4
+ error?: string;
5
+ }
6
+ /** Whether the `docker` CLI/daemon is reachable at all, for the page's empty state. */
7
+ export declare function getDockerStatus(): Promise<DockerStatus>;
8
+ export interface DockerContainerSummary {
9
+ id: string;
10
+ name: string;
11
+ image: string;
12
+ /** Raw `docker ps` state: running, exited, paused, created, restarting, dead. */
13
+ state: string;
14
+ /** Human status string, e.g. "Up 2 hours" or "Exited (0) 3 days ago". */
15
+ status: string;
16
+ ports: string;
17
+ createdAt?: string;
18
+ /** From `com.docker.compose.project` / `.service` labels, when present. */
19
+ project?: string;
20
+ service?: string;
21
+ }
22
+ export declare function listDockerContainers(): Promise<DockerContainerSummary[]>;
23
+ export declare function parseDockerPsLines(stdout: string): DockerContainerSummary[];
24
+ export type DockerContainerAction = "start" | "stop" | "restart";
25
+ export declare function performDockerContainerAction(id: string, action: DockerContainerAction): Promise<void>;
26
+ export declare function readDockerContainerLogs(id: string, tail?: number): Promise<string>;
27
+ /**
28
+ * `docker logs` writes container stdout/stderr as two separate streams, so
29
+ * `execFile` hands them back unordered relative to each other. `--timestamps`
30
+ * prefixes every line with an RFC3339 time, so a lexicographic sort of the
31
+ * combined lines reconstructs chronological order.
32
+ */
33
+ export declare function mergeTimestampedLogLines(stdout: string, stderr: string): string;
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Read-mostly Docker introspection: lists whatever containers are running on
3
+ * the host (registered as a nomoreide service or not) and offers basic
4
+ * lifecycle actions. Mirrors `docker-service-runner.ts`'s approach (shell out
5
+ * via `execFile`, no shell interpolation) but is not tied to a specific
6
+ * compose target — this is "what's on my machine", not "run this service".
7
+ */
8
+ import { execFile } from "node:child_process";
9
+ import { promisify } from "node:util";
10
+ const execFileAsync = promisify(execFile);
11
+ /** Whether the `docker` CLI/daemon is reachable at all, for the page's empty state. */
12
+ export async function getDockerStatus() {
13
+ try {
14
+ const { stdout } = await execFileAsync("docker", [
15
+ "version",
16
+ "--format",
17
+ "{{.Server.Version}}",
18
+ ]);
19
+ return { available: true, version: stdout.trim() };
20
+ }
21
+ catch (error) {
22
+ return { available: false, error: errorMessage(error) };
23
+ }
24
+ }
25
+ export async function listDockerContainers() {
26
+ const { stdout } = await execFileAsync("docker", ["ps", "-a", "--format", "{{json .}}"]);
27
+ return parseDockerPsLines(stdout);
28
+ }
29
+ export function parseDockerPsLines(stdout) {
30
+ return stdout
31
+ .split(/\r?\n/)
32
+ .map((line) => line.trim())
33
+ .filter((line) => line.length > 0)
34
+ .map(parseDockerPsLine)
35
+ .filter((container) => container !== null);
36
+ }
37
+ function parseDockerPsLine(line) {
38
+ let raw;
39
+ try {
40
+ raw = JSON.parse(line);
41
+ }
42
+ catch {
43
+ return null;
44
+ }
45
+ const id = typeof raw.ID === "string" ? raw.ID : undefined;
46
+ if (!id)
47
+ return null;
48
+ const labels = parseDockerLabels(typeof raw.Labels === "string" ? raw.Labels : "");
49
+ return {
50
+ id,
51
+ name: typeof raw.Names === "string" && raw.Names ? raw.Names : id,
52
+ image: typeof raw.Image === "string" ? raw.Image : "",
53
+ state: typeof raw.State === "string" && raw.State ? raw.State : "unknown",
54
+ status: typeof raw.Status === "string" ? raw.Status : "",
55
+ ports: typeof raw.Ports === "string" ? raw.Ports : "",
56
+ createdAt: typeof raw.CreatedAt === "string" ? raw.CreatedAt : undefined,
57
+ project: labels["com.docker.compose.project"],
58
+ service: labels["com.docker.compose.service"],
59
+ };
60
+ }
61
+ /** `docker ps`'s Labels field is a flat `key=value,key=value` string. */
62
+ function parseDockerLabels(raw) {
63
+ const labels = {};
64
+ for (const pair of raw.split(",")) {
65
+ const separator = pair.indexOf("=");
66
+ if (separator === -1)
67
+ continue;
68
+ const key = pair.slice(0, separator).trim();
69
+ if (key)
70
+ labels[key] = pair.slice(separator + 1).trim();
71
+ }
72
+ return labels;
73
+ }
74
+ export async function performDockerContainerAction(id, action) {
75
+ validateContainerId(id);
76
+ await execFileAsync("docker", [action, id]);
77
+ }
78
+ export async function readDockerContainerLogs(id, tail = 200) {
79
+ validateContainerId(id);
80
+ const clampedTail = Math.min(Math.max(Math.trunc(tail) || 200, 1), 2000);
81
+ const { stdout, stderr } = await execFileAsync("docker", [
82
+ "logs",
83
+ "--tail",
84
+ String(clampedTail),
85
+ "--timestamps",
86
+ id,
87
+ ]);
88
+ return mergeTimestampedLogLines(stdout, stderr);
89
+ }
90
+ /**
91
+ * `docker logs` writes container stdout/stderr as two separate streams, so
92
+ * `execFile` hands them back unordered relative to each other. `--timestamps`
93
+ * prefixes every line with an RFC3339 time, so a lexicographic sort of the
94
+ * combined lines reconstructs chronological order.
95
+ */
96
+ export function mergeTimestampedLogLines(stdout, stderr) {
97
+ const lines = [...splitNonEmptyLines(stdout), ...splitNonEmptyLines(stderr)];
98
+ lines.sort((a, b) => a.localeCompare(b));
99
+ return lines.join("\n");
100
+ }
101
+ function splitNonEmptyLines(text) {
102
+ return text.split(/\r?\n/).filter((line) => line.length > 0);
103
+ }
104
+ /** Docker container IDs/names are alphanumeric plus `_.-`; reject anything else. */
105
+ function validateContainerId(id) {
106
+ if (!/^[a-zA-Z0-9][a-zA-Z0-9_.-]*$/.test(id)) {
107
+ throw new Error(`Invalid container id: "${id}"`);
108
+ }
109
+ }
110
+ function errorMessage(error) {
111
+ return error instanceof Error ? error.message : String(error);
112
+ }
113
+ //# sourceMappingURL=docker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docker.js","sourceRoot":"","sources":["../../src/core/docker.ts"],"names":[],"mappings":"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"}