@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.
package/README.md CHANGED
@@ -7,24 +7,83 @@ lightweight and cute API client for AT Protocol.
7
7
  be trusted in returning valid responses.
8
8
 
9
9
  ```ts
10
- import { XRPC, CredentialManager } from '@atcute/client';
10
+ import { Client, CredentialManager, ok, simpleFetchHandler } from '@atcute/client';
11
11
 
12
- const manager = new CredentialManager({ service: 'https://bsky.social' });
13
- const rpc = new XRPC({ handler: manager });
12
+ // import additional lexicons
13
+ import '@atcute/bluesky/lexicons';
14
14
 
15
- await manager.login({ identifier: 'example.com', password: 'ofki-yrwl-hmcc-cvau' });
15
+ // basic usage
16
+ {
17
+ const handler = simpleFetchHandler({ service: 'https://public.api.bsky.app' });
18
+ const rpc = new Client({ handler });
16
19
 
17
- console.log(manager.session);
18
- // -> { refreshJwt: 'eyJhb...', ... }
20
+ // explicit response handling
21
+ {
22
+ const { ok, data } = await rpc.get('app.bsky.actor.getProfile', {
23
+ params: {
24
+ actor: 'bsky.app',
25
+ },
26
+ });
19
27
 
20
- const { data } = await rpc.get('com.atproto.identity.resolveHandle', {
21
- params: {
22
- handle: 'pfrazee.com',
23
- },
24
- });
28
+ if (!ok) {
29
+ switch (data.error) {
30
+ case 'InvalidRequest': {
31
+ // Account doesn't exist
32
+ break;
33
+ }
34
+ case 'AccountTakedown': {
35
+ // Account taken down
36
+ break;
37
+ }
38
+ case 'AccountDeactivated': {
39
+ // Account deactivated
40
+ break;
41
+ }
42
+ }
43
+ }
25
44
 
26
- console.log(data.did);
27
- // -> did:plc:ragtjsm2j2vknwkz3zp4oxrd
45
+ if (ok) {
46
+ console.log(data.displayName);
47
+ // -> "Bluesky"
48
+ }
49
+ }
50
+
51
+ // optimistic response handling
52
+ {
53
+ const data = await ok(
54
+ rpc.get('app.bsky.actor.getProfile', {
55
+ params: {
56
+ actor: 'bsky.app',
57
+ },
58
+ }),
59
+ );
60
+
61
+ console.log(data.displayName);
62
+ // -> "Bluesky"
63
+ }
64
+ }
65
+
66
+ // performing authenticated requests
67
+ {
68
+ const manager = new CredentialManager({ service: 'https://bsky.social' });
69
+ const rpc = new Client({ handler: manager });
70
+
71
+ await manager.login({ identifier: 'example.com', password: 'ofki-yrwl-hmcc-cvau' });
72
+
73
+ console.log(manager.session);
74
+ // -> { refreshJwt: 'eyJhb...', ... }
75
+
76
+ const data = await ok(
77
+ rpc.get('com.atproto.identity.resolveHandle', {
78
+ params: {
79
+ handle: 'pfrazee.com',
80
+ },
81
+ }),
82
+ );
83
+
84
+ console.log(data.did);
85
+ // -> 'did:plc:ragtjsm2j2vknwkz3zp4oxrd'
86
+ }
28
87
  ```
29
88
 
30
89
  by default, the API client only ships with the base AT Protocol (`com.atproto.*`) lexicons and
@@ -0,0 +1,181 @@
1
+ import type { At, Procedures, Queries } from './lexicons.js';
2
+ import { type FetchHandler, type FetchHandlerObject } from './fetch-handler.js';
3
+ type RequiredKeysOf<TType extends object> = TType extends any ? Exclude<{
4
+ [Key in keyof TType]: TType extends Record<Key, TType[Key]> ? Key : never;
5
+ }[keyof TType], undefined> : never;
6
+ type HasRequiredKeys<TType extends object> = RequiredKeysOf<TType> extends never ? false : true;
7
+ type ResponseFormat = 'json' | 'blob' | 'bytes' | 'stream';
8
+ type FormattedResponse<TDef> = {
9
+ json: TDef extends {
10
+ response: {
11
+ json: infer TData;
12
+ };
13
+ } ? TData : unknown;
14
+ blob: Blob;
15
+ bytes: Uint8Array;
16
+ stream: ReadableStream<Uint8Array>;
17
+ };
18
+ type BaseRequestOptions = {
19
+ signal?: AbortSignal;
20
+ headers?: HeadersInit;
21
+ };
22
+ export type QueryRequestOptions<TDef> = BaseRequestOptions & (TDef extends {
23
+ response: infer TResponse;
24
+ } ? TResponse extends {
25
+ json: any;
26
+ } ? {
27
+ as?: ResponseFormat | null;
28
+ } : {
29
+ as: ResponseFormat | null;
30
+ } : {
31
+ as: ResponseFormat | null;
32
+ }) & (TDef extends {
33
+ params: infer TParams;
34
+ } ? {
35
+ params: TParams;
36
+ } : {
37
+ params?: Record<string, unknown>;
38
+ });
39
+ export type ProcedureRequestOptions<TDef> = BaseRequestOptions & (TDef extends {
40
+ response: infer TResponse;
41
+ } ? TResponse extends {
42
+ json: any;
43
+ } ? {
44
+ as?: ResponseFormat | null;
45
+ } : {
46
+ as: ResponseFormat | null;
47
+ } : {
48
+ as: ResponseFormat | null;
49
+ }) & (TDef extends {
50
+ params: infer TParams;
51
+ } ? {
52
+ params: TParams;
53
+ } : {
54
+ params?: Record<string, unknown>;
55
+ }) & (TDef extends {
56
+ input: infer TInput;
57
+ } ? {
58
+ input: TInput;
59
+ } : {
60
+ input?: Record<string, unknown>;
61
+ });
62
+ /** standard XRPC error payload structure */
63
+ export type XRPCErrorPayload = {
64
+ /** error name */
65
+ error: string;
66
+ /** error description */
67
+ message?: string;
68
+ };
69
+ type BaseClientResponse = {
70
+ /** response status */
71
+ status: number;
72
+ /** response headers */
73
+ headers: Headers;
74
+ };
75
+ /** represents a successful response returned by the client */
76
+ export type SuccessClientResponse<TDef, TInit> = BaseClientResponse & {
77
+ ok: true;
78
+ /** response data */
79
+ data: TInit extends {
80
+ as: infer TFormat;
81
+ } ? TFormat extends ResponseFormat ? FormattedResponse<TDef>[TFormat] : TFormat extends null ? null : never : TDef extends {
82
+ response: {
83
+ json: infer TData;
84
+ };
85
+ } ? TData : never;
86
+ };
87
+ /** represents a failed response returned by the client */
88
+ export type FailedClientResponse = BaseClientResponse & {
89
+ ok: false;
90
+ /** response data */
91
+ data: XRPCErrorPayload;
92
+ };
93
+ /** represents a response returned by the client */
94
+ export type ClientResponse<TDef, TInit> = SuccessClientResponse<TDef, TInit> | FailedClientResponse;
95
+ /** options for configuring service proxying */
96
+ export type ServiceProxyOptions = {
97
+ /** DID identifier that the upstream service should look up */
98
+ did: At.Did;
99
+ /**
100
+ * the specific service ID within the resolved DID document's `service` array
101
+ * that the upstream service should forward requests to.
102
+ *
103
+ * must start with `#`
104
+ *
105
+ * common values include:
106
+ * - `#atproto_pds` (personal data server)
107
+ * - `#atproto_labeler` (labeler service)
108
+ * - `#bsky_chat` (Bluesky chat service)
109
+ */
110
+ serviceId: `#${string}`;
111
+ };
112
+ /** options for configuring the client */
113
+ export type ClientOptions = {
114
+ /** the underlying fetch handler it should make requests with */
115
+ handler: FetchHandler | FetchHandlerObject;
116
+ /** service proxy configuration */
117
+ proxy?: ServiceProxyOptions | null;
118
+ };
119
+ /** XRPC API client */
120
+ export declare class Client<TQueries = Queries, TProcedures = Procedures> {
121
+ #private;
122
+ handler: FetchHandler;
123
+ proxy: ServiceProxyOptions | null;
124
+ constructor({ handler, proxy }: ClientOptions);
125
+ /**
126
+ * clones this XRPC client
127
+ * @param opts options to merge with
128
+ * @returns the cloned XRPC client
129
+ */
130
+ clone({ handler, proxy }?: Partial<ClientOptions>): Client<TQueries, TProcedures>;
131
+ /**
132
+ * performs an XRPC query request (HTTP GET)
133
+ * @param name NSID of the query
134
+ * @param options query options
135
+ */
136
+ get<TName extends keyof TQueries, TInit extends QueryRequestOptions<TQueries[TName]>>(name: TName, ...options: HasRequiredKeys<TInit> extends true ? [init: TInit] : [init?: TInit]): Promise<ClientResponse<TQueries[TName], TInit>>;
137
+ /**
138
+ * performs an XRPC procedure request (HTTP POST)
139
+ * @param name NSID of the procedure
140
+ * @param options procedure options
141
+ */
142
+ post<TName extends keyof TProcedures, TInit extends ProcedureRequestOptions<TProcedures[TName]>>(name: TName, ...options: HasRequiredKeys<TInit> extends true ? [init: TInit] : [init?: TInit]): Promise<ClientResponse<TProcedures[TName], TInit>>;
143
+ }
144
+ export declare const isXRPCErrorPayload: (input: any) => input is XRPCErrorPayload;
145
+ type SuccessData<R> = R extends {
146
+ ok: true;
147
+ data: infer D;
148
+ } ? D : never;
149
+ /**
150
+ * takes in the response returned by the client, and either returns the data if
151
+ * it is a successful response, or throws if it's a failed response.
152
+ * @param input either a ClientResponse, or a promise that resolves to a ClientResponse
153
+ * @returns the data from a successful response
154
+ *
155
+ * @example
156
+ * const data = await ok(client.get('com.atproto.server.describeServer'));
157
+ * // ^? ComAtprotoServerDescribeServer.Output
158
+ */
159
+ export declare const ok: {
160
+ <T extends Promise<ClientResponse<any, any>>>(promise: T): Promise<SuccessData<Awaited<T>>>;
161
+ <T extends ClientResponse<any, any>>(response: T): SuccessData<T>;
162
+ };
163
+ /** options when constructing a ClientResponseError */
164
+ export type ClientResponseErrorOptions = {
165
+ status: number;
166
+ headers?: Headers;
167
+ data: XRPCErrorPayload;
168
+ };
169
+ /** represents an error response returned by the client */
170
+ export declare class ClientResponseError extends Error {
171
+ /** error name returned by service */
172
+ readonly error: string;
173
+ /** error message returned by service */
174
+ readonly description?: string;
175
+ /** response status */
176
+ readonly status: number;
177
+ /** response headers */
178
+ readonly headers: Headers;
179
+ constructor({ status, headers, data }: ClientResponseErrorOptions);
180
+ }
181
+ export {};
package/dist/client.js ADDED
@@ -0,0 +1,180 @@
1
+ import { buildFetchHandler } from './fetch-handler.js';
2
+ import { mergeHeaders } from './utils/http.js';
3
+ const JSON_CONTENT_TYPE_RE = /\bapplication\/json\b/;
4
+ /** XRPC API client */
5
+ export class Client {
6
+ constructor({ handler, proxy = null }) {
7
+ this.handler = buildFetchHandler(handler);
8
+ this.proxy = proxy;
9
+ }
10
+ /**
11
+ * clones this XRPC client
12
+ * @param opts options to merge with
13
+ * @returns the cloned XRPC client
14
+ */
15
+ clone({ handler = this.handler, proxy = this.proxy } = {}) {
16
+ return new Client({ handler, proxy });
17
+ }
18
+ get(name, options = {}) {
19
+ return this.#perform('get', name, options);
20
+ }
21
+ post(name, options = {}) {
22
+ return this.#perform('post', name, options);
23
+ }
24
+ async #perform(method, name, { signal, as: format = 'json', headers, input, params }) {
25
+ const isWebInput = input &&
26
+ (input instanceof Blob ||
27
+ ArrayBuffer.isView(input) ||
28
+ input instanceof ArrayBuffer ||
29
+ input instanceof ReadableStream);
30
+ const url = `/xrpc/${name}` + _constructSearchParams(params);
31
+ const response = await this.handler(url, {
32
+ method,
33
+ signal,
34
+ body: input && !isWebInput ? JSON.stringify(input) : input,
35
+ headers: mergeHeaders(headers, {
36
+ 'content-type': input && !isWebInput ? 'application/json' : null,
37
+ 'atproto-proxy': _constructProxyHeader(this.proxy),
38
+ }),
39
+ });
40
+ {
41
+ const status = response.status;
42
+ const headers = response.headers;
43
+ const type = headers.get('content-type');
44
+ if (status !== 200) {
45
+ let json;
46
+ if (type != null && JSON_CONTENT_TYPE_RE.test(type)) {
47
+ // it should be okay to swallow the parsing error here
48
+ try {
49
+ const parsed = await response.json();
50
+ if (isXRPCErrorPayload(parsed)) {
51
+ json = parsed;
52
+ }
53
+ }
54
+ catch { }
55
+ }
56
+ else {
57
+ await response.body?.cancel();
58
+ }
59
+ return {
60
+ ok: false,
61
+ status: status,
62
+ headers: headers,
63
+ data: json ?? {
64
+ error: `UnknownXRPCError`,
65
+ message: `Request failed with status code ${status}`,
66
+ },
67
+ };
68
+ }
69
+ {
70
+ let data;
71
+ switch (format) {
72
+ case 'json': {
73
+ if (type != null && JSON_CONTENT_TYPE_RE.test(type)) {
74
+ // we shouldn't be handling parsing errors
75
+ data = await response.json();
76
+ }
77
+ else {
78
+ await response.body?.cancel();
79
+ throw new TypeError(`Invalid response content-type (got ${type})`);
80
+ }
81
+ break;
82
+ }
83
+ case null: {
84
+ data = null;
85
+ await response.body?.cancel();
86
+ if (type != null) {
87
+ throw new TypeError(`Invalid response content-type (got ${type})`);
88
+ }
89
+ break;
90
+ }
91
+ case 'blob': {
92
+ data = await response.blob();
93
+ break;
94
+ }
95
+ case 'bytes': {
96
+ data = new Uint8Array(await response.arrayBuffer());
97
+ break;
98
+ }
99
+ case 'stream': {
100
+ data = response.body;
101
+ break;
102
+ }
103
+ }
104
+ return {
105
+ ok: true,
106
+ status: status,
107
+ headers: headers,
108
+ data: data,
109
+ };
110
+ }
111
+ }
112
+ }
113
+ }
114
+ // #endregion
115
+ // #region Utility functions
116
+ const _constructSearchParams = (params) => {
117
+ let searchParams;
118
+ for (const key in params) {
119
+ const value = params[key];
120
+ if (value !== undefined) {
121
+ searchParams ??= new URLSearchParams();
122
+ if (Array.isArray(value)) {
123
+ for (let idx = 0, len = value.length; idx < len; idx++) {
124
+ const val = value[idx];
125
+ searchParams.append(key, '' + val);
126
+ }
127
+ }
128
+ else {
129
+ searchParams.set(key, '' + value);
130
+ }
131
+ }
132
+ }
133
+ return searchParams ? `?` + searchParams.toString() : '';
134
+ };
135
+ const _constructProxyHeader = (proxy) => {
136
+ if (proxy != null) {
137
+ return `${proxy.did}${proxy.serviceId}`;
138
+ }
139
+ return null;
140
+ };
141
+ export const isXRPCErrorPayload = (input) => {
142
+ if (typeof input !== 'object' || input == null) {
143
+ return false;
144
+ }
145
+ const kindType = typeof input.error;
146
+ const messageType = typeof input.message;
147
+ return kindType === 'string' && (messageType === 'undefined' || messageType === 'string');
148
+ };
149
+ /**
150
+ * takes in the response returned by the client, and either returns the data if
151
+ * it is a successful response, or throws if it's a failed response.
152
+ * @param input either a ClientResponse, or a promise that resolves to a ClientResponse
153
+ * @returns the data from a successful response
154
+ *
155
+ * @example
156
+ * const data = await ok(client.get('com.atproto.server.describeServer'));
157
+ * // ^? ComAtprotoServerDescribeServer.Output
158
+ */
159
+ export const ok = (input) => {
160
+ if (input instanceof Promise) {
161
+ return input.then(ok);
162
+ }
163
+ if (input.ok) {
164
+ return input.data;
165
+ }
166
+ throw new ClientResponseError(input);
167
+ };
168
+ /** represents an error response returned by the client */
169
+ export class ClientResponseError extends Error {
170
+ constructor({ status, headers = new Headers(), data }) {
171
+ super(`${data.error} > ${data.message ?? '(unspecified description)'}`);
172
+ this.name = 'ClientResponseError';
173
+ this.error = data.error;
174
+ this.description = data.message;
175
+ this.status = status;
176
+ this.headers = headers;
177
+ }
178
+ }
179
+ // #endregion
180
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../lib/client.ts"],"names":[],"mappings":"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"}
@@ -1,95 +1,104 @@
1
1
  import type { At } from './lexicons.js';
2
2
  import { type FetchHandlerObject } from './fetch-handler.js';
3
- /** Interface for the decoded access token, for convenience */
3
+ /**
4
+ * represents the decoded access token, for convenience
5
+ * @deprecated
6
+ */
4
7
  export interface AtpAccessJwt {
5
- /** Access token scope, app password returns a different scope. */
8
+ /** access token scope */
6
9
  scope: 'com.atproto.access' | 'com.atproto.appPass' | 'com.atproto.appPassPrivileged' | 'com.atproto.signupQueued' | 'com.atproto.takendown';
7
- /** Account DID */
10
+ /** account DID */
8
11
  sub: At.Did;
9
- /** Expiration time */
12
+ /** expiration time in Unix seconds */
10
13
  exp: number;
11
- /** Creation/issued time */
14
+ /** token issued time in Unix seconds */
12
15
  iat: number;
13
16
  }
14
- /** Interface for the decoded refresh token, for convenience */
17
+ /**
18
+ * represents the the decoded refresh token, for convenience
19
+ * @deprecated
20
+ */
15
21
  export interface AtpRefreshJwt {
16
- /** Refresh token scope */
22
+ /** refresh token scope */
17
23
  scope: 'com.atproto.refresh';
18
- /** ID of this refresh token */
24
+ /** unique identifier for this session */
19
25
  jti: string;
20
- /** Account DID */
26
+ /** account DID */
21
27
  sub: At.Did;
22
- /** Intended audience of this refresh token, in DID */
28
+ /** intended audience of this refresh token, in DID */
23
29
  aud: At.Did;
24
- /** Expiration time */
30
+ /** token expiration time in seconds */
25
31
  exp: number;
26
- /** Creation/issued time */
32
+ /** token issued time in seconds */
27
33
  iat: number;
28
34
  }
29
- /** Saved session data, this can be reused again for next time. */
35
+ /** session data, can be persisted and reused */
30
36
  export interface AtpSessionData {
31
- /** Refresh token */
37
+ /** refresh token */
32
38
  refreshJwt: string;
33
- /** Access token */
39
+ /** access token */
34
40
  accessJwt: string;
35
- /** Account handle */
41
+ /** account handle */
36
42
  handle: string;
37
- /** Account DID */
43
+ /** account DID */
38
44
  did: At.Did;
39
45
  /** PDS endpoint found in the DID document, this will be used as the service URI if provided */
40
46
  pdsUri?: string;
41
- /** Email address of the account, might not be available if on app password */
47
+ /** email address of the account, might not be available if on app password */
42
48
  email?: string;
43
- /** If the email address has been confirmed or not */
49
+ /** whether the email address has been confirmed or not */
44
50
  emailConfirmed?: boolean;
45
- /** If the account has email-based two-factor authentication enabled */
51
+ /** whether the account has email-based two-factor authentication enabled */
46
52
  emailAuthFactor?: boolean;
47
- /** Whether the account is active (not deactivated, taken down, or suspended) */
53
+ /** whether the account is active (not deactivated, taken down, or suspended) */
48
54
  active: boolean;
49
- /** Possible reason for why the account is inactive */
55
+ /** possible reason for why the account is inactive */
50
56
  inactiveStatus?: string;
51
57
  }
52
58
  export interface CredentialManagerOptions {
53
59
  /** PDS server URL */
54
60
  service: string;
55
- /** Custom fetch function */
56
- fetch?: typeof globalThis.fetch;
57
- /** Function that gets called if the session turned out to have expired during an XRPC request */
61
+ /** custom fetch function */
62
+ fetch?: typeof fetch;
63
+ /** function called when the session expires and can't be refreshed */
58
64
  onExpired?: (session: AtpSessionData) => void;
59
- /** Function that gets called if the session has been refreshed during an XRPC request */
65
+ /** function called after a successful session refresh */
60
66
  onRefresh?: (session: AtpSessionData) => void;
61
- /** Function that gets called if the session object has been refreshed */
67
+ /** function called whenever the session object is updated (login, resume, refresh) */
62
68
  onSessionUpdate?: (session: AtpSessionData) => void;
63
69
  }
64
70
  export declare class CredentialManager implements FetchHandlerObject {
65
71
  #private;
72
+ /** service URL to make authentication requests with */
66
73
  readonly serviceUrl: string;
74
+ /** fetch implementation */
67
75
  fetch: typeof fetch;
68
- /** Current session state */
76
+ /** current active session, undefined if not authenticated */
69
77
  session?: AtpSessionData;
70
78
  constructor({ service, onExpired, onRefresh, onSessionUpdate, fetch: _fetch, }: CredentialManagerOptions);
79
+ /** service URL to make actual API requests with */
71
80
  get dispatchUrl(): string;
72
81
  handle(pathname: string, init: RequestInit): Promise<Response>;
73
82
  /**
74
- * Resume a saved session
75
- * @param session Session information, taken from `AtpAuth#session` after login
83
+ * resume from a persisted session
84
+ * @param session session data, taken from `AtpAuth#session` after login
76
85
  */
77
86
  resume(session: AtpSessionData): Promise<AtpSessionData>;
78
87
  /**
79
- * Perform a login operation
80
- * @param options Login options
81
- * @returns Session data that can be saved for later
88
+ * sign in to an account
89
+ * @param options credential options
90
+ * @returns session data
82
91
  */
83
92
  login(options: AuthLoginOptions): Promise<AtpSessionData>;
84
93
  }
85
- /** Login options */
94
+ /** credentials */
86
95
  export interface AuthLoginOptions {
87
- /** What account to login as, this could be domain handle, DID, or email address */
96
+ /** what account to login as, this could be domain handle, DID, or email address */
88
97
  identifier: string;
89
- /** Account password */
98
+ /** account password */
90
99
  password: string;
91
- /** Two-factor authentication code */
100
+ /** two-factor authentication code, if email TOTP is enabled */
92
101
  code?: string;
93
- /** Allow signing in even if the account has been taken down, */
102
+ /** allow signing in even if the account has been taken down */
94
103
  allowTakendown?: boolean;
95
104
  }