UNPKG

convex

Version:

Client for the Convex Cloud

215 lines (200 loc) 6.14 kB
import { ChalkInstance } from "chalk"; import { logMessage } from "../../bundler/log.js"; import { chalkStderr } from "chalk"; import { deploymentDashboardUrl, deploymentDashboardUrlPage, } from "./dashboard.js"; import type { DeploymentType, DetailedDeploymentCredentials } from "./api.js"; type AnnouncedDeployment = Omit<DetailedDeploymentCredentials, "adminKey">; function stylesFor(dtype: DeploymentType | null): { label: string; bg: string; fg: string; bar: string; } { switch (dtype) { case "prod": return { label: "Production", bg: "#eacae7", fg: "#641aa9", bar: "#8b21f1", }; case "dev": return { label: "Development", bg: "#d2ecbb", fg: "#2b6536", bar: "#3ea34b", }; case "local": return { label: "Local", bg: "#d2ecbb", fg: "#2b6536", bar: "#3ea34b", }; case "anonymous": return { label: "Local", bg: "#d2ecbb", fg: "#2b6536", bar: "#3ea34b", }; case "preview": return { label: "Preview", bg: "#fcedd7", fg: "#933615", bar: "#e25706", }; case "custom": return { label: "Custom", bg: "#dfe2e9", fg: "#292b30", bar: "#989aa3", }; case null: // Self-hosted / --url + --admin-key return { label: "", bg: "#dfe2e9", fg: "#292b30", bar: "#989aa3", }; default: dtype satisfies never; return { label: "Unknown", bg: "#dfe2e9", fg: "#292b30", bar: "#989aa3", }; } } function osc8Link(text: string, url: string): string { if (!process.stderr.isTTY) return text; return `\x1b]8;;${url}\x1b\\${text}\x1b]8;;\x1b\\`; } export type DeploymentAnnouncementHeader = | "Developing against deployment:" | "Showing logs of deployment:" | "Deploying code to deployment:" | null; export function formatTargetedDeployment( header: DeploymentAnnouncementHeader, creds: AnnouncedDeployment, chalk: ChalkInstance, ): string { const fields = creds.deploymentFields; const style = stylesFor(fields?.deploymentType ?? null); const bar = chalk.hex(style.bar)("▌"); const tag = chalk.level > 0 ? chalk.bold.bgHex(style.bg).hex(style.fg)(` ${style.label} `) : `[${style.label}]`; const urlStyled = chalk.dim.underline(osc8Link(creds.url, creds.url)); const dashUrl = dashboardUrlFor(fields); const dashboardSuffix = dashUrl ? process.stderr.isTTY ? ` (${osc8Link(chalk.underline("dashboard"), dashUrl)})` : ` (dashboard: ${dashUrl})` : ""; let refLine: string | null; if (fields === null) { refLine = null; } else if (fields.deploymentType === "local") { const port = portFromUrl(creds.url); const portPart = port !== null ? `Port ${chalk.bold(port)}` : creds.url; const projectPart = fields.teamSlug && fields.projectSlug ? ` • in ${fields.teamSlug}${chalk.dim(":")}${fields.projectSlug}` : ""; refLine = `${tag} ${portPart}${projectPart}${dashboardSuffix}`; } else if (fields.deploymentType === "anonymous") { const port = portFromUrl(creds.url); const portPart = port !== null ? `Port ${chalk.bold(port)}` : creds.url; refLine = `${tag} ${portPart} • No Convex account (run ${chalk.bold("npx convex login")} to link to a project)`; } else { // We display the deployment using the `team:project:ref` // syntax so that users can copy-paste the value when using `--deployment`. const { dimPrefix, boldTail, defaultAlias } = deploymentRefFor(fields); const aliasPart = defaultAlias === null ? "" : ` ${chalk.dim("(")}${chalk.bold(defaultAlias)}${chalk.dim(")")}`; refLine = `${tag} ${chalk.dim(dimPrefix)}${chalk.bold(boldTail)}${aliasPart}${dashboardSuffix}`; } return [ header === null ? null : `${bar} ${header}`, refLine === null ? null : `${bar} ${refLine}`, `${bar} ${chalk.dim("└─")} ${urlStyled}`, ] .filter((x) => x !== null) .join("\n"); } function portFromUrl(url: string): string | null { try { const parsed = new URL(url); return parsed.port || null; } catch { return null; } } export function announceDeploymentTarget( header: DeploymentAnnouncementHeader, creds: AnnouncedDeployment, ) { logMessage(formatTargetedDeployment(header, creds, chalkStderr)); } function deploymentRefFor( fields: DetailedDeploymentCredentials["deploymentFields"] | null, ): { dimPrefix: string; boldTail: string; // For default dev/prod deployments, the short-form alias to append after // the reference in parens (e.g. "dev" or "prod"). `null` otherwise. defaultAlias: "dev" | "prod" | null; } { if (fields === null) { return { dimPrefix: "", boldTail: "", defaultAlias: null }; } if (fields.deploymentType === "local") { return { dimPrefix: "", boldTail: "local", defaultAlias: null }; } const isCloud = fields.deploymentType === "dev" || fields.deploymentType === "preview" || fields.deploymentType === "prod" || fields.deploymentType === "custom"; if (isCloud && fields.teamSlug && fields.projectSlug && fields.reference) { const defaultAlias = fields.isDefault && (fields.deploymentType === "dev" || fields.deploymentType === "prod") ? fields.deploymentType : null; return { dimPrefix: `${fields.teamSlug}:${fields.projectSlug}:`, boldTail: fields.reference, defaultAlias, }; } return { dimPrefix: "", boldTail: fields.deploymentName, defaultAlias: null }; } function dashboardUrlFor( fields: DetailedDeploymentCredentials["deploymentFields"] | null, ): string | null { if (fields === null || fields.deploymentType === "anonymous") { return null; } if (fields.teamSlug && fields.projectSlug) { return deploymentDashboardUrl( fields.teamSlug, fields.projectSlug, fields.deploymentName, ); } return deploymentDashboardUrlPage(fields.deploymentName, ""); }