@moldesk/runtime 0.0.1 → 0.0.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/dist/docker/index.d.ts +41 -4
- package/dist/docker/index.js +140 -14
- package/dist/docker/index.test.d.ts +1 -0
- package/dist/docker/index.test.js +108 -0
- package/dist/filesystem/companion-inputs.d.ts +34 -0
- package/dist/filesystem/companion-inputs.js +123 -0
- package/dist/filesystem/companion-inputs.test.d.ts +1 -0
- package/dist/filesystem/companion-inputs.test.js +256 -0
- package/dist/filesystem/index.d.ts +4 -0
- package/dist/filesystem/index.js +2 -0
- package/dist/filesystem/paths.d.ts +20 -0
- package/dist/filesystem/paths.js +79 -0
- package/dist/filesystem/paths.test.d.ts +1 -0
- package/dist/filesystem/paths.test.js +35 -0
- package/dist/hardware/index.d.ts +21 -0
- package/dist/hardware/index.js +62 -0
- package/dist/hardware/index.test.d.ts +1 -0
- package/dist/hardware/index.test.js +27 -0
- package/dist/index.d.ts +22 -5
- package/dist/index.js +17 -12
- package/dist/install/index.d.ts +83 -0
- package/dist/install/index.js +487 -0
- package/dist/install/index.test.d.ts +1 -0
- package/dist/install/index.test.js +628 -0
- package/dist/nvidia/index.d.ts +29 -0
- package/dist/nvidia/index.js +119 -0
- package/dist/nvidia/index.test.d.ts +1 -0
- package/dist/nvidia/index.test.js +91 -0
- package/dist/process/index.d.ts +34 -0
- package/dist/process/index.js +99 -4
- package/dist/process/index.test.d.ts +1 -0
- package/dist/process/index.test.js +36 -0
- package/dist/providers/python.d.ts +14 -0
- package/dist/providers/python.js +80 -0
- package/dist/providers/python.test.d.ts +1 -0
- package/dist/providers/python.test.js +68 -0
- package/dist/providers.d.ts +49 -0
- package/dist/providers.js +1 -0
- package/dist/providers.test.d.ts +1 -0
- package/dist/providers.test.js +10 -0
- package/dist/python/index.d.ts +14 -3
- package/dist/python/index.js +30 -12
- package/dist/redact.d.ts +6 -0
- package/dist/redact.js +16 -0
- package/dist/redact.test.d.ts +1 -0
- package/dist/redact.test.js +16 -0
- package/dist/system.d.ts +39 -0
- package/dist/system.js +42 -0
- package/dist/system.test.d.ts +1 -0
- package/dist/system.test.js +138 -0
- package/package.json +8 -3
package/dist/python/index.d.ts
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import type { CaptureFn } from "../process/index.js";
|
|
2
|
+
export interface ToolCapability {
|
|
3
|
+
available: boolean;
|
|
3
4
|
version?: string;
|
|
4
5
|
path?: string;
|
|
6
|
+
error?: string;
|
|
5
7
|
}
|
|
6
|
-
|
|
8
|
+
/** Legacy alias kept for existing imports. */
|
|
9
|
+
export type PythonInfo = ToolCapability & {
|
|
10
|
+
found?: boolean;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Detect the host Python interpreter for diagnostics only.
|
|
14
|
+
* Missing tools / timeouts / permission errors become capability
|
|
15
|
+
* results rather than crashes. Never required for managed runtimes.
|
|
16
|
+
*/
|
|
17
|
+
export declare function detectPython(capture?: CaptureFn, timeoutMs?: number): Promise<ToolCapability>;
|
package/dist/python/index.js
CHANGED
|
@@ -1,20 +1,38 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
|
|
1
|
+
const PROBE_TIMEOUT_MS = 10_000;
|
|
2
|
+
function parseVersion(stdout) {
|
|
3
|
+
const cleaned = stdout.trim().replace(/^Python\s+/, "").split(/\s+/)[0];
|
|
4
|
+
return cleaned && cleaned.length > 0 ? cleaned : undefined;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Detect the host Python interpreter for diagnostics only.
|
|
8
|
+
* Missing tools / timeouts / permission errors become capability
|
|
9
|
+
* results rather than crashes. Never required for managed runtimes.
|
|
10
|
+
*/
|
|
11
|
+
export async function detectPython(capture, timeoutMs = PROBE_TIMEOUT_MS) {
|
|
12
|
+
if (!capture) {
|
|
13
|
+
const { defaultCapture } = await import("../process/index.js");
|
|
14
|
+
capture = defaultCapture;
|
|
15
|
+
}
|
|
5
16
|
for (const cmd of ["python3", "python"]) {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const { stdout: pathOut } = await execFileAsync("which", [cmd]);
|
|
17
|
+
const versionResult = await capture(cmd, ["--version"], { timeoutMs });
|
|
18
|
+
if (versionResult.timedOut) {
|
|
9
19
|
return {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
path: pathOut.trim(),
|
|
20
|
+
available: false,
|
|
21
|
+
error: `${cmd} --version timed out after ${timeoutMs}ms`,
|
|
13
22
|
};
|
|
14
23
|
}
|
|
15
|
-
|
|
24
|
+
if (versionResult.code !== 0)
|
|
16
25
|
continue;
|
|
26
|
+
// `python --version` may print to stderr on some interpreters.
|
|
27
|
+
const combined = `${versionResult.stdout}\n${versionResult.stderr}`.trim();
|
|
28
|
+
const version = parseVersion(combined);
|
|
29
|
+
let detectedPath;
|
|
30
|
+
const pathResult = await capture("which", [cmd], { timeoutMs });
|
|
31
|
+
if (pathResult.code === 0) {
|
|
32
|
+
const firstLine = pathResult.stdout.split("\n").map((l) => l.trim()).find(Boolean);
|
|
33
|
+
detectedPath = firstLine;
|
|
17
34
|
}
|
|
35
|
+
return { available: true, version, path: detectedPath };
|
|
18
36
|
}
|
|
19
|
-
return {
|
|
37
|
+
return { available: false, error: "no python3 or python interpreter on PATH" };
|
|
20
38
|
}
|
package/dist/redact.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Redacts values whose keys look like secrets, plus any caller-declared
|
|
3
|
+
* sensitive keys. Used before persisting adapter-declared command env into
|
|
4
|
+
* a durable record (e.g. run.json) — never the full inherited environment.
|
|
5
|
+
*/
|
|
6
|
+
export declare function redactEnv(env: Record<string, string> | undefined, extraSensitiveKeys?: readonly string[]): Record<string, string>;
|
package/dist/redact.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const SECRET_KEY_PATTERN = /token|secret|password|key|credential|auth/i;
|
|
2
|
+
const REDACTED = "[redacted]";
|
|
3
|
+
/**
|
|
4
|
+
* Redacts values whose keys look like secrets, plus any caller-declared
|
|
5
|
+
* sensitive keys. Used before persisting adapter-declared command env into
|
|
6
|
+
* a durable record (e.g. run.json) — never the full inherited environment.
|
|
7
|
+
*/
|
|
8
|
+
export function redactEnv(env, extraSensitiveKeys = []) {
|
|
9
|
+
if (!env)
|
|
10
|
+
return {};
|
|
11
|
+
const sensitive = new Set(extraSensitiveKeys.map((key) => key.toLowerCase()));
|
|
12
|
+
return Object.fromEntries(Object.entries(env).map(([key, value]) => [
|
|
13
|
+
key,
|
|
14
|
+
SECRET_KEY_PATTERN.test(key) || sensitive.has(key.toLowerCase()) ? REDACTED : value,
|
|
15
|
+
]));
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { redactEnv } from "./redact.js";
|
|
3
|
+
describe("redactEnv", () => {
|
|
4
|
+
it("redacts values whose keys look like secrets", () => {
|
|
5
|
+
expect(redactEnv({ API_TOKEN: "abc123", DB_PASSWORD: "hunter2", HOME: "/home/user", PATH: "/usr/bin" })).toEqual({ API_TOKEN: "[redacted]", DB_PASSWORD: "[redacted]", HOME: "/home/user", PATH: "/usr/bin" });
|
|
6
|
+
});
|
|
7
|
+
it("redacts caller-declared sensitive keys regardless of name", () => {
|
|
8
|
+
expect(redactEnv({ MODEL_LICENSE_ID: "xyz" }, ["MODEL_LICENSE_ID"])).toEqual({ MODEL_LICENSE_ID: "[redacted]" });
|
|
9
|
+
});
|
|
10
|
+
it("returns an empty object for undefined input", () => {
|
|
11
|
+
expect(redactEnv(undefined)).toEqual({});
|
|
12
|
+
});
|
|
13
|
+
it("leaves non-matching keys untouched", () => {
|
|
14
|
+
expect(redactEnv({ OUTPUT_DIR: "/tmp/out" })).toEqual({ OUTPUT_DIR: "/tmp/out" });
|
|
15
|
+
});
|
|
16
|
+
});
|
package/dist/system.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type DiskInfo } from "./hardware/index.js";
|
|
2
|
+
import type { StatFsFn } from "./hardware/index.js";
|
|
3
|
+
import { type ToolCapability } from "./python/index.js";
|
|
4
|
+
import { type DockerCapability } from "./docker/index.js";
|
|
5
|
+
import { type NvidiaCapability, type NvidiaGpu } from "./nvidia/index.js";
|
|
6
|
+
import type { CaptureFn } from "./process/index.js";
|
|
7
|
+
export type { ToolCapability, DockerCapability, NvidiaCapability, NvidiaGpu, DiskInfo };
|
|
8
|
+
export interface SystemReport {
|
|
9
|
+
capturedAt: string;
|
|
10
|
+
platform: "darwin" | "linux" | "win32" | "unknown";
|
|
11
|
+
arch: string;
|
|
12
|
+
cpu: {
|
|
13
|
+
model: string;
|
|
14
|
+
logicalCores: number;
|
|
15
|
+
};
|
|
16
|
+
memory: {
|
|
17
|
+
totalBytes: number;
|
|
18
|
+
};
|
|
19
|
+
disk: DiskInfo;
|
|
20
|
+
appleSilicon: boolean;
|
|
21
|
+
/** Host interpreter: diagnostic context only, never required for managed runtimes. */
|
|
22
|
+
hostPython: ToolCapability;
|
|
23
|
+
docker: DockerCapability;
|
|
24
|
+
nvidia: NvidiaCapability;
|
|
25
|
+
}
|
|
26
|
+
export interface SystemReportDeps {
|
|
27
|
+
capture?: CaptureFn;
|
|
28
|
+
statfs?: StatFsFn;
|
|
29
|
+
platform?: NodeJS.Platform | string;
|
|
30
|
+
arch?: string;
|
|
31
|
+
/** Tier-2 verified Docker GPU-access result to inject (install.ts only). */
|
|
32
|
+
dockerGpuAccess?: DockerCapability["gpuAccess"];
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Build one normalized machine report. Cached only within a single CLI
|
|
36
|
+
* invocation by the caller; hardware may change between runs so this
|
|
37
|
+
* function never persists anything.
|
|
38
|
+
*/
|
|
39
|
+
export declare function collectSystemReport(deps?: SystemReportDeps, env?: NodeJS.ProcessEnv): Promise<SystemReport>;
|
package/dist/system.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import os from "node:os";
|
|
2
|
+
import { getDiskInfo } from "./hardware/index.js";
|
|
3
|
+
import { detectPython } from "./python/index.js";
|
|
4
|
+
import { detectDocker } from "./docker/index.js";
|
|
5
|
+
import { detectNvidia } from "./nvidia/index.js";
|
|
6
|
+
function normalizePlatform(raw) {
|
|
7
|
+
if (raw === "darwin" || raw === "linux" || raw === "win32")
|
|
8
|
+
return raw;
|
|
9
|
+
return "unknown";
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Build one normalized machine report. Cached only within a single CLI
|
|
13
|
+
* invocation by the caller; hardware may change between runs so this
|
|
14
|
+
* function never persists anything.
|
|
15
|
+
*/
|
|
16
|
+
export async function collectSystemReport(deps = {}, env = process.env) {
|
|
17
|
+
const rawPlatform = deps.platform ?? os.platform();
|
|
18
|
+
const platform = normalizePlatform(rawPlatform);
|
|
19
|
+
const arch = deps.arch ?? os.arch();
|
|
20
|
+
const cpus = os.cpus();
|
|
21
|
+
const [disk, hostPython, docker, nvidia] = await Promise.all([
|
|
22
|
+
getDiskInfo(env, deps.statfs),
|
|
23
|
+
detectPython(deps.capture),
|
|
24
|
+
detectDocker(deps.capture, { gpuAccess: deps.dockerGpuAccess }),
|
|
25
|
+
detectNvidia(deps.capture),
|
|
26
|
+
]);
|
|
27
|
+
return {
|
|
28
|
+
capturedAt: new Date().toISOString(),
|
|
29
|
+
platform,
|
|
30
|
+
arch,
|
|
31
|
+
cpu: {
|
|
32
|
+
model: cpus[0]?.model ?? "unknown",
|
|
33
|
+
logicalCores: cpus.length,
|
|
34
|
+
},
|
|
35
|
+
memory: { totalBytes: os.totalmem() },
|
|
36
|
+
disk,
|
|
37
|
+
appleSilicon: platform === "darwin" && arch === "arm64",
|
|
38
|
+
hostPython,
|
|
39
|
+
docker,
|
|
40
|
+
nvidia,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { detectPython } from "./python/index.js";
|
|
3
|
+
import { detectDocker } from "./docker/index.js";
|
|
4
|
+
import { detectNvidia } from "./nvidia/index.js";
|
|
5
|
+
import { getDiskInfo } from "./hardware/index.js";
|
|
6
|
+
import { collectSystemReport } from "./system.js";
|
|
7
|
+
function stubCapture(handler) {
|
|
8
|
+
return async (command, args) => {
|
|
9
|
+
const r = handler(command, args);
|
|
10
|
+
return { code: r.code, stdout: r.stdout ?? "", stderr: r.stderr ?? "", timedOut: r.timedOut };
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
describe("python probe", () => {
|
|
14
|
+
it("reports version + path when python3 exists", async () => {
|
|
15
|
+
const capture = stubCapture((cmd, args) => {
|
|
16
|
+
if (cmd === "python3" && args[0] === "--version")
|
|
17
|
+
return { code: 0, stdout: "Python 3.11.9\n" };
|
|
18
|
+
if (cmd === "which")
|
|
19
|
+
return { code: 0, stdout: "/opt/homebrew/bin/python3\n" };
|
|
20
|
+
return { code: 1 };
|
|
21
|
+
});
|
|
22
|
+
const result = await detectPython(capture);
|
|
23
|
+
expect(result).toMatchObject({ available: true, version: "3.11.9", path: "/opt/homebrew/bin/python3" });
|
|
24
|
+
});
|
|
25
|
+
it("degrades to unavailable when no interpreter on PATH", async () => {
|
|
26
|
+
const capture = stubCapture(() => ({ code: 127, stderr: "not found" }));
|
|
27
|
+
const result = await detectPython(capture);
|
|
28
|
+
expect(result.available).toBe(false);
|
|
29
|
+
expect(result.error).toBeDefined();
|
|
30
|
+
});
|
|
31
|
+
it("reports timeout instead of throwing", async () => {
|
|
32
|
+
const capture = stubCapture(() => ({ code: 0, timedOut: true }));
|
|
33
|
+
const result = await detectPython(capture);
|
|
34
|
+
expect(result.available).toBe(false);
|
|
35
|
+
expect(result.error).toMatch(/timed out/);
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
describe("docker probe", () => {
|
|
39
|
+
it("separates installed/running from gpu access", async () => {
|
|
40
|
+
const capture = stubCapture((cmd, args) => {
|
|
41
|
+
if (cmd === "docker" && args[0] === "--version")
|
|
42
|
+
return { code: 0, stdout: "Docker version 24.0.7, build abc\n" };
|
|
43
|
+
if (cmd === "docker" && args[0] === "info")
|
|
44
|
+
return { code: 0, stdout: "Server Version: 24\n" };
|
|
45
|
+
return { code: 1 };
|
|
46
|
+
});
|
|
47
|
+
const result = await detectDocker(capture);
|
|
48
|
+
expect(result).toMatchObject({ available: true, running: true, gpuAccess: "unknown" });
|
|
49
|
+
});
|
|
50
|
+
it("reports stopped daemon without crashing", async () => {
|
|
51
|
+
const capture = stubCapture((cmd, args) => {
|
|
52
|
+
if (args[0] === "--version")
|
|
53
|
+
return { code: 0, stdout: "Docker version 24.0.7\n" };
|
|
54
|
+
return { code: 1, stderr: "Cannot connect to the Docker daemon" };
|
|
55
|
+
});
|
|
56
|
+
const result = await detectDocker(capture);
|
|
57
|
+
expect(result).toMatchObject({ available: true, running: false });
|
|
58
|
+
expect(result.error).toMatch(/daemon not running/);
|
|
59
|
+
});
|
|
60
|
+
it("reports missing docker", async () => {
|
|
61
|
+
const capture = stubCapture(() => ({ code: 127, stderr: "command not found" }));
|
|
62
|
+
const result = await detectDocker(capture);
|
|
63
|
+
expect(result).toMatchObject({ available: false, running: false, gpuAccess: "unknown" });
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
describe("nvidia probe", () => {
|
|
67
|
+
it("parses CSV query output only", async () => {
|
|
68
|
+
const capture = stubCapture((cmd, args) => {
|
|
69
|
+
if (cmd === "nvidia-smi" && args.join(" ").includes("memory.total"))
|
|
70
|
+
return { code: 0, stdout: "0, NVIDIA A100, 81920\n1, NVIDIA A100, 81920\n" };
|
|
71
|
+
if (cmd === "nvidia-smi" && args.includes("-x"))
|
|
72
|
+
return { code: 0, stdout: "<nvidia_smi_log><cuda_version>12.4</cuda_version></nvidia_smi_log>\n" };
|
|
73
|
+
if (cmd === "nvidia-smi")
|
|
74
|
+
return { code: 0, stdout: "550.54.15\n" };
|
|
75
|
+
if (cmd === "nvcc")
|
|
76
|
+
return { code: 0, stdout: "Cuda compilation tools, release 12.4\n" };
|
|
77
|
+
return { code: 1 };
|
|
78
|
+
});
|
|
79
|
+
const result = await detectNvidia(capture);
|
|
80
|
+
expect(result.available).toBe(true);
|
|
81
|
+
expect(result.gpus).toHaveLength(2);
|
|
82
|
+
expect(result.gpus[0]?.totalVramBytes).toBe(81920 * 1024 * 1024);
|
|
83
|
+
expect(result.driverCudaVersion).toBe("12.4");
|
|
84
|
+
expect(result.cudaToolkitVersion).toBe("12.4");
|
|
85
|
+
});
|
|
86
|
+
it("treats missing nvidia-smi as unavailable", async () => {
|
|
87
|
+
const capture = stubCapture(() => ({ code: 127, stderr: "not found" }));
|
|
88
|
+
const result = await detectNvidia(capture);
|
|
89
|
+
expect(result).toMatchObject({ available: false, gpus: [] });
|
|
90
|
+
});
|
|
91
|
+
it("treats unknown/decorative output as unavailable, not a crash", async () => {
|
|
92
|
+
const capture = stubCapture(() => ({
|
|
93
|
+
code: 0,
|
|
94
|
+
stdout: "+-----+-------+\n| GPU | MEM |\n+-----+-------+\n",
|
|
95
|
+
}));
|
|
96
|
+
const result = await detectNvidia(capture);
|
|
97
|
+
expect(result.available).toBe(false);
|
|
98
|
+
expect(result.error).toMatch(/unrecognized nvidia-smi output/);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
describe("disk probe", () => {
|
|
102
|
+
it("queries MOLDESK_HOME nearest parent", async () => {
|
|
103
|
+
const disk = await getDiskInfo({ MOLDESK_HOME: "/tmp/moldesk-test-home-no-such-dir-xyz/sub" }, async () => ({
|
|
104
|
+
availableBytes: 42 * 1024 ** 3,
|
|
105
|
+
}));
|
|
106
|
+
expect(disk.availableBytes).toBe(42 * 1024 ** 3);
|
|
107
|
+
expect(disk.path.length).toBeGreaterThan(0);
|
|
108
|
+
});
|
|
109
|
+
it("falls back to 0 bytes on probe failure, flagged as probeFailed (not a real zero)", async () => {
|
|
110
|
+
const disk = await getDiskInfo({ MOLDESK_HOME: "/tmp" }, async () => null);
|
|
111
|
+
expect(disk.availableBytes).toBe(0);
|
|
112
|
+
expect(disk.probeFailed).toBe(true);
|
|
113
|
+
expect(disk.probeError).toBeTruthy();
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
describe("collectSystemReport", () => {
|
|
117
|
+
it("assembles one report with injected results (no real GPU/Docker)", async () => {
|
|
118
|
+
const capture = stubCapture((cmd, args) => {
|
|
119
|
+
if (cmd === "python3")
|
|
120
|
+
return { code: 0, stdout: "Python 3.11.0\n" };
|
|
121
|
+
if (cmd === "which")
|
|
122
|
+
return { code: 0, stdout: "/usr/bin/python3\n" };
|
|
123
|
+
if (cmd === "docker")
|
|
124
|
+
return { code: 127, stderr: "no docker" };
|
|
125
|
+
if (cmd === "nvidia-smi")
|
|
126
|
+
return { code: 127, stderr: "no gpu" };
|
|
127
|
+
void args;
|
|
128
|
+
return { code: 1 };
|
|
129
|
+
});
|
|
130
|
+
const report = await collectSystemReport({ capture, statfs: async () => ({ availableBytes: 100 * 1024 ** 3 }) }, { MOLDESK_HOME: "/tmp/moldesk-report-test" });
|
|
131
|
+
expect(typeof report.capturedAt).toBe("string");
|
|
132
|
+
expect(report.hostPython.available).toBe(true);
|
|
133
|
+
expect(report.docker.available).toBe(false);
|
|
134
|
+
expect(report.nvidia.available).toBe(false);
|
|
135
|
+
expect(report.disk.availableBytes).toBe(100 * 1024 ** 3);
|
|
136
|
+
expect(["darwin", "linux", "win32", "unknown"]).toContain(report.platform);
|
|
137
|
+
});
|
|
138
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@moldesk/runtime",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"description": "Hardware detection and Python/Docker/process execution for MoleculeDesk",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -18,12 +18,17 @@
|
|
|
18
18
|
"files": [
|
|
19
19
|
"dist"
|
|
20
20
|
],
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"@moldesk/registry": "0.0.2"
|
|
23
|
+
},
|
|
21
24
|
"devDependencies": {
|
|
22
25
|
"typescript": "^5.6.3",
|
|
23
|
-
"@types/node": "^20.16.11"
|
|
26
|
+
"@types/node": "^20.16.11",
|
|
27
|
+
"vitest": "^3.0.0"
|
|
24
28
|
},
|
|
25
29
|
"scripts": {
|
|
26
30
|
"build": "tsc -p tsconfig.json",
|
|
27
|
-
"typecheck": "tsc --noEmit"
|
|
31
|
+
"typecheck": "tsc --noEmit",
|
|
32
|
+
"test": "vitest run"
|
|
28
33
|
}
|
|
29
34
|
}
|