b934b396b1
* feat(api): support creation of oauth based AtpAgents * oauth: misc fixes for confidential clients * fix(xprc): remove ReadableStream.from polyfill * OAuth docs tweaks (#2679) * OAuth: clarification about client_name being shown * OAuth: re-write handle resolution privacy concern * avoid relying on ReadableStream.from in xrpc-server tests * feat(oauth-types): expose "ALLOW_UNSECURE_ORIGINS" constant * feat(handle-resolver): expose "AtprotoIdentityDidMethods" type * fix(oauth-client): ensure that the oauth metadata document contains client_id_metadata_document_supported * fix(oauth-types): prevent unknown query string in loopback client id * fix(identity-resolver): check that handle is in did doc's "alsoKnownAs" * feat(oauth-client:oauth-resolver): allow logging in using either the PDS URL or Entryway URL * fix(oauth-client): return better error in case of invalid "oauth-protected-resource" status code * refactor(did): group atproto specific checks in own * feat(api): relax typing of "appLabelers" and "labelers" AtpClient properties * allow any did as labeller (for tests mainly) * fix(api): allow to override "atproto-proxy" on a per-request basis * remove release candidate versions from changelog * update changeset for api and xrpc packages * Add missing changeset * revert RC versions * Proper wording in OAUTH.md api example * remove "pre" changeset file * xrpc: restore original behavior of setHEader and unsetHeader * docs: add comment for XrpcClient 's constructor arg * feat(api): expose "schemas" publicly * feat(api): allow customizing the whatwg fetch function of the AtpAgent * docs(api): improve migration docs * docs: change reference to BskyAgent to AtpAgent * docs: mention the breaking change regarding setSessionPersistHandler * fix(api): better split AtpClient concerns * fix(xrpc): remove unused import * refactor(api): simplify class hierarchu by removeing AtpClient * fix(api): mock proper method for facets detection * restore ability to restore session asynchronously * feat(api): allow instantiating Agent with same argument as super class * docs(api): properly extend Agent class * style(xrpc): var name * docs(api): remove "async" to header getter --------- Co-authored-by: Devin Ivy <devinivy@gmail.com> Co-authored-by: bnewbold <bnewbold@robocracy.org> Co-authored-by: Hailey <me@haileyok.com>
108 lines
3.0 KiB
Markdown
108 lines
3.0 KiB
Markdown
# @atproto/xrpc: atproto HTTP API Client
|
|
|
|
TypeScript client library for talking to [atproto](https://atproto.com) services, with Lexicon schema validation.
|
|
|
|
[![NPM](https://img.shields.io/npm/v/@atproto/xrpc)](https://www.npmjs.com/package/@atproto/xrpc)
|
|
[![Github CI Status](https://github.com/bluesky-social/atproto/actions/workflows/repo.yaml/badge.svg)](https://github.com/bluesky-social/atproto/actions/workflows/repo.yaml)
|
|
|
|
## Usage
|
|
|
|
```typescript
|
|
import { LexiconDoc } from '@atproto/lexicon'
|
|
import { XrpcClient } from '@atproto/xrpc'
|
|
|
|
const pingLexicon = {
|
|
lexicon: 1,
|
|
id: 'io.example.ping',
|
|
defs: {
|
|
main: {
|
|
type: 'query',
|
|
description: 'Ping the server',
|
|
parameters: {
|
|
type: 'params',
|
|
properties: { message: { type: 'string' } },
|
|
},
|
|
output: {
|
|
encoding: 'application/json',
|
|
schema: {
|
|
type: 'object',
|
|
required: ['message'],
|
|
properties: { message: { type: 'string' } },
|
|
},
|
|
},
|
|
},
|
|
},
|
|
} satisfies LexiconDoc
|
|
|
|
const xrpc = new XrpcClient('https://ping.example.com', [
|
|
// Any number of lexicon here
|
|
pingLexicon,
|
|
])
|
|
|
|
const res1 = await xrpc.call('io.example.ping', {
|
|
message: 'hello world',
|
|
})
|
|
res1.encoding // => 'application/json'
|
|
res1.body // => {message: 'hello world'}
|
|
```
|
|
|
|
### With a custom fetch handler
|
|
|
|
```typescript
|
|
import { XrpcClient } from '@atproto/xrpc'
|
|
|
|
const session = {
|
|
serviceUrl: 'https://ping.example.com',
|
|
token: '<my-token>',
|
|
async refreshToken() {
|
|
const { token } = await fetch('https://auth.example.com/refresh', {
|
|
method: 'POST',
|
|
headers: { Authorization: `Bearer ${this.token}` },
|
|
}).then((res) => res.json())
|
|
|
|
this.token = token
|
|
|
|
return token
|
|
},
|
|
}
|
|
|
|
const sessionBasedFetch: FetchHandler = async (
|
|
url: string,
|
|
init: RequestInit,
|
|
) => {
|
|
const headers = new Headers(init.headers)
|
|
|
|
headers.set('Authorization', `Bearer ${session.token}`)
|
|
|
|
const response = await fetch(new URL(url, session.serviceUrl), {
|
|
...init,
|
|
headers,
|
|
})
|
|
|
|
if (response.status === 401) {
|
|
// Refresh token, then try again.
|
|
const newToken = await session.refreshToken()
|
|
headers.set('Authorization', `Bearer ${newToken}`)
|
|
return fetch(new URL(url, session.serviceUrl), { ...init, headers })
|
|
}
|
|
|
|
return response
|
|
}
|
|
|
|
const xrpc = new XrpcClient(sessionBasedFetch, [
|
|
// Any number of lexicon here
|
|
pingLexicon,
|
|
])
|
|
|
|
//
|
|
```
|
|
|
|
## License
|
|
|
|
This project is dual-licensed under MIT and Apache 2.0 terms:
|
|
|
|
- MIT license ([LICENSE-MIT.txt](https://github.com/bluesky-social/atproto/blob/main/LICENSE-MIT.txt) or http://opensource.org/licenses/MIT)
|
|
- Apache License, Version 2.0, ([LICENSE-APACHE.txt](https://github.com/bluesky-social/atproto/blob/main/LICENSE-APACHE.txt) or http://www.apache.org/licenses/LICENSE-2.0)
|
|
|
|
Downstream projects and end users may chose either license individually, or both together, at their discretion. The motivation for this dual-licensing is the additional software patent assurance provided by Apache 2.0.
|