Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/cli/bin/binary-entry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,4 @@ if (!process.stdin.isTTY || !process.stdout.isTTY) {
process.env.CI = "true";
}

await runCLI();
await runCLI({ distribution: "binary" });
9 changes: 7 additions & 2 deletions packages/cli/src/cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,15 @@ import { readAuth } from "@/core/auth/index.js";
import { CLIExitError } from "./errors.js";
import { ErrorReporter } from "./telemetry/error-reporter.js";
import { addCommandInfoToErrorReporter } from "./telemetry/index.js";
import type { CLIContext } from "./types.js";
import type { CLIContext, Distribution } from "./types.js";

const __dirname = dirname(fileURLToPath(import.meta.url));

async function runCLI(): Promise<void> {
interface RunCLIOptions {
distribution?: Distribution;
}

async function runCLI(options?: RunCLIOptions): Promise<void> {
ensureNpmAssets(join(__dirname, "../assets"));

// Create error reporter - single instance for the CLI session
Expand All @@ -24,6 +28,7 @@ async function runCLI(): Promise<void> {
const context: CLIContext = {
errorReporter,
isNonInteractive,
distribution: options?.distribution ?? "npm",
};

// Create program with injected context
Expand Down
3 changes: 3 additions & 0 deletions packages/cli/src/cli/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import type { ErrorReporter } from "./telemetry/error-reporter.js";

export type Distribution = "npm" | "binary";

export interface CLIContext {
errorReporter: ErrorReporter;
isNonInteractive: boolean;
distribution: Distribution;
}
9 changes: 7 additions & 2 deletions packages/cli/src/cli/utils/runCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ import { login } from "@/cli/commands/auth/login-flow.js";
import type { CLIContext } from "@/cli/types.js";
import { printBanner } from "@/cli/utils/banner.js";
import { theme } from "@/cli/utils/theme.js";
import { printUpgradeNotificationIfAvailable } from "@/cli/utils/upgradeNotification.js";
import {
printUpgradeNotification,
startUpgradeCheck,
} from "@/cli/utils/upgradeNotification.js";
import { isLoggedIn, readAuth } from "@/core/auth/index.js";
import { isCLIError } from "@/core/errors.js";
import { initAppConfig } from "@/core/project/index.js";
Expand Down Expand Up @@ -76,7 +79,7 @@ export async function runCommand(
} else {
intro(theme.colors.base44OrangeBackground(" Base 44 "));
}
await printUpgradeNotificationIfAvailable();
const upgradeCheckPromise = startUpgradeCheck();

try {
// Check authentication if required
Expand Down Expand Up @@ -105,6 +108,8 @@ export async function runCommand(
}

const result = await commandFn();
await printUpgradeNotification(upgradeCheckPromise, context.distribution);

outro(result.outroMessage || "");

if (result.stdout) {
Expand Down
57 changes: 48 additions & 9 deletions packages/cli/src/cli/utils/upgradeNotification.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,61 @@
import { log } from "@clack/prompts";
import { note } from "@clack/prompts";
import type { Distribution } from "@/cli/types.js";
import { theme } from "@/cli/utils/theme.js";
import type { UpgradeInfo } from "@/cli/utils/version-check.js";
import { checkForUpgrade } from "@/cli/utils/version-check.js";

function formatUpgradeMessage(info: UpgradeInfo): string {
type InstallMethod = "npm" | "brew" | "binary";

function detectInstallMethod(distribution: Distribution): InstallMethod {
if (distribution !== "binary") {
return "npm";
}
const execPath = process.execPath.toLowerCase();
if (execPath.includes("/homebrew/") || execPath.includes("/cellar/")) {
return "brew";
}
return "binary";
}

function getUpgradeInstruction(method: InstallMethod): string {
switch (method) {
case "npm":
return "Run: npm install -g base44@latest";
case "brew":
return "Run: brew upgrade base44";
case "binary":
return "Download Base44 CLI from: https://github.com/base44/cli/releases/latest";
}
}

export function startUpgradeCheck(): Promise<UpgradeInfo | null> {
return checkForUpgrade().catch(() => null);
}

function formatUpgradeMessage(
info: UpgradeInfo,
distribution: Distribution,
): string {
const { shinyOrange } = theme.colors;
const { bold } = theme.styles;
const instruction = getUpgradeInstruction(detectInstallMethod(distribution));

return `${shinyOrange("Update available!")} ${shinyOrange(`${info.currentVersion} → ${info.latestVersion}`)} ${shinyOrange("Run:")} ${bold(shinyOrange("npm install -g base44@latest"))}`;
return [
shinyOrange(
`Update available! ${info.currentVersion} → ${bold(info.latestVersion)}`,
),
shinyOrange(instruction),
].join("\n");
}

export async function printUpgradeNotificationIfAvailable(): Promise<void> {
export async function printUpgradeNotification(
upgradeCheckPromise: Promise<UpgradeInfo | null>,
distribution: Distribution,
): Promise<void> {
try {
const upgradeInfo = await checkForUpgrade();
const upgradeInfo = await upgradeCheckPromise;
if (upgradeInfo) {
log.message(formatUpgradeMessage(upgradeInfo));
note(formatUpgradeMessage(upgradeInfo, distribution));
}
} catch {
// Silently ignore errors
}
} catch {}
}
1 change: 0 additions & 1 deletion packages/cli/tests/cli/version-check.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ describe("upgrade notification", () => {
t.expectResult(result).toSucceed();
t.expectResult(result).toContain("Update available!");
t.expectResult(result).toContain("1.0.0");
t.expectResult(result).toContain("npm install -g base44@latest");
});

it("does not display notification when version is current", async () => {
Expand Down
Loading