mirror of
https://github.com/nestriness/nestri.git
synced 2026-08-01 17:34:15 +03:00
feat: Add JS package manager support
This commit is contained in:
@@ -54,6 +54,41 @@ export namespace Installation {
|
||||
if (process.execPath.includes(path.join(".nestri", "bin"))) return "curl";
|
||||
if (process.execPath.includes(path.join(".local", "bin"))) return "curl";
|
||||
|
||||
const exec = process.execPath.toLowerCase();
|
||||
const checks = [
|
||||
{
|
||||
name: "npm" as const,
|
||||
command: () => $`npm list -g --depth=0`.throws(false).text(),
|
||||
},
|
||||
{
|
||||
name: "yarn" as const,
|
||||
command: () => $`yarn global list`.throws(false).text(),
|
||||
},
|
||||
{
|
||||
name: "pnpm" as const,
|
||||
command: () => $`pnpm list -g --depth=0`.throws(false).text(),
|
||||
},
|
||||
{
|
||||
name: "bun" as const,
|
||||
command: () => $`bun pm ls -g`.throws(false).text(),
|
||||
},
|
||||
];
|
||||
|
||||
checks.sort((a, b) => {
|
||||
const aMatches = exec.includes(a.name);
|
||||
const bMatches = exec.includes(b.name);
|
||||
if (aMatches && !bMatches) return -1;
|
||||
if (!aMatches && bMatches) return 1;
|
||||
return 0;
|
||||
});
|
||||
|
||||
for (const check of checks) {
|
||||
const output = await check.command();
|
||||
if (output.includes("@nestri/studio")) {
|
||||
return check.name;
|
||||
}
|
||||
}
|
||||
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
@@ -73,6 +108,15 @@ export namespace Installation {
|
||||
VERSION: target,
|
||||
});
|
||||
break;
|
||||
case "npm":
|
||||
cmd = $`npm install -g @nestri/studio@${target}`;
|
||||
break;
|
||||
case "pnpm":
|
||||
cmd = $`pnpm install -g @nestri/studio@${target}`;
|
||||
break;
|
||||
case "bun":
|
||||
cmd = $`bun install -g @nestri/studio@${target}`;
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unknown method: ${method}`);
|
||||
}
|
||||
@@ -96,15 +140,13 @@ export namespace Installation {
|
||||
export const USER_AGENT = `nestri/${CHANNEL}/${VERSION}`;
|
||||
|
||||
export async function latest() {
|
||||
const res = await fetch(
|
||||
`https://api.github.com/repos/nestrilabs/nestri/releases/latest`,
|
||||
);
|
||||
|
||||
if (!res.ok) {
|
||||
throw new Error(`GitHub API error: ${res.statusText}`);
|
||||
}
|
||||
|
||||
const data = await res.json();
|
||||
return data.tag_name?.replace(/^v/, ""); // removes leading "v" if present
|
||||
const [major] = VERSION.split(".").map((x) => Number(x));
|
||||
const channel = CHANNEL === "latest" ? `latest-${major}` : CHANNEL;
|
||||
return fetch(`https://registry.npmjs.org/@nestri/studio/${channel}`)
|
||||
.then((res) => {
|
||||
if (!res.ok) throw new Error(res.statusText);
|
||||
return res.json();
|
||||
})
|
||||
.then((data: any) => data.version);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,16 @@ import { Log } from "@nestri/core/utils/log";
|
||||
import { NamedError } from "@nestri/core/utils/error";
|
||||
import { Installation } from "@nestri/core/installation/index";
|
||||
|
||||
/**
|
||||
*
|
||||
* So, the utility of this is:
|
||||
* 1. To run the API, and Auth servers (locally or in the cloud) using docker sockets
|
||||
* 2. To provide a CLI interface for managing GPUs, games, and other resources (Studio) thru an ssh utility
|
||||
* 3. To build client and package it into a docker container for local or cloud deployment
|
||||
* 4.
|
||||
*
|
||||
*/
|
||||
|
||||
process.on("unhandledRejection", (e) => {
|
||||
Log.Default.error("rejection", {
|
||||
e: e instanceof Error ? e.message : e,
|
||||
|
||||
Reference in New Issue
Block a user