@atproto/lex-client 0.0.10 → 0.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +32 -0
- package/dist/agent.d.ts +72 -0
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +46 -1
- package/dist/agent.js.map +1 -1
- package/dist/client.d.ts +442 -46
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +145 -1
- package/dist/client.js.map +1 -1
- package/dist/errors.d.ts +202 -48
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +208 -65
- package/dist/errors.js.map +1 -1
- package/dist/lexicons/com/atproto/repo/createRecord.defs.d.ts +20 -20
- package/dist/lexicons/com/atproto/repo/deleteRecord.defs.d.ts +12 -12
- package/dist/lexicons/com/atproto/repo/getRecord.defs.d.ts +6 -6
- package/dist/lexicons/com/atproto/repo/listRecords.defs.d.ts +6 -6
- package/dist/lexicons/com/atproto/repo/putRecord.defs.d.ts +22 -22
- package/dist/lexicons/com/atproto/repo/uploadBlob.defs.d.ts +2 -2
- package/dist/response.d.ts +17 -6
- package/dist/response.d.ts.map +1 -1
- package/dist/response.js +45 -32
- package/dist/response.js.map +1 -1
- package/dist/types.d.ts +51 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/util.d.ts +40 -5
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +22 -0
- package/dist/util.js.map +1 -1
- package/dist/www-authenticate.d.ts +35 -0
- package/dist/www-authenticate.d.ts.map +1 -0
- package/dist/www-authenticate.js +57 -0
- package/dist/www-authenticate.js.map +1 -0
- package/dist/xrpc.d.ts +82 -10
- package/dist/xrpc.d.ts.map +1 -1
- package/dist/xrpc.js +15 -28
- package/dist/xrpc.js.map +1 -1
- package/package.json +7 -7
- package/src/agent.ts +101 -1
- package/src/client.ts +428 -15
- package/src/errors.ts +308 -120
- package/src/response.ts +68 -63
- package/src/types.ts +52 -0
- package/src/util.ts +50 -5
- package/src/www-authenticate.test.ts +227 -0
- package/src/www-authenticate.ts +101 -0
- package/src/xrpc.ts +100 -53
package/src/client.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LexError, LexMap, LexValue } from '@atproto/lex-data'
|
|
1
|
+
import { LexError, LexMap, LexValue, TypedLexMap } from '@atproto/lex-data'
|
|
2
2
|
import {
|
|
3
3
|
AtIdentifierString,
|
|
4
4
|
CidString,
|
|
@@ -19,79 +19,159 @@ import {
|
|
|
19
19
|
getMain,
|
|
20
20
|
} from '@atproto/lex-schema'
|
|
21
21
|
import { Agent, AgentOptions, buildAgent } from './agent.js'
|
|
22
|
+
import { XrpcFailure } from './errors.js'
|
|
22
23
|
import { com } from './lexicons/index.js'
|
|
23
24
|
import { XrpcResponse, XrpcResponseBody } from './response.js'
|
|
24
25
|
import { BinaryBodyInit, CallOptions, Service } from './types.js'
|
|
25
26
|
import { buildAtprotoHeaders } from './util.js'
|
|
26
|
-
import {
|
|
27
|
-
XrpcFailure,
|
|
28
|
-
XrpcOptions,
|
|
29
|
-
XrpcRequestParams,
|
|
30
|
-
xrpc,
|
|
31
|
-
xrpcSafe,
|
|
32
|
-
} from './xrpc.js'
|
|
27
|
+
import { XrpcOptions, XrpcRequestParams, xrpc, xrpcSafe } from './xrpc.js'
|
|
33
28
|
|
|
34
29
|
export type {
|
|
35
30
|
AtIdentifierString,
|
|
36
31
|
CidString,
|
|
37
32
|
DidString,
|
|
33
|
+
Infer,
|
|
38
34
|
InferMethodInputBody,
|
|
39
35
|
InferMethodOutputBody,
|
|
40
36
|
InferRecordKey,
|
|
41
37
|
LexMap,
|
|
42
38
|
LexValue,
|
|
43
39
|
LexiconRecordKey,
|
|
40
|
+
Main,
|
|
44
41
|
NsidString,
|
|
45
42
|
Params,
|
|
46
43
|
Procedure,
|
|
47
44
|
Query,
|
|
48
45
|
RecordSchema,
|
|
49
46
|
Restricted,
|
|
47
|
+
TypedLexMap,
|
|
50
48
|
}
|
|
51
49
|
|
|
50
|
+
/**
|
|
51
|
+
* Configuration options for creating a {@link Client}.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```typescript
|
|
55
|
+
* const options: ClientOptions = {
|
|
56
|
+
* labelers: ['did:plc:labeler1'],
|
|
57
|
+
* service: 'did:web:api.bsky.app#bsky_appview',
|
|
58
|
+
* headers: { 'X-Custom-Header': 'value' }
|
|
59
|
+
* }
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
52
62
|
export type ClientOptions = {
|
|
63
|
+
/** Labeler DIDs to include in requests for content moderation. */
|
|
53
64
|
labelers?: Iterable<DidString>
|
|
65
|
+
/** Custom headers to include in all requests made by this client. */
|
|
54
66
|
headers?: HeadersInit
|
|
67
|
+
/** Service proxy identifier for routing requests through a specific service. */
|
|
55
68
|
service?: Service
|
|
56
69
|
}
|
|
57
70
|
|
|
71
|
+
/**
|
|
72
|
+
* A composable action that can be invoked via {@link Client.call}.
|
|
73
|
+
*
|
|
74
|
+
* Actions provide a way to define custom operations that integrate with the
|
|
75
|
+
* Client's call interface, enabling type-safe, reusable business logic.
|
|
76
|
+
*
|
|
77
|
+
* @typeParam I - The input type for the action
|
|
78
|
+
* @typeParam O - The output type for the action
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```typescript
|
|
82
|
+
* const myAction: Action<{ userId: string }, { profile: Profile }> = async (client, input, options) => {
|
|
83
|
+
* const response = await client.xrpc(someMethod, { params: { actor: input.userId }, ...options })
|
|
84
|
+
* return { profile: response.body }
|
|
85
|
+
* }
|
|
86
|
+
* ```
|
|
87
|
+
*/
|
|
58
88
|
export type Action<I = any, O = any> = (
|
|
59
89
|
client: Client,
|
|
60
90
|
input: I,
|
|
61
91
|
options: CallOptions,
|
|
62
92
|
) => O | Promise<O>
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Extracts the input type from an {@link Action}.
|
|
96
|
+
* @typeParam A - The Action type to extract from
|
|
97
|
+
*/
|
|
63
98
|
export type InferActionInput<A extends Action> =
|
|
64
99
|
A extends Action<infer I, any> ? I : never
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Extracts the output type from an {@link Action}.
|
|
103
|
+
* @typeParam A - The Action type to extract from
|
|
104
|
+
*/
|
|
65
105
|
export type InferActionOutput<A extends Action> =
|
|
66
106
|
A extends Action<any, infer O> ? O : never
|
|
67
107
|
|
|
108
|
+
/**
|
|
109
|
+
* Options for creating a record in an AT Protocol repository.
|
|
110
|
+
*
|
|
111
|
+
* @see {@link Client.createRecord}
|
|
112
|
+
*/
|
|
68
113
|
export type CreateRecordOptions = CallOptions & {
|
|
114
|
+
/** Repository identifier (DID or handle). Defaults to authenticated user's DID. */
|
|
69
115
|
repo?: AtIdentifierString
|
|
116
|
+
/** Compare-and-swap on the repo commit. If specified, must match current commit. */
|
|
70
117
|
swapCommit?: string
|
|
118
|
+
/** Whether to validate the record against its lexicon schema. */
|
|
71
119
|
validate?: boolean
|
|
72
120
|
}
|
|
73
121
|
|
|
122
|
+
/**
|
|
123
|
+
* Options for deleting a record from an AT Protocol repository.
|
|
124
|
+
*
|
|
125
|
+
* @see {@link Client.deleteRecord}
|
|
126
|
+
*/
|
|
74
127
|
export type DeleteRecordOptions = CallOptions & {
|
|
128
|
+
/** Repository identifier (DID or handle). Defaults to authenticated user's DID. */
|
|
75
129
|
repo?: AtIdentifierString
|
|
130
|
+
/** Compare-and-swap on the repo commit. If specified, must match current commit. */
|
|
76
131
|
swapCommit?: string
|
|
132
|
+
/** Compare-and-swap on the record CID. If specified, must match current record. */
|
|
77
133
|
swapRecord?: string
|
|
78
134
|
}
|
|
79
135
|
|
|
136
|
+
/**
|
|
137
|
+
* Options for retrieving a record from an AT Protocol repository.
|
|
138
|
+
*
|
|
139
|
+
* @see {@link Client.getRecord}
|
|
140
|
+
*/
|
|
80
141
|
export type GetRecordOptions = CallOptions & {
|
|
142
|
+
/** Repository identifier (DID or handle). Defaults to authenticated user's DID. */
|
|
81
143
|
repo?: AtIdentifierString
|
|
82
144
|
}
|
|
83
145
|
|
|
146
|
+
/**
|
|
147
|
+
* Options for creating or updating a record in an AT Protocol repository.
|
|
148
|
+
*
|
|
149
|
+
* @see {@link Client.putRecord}
|
|
150
|
+
*/
|
|
84
151
|
export type PutRecordOptions = CallOptions & {
|
|
152
|
+
/** Repository identifier (DID or handle). Defaults to authenticated user's DID. */
|
|
85
153
|
repo?: AtIdentifierString
|
|
154
|
+
/** Compare-and-swap on the repo commit. If specified, must match current commit. */
|
|
86
155
|
swapCommit?: string
|
|
156
|
+
/** Compare-and-swap on the record CID. If specified, must match current record. */
|
|
87
157
|
swapRecord?: string
|
|
158
|
+
/** Whether to validate the record against its lexicon schema. */
|
|
88
159
|
validate?: boolean
|
|
89
160
|
}
|
|
90
161
|
|
|
162
|
+
/**
|
|
163
|
+
* Options for listing records in an AT Protocol repository collection.
|
|
164
|
+
*
|
|
165
|
+
* @see {@link Client.listRecords}
|
|
166
|
+
*/
|
|
91
167
|
export type ListRecordsOptions = CallOptions & {
|
|
168
|
+
/** Repository identifier (DID or handle). Defaults to authenticated user's DID. */
|
|
92
169
|
repo?: AtIdentifierString
|
|
170
|
+
/** Maximum number of records to return. */
|
|
93
171
|
limit?: number
|
|
172
|
+
/** Pagination cursor from a previous response. */
|
|
94
173
|
cursor?: string
|
|
174
|
+
/** If true, returns records in reverse chronological order. */
|
|
95
175
|
reverse?: boolean
|
|
96
176
|
}
|
|
97
177
|
|
|
@@ -102,48 +182,116 @@ export type RecordKeyOptions<
|
|
|
102
182
|
? { rkey?: InferRecordKey<T> }
|
|
103
183
|
: { rkey: InferRecordKey<T> }
|
|
104
184
|
|
|
185
|
+
/**
|
|
186
|
+
* Type-safe options for {@link Client.create}, combining record options with key requirements.
|
|
187
|
+
* @typeParam T - The record schema type
|
|
188
|
+
*/
|
|
105
189
|
export type CreateOptions<T extends RecordSchema> = CreateRecordOptions &
|
|
106
|
-
RecordKeyOptions<T, 'tid'>
|
|
190
|
+
RecordKeyOptions<T, 'tid' | 'any'>
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Output type for record creation operations.
|
|
194
|
+
* Contains the URI and CID of the newly created record.
|
|
195
|
+
*/
|
|
107
196
|
export type CreateOutput = InferMethodOutputBody<
|
|
108
197
|
typeof com.atproto.repo.createRecord.main,
|
|
109
198
|
Uint8Array
|
|
110
199
|
>
|
|
111
200
|
|
|
201
|
+
/**
|
|
202
|
+
* Type-safe options for {@link Client.delete}, combining delete options with key requirements.
|
|
203
|
+
* @typeParam T - The record schema type
|
|
204
|
+
*/
|
|
112
205
|
export type DeleteOptions<T extends RecordSchema> = DeleteRecordOptions &
|
|
113
206
|
RecordKeyOptions<T>
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Output type for record deletion operations.
|
|
210
|
+
*/
|
|
114
211
|
export type DeleteOutput = InferMethodOutputBody<
|
|
115
212
|
typeof com.atproto.repo.deleteRecord.main,
|
|
116
213
|
Uint8Array
|
|
117
214
|
>
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Type-safe options for {@link Client.get}, combining get options with key requirements.
|
|
218
|
+
* @typeParam T - The record schema type
|
|
219
|
+
*/
|
|
118
220
|
export type GetOptions<T extends RecordSchema> = GetRecordOptions &
|
|
119
221
|
RecordKeyOptions<T>
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Output type for record retrieval operations.
|
|
225
|
+
* Contains the record value validated against the schema type.
|
|
226
|
+
* @typeParam T - The record schema type
|
|
227
|
+
*/
|
|
120
228
|
export type GetOutput<T extends RecordSchema> = Omit<
|
|
121
229
|
InferMethodOutputBody<typeof com.atproto.repo.getRecord.main, Uint8Array>,
|
|
122
230
|
'value'
|
|
123
231
|
> & { value: Infer<T> }
|
|
124
232
|
|
|
233
|
+
/**
|
|
234
|
+
* Type-safe options for {@link Client.put}, combining put options with key requirements.
|
|
235
|
+
* @typeParam T - The record schema type
|
|
236
|
+
*/
|
|
125
237
|
export type PutOptions<T extends RecordSchema> = PutRecordOptions &
|
|
126
238
|
RecordKeyOptions<T>
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Output type for record put (create/update) operations.
|
|
242
|
+
* Contains the URI and CID of the record.
|
|
243
|
+
*/
|
|
127
244
|
export type PutOutput = InferMethodOutputBody<
|
|
128
245
|
typeof com.atproto.repo.putRecord.main,
|
|
129
246
|
Uint8Array
|
|
130
247
|
>
|
|
131
248
|
|
|
249
|
+
/**
|
|
250
|
+
* Options for {@link Client.list} operations.
|
|
251
|
+
*/
|
|
132
252
|
export type ListOptions = ListRecordsOptions
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Output type for record listing operations.
|
|
256
|
+
* Contains validated records and any invalid records that failed schema validation.
|
|
257
|
+
* @typeParam T - The record schema type
|
|
258
|
+
*/
|
|
133
259
|
export type ListOutput<T extends RecordSchema> = InferMethodOutputBody<
|
|
134
260
|
typeof com.atproto.repo.listRecords.main,
|
|
135
261
|
Uint8Array
|
|
136
262
|
> & {
|
|
263
|
+
/** Records that successfully validated against the schema. */
|
|
137
264
|
records: ListRecord<Infer<T>>[]
|
|
138
265
|
// @NOTE Because the schema uses "type": "unknown" instead of an open union,
|
|
139
266
|
// we have to use UnknownObject instead of Unknown$TypedObject here.
|
|
267
|
+
/** Records that failed schema validation. */
|
|
140
268
|
invalid: UnknownObject[]
|
|
141
269
|
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* A record from a list operation with its value typed to the schema.
|
|
273
|
+
* @typeParam Value - The validated record value type
|
|
274
|
+
*/
|
|
142
275
|
export type ListRecord<Value extends LexMap> =
|
|
143
276
|
com.atproto.repo.listRecords.Record & {
|
|
144
277
|
value: Value
|
|
145
278
|
}
|
|
146
279
|
|
|
280
|
+
/**
|
|
281
|
+
* The Client class is the primary interface for interacting with AT Protocol
|
|
282
|
+
* services. It provides type-safe methods for XRPC calls, record operations,
|
|
283
|
+
* and blob handling.
|
|
284
|
+
*
|
|
285
|
+
* @example Basic usage
|
|
286
|
+
* ```typescript
|
|
287
|
+
* import { Client } from '@atproto/lex'
|
|
288
|
+
*
|
|
289
|
+
* const client = new Client(agent)
|
|
290
|
+
* const response = await client.xrpc(app.bsky.feed.getTimeline.main, {
|
|
291
|
+
* params: { limit: 50 }
|
|
292
|
+
* })
|
|
293
|
+
* ```
|
|
294
|
+
*/
|
|
147
295
|
export class Client implements Agent {
|
|
148
296
|
static appLabelers: readonly DidString[] = []
|
|
149
297
|
|
|
@@ -154,9 +302,16 @@ export class Client implements Agent {
|
|
|
154
302
|
if (opts.appLabelers) this.appLabelers = [...opts.appLabelers]
|
|
155
303
|
}
|
|
156
304
|
|
|
305
|
+
/** The underlying agent used for making requests. */
|
|
157
306
|
public readonly agent: Agent
|
|
307
|
+
|
|
308
|
+
/** Custom headers included in all requests. */
|
|
158
309
|
public readonly headers: Headers
|
|
310
|
+
|
|
311
|
+
/** Optional service identifier for routing requests. */
|
|
159
312
|
public readonly service?: Service
|
|
313
|
+
|
|
314
|
+
/** Set of labeler DIDs specific to this client instance. */
|
|
160
315
|
public readonly labelers: Set<DidString>
|
|
161
316
|
|
|
162
317
|
constructor(agent: Agent | AgentOptions, options: ClientOptions = {}) {
|
|
@@ -166,32 +321,68 @@ export class Client implements Agent {
|
|
|
166
321
|
this.headers = new Headers(options.headers)
|
|
167
322
|
}
|
|
168
323
|
|
|
324
|
+
/**
|
|
325
|
+
* The DID of the authenticated user, or `undefined` if not authenticated.
|
|
326
|
+
*/
|
|
169
327
|
get did(): DidString | undefined {
|
|
170
328
|
return this.agent.did
|
|
171
329
|
}
|
|
172
330
|
|
|
331
|
+
/**
|
|
332
|
+
* The DID of the authenticated user.
|
|
333
|
+
* @throws {LexError} with code 'AuthenticationRequired' if not authenticated
|
|
334
|
+
*/
|
|
173
335
|
get assertDid(): DidString {
|
|
174
336
|
this.assertAuthenticated()
|
|
175
337
|
return this.did
|
|
176
338
|
}
|
|
177
339
|
|
|
340
|
+
/**
|
|
341
|
+
* Asserts that the client is authenticated.
|
|
342
|
+
* Use as a type guard when you need to ensure authentication.
|
|
343
|
+
*
|
|
344
|
+
* @throws {LexError} with code 'AuthenticationRequired' if not authenticated
|
|
345
|
+
*
|
|
346
|
+
* @example
|
|
347
|
+
* ```typescript
|
|
348
|
+
* client.assertAuthenticated()
|
|
349
|
+
* // TypeScript now knows client.did is defined
|
|
350
|
+
* console.log(client.did)
|
|
351
|
+
* ```
|
|
352
|
+
*/
|
|
178
353
|
public assertAuthenticated(): asserts this is { did: DidString } {
|
|
179
354
|
if (!this.did) throw new LexError('AuthenticationRequired')
|
|
180
355
|
}
|
|
181
356
|
|
|
357
|
+
/**
|
|
358
|
+
* Replaces all labelers with the given set.
|
|
359
|
+
* @param labelers - Iterable of labeler DIDs
|
|
360
|
+
*/
|
|
182
361
|
public setLabelers(labelers: Iterable<DidString> = []) {
|
|
183
362
|
this.clearLabelers()
|
|
184
363
|
this.addLabelers(labelers)
|
|
185
364
|
}
|
|
186
365
|
|
|
366
|
+
/**
|
|
367
|
+
* Adds labelers to the current set.
|
|
368
|
+
* @param labelers - Iterable of labeler DIDs to add
|
|
369
|
+
*/
|
|
187
370
|
public addLabelers(labelers: Iterable<DidString>) {
|
|
188
371
|
for (const labeler of labelers) this.labelers.add(labeler)
|
|
189
372
|
}
|
|
190
373
|
|
|
374
|
+
/**
|
|
375
|
+
* Removes all labelers from this client instance.
|
|
376
|
+
*/
|
|
191
377
|
public clearLabelers() {
|
|
192
378
|
this.labelers.clear()
|
|
193
379
|
}
|
|
194
380
|
|
|
381
|
+
/**
|
|
382
|
+
* Low-level fetch handler for making requests.
|
|
383
|
+
* @param path - The request path
|
|
384
|
+
* @param init - Request initialization options
|
|
385
|
+
*/
|
|
195
386
|
public fetchHandler(path: string, init: RequestInit): Promise<Response> {
|
|
196
387
|
const headers = buildAtprotoHeaders({
|
|
197
388
|
headers: init.headers,
|
|
@@ -214,7 +405,33 @@ export class Client implements Agent {
|
|
|
214
405
|
}
|
|
215
406
|
|
|
216
407
|
/**
|
|
217
|
-
*
|
|
408
|
+
* Makes an XRPC request. Throws on failure.
|
|
409
|
+
*
|
|
410
|
+
* @param ns - The lexicon method definition (e.g., `app.bsky.feed.getTimeline`)
|
|
411
|
+
* @param options - Request options including params and body
|
|
412
|
+
* @returns The successful XRPC response
|
|
413
|
+
* @throws {XrpcFailure} when the request fails or returns an error
|
|
414
|
+
*
|
|
415
|
+
* @example Query with parameters
|
|
416
|
+
* ```typescript
|
|
417
|
+
* const response = await client.xrpc(app.bsky.feed.getTimeline, {
|
|
418
|
+
* params: { limit: 50, cursor: 'abc123' }
|
|
419
|
+
* })
|
|
420
|
+
* console.log(response.body.feed)
|
|
421
|
+
* ```
|
|
422
|
+
*
|
|
423
|
+
* @example Procedure with body
|
|
424
|
+
* ```typescript
|
|
425
|
+
* const response = await client.xrpc(com.atproto.repo.createRecord, {
|
|
426
|
+
* body: {
|
|
427
|
+
* repo: client.assertDid,
|
|
428
|
+
* collection: 'app.bsky.feed.post',
|
|
429
|
+
* record: { text: 'Hello!', createdAt: new Date().toISOString() }
|
|
430
|
+
* }
|
|
431
|
+
* })
|
|
432
|
+
* ```
|
|
433
|
+
*
|
|
434
|
+
* @see {@link xrpcSafe} for a non-throwing variant
|
|
218
435
|
*/
|
|
219
436
|
async xrpc<const M extends Query | Procedure>(
|
|
220
437
|
ns: NonNullable<unknown> extends XrpcOptions<M>
|
|
@@ -232,6 +449,29 @@ export class Client implements Agent {
|
|
|
232
449
|
return xrpc(this, ns, options)
|
|
233
450
|
}
|
|
234
451
|
|
|
452
|
+
/**
|
|
453
|
+
* Makes an XRPC request without throwing on failure.
|
|
454
|
+
* Returns either a successful response or a failure object.
|
|
455
|
+
*
|
|
456
|
+
* @param ns - The lexicon method definition
|
|
457
|
+
* @param options - Request options
|
|
458
|
+
* @returns Either an XrpcResponse on success or XrpcFailure on failure
|
|
459
|
+
*
|
|
460
|
+
* @example
|
|
461
|
+
* ```typescript
|
|
462
|
+
* const result = await client.xrpcSafe(app.bsky.actor.getProfile.main, {
|
|
463
|
+
* params: { actor: 'alice.bsky.social' }
|
|
464
|
+
* })
|
|
465
|
+
*
|
|
466
|
+
* if (result.success) {
|
|
467
|
+
* console.log(result.body.displayName)
|
|
468
|
+
* } else {
|
|
469
|
+
* console.error('Failed:', result.error)
|
|
470
|
+
* }
|
|
471
|
+
* ```
|
|
472
|
+
*
|
|
473
|
+
* @see {@link xrpc} for a throwing variant
|
|
474
|
+
*/
|
|
235
475
|
async xrpcSafe<const M extends Query | Procedure>(
|
|
236
476
|
ns: NonNullable<unknown> extends XrpcOptions<M>
|
|
237
477
|
? Main<M>
|
|
@@ -249,10 +489,27 @@ export class Client implements Agent {
|
|
|
249
489
|
}
|
|
250
490
|
|
|
251
491
|
/**
|
|
252
|
-
*
|
|
492
|
+
* Creates a new record in an AT Protocol repository.
|
|
493
|
+
*
|
|
494
|
+
* @param record - The record to create, must include an {@link NsidString} `$type`
|
|
495
|
+
* @param rkey - Optional record key; if omitted, server generates a TID
|
|
496
|
+
* @param options - Create options including repo, swapCommit, validate
|
|
497
|
+
* @returns The XRPC response containing the created record's URI and CID
|
|
498
|
+
*
|
|
499
|
+
* @example
|
|
500
|
+
* ```typescript
|
|
501
|
+
* const response = await client.createRecord(
|
|
502
|
+
* { $type: 'app.bsky.feed.post', text: 'Hello!', createdAt: new Date().toISOString() },
|
|
503
|
+
* undefined, // Let server generate rkey
|
|
504
|
+
* { validate: true }
|
|
505
|
+
* )
|
|
506
|
+
* console.log(response.body.uri)
|
|
507
|
+
* ```
|
|
508
|
+
*
|
|
509
|
+
* @see {@link create} for a higher-level typed alternative
|
|
253
510
|
*/
|
|
254
511
|
public async createRecord(
|
|
255
|
-
record:
|
|
512
|
+
record: TypedLexMap<NsidString>,
|
|
256
513
|
rkey?: string,
|
|
257
514
|
options?: CreateRecordOptions,
|
|
258
515
|
) {
|
|
@@ -269,6 +526,15 @@ export class Client implements Agent {
|
|
|
269
526
|
})
|
|
270
527
|
}
|
|
271
528
|
|
|
529
|
+
/**
|
|
530
|
+
* Deletes a record from an AT Protocol repository.
|
|
531
|
+
*
|
|
532
|
+
* @param collection - The collection NSID
|
|
533
|
+
* @param rkey - The record key
|
|
534
|
+
* @param options - Delete options including repo, swapCommit, swapRecord
|
|
535
|
+
*
|
|
536
|
+
* @see {@link delete} for a higher-level typed alternative
|
|
537
|
+
*/
|
|
272
538
|
async deleteRecord(
|
|
273
539
|
collection: NsidString,
|
|
274
540
|
rkey: string,
|
|
@@ -286,6 +552,15 @@ export class Client implements Agent {
|
|
|
286
552
|
})
|
|
287
553
|
}
|
|
288
554
|
|
|
555
|
+
/**
|
|
556
|
+
* Retrieves a record from an AT Protocol repository.
|
|
557
|
+
*
|
|
558
|
+
* @param collection - The collection NSID
|
|
559
|
+
* @param rkey - The record key
|
|
560
|
+
* @param options - Get options including repo
|
|
561
|
+
*
|
|
562
|
+
* @see {@link get} for a higher-level typed alternative
|
|
563
|
+
*/
|
|
289
564
|
public async getRecord(
|
|
290
565
|
collection: NsidString,
|
|
291
566
|
rkey: string,
|
|
@@ -301,8 +576,17 @@ export class Client implements Agent {
|
|
|
301
576
|
})
|
|
302
577
|
}
|
|
303
578
|
|
|
579
|
+
/**
|
|
580
|
+
* Creates or updates a record in a repository.
|
|
581
|
+
*
|
|
582
|
+
* @param record - The record to put, must include an {@link NsidString} `$type`
|
|
583
|
+
* @param rkey - The record key
|
|
584
|
+
* @param options - Put options including repo, swapCommit, swapRecord, validate
|
|
585
|
+
*
|
|
586
|
+
* @see {@link put} for a higher-level typed alternative
|
|
587
|
+
*/
|
|
304
588
|
async putRecord(
|
|
305
|
-
record:
|
|
589
|
+
record: TypedLexMap<NsidString>,
|
|
306
590
|
rkey: string,
|
|
307
591
|
options?: PutRecordOptions,
|
|
308
592
|
) {
|
|
@@ -320,6 +604,14 @@ export class Client implements Agent {
|
|
|
320
604
|
})
|
|
321
605
|
}
|
|
322
606
|
|
|
607
|
+
/**
|
|
608
|
+
* Lists records in a collection.
|
|
609
|
+
*
|
|
610
|
+
* @param nsid - The collection NSID
|
|
611
|
+
* @param options - List options including repo, limit, cursor, reverse
|
|
612
|
+
*
|
|
613
|
+
* @see {@link list} for a higher-level typed alternative
|
|
614
|
+
*/
|
|
323
615
|
async listRecords(nsid: NsidString, options?: ListRecordsOptions) {
|
|
324
616
|
return this.xrpc(com.atproto.repo.listRecords.main, {
|
|
325
617
|
...options,
|
|
@@ -333,6 +625,22 @@ export class Client implements Agent {
|
|
|
333
625
|
})
|
|
334
626
|
}
|
|
335
627
|
|
|
628
|
+
/**
|
|
629
|
+
* Uploads a blob to an AT Protocol repository.
|
|
630
|
+
*
|
|
631
|
+
* @param body - The blob data (Uint8Array, ReadableStream, Blob, etc.)
|
|
632
|
+
* @param options - Upload options including encoding hint
|
|
633
|
+
* @returns Response containing the blob reference
|
|
634
|
+
*
|
|
635
|
+
* @example
|
|
636
|
+
* ```typescript
|
|
637
|
+
* const imageData = await fetch('image.png').then(r => r.arrayBuffer())
|
|
638
|
+
* const response = await client.uploadBlob(new Uint8Array(imageData), {
|
|
639
|
+
* encoding: 'image/png'
|
|
640
|
+
* })
|
|
641
|
+
* console.log(response.body.blob) // Use this ref in records
|
|
642
|
+
* ```
|
|
643
|
+
*/
|
|
336
644
|
async uploadBlob(
|
|
337
645
|
body: BinaryBodyInit,
|
|
338
646
|
options?: CallOptions & { encoding?: `${string}/${string}` },
|
|
@@ -343,6 +651,13 @@ export class Client implements Agent {
|
|
|
343
651
|
})
|
|
344
652
|
}
|
|
345
653
|
|
|
654
|
+
/**
|
|
655
|
+
* Retrieves a blob by DID and CID.
|
|
656
|
+
*
|
|
657
|
+
* @param did - The DID of the repository containing the blob
|
|
658
|
+
* @param cid - The CID of the blob
|
|
659
|
+
* @param options - Call options
|
|
660
|
+
*/
|
|
346
661
|
async getBlob(did: DidString, cid: CidString, options?: CallOptions) {
|
|
347
662
|
return this.xrpc(com.atproto.sync.getBlob.main, {
|
|
348
663
|
...options,
|
|
@@ -350,11 +665,42 @@ export class Client implements Agent {
|
|
|
350
665
|
})
|
|
351
666
|
}
|
|
352
667
|
|
|
668
|
+
/**
|
|
669
|
+
* Universal call method for queries, procedures, and custom actions.
|
|
670
|
+
* Automatically determines the call type based on the lexicon definition.
|
|
671
|
+
*
|
|
672
|
+
* @param ns - The lexicon method or action definition
|
|
673
|
+
* @param arg - The input argument (params for queries, body for procedures, input for actions)
|
|
674
|
+
* @param options - Call options
|
|
675
|
+
* @returns The method response body or action output
|
|
676
|
+
* @see {@link xrpc} if you need access to the full response object
|
|
677
|
+
*
|
|
678
|
+
* @example Query
|
|
679
|
+
* ```typescript
|
|
680
|
+
* const profile = await client.call(app.bsky.actor.getProfile.main, {
|
|
681
|
+
* actor: 'alice.bsky.social'
|
|
682
|
+
* })
|
|
683
|
+
* ```
|
|
684
|
+
*
|
|
685
|
+
* @example Procedure
|
|
686
|
+
* ```typescript
|
|
687
|
+
* const result = await client.call(com.atproto.repo.createRecord.main, {
|
|
688
|
+
* repo: did,
|
|
689
|
+
* collection: 'app.bsky.feed.post',
|
|
690
|
+
* record: { text: 'Hello!' }
|
|
691
|
+
* })
|
|
692
|
+
* ```
|
|
693
|
+
*/
|
|
353
694
|
public async call<const T extends Query>(
|
|
354
695
|
ns: NonNullable<unknown> extends XrpcRequestParams<T>
|
|
355
696
|
? Main<T>
|
|
356
697
|
: Restricted<'This query type requires a "params" argument'>,
|
|
357
698
|
): Promise<XrpcResponseBody<T>>
|
|
699
|
+
public async call<const T extends Procedure>(
|
|
700
|
+
ns: undefined extends InferMethodInputBody<T, Uint8Array>
|
|
701
|
+
? Main<T>
|
|
702
|
+
: Restricted<'This procedure type requires an "input" argument'>,
|
|
703
|
+
): Promise<XrpcResponseBody<T>>
|
|
358
704
|
public async call<const T extends Action>(
|
|
359
705
|
ns: void extends InferActionInput<T>
|
|
360
706
|
? Main<T>
|
|
@@ -401,6 +747,30 @@ export class Client implements Agent {
|
|
|
401
747
|
}
|
|
402
748
|
}
|
|
403
749
|
|
|
750
|
+
/**
|
|
751
|
+
* Creates a new record with full type safety based on the schema.
|
|
752
|
+
*
|
|
753
|
+
* @param ns - The record schema definition
|
|
754
|
+
* @param input - The record data (without `$type`, which is added automatically)
|
|
755
|
+
* @param options - Create options including rkey (required for some record types)
|
|
756
|
+
* @returns The create output including URI and CID
|
|
757
|
+
*
|
|
758
|
+
* @example Creating a post
|
|
759
|
+
* ```typescript
|
|
760
|
+
* const result = await client.create(app.bsky.feed.post.main, {
|
|
761
|
+
* text: 'Hello, world!',
|
|
762
|
+
* createdAt: new Date().toISOString()
|
|
763
|
+
* })
|
|
764
|
+
* console.log(result.uri)
|
|
765
|
+
* ```
|
|
766
|
+
*
|
|
767
|
+
* @example Creating a record with explicit rkey
|
|
768
|
+
* ```typescript
|
|
769
|
+
* const result = await client.create(app.bsky.actor.profile.main, {
|
|
770
|
+
* displayName: 'Alice'
|
|
771
|
+
* }, { rkey: 'self' })
|
|
772
|
+
* ```
|
|
773
|
+
*/
|
|
404
774
|
public async create<const T extends RecordSchema>(
|
|
405
775
|
ns: NonNullable<unknown> extends CreateOptions<T>
|
|
406
776
|
? Main<T>
|
|
@@ -418,13 +788,20 @@ export class Client implements Agent {
|
|
|
418
788
|
options: CreateOptions<T> = {} as CreateOptions<T>,
|
|
419
789
|
): Promise<CreateOutput> {
|
|
420
790
|
const schema: T = getMain(ns)
|
|
421
|
-
const record = schema.build(input) as
|
|
791
|
+
const record = schema.build(input) as TypedLexMap<NsidString>
|
|
422
792
|
const rkey = options.rkey ?? getDefaultRecordKey(schema)
|
|
423
793
|
if (rkey !== undefined) schema.keySchema.assert(rkey)
|
|
424
794
|
const response = await this.createRecord(record, rkey, options)
|
|
425
795
|
return response.body
|
|
426
796
|
}
|
|
427
797
|
|
|
798
|
+
/**
|
|
799
|
+
* Deletes a record with type-safe options.
|
|
800
|
+
*
|
|
801
|
+
* @param ns - The record schema definition
|
|
802
|
+
* @param options - Delete options (rkey required for non-literal keys)
|
|
803
|
+
* @returns The delete output
|
|
804
|
+
*/
|
|
428
805
|
public async delete<const T extends RecordSchema>(
|
|
429
806
|
ns: NonNullable<unknown> extends DeleteOptions<T>
|
|
430
807
|
? Main<T>
|
|
@@ -446,6 +823,20 @@ export class Client implements Agent {
|
|
|
446
823
|
return response.body
|
|
447
824
|
}
|
|
448
825
|
|
|
826
|
+
/**
|
|
827
|
+
* Retrieves a record with type-safe validation.
|
|
828
|
+
*
|
|
829
|
+
* @param ns - The record schema definition
|
|
830
|
+
* @param options - Get options (rkey required for non-literal keys)
|
|
831
|
+
* @returns The record data validated against the schema
|
|
832
|
+
*
|
|
833
|
+
* @example
|
|
834
|
+
* ```typescript
|
|
835
|
+
* const profile = await client.get(app.bsky.actor.profile.main)
|
|
836
|
+
* // profile.value is typed as app.bsky.actor.profile.Record
|
|
837
|
+
* console.log(profile.value.displayName)
|
|
838
|
+
* ```
|
|
839
|
+
*/
|
|
449
840
|
public async get<const T extends RecordSchema>(
|
|
450
841
|
ns: T['key'] extends `literal:${string}`
|
|
451
842
|
? Main<T>
|
|
@@ -468,6 +859,14 @@ export class Client implements Agent {
|
|
|
468
859
|
return { ...response.body, value }
|
|
469
860
|
}
|
|
470
861
|
|
|
862
|
+
/**
|
|
863
|
+
* Creates or updates a record with full type safety.
|
|
864
|
+
*
|
|
865
|
+
* @param ns - The record schema definition
|
|
866
|
+
* @param input - The record data
|
|
867
|
+
* @param options - Put options (rkey required for non-literal keys)
|
|
868
|
+
* @returns The put output including URI and CID
|
|
869
|
+
*/
|
|
471
870
|
public async put<const T extends RecordSchema>(
|
|
472
871
|
ns: NonNullable<unknown> extends PutOptions<T>
|
|
473
872
|
? Main<T>
|
|
@@ -485,12 +884,26 @@ export class Client implements Agent {
|
|
|
485
884
|
options: PutOptions<T> = {} as PutOptions<T>,
|
|
486
885
|
): Promise<PutOutput> {
|
|
487
886
|
const schema: T = getMain(ns)
|
|
488
|
-
const record = schema.build(input) as
|
|
887
|
+
const record = schema.build(input) as TypedLexMap<NsidString>
|
|
489
888
|
const rkey = options.rkey ?? getLiteralRecordKey(schema)
|
|
490
889
|
const response = await this.putRecord(record, rkey, options)
|
|
491
890
|
return response.body
|
|
492
891
|
}
|
|
493
892
|
|
|
893
|
+
/**
|
|
894
|
+
* Lists records with type-safe validation and separation of valid/invalid records.
|
|
895
|
+
*
|
|
896
|
+
* @param ns - The record schema definition
|
|
897
|
+
* @param options - List options
|
|
898
|
+
* @returns Records split into valid (matching schema) and invalid arrays
|
|
899
|
+
*
|
|
900
|
+
* @example
|
|
901
|
+
* ```typescript
|
|
902
|
+
* const result = await client.list(app.bsky.feed.post.main, { limit: 100 })
|
|
903
|
+
* console.log(`Found ${result.records.length} valid posts`)
|
|
904
|
+
* console.log(`Found ${result.invalid.length} invalid records`)
|
|
905
|
+
* ```
|
|
906
|
+
*/
|
|
494
907
|
async list<const T extends RecordSchema>(
|
|
495
908
|
ns: Main<T>,
|
|
496
909
|
options?: ListOptions,
|