fix: fixed issue with auth selection in init command
373d448c
3 file(s) · +77 −4
| 35 | 35 | ||
| 36 | 36 | # Bun lockfile - keep but binary cache |
|
| 37 | 37 | bun.lockb |
|
| 38 | + | packages/ui |
| 13 | 13 | } from "@clack/prompts"; |
|
| 14 | 14 | import * as path from "node:path"; |
|
| 15 | 15 | import { findConfig, generateConfigTemplate } from "../lib/config"; |
|
| 16 | - | import { loadCredentials } from "../lib/credentials"; |
|
| 16 | + | import { loadCredentials, listAllCredentials } from "../lib/credentials"; |
|
| 17 | 17 | import { createAgent, createPublication } from "../lib/atproto"; |
|
| 18 | + | import { selectCredential } from "../lib/credential-select"; |
|
| 18 | 19 | import type { FrontmatterMapping, BlueskyConfig } from "../lib/types"; |
|
| 19 | 20 | ||
| 20 | 21 | async function fileExists(filePath: string): Promise<boolean> { |
|
| 186 | 187 | } |
|
| 187 | 188 | ||
| 188 | 189 | let publicationUri: string; |
|
| 189 | - | const credentials = await loadCredentials(); |
|
| 190 | + | let credentials = await loadCredentials(); |
|
| 190 | 191 | ||
| 191 | 192 | if (publicationChoice === "create") { |
|
| 192 | 193 | // Need credentials to create a publication |
|
| 193 | 194 | if (!credentials) { |
|
| 195 | + | // Check if there are multiple identities - if so, prompt to select |
|
| 196 | + | const allCredentials = await listAllCredentials(); |
|
| 197 | + | if (allCredentials.length > 1) { |
|
| 198 | + | credentials = await selectCredential(allCredentials); |
|
| 199 | + | } else if (allCredentials.length === 1) { |
|
| 200 | + | // Single credential exists but couldn't be loaded - try to load it explicitly |
|
| 201 | + | credentials = await selectCredential(allCredentials); |
|
| 202 | + | } else { |
|
| 203 | + | log.error( |
|
| 204 | + | "You must authenticate first. Run 'sequoia login' (recommended) or 'sequoia auth' before creating a publication.", |
|
| 205 | + | ); |
|
| 206 | + | process.exit(1); |
|
| 207 | + | } |
|
| 208 | + | } |
|
| 209 | + | ||
| 210 | + | if (!credentials) { |
|
| 194 | 211 | log.error( |
|
| 195 | - | "You must authenticate first. Run 'sequoia auth' before creating a publication.", |
|
| 212 | + | "Could not load credentials. Try running 'sequoia login' again to re-authenticate.", |
|
| 196 | 213 | ); |
|
| 197 | 214 | process.exit(1); |
|
| 198 | 215 | } |
|
| 206 | 223 | } catch (_error) { |
|
| 207 | 224 | s.stop("Failed to connect"); |
|
| 208 | 225 | log.error( |
|
| 209 | - | "Failed to connect. Check your credentials with 'sequoia auth'.", |
|
| 226 | + | "Failed to connect. Try re-authenticating with 'sequoia login' or 'sequoia auth'.", |
|
| 210 | 227 | ); |
|
| 211 | 228 | process.exit(1); |
|
| 212 | 229 | } |
|
| 1 | + | import { select } from "@clack/prompts"; |
|
| 2 | + | import { getOAuthHandle, getOAuthSession } from "./oauth-store"; |
|
| 3 | + | import { getCredentials } from "./credentials"; |
|
| 4 | + | import type { Credentials } from "./types"; |
|
| 5 | + | import { exitOnCancel } from "./prompts"; |
|
| 6 | + | ||
| 7 | + | /** |
|
| 8 | + | * Prompt user to select from multiple credentials |
|
| 9 | + | */ |
|
| 10 | + | export async function selectCredential( |
|
| 11 | + | allCredentials: Array<{ id: string; type: "app-password" | "oauth" }>, |
|
| 12 | + | ): Promise<Credentials | null> { |
|
| 13 | + | // Build options with friendly labels |
|
| 14 | + | const options = await Promise.all( |
|
| 15 | + | allCredentials.map(async ({ id, type }) => { |
|
| 16 | + | let label = id; |
|
| 17 | + | if (type === "oauth") { |
|
| 18 | + | const handle = await getOAuthHandle(id); |
|
| 19 | + | label = handle ? `${handle} (${id})` : id; |
|
| 20 | + | } |
|
| 21 | + | return { |
|
| 22 | + | value: { id, type }, |
|
| 23 | + | label: `${label} [${type}]`, |
|
| 24 | + | }; |
|
| 25 | + | }), |
|
| 26 | + | ); |
|
| 27 | + | ||
| 28 | + | const selected = exitOnCancel( |
|
| 29 | + | await select({ |
|
| 30 | + | message: "Multiple identities found. Select one:", |
|
| 31 | + | options, |
|
| 32 | + | }), |
|
| 33 | + | ); |
|
| 34 | + | ||
| 35 | + | // Load the full credentials for the selected identity |
|
| 36 | + | if (selected.type === "oauth") { |
|
| 37 | + | const session = await getOAuthSession(selected.id); |
|
| 38 | + | if (session) { |
|
| 39 | + | const handle = await getOAuthHandle(selected.id); |
|
| 40 | + | return { |
|
| 41 | + | type: "oauth", |
|
| 42 | + | did: selected.id, |
|
| 43 | + | handle: handle || selected.id, |
|
| 44 | + | pdsUrl: "https://bsky.social", |
|
| 45 | + | }; |
|
| 46 | + | } |
|
| 47 | + | } else { |
|
| 48 | + | const creds = await getCredentials(selected.id); |
|
| 49 | + | if (creds) { |
|
| 50 | + | return creds; |
|
| 51 | + | } |
|
| 52 | + | } |
|
| 53 | + | ||
| 54 | + | return null; |
|
| 55 | + | } |