chore: cleaned up remaining auth implementations 4949b8ce
Steve · 2026-02-04 22:49 7 file(s) · +74 −16
packages/cli/src/commands/init.ts +3 −2
325 325
			};
326 326
		}
327 327
328 -
		// Get PDS URL from credentials (already loaded earlier)
329 -
		const pdsUrl = credentials?.pdsUrl;
328 +
		// Get PDS URL from credentials (only available for app-password auth)
329 +
		const pdsUrl =
330 +
			credentials?.type === "app-password" ? credentials.pdsUrl : undefined;
330 331
331 332
		// Generate config file
332 333
		const configContent = generateConfigTemplate({
packages/cli/src/commands/publish.ts +5 −2
107 107
						type: "oauth",
108 108
						did: selected,
109 109
						handle: handle || selected,
110 -
						pdsUrl: "https://bsky.social",
111 110
					};
112 111
				}
113 112
			} else {
246 245
		}
247 246
248 247
		// Create agent
249 -
		s.start(`Connecting to ${credentials.pdsUrl}...`);
248 +
		const connectingTo =
249 +
			credentials.type === "oauth"
250 +
				? credentials.handle
251 +
				: credentials.pdsUrl;
252 +
		s.start(`Connecting as ${connectingTo}...`);
250 253
		let agent: Awaited<ReturnType<typeof createAgent>> | undefined;
251 254
		try {
252 255
			agent = await createAgent(credentials);
packages/cli/src/commands/sync.ts +5 −2
93 93
						type: "oauth",
94 94
						did: selected,
95 95
						handle: handle || selected,
96 -
						pdsUrl: "https://bsky.social",
97 96
					};
98 97
				}
99 98
			} else {
108 107
109 108
		// Create agent
110 109
		const s = spinner();
111 -
		s.start(`Connecting to ${credentials.pdsUrl}...`);
110 +
		const connectingTo =
111 +
			credentials.type === "oauth"
112 +
				? credentials.handle
113 +
				: credentials.pdsUrl;
114 +
		s.start(`Connecting as ${connectingTo}...`);
112 115
		let agent: Awaited<ReturnType<typeof createAgent>> | undefined;
113 116
		try {
114 117
			agent = await createAgent(credentials);
packages/cli/src/commands/update.ts +60 −5
11 11
	log,
12 12
} from "@clack/prompts";
13 13
import { findConfig, loadConfig, generateConfigTemplate } from "../lib/config";
14 -
import { loadCredentials } from "../lib/credentials";
14 +
import {
15 +
	loadCredentials,
16 +
	listAllCredentials,
17 +
	getCredentials,
18 +
} from "../lib/credentials";
19 +
import { getOAuthHandle, getOAuthSession } from "../lib/oauth-store";
15 20
import { createAgent, getPublication, updatePublication } from "../lib/atproto";
16 21
import { exitOnCancel } from "../lib/prompts";
17 22
import type {
438 443
439 444
async function updatePublicationFlow(config: PublisherConfig): Promise<void> {
440 445
	// Load credentials
441 -
	const credentials = await loadCredentials(config.identity);
446 +
	let credentials = await loadCredentials(config.identity);
447 +
442 448
	if (!credentials) {
443 -
		log.error(
444 -
			"No credentials found. Run 'sequoia auth' or 'sequoia login' first.",
449 +
		const identities = await listAllCredentials();
450 +
		if (identities.length === 0) {
451 +
			log.error(
452 +
				"No credentials found. Run 'sequoia login' or 'sequoia auth' first.",
453 +
			);
454 +
			process.exit(1);
455 +
		}
456 +
457 +
		// Build labels with handles for OAuth sessions
458 +
		const options = await Promise.all(
459 +
			identities.map(async (cred) => {
460 +
				if (cred.type === "oauth") {
461 +
					const handle = await getOAuthHandle(cred.id);
462 +
					return {
463 +
						value: cred.id,
464 +
						label: `${handle || cred.id} (OAuth)`,
465 +
					};
466 +
				}
467 +
				return {
468 +
					value: cred.id,
469 +
					label: `${cred.id} (App Password)`,
470 +
				};
471 +
			}),
445 472
		);
446 -
		process.exit(1);
473 +
474 +
		log.info("Multiple identities found. Select one to use:");
475 +
		const selected = exitOnCancel(
476 +
			await select({
477 +
				message: "Identity:",
478 +
				options,
479 +
			}),
480 +
		);
481 +
482 +
		// Load the selected credentials
483 +
		const selectedCred = identities.find((c) => c.id === selected);
484 +
		if (selectedCred?.type === "oauth") {
485 +
			const session = await getOAuthSession(selected);
486 +
			if (session) {
487 +
				const handle = await getOAuthHandle(selected);
488 +
				credentials = {
489 +
					type: "oauth",
490 +
					did: selected,
491 +
					handle: handle || selected,
492 +
				};
493 +
			}
494 +
		} else {
495 +
			credentials = await getCredentials(selected);
496 +
		}
497 +
498 +
		if (!credentials) {
499 +
			log.error("Failed to load selected credentials.");
500 +
			process.exit(1);
501 +
		}
447 502
	}
448 503
449 504
	const s = spinner();
packages/cli/src/lib/credential-select.ts +0 −1
41 41
				type: "oauth",
42 42
				did: selected.id,
43 43
				handle: handle || selected.id,
44 -
				pdsUrl: "https://bsky.social",
45 44
			};
46 45
		}
47 46
	} else {
packages/cli/src/lib/credentials.ts +0 −3
96 96
				type: "oauth",
97 97
				did: profile,
98 98
				handle: handle || profile,
99 -
				pdsUrl: "https://bsky.social", // Will be resolved from DID doc
100 99
			};
101 100
		}
102 101
	}
109 108
			type: "oauth",
110 109
			did: match.did,
111 110
			handle: match.handle || match.did,
112 -
			pdsUrl: "https://bsky.social",
113 111
		};
114 112
	}
115 113
186 184
					type: "oauth",
187 185
					did: oauthDids[0],
188 186
					handle: handle || oauthDids[0],
189 -
					pdsUrl: "https://bsky.social",
190 187
				};
191 188
			}
192 189
		}
packages/cli/src/lib/types.ts +1 −1
54 54
}
55 55
56 56
// OAuth credentials (references stored OAuth session)
57 +
// Note: pdsUrl is not needed for OAuth - the OAuth client resolves PDS from the DID
57 58
export interface OAuthCredentials {
58 59
	type: "oauth";
59 60
	did: string;
60 61
	handle: string;
61 -
	pdsUrl: string;
62 62
}
63 63
64 64
// Union type for all credential types