fix: fixed issue with auth selection in init command 373d448c
Steve · 2026-02-04 20:03 3 file(s) · +77 −4
.gitignore +1 −0
35 35
36 36
# Bun lockfile - keep but binary cache
37 37
bun.lockb
38 +
packages/ui
packages/cli/src/commands/init.ts +21 −4
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
			}
packages/cli/src/lib/credential-select.ts (added) +55 −0
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 +
}