Skip to content

Commit d9a975c

Browse files
authored
feat: add upgrade command (#19)
1 parent b8311b4 commit d9a975c

File tree

2 files changed

+109
-1
lines changed

2 files changed

+109
-1
lines changed
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import { execSync } from "node:child_process";
2+
import { existsSync } from "node:fs";
3+
4+
import { Command, Flags } from "@oclif/core";
5+
import { getBuildType } from "@layr-labs/ecloud-sdk";
6+
7+
import chalk from "chalk";
8+
9+
// Package being upgraded
10+
const ecloudCLIPackage = "@layr-labs/ecloud-cli";
11+
12+
// Possible PackManagers being covered
13+
export type PackageManager =
14+
| "npm"
15+
| "pnpm"
16+
| "yarn"
17+
| "yarnBerry"
18+
| "bun"
19+
| "unknown";
20+
21+
// Detect package-manager from UA, check for bun as special case
22+
export function detectPM(): PackageManager {
23+
const ua = process.env.npm_config_user_agent ?? "";
24+
25+
if (ua.includes("pnpm/")) return "pnpm";
26+
if (ua.includes("yarn/1")) return "yarn";
27+
if (ua.match(/yarn\/[23]/)) return "yarnBerry";
28+
if (ua.includes("npm/")) return "npm";
29+
30+
if (isBun()) return "bun";
31+
32+
return "unknown";
33+
}
34+
35+
// Detect bun using env falling back to checking for bun binary
36+
function isBun(): boolean {
37+
const execPath = process.execPath?.toLowerCase() ?? "";
38+
if (execPath.includes("bun")) return true;
39+
40+
if (process.env.BUN_INSTALL || process.env.BUN_RUNTIME) return true;
41+
42+
try {
43+
const cmd = process.platform === "win32" ? "where bun" : "which bun";
44+
const p = execSync(cmd).toString().split(/\r?\n/)[0]?.trim();
45+
if (p && existsSync(p)) return true;
46+
} catch {
47+
// ignore
48+
}
49+
50+
return false;
51+
}
52+
53+
// Unified "upgrade global to latest" by manager
54+
export function upgradePackage(packageManager?: string, buildTag = "latest"): void {
55+
const pm = packageManager ?? detectPM();
56+
57+
const cmd = (() => {
58+
switch (pm) {
59+
case "npm":
60+
return `npm install -g ${ecloudCLIPackage}@${buildTag}`;
61+
case "pnpm":
62+
return `pnpm install -g ${ecloudCLIPackage}@${buildTag}`;
63+
case "yarn":
64+
return `yarn global add ${ecloudCLIPackage}@${buildTag}`;
65+
case "yarnBerry":
66+
// best effort, behaves more like a disposable global
67+
return `yarn dlx ${ecloudCLIPackage}@${buildTag}`;
68+
case "bun":
69+
return `bun add -g ${ecloudCLIPackage}@${buildTag}`;
70+
case "unknown":
71+
default:
72+
throw new Error();
73+
}
74+
})();
75+
76+
execSync(cmd, { stdio: "inherit" });
77+
}
78+
79+
// export Upgrade command to perform upgradePackage() call
80+
export default class Upgrade extends Command {
81+
static description = "Upgrade ecloud-cli package";
82+
83+
static flags = {
84+
"package-manager": Flags.string({
85+
required: false,
86+
description: "Explicitly set package-manager to use for upgrade",
87+
options: ["npm", "pnpm", "yarn", "yarnBerry", "bun"],
88+
env: "PACKAGE_MANAGER",
89+
}),
90+
};
91+
92+
async run() {
93+
const { flags } = await this.parse(Upgrade);
94+
95+
const buildType = getBuildType();
96+
const buildTag = buildType === "dev" ? "dev" : "latest";
97+
98+
try {
99+
upgradePackage(flags["package-manager"], buildTag);
100+
this.log(`\n${chalk.green(`Upgrade successful!`)}`);
101+
} catch (e) {
102+
this.log(`\n${chalk.red(`Upgrade failed!`)}`);
103+
this.log(`\n${chalk.red(`Cannot determine package manager to upgrade ${ecloudCLIPackage}.`)}`);
104+
this.log(`\n${chalk.red(`Use ${chalk.yellow("`package-manager`")} flag to instruct upgrade (<supported managers: npm|pnpm|yarn|yarnBerry|bun>).`)}\n`);
105+
throw e;
106+
}
107+
}
108+
}

packages/sdk/src/client/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export { createBillingModule, type BillingModuleConfig } from "./modules/billing
2323

2424
// Export utility functions for CLI use
2525
export { getOrPromptAppID } from "./common/utils/prompts";
26-
export { getEnvironmentConfig, getAvailableEnvironments, isEnvironmentAvailable } from "./common/config/environment";
26+
export { getEnvironmentConfig, getAvailableEnvironments, isEnvironmentAvailable, getBuildType } from "./common/config/environment";
2727
export { isSubscriptionActive } from "./common/utils/billing";
2828

2929
// Export global config functions

0 commit comments

Comments
 (0)