@automaton-labs/aib 0.0.1 → 0.0.3
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/help/help-meta.json +2 -2
- package/package.json +28 -27
- package/scripts/postinstall.cjs +5 -4
- package/scripts/provision-runtime.cjs +86 -8
package/dist/help/help-meta.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"helpVersion": "0.1.0",
|
|
4
|
-
"generatedAt": "2026-05-
|
|
5
|
-
"sourceCommit": "
|
|
4
|
+
"generatedAt": "2026-05-25T01:16:44+03:00",
|
|
5
|
+
"sourceCommit": "682a840",
|
|
6
6
|
"contentHash": "sha256:fa654cee3287525d7a9dce2fd8d4fa159138898ee4b7c8ebf6fed43bde58074a",
|
|
7
7
|
"topics": {
|
|
8
8
|
"help-format": {
|
package/package.json
CHANGED
|
@@ -1,32 +1,33 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "@automaton-labs/aib",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "CLI for discovering and calling the local aib IDE extension runtime.",
|
|
5
|
-
"publishConfig": {
|
|
6
|
-
"access": "public"
|
|
7
|
-
},
|
|
8
|
-
"bin": {
|
|
9
|
-
"aib": "dist/bin/aib.js"
|
|
10
|
-
},
|
|
11
|
-
"files": [
|
|
12
|
-
"dist",
|
|
13
|
-
"extension",
|
|
14
|
-
"scripts/install-windows-launcher.cjs",
|
|
15
|
-
"scripts/postinstall.cjs",
|
|
16
|
-
"scripts/provision-runtime.cjs",
|
|
17
|
-
"runtimes/launcher",
|
|
18
|
-
"README.md",
|
|
19
|
-
"package.json"
|
|
20
|
-
],
|
|
21
|
-
"scripts": {
|
|
22
|
-
"build": "tsc -p . && node scripts/copy-managed-host-assets.cjs",
|
|
23
|
-
"build:package": "node ../../scripts/package/clean-paths.cjs dist && tsc -p tsconfig.package.json && node scripts/copy-managed-host-assets.cjs && node ../../scripts/package/minify-js.cjs dist",
|
|
24
|
-
"typecheck": "tsc -p . --noEmit",
|
|
25
|
-
"postinstall": "node scripts/postinstall.cjs",
|
|
26
|
-
"prepack": "npm run build:package && node scripts/copy-extension-vsix.cjs",
|
|
27
|
-
"pack:local": "npm pack --pack-destination ../../.tmp"
|
|
28
|
-
},
|
|
2
|
+
"name": "@automaton-labs/aib",
|
|
3
|
+
"version": "0.0.3",
|
|
4
|
+
"description": "CLI for discovering and calling the local aib IDE extension runtime.",
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"access": "public"
|
|
7
|
+
},
|
|
8
|
+
"bin": {
|
|
9
|
+
"aib": "dist/bin/aib.js"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"dist",
|
|
13
|
+
"extension",
|
|
14
|
+
"scripts/install-windows-launcher.cjs",
|
|
15
|
+
"scripts/postinstall.cjs",
|
|
16
|
+
"scripts/provision-runtime.cjs",
|
|
17
|
+
"runtimes/launcher",
|
|
18
|
+
"README.md",
|
|
19
|
+
"package.json"
|
|
20
|
+
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "tsc -p . && node scripts/copy-managed-host-assets.cjs",
|
|
23
|
+
"build:package": "node ../../scripts/package/clean-paths.cjs dist && tsc -p tsconfig.package.json && node scripts/copy-managed-host-assets.cjs && node ../../scripts/package/minify-js.cjs dist",
|
|
24
|
+
"typecheck": "tsc -p . --noEmit",
|
|
25
|
+
"postinstall": "node scripts/postinstall.cjs",
|
|
26
|
+
"prepack": "npm run build:package && node scripts/copy-extension-vsix.cjs",
|
|
27
|
+
"pack:local": "npm pack --pack-destination ../../.tmp"
|
|
28
|
+
},
|
|
29
29
|
"dependencies": {
|
|
30
|
+
"typescript": "^6.0.3",
|
|
30
31
|
"ws": "^8.20.0",
|
|
31
32
|
"zod": "^4.1.12"
|
|
32
33
|
},
|
package/scripts/postinstall.cjs
CHANGED
|
@@ -6,14 +6,15 @@ const { spawnSync } = require("node:child_process");
|
|
|
6
6
|
const packageRoot = path.resolve(__dirname, "..");
|
|
7
7
|
|
|
8
8
|
runBestEffort(path.join(__dirname, "install-windows-launcher.cjs"));
|
|
9
|
-
runBestEffort(path.join(__dirname, "provision-runtime.cjs"), ["
|
|
9
|
+
runBestEffort(path.join(__dirname, "provision-runtime.cjs"), [], { inheritOutput: process.env.AIB_POSTINSTALL_QUIET !== "1" });
|
|
10
10
|
|
|
11
|
-
function runBestEffort(scriptPath, args = []) {
|
|
11
|
+
function runBestEffort(scriptPath, args = [], options = {}) {
|
|
12
|
+
const inheritOutput = options.inheritOutput === true;
|
|
12
13
|
const result = spawnSync(process.execPath, [scriptPath, ...args], {
|
|
13
14
|
cwd: packageRoot,
|
|
14
15
|
env: process.env,
|
|
15
16
|
encoding: "utf8",
|
|
16
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
17
|
+
stdio: inheritOutput ? ["ignore", "inherit", "inherit"] : ["ignore", "pipe", "pipe"],
|
|
17
18
|
windowsHide: true
|
|
18
19
|
});
|
|
19
20
|
|
|
@@ -22,7 +23,7 @@ function runBestEffort(scriptPath, args = []) {
|
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
if (process.env.AIB_POSTINSTALL_STRICT === "1") {
|
|
25
|
-
process.stderr.write(result
|
|
26
|
+
process.stderr.write(result?.stderr || result?.stdout || `postinstall helper failed: ${scriptPath}\n`);
|
|
26
27
|
process.exit(result.status ?? 1);
|
|
27
28
|
}
|
|
28
29
|
}
|
|
@@ -14,6 +14,7 @@ const packageJson = JSON.parse(fs.readFileSync(path.join(packageRoot, "package.j
|
|
|
14
14
|
const platformKey = `${process.platform}-${process.arch}`;
|
|
15
15
|
|
|
16
16
|
const options = parseArgs(process.argv.slice(2));
|
|
17
|
+
const reporter = createReporter(!options.quiet);
|
|
17
18
|
|
|
18
19
|
main().catch((error) => {
|
|
19
20
|
if (!options.quiet) {
|
|
@@ -25,7 +26,7 @@ main().catch((error) => {
|
|
|
25
26
|
async function main() {
|
|
26
27
|
if (runtimeComplete()) {
|
|
27
28
|
if (!options.quiet) {
|
|
28
|
-
|
|
29
|
+
reporter.info(`aib runtime ready: ${path.relative(process.cwd(), runtimesDir) || runtimesDir}`);
|
|
29
30
|
}
|
|
30
31
|
return;
|
|
31
32
|
}
|
|
@@ -49,23 +50,26 @@ async function main() {
|
|
|
49
50
|
|
|
50
51
|
if (!source && !url && !manifestSource && !manifestUrl) {
|
|
51
52
|
if (!options.quiet) {
|
|
52
|
-
|
|
53
|
+
reporter.info("aib runtime not provisioned: set AIB_RUNTIME_ARCHIVE, AIB_RUNTIME_URL, AIB_RUNTIME_MANIFEST, or AIB_RUNTIME_MANIFEST_URL");
|
|
53
54
|
}
|
|
54
55
|
return;
|
|
55
56
|
}
|
|
56
57
|
|
|
58
|
+
reporter.info(`aib runtime: provisioning ${platformKey}`);
|
|
57
59
|
const resolution = source || url
|
|
58
|
-
? { archivePath: source ? path.resolve(source) : await downloadRuntimeArchive(url), expectedSha256: options.sha256 ?? process.env.AIB_RUNTIME_SHA256 ?? null }
|
|
60
|
+
? { archivePath: source ? path.resolve(source) : await downloadRuntimeArchive(url, "runtime archive"), expectedSha256: options.sha256 ?? process.env.AIB_RUNTIME_SHA256 ?? null }
|
|
59
61
|
: await resolveFromManifest(manifestSource, manifestUrl);
|
|
60
62
|
const archivePath = resolution.archivePath;
|
|
61
63
|
if (!fs.existsSync(archivePath)) {
|
|
62
64
|
throw new Error(`Runtime archive not found: ${archivePath}`);
|
|
63
65
|
}
|
|
64
66
|
if (resolution.expectedSha256) {
|
|
67
|
+
reporter.info("aib runtime: verifying checksum");
|
|
65
68
|
assertSha256(archivePath, resolution.expectedSha256);
|
|
66
69
|
}
|
|
67
70
|
|
|
68
71
|
fs.mkdirSync(runtimesDir, { recursive: true });
|
|
72
|
+
reporter.info("aib runtime: extracting archive");
|
|
69
73
|
extractRuntimeArchive(archivePath);
|
|
70
74
|
|
|
71
75
|
if (!runtimeComplete()) {
|
|
@@ -73,7 +77,7 @@ async function main() {
|
|
|
73
77
|
}
|
|
74
78
|
|
|
75
79
|
if (!options.quiet) {
|
|
76
|
-
|
|
80
|
+
reporter.info(`aib runtime provisioned: ${path.relative(process.cwd(), runtimesDir) || runtimesDir}`);
|
|
77
81
|
}
|
|
78
82
|
}
|
|
79
83
|
|
|
@@ -124,6 +128,7 @@ function parseArgs(argv) {
|
|
|
124
128
|
}
|
|
125
129
|
|
|
126
130
|
async function resolveFromManifest(manifestSource, manifestUrl) {
|
|
131
|
+
reporter.info("aib runtime: resolving manifest");
|
|
127
132
|
const manifest = manifestSource
|
|
128
133
|
? JSON.parse(fs.readFileSync(path.resolve(manifestSource), "utf8"))
|
|
129
134
|
: await downloadJson(manifestUrl);
|
|
@@ -146,7 +151,7 @@ async function resolveFromManifest(manifestSource, manifestUrl) {
|
|
|
146
151
|
}
|
|
147
152
|
|
|
148
153
|
async function downloadJson(url) {
|
|
149
|
-
const filePath = await downloadRuntimeArchive(url);
|
|
154
|
+
const filePath = await downloadRuntimeArchive(url, "runtime manifest");
|
|
150
155
|
return JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
151
156
|
}
|
|
152
157
|
|
|
@@ -262,7 +267,7 @@ function assertSha256(filePath, expectedSha256) {
|
|
|
262
267
|
}
|
|
263
268
|
}
|
|
264
269
|
|
|
265
|
-
function downloadRuntimeArchive(url) {
|
|
270
|
+
function downloadRuntimeArchive(url, label = "runtime archive") {
|
|
266
271
|
return new Promise((resolve, reject) => {
|
|
267
272
|
if (!url) {
|
|
268
273
|
reject(new Error("Runtime URL is empty."));
|
|
@@ -276,7 +281,7 @@ function downloadRuntimeArchive(url) {
|
|
|
276
281
|
if (response.statusCode && response.statusCode >= 300 && response.statusCode < 400 && response.headers.location) {
|
|
277
282
|
file.close();
|
|
278
283
|
fs.rmSync(targetPath, { force: true });
|
|
279
|
-
downloadRuntimeArchive(new URL(response.headers.location, url).toString()).then(resolve, reject);
|
|
284
|
+
downloadRuntimeArchive(new URL(response.headers.location, url).toString(), label).then(resolve, reject);
|
|
280
285
|
return;
|
|
281
286
|
}
|
|
282
287
|
if (response.statusCode !== 200) {
|
|
@@ -285,9 +290,15 @@ function downloadRuntimeArchive(url) {
|
|
|
285
290
|
reject(new Error(`Runtime download failed with HTTP ${response.statusCode}: ${url}`));
|
|
286
291
|
return;
|
|
287
292
|
}
|
|
293
|
+
const totalBytes = Number.parseInt(String(response.headers["content-length"] ?? ""), 10);
|
|
294
|
+
const progress = reporter.startProgress(`aib runtime: downloading ${label}`, Number.isFinite(totalBytes) ? totalBytes : null);
|
|
295
|
+
response.on("data", (chunk) => progress.add(chunk.length));
|
|
288
296
|
response.pipe(file);
|
|
289
297
|
file.on("finish", () => {
|
|
290
|
-
file.close(() =>
|
|
298
|
+
file.close(() => {
|
|
299
|
+
progress.done();
|
|
300
|
+
resolve(targetPath);
|
|
301
|
+
});
|
|
291
302
|
});
|
|
292
303
|
});
|
|
293
304
|
request.on("error", (error) => {
|
|
@@ -297,3 +308,70 @@ function downloadRuntimeArchive(url) {
|
|
|
297
308
|
});
|
|
298
309
|
});
|
|
299
310
|
}
|
|
311
|
+
|
|
312
|
+
function createReporter(enabled) {
|
|
313
|
+
const stream = process.stderr;
|
|
314
|
+
const useCarriageReturn = Boolean(stream.isTTY);
|
|
315
|
+
return {
|
|
316
|
+
info(message) {
|
|
317
|
+
if (!enabled) {
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
stream.write(`${message}\n`);
|
|
321
|
+
},
|
|
322
|
+
startProgress(label, totalBytes) {
|
|
323
|
+
if (!enabled) {
|
|
324
|
+
return { add() {}, done() {} };
|
|
325
|
+
}
|
|
326
|
+
let downloadedBytes = 0;
|
|
327
|
+
let lastWriteMs = 0;
|
|
328
|
+
let ended = false;
|
|
329
|
+
const startedMs = Date.now();
|
|
330
|
+
const minIntervalMs = useCarriageReturn ? 750 : 5000;
|
|
331
|
+
const write = (force = false) => {
|
|
332
|
+
const now = Date.now();
|
|
333
|
+
if (!force && now - lastWriteMs < minIntervalMs) {
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
lastWriteMs = now;
|
|
337
|
+
const percent = totalBytes ? Math.min(100, (downloadedBytes / totalBytes) * 100) : null;
|
|
338
|
+
const elapsedSeconds = Math.max(0.001, (now - startedMs) / 1000);
|
|
339
|
+
const rateBytes = downloadedBytes / elapsedSeconds;
|
|
340
|
+
const text = percent === null
|
|
341
|
+
? `${label}: ${formatBytes(downloadedBytes)} downloaded (${formatBytes(rateBytes)}/s)`
|
|
342
|
+
: `${label}: ${percent.toFixed(1)}% ${formatBytes(downloadedBytes)} / ${formatBytes(totalBytes)} (${formatBytes(rateBytes)}/s)`;
|
|
343
|
+
stream.write(useCarriageReturn ? `\r${text}` : `${text}\n`);
|
|
344
|
+
};
|
|
345
|
+
write(true);
|
|
346
|
+
return {
|
|
347
|
+
add(byteCount) {
|
|
348
|
+
downloadedBytes += byteCount;
|
|
349
|
+
write(false);
|
|
350
|
+
},
|
|
351
|
+
done() {
|
|
352
|
+
if (ended) {
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
ended = true;
|
|
356
|
+
write(true);
|
|
357
|
+
stream.write(useCarriageReturn ? "\n" : "");
|
|
358
|
+
}
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
function formatBytes(bytes) {
|
|
365
|
+
if (!Number.isFinite(bytes) || bytes < 0) {
|
|
366
|
+
return "0 B";
|
|
367
|
+
}
|
|
368
|
+
const units = ["B", "KB", "MB", "GB"];
|
|
369
|
+
let value = bytes;
|
|
370
|
+
let unitIndex = 0;
|
|
371
|
+
while (value >= 1024 && unitIndex < units.length - 1) {
|
|
372
|
+
value /= 1024;
|
|
373
|
+
unitIndex += 1;
|
|
374
|
+
}
|
|
375
|
+
const digits = value >= 100 || unitIndex === 0 ? 0 : value >= 10 ? 1 : 2;
|
|
376
|
+
return `${value.toFixed(digits)} ${units[unitIndex]}`;
|
|
377
|
+
}
|