@atcute/client 3.0.0 → 3.1.0

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.
@@ -1,65 +1,71 @@
1
1
  import type { At, ComAtprotoServerCreateSession } from './lexicons.js';
2
2
 
3
+ import { Client, ClientResponseError, isXRPCErrorPayload, ok } from './client.js';
3
4
  import { simpleFetchHandler, type FetchHandlerObject } from './fetch-handler.js';
4
- import { XRPC, XRPCError } from './rpc.js';
5
5
 
6
6
  import { getPdsEndpoint, type DidDocument } from './utils/did.js';
7
7
  import { decodeJwt } from './utils/jwt.js';
8
8
 
9
- /** Interface for the decoded access token, for convenience */
9
+ /**
10
+ * represents the decoded access token, for convenience
11
+ * @deprecated
12
+ */
10
13
  export interface AtpAccessJwt {
11
- /** Access token scope, app password returns a different scope. */
14
+ /** access token scope */
12
15
  scope:
13
16
  | 'com.atproto.access'
14
17
  | 'com.atproto.appPass'
15
18
  | 'com.atproto.appPassPrivileged'
16
19
  | 'com.atproto.signupQueued'
17
20
  | 'com.atproto.takendown';
18
- /** Account DID */
21
+ /** account DID */
19
22
  sub: At.Did;
20
- /** Expiration time */
23
+ /** expiration time in Unix seconds */
21
24
  exp: number;
22
- /** Creation/issued time */
25
+ /** token issued time in Unix seconds */
23
26
  iat: number;
24
27
  }
25
28
 
26
- /** Interface for the decoded refresh token, for convenience */
29
+ /**
30
+ * represents the the decoded refresh token, for convenience
31
+ * @deprecated
32
+ */
27
33
  export interface AtpRefreshJwt {
28
- /** Refresh token scope */
34
+ /** refresh token scope */
29
35
  scope: 'com.atproto.refresh';
30
- /** ID of this refresh token */
36
+ /** unique identifier for this session */
31
37
  jti: string;
32
- /** Account DID */
38
+ /** account DID */
33
39
  sub: At.Did;
34
- /** Intended audience of this refresh token, in DID */
40
+ /** intended audience of this refresh token, in DID */
35
41
  aud: At.Did;
36
- /** Expiration time */
42
+ /** token expiration time in seconds */
37
43
  exp: number;
38
- /** Creation/issued time */
44
+ /** token issued time in seconds */
39
45
  iat: number;
40
46
  }
41
47
 
42
- /** Saved session data, this can be reused again for next time. */
48
+ /** session data, can be persisted and reused */
43
49
  export interface AtpSessionData {
44
- /** Refresh token */
50
+ /** refresh token */
45
51
  refreshJwt: string;
46
- /** Access token */
52
+ /** access token */
47
53
  accessJwt: string;
48
- /** Account handle */
54
+ /** account handle */
49
55
  handle: string;
50
- /** Account DID */
56
+ /** account DID */
51
57
  did: At.Did;
52
58
  /** PDS endpoint found in the DID document, this will be used as the service URI if provided */
53
59
  pdsUri?: string;
54
- /** Email address of the account, might not be available if on app password */
60
+ /** email address of the account, might not be available if on app password */
55
61
  email?: string;
56
- /** If the email address has been confirmed or not */
62
+ /** whether the email address has been confirmed or not */
57
63
  emailConfirmed?: boolean;
58
- /** If the account has email-based two-factor authentication enabled */
64
+ /** whether the account has email-based two-factor authentication enabled */
59
65
  emailAuthFactor?: boolean;
60
- /** Whether the account is active (not deactivated, taken down, or suspended) */
66
+ /** whether the account is active (not deactivated, taken down, or suspended) */
61
67
  active: boolean;
62
- /** Possible reason for why the account is inactive */
68
+ /** possible reason for why the account is inactive */
63
69
  inactiveStatus?: string;
64
70
  }
65
71
 
@@ -67,29 +73,36 @@ export interface CredentialManagerOptions {
67
73
  /** PDS server URL */
68
74
  service: string;
69
75
 
70
- /** Custom fetch function */
71
- fetch?: typeof globalThis.fetch;
76
+ /** custom fetch function */
77
+ fetch?: typeof fetch;
72
78
 
73
- /** Function that gets called if the session turned out to have expired during an XRPC request */
79
+ /** function called when the session expires and can't be refreshed */
74
80
  onExpired?: (session: AtpSessionData) => void;
75
- /** Function that gets called if the session has been refreshed during an XRPC request */
81
+ /** function called after a successful session refresh */
76
82
  onRefresh?: (session: AtpSessionData) => void;
77
- /** Function that gets called if the session object has been refreshed */
83
+ /** function called whenever the session object is updated (login, resume, refresh) */
78
84
  onSessionUpdate?: (session: AtpSessionData) => void;
79
85
  }
80
86
 
81
87
  export class CredentialManager implements FetchHandlerObject {
88
+ /** service URL to make authentication requests with */
82
89
  readonly serviceUrl: string;
90
+ /** fetch implementation */
83
91
  fetch: typeof fetch;
84
92
 
85
- #server: XRPC;
93
+ /** internal client instance for making authentication requests */
94
+ #server: Client;
95
+ /** holds a promise for the current refresh operation, used for debouncing */
86
96
  #refreshSessionPromise: Promise<void> | undefined;
87
97
 
98
+ /** callback for session expiration */
88
99
  #onExpired: CredentialManagerOptions['onExpired'];
100
+ /** callback for successful session refresh */
89
101
  #onRefresh: CredentialManagerOptions['onRefresh'];
102
+ /** callback for session updates */
90
103
  #onSessionUpdate: CredentialManagerOptions['onSessionUpdate'];
91
104
 
92
- /** Current session state */
105
+ /** current active session, undefined if not authenticated */
93
106
  session?: AtpSessionData;
94
107
 
95
108
  constructor({
@@ -102,13 +115,14 @@ export class CredentialManager implements FetchHandlerObject {
102
115
  this.serviceUrl = service;
103
116
  this.fetch = _fetch;
104
117
 
105
- this.#server = new XRPC({ handler: simpleFetchHandler({ service: service, fetch: _fetch }) });
118
+ this.#server = new Client({ handler: simpleFetchHandler({ service, fetch: _fetch }) });
106
119
 
107
120
  this.#onRefresh = onRefresh;
108
121
  this.#onExpired = onExpired;
109
122
  this.#onSessionUpdate = onSessionUpdate;
110
123
  }
111
124
 
125
+ /** service URL to make actual API requests with */
112
126
  get dispatchUrl() {
113
127
  return this.session?.pdsUri ?? this.serviceUrl;
114
128
  }
@@ -138,13 +152,14 @@ export class CredentialManager implements FetchHandlerObject {
138
152
  return initialResponse;
139
153
  }
140
154
 
141
- // Return initial response if:
142
- // - refreshSession returns expired
143
- // - Body stream has been consumed
155
+ // return initial response if:
156
+ // - the above refreshSession failed and cleared the session
157
+ // - provided request body was a stream, which can't be resent once consumed
144
158
  if (!this.session || init.body instanceof ReadableStream) {
145
159
  return initialResponse;
146
160
  }
147
161
 
162
+ // set the new token and retry the request
148
163
  headers.set('authorization', `Bearer ${this.session.accessJwt}`);
149
164
 
150
165
  return await (0, this.fetch)(url, { ...init, headers });
@@ -158,30 +173,29 @@ export class CredentialManager implements FetchHandlerObject {
158
173
 
159
174
  async #refreshSessionInner(): Promise<void> {
160
175
  const currentSession = this.session;
161
-
162
176
  if (!currentSession) {
163
177
  return;
164
178
  }
165
179
 
166
- try {
167
- const { data } = await this.#server.call('com.atproto.server.refreshSession', {
168
- headers: {
169
- authorization: `Bearer ${currentSession.refreshJwt}`,
170
- },
171
- });
172
-
173
- this.#updateSession({ ...currentSession, ...data });
174
- this.#onRefresh?.(this.session!);
175
- } catch (err) {
176
- if (err instanceof XRPCError) {
177
- const kind = err.kind;
178
-
179
- if (kind === 'ExpiredToken' || kind === 'InvalidToken') {
180
- this.session = undefined;
181
- this.#onExpired?.(currentSession);
182
- }
180
+ const response = await this.#server.post('com.atproto.server.refreshSession', {
181
+ headers: {
182
+ authorization: `Bearer ${currentSession.refreshJwt}`,
183
+ },
184
+ });
185
+
186
+ if (!response.ok) {
187
+ const error = response.data.error;
188
+
189
+ if (error === 'ExpiredToken' || error === 'InvalidToken') {
190
+ this.session = undefined;
191
+ this.#onExpired?.(currentSession);
183
192
  }
193
+
194
+ throw new ClientResponseError(response);
184
195
  }
196
+
197
+ this.#updateSession({ ...currentSession, ...response.data });
198
+ this.#onRefresh?.(this.session!);
185
199
  }
186
200
 
187
201
  #updateSession(raw: ComAtprotoServerCreateSession.Output): AtpSessionData {
@@ -192,7 +206,7 @@ export class CredentialManager implements FetchHandlerObject {
192
206
  pdsUri = getPdsEndpoint(didDoc);
193
207
  }
194
208
 
195
- const newSession = {
209
+ const newSession: AtpSessionData = {
196
210
  accessJwt: raw.accessJwt,
197
211
  refreshJwt: raw.refreshJwt,
198
212
  handle: raw.handle,
@@ -200,7 +214,7 @@ export class CredentialManager implements FetchHandlerObject {
200
214
  pdsUri: pdsUri,
201
215
  email: raw.email,
202
216
  emailConfirmed: raw.emailConfirmed,
203
- emailAuthFactor: raw.emailConfirmed,
217
+ emailAuthFactor: raw.emailAuthFactor,
204
218
  active: raw.active ?? true,
205
219
  inactiveStatus: raw.status,
206
220
  };
@@ -212,16 +226,16 @@ export class CredentialManager implements FetchHandlerObject {
212
226
  }
213
227
 
214
228
  /**
215
- * Resume a saved session
216
- * @param session Session information, taken from `AtpAuth#session` after login
229
+ * resume from a persisted session
230
+ * @param session session data, taken from `AtpAuth#session` after login
217
231
  */
218
232
  async resume(session: AtpSessionData): Promise<AtpSessionData> {
219
- const now = Date.now() / 1000 + 60 * 5;
233
+ const now = Date.now() / 1_000 + 60 * 5;
220
234
 
221
235
  const refreshToken = decodeJwt(session.refreshJwt) as AtpRefreshJwt;
222
236
 
223
237
  if (now >= refreshToken.exp) {
224
- throw new XRPCError(401, { kind: 'InvalidToken' });
238
+ throw new ClientResponseError({ status: 401, data: { error: 'InvalidToken' } });
225
239
  }
226
240
 
227
241
  const accessToken = decodeJwt(session.accessJwt) as AtpAccessJwt;
@@ -230,62 +244,69 @@ export class CredentialManager implements FetchHandlerObject {
230
244
  if (now >= accessToken.exp) {
231
245
  await this.#refreshSession();
232
246
  } else {
233
- const promise = this.#server.get('com.atproto.server.getSession', {
234
- headers: {
235
- authorization: `Bearer ${session.accessJwt}`,
247
+ const promise = ok(
248
+ this.#server.get('com.atproto.server.getSession', {
249
+ headers: {
250
+ authorization: `Bearer ${session.accessJwt}`,
251
+ },
252
+ }),
253
+ );
254
+
255
+ promise.then(
256
+ (next) => {
257
+ const existing = this.session;
258
+ if (!existing || existing.did !== next.did) {
259
+ return;
260
+ }
261
+
262
+ this.#updateSession({ ...existing, ...next });
236
263
  },
237
- });
238
-
239
- promise.then((response) => {
240
- const existing = this.session;
241
- const next = response.data;
242
-
243
- if (!existing) {
244
- return;
245
- }
246
-
247
- this.#updateSession({ ...existing, ...next });
248
- });
264
+ (_err) => {
265
+ // ignore error
266
+ },
267
+ );
249
268
  }
250
269
 
251
270
  if (!this.session) {
252
- throw new XRPCError(401, { kind: 'InvalidToken' });
271
+ throw new ClientResponseError({ status: 401, data: { error: 'InvalidToken' } });
253
272
  }
254
273
 
255
274
  return this.session;
256
275
  }
257
276
 
258
277
  /**
259
- * Perform a login operation
260
- * @param options Login options
261
- * @returns Session data that can be saved for later
278
+ * sign in to an account
279
+ * @param options credential options
280
+ * @returns session data
262
281
  */
263
282
  async login(options: AuthLoginOptions): Promise<AtpSessionData> {
264
283
  // Reset the session
265
284
  this.session = undefined;
266
285
 
267
- const res = await this.#server.call('com.atproto.server.createSession', {
268
- data: {
269
- identifier: options.identifier,
270
- password: options.password,
271
- authFactorToken: options.code,
272
- allowTakendown: options.allowTakendown,
273
- },
274
- });
286
+ const session = await ok(
287
+ this.#server.post('com.atproto.server.createSession', {
288
+ input: {
289
+ identifier: options.identifier,
290
+ password: options.password,
291
+ authFactorToken: options.code,
292
+ allowTakendown: options.allowTakendown,
293
+ },
294
+ }),
295
+ );
275
296
 
276
- return this.#updateSession(res.data);
297
+ return this.#updateSession(session);
277
298
  }
278
299
  }
279
300
 
280
- /** Login options */
301
+ /** credentials */
281
302
  export interface AuthLoginOptions {
282
- /** What account to login as, this could be domain handle, DID, or email address */
303
+ /** what account to login as, this could be domain handle, DID, or email address */
283
304
  identifier: string;
284
- /** Account password */
305
+ /** account password */
285
306
  password: string;
286
- /** Two-factor authentication code */
307
+ /** two-factor authentication code, if email TOTP is enabled */
287
308
  code?: string;
288
- /** Allow signing in even if the account has been taken down, */
309
+ /** allow signing in even if the account has been taken down */
289
310
  allowTakendown?: boolean;
290
311
  }
291
312
 
@@ -298,6 +319,9 @@ const isExpiredTokenResponse = async (response: Response): Promise<boolean> => {
298
319
  return false;
299
320
  }
300
321
 
322
+ // this is nasty as it relies heavily on what the PDS returns, but avoiding
323
+ // cloning and reading the request as much as possible is better.
324
+
301
325
  // {"error":"ExpiredToken","message":"Token has expired"}
302
326
  // {"error":"ExpiredToken","message":"Token is expired"}
303
327
  if (extractContentLength(response.headers) > 54 * 1.5) {
@@ -305,8 +329,10 @@ const isExpiredTokenResponse = async (response: Response): Promise<boolean> => {
305
329
  }
306
330
 
307
331
  try {
308
- const { error, message } = await response.clone().json();
309
- return error === 'ExpiredToken' && (typeof message === 'string' || message === undefined);
332
+ const data = await response.clone().json();
333
+ if (isXRPCErrorPayload(data)) {
334
+ return data.error === 'ExpiredToken';
335
+ }
310
336
  } catch {}
311
337
 
312
338
  return false;
@@ -1,7 +1,7 @@
1
- /** Fetch handler function */
1
+ /** fetch handler function */
2
2
  export type FetchHandler = (pathname: string, init: RequestInit) => Promise<Response>;
3
3
 
4
- /** Fetch handler in an object */
4
+ /** fetch handler in an object */
5
5
  export interface FetchHandlerObject {
6
6
  handle(this: FetchHandlerObject, pathname: string, init: RequestInit): Promise<Response>;
7
7
  }
@@ -25,6 +25,6 @@ export const simpleFetchHandler = ({
25
25
  }: SimpleFetchHandlerOptions): FetchHandler => {
26
26
  return async (pathname, init) => {
27
27
  const url = new URL(pathname, service);
28
- return _fetch(url, init);
28
+ return await _fetch(url, init);
29
29
  };
30
30
  };
package/lib/index.ts CHANGED
@@ -1,3 +1,4 @@
1
- export * from './rpc.js';
2
- export * from './fetch-handler.js';
1
+ export * from './client.js';
3
2
  export * from './credential-manager.js';
3
+ export * from './fetch-handler.js';
4
+ export * from './rpc.js';
package/lib/lexicons.ts CHANGED
@@ -316,6 +316,17 @@ export declare namespace ComAtprotoAdminUpdateAccountPassword {
316
316
  type Output = undefined;
317
317
  }
318
318
 
319
+ /** Administrative action to update an account's signing key in their Did document. */
320
+ export declare namespace ComAtprotoAdminUpdateAccountSigningKey {
321
+ interface Params {}
322
+ interface Input {
323
+ did: At.Did;
324
+ /** Did-key formatted public key */
325
+ signingKey: At.Did;
326
+ }
327
+ type Output = undefined;
328
+ }
329
+
319
330
  /** Update the service-specific admin status of a subject (account, record, or blob). */
320
331
  export declare namespace ComAtprotoAdminUpdateSubjectStatus {
321
332
  interface Params {}
@@ -1336,6 +1347,10 @@ export declare namespace ComAtprotoServerUpdateEmail {
1336
1347
  }
1337
1348
  }
1338
1349
 
1350
+ export declare namespace ComAtprotoSyncDefs {
1351
+ type HostStatus = 'active' | 'banned' | 'idle' | 'offline' | 'throttled' | (string & {});
1352
+ }
1353
+
1339
1354
  /** Get a blob associated with a given account. Returns the full blob as originally uploaded. Does not require auth; implemented by PDS. */
1340
1355
  export declare namespace ComAtprotoSyncGetBlob {
1341
1356
  interface Params {
@@ -1404,6 +1419,26 @@ export declare namespace ComAtprotoSyncGetHead {
1404
1419
  }
1405
1420
  }
1406
1421
 
1422
+ /** Returns information about a specified upstream host, as consumed by the server. Implemented by relays. */
1423
+ export declare namespace ComAtprotoSyncGetHostStatus {
1424
+ interface Params {
1425
+ /** Hostname of the host (eg, PDS or relay) being queried. */
1426
+ hostname: string;
1427
+ }
1428
+ type Input = undefined;
1429
+ interface Output {
1430
+ hostname: string;
1431
+ /** Number of accounts on the server which are associated with the upstream host. Note that the upstream may actually have more accounts. */
1432
+ accountCount?: number;
1433
+ /** Recent repo stream event sequence number. May be delayed from actual stream processing (eg, persisted cursor not in-memory cursor). */
1434
+ seq?: number;
1435
+ status?: ComAtprotoSyncDefs.HostStatus;
1436
+ }
1437
+ interface Errors {
1438
+ HostNotFound: {};
1439
+ }
1440
+ }
1441
+
1407
1442
  /** Get the current commit CID & revision of the specified repo. Does not require auth. */
1408
1443
  export declare namespace ComAtprotoSyncGetLatestCommit {
1409
1444
  interface Params {
@@ -1516,6 +1551,34 @@ export declare namespace ComAtprotoSyncListBlobs {
1516
1551
  }
1517
1552
  }
1518
1553
 
1554
+ /** Enumerates upstream hosts (eg, PDS or relay instances) that this service consumes from. Implemented by relays. */
1555
+ export declare namespace ComAtprotoSyncListHosts {
1556
+ interface Params {
1557
+ cursor?: string;
1558
+ /**
1559
+ * Minimum: 1 \
1560
+ * Maximum: 1000
1561
+ * @default 200
1562
+ */
1563
+ limit?: number;
1564
+ }
1565
+ type Input = undefined;
1566
+ interface Output {
1567
+ /** Sort order is not formally specified. Recommended order is by time host was first seen by the server, with oldest first. */
1568
+ hosts: Host[];
1569
+ cursor?: string;
1570
+ }
1571
+ interface Host {
1572
+ [Brand.Type]?: 'com.atproto.sync.listHosts#host';
1573
+ /** hostname of server; not a URL (no scheme) */
1574
+ hostname: string;
1575
+ accountCount?: number;
1576
+ /** Recent repo stream event sequence number. May be delayed from actual stream processing (eg, persisted cursor not in-memory cursor). */
1577
+ seq?: number;
1578
+ status?: ComAtprotoSyncDefs.HostStatus;
1579
+ }
1580
+ }
1581
+
1519
1582
  /** Enumerates all the DID, rev, and commit CID for all repos hosted by this service. Does not require auth; implemented by PDS and Relay. */
1520
1583
  export declare namespace ComAtprotoSyncListRepos {
1521
1584
  interface Params {
@@ -1593,6 +1656,9 @@ export declare namespace ComAtprotoSyncRequestCrawl {
1593
1656
  hostname: string;
1594
1657
  }
1595
1658
  type Output = undefined;
1659
+ interface Errors {
1660
+ HostBanned: {};
1661
+ }
1596
1662
  }
1597
1663
 
1598
1664
  export declare namespace ComAtprotoSyncSubscribeRepos {
@@ -1887,6 +1953,12 @@ export declare interface Queries {
1887
1953
  output: ComAtprotoSyncGetHead.Output;
1888
1954
  response: { json: ComAtprotoSyncGetHead.Output };
1889
1955
  };
1956
+ 'com.atproto.sync.getHostStatus': {
1957
+ params: ComAtprotoSyncGetHostStatus.Params;
1958
+ /** @deprecated */
1959
+ output: ComAtprotoSyncGetHostStatus.Output;
1960
+ response: { json: ComAtprotoSyncGetHostStatus.Output };
1961
+ };
1890
1962
  'com.atproto.sync.getLatestCommit': {
1891
1963
  params: ComAtprotoSyncGetLatestCommit.Params;
1892
1964
  /** @deprecated */
@@ -1917,6 +1989,12 @@ export declare interface Queries {
1917
1989
  output: ComAtprotoSyncListBlobs.Output;
1918
1990
  response: { json: ComAtprotoSyncListBlobs.Output };
1919
1991
  };
1992
+ 'com.atproto.sync.listHosts': {
1993
+ params: ComAtprotoSyncListHosts.Params;
1994
+ /** @deprecated */
1995
+ output: ComAtprotoSyncListHosts.Output;
1996
+ response: { json: ComAtprotoSyncListHosts.Output };
1997
+ };
1920
1998
  'com.atproto.sync.listRepos': {
1921
1999
  params: ComAtprotoSyncListRepos.Params;
1922
2000
  /** @deprecated */
@@ -1970,6 +2048,9 @@ export declare interface Procedures {
1970
2048
  'com.atproto.admin.updateAccountPassword': {
1971
2049
  input: ComAtprotoAdminUpdateAccountPassword.Input;
1972
2050
  };
2051
+ 'com.atproto.admin.updateAccountSigningKey': {
2052
+ input: ComAtprotoAdminUpdateAccountSigningKey.Input;
2053
+ };
1973
2054
  'com.atproto.admin.updateSubjectStatus': {
1974
2055
  input: ComAtprotoAdminUpdateSubjectStatus.Input;
1975
2056
  /** @deprecated */
package/lib/rpc.ts CHANGED
@@ -3,15 +3,24 @@ import type { At, Procedures, Queries } from './lexicons.js';
3
3
  import { buildFetchHandler, type FetchHandler, type FetchHandlerObject } from './fetch-handler.js';
4
4
  import { mergeHeaders } from './utils/http.js';
5
5
 
6
+ /**
7
+ * @deprecated
8
+ */
6
9
  export type HeadersObject = Record<string, string>;
7
10
 
8
- /** Response from XRPC service */
11
+ /**
12
+ * Response from XRPC service
13
+ * @deprecated
14
+ */
9
15
  export interface XRPCResponse<T = any> {
10
16
  data: T;
11
17
  headers: HeadersObject;
12
18
  }
13
19
 
14
- /** Options for constructing an XRPC error */
20
+ /**
21
+ * Options for constructing an XRPC error
22
+ * @deprecated
23
+ */
15
24
  export interface XRPCErrorOptions {
16
25
  kind?: string;
17
26
  description?: string;
@@ -19,7 +28,10 @@ export interface XRPCErrorOptions {
19
28
  cause?: unknown;
20
29
  }
21
30
 
22
- /** Error coming from the XRPC service */
31
+ /**
32
+ * Error coming from the XRPC service
33
+ * @deprecated
34
+ */
23
35
  export class XRPCError extends Error {
24
36
  override name = 'XRPCError';
25
37
 
@@ -50,19 +62,28 @@ export class XRPCError extends Error {
50
62
  }
51
63
  }
52
64
 
53
- /** Service proxy options */
65
+ /**
66
+ * Service proxy options
67
+ * @deprecated
68
+ */
54
69
  export interface XRPCProxyOptions {
55
70
  type: 'atproto_pds' | 'atproto_labeler' | 'bsky_fg' | 'bsky_notif' | ({} & string);
56
71
  service: At.Did;
57
72
  }
58
73
 
59
- /** Options for constructing an XRPC */
74
+ /**
75
+ * Options for constructing an XRPC
76
+ * @deprecated
77
+ */
60
78
  export interface XRPCOptions {
61
79
  handler: FetchHandler | FetchHandlerObject;
62
80
  proxy?: XRPCProxyOptions;
63
81
  }
64
82
 
65
- /** XRPC request options */
83
+ /**
84
+ * XRPC request options
85
+ * @deprecated
86
+ */
66
87
  export interface XRPCRequestOptions {
67
88
  type: 'get' | 'post';
68
89
  nsid: string;
@@ -72,7 +93,10 @@ export interface XRPCRequestOptions {
72
93
  signal?: AbortSignal;
73
94
  }
74
95
 
75
- /** XRPC response */
96
+ /**
97
+ * XRPC response
98
+ * @deprecated
99
+ */
76
100
  export interface XRPCResponse<T = any> {
77
101
  data: T;
78
102
  headers: HeadersObject;
@@ -86,13 +110,19 @@ interface BaseRPCOptions {
86
110
  signal?: AbortSignal;
87
111
  }
88
112
 
89
- /** Options for the query/procedure request */
113
+ /**
114
+ * Options for the query/procedure request
115
+ * @deprecated
116
+ */
90
117
  export type RPCOptions<T> = BaseRPCOptions &
91
118
  (T extends { params: any } ? { params: T['params'] } : {}) &
92
119
  (T extends { input: any } ? { data: T['input'] } : {});
93
120
 
94
121
  type OutputOf<T> = T extends { output: any } ? T['output'] : never;
95
122
 
123
+ /**
124
+ * @deprecated
125
+ */
96
126
  export class XRPC {
97
127
  handle: FetchHandler;
98
128
  proxy: XRPCProxyOptions | undefined;
@@ -253,10 +283,16 @@ interface ErrorResponseBody {
253
283
  message?: string;
254
284
  }
255
285
 
286
+ /**
287
+ * @deprecated
288
+ */
256
289
  export const clone = (rpc: XRPC): XRPC => {
257
290
  return new XRPC({ handler: rpc.handle, proxy: rpc.proxy });
258
291
  };
259
292
 
293
+ /**
294
+ * @deprecated
295
+ */
260
296
  export const withProxy = (rpc: XRPC, options: XRPCProxyOptions) => {
261
297
  return new XRPC({ handler: rpc.handle, proxy: options });
262
298
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@atcute/client",
4
- "version": "3.0.0",
4
+ "version": "3.1.0",
5
5
  "description": "lightweight and cute API client for AT Protocol",
6
6
  "license": "MIT",
7
7
  "repository": {
@@ -25,7 +25,7 @@
25
25
  "@vitest/coverage-v8": "^3.0.4",
26
26
  "vitest": "^3.0.4",
27
27
  "@atcute/internal-dev-env": "^1.0.1",
28
- "@atcute/lex-cli": "^1.1.0"
28
+ "@atcute/lex-cli": "^1.1.2"
29
29
  },
30
30
  "scripts": {
31
31
  "build": "tsc --project tsconfig.build.json",