rightsize 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/LICENSE +202 -0
- package/NOTICE +4 -0
- package/README.md +255 -0
- package/dist/backend-docker/backend.d.ts +53 -0
- package/dist/backend-docker/backend.d.ts.map +1 -0
- package/dist/backend-docker/backend.js +336 -0
- package/dist/backend-docker/backend.js.map +1 -0
- package/dist/backend-docker/client.d.ts +82 -0
- package/dist/backend-docker/client.d.ts.map +1 -0
- package/dist/backend-docker/client.js +190 -0
- package/dist/backend-docker/client.js.map +1 -0
- package/dist/backend-docker/frames.d.ts +44 -0
- package/dist/backend-docker/frames.d.ts.map +1 -0
- package/dist/backend-docker/frames.js +105 -0
- package/dist/backend-docker/frames.js.map +1 -0
- package/dist/backend-docker/index.d.ts +5 -0
- package/dist/backend-docker/index.d.ts.map +1 -0
- package/dist/backend-docker/index.js +20 -0
- package/dist/backend-docker/index.js.map +1 -0
- package/dist/backend-docker/json.d.ts +13 -0
- package/dist/backend-docker/json.d.ts.map +1 -0
- package/dist/backend-docker/json.js +47 -0
- package/dist/backend-docker/json.js.map +1 -0
- package/dist/backend-docker/labels.d.ts +11 -0
- package/dist/backend-docker/labels.d.ts.map +1 -0
- package/dist/backend-docker/labels.js +13 -0
- package/dist/backend-docker/labels.js.map +1 -0
- package/dist/backend-docker/port-conflict.d.ts +9 -0
- package/dist/backend-docker/port-conflict.d.ts.map +1 -0
- package/dist/backend-docker/port-conflict.js +12 -0
- package/dist/backend-docker/port-conflict.js.map +1 -0
- package/dist/backend-docker/provider.d.ts +22 -0
- package/dist/backend-docker/provider.d.ts.map +1 -0
- package/dist/backend-docker/provider.js +36 -0
- package/dist/backend-docker/provider.js.map +1 -0
- package/dist/backend-msb/backend.d.ts +169 -0
- package/dist/backend-msb/backend.d.ts.map +1 -0
- package/dist/backend-msb/backend.js +664 -0
- package/dist/backend-msb/backend.js.map +1 -0
- package/dist/backend-msb/commands.d.ts +28 -0
- package/dist/backend-msb/commands.d.ts.map +1 -0
- package/dist/backend-msb/commands.js +67 -0
- package/dist/backend-msb/commands.js.map +1 -0
- package/dist/backend-msb/exec-tunnel.d.ts +33 -0
- package/dist/backend-msb/exec-tunnel.d.ts.map +1 -0
- package/dist/backend-msb/exec-tunnel.js +163 -0
- package/dist/backend-msb/exec-tunnel.js.map +1 -0
- package/dist/backend-msb/follow-replay.d.ts +14 -0
- package/dist/backend-msb/follow-replay.d.ts.map +1 -0
- package/dist/backend-msb/follow-replay.js +20 -0
- package/dist/backend-msb/follow-replay.js.map +1 -0
- package/dist/backend-msb/image-cache.d.ts +25 -0
- package/dist/backend-msb/image-cache.d.ts.map +1 -0
- package/dist/backend-msb/image-cache.js +27 -0
- package/dist/backend-msb/image-cache.js.map +1 -0
- package/dist/backend-msb/index.d.ts +6 -0
- package/dist/backend-msb/index.d.ts.map +1 -0
- package/dist/backend-msb/index.js +21 -0
- package/dist/backend-msb/index.js.map +1 -0
- package/dist/backend-msb/invoke.d.ts +24 -0
- package/dist/backend-msb/invoke.d.ts.map +1 -0
- package/dist/backend-msb/invoke.js +73 -0
- package/dist/backend-msb/invoke.js.map +1 -0
- package/dist/backend-msb/ls-json.d.ts +23 -0
- package/dist/backend-msb/ls-json.d.ts.map +1 -0
- package/dist/backend-msb/ls-json.js +113 -0
- package/dist/backend-msb/ls-json.js.map +1 -0
- package/dist/backend-msb/network-links.d.ts +7 -0
- package/dist/backend-msb/network-links.d.ts.map +1 -0
- package/dist/backend-msb/network-links.js +31 -0
- package/dist/backend-msb/network-links.js.map +1 -0
- package/dist/backend-msb/platform.d.ts +29 -0
- package/dist/backend-msb/platform.d.ts.map +1 -0
- package/dist/backend-msb/platform.js +128 -0
- package/dist/backend-msb/platform.js.map +1 -0
- package/dist/backend-msb/port-conflict.d.ts +10 -0
- package/dist/backend-msb/port-conflict.d.ts.map +1 -0
- package/dist/backend-msb/port-conflict.js +16 -0
- package/dist/backend-msb/port-conflict.js.map +1 -0
- package/dist/backend-msb/provider.d.ts +10 -0
- package/dist/backend-msb/provider.d.ts.map +1 -0
- package/dist/backend-msb/provider.js +40 -0
- package/dist/backend-msb/provider.js.map +1 -0
- package/dist/backend-msb/provisioner.d.ts +19 -0
- package/dist/backend-msb/provisioner.d.ts.map +1 -0
- package/dist/backend-msb/provisioner.js +332 -0
- package/dist/backend-msb/provisioner.js.map +1 -0
- package/dist/backend-msb/reaper.d.ts +10 -0
- package/dist/backend-msb/reaper.d.ts.map +1 -0
- package/dist/backend-msb/reaper.js +73 -0
- package/dist/backend-msb/reaper.js.map +1 -0
- package/dist/core/backend.d.ts +98 -0
- package/dist/core/backend.d.ts.map +1 -0
- package/dist/core/backend.js +2 -0
- package/dist/core/backend.js.map +1 -0
- package/dist/core/backends.d.ts +37 -0
- package/dist/core/backends.d.ts.map +1 -0
- package/dist/core/backends.js +127 -0
- package/dist/core/backends.js.map +1 -0
- package/dist/core/cleanup.d.ts +37 -0
- package/dist/core/cleanup.d.ts.map +1 -0
- package/dist/core/cleanup.js +86 -0
- package/dist/core/cleanup.js.map +1 -0
- package/dist/core/errors.d.ts +51 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +66 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/free-ports.d.ts +23 -0
- package/dist/core/free-ports.d.ts.map +1 -0
- package/dist/core/free-ports.js +63 -0
- package/dist/core/free-ports.js.map +1 -0
- package/dist/core/generic-container.d.ts +145 -0
- package/dist/core/generic-container.d.ts.map +1 -0
- package/dist/core/generic-container.js +385 -0
- package/dist/core/generic-container.js.map +1 -0
- package/dist/core/model.d.ts +60 -0
- package/dist/core/model.d.ts.map +1 -0
- package/dist/core/model.js +2 -0
- package/dist/core/model.js.map +1 -0
- package/dist/core/mountable-file.d.ts +25 -0
- package/dist/core/mountable-file.d.ts.map +1 -0
- package/dist/core/mountable-file.js +64 -0
- package/dist/core/mountable-file.js.map +1 -0
- package/dist/core/network.d.ts +58 -0
- package/dist/core/network.d.ts.map +1 -0
- package/dist/core/network.js +84 -0
- package/dist/core/network.js.map +1 -0
- package/dist/core/run-id.d.ts +18 -0
- package/dist/core/run-id.d.ts.map +1 -0
- package/dist/core/run-id.js +18 -0
- package/dist/core/run-id.js.map +1 -0
- package/dist/core/wait.d.ts +59 -0
- package/dist/core/wait.d.ts.map +1 -0
- package/dist/core/wait.js +239 -0
- package/dist/core/wait.js.map +1 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/modules/arango.d.ts +14 -0
- package/dist/modules/arango.d.ts.map +1 -0
- package/dist/modules/arango.js +37 -0
- package/dist/modules/arango.js.map +1 -0
- package/dist/modules/clickhouse.d.ts +37 -0
- package/dist/modules/clickhouse.d.ts.map +1 -0
- package/dist/modules/clickhouse.js +69 -0
- package/dist/modules/clickhouse.js.map +1 -0
- package/dist/modules/flink.d.ts +65 -0
- package/dist/modules/flink.d.ts.map +1 -0
- package/dist/modules/flink.js +125 -0
- package/dist/modules/flink.js.map +1 -0
- package/dist/modules/floci.d.ts +46 -0
- package/dist/modules/floci.d.ts.map +1 -0
- package/dist/modules/floci.js +62 -0
- package/dist/modules/floci.js.map +1 -0
- package/dist/modules/index.d.ts +31 -0
- package/dist/modules/index.d.ts.map +1 -0
- package/dist/modules/index.js +31 -0
- package/dist/modules/index.js.map +1 -0
- package/dist/modules/kafka.d.ts +11 -0
- package/dist/modules/kafka.d.ts.map +1 -0
- package/dist/modules/kafka.js +41 -0
- package/dist/modules/kafka.js.map +1 -0
- package/dist/modules/keycloak.d.ts +40 -0
- package/dist/modules/keycloak.d.ts.map +1 -0
- package/dist/modules/keycloak.js +67 -0
- package/dist/modules/keycloak.js.map +1 -0
- package/dist/modules/mariadb.d.ts +56 -0
- package/dist/modules/mariadb.d.ts.map +1 -0
- package/dist/modules/mariadb.js +89 -0
- package/dist/modules/mariadb.js.map +1 -0
- package/dist/modules/memcached.d.ts +24 -0
- package/dist/modules/memcached.d.ts.map +1 -0
- package/dist/modules/memcached.js +105 -0
- package/dist/modules/memcached.js.map +1 -0
- package/dist/modules/mongodb.d.ts +19 -0
- package/dist/modules/mongodb.d.ts.map +1 -0
- package/dist/modules/mongodb.js +69 -0
- package/dist/modules/mongodb.js.map +1 -0
- package/dist/modules/mysql.d.ts +61 -0
- package/dist/modules/mysql.d.ts.map +1 -0
- package/dist/modules/mysql.js +101 -0
- package/dist/modules/mysql.js.map +1 -0
- package/dist/modules/neo4j.d.ts +60 -0
- package/dist/modules/neo4j.d.ts.map +1 -0
- package/dist/modules/neo4j.js +83 -0
- package/dist/modules/neo4j.js.map +1 -0
- package/dist/modules/pinot.d.ts +30 -0
- package/dist/modules/pinot.d.ts.map +1 -0
- package/dist/modules/pinot.js +49 -0
- package/dist/modules/pinot.js.map +1 -0
- package/dist/modules/postgres.d.ts +29 -0
- package/dist/modules/postgres.d.ts.map +1 -0
- package/dist/modules/postgres.js +73 -0
- package/dist/modules/postgres.js.map +1 -0
- package/dist/modules/rabbitmq.d.ts +46 -0
- package/dist/modules/rabbitmq.d.ts.map +1 -0
- package/dist/modules/rabbitmq.js +68 -0
- package/dist/modules/rabbitmq.js.map +1 -0
- package/dist/modules/redis.d.ts +15 -0
- package/dist/modules/redis.d.ts.map +1 -0
- package/dist/modules/redis.js +24 -0
- package/dist/modules/redis.js.map +1 -0
- package/dist/modules/redpanda.d.ts +27 -0
- package/dist/modules/redpanda.d.ts.map +1 -0
- package/dist/modules/redpanda.js +58 -0
- package/dist/modules/redpanda.js.map +1 -0
- package/dist/modules/spring-cloud-config.d.ts +18 -0
- package/dist/modules/spring-cloud-config.d.ts.map +1 -0
- package/dist/modules/spring-cloud-config.js +28 -0
- package/dist/modules/spring-cloud-config.js.map +1 -0
- package/dist/modules/wiremock.d.ts +21 -0
- package/dist/modules/wiremock.d.ts.map +1 -0
- package/dist/modules/wiremock.js +32 -0
- package/dist/modules/wiremock.js.map +1 -0
- package/package.json +104 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parses `msb ls --format json` — the msb backend's only way to learn which
|
|
3
|
+
* sandboxes currently show `"status":"Running"`. The current msb release's shape is a flat
|
|
4
|
+
* JSON array of objects with keys `created_at, image, name, status` (status
|
|
5
|
+
* capitalized). `JSON.parse` handles that shape fine, but a hand-rolled
|
|
6
|
+
* string/escape-aware brace scanner is kept as the primary path anyway: it
|
|
7
|
+
* degrades gracefully (skip the malformed object, keep the rest) on the kind
|
|
8
|
+
* of schema drift a future msb release might introduce, where `JSON.parse`
|
|
9
|
+
* would simply throw and cost the caller every entry instead of the one bad
|
|
10
|
+
* one.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Names of sandboxes whose `status` is exactly `"Running"` (capitalized —
|
|
14
|
+
* msb never lowercases it). An entry missing `name` or `status` is skipped
|
|
15
|
+
* outright, never counted as a name-less running sandbox. Tries `JSON.parse`
|
|
16
|
+
* first for the common case and falls back to the tolerant brace scanner
|
|
17
|
+
* only if that throws, so well-formed output pays no scanning cost while
|
|
18
|
+
* malformed output still degrades gracefully instead of losing everything.
|
|
19
|
+
*/
|
|
20
|
+
export declare function runningNames(json: string): Set<string>;
|
|
21
|
+
/** Test-only: forces the tolerant scanner path regardless of whether JSON.parse would succeed. */
|
|
22
|
+
export declare function _scanRunningNamesForTests(json: string): Set<string>;
|
|
23
|
+
//# sourceMappingURL=ls-json.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ls-json.d.ts","sourceRoot":"","sources":["../../src/backend-msb/ls-json.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AA2EH;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAetD;AAED,kGAAkG;AAClG,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAQnE"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parses `msb ls --format json` — the msb backend's only way to learn which
|
|
3
|
+
* sandboxes currently show `"status":"Running"`. The current msb release's shape is a flat
|
|
4
|
+
* JSON array of objects with keys `created_at, image, name, status` (status
|
|
5
|
+
* capitalized). `JSON.parse` handles that shape fine, but a hand-rolled
|
|
6
|
+
* string/escape-aware brace scanner is kept as the primary path anyway: it
|
|
7
|
+
* degrades gracefully (skip the malformed object, keep the rest) on the kind
|
|
8
|
+
* of schema drift a future msb release might introduce, where `JSON.parse`
|
|
9
|
+
* would simply throw and cost the caller every entry instead of the one bad
|
|
10
|
+
* one.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Splits a top-level JSON array's text into the substrings of its immediate
|
|
14
|
+
* object elements, string- and escape-aware so a `}` or `,` inside a quoted
|
|
15
|
+
* value never miscounts as structural. Never throws: anything that isn't
|
|
16
|
+
* bracket-balanced simply yields whatever complete objects were found before
|
|
17
|
+
* the text ran out.
|
|
18
|
+
*/
|
|
19
|
+
function splitTopLevelObjects(text) {
|
|
20
|
+
const objects = [];
|
|
21
|
+
let depth = 0;
|
|
22
|
+
let start = -1;
|
|
23
|
+
let inString = false;
|
|
24
|
+
let escaped = false;
|
|
25
|
+
for (let i = 0; i < text.length; i++) {
|
|
26
|
+
const ch = text[i];
|
|
27
|
+
if (inString) {
|
|
28
|
+
if (escaped) {
|
|
29
|
+
escaped = false;
|
|
30
|
+
}
|
|
31
|
+
else if (ch === "\\") {
|
|
32
|
+
escaped = true;
|
|
33
|
+
}
|
|
34
|
+
else if (ch === '"') {
|
|
35
|
+
inString = false;
|
|
36
|
+
}
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (ch === '"') {
|
|
40
|
+
inString = true;
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
if (ch === "{") {
|
|
44
|
+
if (depth === 0) {
|
|
45
|
+
start = i;
|
|
46
|
+
}
|
|
47
|
+
depth++;
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
if (ch === "}") {
|
|
51
|
+
if (depth > 0) {
|
|
52
|
+
depth--;
|
|
53
|
+
if (depth === 0 && start >= 0) {
|
|
54
|
+
objects.push(text.slice(start, i + 1));
|
|
55
|
+
start = -1;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return objects;
|
|
62
|
+
}
|
|
63
|
+
/** Extracts a single string field's value from one object's raw text, tolerant of key order. */
|
|
64
|
+
function extractStringField(objectText, field) {
|
|
65
|
+
const re = new RegExp(`"${field}"\\s*:\\s*"((?:[^"\\\\]|\\\\.)*)"`);
|
|
66
|
+
const match = re.exec(objectText);
|
|
67
|
+
if (match === undefined || match === null || match[1] === undefined) {
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
return match[1].replace(/\\"/g, '"').replace(/\\\\/g, "\\");
|
|
71
|
+
}
|
|
72
|
+
function scanEntries(json) {
|
|
73
|
+
return splitTopLevelObjects(json).map((objectText) => ({
|
|
74
|
+
name: extractStringField(objectText, "name"),
|
|
75
|
+
status: extractStringField(objectText, "status"),
|
|
76
|
+
}));
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Names of sandboxes whose `status` is exactly `"Running"` (capitalized —
|
|
80
|
+
* msb never lowercases it). An entry missing `name` or `status` is skipped
|
|
81
|
+
* outright, never counted as a name-less running sandbox. Tries `JSON.parse`
|
|
82
|
+
* first for the common case and falls back to the tolerant brace scanner
|
|
83
|
+
* only if that throws, so well-formed output pays no scanning cost while
|
|
84
|
+
* malformed output still degrades gracefully instead of losing everything.
|
|
85
|
+
*/
|
|
86
|
+
export function runningNames(json) {
|
|
87
|
+
let entries;
|
|
88
|
+
try {
|
|
89
|
+
const parsed = JSON.parse(json);
|
|
90
|
+
entries = Array.isArray(parsed) ? parsed : [];
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
entries = scanEntries(json);
|
|
94
|
+
}
|
|
95
|
+
const names = new Set();
|
|
96
|
+
for (const entry of entries) {
|
|
97
|
+
if (entry.status === "Running" && typeof entry.name === "string") {
|
|
98
|
+
names.add(entry.name);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return names;
|
|
102
|
+
}
|
|
103
|
+
/** Test-only: forces the tolerant scanner path regardless of whether JSON.parse would succeed. */
|
|
104
|
+
export function _scanRunningNamesForTests(json) {
|
|
105
|
+
const names = new Set();
|
|
106
|
+
for (const entry of scanEntries(json)) {
|
|
107
|
+
if (entry.status === "Running" && typeof entry.name === "string") {
|
|
108
|
+
names.add(entry.name);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return names;
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=ls-json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ls-json.js","sourceRoot":"","sources":["../../src/backend-msb/ls-json.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { NetworkLink } from "../core/backend.js";
|
|
2
|
+
/** Two siblings publishing the same guest port on one network have nowhere distinct to tunnel to. */
|
|
3
|
+
export declare function requireNoDuplicateGuestPorts(links: readonly NetworkLink[]): void;
|
|
4
|
+
export declare function requireAliasesAreValid(links: readonly NetworkLink[]): void;
|
|
5
|
+
/** The `sh -c` script that appends one `/etc/hosts` line per distinct alias. */
|
|
6
|
+
export declare function hostsAliasScript(links: readonly NetworkLink[]): string;
|
|
7
|
+
//# sourceMappingURL=network-links.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"network-links.d.ts","sourceRoot":"","sources":["../../src/backend-msb/network-links.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAUtD,qGAAqG;AACrG,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,SAAS,WAAW,EAAE,GAAG,IAAI,CAWhF;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,SAAS,WAAW,EAAE,GAAG,IAAI,CAW1E;AAED,gFAAgF;AAChF,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,WAAW,EAAE,GAAG,MAAM,CAGtE"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { UnsupportedByBackendError } from "../core/errors.js";
|
|
2
|
+
const BACKEND_NAME = "microsandbox";
|
|
3
|
+
// Permissive DNS-label charset: aliases are interpolated into a `sh -c`
|
|
4
|
+
// `/etc/hosts` echo, so this exists to reject shell-metacharacter aliases
|
|
5
|
+
// that could break out of the quoting, not to enforce a strict hostname
|
|
6
|
+
// grammar.
|
|
7
|
+
const ALIAS_CHARSET = /^[A-Za-z0-9._-]+$/;
|
|
8
|
+
/** Two siblings publishing the same guest port on one network have nowhere distinct to tunnel to. */
|
|
9
|
+
export function requireNoDuplicateGuestPorts(links) {
|
|
10
|
+
const seen = new Set();
|
|
11
|
+
for (const link of links) {
|
|
12
|
+
if (seen.has(link.guestPort)) {
|
|
13
|
+
throw new UnsupportedByBackendError(`two siblings exposing the same guest port ${link.guestPort} on one network`, BACKEND_NAME);
|
|
14
|
+
}
|
|
15
|
+
seen.add(link.guestPort);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export function requireAliasesAreValid(links) {
|
|
19
|
+
const aliases = new Set(links.map((l) => l.alias));
|
|
20
|
+
for (const alias of aliases) {
|
|
21
|
+
if (!ALIAS_CHARSET.test(alias)) {
|
|
22
|
+
throw new UnsupportedByBackendError(`network alias '${alias}'`, BACKEND_NAME, "use a valid DNS label instead (allowed: letters, digits, '.', '_', '-')");
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/** The `sh -c` script that appends one `/etc/hosts` line per distinct alias. */
|
|
27
|
+
export function hostsAliasScript(links) {
|
|
28
|
+
const aliases = [...new Set(links.map((l) => l.alias))];
|
|
29
|
+
return aliases.map((alias) => `echo '127.0.0.1 ${alias}' >> /etc/hosts`).join("; ");
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=network-links.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"network-links.js","sourceRoot":"","sources":["../../src/backend-msb/network-links.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAG9D,MAAM,YAAY,GAAG,cAAc,CAAC;AAEpC,wEAAwE;AACxE,0EAA0E;AAC1E,wEAAwE;AACxE,WAAW;AACX,MAAM,aAAa,GAAG,mBAAmB,CAAC;AAE1C,qGAAqG;AACrG,MAAM,UAAU,4BAA4B,CAAC,KAA6B;IACxE,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,yBAAyB,CACjC,6CAA6C,IAAI,CAAC,SAAS,iBAAiB,EAC5E,YAAY,CACb,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC3B,CAAC;AACH,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,KAA6B;IAClE,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;IACnD,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YAC/B,MAAM,IAAI,yBAAyB,CACjC,kBAAkB,KAAK,GAAG,EAC1B,YAAY,EACZ,yEAAyE,CAC1E,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,gBAAgB,CAAC,KAA6B;IAC5D,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACxD,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,mBAAmB,KAAK,iBAAiB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACtF,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/** The five platforms the pinned microsandbox release ships a build for. */
|
|
2
|
+
export type Platform = "darwin-arm64" | "linux-x64" | "linux-arm64" | "win32-x64" | "win32-arm64";
|
|
3
|
+
/** Platform detection and per-platform msb/krun asset naming, backing `MsbBackendProvider.isSupported`. */
|
|
4
|
+
export declare const PlatformInfo: {
|
|
5
|
+
/** This process's msb platform, or `undefined` if msb ships no build for it. */
|
|
6
|
+
current(): Platform | undefined;
|
|
7
|
+
/** The `msb` release asset filename for this platform. */
|
|
8
|
+
msbAsset(p: Platform): string;
|
|
9
|
+
/** The libkrunfw release asset filename for this platform — what it is downloaded as. */
|
|
10
|
+
krunAsset(p: Platform): string;
|
|
11
|
+
/**
|
|
12
|
+
* The basename the msb binary must be installed under inside `bin/` —
|
|
13
|
+
* suffixless (`msb`) on macOS/Linux, `msb.exe` on Windows (there is no
|
|
14
|
+
* such thing as a suffixless executable on Windows; the OS resolves
|
|
15
|
+
* executables by extension, not an executable permission bit). Derived
|
|
16
|
+
* from the platform rather than a literal `"msb"` constant so the
|
|
17
|
+
* provisioner's install-target path is correct on every platform.
|
|
18
|
+
*/
|
|
19
|
+
msbBinaryName(p: Platform): string;
|
|
20
|
+
/** The filename the library must be installed under for msb to resolve it. */
|
|
21
|
+
krunInstallName(p: Platform): string;
|
|
22
|
+
/** Whether this machine can actually run msb's microVMs right now (KVM access on Linux; always true once the platform itself resolves on macOS or Windows — see `virtualizationAvailable`'s doc comment for why Windows is attempt-and-report). */
|
|
23
|
+
virtualizationAvailable(): boolean;
|
|
24
|
+
/** Test seam: exercises the pure decision tables against injected platform/arch strings. */
|
|
25
|
+
_currentFor(processPlatform: string, processArch: string): Platform | undefined;
|
|
26
|
+
/** Test seam: exercises `virtualizationAvailable`'s pure per-OS branches against injected platform/arch strings, without a real `/dev/kvm` or host OS. */
|
|
27
|
+
_virtualizationAvailableFor(processPlatform: string, processArch: string): boolean;
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=platform.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../../src/backend-msb/platform.ts"],"names":[],"mappings":"AAEA,4EAA4E;AAC5E,MAAM,MAAM,QAAQ,GAAG,cAAc,GAAG,WAAW,GAAG,aAAa,GAAG,WAAW,GAAG,aAAa,CAAC;AA0FlG,2GAA2G;AAC3G,eAAO,MAAM,YAAY;IACvB,gFAAgF;eACrE,QAAQ,GAAG,SAAS;IAG/B,0DAA0D;gBAC9C,QAAQ,GAAG,MAAM;IAG7B,yFAAyF;iBAC5E,QAAQ,GAAG,MAAM;IAG9B;;;;;;;OAOG;qBACc,QAAQ,GAAG,MAAM;IAGlC,8EAA8E;uBAC3D,QAAQ,GAAG,MAAM;IAGpC,mPAAmP;+BACxN,OAAO;IAGlC,4FAA4F;iCAC/D,MAAM,eAAe,MAAM,GAAG,QAAQ,GAAG,SAAS;IAG/E,0JAA0J;iDAC7G,MAAM,eAAe,MAAM,GAAG,OAAO;CAGnF,CAAC"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
const MSB_ASSETS = {
|
|
3
|
+
"darwin-arm64": "msb-darwin-aarch64",
|
|
4
|
+
"linux-x64": "msb-linux-x86_64",
|
|
5
|
+
"linux-arm64": "msb-linux-aarch64",
|
|
6
|
+
"win32-x64": "msb-windows-x86_64.exe",
|
|
7
|
+
"win32-arm64": "msb-windows-aarch64.exe",
|
|
8
|
+
};
|
|
9
|
+
const KRUN_ASSETS = {
|
|
10
|
+
"darwin-arm64": "libkrunfw-darwin-aarch64.dylib",
|
|
11
|
+
"linux-x64": "libkrunfw-linux-x86_64.so",
|
|
12
|
+
"linux-arm64": "libkrunfw-linux-aarch64.so",
|
|
13
|
+
"win32-x64": "libkrunfw-windows-x86_64.dll",
|
|
14
|
+
"win32-arm64": "libkrunfw-windows-aarch64.dll",
|
|
15
|
+
};
|
|
16
|
+
// The exact filename msb resolves the library under: it probes `../lib/` next to its
|
|
17
|
+
// own binary for `libkrunfw.so.<version>` on Linux, `libkrunfw.<abi>.dylib` on macOS,
|
|
18
|
+
// and unversioned `libkrunfw.dll` on Windows (confirmed against install.ps1, the
|
|
19
|
+
// upstream Windows installer's own copy step: it moves the extracted bundle's
|
|
20
|
+
// `libkrunfw.dll` straight to `lib\libkrunfw.dll`, no version suffix) — never the
|
|
21
|
+
// release-asset name — so the provisioner installs the downloaded asset under this
|
|
22
|
+
// name. The embedded libkrunfw version/ABI is part of the pinned msb release;
|
|
23
|
+
// re-verify all names when bumping the pin.
|
|
24
|
+
const KRUN_INSTALL_NAMES = {
|
|
25
|
+
"darwin-arm64": "libkrunfw.5.dylib",
|
|
26
|
+
"linux-x64": "libkrunfw.so.5.5.0",
|
|
27
|
+
"linux-arm64": "libkrunfw.so.5.5.0",
|
|
28
|
+
"win32-x64": "libkrunfw.dll",
|
|
29
|
+
"win32-arm64": "libkrunfw.dll",
|
|
30
|
+
};
|
|
31
|
+
function currentPlatform(processPlatform, processArch) {
|
|
32
|
+
if (processPlatform === "darwin" && processArch === "arm64") {
|
|
33
|
+
return "darwin-arm64";
|
|
34
|
+
}
|
|
35
|
+
if (processPlatform === "linux" && processArch === "x64") {
|
|
36
|
+
return "linux-x64";
|
|
37
|
+
}
|
|
38
|
+
if (processPlatform === "linux" && processArch === "arm64") {
|
|
39
|
+
return "linux-arm64";
|
|
40
|
+
}
|
|
41
|
+
if (processPlatform === "win32" && processArch === "x64") {
|
|
42
|
+
return "win32-x64";
|
|
43
|
+
}
|
|
44
|
+
if (processPlatform === "win32" && processArch === "arm64") {
|
|
45
|
+
return "win32-arm64";
|
|
46
|
+
}
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Linux needs `/dev/kvm` open for read+write; Apple Silicon's virtualization
|
|
51
|
+
* is available whenever the platform itself resolves (Virtualization.framework
|
|
52
|
+
* needs no device-file probe). Windows is attempt-and-report rather than
|
|
53
|
+
* probed: there is no cheap, reliable no-spawn signal for Windows Hypervisor
|
|
54
|
+
* Platform availability (querying the `HypervisorPlatform` optional feature
|
|
55
|
+
* needs a PowerShell subprocess, which this synchronous method cannot spawn
|
|
56
|
+
* without blocking), and the windows-spike findings (2026-07-05, msb 0.6.3 on
|
|
57
|
+
* windows-2022/windows-2025 hosted runners) showed WHP already enabled out of
|
|
58
|
+
* the box on both — so a detected Windows platform reports true here, exactly
|
|
59
|
+
* as macOS does, and a genuinely WHP-less host finds out from msb's own error
|
|
60
|
+
* at boot (`msb doctor`/`msb run` fail loudly), not a silent Docker downgrade.
|
|
61
|
+
* All branches use the synchronous `fs` calls — never `fs.access` — because
|
|
62
|
+
* `BackendProvider.isSupported()` (the caller, `MsbBackendProvider`) is a
|
|
63
|
+
* synchronous interface method: an async probe here would make
|
|
64
|
+
* `isSupported()` return a Promise, which the pure resolver in
|
|
65
|
+
* `Backends.resolve` would read as truthy ("supported") without ever
|
|
66
|
+
* awaiting it.
|
|
67
|
+
*/
|
|
68
|
+
function virtualizationAvailable(processPlatform, processArch) {
|
|
69
|
+
if (processPlatform === "darwin") {
|
|
70
|
+
return currentPlatform(processPlatform, processArch) !== undefined;
|
|
71
|
+
}
|
|
72
|
+
if (processPlatform === "linux") {
|
|
73
|
+
try {
|
|
74
|
+
fs.accessSync("/dev/kvm", fs.constants.R_OK | fs.constants.W_OK);
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (processPlatform === "win32") {
|
|
82
|
+
return currentPlatform(processPlatform, processArch) !== undefined;
|
|
83
|
+
}
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
/** Platform detection and per-platform msb/krun asset naming, backing `MsbBackendProvider.isSupported`. */
|
|
87
|
+
export const PlatformInfo = {
|
|
88
|
+
/** This process's msb platform, or `undefined` if msb ships no build for it. */
|
|
89
|
+
current() {
|
|
90
|
+
return currentPlatform(process.platform, process.arch);
|
|
91
|
+
},
|
|
92
|
+
/** The `msb` release asset filename for this platform. */
|
|
93
|
+
msbAsset(p) {
|
|
94
|
+
return MSB_ASSETS[p];
|
|
95
|
+
},
|
|
96
|
+
/** The libkrunfw release asset filename for this platform — what it is downloaded as. */
|
|
97
|
+
krunAsset(p) {
|
|
98
|
+
return KRUN_ASSETS[p];
|
|
99
|
+
},
|
|
100
|
+
/**
|
|
101
|
+
* The basename the msb binary must be installed under inside `bin/` —
|
|
102
|
+
* suffixless (`msb`) on macOS/Linux, `msb.exe` on Windows (there is no
|
|
103
|
+
* such thing as a suffixless executable on Windows; the OS resolves
|
|
104
|
+
* executables by extension, not an executable permission bit). Derived
|
|
105
|
+
* from the platform rather than a literal `"msb"` constant so the
|
|
106
|
+
* provisioner's install-target path is correct on every platform.
|
|
107
|
+
*/
|
|
108
|
+
msbBinaryName(p) {
|
|
109
|
+
return p === "win32-x64" || p === "win32-arm64" ? "msb.exe" : "msb";
|
|
110
|
+
},
|
|
111
|
+
/** The filename the library must be installed under for msb to resolve it. */
|
|
112
|
+
krunInstallName(p) {
|
|
113
|
+
return KRUN_INSTALL_NAMES[p];
|
|
114
|
+
},
|
|
115
|
+
/** Whether this machine can actually run msb's microVMs right now (KVM access on Linux; always true once the platform itself resolves on macOS or Windows — see `virtualizationAvailable`'s doc comment for why Windows is attempt-and-report). */
|
|
116
|
+
virtualizationAvailable() {
|
|
117
|
+
return virtualizationAvailable(process.platform, process.arch);
|
|
118
|
+
},
|
|
119
|
+
/** Test seam: exercises the pure decision tables against injected platform/arch strings. */
|
|
120
|
+
_currentFor(processPlatform, processArch) {
|
|
121
|
+
return currentPlatform(processPlatform, processArch);
|
|
122
|
+
},
|
|
123
|
+
/** Test seam: exercises `virtualizationAvailable`'s pure per-OS branches against injected platform/arch strings, without a real `/dev/kvm` or host OS. */
|
|
124
|
+
_virtualizationAvailableFor(processPlatform, processArch) {
|
|
125
|
+
return virtualizationAvailable(processPlatform, processArch);
|
|
126
|
+
},
|
|
127
|
+
};
|
|
128
|
+
//# sourceMappingURL=platform.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform.js","sourceRoot":"","sources":["../../src/backend-msb/platform.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* msb has no structured error for a host-port bind conflict — only the
|
|
3
|
+
* `msb run` child's combined stdout/stderr text — so this is a best-effort
|
|
4
|
+
* message match, msb-specific wording kept local to this backend rather than
|
|
5
|
+
* folded into `GenericContainer`'s own cause-chain classifier (which handles
|
|
6
|
+
* the typed `PortBindConflictError` case once this function has produced
|
|
7
|
+
* one).
|
|
8
|
+
*/
|
|
9
|
+
export declare function isPortBindConflictOutput(output: string): boolean;
|
|
10
|
+
//# sourceMappingURL=port-conflict.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"port-conflict.d.ts","sourceRoot":"","sources":["../../src/backend-msb/port-conflict.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAQhE"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* msb has no structured error for a host-port bind conflict — only the
|
|
3
|
+
* `msb run` child's combined stdout/stderr text — so this is a best-effort
|
|
4
|
+
* message match, msb-specific wording kept local to this backend rather than
|
|
5
|
+
* folded into `GenericContainer`'s own cause-chain classifier (which handles
|
|
6
|
+
* the typed `PortBindConflictError` case once this function has produced
|
|
7
|
+
* one).
|
|
8
|
+
*/
|
|
9
|
+
export function isPortBindConflictOutput(output) {
|
|
10
|
+
const m = output.toLowerCase();
|
|
11
|
+
return (m.includes("address already in use") ||
|
|
12
|
+
m.includes("port is already allocated") ||
|
|
13
|
+
m.includes("bind: address already in use") ||
|
|
14
|
+
(m.includes("already in use") && m.includes("port")));
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=port-conflict.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"port-conflict.js","sourceRoot":"","sources":["../../src/backend-msb/port-conflict.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,UAAU,wBAAwB,CAAC,MAAc;IACrD,MAAM,CAAC,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;IAC/B,OAAO,CACL,CAAC,CAAC,QAAQ,CAAC,wBAAwB,CAAC;QACpC,CAAC,CAAC,QAAQ,CAAC,2BAA2B,CAAC;QACvC,CAAC,CAAC,QAAQ,CAAC,8BAA8B,CAAC;QAC1C,CAAC,CAAC,CAAC,QAAQ,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CACrD,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { BackendProvider, SandboxBackend } from "../core/backend.js";
|
|
2
|
+
export declare class MsbBackendProvider implements BackendProvider {
|
|
3
|
+
/** `"microsandbox"` — matched case-insensitively against `RIGHTSIZE_BACKEND`. */
|
|
4
|
+
readonly name = "microsandbox";
|
|
5
|
+
readonly priority = 20;
|
|
6
|
+
isSupported(): boolean;
|
|
7
|
+
unsupportedReason(): string;
|
|
8
|
+
create(): SandboxBackend;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/backend-msb/provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAK1E,qBAAa,kBAAmB,YAAW,eAAe;IACxD,iFAAiF;IACjF,QAAQ,CAAC,IAAI,kBAAkB;IAC/B,QAAQ,CAAC,QAAQ,MAAM;IAEvB,WAAW,IAAI,OAAO;IAQtB,iBAAiB,IAAI,MAAM;IAa3B,MAAM,IAAI,cAAc;CAczB"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { PlatformInfo } from "./platform.js";
|
|
2
|
+
import { ensureInstalled } from "./provisioner.js";
|
|
3
|
+
import { MsbCliBackend } from "./backend.js";
|
|
4
|
+
export class MsbBackendProvider {
|
|
5
|
+
/** `"microsandbox"` — matched case-insensitively against `RIGHTSIZE_BACKEND`. */
|
|
6
|
+
name = "microsandbox";
|
|
7
|
+
priority = 20;
|
|
8
|
+
isSupported() {
|
|
9
|
+
// Both sides of this && are synchronous (platform.ts never uses async
|
|
10
|
+
// fs.access) — this method must never return a Promise, or the pure
|
|
11
|
+
// resolver in Backends.resolve would read a truthy Promise as "supported"
|
|
12
|
+
// without ever awaiting it.
|
|
13
|
+
return PlatformInfo.current() !== undefined && PlatformInfo.virtualizationAvailable();
|
|
14
|
+
}
|
|
15
|
+
unsupportedReason() {
|
|
16
|
+
if (PlatformInfo.current() === undefined) {
|
|
17
|
+
return `no msb build for ${process.platform}/${process.arch} (Intel Mac: use the docker backend)`;
|
|
18
|
+
}
|
|
19
|
+
if (process.platform === "win32") {
|
|
20
|
+
return ("Windows Hypervisor Platform is not enabled (run 'msb doctor --fix' in an elevated " +
|
|
21
|
+
"terminal, which may require a reboot), or use the docker backend");
|
|
22
|
+
}
|
|
23
|
+
return "/dev/kvm is not accessible (need KVM, or run on Apple Silicon macOS)";
|
|
24
|
+
}
|
|
25
|
+
create() {
|
|
26
|
+
// create() is a synchronous ServiceLoader-style factory, but
|
|
27
|
+
// locating/installing msb is inherently async. The
|
|
28
|
+
// backend holds the provisioning promise and awaits it lazily on first
|
|
29
|
+
// use; sweepOrphans() piggybacks on that same lazy resolution rather
|
|
30
|
+
// than blocking construction.
|
|
31
|
+
const backend = new MsbCliBackend(ensureInstalled());
|
|
32
|
+
void backend.sweepOrphans().catch(() => {
|
|
33
|
+
// Best-effort: a failed sweep must not prevent this backend from
|
|
34
|
+
// being usable — the next run's sweep gets another chance, and a
|
|
35
|
+
// container that's actually still running is left alone either way.
|
|
36
|
+
});
|
|
37
|
+
return backend;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/backend-msb/provider.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,MAAM,OAAO,kBAAkB;IAC7B,iFAAiF;IACxE,IAAI,GAAG,cAAc,CAAC;IACtB,QAAQ,GAAG,EAAE,CAAC;IAEvB,WAAW;QACT,sEAAsE;QACtE,oEAAoE;QACpE,0EAA0E;QAC1E,4BAA4B;QAC5B,OAAO,YAAY,CAAC,OAAO,EAAE,KAAK,SAAS,IAAI,YAAY,CAAC,uBAAuB,EAAE,CAAC;IACxF,CAAC;IAED,iBAAiB;QACf,IAAI,YAAY,CAAC,OAAO,EAAE,KAAK,SAAS,EAAE,CAAC;YACzC,OAAO,oBAAoB,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,IAAI,sCAAsC,CAAC;QACpG,CAAC;QACD,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;YACjC,OAAO,CACL,oFAAoF;gBACpF,kEAAkE,CACnE,CAAC;QACJ,CAAC;QACD,OAAO,sEAAsE,CAAC;IAChF,CAAC;IAED,MAAM;QACJ,6DAA6D;QAC7D,mDAAmD;QACnD,uEAAuE;QACvE,qEAAqE;QACrE,8BAA8B;QAC9B,MAAM,OAAO,GAAG,IAAI,aAAa,CAAC,eAAe,EAAE,CAAC,CAAC;QACrD,KAAK,OAAO,CAAC,YAAY,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE;YACrC,iEAAiE;YACjE,iEAAiE;YACjE,oEAAoE;QACtE,CAAC,CAAC,CAAC;QACH,OAAO,OAAO,CAAC;IACjB,CAAC;CACF"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Platform } from "./platform.js";
|
|
2
|
+
export declare const MSB_VERSION = "0.6.3";
|
|
3
|
+
/** Test seam: the full resolution logic parameterized over the release base URL, cache dir, and environment. */
|
|
4
|
+
export declare function ensureInstalledAt(baseUrl: string, cacheDir: string, env: Record<string, string | undefined>): Promise<string>;
|
|
5
|
+
/** Resolves (downloading and verifying if needed) a runnable `msb` binary path, using the real GitHub release base, `RIGHTSIZE_CACHE_DIR`, and `process.env`. */
|
|
6
|
+
export declare function ensureInstalled(): Promise<string>;
|
|
7
|
+
/** Test-only access to the pure checksum-line parser, exercised against real-shape and malformed input. */
|
|
8
|
+
export declare function _parseChecksumsForTests(text: string): Map<string, string>;
|
|
9
|
+
/**
|
|
10
|
+
* Test-only seam: `downloadAndInstall` parameterized over an injected
|
|
11
|
+
* `Platform` value, rather than the real `PlatformInfo.current()`. This is
|
|
12
|
+
* how the `.exe`/`.dll` install shape (Windows asset names, `bin\msb.exe`,
|
|
13
|
+
* unversioned `lib\libkrunfw.dll`) is exercised against the real
|
|
14
|
+
* download-verify-rename pipeline from a non-Windows CI/dev machine — the
|
|
15
|
+
* public `ensureInstalledAt` always resolves the platform from the real
|
|
16
|
+
* process, so it can only ever prove the CURRENT host's shape without this.
|
|
17
|
+
*/
|
|
18
|
+
export declare function _downloadAndInstallForTests(baseUrl: string, platform: Platform, installDir: string, msbPath: string, krunPath: string): Promise<void>;
|
|
19
|
+
//# sourceMappingURL=provisioner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provisioner.d.ts","sourceRoot":"","sources":["../../src/backend-msb/provisioner.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,eAAO,MAAM,WAAW,UAAU,CAAC;AAiSnC,gHAAgH;AAChH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GACtC,OAAO,CAAC,MAAM,CAAC,CA8CjB;AAED,iKAAiK;AACjK,wBAAgB,eAAe,IAAI,OAAO,CAAC,MAAM,CAAC,CAEjD;AAED,2GAA2G;AAC3G,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAEzE;AAED;;;;;;;;GAQG;AACH,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,QAAQ,EAClB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAEf"}
|