fix console account URL handling (#18809)

This commit is contained in:
Kit Langton 2026-03-23 13:11:38 -04:00 committed by GitHub
parent b556979634
commit 3a0bf2f39f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 70 additions and 10 deletions

View File

@ -10,6 +10,26 @@ const openBrowser = (url: string) => Effect.promise(() => open(url).catch(() =>
const println = (msg: string) => Effect.sync(() => UI.println(msg)) const println = (msg: string) => Effect.sync(() => UI.println(msg))
const dim = (value: string) => UI.Style.TEXT_DIM + value + UI.Style.TEXT_NORMAL
const activeSuffix = (isActive: boolean) => (isActive ? dim(" (active)") : "")
export const formatAccountLabel = (account: { email: string; url: string }, isActive: boolean) =>
`${account.email} ${dim(account.url)}${activeSuffix(isActive)}`
const formatOrgChoiceLabel = (account: { email: string }, org: { name: string }, isActive: boolean) =>
`${org.name} (${account.email})${activeSuffix(isActive)}`
export const formatOrgLine = (
account: { email: string; url: string },
org: { id: string; name: string },
isActive: boolean,
) => {
const dot = isActive ? UI.Style.TEXT_SUCCESS + "●" + UI.Style.TEXT_NORMAL : " "
const name = isActive ? UI.Style.TEXT_HIGHLIGHT_BOLD + org.name + UI.Style.TEXT_NORMAL : org.name
return ` ${dot} ${name} ${dim(account.email)} ${dim(account.url)} ${dim(org.id)}`
}
const isActiveOrgChoice = ( const isActiveOrgChoice = (
active: Option.Option<{ id: AccountID; active_org_id: OrgID | null }>, active: Option.Option<{ id: AccountID; active_org_id: OrgID | null }>,
choice: { accountID: AccountID; orgID: OrgID }, choice: { accountID: AccountID; orgID: OrgID },
@ -76,10 +96,9 @@ const logoutEffect = Effect.fn("logout")(function* (email?: string) {
const opts = accounts.map((a) => { const opts = accounts.map((a) => {
const isActive = Option.isSome(activeID) && activeID.value === a.id const isActive = Option.isSome(activeID) && activeID.value === a.id
const server = UI.Style.TEXT_DIM + a.url + UI.Style.TEXT_NORMAL
return { return {
value: a, value: a,
label: isActive ? `${a.email} ${server}` + UI.Style.TEXT_DIM + " (active)" : `${a.email} ${server}`, label: formatAccountLabel(a, isActive),
} }
}) })
@ -109,9 +128,7 @@ const switchEffect = Effect.fn("switch")(function* () {
const isActive = isActiveOrgChoice(active, { accountID: group.account.id, orgID: org.id }) const isActive = isActiveOrgChoice(active, { accountID: group.account.id, orgID: org.id })
return { return {
value: { orgID: org.id, accountID: group.account.id, label: org.name }, value: { orgID: org.id, accountID: group.account.id, label: org.name },
label: isActive label: formatOrgChoiceLabel(group.account, org, isActive),
? `${org.name} (${group.account.email})` + UI.Style.TEXT_DIM + " (active)"
: `${org.name} (${group.account.email})`,
} }
}), }),
) )
@ -139,15 +156,21 @@ const orgsEffect = Effect.fn("orgs")(function* () {
for (const group of groups) { for (const group of groups) {
for (const org of group.orgs) { for (const org of group.orgs) {
const isActive = isActiveOrgChoice(active, { accountID: group.account.id, orgID: org.id }) const isActive = isActiveOrgChoice(active, { accountID: group.account.id, orgID: org.id })
const dot = isActive ? UI.Style.TEXT_SUCCESS + "●" + UI.Style.TEXT_NORMAL : " " yield* println(formatOrgLine(group.account, org, isActive))
const name = isActive ? UI.Style.TEXT_HIGHLIGHT_BOLD + org.name + UI.Style.TEXT_NORMAL : org.name
const email = UI.Style.TEXT_DIM + group.account.email + UI.Style.TEXT_NORMAL
const id = UI.Style.TEXT_DIM + org.id + UI.Style.TEXT_NORMAL
yield* println(` ${dot} ${name} ${email} ${id}`)
} }
} }
}) })
const openEffect = Effect.fn("open")(function* () {
const service = yield* Account.Service
const active = yield* service.active()
if (Option.isNone(active)) return yield* println("No active account")
const url = active.value.url
yield* openBrowser(url)
yield* Prompt.outro("Opened " + url)
})
export const LoginCommand = cmd({ export const LoginCommand = cmd({
command: "login <url>", command: "login <url>",
describe: false, describe: false,
@ -195,6 +218,15 @@ export const OrgsCommand = cmd({
}, },
}) })
export const OpenCommand = cmd({
command: "open",
describe: false,
async handler() {
UI.empty()
await Account.runPromise((_svc) => openEffect())
},
})
export const ConsoleCommand = cmd({ export const ConsoleCommand = cmd({
command: "console", command: "console",
describe: false, describe: false,
@ -216,6 +248,10 @@ export const ConsoleCommand = cmd({
...OrgsCommand, ...OrgsCommand,
describe: "list orgs", describe: "list orgs",
}) })
.command({
...OpenCommand,
describe: "open active console account",
})
.demandCommand(), .demandCommand(),
async handler() {}, async handler() {},
}) })

View File

@ -0,0 +1,24 @@
import { describe, expect, test } from "bun:test"
import stripAnsi from "strip-ansi"
import { formatAccountLabel, formatOrgLine } from "../../src/cli/cmd/account"
describe("console account display", () => {
test("includes the account url in account labels", () => {
expect(stripAnsi(formatAccountLabel({ email: "one@example.com", url: "https://one.example.com" }, false))).toBe(
"one@example.com https://one.example.com",
)
})
test("includes the active marker in account labels", () => {
expect(stripAnsi(formatAccountLabel({ email: "one@example.com", url: "https://one.example.com" }, true))).toBe(
"one@example.com https://one.example.com (active)",
)
})
test("includes the account url in org rows", () => {
expect(
stripAnsi(formatOrgLine({ email: "one@example.com", url: "https://one.example.com" }, { id: "org-1", name: "One" }, true)),
).toBe(" ● One one@example.com https://one.example.com org-1")
})
})