@atproto/lex-client 0.0.11 → 0.0.13
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 +26 -0
- package/dist/agent.d.ts +67 -0
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +31 -0
- package/dist/agent.js.map +1 -1
- package/dist/client.d.ts +443 -45
- 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 +162 -9
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +132 -8
- package/dist/errors.js.map +1 -1
- package/dist/lexicons/com/atproto/repo/createRecord.defs.d.ts +29 -25
- package/dist/lexicons/com/atproto/repo/createRecord.defs.d.ts.map +1 -1
- package/dist/lexicons/com/atproto/repo/createRecord.defs.js +3 -2
- package/dist/lexicons/com/atproto/repo/createRecord.defs.js.map +1 -1
- package/dist/lexicons/com/atproto/repo/deleteRecord.defs.d.ts +17 -17
- package/dist/lexicons/com/atproto/repo/deleteRecord.defs.d.ts.map +1 -1
- package/dist/lexicons/com/atproto/repo/deleteRecord.defs.js.map +1 -1
- package/dist/lexicons/com/atproto/repo/getRecord.defs.d.ts +9 -9
- package/dist/lexicons/com/atproto/repo/getRecord.defs.d.ts.map +1 -1
- package/dist/lexicons/com/atproto/repo/getRecord.defs.js +1 -1
- package/dist/lexicons/com/atproto/repo/getRecord.defs.js.map +1 -1
- package/dist/lexicons/com/atproto/repo/listRecords.defs.d.ts +8 -8
- package/dist/lexicons/com/atproto/repo/listRecords.defs.d.ts.map +1 -1
- package/dist/lexicons/com/atproto/repo/listRecords.defs.js +1 -1
- package/dist/lexicons/com/atproto/repo/listRecords.defs.js.map +1 -1
- package/dist/lexicons/com/atproto/repo/putRecord.defs.d.ts +31 -27
- package/dist/lexicons/com/atproto/repo/putRecord.defs.d.ts.map +1 -1
- package/dist/lexicons/com/atproto/repo/putRecord.defs.js +3 -2
- package/dist/lexicons/com/atproto/repo/putRecord.defs.js.map +1 -1
- package/dist/lexicons/com/atproto/repo/uploadBlob.defs.d.ts +7 -7
- package/dist/lexicons/com/atproto/repo/uploadBlob.defs.d.ts.map +1 -1
- package/dist/lexicons/com/atproto/repo/uploadBlob.defs.js.map +1 -1
- package/dist/lexicons/com/atproto/sync/getBlob.defs.d.ts +3 -3
- package/dist/lexicons/com/atproto/sync/getBlob.defs.d.ts.map +1 -1
- package/dist/lexicons/com/atproto/sync/getBlob.defs.js.map +1 -1
- package/dist/response.d.ts +14 -4
- package/dist/response.d.ts.map +1 -1
- package/dist/response.js +19 -9
- 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 +23 -0
- package/dist/www-authenticate.d.ts.map +1 -1
- package/dist/www-authenticate.js.map +1 -1
- package/dist/xrpc.d.ts +81 -1
- package/dist/xrpc.d.ts.map +1 -1
- package/dist/xrpc.js.map +1 -1
- package/package.json +7 -7
- package/src/agent.ts +67 -0
- package/src/client.ts +424 -11
- package/src/errors.ts +165 -12
- package/src/lexicons/com/atproto/repo/createRecord.defs.ts +15 -7
- package/src/lexicons/com/atproto/repo/deleteRecord.defs.ts +11 -5
- package/src/lexicons/com/atproto/repo/getRecord.defs.ts +7 -4
- package/src/lexicons/com/atproto/repo/listRecords.defs.ts +8 -5
- package/src/lexicons/com/atproto/repo/putRecord.defs.ts +15 -7
- package/src/lexicons/com/atproto/repo/uploadBlob.defs.ts +11 -5
- package/src/lexicons/com/atproto/sync/getBlob.defs.ts +6 -3
- package/src/response.ts +22 -19
- package/src/types.ts +52 -0
- package/src/util.ts +50 -5
- package/src/www-authenticate.ts +24 -0
- package/src/xrpc.ts +83 -4
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,
|
|
@@ -15,7 +15,6 @@ import {
|
|
|
15
15
|
Query,
|
|
16
16
|
RecordSchema,
|
|
17
17
|
Restricted,
|
|
18
|
-
UnknownObject,
|
|
19
18
|
getMain,
|
|
20
19
|
} from '@atproto/lex-schema'
|
|
21
20
|
import { Agent, AgentOptions, buildAgent } from './agent.js'
|
|
@@ -30,63 +29,148 @@ export type {
|
|
|
30
29
|
AtIdentifierString,
|
|
31
30
|
CidString,
|
|
32
31
|
DidString,
|
|
32
|
+
Infer,
|
|
33
33
|
InferMethodInputBody,
|
|
34
34
|
InferMethodOutputBody,
|
|
35
35
|
InferRecordKey,
|
|
36
36
|
LexMap,
|
|
37
37
|
LexValue,
|
|
38
38
|
LexiconRecordKey,
|
|
39
|
+
Main,
|
|
39
40
|
NsidString,
|
|
40
41
|
Params,
|
|
41
42
|
Procedure,
|
|
42
43
|
Query,
|
|
43
44
|
RecordSchema,
|
|
44
45
|
Restricted,
|
|
46
|
+
TypedLexMap,
|
|
45
47
|
}
|
|
46
48
|
|
|
49
|
+
/**
|
|
50
|
+
* Configuration options for creating a {@link Client}.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```typescript
|
|
54
|
+
* const options: ClientOptions = {
|
|
55
|
+
* labelers: ['did:plc:labeler1'],
|
|
56
|
+
* service: 'did:web:api.bsky.app#bsky_appview',
|
|
57
|
+
* headers: { 'X-Custom-Header': 'value' }
|
|
58
|
+
* }
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
47
61
|
export type ClientOptions = {
|
|
62
|
+
/** Labeler DIDs to include in requests for content moderation. */
|
|
48
63
|
labelers?: Iterable<DidString>
|
|
64
|
+
/** Custom headers to include in all requests made by this client. */
|
|
49
65
|
headers?: HeadersInit
|
|
66
|
+
/** Service proxy identifier for routing requests through a specific service. */
|
|
50
67
|
service?: Service
|
|
51
68
|
}
|
|
52
69
|
|
|
70
|
+
/**
|
|
71
|
+
* A composable action that can be invoked via {@link Client.call}.
|
|
72
|
+
*
|
|
73
|
+
* Actions provide a way to define custom operations that integrate with the
|
|
74
|
+
* Client's call interface, enabling type-safe, reusable business logic.
|
|
75
|
+
*
|
|
76
|
+
* @typeParam I - The input type for the action
|
|
77
|
+
* @typeParam O - The output type for the action
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```typescript
|
|
81
|
+
* const myAction: Action<{ userId: string }, { profile: Profile }> = async (client, input, options) => {
|
|
82
|
+
* const response = await client.xrpc(someMethod, { params: { actor: input.userId }, ...options })
|
|
83
|
+
* return { profile: response.body }
|
|
84
|
+
* }
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
53
87
|
export type Action<I = any, O = any> = (
|
|
54
88
|
client: Client,
|
|
55
89
|
input: I,
|
|
56
90
|
options: CallOptions,
|
|
57
91
|
) => O | Promise<O>
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Extracts the input type from an {@link Action}.
|
|
95
|
+
* @typeParam A - The Action type to extract from
|
|
96
|
+
*/
|
|
58
97
|
export type InferActionInput<A extends Action> =
|
|
59
98
|
A extends Action<infer I, any> ? I : never
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Extracts the output type from an {@link Action}.
|
|
102
|
+
* @typeParam A - The Action type to extract from
|
|
103
|
+
*/
|
|
60
104
|
export type InferActionOutput<A extends Action> =
|
|
61
105
|
A extends Action<any, infer O> ? O : never
|
|
62
106
|
|
|
107
|
+
/**
|
|
108
|
+
* Options for creating a record in an AT Protocol repository.
|
|
109
|
+
*
|
|
110
|
+
* @see {@link Client.createRecord}
|
|
111
|
+
*/
|
|
63
112
|
export type CreateRecordOptions = CallOptions & {
|
|
113
|
+
/** Repository identifier (DID or handle). Defaults to authenticated user's DID. */
|
|
64
114
|
repo?: AtIdentifierString
|
|
115
|
+
/** Compare-and-swap on the repo commit. If specified, must match current commit. */
|
|
65
116
|
swapCommit?: string
|
|
117
|
+
/** Whether to validate the record against its lexicon schema. */
|
|
66
118
|
validate?: boolean
|
|
67
119
|
}
|
|
68
120
|
|
|
121
|
+
/**
|
|
122
|
+
* Options for deleting a record from an AT Protocol repository.
|
|
123
|
+
*
|
|
124
|
+
* @see {@link Client.deleteRecord}
|
|
125
|
+
*/
|
|
69
126
|
export type DeleteRecordOptions = CallOptions & {
|
|
127
|
+
/** Repository identifier (DID or handle). Defaults to authenticated user's DID. */
|
|
70
128
|
repo?: AtIdentifierString
|
|
129
|
+
/** Compare-and-swap on the repo commit. If specified, must match current commit. */
|
|
71
130
|
swapCommit?: string
|
|
131
|
+
/** Compare-and-swap on the record CID. If specified, must match current record. */
|
|
72
132
|
swapRecord?: string
|
|
73
133
|
}
|
|
74
134
|
|
|
135
|
+
/**
|
|
136
|
+
* Options for retrieving a record from an AT Protocol repository.
|
|
137
|
+
*
|
|
138
|
+
* @see {@link Client.getRecord}
|
|
139
|
+
*/
|
|
75
140
|
export type GetRecordOptions = CallOptions & {
|
|
141
|
+
/** Repository identifier (DID or handle). Defaults to authenticated user's DID. */
|
|
76
142
|
repo?: AtIdentifierString
|
|
77
143
|
}
|
|
78
144
|
|
|
145
|
+
/**
|
|
146
|
+
* Options for creating or updating a record in an AT Protocol repository.
|
|
147
|
+
*
|
|
148
|
+
* @see {@link Client.putRecord}
|
|
149
|
+
*/
|
|
79
150
|
export type PutRecordOptions = CallOptions & {
|
|
151
|
+
/** Repository identifier (DID or handle). Defaults to authenticated user's DID. */
|
|
80
152
|
repo?: AtIdentifierString
|
|
153
|
+
/** Compare-and-swap on the repo commit. If specified, must match current commit. */
|
|
81
154
|
swapCommit?: string
|
|
155
|
+
/** Compare-and-swap on the record CID. If specified, must match current record. */
|
|
82
156
|
swapRecord?: string
|
|
157
|
+
/** Whether to validate the record against its lexicon schema. */
|
|
83
158
|
validate?: boolean
|
|
84
159
|
}
|
|
85
160
|
|
|
161
|
+
/**
|
|
162
|
+
* Options for listing records in an AT Protocol repository collection.
|
|
163
|
+
*
|
|
164
|
+
* @see {@link Client.listRecords}
|
|
165
|
+
*/
|
|
86
166
|
export type ListRecordsOptions = CallOptions & {
|
|
167
|
+
/** Repository identifier (DID or handle). Defaults to authenticated user's DID. */
|
|
87
168
|
repo?: AtIdentifierString
|
|
169
|
+
/** Maximum number of records to return. */
|
|
88
170
|
limit?: number
|
|
171
|
+
/** Pagination cursor from a previous response. */
|
|
89
172
|
cursor?: string
|
|
173
|
+
/** If true, returns records in reverse chronological order. */
|
|
90
174
|
reverse?: boolean
|
|
91
175
|
}
|
|
92
176
|
|
|
@@ -97,48 +181,117 @@ export type RecordKeyOptions<
|
|
|
97
181
|
? { rkey?: InferRecordKey<T> }
|
|
98
182
|
: { rkey: InferRecordKey<T> }
|
|
99
183
|
|
|
184
|
+
/**
|
|
185
|
+
* Type-safe options for {@link Client.create}, combining record options with key requirements.
|
|
186
|
+
* @typeParam T - The record schema type
|
|
187
|
+
*/
|
|
100
188
|
export type CreateOptions<T extends RecordSchema> = CreateRecordOptions &
|
|
101
189
|
RecordKeyOptions<T, 'tid' | 'any'>
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Output type for record creation operations.
|
|
193
|
+
* Contains the URI and CID of the newly created record.
|
|
194
|
+
*/
|
|
102
195
|
export type CreateOutput = InferMethodOutputBody<
|
|
103
196
|
typeof com.atproto.repo.createRecord.main,
|
|
104
197
|
Uint8Array
|
|
105
198
|
>
|
|
106
199
|
|
|
200
|
+
/**
|
|
201
|
+
* Type-safe options for {@link Client.delete}, combining delete options with key requirements.
|
|
202
|
+
* @typeParam T - The record schema type
|
|
203
|
+
*/
|
|
107
204
|
export type DeleteOptions<T extends RecordSchema> = DeleteRecordOptions &
|
|
108
205
|
RecordKeyOptions<T>
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Output type for record deletion operations.
|
|
209
|
+
*/
|
|
109
210
|
export type DeleteOutput = InferMethodOutputBody<
|
|
110
211
|
typeof com.atproto.repo.deleteRecord.main,
|
|
111
212
|
Uint8Array
|
|
112
213
|
>
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Type-safe options for {@link Client.get}, combining get options with key requirements.
|
|
217
|
+
* @typeParam T - The record schema type
|
|
218
|
+
*/
|
|
113
219
|
export type GetOptions<T extends RecordSchema> = GetRecordOptions &
|
|
114
220
|
RecordKeyOptions<T>
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Output type for record retrieval operations.
|
|
224
|
+
* Contains the record value validated against the schema type.
|
|
225
|
+
* @typeParam T - The record schema type
|
|
226
|
+
*/
|
|
115
227
|
export type GetOutput<T extends RecordSchema> = Omit<
|
|
116
228
|
InferMethodOutputBody<typeof com.atproto.repo.getRecord.main, Uint8Array>,
|
|
117
229
|
'value'
|
|
118
230
|
> & { value: Infer<T> }
|
|
119
231
|
|
|
232
|
+
/**
|
|
233
|
+
* Type-safe options for {@link Client.put}, combining put options with key requirements.
|
|
234
|
+
* @typeParam T - The record schema type
|
|
235
|
+
*/
|
|
120
236
|
export type PutOptions<T extends RecordSchema> = PutRecordOptions &
|
|
121
237
|
RecordKeyOptions<T>
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Output type for record put (create/update) operations.
|
|
241
|
+
* Contains the URI and CID of the record.
|
|
242
|
+
*/
|
|
122
243
|
export type PutOutput = InferMethodOutputBody<
|
|
123
244
|
typeof com.atproto.repo.putRecord.main,
|
|
124
245
|
Uint8Array
|
|
125
246
|
>
|
|
126
247
|
|
|
248
|
+
/**
|
|
249
|
+
* Options for {@link Client.list} operations.
|
|
250
|
+
*/
|
|
127
251
|
export type ListOptions = ListRecordsOptions
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Output type for record listing operations.
|
|
255
|
+
* Contains validated records and any invalid records that failed schema validation.
|
|
256
|
+
* @typeParam T - The record schema type
|
|
257
|
+
*/
|
|
128
258
|
export type ListOutput<T extends RecordSchema> = InferMethodOutputBody<
|
|
129
259
|
typeof com.atproto.repo.listRecords.main,
|
|
130
260
|
Uint8Array
|
|
131
261
|
> & {
|
|
262
|
+
/** Records that successfully validated against the schema. */
|
|
132
263
|
records: ListRecord<Infer<T>>[]
|
|
133
264
|
// @NOTE Because the schema uses "type": "unknown" instead of an open union,
|
|
134
|
-
// we have to use
|
|
135
|
-
|
|
265
|
+
// we have to use LexMap instead of Unknown$TypedObject here, which is
|
|
266
|
+
// unfortunate.
|
|
267
|
+
/** Records that failed schema validation. */
|
|
268
|
+
invalid: LexMap[]
|
|
136
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
|
+
*/
|
|
137
275
|
export type ListRecord<Value extends LexMap> =
|
|
138
276
|
com.atproto.repo.listRecords.Record & {
|
|
139
277
|
value: Value
|
|
140
278
|
}
|
|
141
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
|
+
*/
|
|
142
295
|
export class Client implements Agent {
|
|
143
296
|
static appLabelers: readonly DidString[] = []
|
|
144
297
|
|
|
@@ -149,9 +302,16 @@ export class Client implements Agent {
|
|
|
149
302
|
if (opts.appLabelers) this.appLabelers = [...opts.appLabelers]
|
|
150
303
|
}
|
|
151
304
|
|
|
305
|
+
/** The underlying agent used for making requests. */
|
|
152
306
|
public readonly agent: Agent
|
|
307
|
+
|
|
308
|
+
/** Custom headers included in all requests. */
|
|
153
309
|
public readonly headers: Headers
|
|
310
|
+
|
|
311
|
+
/** Optional service identifier for routing requests. */
|
|
154
312
|
public readonly service?: Service
|
|
313
|
+
|
|
314
|
+
/** Set of labeler DIDs specific to this client instance. */
|
|
155
315
|
public readonly labelers: Set<DidString>
|
|
156
316
|
|
|
157
317
|
constructor(agent: Agent | AgentOptions, options: ClientOptions = {}) {
|
|
@@ -161,32 +321,68 @@ export class Client implements Agent {
|
|
|
161
321
|
this.headers = new Headers(options.headers)
|
|
162
322
|
}
|
|
163
323
|
|
|
324
|
+
/**
|
|
325
|
+
* The DID of the authenticated user, or `undefined` if not authenticated.
|
|
326
|
+
*/
|
|
164
327
|
get did(): DidString | undefined {
|
|
165
328
|
return this.agent.did
|
|
166
329
|
}
|
|
167
330
|
|
|
331
|
+
/**
|
|
332
|
+
* The DID of the authenticated user.
|
|
333
|
+
* @throws {LexError} with code 'AuthenticationRequired' if not authenticated
|
|
334
|
+
*/
|
|
168
335
|
get assertDid(): DidString {
|
|
169
336
|
this.assertAuthenticated()
|
|
170
337
|
return this.did
|
|
171
338
|
}
|
|
172
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
|
+
*/
|
|
173
353
|
public assertAuthenticated(): asserts this is { did: DidString } {
|
|
174
354
|
if (!this.did) throw new LexError('AuthenticationRequired')
|
|
175
355
|
}
|
|
176
356
|
|
|
357
|
+
/**
|
|
358
|
+
* Replaces all labelers with the given set.
|
|
359
|
+
* @param labelers - Iterable of labeler DIDs
|
|
360
|
+
*/
|
|
177
361
|
public setLabelers(labelers: Iterable<DidString> = []) {
|
|
178
362
|
this.clearLabelers()
|
|
179
363
|
this.addLabelers(labelers)
|
|
180
364
|
}
|
|
181
365
|
|
|
366
|
+
/**
|
|
367
|
+
* Adds labelers to the current set.
|
|
368
|
+
* @param labelers - Iterable of labeler DIDs to add
|
|
369
|
+
*/
|
|
182
370
|
public addLabelers(labelers: Iterable<DidString>) {
|
|
183
371
|
for (const labeler of labelers) this.labelers.add(labeler)
|
|
184
372
|
}
|
|
185
373
|
|
|
374
|
+
/**
|
|
375
|
+
* Removes all labelers from this client instance.
|
|
376
|
+
*/
|
|
186
377
|
public clearLabelers() {
|
|
187
378
|
this.labelers.clear()
|
|
188
379
|
}
|
|
189
380
|
|
|
381
|
+
/**
|
|
382
|
+
* Low-level fetch handler for making requests.
|
|
383
|
+
* @param path - The request path
|
|
384
|
+
* @param init - Request initialization options
|
|
385
|
+
*/
|
|
190
386
|
public fetchHandler(path: string, init: RequestInit): Promise<Response> {
|
|
191
387
|
const headers = buildAtprotoHeaders({
|
|
192
388
|
headers: init.headers,
|
|
@@ -209,7 +405,33 @@ export class Client implements Agent {
|
|
|
209
405
|
}
|
|
210
406
|
|
|
211
407
|
/**
|
|
212
|
-
*
|
|
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
|
|
213
435
|
*/
|
|
214
436
|
async xrpc<const M extends Query | Procedure>(
|
|
215
437
|
ns: NonNullable<unknown> extends XrpcOptions<M>
|
|
@@ -227,6 +449,29 @@ export class Client implements Agent {
|
|
|
227
449
|
return xrpc(this, ns, options)
|
|
228
450
|
}
|
|
229
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
|
+
*/
|
|
230
475
|
async xrpcSafe<const M extends Query | Procedure>(
|
|
231
476
|
ns: NonNullable<unknown> extends XrpcOptions<M>
|
|
232
477
|
? Main<M>
|
|
@@ -244,10 +489,27 @@ export class Client implements Agent {
|
|
|
244
489
|
}
|
|
245
490
|
|
|
246
491
|
/**
|
|
247
|
-
*
|
|
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
|
|
248
510
|
*/
|
|
249
511
|
public async createRecord(
|
|
250
|
-
record:
|
|
512
|
+
record: TypedLexMap<NsidString>,
|
|
251
513
|
rkey?: string,
|
|
252
514
|
options?: CreateRecordOptions,
|
|
253
515
|
) {
|
|
@@ -264,6 +526,15 @@ export class Client implements Agent {
|
|
|
264
526
|
})
|
|
265
527
|
}
|
|
266
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
|
+
*/
|
|
267
538
|
async deleteRecord(
|
|
268
539
|
collection: NsidString,
|
|
269
540
|
rkey: string,
|
|
@@ -281,6 +552,15 @@ export class Client implements Agent {
|
|
|
281
552
|
})
|
|
282
553
|
}
|
|
283
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
|
+
*/
|
|
284
564
|
public async getRecord(
|
|
285
565
|
collection: NsidString,
|
|
286
566
|
rkey: string,
|
|
@@ -296,8 +576,17 @@ export class Client implements Agent {
|
|
|
296
576
|
})
|
|
297
577
|
}
|
|
298
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
|
+
*/
|
|
299
588
|
async putRecord(
|
|
300
|
-
record:
|
|
589
|
+
record: TypedLexMap<NsidString>,
|
|
301
590
|
rkey: string,
|
|
302
591
|
options?: PutRecordOptions,
|
|
303
592
|
) {
|
|
@@ -315,6 +604,14 @@ export class Client implements Agent {
|
|
|
315
604
|
})
|
|
316
605
|
}
|
|
317
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
|
+
*/
|
|
318
615
|
async listRecords(nsid: NsidString, options?: ListRecordsOptions) {
|
|
319
616
|
return this.xrpc(com.atproto.repo.listRecords.main, {
|
|
320
617
|
...options,
|
|
@@ -328,6 +625,22 @@ export class Client implements Agent {
|
|
|
328
625
|
})
|
|
329
626
|
}
|
|
330
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
|
+
*/
|
|
331
644
|
async uploadBlob(
|
|
332
645
|
body: BinaryBodyInit,
|
|
333
646
|
options?: CallOptions & { encoding?: `${string}/${string}` },
|
|
@@ -338,6 +651,13 @@ export class Client implements Agent {
|
|
|
338
651
|
})
|
|
339
652
|
}
|
|
340
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
|
+
*/
|
|
341
661
|
async getBlob(did: DidString, cid: CidString, options?: CallOptions) {
|
|
342
662
|
return this.xrpc(com.atproto.sync.getBlob.main, {
|
|
343
663
|
...options,
|
|
@@ -345,6 +665,32 @@ export class Client implements Agent {
|
|
|
345
665
|
})
|
|
346
666
|
}
|
|
347
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
|
+
*/
|
|
348
694
|
public async call<const T extends Query>(
|
|
349
695
|
ns: NonNullable<unknown> extends XrpcRequestParams<T>
|
|
350
696
|
? 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,
|
|
@@ -528,7 +941,7 @@ function getLiteralRecordKey<const T extends RecordSchema>(
|
|
|
528
941
|
schema: T,
|
|
529
942
|
): InferRecordKey<T> {
|
|
530
943
|
if (schema.key.startsWith('literal:')) {
|
|
531
|
-
return schema.key.slice(8)
|
|
944
|
+
return schema.key.slice(8) as InferRecordKey<T>
|
|
532
945
|
}
|
|
533
946
|
|
|
534
947
|
throw new TypeError(
|