@learnrudi/cli 1.7.0 → 1.8.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/index.cjs +137 -38
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -186,7 +186,6 @@ __export(src_exports, {
|
|
|
186
186
|
PACKAGE_KINDS: () => PACKAGE_KINDS2,
|
|
187
187
|
RUNTIMES_DOWNLOAD_BASE: () => RUNTIMES_DOWNLOAD_BASE,
|
|
188
188
|
RUNTIMES_RELEASE_VERSION: () => RUNTIMES_RELEASE_VERSION,
|
|
189
|
-
STACKS_RELEASE_VERSION: () => STACKS_RELEASE_VERSION,
|
|
190
189
|
checkCache: () => checkCache,
|
|
191
190
|
clearCache: () => clearCache,
|
|
192
191
|
computeHash: () => computeHash,
|
|
@@ -383,7 +382,7 @@ async function downloadPackage(pkg, destPath, options = {}) {
|
|
|
383
382
|
}
|
|
384
383
|
onProgress?.({ phase: "downloading", package: pkg.name || pkg.id });
|
|
385
384
|
if (pkg.kind === "stack" || registryPath.includes("/stacks/")) {
|
|
386
|
-
await
|
|
385
|
+
await downloadStackFromGitHub(registryPath, destPath, onProgress);
|
|
387
386
|
return { success: true, path: destPath };
|
|
388
387
|
}
|
|
389
388
|
if (registryPath.endsWith(".md")) {
|
|
@@ -404,45 +403,129 @@ async function downloadPackage(pkg, destPath, options = {}) {
|
|
|
404
403
|
}
|
|
405
404
|
throw new Error(`Unsupported package type: ${registryPath}`);
|
|
406
405
|
}
|
|
407
|
-
async function
|
|
408
|
-
const
|
|
409
|
-
const
|
|
410
|
-
const
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
406
|
+
async function downloadStackFromGitHub(registryPath, destPath, onProgress) {
|
|
407
|
+
const baseUrl = `${GITHUB_RAW_BASE}/${registryPath}`;
|
|
408
|
+
const apiUrl = `https://api.github.com/repos/learn-rudi/registry/contents/${registryPath}`;
|
|
409
|
+
const listResponse = await fetch(apiUrl, {
|
|
410
|
+
headers: {
|
|
411
|
+
"User-Agent": "rudi-cli/2.0",
|
|
412
|
+
"Accept": "application/vnd.github.v3+json"
|
|
413
|
+
}
|
|
414
|
+
});
|
|
415
|
+
if (!listResponse.ok) {
|
|
416
|
+
throw new Error(`Stack not found: ${registryPath}`);
|
|
417
|
+
}
|
|
418
|
+
const contents = await listResponse.json();
|
|
419
|
+
if (!Array.isArray(contents)) {
|
|
420
|
+
throw new Error(`Invalid stack directory: ${registryPath}`);
|
|
421
|
+
}
|
|
422
|
+
const existingItems = /* @__PURE__ */ new Map();
|
|
423
|
+
for (const item of contents) {
|
|
424
|
+
existingItems.set(item.name, item);
|
|
425
|
+
}
|
|
426
|
+
const manifestItem = existingItems.get("manifest.json");
|
|
427
|
+
if (!manifestItem) {
|
|
428
|
+
throw new Error(`Stack missing manifest.json: ${registryPath}`);
|
|
416
429
|
}
|
|
417
|
-
const
|
|
430
|
+
const manifestResponse = await fetch(manifestItem.download_url, {
|
|
431
|
+
headers: { "User-Agent": "rudi-cli/2.0" }
|
|
432
|
+
});
|
|
433
|
+
const manifest = await manifestResponse.json();
|
|
434
|
+
import_fs2.default.writeFileSync(import_path2.default.join(destPath, "manifest.json"), JSON.stringify(manifest, null, 2));
|
|
435
|
+
onProgress?.({ phase: "downloading", file: "manifest.json" });
|
|
436
|
+
const pkgJsonItem = existingItems.get("package.json");
|
|
437
|
+
if (pkgJsonItem) {
|
|
438
|
+
const pkgJsonResponse = await fetch(pkgJsonItem.download_url, {
|
|
439
|
+
headers: { "User-Agent": "rudi-cli/2.0" }
|
|
440
|
+
});
|
|
441
|
+
if (pkgJsonResponse.ok) {
|
|
442
|
+
const pkgJson = await pkgJsonResponse.text();
|
|
443
|
+
import_fs2.default.writeFileSync(import_path2.default.join(destPath, "package.json"), pkgJson);
|
|
444
|
+
onProgress?.({ phase: "downloading", file: "package.json" });
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
const envExampleItem = existingItems.get(".env.example");
|
|
448
|
+
if (envExampleItem) {
|
|
449
|
+
const envResponse = await fetch(envExampleItem.download_url, {
|
|
450
|
+
headers: { "User-Agent": "rudi-cli/2.0" }
|
|
451
|
+
});
|
|
452
|
+
if (envResponse.ok) {
|
|
453
|
+
const envContent = await envResponse.text();
|
|
454
|
+
import_fs2.default.writeFileSync(import_path2.default.join(destPath, ".env.example"), envContent);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
const tsconfigItem = existingItems.get("tsconfig.json");
|
|
458
|
+
if (tsconfigItem) {
|
|
459
|
+
const tsconfigResponse = await fetch(tsconfigItem.download_url, {
|
|
460
|
+
headers: { "User-Agent": "rudi-cli/2.0" }
|
|
461
|
+
});
|
|
462
|
+
if (tsconfigResponse.ok) {
|
|
463
|
+
const tsconfig = await tsconfigResponse.text();
|
|
464
|
+
import_fs2.default.writeFileSync(import_path2.default.join(destPath, "tsconfig.json"), tsconfig);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
const requirementsItem = existingItems.get("requirements.txt");
|
|
468
|
+
if (requirementsItem) {
|
|
469
|
+
const reqResponse = await fetch(requirementsItem.download_url, {
|
|
470
|
+
headers: { "User-Agent": "rudi-cli/2.0" }
|
|
471
|
+
});
|
|
472
|
+
if (reqResponse.ok) {
|
|
473
|
+
const requirements = await reqResponse.text();
|
|
474
|
+
import_fs2.default.writeFileSync(import_path2.default.join(destPath, "requirements.txt"), requirements);
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
const sourceDirs = ["src", "dist", "node", "python", "lib"];
|
|
478
|
+
for (const dirName of sourceDirs) {
|
|
479
|
+
const dirItem = existingItems.get(dirName);
|
|
480
|
+
if (dirItem && dirItem.type === "dir") {
|
|
481
|
+
onProgress?.({ phase: "downloading", directory: dirName });
|
|
482
|
+
await downloadDirectoryFromGitHub(
|
|
483
|
+
`${baseUrl}/${dirName}`,
|
|
484
|
+
import_path2.default.join(destPath, dirName),
|
|
485
|
+
onProgress
|
|
486
|
+
);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
async function downloadDirectoryFromGitHub(dirUrl, destDir, onProgress) {
|
|
491
|
+
const apiUrl = dirUrl.replace("https://raw.githubusercontent.com/", "https://api.github.com/repos/").replace("/main/", "/contents/");
|
|
418
492
|
try {
|
|
419
|
-
const response = await fetch(
|
|
493
|
+
const response = await fetch(apiUrl, {
|
|
420
494
|
headers: {
|
|
421
495
|
"User-Agent": "rudi-cli/2.0",
|
|
422
|
-
"Accept": "application/
|
|
496
|
+
"Accept": "application/vnd.github.v3+json"
|
|
423
497
|
}
|
|
424
498
|
});
|
|
425
499
|
if (!response.ok) {
|
|
426
|
-
|
|
500
|
+
return;
|
|
427
501
|
}
|
|
428
|
-
const
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
if (import_fs2.default.existsSync(destPath)) {
|
|
432
|
-
import_fs2.default.rmSync(destPath, { recursive: true });
|
|
502
|
+
const contents = await response.json();
|
|
503
|
+
if (!Array.isArray(contents)) {
|
|
504
|
+
return;
|
|
433
505
|
}
|
|
434
|
-
import_fs2.default.
|
|
435
|
-
|
|
436
|
-
execSync7(`tar -xzf "${tempFile}" -C "${destPath}"`, {
|
|
437
|
-
stdio: "pipe"
|
|
438
|
-
});
|
|
439
|
-
import_fs2.default.unlinkSync(tempFile);
|
|
440
|
-
onProgress?.({ phase: "complete", package: stackName, path: destPath });
|
|
441
|
-
} catch (error) {
|
|
442
|
-
if (import_fs2.default.existsSync(tempFile)) {
|
|
443
|
-
import_fs2.default.unlinkSync(tempFile);
|
|
506
|
+
if (!import_fs2.default.existsSync(destDir)) {
|
|
507
|
+
import_fs2.default.mkdirSync(destDir, { recursive: true });
|
|
444
508
|
}
|
|
445
|
-
|
|
509
|
+
for (const item of contents) {
|
|
510
|
+
if (item.type === "file") {
|
|
511
|
+
const fileResponse = await fetch(item.download_url, {
|
|
512
|
+
headers: { "User-Agent": "rudi-cli/2.0" }
|
|
513
|
+
});
|
|
514
|
+
if (fileResponse.ok) {
|
|
515
|
+
const content = await fileResponse.text();
|
|
516
|
+
import_fs2.default.writeFileSync(import_path2.default.join(destDir, item.name), content);
|
|
517
|
+
onProgress?.({ phase: "downloading", file: item.name });
|
|
518
|
+
}
|
|
519
|
+
} else if (item.type === "dir") {
|
|
520
|
+
await downloadDirectoryFromGitHub(
|
|
521
|
+
item.url.replace("https://api.github.com/repos/", "https://raw.githubusercontent.com/").replace("/contents/", "/main/"),
|
|
522
|
+
import_path2.default.join(destDir, item.name),
|
|
523
|
+
onProgress
|
|
524
|
+
);
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
} catch (error) {
|
|
528
|
+
console.error(`Warning: Could not download ${dirUrl}: ${error.message}`);
|
|
446
529
|
}
|
|
447
530
|
}
|
|
448
531
|
async function downloadRuntime(runtime, version, destPath, options = {}) {
|
|
@@ -720,7 +803,7 @@ async function computeHash(filePath) {
|
|
|
720
803
|
stream.on("error", reject);
|
|
721
804
|
});
|
|
722
805
|
}
|
|
723
|
-
var import_fs2, import_path2, import_crypto, DEFAULT_REGISTRY_URL, RUNTIMES_DOWNLOAD_BASE, CACHE_TTL, PACKAGE_KINDS2, KIND_PLURALS, GITHUB_RAW_BASE,
|
|
806
|
+
var import_fs2, import_path2, import_crypto, DEFAULT_REGISTRY_URL, RUNTIMES_DOWNLOAD_BASE, CACHE_TTL, PACKAGE_KINDS2, KIND_PLURALS, GITHUB_RAW_BASE, RUNTIMES_RELEASE_VERSION;
|
|
724
807
|
var init_src2 = __esm({
|
|
725
808
|
"../packages/registry-client/src/index.js"() {
|
|
726
809
|
import_fs2 = __toESM(require("fs"), 1);
|
|
@@ -735,8 +818,6 @@ var init_src2 = __esm({
|
|
|
735
818
|
binary: "binaries"
|
|
736
819
|
};
|
|
737
820
|
GITHUB_RAW_BASE = "https://raw.githubusercontent.com/learn-rudi/registry/main";
|
|
738
|
-
STACKS_DOWNLOAD_BASE = "https://github.com/learn-rudi/registry/releases/download";
|
|
739
|
-
STACKS_RELEASE_VERSION = "stacks-v1.0.0";
|
|
740
821
|
RUNTIMES_RELEASE_VERSION = "v1.0.0";
|
|
741
822
|
}
|
|
742
823
|
});
|
|
@@ -16303,8 +16384,25 @@ async function loadManifest(installPath) {
|
|
|
16303
16384
|
return null;
|
|
16304
16385
|
}
|
|
16305
16386
|
}
|
|
16387
|
+
function getBundledBinary(runtime, binary) {
|
|
16388
|
+
const platform = process.platform;
|
|
16389
|
+
const rudiHome = process.env.RUDI_HOME || path8.join(process.env.HOME || process.env.USERPROFILE, ".rudi");
|
|
16390
|
+
if (runtime === "node") {
|
|
16391
|
+
const npmPath = platform === "win32" ? path8.join(rudiHome, "runtimes", "node", "npm.cmd") : path8.join(rudiHome, "runtimes", "node", "bin", "npm");
|
|
16392
|
+
if (require("fs").existsSync(npmPath)) {
|
|
16393
|
+
return npmPath;
|
|
16394
|
+
}
|
|
16395
|
+
}
|
|
16396
|
+
if (runtime === "python") {
|
|
16397
|
+
const pipPath = platform === "win32" ? path8.join(rudiHome, "runtimes", "python", "Scripts", "pip.exe") : path8.join(rudiHome, "runtimes", "python", "bin", "pip3");
|
|
16398
|
+
if (require("fs").existsSync(pipPath)) {
|
|
16399
|
+
return pipPath;
|
|
16400
|
+
}
|
|
16401
|
+
}
|
|
16402
|
+
return binary;
|
|
16403
|
+
}
|
|
16306
16404
|
async function installDependencies(stackPath, manifest) {
|
|
16307
|
-
const runtime = manifest?.runtime || "node";
|
|
16405
|
+
const runtime = manifest?.runtime || manifest?.mcp?.runtime || "node";
|
|
16308
16406
|
try {
|
|
16309
16407
|
if (runtime === "node") {
|
|
16310
16408
|
const packageJsonPath = path8.join(stackPath, "package.json");
|
|
@@ -16319,11 +16417,11 @@ async function installDependencies(stackPath, manifest) {
|
|
|
16319
16417
|
return { installed: false, reason: "Dependencies already installed" };
|
|
16320
16418
|
} catch {
|
|
16321
16419
|
}
|
|
16420
|
+
const npmCmd = getBundledBinary("node", "npm");
|
|
16322
16421
|
console.log(` Installing npm dependencies...`);
|
|
16323
|
-
(0, import_child_process2.execSync)("
|
|
16422
|
+
(0, import_child_process2.execSync)(`"${npmCmd}" install --production`, {
|
|
16324
16423
|
cwd: stackPath,
|
|
16325
16424
|
stdio: "pipe"
|
|
16326
|
-
// Suppress output
|
|
16327
16425
|
});
|
|
16328
16426
|
return { installed: true };
|
|
16329
16427
|
} else if (runtime === "python") {
|
|
@@ -16333,8 +16431,9 @@ async function installDependencies(stackPath, manifest) {
|
|
|
16333
16431
|
} catch {
|
|
16334
16432
|
return { installed: false, reason: "No requirements.txt" };
|
|
16335
16433
|
}
|
|
16434
|
+
const pipCmd = getBundledBinary("python", "pip");
|
|
16336
16435
|
console.log(` Installing pip dependencies...`);
|
|
16337
|
-
(0, import_child_process2.execSync)("
|
|
16436
|
+
(0, import_child_process2.execSync)(`"${pipCmd}" install -r requirements.txt`, {
|
|
16338
16437
|
cwd: stackPath,
|
|
16339
16438
|
stdio: "pipe"
|
|
16340
16439
|
});
|