a collection of lightweight TypeScript packages for AT Protocol, the protocol powering Bluesky
atproto bluesky typescript npm
101
fork

Configure Feed

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

docs(client): update examples to point to password-session

Mary 9d5833a1 06c998bf

+50 -26
+50 -26
packages/clients/client/README.md
··· 145 145 ```ts 146 146 import { Client, ok, simpleFetchHandler } from '@atcute/client'; 147 147 148 - const rpc = new Client({ handler: simpleFetchHandler({ service: 'https://public.api.bsky.app' }) }); 148 + const rpc = new Client({ 149 + handler: simpleFetchHandler({ service: 'https://public.api.bsky.app' }), 150 + }); 149 151 150 152 // throws ClientResponseError if the request fails 151 153 const profile = await ok(rpc.get('app.bsky.actor.getProfile', { params: { actor: 'bsky.app' } })); ··· 172 174 173 175 ### authenticated requests 174 176 175 - use `CredentialManager` to handle authentication. it manages tokens, automatically refreshes expired 176 - access tokens, and can persist sessions: 177 + for password-based authentication, use `PasswordSession` from `@atcute/password-session`. it manages 178 + tokens, automatically refreshes expired access tokens, and can persist sessions: 179 + 180 + ```sh 181 + npm install @atcute/password-session 182 + ``` 177 183 178 184 ```ts 179 - import { Client, CredentialManager, ok } from '@atcute/client'; 185 + import { Client, ok } from '@atcute/client'; 186 + import { PasswordSession } from '@atcute/password-session'; 180 187 181 - const manager = new CredentialManager({ service: 'https://bsky.social' }); 182 - const rpc = new Client({ handler: manager }); 188 + const auth = await PasswordSession.login({ 189 + service: 'https://bsky.social', 190 + identifier: 'you.bsky.social', 191 + password: 'your-app-password', 192 + }); 183 193 184 - // sign in with handle/email and password (or app password) 185 - await manager.login({ identifier: 'you.bsky.social', password: 'your-app-password' }); 194 + const rpc = new Client({ handler: auth }); 186 195 187 196 // requests are now authenticated 188 197 const session = await ok(rpc.get('com.atproto.server.getSession')); ··· 190 199 // -> "did:plc:..." 191 200 ``` 192 201 193 - save `manager.session` to persist login across app restarts: 202 + save `auth.session` to persist login across app restarts: 194 203 195 204 ```ts 196 205 // after login, save the session 197 - localStorage.setItem('session', JSON.stringify(manager.session)); 206 + localStorage.setItem('session', JSON.stringify(auth.session)); 198 207 ``` 199 208 200 209 ```ts 201 210 // later, restore the session 202 211 const saved = localStorage.getItem('session'); 203 212 if (saved) { 204 - await manager.resume(JSON.parse(saved)); 213 + const auth = await PasswordSession.resume(JSON.parse(saved)); 214 + const rpc = new Client({ handler: auth }); 205 215 } 206 216 ``` 207 217 208 218 use callbacks to keep persisted sessions in sync: 209 219 210 220 ```ts 211 - const manager = new CredentialManager({ 212 - service: 'https://bsky.social', 213 - onSessionUpdate(session) { 214 - // called on login, resume, and token refresh 215 - localStorage.setItem('session', JSON.stringify(session)); 221 + const auth = await PasswordSession.login( 222 + { 223 + service: 'https://bsky.social', 224 + identifier: 'you.bsky.social', 225 + password: 'your-app-password', 216 226 }, 217 - onExpired(session) { 218 - // called when refresh token expires and can't be renewed 219 - localStorage.removeItem('session'); 227 + { 228 + onUpdate(session) { 229 + // called on login and token refresh 230 + localStorage.setItem('session', JSON.stringify(session)); 231 + }, 232 + onDelete(session) { 233 + // called on logout or session invalidation 234 + localStorage.removeItem('session'); 235 + }, 220 236 }, 221 - }); 237 + ); 222 238 ``` 223 239 224 240 ### response formats ··· 269 285 import { Client, ok, simpleFetchHandler } from '@atcute/client'; 270 286 import { AppBskyActorGetProfile } from '@atcute/bluesky'; 271 287 272 - const rpc = new Client({ handler: simpleFetchHandler({ service: 'https://public.api.bsky.app' }) }); 288 + const rpc = new Client({ 289 + handler: simpleFetchHandler({ service: 'https://public.api.bsky.app' }), 290 + }); 273 291 274 292 // validates params, input, and output against the schema 275 293 const response = await rpc.call(AppBskyActorGetProfile, { ··· 303 321 forwards the request with authorization headers proving it's acting on your behalf. 304 322 305 323 ```ts 306 - // must be authenticated via CredentialManager 307 - const manager = new CredentialManager({ service: 'https://bsky.social' }); 308 - await manager.login({ identifier: 'you.bsky.social', password: 'your-app-password' }); 324 + import { Client, ok } from '@atcute/client'; 325 + import { PasswordSession } from '@atcute/password-session'; 326 + 327 + // must be authenticated 328 + const session = await PasswordSession.login({ 329 + service: 'https://bsky.social', 330 + identifier: 'you.bsky.social', 331 + password: 'your-app-password', 332 + }); 309 333 310 334 // create a client that proxies requests through your PDS to the chat service 311 335 const chatClient = new Client({ 312 - handler: manager, 336 + handler: session, 313 337 proxy: { 314 338 did: 'did:web:api.bsky.chat', 315 339 serviceId: '#bsky_chat', ··· 346 370 const rpc = new Client({ handler: customHandler }); 347 371 ``` 348 372 349 - or implement `FetchHandlerObject` for stateful handlers (like `CredentialManager` does): 373 + or implement `FetchHandlerObject` for stateful handlers (like `PasswordSession` does): 350 374 351 375 ```ts 352 376 import type { FetchHandlerObject } from '@atcute/client';