@ricsam/r5d-macos-vm 0.0.0 → 0.0.55
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 +53 -28
- package/bootstrap/Install r5d.command +81 -0
- package/bootstrap/README.txt +7 -0
- package/bootstrap/dev.r5d.worker-terminal.plist.template +23 -0
- package/bootstrap/install-worker-launch-agent.sh +47 -0
- package/bootstrap/start-worker.command.template +71 -0
- package/dist/cjs/artifact-manifest.cjs +224 -0
- package/dist/cjs/cli.cjs +179 -0
- package/dist/cjs/host.cjs +62 -0
- package/dist/cjs/main.cjs +10 -0
- package/dist/cjs/native-runtime.cjs +464 -0
- package/dist/cjs/package.json +5 -0
- package/dist/mjs/artifact-manifest.mjs +176 -0
- package/dist/mjs/cli.mjs +144 -0
- package/dist/mjs/host.mjs +37 -0
- package/dist/mjs/main.mjs +9 -0
- package/dist/mjs/native-runtime.mjs +421 -0
- package/dist/mjs/package.json +5 -0
- package/dist/types/artifact-manifest.d.ts +33 -0
- package/dist/types/cli.d.ts +23 -0
- package/dist/types/host.d.ts +7 -0
- package/dist/types/main.d.ts +2 -0
- package/dist/types/native-runtime.d.ts +28 -0
- package/native-artifact.json +14 -0
- package/package.json +39 -7
package/dist/cjs/cli.cjs
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var cli_exports = {};
|
|
30
|
+
__export(cli_exports, {
|
|
31
|
+
getHelpText: () => getHelpText,
|
|
32
|
+
invokeNativeProcess: () => invokeNativeProcess,
|
|
33
|
+
normalizeNativeArguments: () => normalizeNativeArguments,
|
|
34
|
+
runCli: () => runCli,
|
|
35
|
+
validateVmName: () => validateVmName
|
|
36
|
+
});
|
|
37
|
+
module.exports = __toCommonJS(cli_exports);
|
|
38
|
+
var import_node_fs = __toESM(require("node:fs"), 1);
|
|
39
|
+
var import_node_path = __toESM(require("node:path"), 1);
|
|
40
|
+
var import_node_url = require("node:url");
|
|
41
|
+
var import_node_child_process = require("node:child_process");
|
|
42
|
+
var import_artifact_manifest = require("./artifact-manifest.cjs");
|
|
43
|
+
var import_host = require("./host.cjs");
|
|
44
|
+
var import_native_runtime = require("./native-runtime.cjs");
|
|
45
|
+
const import_meta = {};
|
|
46
|
+
function defaultModulePath() {
|
|
47
|
+
if (typeof __filename === "string") return __filename;
|
|
48
|
+
return (0, import_node_url.fileURLToPath)(import_meta.url);
|
|
49
|
+
}
|
|
50
|
+
const HELP = `Usage: r5d-macos-vm <command> [options]
|
|
51
|
+
|
|
52
|
+
Commands:
|
|
53
|
+
doctor [--json] Check host and native virtualization support
|
|
54
|
+
create [name] [...] Download macOS from Apple and create a VM
|
|
55
|
+
list [--json] List locally managed VMs
|
|
56
|
+
status [name] [--json] Show VM state
|
|
57
|
+
start [name] [--json] Start a VM in its window
|
|
58
|
+
run [name] [--json] Alias for start
|
|
59
|
+
stop [name] [--force] Stop a VM
|
|
60
|
+
delete <name> --yes [--purge] Move a VM to Trash, or permanently purge it
|
|
61
|
+
cache prune Remove restore images and old native runners
|
|
62
|
+
--version Show the package version
|
|
63
|
+
|
|
64
|
+
`;
|
|
65
|
+
function findBootstrapDirectory(modulePath) {
|
|
66
|
+
const packageRoot = (0, import_artifact_manifest.findPackageRoot)(modulePath);
|
|
67
|
+
const candidate = packageRoot ? import_node_path.default.join(packageRoot, "bootstrap") : null;
|
|
68
|
+
if (candidate && import_node_fs.default.existsSync(candidate) && import_node_fs.default.statSync(candidate).isDirectory()) return candidate;
|
|
69
|
+
throw new Error("The guest bootstrap assets are missing. Reinstall @ricsam/r5d-macos-vm.");
|
|
70
|
+
}
|
|
71
|
+
const NAMED_COMMANDS = /* @__PURE__ */ new Set(["create", "run", "start", "status", "stop", "delete", "delete-check"]);
|
|
72
|
+
function validateVmName(name) {
|
|
73
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9_.-]{0,62}$/.test(name)) {
|
|
74
|
+
throw new Error("VM names must start with a letter or number and contain at most 63 letters, numbers, dots, underscores, or hyphens.");
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function findCommandIndex(args) {
|
|
78
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
79
|
+
if (args[index] === "--json") continue;
|
|
80
|
+
if (args[index] === "--state-root") {
|
|
81
|
+
index += 1;
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
return index;
|
|
85
|
+
}
|
|
86
|
+
return -1;
|
|
87
|
+
}
|
|
88
|
+
function normalizeNativeArguments(args, bootstrapDir) {
|
|
89
|
+
const normalized = [...args];
|
|
90
|
+
const commandIndex = findCommandIndex(normalized);
|
|
91
|
+
if (commandIndex < 0) return normalized;
|
|
92
|
+
const command = normalized[commandIndex];
|
|
93
|
+
if (NAMED_COMMANDS.has(command)) {
|
|
94
|
+
const nameOptionIndex = normalized.indexOf("--name");
|
|
95
|
+
if (nameOptionIndex >= 0) {
|
|
96
|
+
const name = normalized[nameOptionIndex + 1];
|
|
97
|
+
if (!name || name.startsWith("-")) throw new Error("Missing value for --name.");
|
|
98
|
+
validateVmName(name);
|
|
99
|
+
} else {
|
|
100
|
+
let positionalIndex = commandIndex + 1;
|
|
101
|
+
while (normalized[positionalIndex] === "--json" || normalized[positionalIndex] === "--state-root") {
|
|
102
|
+
if (normalized[positionalIndex] === "--state-root") positionalIndex += 2;
|
|
103
|
+
else positionalIndex += 1;
|
|
104
|
+
}
|
|
105
|
+
const positionalName = normalized[positionalIndex];
|
|
106
|
+
if (positionalName && !positionalName.startsWith("-")) {
|
|
107
|
+
validateVmName(positionalName);
|
|
108
|
+
normalized.splice(positionalIndex, 1, "--name", positionalName);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
if (command === "create" && !normalized.includes("--bootstrap-dir")) {
|
|
113
|
+
normalized.push("--bootstrap-dir", bootstrapDir);
|
|
114
|
+
}
|
|
115
|
+
return normalized;
|
|
116
|
+
}
|
|
117
|
+
const invokeNativeProcess = (executable, args) => new Promise((resolve, reject) => {
|
|
118
|
+
const child = (0, import_node_child_process.spawn)(executable, [...args], { stdio: "inherit", shell: false });
|
|
119
|
+
const forwardSignal = (signal) => child.kill(signal);
|
|
120
|
+
const onSigint = () => forwardSignal("SIGINT");
|
|
121
|
+
const onSigterm = () => forwardSignal("SIGTERM");
|
|
122
|
+
process.once("SIGINT", onSigint);
|
|
123
|
+
process.once("SIGTERM", onSigterm);
|
|
124
|
+
child.once("error", reject);
|
|
125
|
+
child.once("close", (code, signal) => {
|
|
126
|
+
process.off("SIGINT", onSigint);
|
|
127
|
+
process.off("SIGTERM", onSigterm);
|
|
128
|
+
if (signal) resolve(128 + (signal === "SIGINT" ? 2 : 15));
|
|
129
|
+
else resolve(code ?? 1);
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
function resolveManifestPath(modulePath, explicitPath) {
|
|
133
|
+
if (explicitPath) return import_node_path.default.resolve(explicitPath);
|
|
134
|
+
const packageRoot = (0, import_artifact_manifest.findPackageRoot)(modulePath);
|
|
135
|
+
const candidate = packageRoot ? import_node_path.default.join(packageRoot, "native-artifact.json") : null;
|
|
136
|
+
if (!candidate || !import_node_fs.default.existsSync(candidate)) {
|
|
137
|
+
throw new Error("The native artifact manifest is missing. Reinstall @ricsam/r5d-macos-vm.");
|
|
138
|
+
}
|
|
139
|
+
return candidate;
|
|
140
|
+
}
|
|
141
|
+
async function runCli(args, dependencies = {}) {
|
|
142
|
+
const modulePath = dependencies.modulePath ?? defaultModulePath();
|
|
143
|
+
const stdout = dependencies.stdout ?? process.stdout;
|
|
144
|
+
const packageVersion = dependencies.packageVersion ?? (0, import_artifact_manifest.findPackageVersion)(modulePath);
|
|
145
|
+
if (args.length === 0 || args[0] === "--help" || args[0] === "-h" || args[0] === "help") {
|
|
146
|
+
stdout.write(HELP);
|
|
147
|
+
return 0;
|
|
148
|
+
}
|
|
149
|
+
if (args[0] === "--version" || args[0] === "-v" || args[0] === "version") {
|
|
150
|
+
stdout.write(`r5d-macos-vm ${packageVersion}
|
|
151
|
+
`);
|
|
152
|
+
return 0;
|
|
153
|
+
}
|
|
154
|
+
(0, import_host.validateHostInformation)(dependencies.hostInformation ?? await (0, import_host.readHostInformation)());
|
|
155
|
+
const manifest = (0, import_artifact_manifest.readNativeArtifactManifest)(resolveManifestPath(modulePath, dependencies.manifestPath), packageVersion);
|
|
156
|
+
const executable = await (dependencies.ensureRuntime ?? import_native_runtime.ensureNativeRuntime)(manifest, dependencies.runtime);
|
|
157
|
+
const bootstrapDir = dependencies.bootstrapDir ?? findBootstrapDirectory(modulePath);
|
|
158
|
+
const nativeArgs = normalizeNativeArguments(args, bootstrapDir);
|
|
159
|
+
const exitCode = await (dependencies.invokeNative ?? invokeNativeProcess)(executable, nativeArgs);
|
|
160
|
+
const commandIndex = findCommandIndex(nativeArgs);
|
|
161
|
+
if (exitCode === 0 && commandIndex >= 0 && nativeArgs[commandIndex] === "cache" && nativeArgs[commandIndex + 1] === "prune") {
|
|
162
|
+
await (dependencies.pruneRuntimes ?? import_native_runtime.pruneObsoleteNativeRuntimes)(
|
|
163
|
+
executable,
|
|
164
|
+
dependencies.runtime?.cacheRoot ?? (0, import_native_runtime.defaultCacheRoot)()
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
return exitCode;
|
|
168
|
+
}
|
|
169
|
+
function getHelpText() {
|
|
170
|
+
return HELP;
|
|
171
|
+
}
|
|
172
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
173
|
+
0 && (module.exports = {
|
|
174
|
+
getHelpText,
|
|
175
|
+
invokeNativeProcess,
|
|
176
|
+
normalizeNativeArguments,
|
|
177
|
+
runCli,
|
|
178
|
+
validateVmName
|
|
179
|
+
});
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var host_exports = {};
|
|
20
|
+
__export(host_exports, {
|
|
21
|
+
readHostInformation: () => readHostInformation,
|
|
22
|
+
validateHostInformation: () => validateHostInformation
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(host_exports);
|
|
25
|
+
var import_node_child_process = require("node:child_process");
|
|
26
|
+
function runSwVers() {
|
|
27
|
+
return new Promise((resolve, reject) => {
|
|
28
|
+
const child = (0, import_node_child_process.spawn)("/usr/bin/sw_vers", ["-productVersion"], {
|
|
29
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
30
|
+
env: { ...process.env, LANG: "C", LC_ALL: "C" }
|
|
31
|
+
});
|
|
32
|
+
let stdout = "";
|
|
33
|
+
let stderr = "";
|
|
34
|
+
child.stdout.setEncoding("utf8").on("data", (chunk) => stdout += chunk);
|
|
35
|
+
child.stderr.setEncoding("utf8").on("data", (chunk) => stderr += chunk);
|
|
36
|
+
child.once("error", reject);
|
|
37
|
+
child.once("close", (code) => {
|
|
38
|
+
if (code === 0) resolve(stdout.trim());
|
|
39
|
+
else reject(new Error(`sw_vers failed (${code ?? "signal"}): ${stderr.trim()}`));
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
async function readHostInformation() {
|
|
44
|
+
return {
|
|
45
|
+
platform: process.platform,
|
|
46
|
+
architecture: process.arch,
|
|
47
|
+
macOSVersion: process.platform === "darwin" ? await runSwVers() : "unknown"
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function validateHostInformation(host) {
|
|
51
|
+
if (host.platform !== "darwin") throw new Error("r5d-macos-vm requires macOS.");
|
|
52
|
+
if (host.architecture !== "arm64") throw new Error("r5d-macos-vm requires an Apple silicon Mac (arm64).");
|
|
53
|
+
const match = /^(\d+)(?:\.(\d+))?/.exec(host.macOSVersion);
|
|
54
|
+
if (!match || Number(match[1]) < 14) {
|
|
55
|
+
throw new Error(`r5d-macos-vm requires macOS 14 or newer (found ${host.macOSVersion}).`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
59
|
+
0 && (module.exports = {
|
|
60
|
+
readHostInformation,
|
|
61
|
+
validateHostInformation
|
|
62
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var import_cli = require("./cli.cjs");
|
|
4
|
+
(0, import_cli.runCli)(process.argv.slice(2)).then((exitCode) => {
|
|
5
|
+
process.exitCode = exitCode;
|
|
6
|
+
}).catch((error) => {
|
|
7
|
+
process.stderr.write(`r5d-macos-vm: ${error instanceof Error ? error.message : String(error)}
|
|
8
|
+
`);
|
|
9
|
+
process.exitCode = 1;
|
|
10
|
+
});
|