phase 4: delete the session bridge (SessionAgent, agent.ts, agentToLexClient)
This commit is contained in:
@@ -1,59 +1,10 @@
|
||||
import {type AtpAgent} from '@atproto/api'
|
||||
import {Client} from '@atproto/lex-client'
|
||||
import {type PasswordSession} from '@atproto/lex-password-session'
|
||||
import {api} from '@bsky.app/sdk'
|
||||
|
||||
import {PUBLIC_BSKY_SERVICE} from '#/lib/constants'
|
||||
import {BLUESKY_PROXY_HEADER, PUBLIC_BSKY_SERVICE} from '#/lib/constants'
|
||||
import {networkAwareFetch} from './session-core'
|
||||
|
||||
/**
|
||||
* Stable per-agent cache of lex `Client` instances. We never reuse an
|
||||
* `AtpAgent` (the session provider disposes the previous one on switch), so a
|
||||
* `WeakMap` keyed on the agent gives us a client whose identity is stable for
|
||||
* the lifetime of that agent. This keeps React Query keys and hook consumers
|
||||
* from churning on every render.
|
||||
*/
|
||||
const clientForAgent = new WeakMap<AtpAgent, Client>()
|
||||
|
||||
/**
|
||||
* Wrap a live {@link AtpAgent} as a lex {@link Client}, bridging the old session
|
||||
* source of truth to the new SDK so features can migrate incrementally.
|
||||
*
|
||||
* The client talks to the agent through the minimal lex `Agent` interface
|
||||
* (`{ did, fetchHandler }`). We deliberately route `fetchHandler` through
|
||||
* `agent.fetchHandler` (the agent's XRPC dispatch layer) rather than
|
||||
* `agent.sessionManager.fetchHandler`:
|
||||
*
|
||||
* - `agent.fetchHandler` (see @atproto/api `agent.js`) is where the agent
|
||||
* applies its configured `atproto-proxy` header (set via `configureProxy` to
|
||||
* the appview) and its `atproto-accept-labelers` header, before delegating to
|
||||
* `sessionManager.fetchHandler` for authorization + token refresh.
|
||||
* - `sessionManager.fetchHandler` (`CredentialSession`) only adds the auth
|
||||
* token and handles refresh - it does NOT proxy or attach labelers. Wrapping
|
||||
* it directly would silently drop appview proxying and moderation labelers.
|
||||
*
|
||||
* Because the wrapped agent already applies proxy + labeler headers, we do NOT
|
||||
* pass a `service` option to the `Client` (lex-client only sets `atproto-proxy`
|
||||
* when `service` is provided) and we leave `Client.appLabelers` at its default
|
||||
* empty set. This avoids double-setting either header.
|
||||
*
|
||||
* Results are memoized per-agent so the returned client is referentially stable.
|
||||
*/
|
||||
export function agentToLexClient(agent: AtpAgent): Client {
|
||||
const cached = clientForAgent.get(agent)
|
||||
if (cached) {
|
||||
return cached
|
||||
}
|
||||
const client = new Client({
|
||||
get did() {
|
||||
return agent.did
|
||||
},
|
||||
fetchHandler: (path, init) => agent.fetchHandler(path, init),
|
||||
})
|
||||
clientForAgent.set(agent, client)
|
||||
return client
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazily-constructed unauthenticated client pointed at the public appview. It
|
||||
* hits {@link PUBLIC_BSKY_SERVICE} directly, mirroring `createPublicAgent`'s
|
||||
@@ -135,18 +86,26 @@ export function getUnauthenticatedClient(): Client {
|
||||
/**
|
||||
* Build the authed appview client over a {@link PasswordSession}.
|
||||
*
|
||||
* Requests are proxied to the Bluesky appview (`atproto-proxy:
|
||||
* did:web:api.bsky.app#bsky_appview`) and carry the per-instance labelers.
|
||||
* The Bluesky moderation labeler (`api.moderation.did`) is always included as
|
||||
* a base labeler because sending ANY `atproto-accept-labelers` header replaces
|
||||
* the server-side default - so we must re-assert it to keep it active.
|
||||
* Requests are proxied to the Bluesky appview and carry the per-instance
|
||||
* labelers. The Bluesky moderation labeler (`api.moderation.did`) is always
|
||||
* included as a base labeler because sending ANY `atproto-accept-labelers`
|
||||
* header replaces the server-side default - so we must re-assert it to keep it
|
||||
* active.
|
||||
*
|
||||
* The proxy `service` is read from `BLUESKY_PROXY_HEADER.get()` (rather than
|
||||
* hard-coding `api.app.service`). Its default value equals `api.app.service`
|
||||
* (`did:web:api.bsky.app#bsky_appview`), so production is unchanged; the getter
|
||||
* exists so the e2e `TestCtrls` hack can retarget the appview by calling
|
||||
* `BLUESKY_PROXY_HEADER.set()` before sign-in (the client is built at
|
||||
* sign-in, so it picks up the override).
|
||||
*/
|
||||
export function buildAppviewClient(
|
||||
session: PasswordSession,
|
||||
labelerDids: string[],
|
||||
): Client {
|
||||
return new Client(session, {
|
||||
service: api.app.service,
|
||||
/* BLUESKY_PROXY_HEADER.get() is a `did:...#...` ProxyHeaderValue, assignable to Service */
|
||||
service: BLUESKY_PROXY_HEADER.get(),
|
||||
/* labelerDids are validated DID strings; cast to the DidString template type */
|
||||
labelers: [
|
||||
api.moderation.did,
|
||||
|
||||
Reference in New Issue
Block a user