signalk-container 0.1.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/jobs.js ADDED
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runJob = runJob;
4
+ const crypto_1 = require("crypto");
5
+ const runtime_1 = require("./runtime");
6
+ async function runJob(runtime, config) {
7
+ const id = (0, crypto_1.randomUUID)();
8
+ const jobName = `sk-job-${id.slice(0, 8)}`;
9
+ const createdAt = new Date().toISOString();
10
+ const result = {
11
+ id,
12
+ status: "pending",
13
+ image: config.image,
14
+ command: config.command,
15
+ label: config.label,
16
+ log: [],
17
+ createdAt,
18
+ runtime: runtime.runtime,
19
+ };
20
+ try {
21
+ const inspectResult = await (0, runtime_1.execRuntime)(runtime, [
22
+ "image",
23
+ "inspect",
24
+ config.image,
25
+ ]);
26
+ if (inspectResult.exitCode !== 0) {
27
+ result.status = "pulling";
28
+ config.onProgress?.(`Pulling ${config.image}...`);
29
+ const pullResult = await (0, runtime_1.execRuntimeLong)(runtime, ["pull", config.image], config.onProgress, config.timeout ? config.timeout * 1000 : 300000);
30
+ if (pullResult.exitCode !== 0) {
31
+ result.status = "failed";
32
+ result.error = `Pull failed: ${pullResult.log.slice(-3).join("\n")}`;
33
+ result.log = pullResult.log;
34
+ return result;
35
+ }
36
+ }
37
+ result.status = "running";
38
+ result.startedAt = new Date().toISOString();
39
+ const args = ["run", "--rm", "--name", jobName];
40
+ if (config.inputs) {
41
+ for (const [containerPath, hostPath] of Object.entries(config.inputs)) {
42
+ const suffix = runtime.runtime === "podman" ? ":ro,Z" : ":ro";
43
+ args.push("-v", `${hostPath}:${containerPath}${suffix}`);
44
+ }
45
+ }
46
+ if (config.outputs) {
47
+ for (const [containerPath, hostPath] of Object.entries(config.outputs)) {
48
+ const suffix = runtime.runtime === "podman" ? ":Z" : "";
49
+ args.push("-v", `${hostPath}:${containerPath}${suffix}`);
50
+ }
51
+ }
52
+ if (config.env) {
53
+ for (const [key, value] of Object.entries(config.env)) {
54
+ args.push("-e", `${key}=${value}`);
55
+ }
56
+ }
57
+ args.push(config.image, ...config.command);
58
+ const runResult = await (0, runtime_1.execRuntimeLong)(runtime, args, config.onProgress, config.timeout ? config.timeout * 1000 : 600000);
59
+ result.exitCode = runResult.exitCode;
60
+ result.log = runResult.log;
61
+ result.completedAt = new Date().toISOString();
62
+ result.status = runResult.exitCode === 0 ? "completed" : "failed";
63
+ if (runResult.exitCode !== 0) {
64
+ result.error = `Container exited with code ${runResult.exitCode}`;
65
+ }
66
+ }
67
+ catch (err) {
68
+ result.status = "failed";
69
+ result.error = err instanceof Error ? err.message : String(err);
70
+ result.completedAt = new Date().toISOString();
71
+ await (0, runtime_1.execRuntime)(runtime, ["rm", "-f", jobName]).catch(() => { });
72
+ }
73
+ return result;
74
+ }
75
+ //# sourceMappingURL=jobs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jobs.js","sourceRoot":"","sources":["../src/jobs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import { ContainerRuntimeInfo, RuntimePreference } from "./types";
2
+ export declare function detectRuntime(preference: RuntimePreference): Promise<ContainerRuntimeInfo | null>;
3
+ export declare function runtimeCmd(info: ContainerRuntimeInfo): string;
4
+ export declare function execRuntime(info: ContainerRuntimeInfo, args: string[]): Promise<{
5
+ stdout: string;
6
+ stderr: string;
7
+ exitCode: number;
8
+ }>;
9
+ export declare function execRuntimeLong(info: ContainerRuntimeInfo, args: string[], onProgress?: (msg: string) => void, timeout?: number): Promise<{
10
+ exitCode: number;
11
+ log: string[];
12
+ }>;
13
+ //# sourceMappingURL=runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAe,iBAAiB,EAAE,MAAM,SAAS,CAAC;AA2D/E,wBAAsB,aAAa,CACjC,UAAU,EAAE,iBAAiB,GAC5B,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CActC;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,oBAAoB,GAAG,MAAM,CAE7D;AAED,wBAAsB,WAAW,CAC/B,IAAI,EAAE,oBAAoB,EAC1B,IAAI,EAAE,MAAM,EAAE,GACb,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAE/D;AAED,wBAAsB,eAAe,CACnC,IAAI,EAAE,oBAAoB,EAC1B,IAAI,EAAE,MAAM,EAAE,EACd,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,EAClC,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CA+C9C"}
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.detectRuntime = detectRuntime;
4
+ exports.runtimeCmd = runtimeCmd;
5
+ exports.execRuntime = execRuntime;
6
+ exports.execRuntimeLong = execRuntimeLong;
7
+ const child_process_1 = require("child_process");
8
+ function cleanEnv() {
9
+ const env = { ...process.env };
10
+ for (const key of Object.keys(env)) {
11
+ if (key.startsWith("LISTEN_")) {
12
+ delete env[key];
13
+ }
14
+ }
15
+ return env;
16
+ }
17
+ function exec(cmd, args, env) {
18
+ return new Promise((resolve) => {
19
+ (0, child_process_1.execFile)(cmd, args, { env: env ?? cleanEnv(), timeout: 10000 }, (error, stdout, stderr) => {
20
+ resolve({
21
+ stdout: (stdout ?? "").toString().trim(),
22
+ stderr: (stderr ?? "").toString().trim(),
23
+ exitCode: error
24
+ ? typeof error.code === "number"
25
+ ? error.code
26
+ : 1
27
+ : 0,
28
+ });
29
+ });
30
+ });
31
+ }
32
+ async function tryRuntime(name, env) {
33
+ const result = await exec(name, ["--version"], env);
34
+ if (result.exitCode !== 0)
35
+ return null;
36
+ const version = result.stdout.replace(/^.*version\s*/i, "").split(/[\s,]/)[0] || "unknown";
37
+ let isPodmanDockerShim = false;
38
+ if (name === "docker") {
39
+ isPodmanDockerShim = result.stdout.toLowerCase().includes("podman");
40
+ }
41
+ return {
42
+ runtime: isPodmanDockerShim ? "podman" : name,
43
+ version,
44
+ isPodmanDockerShim,
45
+ };
46
+ }
47
+ async function detectRuntime(preference) {
48
+ const env = cleanEnv();
49
+ if (preference !== "auto") {
50
+ return tryRuntime(preference, env);
51
+ }
52
+ const podman = await tryRuntime("podman", env);
53
+ if (podman)
54
+ return podman;
55
+ const docker = await tryRuntime("docker", env);
56
+ if (docker)
57
+ return docker;
58
+ return null;
59
+ }
60
+ function runtimeCmd(info) {
61
+ return info.isPodmanDockerShim ? "docker" : info.runtime;
62
+ }
63
+ async function execRuntime(info, args) {
64
+ return exec(runtimeCmd(info), args, cleanEnv());
65
+ }
66
+ async function execRuntimeLong(info, args, onProgress, timeout) {
67
+ const cmd = runtimeCmd(info);
68
+ const env = cleanEnv();
69
+ const log = [];
70
+ const maxLogLines = 200;
71
+ return new Promise((resolve, reject) => {
72
+ const proc = (0, child_process_1.execFile)(cmd, args, {
73
+ env,
74
+ timeout: timeout ?? 600000,
75
+ maxBuffer: 10 * 1024 * 1024,
76
+ });
77
+ proc.stdout?.on("data", (data) => {
78
+ const lines = data.toString().split("\n").filter(Boolean);
79
+ for (const line of lines) {
80
+ if (log.length >= maxLogLines)
81
+ log.shift();
82
+ log.push(line);
83
+ try {
84
+ onProgress?.(line);
85
+ }
86
+ catch {
87
+ /* plugin callback errors must not crash us */
88
+ }
89
+ }
90
+ });
91
+ proc.stderr?.on("data", (data) => {
92
+ const lines = data.toString().split("\n").filter(Boolean);
93
+ for (const line of lines) {
94
+ if (log.length >= maxLogLines)
95
+ log.shift();
96
+ log.push(line);
97
+ try {
98
+ onProgress?.(line);
99
+ }
100
+ catch {
101
+ /* plugin callback errors must not crash us */
102
+ }
103
+ }
104
+ });
105
+ proc.on("close", (code) => {
106
+ resolve({ exitCode: code ?? 1, log });
107
+ });
108
+ proc.on("error", (err) => {
109
+ reject(err);
110
+ });
111
+ });
112
+ }
113
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=runtime.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.test.d.ts","sourceRoot":"","sources":["../../src/test/runtime.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const node_test_1 = require("node:test");
7
+ const strict_1 = __importDefault(require("node:assert/strict"));
8
+ const runtime_1 = require("../runtime");
9
+ (0, node_test_1.describe)("detectRuntime", () => {
10
+ (0, node_test_1.it)("returns a runtime info object when podman or docker is available", async () => {
11
+ const result = await (0, runtime_1.detectRuntime)("auto");
12
+ // On CI or dev machines, at least one should be available
13
+ // If neither is installed, result is null — that's also valid
14
+ if (result) {
15
+ strict_1.default.ok(result.runtime === "podman" || result.runtime === "docker", `unexpected runtime: ${result.runtime}`);
16
+ strict_1.default.ok(typeof result.version === "string");
17
+ strict_1.default.ok(typeof result.isPodmanDockerShim === "boolean");
18
+ }
19
+ });
20
+ (0, node_test_1.it)("returns null for a nonexistent runtime", async () => {
21
+ // Force a specific runtime that doesn't exist
22
+ const result = await (0, runtime_1.detectRuntime)("podman");
23
+ // This may or may not be null depending on the system
24
+ // but the function should not throw
25
+ if (result) {
26
+ strict_1.default.equal(result.runtime, "podman");
27
+ }
28
+ });
29
+ });
30
+ //# sourceMappingURL=runtime.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.test.js","sourceRoot":"","sources":["../../src/test/runtime.test.ts"],"names":[],"mappings":";;;;;AAAA,yCAAyC;AACzC,gEAAwC;AACxC,wCAA2C;AAE3C,IAAA,oBAAQ,EAAC,eAAe,EAAE,GAAG,EAAE;IAC7B,IAAA,cAAE,EAAC,kEAAkE,EAAE,KAAK,IAAI,EAAE;QAChF,MAAM,MAAM,GAAG,MAAM,IAAA,uBAAa,EAAC,MAAM,CAAC,CAAC;QAC3C,0DAA0D;QAC1D,8DAA8D;QAC9D,IAAI,MAAM,EAAE,CAAC;YACX,gBAAM,CAAC,EAAE,CACP,MAAM,CAAC,OAAO,KAAK,QAAQ,IAAI,MAAM,CAAC,OAAO,KAAK,QAAQ,EAC1D,uBAAuB,MAAM,CAAC,OAAO,EAAE,CACxC,CAAC;YACF,gBAAM,CAAC,EAAE,CAAC,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC;YAC9C,gBAAM,CAAC,EAAE,CAAC,OAAO,MAAM,CAAC,kBAAkB,KAAK,SAAS,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,IAAA,cAAE,EAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;QACtD,8CAA8C;QAC9C,MAAM,MAAM,GAAG,MAAM,IAAA,uBAAa,EAAC,QAAe,CAAC,CAAC;QACpD,sDAAsD;QACtD,oCAAoC;QACpC,IAAI,MAAM,EAAE,CAAC;YACX,gBAAM,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACzC,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.test.d.ts","sourceRoot":"","sources":["../../src/test/types.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const node_test_1 = require("node:test");
7
+ const strict_1 = __importDefault(require("node:assert/strict"));
8
+ (0, node_test_1.describe)("type contracts", () => {
9
+ (0, node_test_1.it)("ContainerConfig accepts valid config", () => {
10
+ const config = {
11
+ image: "questdb/questdb",
12
+ tag: "9.2.0",
13
+ ports: { "9000/tcp": "127.0.0.1:9000" },
14
+ volumes: {
15
+ "/var/lib/questdb": "/tmp/plugin-config-data/questdb",
16
+ },
17
+ env: { QDB_TELEMETRY_ENABLED: "false" },
18
+ restart: "unless-stopped",
19
+ };
20
+ strict_1.default.equal(config.image, "questdb/questdb");
21
+ strict_1.default.equal(config.tag, "9.2.0");
22
+ strict_1.default.equal(config.restart, "unless-stopped");
23
+ });
24
+ (0, node_test_1.it)("ContainerState enum values are correct", () => {
25
+ const states = [
26
+ "running",
27
+ "stopped",
28
+ "missing",
29
+ "no-runtime",
30
+ ];
31
+ strict_1.default.equal(states.length, 4);
32
+ });
33
+ (0, node_test_1.it)("ContainerRuntimeInfo has required fields", () => {
34
+ const info = {
35
+ runtime: "podman",
36
+ version: "5.2.1",
37
+ isPodmanDockerShim: false,
38
+ };
39
+ strict_1.default.equal(info.runtime, "podman");
40
+ strict_1.default.equal(info.isPodmanDockerShim, false);
41
+ });
42
+ (0, node_test_1.it)("ContainerManagerApi shape is complete", () => {
43
+ const methods = [
44
+ "getRuntime",
45
+ "pullImage",
46
+ "imageExists",
47
+ "ensureRunning",
48
+ "stop",
49
+ "remove",
50
+ "getState",
51
+ "runJob",
52
+ "prune",
53
+ "listContainers",
54
+ ];
55
+ strict_1.default.equal(methods.length, 10);
56
+ });
57
+ });
58
+ //# sourceMappingURL=types.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.test.js","sourceRoot":"","sources":["../../src/test/types.test.ts"],"names":[],"mappings":";;;;;AAAA,yCAAyC;AACzC,gEAAwC;AAQxC,IAAA,oBAAQ,EAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,IAAA,cAAE,EAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,MAAM,GAAoB;YAC9B,KAAK,EAAE,iBAAiB;YACxB,GAAG,EAAE,OAAO;YACZ,KAAK,EAAE,EAAE,UAAU,EAAE,gBAAgB,EAAE;YACvC,OAAO,EAAE;gBACP,kBAAkB,EAAE,iCAAiC;aACtD;YACD,GAAG,EAAE,EAAE,qBAAqB,EAAE,OAAO,EAAE;YACvC,OAAO,EAAE,gBAAgB;SAC1B,CAAC;QACF,gBAAM,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC;QAC9C,gBAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAClC,gBAAM,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,IAAA,cAAE,EAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,MAAM,MAAM,GAAqB;YAC/B,SAAS;YACT,SAAS;YACT,SAAS;YACT,YAAY;SACb,CAAC;QACF,gBAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,IAAA,cAAE,EAAC,0CAA0C,EAAE,GAAG,EAAE;QAClD,MAAM,IAAI,GAAyB;YACjC,OAAO,EAAE,QAAQ;YACjB,OAAO,EAAE,OAAO;YAChB,kBAAkB,EAAE,KAAK;SAC1B,CAAC;QACF,gBAAM,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACrC,gBAAM,CAAC,KAAK,CAAC,IAAI,CAAC,kBAAkB,EAAE,KAAK,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,IAAA,cAAE,EAAC,uCAAuC,EAAE,GAAG,EAAE;QAC/C,MAAM,OAAO,GAAkC;YAC7C,YAAY;YACZ,WAAW;YACX,aAAa;YACb,eAAe;YACf,MAAM;YACN,QAAQ;YACR,UAAU;YACV,QAAQ;YACR,OAAO;YACP,gBAAgB;SACjB,CAAC;QACF,gBAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,78 @@
1
+ export type RuntimeName = "podman" | "docker";
2
+ export type RuntimePreference = "auto" | RuntimeName;
3
+ export interface ContainerRuntimeInfo {
4
+ runtime: RuntimeName;
5
+ version: string;
6
+ isPodmanDockerShim: boolean;
7
+ }
8
+ export type ContainerState = "running" | "stopped" | "missing" | "no-runtime";
9
+ export interface ContainerConfig {
10
+ image: string;
11
+ tag: string;
12
+ ports?: Record<string, string>;
13
+ volumes?: Record<string, string>;
14
+ env?: Record<string, string>;
15
+ restart?: "no" | "unless-stopped" | "always";
16
+ command?: string[];
17
+ networkMode?: string;
18
+ }
19
+ export interface ContainerInfo {
20
+ name: string;
21
+ image: string;
22
+ state: ContainerState;
23
+ created: string;
24
+ ports: string[];
25
+ managedBy: string;
26
+ }
27
+ export interface ContainerJobConfig {
28
+ image: string;
29
+ command: string[];
30
+ inputs?: Record<string, string>;
31
+ outputs?: Record<string, string>;
32
+ env?: Record<string, string>;
33
+ timeout?: number;
34
+ onProgress?: (msg: string) => void;
35
+ label?: string;
36
+ }
37
+ export type ContainerJobStatus = "pending" | "pulling" | "running" | "completed" | "failed";
38
+ export interface ContainerJobResult {
39
+ id: string;
40
+ status: ContainerJobStatus;
41
+ image: string;
42
+ command: string[];
43
+ label?: string;
44
+ exitCode?: number;
45
+ log: string[];
46
+ error?: string;
47
+ createdAt: string;
48
+ startedAt?: string;
49
+ completedAt?: string;
50
+ runtime?: RuntimeName;
51
+ }
52
+ export interface PruneResult {
53
+ imagesRemoved: number;
54
+ spaceReclaimed: string;
55
+ }
56
+ export interface HealthCheckOptions {
57
+ healthCheck?: () => Promise<boolean>;
58
+ onUnhealthy?: (name: string, error: string) => void;
59
+ }
60
+ export interface ContainerManagerApi {
61
+ getRuntime(): ContainerRuntimeInfo | null;
62
+ pullImage(image: string, onProgress?: (msg: string) => void): Promise<void>;
63
+ imageExists(image: string): Promise<boolean>;
64
+ ensureRunning(name: string, config: ContainerConfig, options?: HealthCheckOptions): Promise<void>;
65
+ start(name: string): Promise<void>;
66
+ stop(name: string): Promise<void>;
67
+ remove(name: string): Promise<void>;
68
+ getState(name: string): Promise<ContainerState>;
69
+ runJob(config: ContainerJobConfig): Promise<ContainerJobResult>;
70
+ prune(): Promise<PruneResult>;
71
+ listContainers(): Promise<ContainerInfo[]>;
72
+ }
73
+ export interface PluginConfig {
74
+ runtime: RuntimePreference;
75
+ pruneSchedule: "off" | "weekly" | "monthly";
76
+ maxConcurrentJobs: number;
77
+ }
78
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}