open source is social v-it.org
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

login: local-only session check, noop handleResolver for restoreAgent

- Add checkSession(did) for fast local session validation (read
session.json, check token expiry, no network/OAuth client needed)
- Use checkSession in login's "already logged in?" path instead of
restoreAgent, eliminating unnecessary network round-trip
- Pass noop handleResolver to NodeOAuthClient in restoreAgent() to
prevent AtprotoHandleResolverNode from holding the event loop open
- Extract shared clientMetadata constant to DRY up OAuth client config

+38 -19
+5 -7
src/cmd/login.js
··· 5 5 import { spawn } from 'node:child_process'; 6 6 import { createInterface } from 'node:readline'; 7 7 import { loadConfig, saveConfig } from '../lib/config.js'; 8 - import { createOAuthClient, createSessionStore, createStore, restoreAgent } from '../lib/oauth.js'; 8 + import { createOAuthClient, createSessionStore, createStore, checkSession } from '../lib/oauth.js'; 9 9 10 10 export default function register(program) { 11 11 program ··· 24 24 if (!force) { 25 25 const existing = loadConfig(); 26 26 if (existing.did) { 27 - try { 28 - console.log('Checking session...'); 29 - await restoreAgent(existing.did); 30 - console.log(`Already logged in as ${existing.did}`); 27 + console.log('Checking session...'); 28 + const validDid = checkSession(existing.did); 29 + if (validDid) { 30 + console.log(`Already logged in as ${validDid}`); 31 31 return; 32 - } catch { 33 - // session invalid - fall through to OAuth 34 32 } 35 33 } 36 34 }
+33 -12
src/lib/oauth.js
··· 14 14 del: async () => {}, 15 15 }; 16 16 17 + const clientMetadata = { 18 + client_id: 'https://v-it.org/client-metadata.json', 19 + client_name: 'vit CLI', 20 + application_type: 'native', 21 + grant_types: ['authorization_code', 'refresh_token'], 22 + response_types: ['code'], 23 + scope: 'atproto transition:generic', 24 + token_endpoint_auth_method: 'none', 25 + dpop_bound_access_tokens: true, 26 + client_uri: 'https://v-it.org', 27 + }; 28 + 17 29 export function createStore() { 18 30 const map = new Map(); 19 31 ··· 49 61 }; 50 62 } 51 63 64 + export function checkSession(did) { 65 + try { 66 + const raw = readFileSync(configPath('session.json'), 'utf-8'); 67 + const data = JSON.parse(raw); 68 + const expiresAt = data[did]?.tokenSet?.expires_at; 69 + if (!expiresAt) return null; 70 + return new Date(expiresAt) > new Date() ? did : null; 71 + } catch { 72 + return null; 73 + } 74 + } 75 + 52 76 export function createOAuthClient({ stateStore, sessionStore, redirectUri }) { 53 77 return new NodeOAuthClient({ 54 78 requestLock, 55 79 clientMetadata: { 56 - client_id: 'https://v-it.org/client-metadata.json', 57 - client_name: 'vit CLI', 58 - application_type: 'native', 59 - grant_types: ['authorization_code', 'refresh_token'], 60 - response_types: ['code'], 80 + ...clientMetadata, 61 81 redirect_uris: [redirectUri], 62 - scope: 'atproto transition:generic', 63 - token_endpoint_auth_method: 'none', 64 - dpop_bound_access_tokens: true, 65 - client_uri: 'https://v-it.org', 66 82 }, 67 83 stateStore, 68 84 sessionStore, ··· 71 87 72 88 export async function restoreAgent(did) { 73 89 const sessionStore = createSessionStore(); 74 - const client = createOAuthClient({ 90 + const client = new NodeOAuthClient({ 91 + handleResolver: { resolve() { throw new Error('handle resolution not needed for restore'); } }, 92 + requestLock, 93 + clientMetadata: { 94 + ...clientMetadata, 95 + redirect_uris: ['http://127.0.0.1'], 96 + }, 97 + stateStore: noopStore, 75 98 sessionStore, 76 - stateStore: noopStore, 77 - redirectUri: 'http://127.0.0.1', 78 99 }); 79 100 const session = await client.restore(did); 80 101 return { agent: new Agent(session), session };