A CLI for publishing standard.site documents to ATProto sequoia.pub
standard site lexicon cli publishing

Clean up remaining auth implementations #17

merged opened by stevedylan.dev targeting main from chore/auth-cleanup

Small refactors and better handling of multiple identities in functions that require auth

Labels

None yet.

assignee

None yet.

Participants 1
AT URI
at://did:plc:ia2zdnhjaokf5lazhxrmj6eu/sh.tangled.repo.pull/3me3ie4j7m622
+70 -16
Diff #1
+3 -2
packages/cli/src/commands/init.ts
··· 325 }; 326 } 327 328 - // Get PDS URL from credentials (already loaded earlier) 329 - const pdsUrl = credentials?.pdsUrl; 330 331 // Generate config file 332 const configContent = generateConfigTemplate({
··· 325 }; 326 } 327 328 + // Get PDS URL from credentials (only available for app-password auth) 329 + const pdsUrl = 330 + credentials?.type === "app-password" ? credentials.pdsUrl : undefined; 331 332 // Generate config file 333 const configContent = generateConfigTemplate({
+3 -2
packages/cli/src/commands/publish.ts
··· 107 type: "oauth", 108 did: selected, 109 handle: handle || selected, 110 - pdsUrl: "https://bsky.social", 111 }; 112 } 113 } else { ··· 246 } 247 248 // Create agent 249 - s.start(`Connecting to ${credentials.pdsUrl}...`); 250 let agent: Awaited<ReturnType<typeof createAgent>> | undefined; 251 try { 252 agent = await createAgent(credentials);
··· 107 type: "oauth", 108 did: selected, 109 handle: handle || selected, 110 }; 111 } 112 } else { ··· 245 } 246 247 // Create agent 248 + const connectingTo = 249 + credentials.type === "oauth" ? credentials.handle : credentials.pdsUrl; 250 + s.start(`Connecting as ${connectingTo}...`); 251 let agent: Awaited<ReturnType<typeof createAgent>> | undefined; 252 try { 253 agent = await createAgent(credentials);
+3 -2
packages/cli/src/commands/sync.ts
··· 93 type: "oauth", 94 did: selected, 95 handle: handle || selected, 96 - pdsUrl: "https://bsky.social", 97 }; 98 } 99 } else { ··· 108 109 // Create agent 110 const s = spinner(); 111 - s.start(`Connecting to ${credentials.pdsUrl}...`); 112 let agent: Awaited<ReturnType<typeof createAgent>> | undefined; 113 try { 114 agent = await createAgent(credentials);
··· 93 type: "oauth", 94 did: selected, 95 handle: handle || selected, 96 }; 97 } 98 } else { ··· 107 108 // Create agent 109 const s = spinner(); 110 + const connectingTo = 111 + credentials.type === "oauth" ? credentials.handle : credentials.pdsUrl; 112 + s.start(`Connecting as ${connectingTo}...`); 113 let agent: Awaited<ReturnType<typeof createAgent>> | undefined; 114 try { 115 agent = await createAgent(credentials);
+60 -5
packages/cli/src/commands/update.ts
··· 11 log, 12 } from "@clack/prompts"; 13 import { findConfig, loadConfig, generateConfigTemplate } from "../lib/config"; 14 - import { loadCredentials } from "../lib/credentials"; 15 import { createAgent, getPublication, updatePublication } from "../lib/atproto"; 16 import { exitOnCancel } from "../lib/prompts"; 17 import type { ··· 438 439 async function updatePublicationFlow(config: PublisherConfig): Promise<void> { 440 // Load credentials 441 - const credentials = await loadCredentials(config.identity); 442 if (!credentials) { 443 - log.error( 444 - "No credentials found. Run 'sequoia auth' or 'sequoia login' first.", 445 ); 446 - process.exit(1); 447 } 448 449 const s = spinner();
··· 11 log, 12 } from "@clack/prompts"; 13 import { findConfig, loadConfig, generateConfigTemplate } from "../lib/config"; 14 + import { 15 + loadCredentials, 16 + listAllCredentials, 17 + getCredentials, 18 + } from "../lib/credentials"; 19 + import { getOAuthHandle, getOAuthSession } from "../lib/oauth-store"; 20 import { createAgent, getPublication, updatePublication } from "../lib/atproto"; 21 import { exitOnCancel } from "../lib/prompts"; 22 import type { ··· 443 444 async function updatePublicationFlow(config: PublisherConfig): Promise<void> { 445 // Load credentials 446 + let credentials = await loadCredentials(config.identity); 447 + 448 if (!credentials) { 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 + }), 472 ); 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 + } 502 } 503 504 const s = spinner();
-1
packages/cli/src/lib/credential-select.ts
··· 41 type: "oauth", 42 did: selected.id, 43 handle: handle || selected.id, 44 - pdsUrl: "https://bsky.social", 45 }; 46 } 47 } else {
··· 41 type: "oauth", 42 did: selected.id, 43 handle: handle || selected.id, 44 }; 45 } 46 } else {
-3
packages/cli/src/lib/credentials.ts
··· 96 type: "oauth", 97 did: profile, 98 handle: handle || profile, 99 - pdsUrl: "https://bsky.social", // Will be resolved from DID doc 100 }; 101 } 102 } ··· 109 type: "oauth", 110 did: match.did, 111 handle: match.handle || match.did, 112 - pdsUrl: "https://bsky.social", 113 }; 114 } 115 ··· 186 type: "oauth", 187 did: oauthDids[0], 188 handle: handle || oauthDids[0], 189 - pdsUrl: "https://bsky.social", 190 }; 191 } 192 }
··· 96 type: "oauth", 97 did: profile, 98 handle: handle || profile, 99 }; 100 } 101 } ··· 108 type: "oauth", 109 did: match.did, 110 handle: match.handle || match.did, 111 }; 112 } 113 ··· 184 type: "oauth", 185 did: oauthDids[0], 186 handle: handle || oauthDids[0], 187 }; 188 } 189 }
+1 -1
packages/cli/src/lib/types.ts
··· 54 } 55 56 // OAuth credentials (references stored OAuth session) 57 export interface OAuthCredentials { 58 type: "oauth"; 59 did: string; 60 handle: string; 61 - pdsUrl: string; 62 } 63 64 // Union type for all credential types
··· 54 } 55 56 // OAuth credentials (references stored OAuth session) 57 + // Note: pdsUrl is not needed for OAuth - the OAuth client resolves PDS from the DID 58 export interface OAuthCredentials { 59 type: "oauth"; 60 did: string; 61 handle: string; 62 } 63 64 // Union type for all credential types

History

2 rounds 0 comments
sign up or login to add to the discussion
2 commits
expand
chore: cleaned up remaining auth implementations
chore: format
expand 0 comments
pull request successfully merged
1 commit
expand
chore: cleaned up remaining auth implementations
1/1 failed
expand
expand 0 comments