@atcute/client 1.0.0 → 2.0.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
@@ -2,22 +2,21 @@
2
2
 
3
3
  lightweight and cute API client for AT Protocol.
4
4
 
5
- - Small, comes in at ~1,720 b minified (~904 b minzipped).
5
+ - Small, the bare minimum is ~1 kB gzipped with the full package at ~2.4 kB gzipped.
6
6
  - No validations, type definitions match actual HTTP responses.
7
7
 
8
8
  This package only contains the base AT Protocol lexicons and endpoints, along with an authentication middleware.
9
9
  For Bluesky-related lexicons, see `@atcute/bluesky` package.
10
10
 
11
11
  ```ts
12
- import { XRPC } from '@atcute/client';
13
- import { AtpAuth } from '@atcute/client/middlewares/auth';
12
+ import { XRPC, CredentialManager } from '@atcute/client';
14
13
 
15
- const rpc = new XRPC({ service: 'https://bsky.social' });
16
- const auth = new AtpAuth(rpc);
14
+ const manager = new CredentialManager({ service: 'https://bsky.social' });
15
+ const rpc = new XRPC({ handler: manager });
17
16
 
18
- await auth.login({ identifier: 'example.com', password: 'ofki-yrwl-hmcc-cvau' });
17
+ await manager.login({ identifier: 'example.com', password: 'ofki-yrwl-hmcc-cvau' });
19
18
 
20
- console.log(auth.session);
19
+ console.log(manager.session);
21
20
  // -> { refreshJwt: 'eyJhb...', ... }
22
21
 
23
22
  const { data } = await rpc.get('com.atproto.identity.resolveHandle', {
@@ -1,9 +1,5 @@
1
- /**
2
- * @module
3
- * Contains a middleware that handles authentication to a personal data server.
4
- */
5
- import { type XRPC } from '../index.js';
6
- import type { At } from '../lexicons.js';
1
+ import type { At } from './lexicons.js';
2
+ import { type FetchHandlerObject } from './fetch-handler.js';
7
3
  /** Interface for the decoded access token, for convenience */
8
4
  export interface AtpAccessJwt {
9
5
  /** Access token scope, app password returns a different scope. */
@@ -53,21 +49,27 @@ export interface AtpSessionData {
53
49
  /** Possible reason for why the account is inactive */
54
50
  inactiveStatus?: string;
55
51
  }
56
- /** Additional options for constructing an authentication middleware */
57
- export interface AtpAuthOptions {
58
- /** This function gets called if the session turned out to have expired during an XRPC request */
52
+ export interface CredentialManagerOptions {
53
+ /** PDS server URL */
54
+ 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 */
59
58
  onExpired?: (session: AtpSessionData) => void;
60
- /** This function gets called if the session has been refreshed during an XRPC request */
59
+ /** Function that gets called if the session has been refreshed during an XRPC request */
61
60
  onRefresh?: (session: AtpSessionData) => void;
62
- /** This function gets called if the session object has been refreshed */
61
+ /** Function that gets called if the session object has been refreshed */
63
62
  onSessionUpdate?: (session: AtpSessionData) => void;
64
63
  }
65
- /** Authentication/session management middleware */
66
- export declare class AtpAuth {
64
+ export declare class CredentialManager implements FetchHandlerObject {
67
65
  #private;
66
+ readonly serviceUrl: string;
67
+ fetch: typeof fetch;
68
68
  /** Current session state */
69
69
  session?: AtpSessionData;
70
- constructor(rpc: XRPC, { onExpired, onRefresh, onSessionUpdate }?: AtpAuthOptions);
70
+ constructor({ service, onExpired, onRefresh, onSessionUpdate, fetch: _fetch, }: CredentialManagerOptions);
71
+ get dispatchUrl(): string;
72
+ handle(pathname: string, init: RequestInit): Promise<Response>;
71
73
  /**
72
74
  * Resume a saved session
73
75
  * @param session Session information, taken from `AtpAuth#session` after login
@@ -0,0 +1,177 @@
1
+ import { simpleFetchHandler } from './fetch-handler.js';
2
+ import { XRPC, XRPCError } from './rpc.js';
3
+ import { getPdsEndpoint } from './utils/did.js';
4
+ import { decodeJwt } from './utils/jwt.js';
5
+ export class CredentialManager {
6
+ #server;
7
+ #refreshSessionPromise;
8
+ #onExpired;
9
+ #onRefresh;
10
+ #onSessionUpdate;
11
+ constructor({ service, onExpired, onRefresh, onSessionUpdate, fetch: _fetch = fetch, }) {
12
+ this.serviceUrl = service;
13
+ this.fetch = _fetch;
14
+ this.#server = new XRPC({ handler: simpleFetchHandler({ service: service, fetch: _fetch }) });
15
+ this.#onRefresh = onRefresh;
16
+ this.#onExpired = onExpired;
17
+ this.#onSessionUpdate = onSessionUpdate;
18
+ }
19
+ get dispatchUrl() {
20
+ return this.session?.pdsUri ?? this.serviceUrl;
21
+ }
22
+ async handle(pathname, init) {
23
+ await this.#refreshSessionPromise;
24
+ const url = new URL(pathname, this.dispatchUrl);
25
+ const request = new Request(url, init);
26
+ if (!this.session || request.headers.has('authorization')) {
27
+ return this.fetch(request);
28
+ }
29
+ request.headers.set('authorization', `Bearer ${this.session.accessJwt}`);
30
+ const initialResponse = await this.fetch(request);
31
+ const isExpired = await isExpiredTokenResponse(initialResponse);
32
+ if (!isExpired) {
33
+ return initialResponse;
34
+ }
35
+ try {
36
+ await this.#refreshSession();
37
+ }
38
+ catch {
39
+ return initialResponse;
40
+ }
41
+ // Return initial response if:
42
+ // - refreshSession returns expired
43
+ // - Body stream has been consumed
44
+ if (!this.session || init.body instanceof ReadableStream) {
45
+ return initialResponse;
46
+ }
47
+ request.headers.set('authorization', `Bearer ${this.session.accessJwt}`);
48
+ return await this.fetch(request);
49
+ }
50
+ #refreshSession() {
51
+ return (this.#refreshSessionPromise ||= this.#refreshSessionInner().finally(() => (this.#refreshSessionPromise = undefined)));
52
+ }
53
+ async #refreshSessionInner() {
54
+ const currentSession = this.session;
55
+ if (!currentSession) {
56
+ return;
57
+ }
58
+ try {
59
+ const { data } = await this.#server.call('com.atproto.server.refreshSession', {
60
+ headers: {
61
+ authorization: `Bearer ${currentSession.refreshJwt}`,
62
+ },
63
+ });
64
+ this.#updateSession({ ...currentSession, ...data });
65
+ this.#onRefresh?.(this.session);
66
+ }
67
+ catch (err) {
68
+ if (err instanceof XRPCError) {
69
+ const kind = err.kind;
70
+ if (kind === 'ExpiredToken' || kind === 'InvalidToken') {
71
+ this.session = undefined;
72
+ this.#onExpired?.(currentSession);
73
+ }
74
+ }
75
+ }
76
+ }
77
+ #updateSession(raw) {
78
+ const didDoc = raw.didDoc;
79
+ let pdsUri;
80
+ if (didDoc) {
81
+ pdsUri = getPdsEndpoint(didDoc);
82
+ }
83
+ const newSession = {
84
+ accessJwt: raw.accessJwt,
85
+ refreshJwt: raw.refreshJwt,
86
+ handle: raw.handle,
87
+ did: raw.did,
88
+ pdsUri: pdsUri,
89
+ email: raw.email,
90
+ emailConfirmed: raw.emailConfirmed,
91
+ emailAuthFactor: raw.emailConfirmed,
92
+ active: raw.active ?? true,
93
+ inactiveStatus: raw.status,
94
+ };
95
+ this.session = newSession;
96
+ this.#onSessionUpdate?.(newSession);
97
+ return newSession;
98
+ }
99
+ /**
100
+ * Resume a saved session
101
+ * @param session Session information, taken from `AtpAuth#session` after login
102
+ */
103
+ async resume(session) {
104
+ const now = Date.now() / 1000 + 60 * 5;
105
+ const refreshToken = decodeJwt(session.refreshJwt);
106
+ if (now >= refreshToken.exp) {
107
+ throw new XRPCError(401, { kind: 'InvalidToken' });
108
+ }
109
+ const accessToken = decodeJwt(session.accessJwt);
110
+ this.session = session;
111
+ if (now >= accessToken.exp) {
112
+ await this.#refreshSession();
113
+ }
114
+ else {
115
+ const promise = this.#server.get('com.atproto.server.getSession', {
116
+ headers: {
117
+ authorization: `Bearer ${session.accessJwt}`,
118
+ },
119
+ });
120
+ promise.then((response) => {
121
+ const existing = this.session;
122
+ const next = response.data;
123
+ if (!existing) {
124
+ return;
125
+ }
126
+ this.#updateSession({ ...existing, ...next });
127
+ });
128
+ }
129
+ if (!this.session) {
130
+ throw new XRPCError(401, { kind: 'InvalidToken' });
131
+ }
132
+ return this.session;
133
+ }
134
+ /**
135
+ * Perform a login operation
136
+ * @param options Login options
137
+ * @returns Session data that can be saved for later
138
+ */
139
+ async login(options) {
140
+ // Reset the session
141
+ this.session = undefined;
142
+ const res = await this.#server.call('com.atproto.server.createSession', {
143
+ data: {
144
+ identifier: options.identifier,
145
+ password: options.password,
146
+ authFactorToken: options.code,
147
+ },
148
+ });
149
+ return this.#updateSession(res.data);
150
+ }
151
+ }
152
+ const isExpiredTokenResponse = async (response) => {
153
+ if (response.status !== 400) {
154
+ return false;
155
+ }
156
+ if (extractContentType(response.headers) !== 'application/json') {
157
+ return false;
158
+ }
159
+ // {"error":"ExpiredToken","message":"Token has expired"}
160
+ // {"error":"ExpiredToken","message":"Token is expired"}
161
+ if (extractContentLength(response.headers) > 54 * 1.5) {
162
+ return false;
163
+ }
164
+ try {
165
+ const { error, message } = await response.clone().json();
166
+ return error === 'ExpiredToken' && (typeof message === 'string' || message === undefined);
167
+ }
168
+ catch { }
169
+ return false;
170
+ };
171
+ const extractContentType = (headers) => {
172
+ return headers.get('content-type')?.split(';')[0]?.trim();
173
+ };
174
+ const extractContentLength = (headers) => {
175
+ return Number(headers.get('content-length') ?? ';');
176
+ };
177
+ //# sourceMappingURL=credential-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credential-manager.js","sourceRoot":"","sources":["../lib/credential-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /** Fetch handler function */
2
+ export type FetchHandler = (pathname: string, init: RequestInit) => Promise<Response>;
3
+ /** Fetch handler in an object */
4
+ export interface FetchHandlerObject {
5
+ handle(this: FetchHandlerObject, pathname: string, init: RequestInit): Promise<Response>;
6
+ }
7
+ export declare const buildFetchHandler: (handler: FetchHandler | FetchHandlerObject) => FetchHandler;
8
+ export interface SimpleFetchHandlerOptions {
9
+ service: string | URL;
10
+ fetch?: typeof globalThis.fetch;
11
+ }
12
+ export declare const simpleFetchHandler: ({ service, fetch: _fetch, }: SimpleFetchHandlerOptions) => FetchHandler;
@@ -0,0 +1,13 @@
1
+ export const buildFetchHandler = (handler) => {
2
+ if (typeof handler === 'object') {
3
+ return handler.handle.bind(handler);
4
+ }
5
+ return handler;
6
+ };
7
+ export const simpleFetchHandler = ({ service, fetch: _fetch = fetch, }) => {
8
+ return async (pathname, init) => {
9
+ const url = new URL(pathname, service);
10
+ return _fetch(url, init);
11
+ };
12
+ };
13
+ //# sourceMappingURL=fetch-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-handler.js","sourceRoot":"","sources":["../lib/fetch-handler.ts"],"names":[],"mappings":"AAQA,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,OAA0C,EAAgB,EAAE;IAC7F,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QACjC,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACrC,CAAC;IAED,OAAO,OAAO,CAAC;AAChB,CAAC,CAAC;AAOF,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,EAClC,OAAO,EACP,KAAK,EAAE,MAAM,GAAG,KAAK,GACM,EAAgB,EAAE;IAC7C,OAAO,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE;QAC/B,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACvC,OAAO,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAC1B,CAAC,CAAC;AACH,CAAC,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,177 +1,3 @@
1
- /**
2
- * @module
3
- * Handles the actual XRPC client functionalities.
4
- */
5
- import type { At, Procedures, Queries } from './lexicons.ts';
6
- export type Headers = Record<string, string>;
7
- /** Possible response status from an XRPC service, status <100 is used for the library itself. */
8
- export declare const enum ResponseType {
9
- /** Unknown error from the library */
10
- Unknown = 1,
11
- /** The server returned an invalid response */
12
- InvalidResponse = 2,
13
- /** Successful response from the service */
14
- Success = 200,
15
- /** Request was considered invalid by the service */
16
- InvalidRequest = 400,
17
- /** Service requires an authentication token */
18
- AuthRequired = 401,
19
- /** Request is forbidden by the service */
20
- Forbidden = 403,
21
- /** Not a XRPC service */
22
- XRPCNotSupported = 404,
23
- /** Payload is considered too large by the service */
24
- PayloadTooLarge = 413,
25
- /** Ratelimit was exceeded */
26
- RateLimitExceeded = 429,
27
- /** Internal server error */
28
- InternalServerError = 500,
29
- /** Method hasn't been implemented */
30
- MethodNotImplemented = 501,
31
- /** Failure by an upstream service */
32
- UpstreamFailure = 502,
33
- /** Not enough resources */
34
- NotEnoughResouces = 503,
35
- /** Timeout from upstream service */
36
- UpstreamTimeout = 504
37
- }
38
- /** XRPC response status which are recoverable (network error) */
39
- export declare const RECOVERABLE_RESPONSE_STATUS: number[];
40
- /** Request type, either query (GET) or procedure (POST) */
41
- export type RequestType = 'get' | 'post';
42
- /** XRPC that gets passed around middlewares and eventually to the service. */
43
- export interface XRPCRequest {
44
- service: string;
45
- type: RequestType;
46
- nsid: string;
47
- headers: Headers;
48
- params: Record<string, unknown>;
49
- encoding?: string;
50
- data?: FormData | Blob | ArrayBufferView | Record<string, unknown>;
51
- signal?: AbortSignal;
52
- }
53
- /** Response from XRPC service */
54
- export interface XRPCResponse<T = any> {
55
- data: T;
56
- headers: Headers;
57
- }
58
- /** Options for constructing an XRPC error */
59
- export interface XRPCErrorOptions {
60
- kind?: string;
61
- message?: string;
62
- headers?: Headers;
63
- cause?: unknown;
64
- }
65
- /** Error coming from the XRPC service */
66
- export declare class XRPCError extends Error {
67
- name: string;
68
- /** Response status */
69
- status: number;
70
- /** Response headers */
71
- headers: Headers;
72
- /** Error kind */
73
- kind?: string;
74
- constructor(status: number, { kind, message, headers, cause }?: XRPCErrorOptions);
75
- }
76
- /** Response returned from middlewares and XRPC service */
77
- export interface XRPCFetchReturn {
78
- status: number;
79
- headers: Headers;
80
- body: unknown;
81
- }
82
- /** Fetch function */
83
- export type XRPCFetch = (req: XRPCRequest) => Promise<XRPCFetchReturn>;
84
- /** Function that constructs a middleware */
85
- export type XRPCHook = (next: XRPCFetch) => XRPCFetch;
86
- /** Options for constructing an XRPC class */
87
- export interface XRPCOptions {
88
- service: string;
89
- }
90
- /** Base options for the query/procedure request */
91
- interface BaseRPCOptions {
92
- /** `Content-Type` encoding for the input, defaults to `application/json` if passing a JSON object */
93
- encoding?: string;
94
- /** Request headers to make */
95
- headers?: Headers;
96
- /** Signal for aborting the request */
97
- signal?: AbortSignal;
98
- }
99
- /** Options for the query/procedure request */
100
- export type RPCOptions<T> = BaseRPCOptions & (T extends {
101
- params: any;
102
- } ? {
103
- params: T['params'];
104
- } : {}) & (T extends {
105
- input: any;
106
- } ? {
107
- data: T['input'];
108
- } : {});
109
- type OutputOf<T> = T extends {
110
- output: any;
111
- } ? T['output'] : never;
112
- /** The client that sends out requests. */
113
- export declare class XRPC {
114
- #private;
115
- /** The service it should connect to */
116
- service: string;
117
- /** XRPC fetch handler */
118
- fetch: XRPCFetch;
119
- constructor(options: XRPCOptions);
120
- /**
121
- * Adds a hook to intercept XRPC requests.
122
- * Hooks are executed from last-registered to first-registered
123
- * @param fn Hook function
124
- */
125
- hook(fn: XRPCHook): void;
126
- /**
127
- * Makes a query (GET) request
128
- * @param nsid Namespace ID of a query endpoint
129
- * @param options Options to include like parameters
130
- * @returns The response of the request
131
- */
132
- get<K extends keyof Queries>(nsid: K, options: RPCOptions<Queries[K]>): Promise<XRPCResponse<OutputOf<Queries[K]>>>;
133
- /**
134
- * Makes a procedure (POST) request
135
- * @param nsid Namespace ID of a procedure endpoint
136
- * @param options Options to include like input body or parameters
137
- * @returns The response of the request
138
- */
139
- call<K extends keyof Procedures>(nsid: K, options: RPCOptions<Procedures[K]>): Promise<XRPCResponse<OutputOf<Procedures[K]>>>;
140
- }
141
- /**
142
- * Clones an XRPC instance
143
- * @param rpc Base instance
144
- * @returns The cloned instance
145
- */
146
- export declare const clone: (rpc: XRPC) => XRPC;
147
- /**
148
- * Clones an existing XRPC instance, with a proxy on top.
149
- * @param rpc Base instance
150
- * @param opts Proxying options
151
- * @returns Cloned instance with a proxy added
152
- */
153
- export declare const withProxy: (rpc: XRPC, opts: ProxyOptions) => XRPC;
154
- /** Known endpoint types for proxying */
155
- export type ProxyType = 'atproto_labeler' | 'bsky_fg';
156
- /** Options for proxying a request */
157
- export interface ProxyOptions {
158
- /** Service it should proxy requests to */
159
- service: At.DID;
160
- /** The endpoint to connect */
161
- type: ProxyType | (string & {});
162
- }
163
- /** Default fetch handler */
164
- export declare const fetchHandler: XRPCFetch;
165
- /**
166
- * Check if provided value is an error object
167
- * @param value Response value
168
- * @param names If provided, also checks if the error name matches what you expect
169
- * @returns A boolean on the check
170
- */
171
- export declare const isErrorResponse: (value: any, names?: string[]) => value is ErrorResponseBody;
172
- /** Response body from a thrown query/procedure */
173
- export interface ErrorResponseBody {
174
- error?: string;
175
- message?: string;
176
- }
177
- export {};
1
+ export * from './rpc.js';
2
+ export * from './fetch-handler.js';
3
+ export * from './credential-manager.js';
package/dist/index.js CHANGED
@@ -1,207 +1,4 @@
1
- /**
2
- * @module
3
- * Handles the actual XRPC client functionalities.
4
- */
5
- /** Possible response status from an XRPC service, status <100 is used for the library itself. */
6
- export var ResponseType;
7
- (function (ResponseType) {
8
- /** Unknown error from the library */
9
- ResponseType[ResponseType["Unknown"] = 1] = "Unknown";
10
- /** The server returned an invalid response */
11
- ResponseType[ResponseType["InvalidResponse"] = 2] = "InvalidResponse";
12
- /** Successful response from the service */
13
- ResponseType[ResponseType["Success"] = 200] = "Success";
14
- /** Request was considered invalid by the service */
15
- ResponseType[ResponseType["InvalidRequest"] = 400] = "InvalidRequest";
16
- /** Service requires an authentication token */
17
- ResponseType[ResponseType["AuthRequired"] = 401] = "AuthRequired";
18
- /** Request is forbidden by the service */
19
- ResponseType[ResponseType["Forbidden"] = 403] = "Forbidden";
20
- /** Not a XRPC service */
21
- ResponseType[ResponseType["XRPCNotSupported"] = 404] = "XRPCNotSupported";
22
- /** Payload is considered too large by the service */
23
- ResponseType[ResponseType["PayloadTooLarge"] = 413] = "PayloadTooLarge";
24
- /** Ratelimit was exceeded */
25
- ResponseType[ResponseType["RateLimitExceeded"] = 429] = "RateLimitExceeded";
26
- /** Internal server error */
27
- ResponseType[ResponseType["InternalServerError"] = 500] = "InternalServerError";
28
- /** Method hasn't been implemented */
29
- ResponseType[ResponseType["MethodNotImplemented"] = 501] = "MethodNotImplemented";
30
- /** Failure by an upstream service */
31
- ResponseType[ResponseType["UpstreamFailure"] = 502] = "UpstreamFailure";
32
- /** Not enough resources */
33
- ResponseType[ResponseType["NotEnoughResouces"] = 503] = "NotEnoughResouces";
34
- /** Timeout from upstream service */
35
- ResponseType[ResponseType["UpstreamTimeout"] = 504] = "UpstreamTimeout";
36
- })(ResponseType || (ResponseType = {}));
37
- /** XRPC response status which are recoverable (network error) */
38
- export const RECOVERABLE_RESPONSE_STATUS = [1, 408, 425, 429, 500, 502, 503, 504, 522, 524];
39
- /** Error coming from the XRPC service */
40
- export class XRPCError extends Error {
41
- name = 'XRPCError';
42
- /** Response status */
43
- status;
44
- /** Response headers */
45
- headers;
46
- /** Error kind */
47
- kind;
48
- constructor(status, { kind, message, headers, cause } = {}) {
49
- super(message || `Unspecified error message`, { cause });
50
- this.status = status;
51
- this.kind = kind;
52
- this.headers = headers || {};
53
- }
54
- }
55
- /** The client that sends out requests. */
56
- export class XRPC {
57
- /** The service it should connect to */
58
- service;
59
- /** XRPC fetch handler */
60
- fetch = fetchHandler;
61
- constructor(options) {
62
- this.service = options.service;
63
- }
64
- /**
65
- * Adds a hook to intercept XRPC requests.
66
- * Hooks are executed from last-registered to first-registered
67
- * @param fn Hook function
68
- */
69
- hook(fn) {
70
- this.fetch = fn(this.fetch);
71
- }
72
- /**
73
- * Makes a query (GET) request
74
- * @param nsid Namespace ID of a query endpoint
75
- * @param options Options to include like parameters
76
- * @returns The response of the request
77
- */
78
- get(nsid, options) {
79
- return this.#call({ type: 'get', nsid: nsid, ...options });
80
- }
81
- /**
82
- * Makes a procedure (POST) request
83
- * @param nsid Namespace ID of a procedure endpoint
84
- * @param options Options to include like input body or parameters
85
- * @returns The response of the request
86
- */
87
- call(nsid, options) {
88
- return this.#call({ type: 'post', nsid: nsid, ...options });
89
- }
90
- async #call(request) {
91
- const { status, headers, body } = await this.fetch({
92
- ...request,
93
- service: this.service,
94
- headers: request.headers === undefined ? {} : request.headers,
95
- params: request.params === undefined ? {} : request.params,
96
- });
97
- if (status === ResponseType.Success) {
98
- return { data: body, headers: headers };
99
- }
100
- else if (isErrorResponse(body)) {
101
- throw new XRPCError(status, { kind: body.error, message: body.message, headers });
102
- }
103
- else {
104
- throw new XRPCError(status, { headers });
105
- }
106
- }
107
- }
108
- /**
109
- * Clones an XRPC instance
110
- * @param rpc Base instance
111
- * @returns The cloned instance
112
- */
113
- export const clone = (rpc) => {
114
- const cloned = new XRPC({ service: rpc.service });
115
- cloned.fetch = rpc.fetch;
116
- return cloned;
117
- };
118
- /**
119
- * Clones an existing XRPC instance, with a proxy on top.
120
- * @param rpc Base instance
121
- * @param opts Proxying options
122
- * @returns Cloned instance with a proxy added
123
- */
124
- export const withProxy = (rpc, opts) => {
125
- const cloned = clone(rpc);
126
- cloned.hook((next) => (request) => {
127
- return next({
128
- ...request,
129
- headers: {
130
- ...request.headers,
131
- 'atproto-proxy': `${opts.service}#${opts.type}`,
132
- },
133
- });
134
- });
135
- return cloned;
136
- };
137
- /** Default fetch handler */
138
- export const fetchHandler = async ({ service, type, nsid, headers, params, encoding, data: input, signal, }) => {
139
- const uri = new URL(`/xrpc/${nsid}`, service);
140
- const searchParams = uri.searchParams;
141
- for (const key in params) {
142
- const value = params[key];
143
- if (value !== undefined) {
144
- if (Array.isArray(value)) {
145
- for (let idx = 0, len = value.length; idx < len; idx++) {
146
- const val = value[idx];
147
- searchParams.append(key, val);
148
- }
149
- }
150
- else {
151
- searchParams.set(key, value);
152
- }
153
- }
154
- }
155
- const isProcedure = type === 'post';
156
- const isJson = typeof input === 'object' &&
157
- !(input instanceof FormData || input instanceof Blob || ArrayBuffer.isView(input));
158
- const response = await fetch(uri, {
159
- signal: signal,
160
- method: isProcedure ? 'POST' : 'GET',
161
- headers: encoding || isJson ? { ...headers, 'Content-Type': encoding || 'application/json' } : headers,
162
- body: isJson ? JSON.stringify(input) : input,
163
- });
164
- const responseHeaders = response.headers;
165
- const responseType = responseHeaders.get('Content-Type');
166
- let promise;
167
- let data;
168
- if (responseType) {
169
- if (responseType.startsWith('application/json')) {
170
- promise = response.json();
171
- }
172
- else if (responseType.startsWith('text/')) {
173
- promise = response.text();
174
- }
175
- }
176
- try {
177
- data = await (promise || response.arrayBuffer().then((buffer) => new Uint8Array(buffer)));
178
- }
179
- catch (err) {
180
- throw new XRPCError(ResponseType.InvalidResponse, {
181
- cause: err,
182
- message: `Failed to parse response body`,
183
- });
184
- }
185
- return {
186
- status: response.status,
187
- headers: Object.fromEntries(responseHeaders),
188
- body: data,
189
- };
190
- };
191
- /**
192
- * Check if provided value is an error object
193
- * @param value Response value
194
- * @param names If provided, also checks if the error name matches what you expect
195
- * @returns A boolean on the check
196
- */
197
- export const isErrorResponse = (value, names) => {
198
- if (typeof value !== 'object' || !value) {
199
- return false;
200
- }
201
- const kindType = typeof value.error;
202
- const messageType = typeof value.message;
203
- return ((kindType === 'undefined' || kindType === 'string') &&
204
- (messageType === 'undefined' || messageType === 'string') &&
205
- (!names || names.includes(value.error)));
206
- };
1
+ export * from './rpc.js';
2
+ export * from './fetch-handler.js';
3
+ export * from './credential-manager.js';
207
4
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../lib/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../lib/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,oBAAoB,CAAC;AACnC,cAAc,yBAAyB,CAAC"}
package/dist/rpc.d.ts ADDED
@@ -0,0 +1,96 @@
1
+ import type { At, Procedures, Queries } from './lexicons.js';
2
+ import { type FetchHandler, type FetchHandlerObject } from './fetch-handler.js';
3
+ export type HeadersObject = Record<string, string>;
4
+ /** Response from XRPC service */
5
+ export interface XRPCResponse<T = any> {
6
+ data: T;
7
+ headers: HeadersObject;
8
+ }
9
+ /** Options for constructing an XRPC error */
10
+ export interface XRPCErrorOptions {
11
+ kind?: string;
12
+ description?: string;
13
+ headers?: HeadersObject;
14
+ cause?: unknown;
15
+ }
16
+ /** Error coming from the XRPC service */
17
+ export declare class XRPCError extends Error {
18
+ name: string;
19
+ /** Response status */
20
+ status: number;
21
+ /** Response headers */
22
+ headers: HeadersObject;
23
+ /** Error kind */
24
+ kind?: string;
25
+ /** Error description */
26
+ description?: string;
27
+ constructor(status: number, { kind, description, headers, cause }?: XRPCErrorOptions);
28
+ }
29
+ /** Service proxy options */
30
+ export interface XRPCProxyOptions {
31
+ type: 'atproto_pds' | 'atproto_labeler' | 'bsky_fg' | 'bsky_notif' | ({} & string);
32
+ service: At.DID;
33
+ }
34
+ /** Options for constructing an XRPC */
35
+ export interface XRPCOptions {
36
+ handler: FetchHandler | FetchHandlerObject;
37
+ proxy?: XRPCProxyOptions;
38
+ }
39
+ /** XRPC request options */
40
+ export interface XRPCRequestOptions {
41
+ type: 'get' | 'post';
42
+ nsid: string;
43
+ headers?: HeadersInit;
44
+ params?: Record<string, unknown>;
45
+ data?: FormData | Blob | ArrayBufferView | Record<string, unknown>;
46
+ signal?: AbortSignal;
47
+ }
48
+ /** XRPC response */
49
+ export interface XRPCResponse<T = any> {
50
+ data: T;
51
+ headers: HeadersObject;
52
+ }
53
+ /** Base options for the query/procedure request */
54
+ interface BaseRPCOptions {
55
+ /** Request headers to make */
56
+ headers?: HeadersInit;
57
+ /** Signal for aborting the request */
58
+ signal?: AbortSignal;
59
+ }
60
+ /** Options for the query/procedure request */
61
+ export type RPCOptions<T> = BaseRPCOptions & (T extends {
62
+ params: any;
63
+ } ? {
64
+ params: T['params'];
65
+ } : {}) & (T extends {
66
+ input: any;
67
+ } ? {
68
+ data: T['input'];
69
+ } : {});
70
+ type OutputOf<T> = T extends {
71
+ output: any;
72
+ } ? T['output'] : never;
73
+ export declare class XRPC {
74
+ handle: FetchHandler;
75
+ proxy: XRPCProxyOptions | undefined;
76
+ constructor({ handler, proxy }: XRPCOptions);
77
+ /**
78
+ * Makes a query (GET) request
79
+ * @param nsid Namespace ID of a query endpoint
80
+ * @param options Options to include like parameters
81
+ * @returns The response of the request
82
+ */
83
+ get<K extends keyof Queries>(nsid: K, options: RPCOptions<Queries[K]>): Promise<XRPCResponse<OutputOf<Queries[K]>>>;
84
+ /**
85
+ * Makes a procedure (POST) request
86
+ * @param nsid Namespace ID of a procedure endpoint
87
+ * @param options Options to include like input body or parameters
88
+ * @returns The response of the request
89
+ */
90
+ call<K extends keyof Procedures>(nsid: K, options: RPCOptions<Procedures[K]>): Promise<XRPCResponse<OutputOf<Procedures[K]>>>;
91
+ /** Makes a request to the XRPC service */
92
+ request(options: XRPCRequestOptions): Promise<XRPCResponse>;
93
+ }
94
+ export declare const clone: (rpc: XRPC) => XRPC;
95
+ export declare const withProxy: (rpc: XRPC, options: XRPCProxyOptions) => XRPC;
96
+ export {};
package/dist/rpc.js ADDED
@@ -0,0 +1,173 @@
1
+ import { buildFetchHandler } from './fetch-handler.js';
2
+ import { mergeHeaders } from './utils/http.js';
3
+ /** Possible response status from an XRPC service, status <100 is used for the library itself. */
4
+ var ResponseType;
5
+ (function (ResponseType) {
6
+ /** Unknown error from the library */
7
+ ResponseType[ResponseType["Unknown"] = 1] = "Unknown";
8
+ /** The server returned an invalid response */
9
+ ResponseType[ResponseType["InvalidResponse"] = 2] = "InvalidResponse";
10
+ /** Successful response from the service */
11
+ ResponseType[ResponseType["Success"] = 200] = "Success";
12
+ /** Request was considered invalid by the service */
13
+ ResponseType[ResponseType["InvalidRequest"] = 400] = "InvalidRequest";
14
+ /** Service requires an authentication token */
15
+ ResponseType[ResponseType["AuthRequired"] = 401] = "AuthRequired";
16
+ /** Request is forbidden by the service */
17
+ ResponseType[ResponseType["Forbidden"] = 403] = "Forbidden";
18
+ /** Not a XRPC service */
19
+ ResponseType[ResponseType["XRPCNotSupported"] = 404] = "XRPCNotSupported";
20
+ /** Payload is considered too large by the service */
21
+ ResponseType[ResponseType["PayloadTooLarge"] = 413] = "PayloadTooLarge";
22
+ /** Ratelimit was exceeded */
23
+ ResponseType[ResponseType["RateLimitExceeded"] = 429] = "RateLimitExceeded";
24
+ /** Internal server error */
25
+ ResponseType[ResponseType["InternalServerError"] = 500] = "InternalServerError";
26
+ /** Method hasn't been implemented */
27
+ ResponseType[ResponseType["MethodNotImplemented"] = 501] = "MethodNotImplemented";
28
+ /** Failure by an upstream service */
29
+ ResponseType[ResponseType["UpstreamFailure"] = 502] = "UpstreamFailure";
30
+ /** Not enough resources */
31
+ ResponseType[ResponseType["NotEnoughResouces"] = 503] = "NotEnoughResouces";
32
+ /** Timeout from upstream service */
33
+ ResponseType[ResponseType["UpstreamTimeout"] = 504] = "UpstreamTimeout";
34
+ })(ResponseType || (ResponseType = {}));
35
+ /** Error coming from the XRPC service */
36
+ export class XRPCError extends Error {
37
+ constructor(status, { kind, description, headers, cause } = {}) {
38
+ super(`${kind || 'UnspecifiedKind'} > ${description || `Unspecified error description`}`, { cause });
39
+ this.name = 'XRPCError';
40
+ this.status = status;
41
+ this.kind = kind;
42
+ this.description = description;
43
+ this.headers = headers || {};
44
+ }
45
+ }
46
+ export class XRPC {
47
+ constructor({ handler, proxy }) {
48
+ this.handle = buildFetchHandler(handler);
49
+ this.proxy = proxy;
50
+ }
51
+ /**
52
+ * Makes a query (GET) request
53
+ * @param nsid Namespace ID of a query endpoint
54
+ * @param options Options to include like parameters
55
+ * @returns The response of the request
56
+ */
57
+ get(nsid, options) {
58
+ return this.request({ type: 'get', nsid: nsid, ...options });
59
+ }
60
+ /**
61
+ * Makes a procedure (POST) request
62
+ * @param nsid Namespace ID of a procedure endpoint
63
+ * @param options Options to include like input body or parameters
64
+ * @returns The response of the request
65
+ */
66
+ call(nsid, options) {
67
+ return this.request({ type: 'post', nsid: nsid, ...options });
68
+ }
69
+ /** Makes a request to the XRPC service */
70
+ async request(options) {
71
+ const data = options.data;
72
+ const url = `/xrpc/${options.nsid}` + constructSearchParams(options.params);
73
+ const isInputJson = isJsonValue(data);
74
+ const response = await this.handle(url, {
75
+ method: options.type,
76
+ signal: options.signal,
77
+ body: isInputJson ? JSON.stringify(data) : data,
78
+ headers: mergeHeaders(options.headers, {
79
+ 'content-type': isInputJson ? 'application/json' : null,
80
+ 'atproto-proxy': constructProxyHeader(this.proxy),
81
+ }),
82
+ });
83
+ const responseStatus = response.status;
84
+ const responseHeaders = Object.fromEntries(response.headers);
85
+ const responseType = responseHeaders['content-type'];
86
+ let promise;
87
+ let ret;
88
+ if (responseType) {
89
+ if (responseType.startsWith('application/json')) {
90
+ promise = response.json();
91
+ }
92
+ else if (responseType.startsWith('text/')) {
93
+ promise = response.text();
94
+ }
95
+ }
96
+ try {
97
+ ret = await (promise || response.arrayBuffer().then((buffer) => new Uint8Array(buffer)));
98
+ }
99
+ catch (err) {
100
+ throw new XRPCError(ResponseType.InvalidResponse, {
101
+ cause: err,
102
+ kind: 'InvalidResponse',
103
+ description: `Failed to parse response body`,
104
+ headers: responseHeaders,
105
+ });
106
+ }
107
+ if (responseStatus === ResponseType.Success) {
108
+ return {
109
+ data: ret,
110
+ headers: responseHeaders,
111
+ };
112
+ }
113
+ if (isErrorResponse(ret)) {
114
+ throw new XRPCError(responseStatus, {
115
+ kind: ret.error,
116
+ description: ret.message,
117
+ headers: responseHeaders,
118
+ });
119
+ }
120
+ throw new XRPCError(responseStatus, { headers: responseHeaders });
121
+ }
122
+ }
123
+ const constructProxyHeader = (proxy) => {
124
+ if (proxy) {
125
+ return `${proxy.service}#${proxy.type}`;
126
+ }
127
+ return null;
128
+ };
129
+ const constructSearchParams = (params) => {
130
+ let searchParams;
131
+ for (const key in params) {
132
+ const value = params[key];
133
+ if (value !== undefined) {
134
+ searchParams ??= new URLSearchParams();
135
+ if (Array.isArray(value)) {
136
+ for (let idx = 0, len = value.length; idx < len; idx++) {
137
+ const val = value[idx];
138
+ searchParams.append(key, '' + val);
139
+ }
140
+ }
141
+ else {
142
+ searchParams.set(key, '' + value);
143
+ }
144
+ }
145
+ }
146
+ return searchParams ? `?` + searchParams.toString() : '';
147
+ };
148
+ const isJsonValue = (o) => {
149
+ if (typeof o !== 'object' || o === null) {
150
+ return false;
151
+ }
152
+ if ('toJSON' in o) {
153
+ return true;
154
+ }
155
+ const proto = Object.getPrototypeOf(o);
156
+ return proto === null || proto === Object.prototype;
157
+ };
158
+ const isErrorResponse = (value) => {
159
+ if (typeof value !== 'object' || value === null) {
160
+ return false;
161
+ }
162
+ const kindType = typeof value.error;
163
+ const messageType = typeof value.message;
164
+ return ((kindType === 'undefined' || kindType === 'string') &&
165
+ (messageType === 'undefined' || messageType === 'string'));
166
+ };
167
+ export const clone = (rpc) => {
168
+ return new XRPC({ handler: rpc.handle, proxy: rpc.proxy });
169
+ };
170
+ export const withProxy = (rpc, options) => {
171
+ return new XRPC({ handler: rpc.handle, proxy: options });
172
+ };
173
+ //# sourceMappingURL=rpc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rpc.js","sourceRoot":"","sources":["../lib/rpc.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,8 @@
1
1
  /**
2
2
  * @module
3
- * DID document-related functionalities
3
+ * DID document-related functionalities.
4
+ * This module is exported for convenience and is no way part of public API,
5
+ * it can be removed at any time.
4
6
  */
5
7
  /**
6
8
  * Retrieves AT Protocol PDS endpoint from the DID document, if available
package/dist/utils/did.js CHANGED
@@ -1,6 +1,8 @@
1
1
  /**
2
2
  * @module
3
- * DID document-related functionalities
3
+ * DID document-related functionalities.
4
+ * This module is exported for convenience and is no way part of public API,
5
+ * it can be removed at any time.
4
6
  */
5
7
  /**
6
8
  * Retrieves AT Protocol PDS endpoint from the DID document, if available
@@ -1 +1 @@
1
- {"version":3,"file":"did.js","sourceRoot":"","sources":["../../lib/utils/did.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,GAAgB,EAAsB,EAAE;IACtE,OAAO,kBAAkB,CAAC,GAAG,EAAE,cAAc,EAAE,2BAA2B,CAAC,CAAC;AAC7E,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CACjC,GAAgB,EAChB,SAAiB,EACjB,WAAmB,EACE,EAAE;IACvB,MAAM,GAAG,GAAG,GAAG,CAAC,EAAE,CAAC;IAEnB,MAAM,YAAY,GAAG,GAAG,GAAG,SAAS,CAAC;IACrC,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,KAAK,SAAS,IAAI,OAAO,CAAC,EAAE,KAAK,YAAY,CAAC,CAAC;IAEtG,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,IAAI,OAAO,KAAK,CAAC,eAAe,KAAK,QAAQ,EAAE,CAAC;QACvF,OAAO,SAAS,CAAC;IAClB,CAAC;IAED,OAAO,WAAW,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;AAC3C,CAAC,CAAC;AAEF,MAAM,WAAW,GAAG,CAAC,MAAc,EAAsB,EAAE;IAC1D,IAAI,GAAG,CAAC;IACR,IAAI,CAAC;QACJ,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;IACvB,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,SAAS,CAAC;IAClB,CAAC;IAED,MAAM,KAAK,GAAG,GAAG,CAAC,QAAQ,CAAC;IAE3B,IAAI,GAAG,CAAC,QAAQ,IAAI,CAAC,KAAK,KAAK,OAAO,IAAI,KAAK,KAAK,QAAQ,CAAC,EAAE,CAAC;QAC/D,OAAO,MAAM,CAAC;IACf,CAAC;AACF,CAAC,CAAC"}
1
+ {"version":3,"file":"did.js","sourceRoot":"","sources":["../../lib/utils/did.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,GAAgB,EAAsB,EAAE;IACtE,OAAO,kBAAkB,CAAC,GAAG,EAAE,cAAc,EAAE,2BAA2B,CAAC,CAAC;AAC7E,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CACjC,GAAgB,EAChB,SAAiB,EACjB,WAAmB,EACE,EAAE;IACvB,MAAM,GAAG,GAAG,GAAG,CAAC,EAAE,CAAC;IAEnB,MAAM,YAAY,GAAG,GAAG,GAAG,SAAS,CAAC;IACrC,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,KAAK,SAAS,IAAI,OAAO,CAAC,EAAE,KAAK,YAAY,CAAC,CAAC;IAEtG,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,IAAI,OAAO,KAAK,CAAC,eAAe,KAAK,QAAQ,EAAE,CAAC;QACvF,OAAO,SAAS,CAAC;IAClB,CAAC;IAED,OAAO,WAAW,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;AAC3C,CAAC,CAAC;AAEF,MAAM,WAAW,GAAG,CAAC,MAAc,EAAsB,EAAE;IAC1D,IAAI,GAAG,CAAC;IACR,IAAI,CAAC;QACJ,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;IACvB,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,SAAS,CAAC;IAClB,CAAC;IAED,MAAM,KAAK,GAAG,GAAG,CAAC,QAAQ,CAAC;IAE3B,IAAI,GAAG,CAAC,QAAQ,IAAI,CAAC,KAAK,KAAK,OAAO,IAAI,KAAK,KAAK,QAAQ,CAAC,EAAE,CAAC;QAC/D,OAAO,MAAM,CAAC;IACf,CAAC;AACF,CAAC,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @module
3
+ * Assortment of HTTP utilities
4
+ * This module is exported for convenience and is no way part of public API,
5
+ * it can be removed at any time.
6
+ */
7
+ export declare const mergeHeaders: (init: HeadersInit | undefined, defaults: Record<string, string | null>) => HeadersInit | undefined;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @module
3
+ * Assortment of HTTP utilities
4
+ * This module is exported for convenience and is no way part of public API,
5
+ * it can be removed at any time.
6
+ */
7
+ export const mergeHeaders = (init, defaults) => {
8
+ let headers;
9
+ for (const name in defaults) {
10
+ const value = defaults[name];
11
+ if (value !== null) {
12
+ headers ??= new Headers(init);
13
+ if (!headers.has(name)) {
14
+ headers.set(name, value);
15
+ }
16
+ }
17
+ }
18
+ return headers ?? init;
19
+ };
20
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../lib/utils/http.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,YAAY,GAAG,CAC3B,IAA6B,EAC7B,QAAuC,EACb,EAAE;IAC5B,IAAI,OAA4B,CAAC;IAEjC,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;QAE7B,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACpB,OAAO,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;YAE9B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBACxB,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YAC1B,CAAC;QACF,CAAC;IACF,CAAC;IAED,OAAO,OAAO,IAAI,IAAI,CAAC;AACxB,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@atcute/client",
4
- "version": "1.0.0",
4
+ "version": "2.0.0",
5
5
  "description": "lightweight and cute API client for AT Protocol",
6
6
  "license": "MIT",
7
7
  "repository": {
@@ -13,16 +13,19 @@
13
13
  "exports": {
14
14
  ".": "./dist/index.js",
15
15
  "./lexicons": "./dist/lexicons.js",
16
- "./middlewares/auth": "./dist/middlewares/auth.js",
17
- "./middlewares/mod": "./dist/middlewares/mod.js",
18
16
  "./utils/did": "./dist/utils/did.js",
17
+ "./utils/http": "./dist/utils/http.js",
19
18
  "./utils/jwt": "./dist/utils/jwt.js"
20
19
  },
21
20
  "devDependencies": {
21
+ "@vitest/coverage-v8": "^2.0.5",
22
+ "vitest": "^2.0.5",
23
+ "@atcute/internal-dev-env": "^1.0.0",
22
24
  "@atcute/lex-cli": "^1.0.0"
23
25
  },
24
26
  "scripts": {
25
- "build": "tsc",
27
+ "build": "tsc --project tsconfig.build.json",
28
+ "test": "vitest run",
26
29
  "generate": "./scripts/generate-lexicons.sh",
27
30
  "prepublish": "rm -rf dist; pnpm run build"
28
31
  }
@@ -1,150 +0,0 @@
1
- /**
2
- * @module
3
- * Contains a middleware that handles authentication to a personal data server.
4
- */
5
- import { fetchHandler, isErrorResponse, XRPCError } from '../index.js';
6
- import { getPdsEndpoint } from '../utils/did.js';
7
- import { decodeJwt } from '../utils/jwt.js';
8
- /** Authentication/session management middleware */
9
- export class AtpAuth {
10
- #rpc;
11
- #refreshSessionPromise;
12
- #onExpired;
13
- #onRefresh;
14
- #onSessionUpdate;
15
- /** Current session state */
16
- session;
17
- constructor(rpc, { onExpired, onRefresh, onSessionUpdate } = {}) {
18
- this.#rpc = rpc;
19
- this.#onRefresh = onRefresh;
20
- this.#onExpired = onExpired;
21
- this.#onSessionUpdate = onSessionUpdate;
22
- rpc.hook((next) => async (request) => {
23
- await this.#refreshSessionPromise;
24
- let res = await next(this.#decorateRequest(request));
25
- if (isErrorResponse(res.body, ['ExpiredToken']) && this.session?.refreshJwt) {
26
- await this.#refreshSession();
27
- if (this.session) {
28
- // retry fetch
29
- res = await next(this.#decorateRequest(request));
30
- }
31
- }
32
- return res;
33
- });
34
- }
35
- #decorateRequest(req) {
36
- const session = this.session;
37
- if (session && !req.headers['Authorization']) {
38
- return {
39
- ...req,
40
- service: session.pdsUri || req.service,
41
- headers: {
42
- ...req.headers,
43
- Authorization: `Bearer ${session.accessJwt}`,
44
- },
45
- };
46
- }
47
- return req;
48
- }
49
- #refreshSession() {
50
- return (this.#refreshSessionPromise ||= this.#refreshSessionInner().finally(() => {
51
- this.#refreshSessionPromise = undefined;
52
- }));
53
- }
54
- async #refreshSessionInner() {
55
- const session = this.session;
56
- if (!session || !session.refreshJwt) {
57
- return;
58
- }
59
- const res = await fetchHandler({
60
- service: session.pdsUri || this.#rpc.service,
61
- type: 'post',
62
- nsid: 'com.atproto.server.refreshSession',
63
- headers: {
64
- Authorization: `Bearer ${session.refreshJwt}`,
65
- },
66
- params: {},
67
- });
68
- if (isErrorResponse(res.body, ['ExpiredToken', 'InvalidToken'])) {
69
- // failed due to a bad refresh token
70
- this.session = undefined;
71
- this.#onExpired?.(session);
72
- }
73
- else if (res.status === 200) {
74
- // succeeded, update the session
75
- this.#updateSession({ ...session, ...res.body });
76
- this.#onRefresh?.(this.session);
77
- }
78
- }
79
- #updateSession(raw) {
80
- const didDoc = raw.didDoc;
81
- let pdsUri;
82
- if (didDoc) {
83
- pdsUri = getPdsEndpoint(didDoc);
84
- }
85
- const newSession = {
86
- accessJwt: raw.accessJwt,
87
- refreshJwt: raw.refreshJwt,
88
- handle: raw.handle,
89
- did: raw.did,
90
- pdsUri: pdsUri,
91
- email: raw.email,
92
- emailConfirmed: raw.emailConfirmed,
93
- emailAuthFactor: raw.emailConfirmed,
94
- active: raw.active ?? true,
95
- inactiveStatus: raw.status,
96
- };
97
- this.session = newSession;
98
- this.#onSessionUpdate?.(newSession);
99
- return newSession;
100
- }
101
- /**
102
- * Resume a saved session
103
- * @param session Session information, taken from `AtpAuth#session` after login
104
- */
105
- async resume(session) {
106
- const now = Date.now() / 1000 + 60 * 5;
107
- const refreshToken = decodeJwt(session.refreshJwt);
108
- if (now >= refreshToken.exp) {
109
- throw new XRPCError(401, { kind: 'InvalidToken' });
110
- }
111
- const accessToken = decodeJwt(session.accessJwt);
112
- this.session = session;
113
- if (now >= accessToken.exp) {
114
- await this.#refreshSession();
115
- }
116
- else {
117
- const promise = this.#rpc.get('com.atproto.server.getSession', {});
118
- promise.then((response) => {
119
- const existing = this.session;
120
- const next = response.data;
121
- if (!existing) {
122
- return;
123
- }
124
- this.#updateSession({ ...existing, ...next });
125
- });
126
- }
127
- if (!this.session) {
128
- throw new XRPCError(401, { kind: 'InvalidToken' });
129
- }
130
- return this.session;
131
- }
132
- /**
133
- * Perform a login operation
134
- * @param options Login options
135
- * @returns Session data that can be saved for later
136
- */
137
- async login(options) {
138
- // Reset the session
139
- this.session = undefined;
140
- const res = await this.#rpc.call('com.atproto.server.createSession', {
141
- data: {
142
- identifier: options.identifier,
143
- password: options.password,
144
- authFactorToken: options.code,
145
- },
146
- });
147
- return this.#updateSession(res.data);
148
- }
149
- }
150
- //# sourceMappingURL=auth.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../lib/middlewares/auth.ts"],"names":[],"mappings":"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"}
@@ -1,24 +0,0 @@
1
- /**
2
- * @module
3
- * Contains a middleware that adds `atproto-accept-labelers` header to requests.
4
- */
5
- import type { XRPC } from '../index.js';
6
- import type { At } from '../lexicons.js';
7
- /** Options for constructing a moderation middleware */
8
- export interface AtpModOptions {
9
- /** Array of moderation services to use */
10
- labelers?: ModerationService[];
11
- }
12
- /** Moderation middleware, unstable. */
13
- export declare class AtpMod {
14
- /** Array of moderation services that gets forwarded as a header */
15
- labelers: ModerationService[];
16
- constructor(rpc: XRPC, { labelers }?: AtpModOptions);
17
- }
18
- /** Interface detailing what moderator service to use and how it should be used. */
19
- export interface ModerationService {
20
- /** Moderator service to use */
21
- did: At.DID;
22
- /** Whether it should apply takedowns made by this service. */
23
- redact?: boolean;
24
- }
@@ -1,24 +0,0 @@
1
- /**
2
- * @module
3
- * Contains a middleware that adds `atproto-accept-labelers` header to requests.
4
- */
5
- /** Moderation middleware, unstable. */
6
- export class AtpMod {
7
- /** Array of moderation services that gets forwarded as a header */
8
- labelers;
9
- constructor(rpc, { labelers = [] } = {}) {
10
- this.labelers = labelers;
11
- rpc.hook((next) => (request) => {
12
- return next({
13
- ...request,
14
- headers: {
15
- ...request.headers,
16
- 'atproto-accept-labelers': this.labelers
17
- .map((labeler) => labeler.did + (labeler.redact ? `;redact` : ``))
18
- .join(', '),
19
- },
20
- });
21
- });
22
- }
23
- }
24
- //# sourceMappingURL=mod.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"mod.js","sourceRoot":"","sources":["../../lib/middlewares/mod.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAWH,uCAAuC;AACvC,MAAM,OAAO,MAAM;IAClB,mEAAmE;IACnE,QAAQ,CAAsB;IAE9B,YAAY,GAAS,EAAE,EAAE,QAAQ,GAAG,EAAE,KAAoB,EAAE;QAC3D,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAEzB,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,EAAE;YAC9B,OAAO,IAAI,CAAC;gBACX,GAAG,OAAO;gBACV,OAAO,EAAE;oBACR,GAAG,OAAO,CAAC,OAAO;oBAClB,yBAAyB,EAAE,IAAI,CAAC,QAAQ;yBACtC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;yBACjE,IAAI,CAAC,IAAI,CAAC;iBACZ;aACD,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;IACJ,CAAC;CACD"}