From 373d448c935601cd36d7c6177516842aa6d4292b Mon Sep 17 00:00:00 2001 From: Steve Date: Wed, 4 Feb 2026 20:03:23 -0500 Subject: [PATCH] fix: fixed issue with auth selection in init command --- .gitignore | 1 + packages/cli/src/commands/init.ts | 25 +++++++++-- packages/cli/src/lib/credential-select.ts | 55 +++++++++++++++++++++++ 3 files changed, 77 insertions(+), 4 deletions(-) create mode 100644 packages/cli/src/lib/credential-select.ts diff --git a/.gitignore b/.gitignore index 74e21d7..ea69175 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,4 @@ report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json # Bun lockfile - keep but binary cache bun.lockb +packages/ui diff --git a/packages/cli/src/commands/init.ts b/packages/cli/src/commands/init.ts index 4abdf5b..6476314 100644 --- a/packages/cli/src/commands/init.ts +++ b/packages/cli/src/commands/init.ts @@ -13,8 +13,9 @@ import { } from "@clack/prompts"; import * as path from "node:path"; import { findConfig, generateConfigTemplate } from "../lib/config"; -import { loadCredentials } from "../lib/credentials"; +import { loadCredentials, listAllCredentials } from "../lib/credentials"; import { createAgent, createPublication } from "../lib/atproto"; +import { selectCredential } from "../lib/credential-select"; import type { FrontmatterMapping, BlueskyConfig } from "../lib/types"; async function fileExists(filePath: string): Promise { @@ -186,13 +187,29 @@ export const initCommand = command({ } let publicationUri: string; - const credentials = await loadCredentials(); + let credentials = await loadCredentials(); if (publicationChoice === "create") { // Need credentials to create a publication + if (!credentials) { + // Check if there are multiple identities - if so, prompt to select + const allCredentials = await listAllCredentials(); + if (allCredentials.length > 1) { + credentials = await selectCredential(allCredentials); + } else if (allCredentials.length === 1) { + // Single credential exists but couldn't be loaded - try to load it explicitly + credentials = await selectCredential(allCredentials); + } else { + log.error( + "You must authenticate first. Run 'sequoia login' (recommended) or 'sequoia auth' before creating a publication.", + ); + process.exit(1); + } + } + if (!credentials) { log.error( - "You must authenticate first. Run 'sequoia auth' before creating a publication.", + "Could not load credentials. Try running 'sequoia login' again to re-authenticate.", ); process.exit(1); } @@ -206,7 +223,7 @@ export const initCommand = command({ } catch (_error) { s.stop("Failed to connect"); log.error( - "Failed to connect. Check your credentials with 'sequoia auth'.", + "Failed to connect. Try re-authenticating with 'sequoia login' or 'sequoia auth'.", ); process.exit(1); } diff --git a/packages/cli/src/lib/credential-select.ts b/packages/cli/src/lib/credential-select.ts new file mode 100644 index 0000000..2d0cd1c --- /dev/null +++ b/packages/cli/src/lib/credential-select.ts @@ -0,0 +1,55 @@ +import { select } from "@clack/prompts"; +import { getOAuthHandle, getOAuthSession } from "./oauth-store"; +import { getCredentials } from "./credentials"; +import type { Credentials } from "./types"; +import { exitOnCancel } from "./prompts"; + +/** + * Prompt user to select from multiple credentials + */ +export async function selectCredential( + allCredentials: Array<{ id: string; type: "app-password" | "oauth" }>, +): Promise { + // Build options with friendly labels + const options = await Promise.all( + allCredentials.map(async ({ id, type }) => { + let label = id; + if (type === "oauth") { + const handle = await getOAuthHandle(id); + label = handle ? `${handle} (${id})` : id; + } + return { + value: { id, type }, + label: `${label} [${type}]`, + }; + }), + ); + + const selected = exitOnCancel( + await select({ + message: "Multiple identities found. Select one:", + options, + }), + ); + + // Load the full credentials for the selected identity + if (selected.type === "oauth") { + const session = await getOAuthSession(selected.id); + if (session) { + const handle = await getOAuthHandle(selected.id); + return { + type: "oauth", + did: selected.id, + handle: handle || selected.id, + pdsUrl: "https://bsky.social", + }; + } + } else { + const creds = await getCredentials(selected.id); + if (creds) { + return creds; + } + } + + return null; +} -- 2.51.2