@atcute/client 3.0.1 → 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.
- package/README.md +72 -13
- package/dist/client.d.ts +181 -0
- package/dist/client.js +180 -0
- package/dist/client.js.map +1 -0
- package/dist/credential-manager.d.ts +47 -38
- package/dist/credential-manager.js +50 -41
- package/dist/credential-manager.js.map +1 -1
- package/dist/fetch-handler.d.ts +2 -2
- package/dist/fetch-handler.js +1 -1
- package/dist/fetch-handler.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/rpc.d.ts +44 -8
- package/dist/rpc.js +13 -1
- package/dist/rpc.js.map +1 -1
- package/lib/client.ts +406 -0
- package/lib/credential-manager.ts +119 -93
- package/lib/fetch-handler.ts +3 -3
- package/lib/index.ts +3 -2
- package/lib/rpc.ts +44 -8
- package/package.json +2 -2
|
@@ -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
|
-
/**
|
|
9
|
+
/**
|
|
10
|
+
* represents the decoded access token, for convenience
|
|
11
|
+
* @deprecated
|
|
12
|
+
*/
|
|
10
13
|
export interface AtpAccessJwt {
|
|
11
|
-
/**
|
|
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
|
-
/**
|
|
21
|
+
/** account DID */
|
|
19
22
|
sub: At.Did;
|
|
20
|
-
/**
|
|
23
|
+
/** expiration time in Unix seconds */
|
|
21
24
|
exp: number;
|
|
22
|
-
/**
|
|
25
|
+
/** token issued time in Unix seconds */
|
|
23
26
|
iat: number;
|
|
24
27
|
}
|
|
25
28
|
|
|
26
|
-
/**
|
|
29
|
+
/**
|
|
30
|
+
* represents the the decoded refresh token, for convenience
|
|
31
|
+
* @deprecated
|
|
32
|
+
*/
|
|
27
33
|
export interface AtpRefreshJwt {
|
|
28
|
-
/**
|
|
34
|
+
/** refresh token scope */
|
|
29
35
|
scope: 'com.atproto.refresh';
|
|
30
|
-
/**
|
|
36
|
+
/** unique identifier for this session */
|
|
31
37
|
jti: string;
|
|
32
|
-
/**
|
|
38
|
+
/** account DID */
|
|
33
39
|
sub: At.Did;
|
|
34
|
-
/**
|
|
40
|
+
/** intended audience of this refresh token, in DID */
|
|
35
41
|
aud: At.Did;
|
|
36
|
-
/**
|
|
42
|
+
/** token expiration time in seconds */
|
|
37
43
|
exp: number;
|
|
38
|
-
/**
|
|
44
|
+
/** token issued time in seconds */
|
|
39
45
|
iat: number;
|
|
40
46
|
}
|
|
41
47
|
|
|
42
|
-
/**
|
|
48
|
+
/** session data, can be persisted and reused */
|
|
43
49
|
export interface AtpSessionData {
|
|
44
|
-
/**
|
|
50
|
+
/** refresh token */
|
|
45
51
|
refreshJwt: string;
|
|
46
|
-
/**
|
|
52
|
+
/** access token */
|
|
47
53
|
accessJwt: string;
|
|
48
|
-
/**
|
|
54
|
+
/** account handle */
|
|
49
55
|
handle: string;
|
|
50
|
-
/**
|
|
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
|
-
/**
|
|
60
|
+
/** email address of the account, might not be available if on app password */
|
|
55
61
|
email?: string;
|
|
56
|
-
/**
|
|
62
|
+
/** whether the email address has been confirmed or not */
|
|
57
63
|
emailConfirmed?: boolean;
|
|
58
|
-
/**
|
|
64
|
+
/** whether the account has email-based two-factor authentication enabled */
|
|
59
65
|
emailAuthFactor?: boolean;
|
|
60
|
-
/**
|
|
66
|
+
/** whether the account is active (not deactivated, taken down, or suspended) */
|
|
61
67
|
active: boolean;
|
|
62
|
-
/**
|
|
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
|
-
/**
|
|
71
|
-
fetch?: typeof
|
|
76
|
+
/** custom fetch function */
|
|
77
|
+
fetch?: typeof fetch;
|
|
72
78
|
|
|
73
|
-
/**
|
|
79
|
+
/** function called when the session expires and can't be refreshed */
|
|
74
80
|
onExpired?: (session: AtpSessionData) => void;
|
|
75
|
-
/**
|
|
81
|
+
/** function called after a successful session refresh */
|
|
76
82
|
onRefresh?: (session: AtpSessionData) => void;
|
|
77
|
-
/**
|
|
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
|
-
|
|
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
|
-
/**
|
|
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
|
|
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
|
-
//
|
|
142
|
-
// - refreshSession
|
|
143
|
-
// -
|
|
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
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
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.
|
|
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
|
-
*
|
|
216
|
-
* @param session
|
|
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() /
|
|
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
|
|
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 =
|
|
234
|
-
|
|
235
|
-
|
|
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
|
-
|
|
240
|
-
|
|
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
|
|
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
|
-
*
|
|
260
|
-
* @param options
|
|
261
|
-
* @returns
|
|
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
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
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(
|
|
297
|
+
return this.#updateSession(session);
|
|
277
298
|
}
|
|
278
299
|
}
|
|
279
300
|
|
|
280
|
-
/**
|
|
301
|
+
/** credentials */
|
|
281
302
|
export interface AuthLoginOptions {
|
|
282
|
-
/**
|
|
303
|
+
/** what account to login as, this could be domain handle, DID, or email address */
|
|
283
304
|
identifier: string;
|
|
284
|
-
/**
|
|
305
|
+
/** account password */
|
|
285
306
|
password: string;
|
|
286
|
-
/**
|
|
307
|
+
/** two-factor authentication code, if email TOTP is enabled */
|
|
287
308
|
code?: string;
|
|
288
|
-
/**
|
|
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
|
|
309
|
-
|
|
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;
|
package/lib/fetch-handler.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/** fetch handler function */
|
|
2
2
|
export type FetchHandler = (pathname: string, init: RequestInit) => Promise<Response>;
|
|
3
3
|
|
|
4
|
-
/**
|
|
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
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
|
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.
|
|
28
|
+
"@atcute/lex-cli": "^1.1.2"
|
|
29
29
|
},
|
|
30
30
|
"scripts": {
|
|
31
31
|
"build": "tsc --project tsconfig.build.json",
|