@atproto/lex-client 0.0.4 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +42 -0
- package/dist/agent.d.ts +10 -9
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +3 -0
- package/dist/agent.js.map +1 -1
- package/dist/client.d.ts +51 -113
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +38 -42
- package/dist/client.js.map +1 -1
- package/dist/errors.d.ts +82 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +132 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lexicons/com/atproto/repo/createRecord.defs.d.ts +7 -7
- package/dist/lexicons/com/atproto/repo/createRecord.defs.d.ts.map +1 -1
- package/dist/lexicons/com/atproto/repo/createRecord.defs.js +8 -12
- package/dist/lexicons/com/atproto/repo/createRecord.defs.js.map +1 -1
- package/dist/lexicons/com/atproto/repo/deleteRecord.defs.d.ts +7 -7
- package/dist/lexicons/com/atproto/repo/deleteRecord.defs.d.ts.map +1 -1
- package/dist/lexicons/com/atproto/repo/deleteRecord.defs.js +8 -12
- package/dist/lexicons/com/atproto/repo/deleteRecord.defs.js.map +1 -1
- package/dist/lexicons/com/atproto/repo/getRecord.defs.d.ts +5 -6
- package/dist/lexicons/com/atproto/repo/getRecord.defs.d.ts.map +1 -1
- package/dist/lexicons/com/atproto/repo/getRecord.defs.js +6 -10
- package/dist/lexicons/com/atproto/repo/getRecord.defs.js.map +1 -1
- package/dist/lexicons/com/atproto/repo/listRecords.defs.d.ts +5 -6
- package/dist/lexicons/com/atproto/repo/listRecords.defs.d.ts.map +1 -1
- package/dist/lexicons/com/atproto/repo/listRecords.defs.js +5 -8
- package/dist/lexicons/com/atproto/repo/listRecords.defs.js.map +1 -1
- package/dist/lexicons/com/atproto/repo/putRecord.defs.d.ts +7 -7
- package/dist/lexicons/com/atproto/repo/putRecord.defs.d.ts.map +1 -1
- package/dist/lexicons/com/atproto/repo/putRecord.defs.js +8 -12
- package/dist/lexicons/com/atproto/repo/putRecord.defs.js.map +1 -1
- package/dist/lexicons/com/atproto/repo/uploadBlob.defs.d.ts +7 -7
- package/dist/lexicons/com/atproto/repo/uploadBlob.defs.d.ts.map +1 -1
- package/dist/lexicons/com/atproto/repo/uploadBlob.defs.js +6 -9
- package/dist/lexicons/com/atproto/repo/uploadBlob.defs.js.map +1 -1
- package/dist/lexicons/com/atproto/sync/getBlob.d.ts +3 -0
- package/dist/lexicons/com/atproto/sync/getBlob.d.ts.map +1 -0
- package/dist/lexicons/com/atproto/sync/getBlob.defs.d.ts +25 -0
- package/dist/lexicons/com/atproto/sync/getBlob.defs.d.ts.map +1 -0
- package/dist/lexicons/com/atproto/sync/getBlob.defs.js +27 -0
- package/dist/lexicons/com/atproto/sync/getBlob.defs.js.map +1 -0
- package/dist/lexicons/com/atproto/sync/getBlob.js +10 -0
- package/dist/lexicons/com/atproto/sync/getBlob.js.map +1 -0
- package/dist/lexicons/com/atproto/sync.d.ts +2 -0
- package/dist/lexicons/com/atproto/sync.d.ts.map +1 -0
- package/dist/lexicons/com/atproto/sync.js +9 -0
- package/dist/lexicons/com/atproto/sync.js.map +1 -0
- package/dist/lexicons/com/atproto.d.ts +1 -0
- package/dist/lexicons/com/atproto.d.ts.map +1 -1
- package/dist/lexicons/com/atproto.js +2 -1
- package/dist/lexicons/com/atproto.js.map +1 -1
- package/dist/lexicons.d.ts +2 -0
- package/dist/lexicons.d.ts.map +1 -0
- package/dist/lexicons.js +6 -0
- package/dist/lexicons.js.map +1 -0
- package/dist/response.d.ts +25 -8
- package/dist/response.d.ts.map +1 -1
- package/dist/response.js +123 -10
- package/dist/response.js.map +1 -1
- package/dist/types.d.ts +18 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +0 -4
- package/dist/types.js.map +1 -1
- package/dist/util.d.ts +14 -0
- package/dist/util.d.ts.map +1 -0
- package/dist/util.js +65 -0
- package/dist/util.js.map +1 -0
- package/dist/xrpc.d.ts +35 -32
- package/dist/xrpc.d.ts.map +1 -1
- package/dist/xrpc.js +116 -124
- package/dist/xrpc.js.map +1 -1
- package/package.json +10 -10
- package/src/agent.ts +18 -14
- package/src/client.ts +135 -114
- package/src/errors.ts +206 -0
- package/src/index.ts +1 -1
- package/src/lexicons/com/atproto/repo/createRecord.defs.ts +31 -36
- package/src/lexicons/com/atproto/repo/deleteRecord.defs.ts +27 -32
- package/src/lexicons/com/atproto/repo/getRecord.defs.ts +12 -17
- package/src/lexicons/com/atproto/repo/listRecords.defs.ts +13 -15
- package/src/lexicons/com/atproto/repo/putRecord.defs.ts +32 -37
- package/src/lexicons/com/atproto/repo/uploadBlob.defs.ts +13 -15
- package/src/lexicons/com/atproto/sync/getBlob.defs.ts +37 -0
- package/src/lexicons/com/atproto/sync/getBlob.ts +6 -0
- package/src/lexicons/com/atproto/sync.ts +5 -0
- package/src/lexicons/com/atproto.ts +1 -0
- package/src/lexicons.ts +1 -0
- package/src/response.ts +201 -15
- package/src/types.ts +26 -5
- package/src/util.ts +84 -0
- package/src/xrpc.ts +220 -232
- package/tsconfig.tests.json +4 -7
- package/dist/error.d.ts +0 -66
- package/dist/error.d.ts.map +0 -1
- package/dist/error.js +0 -100
- package/dist/error.js.map +0 -1
- package/src/error.ts +0 -145
package/dist/xrpc.js
CHANGED
|
@@ -1,25 +1,45 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.asLexRpcFailure = asLexRpcFailure;
|
|
3
4
|
exports.xrpc = xrpc;
|
|
4
|
-
exports.
|
|
5
|
-
|
|
6
|
-
exports.xrpcRequestInit = xrpcRequestInit;
|
|
7
|
-
exports.xrpcRequestHeaders = xrpcRequestHeaders;
|
|
8
|
-
exports.xrpcResponseHandler = xrpcResponseHandler;
|
|
9
|
-
exports.extractEncoding = extractEncoding;
|
|
10
|
-
exports.readResponseBody = readResponseBody;
|
|
5
|
+
exports.xrpcSafe = xrpcSafe;
|
|
6
|
+
const lex_data_1 = require("@atproto/lex-data");
|
|
11
7
|
const lex_json_1 = require("@atproto/lex-json");
|
|
12
8
|
const lex_schema_1 = require("@atproto/lex-schema");
|
|
13
|
-
const
|
|
9
|
+
const errors_js_1 = require("./errors.js");
|
|
14
10
|
const response_js_1 = require("./response.js");
|
|
15
|
-
const
|
|
11
|
+
const util_js_1 = require("./util.js");
|
|
12
|
+
/**
|
|
13
|
+
* Utility method to type cast the error thrown by {@link xrpc} to an
|
|
14
|
+
* {@link LexRpcFailure} matching the provided method. Only use this function
|
|
15
|
+
* inside a catch block right after calling {@link xrpc}, and use the same
|
|
16
|
+
* method type parameter as used in the {@link xrpc} call.
|
|
17
|
+
*/
|
|
18
|
+
function asLexRpcFailure(err) {
|
|
19
|
+
if (err instanceof errors_js_1.LexRpcResponseError)
|
|
20
|
+
return err;
|
|
21
|
+
if (err instanceof errors_js_1.LexRpcUpstreamError)
|
|
22
|
+
return err;
|
|
23
|
+
return errors_js_1.LexRpcUnexpectedError.from(err);
|
|
24
|
+
}
|
|
16
25
|
async function xrpc(agent, ns, options = {}) {
|
|
26
|
+
try {
|
|
27
|
+
return await lexRpcRequest(agent, ns, options);
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
throw asLexRpcFailure(err);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
async function xrpcSafe(agent, ns, options = {}) {
|
|
34
|
+
return lexRpcRequest(agent, ns, options).catch((asLexRpcFailure));
|
|
35
|
+
}
|
|
36
|
+
async function lexRpcRequest(agent, ns, options = {}) {
|
|
37
|
+
const method = (0, lex_schema_1.getMain)(ns);
|
|
17
38
|
options.signal?.throwIfAborted();
|
|
18
|
-
const method = (0, types_js_1.getMain)(ns);
|
|
19
39
|
const url = xrpcRequestUrl(method, options);
|
|
20
40
|
const request = xrpcRequestInit(method, options);
|
|
21
41
|
const response = await agent.fetchHandler(url, request);
|
|
22
|
-
return
|
|
42
|
+
return response_js_1.LexRpcResponse.fromFetchResponse(method, response, options);
|
|
23
43
|
}
|
|
24
44
|
function xrpcRequestUrl(method, options) {
|
|
25
45
|
const path = `/xrpc/${method.nsid}`;
|
|
@@ -33,15 +53,26 @@ function xrpcRequestParams(schema, params, options) {
|
|
|
33
53
|
return urlSearchParams?.size ? urlSearchParams.toString() : undefined;
|
|
34
54
|
}
|
|
35
55
|
function xrpcRequestInit(schema, options) {
|
|
36
|
-
const headers =
|
|
56
|
+
const headers = (0, util_js_1.buildAtprotoHeaders)(options);
|
|
57
|
+
// Tell the server what type of response we're expecting
|
|
58
|
+
if (schema.output.encoding) {
|
|
59
|
+
headers.set('accept', schema.output.encoding);
|
|
60
|
+
}
|
|
61
|
+
// Caller should not set content-type header
|
|
62
|
+
if (headers.has('content-type')) {
|
|
63
|
+
const contentType = headers.get('content-type');
|
|
64
|
+
throw new TypeError(`Unexpected content-type header (${contentType})`);
|
|
65
|
+
}
|
|
37
66
|
// Requests with body
|
|
38
|
-
if ('input' in schema
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
67
|
+
if ('input' in schema) {
|
|
68
|
+
const encodingHint = options.encoding;
|
|
69
|
+
const input = xrpcProcedureInput(schema, options, encodingHint);
|
|
70
|
+
if (input) {
|
|
71
|
+
headers.set('content-type', input.encoding);
|
|
72
|
+
}
|
|
73
|
+
else if (encodingHint != null) {
|
|
74
|
+
throw new TypeError(`Unexpected encoding hint (${encodingHint})`);
|
|
43
75
|
}
|
|
44
|
-
headers.set('content-type', schema.input.encoding);
|
|
45
76
|
return {
|
|
46
77
|
duplex: 'half',
|
|
47
78
|
redirect: 'follow',
|
|
@@ -50,9 +81,7 @@ function xrpcRequestInit(schema, options) {
|
|
|
50
81
|
signal: options.signal,
|
|
51
82
|
method: 'POST',
|
|
52
83
|
headers,
|
|
53
|
-
body:
|
|
54
|
-
? schema.input?.body.parse(options.body)
|
|
55
|
-
: options.body),
|
|
84
|
+
body: input?.body,
|
|
56
85
|
};
|
|
57
86
|
}
|
|
58
87
|
// Requests without body
|
|
@@ -62,124 +91,87 @@ function xrpcRequestInit(schema, options) {
|
|
|
62
91
|
referrerPolicy: 'strict-origin-when-cross-origin', // (default)
|
|
63
92
|
mode: 'cors', // (default)
|
|
64
93
|
signal: options.signal,
|
|
65
|
-
method:
|
|
94
|
+
method: 'GET',
|
|
66
95
|
headers,
|
|
67
96
|
};
|
|
68
97
|
}
|
|
69
|
-
function
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
if (options.labelers) {
|
|
75
|
-
headers.set('atproto-accept-labelers', [...options.labelers, headers.get('atproto-accept-labelers')?.trim()]
|
|
76
|
-
.filter(Boolean)
|
|
77
|
-
.join(', '));
|
|
78
|
-
}
|
|
79
|
-
return headers;
|
|
80
|
-
}
|
|
81
|
-
function xrpcRequestBody(encoding, body) {
|
|
82
|
-
if (encoding === undefined) {
|
|
83
|
-
return null;
|
|
98
|
+
function xrpcProcedureInput(method, options, encodingHint) {
|
|
99
|
+
const { input } = method;
|
|
100
|
+
const { body } = options;
|
|
101
|
+
if (options.validateRequest) {
|
|
102
|
+
input.schema?.check(body);
|
|
84
103
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
return body;
|
|
92
|
-
}
|
|
93
|
-
else {
|
|
94
|
-
if (ArrayBuffer.isView(body) || body instanceof ArrayBuffer)
|
|
95
|
-
return body;
|
|
96
|
-
}
|
|
97
|
-
throw new TypeError(`Invalid ${typeof body} body for ${encoding} encoding`);
|
|
98
|
-
}
|
|
99
|
-
async function xrpcResponseHandler(response, schema, options) {
|
|
100
|
-
// @NOTE The body MUST either be read or canceled to avoid resource leaks.
|
|
101
|
-
// Since nothing should cause an exception before "readXrpcResponseBody" is
|
|
102
|
-
// called, we can safely not use a try/finally here.
|
|
103
|
-
const encoding = extractEncoding(response.headers);
|
|
104
|
-
const body = await readResponseBody(response, encoding).catch((cause) => {
|
|
105
|
-
throw new error_js_1.XrpcServiceError(error_js_1.KnownError.InvalidResponse, response.status, response.headers, undefined, 'Failed to read XRPC response', { cause });
|
|
106
|
-
});
|
|
107
|
-
// @NOTE redirect is set to 'follow', so we shouldn't get 3xx responses here
|
|
108
|
-
if (response.status < 200 || response.status >= 300) {
|
|
109
|
-
// All unsuccessful responses should follow a standard error response
|
|
110
|
-
// schema. The Content-Type should be application/json, and the payload
|
|
111
|
-
// should be a JSON object with the following fields:
|
|
112
|
-
// - error (string, required): type name of the error (generic ASCII
|
|
113
|
-
// constant, no whitespace)
|
|
114
|
-
// - message (string, optional): description of the error, appropriate for
|
|
115
|
-
// display to humans
|
|
116
|
-
if (body != null &&
|
|
117
|
-
encoding === 'application/json' &&
|
|
118
|
-
error_js_1.xrpcErrorBodySchema.matches(body)) {
|
|
119
|
-
throw new error_js_1.XrpcResponseError(response.status, response.headers, encoding, body);
|
|
104
|
+
// Special handling for endpoints expecting application/json input
|
|
105
|
+
if (input.encoding === 'application/json') {
|
|
106
|
+
// @NOTE **NOT** using isLexValue here to avoid deep checks in order to
|
|
107
|
+
// distinguish between LexValue and BinaryBodyInit.
|
|
108
|
+
if (!(0, lex_data_1.isLexScalar)(body) && !(0, lex_data_1.isPlainObject)(body) && !Array.isArray(body)) {
|
|
109
|
+
throw new TypeError(`Expected LexValue body, got ${typeof body}`);
|
|
120
110
|
}
|
|
121
|
-
|
|
122
|
-
? error_js_1.KnownError.InternalServerError
|
|
123
|
-
: error_js_1.KnownError.InvalidResponse, response.status, response.headers, body);
|
|
111
|
+
return buildPayload(input, (0, lex_json_1.lexStringify)(body), encodingHint);
|
|
124
112
|
}
|
|
125
|
-
//
|
|
126
|
-
|
|
127
|
-
|
|
113
|
+
// Other encodings will be sent unaltered (ie. as binary data)
|
|
114
|
+
switch (typeof body) {
|
|
115
|
+
case 'undefined':
|
|
116
|
+
case 'string':
|
|
117
|
+
return buildPayload(input, body, encodingHint);
|
|
118
|
+
case 'object': {
|
|
119
|
+
if (body === null)
|
|
120
|
+
break;
|
|
121
|
+
if (ArrayBuffer.isView(body) ||
|
|
122
|
+
body instanceof ArrayBuffer ||
|
|
123
|
+
body instanceof ReadableStream) {
|
|
124
|
+
return buildPayload(input, body, encodingHint);
|
|
125
|
+
}
|
|
126
|
+
else if ((0, util_js_1.isAsyncIterable)(body)) {
|
|
127
|
+
return buildPayload(input, (0, util_js_1.toReadableStream)(body), encodingHint);
|
|
128
|
+
}
|
|
129
|
+
else if ((0, util_js_1.isBlobLike)(body)) {
|
|
130
|
+
return buildPayload(input, body, encodingHint || body.type);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
128
133
|
}
|
|
129
|
-
|
|
134
|
+
throw new TypeError(`Invalid ${typeof body} body for ${input.encoding} encoding`);
|
|
135
|
+
}
|
|
136
|
+
function buildPayload(schema, body, encodingHint) {
|
|
137
|
+
if (schema.encoding === undefined) {
|
|
130
138
|
if (body !== undefined) {
|
|
131
|
-
throw new
|
|
139
|
+
throw new TypeError(`Cannot send a ${typeof body} body with undefined encoding`);
|
|
132
140
|
}
|
|
133
|
-
return
|
|
141
|
+
return null;
|
|
134
142
|
}
|
|
135
|
-
|
|
136
|
-
//
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
return new response_js_1.XrpcResponse(schema, response.status, response.headers, schema.output.schema == null || options?.validateResponse === false
|
|
141
|
-
? body
|
|
142
|
-
: schema.output.schema.parse(body));
|
|
143
|
+
if (body === undefined) {
|
|
144
|
+
// This error would be returned by the server, but we can catch it earlier
|
|
145
|
+
// to avoid un-necessary requests. Note that a content-length of 0 does not
|
|
146
|
+
// necessary mean that the body is "empty" (e.g. an empty txt file).
|
|
147
|
+
throw new TypeError(`A request body is expected but none was provided`);
|
|
143
148
|
}
|
|
149
|
+
const encoding = buildEncoding(schema, encodingHint);
|
|
150
|
+
return { encoding, body };
|
|
144
151
|
}
|
|
145
|
-
function
|
|
146
|
-
|
|
147
|
-
if (!
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
if (encoding == null) {
|
|
154
|
-
if (response.body == null)
|
|
155
|
-
return undefined;
|
|
156
|
-
// Let's make sure the body is empty (while avoiding reading it all).
|
|
157
|
-
if (!('getReader' in response.body)) {
|
|
158
|
-
// Some environments may not support body.getReader(), fall back to
|
|
159
|
-
// reading the whole body.
|
|
160
|
-
const buffer = await response.arrayBuffer();
|
|
161
|
-
if (buffer.byteLength === 0)
|
|
162
|
-
return undefined;
|
|
163
|
-
}
|
|
164
|
-
else {
|
|
165
|
-
const reader = response.body.getReader();
|
|
166
|
-
const next = await reader.read();
|
|
167
|
-
if (next.done)
|
|
168
|
-
return undefined;
|
|
169
|
-
await reader.cancel(); // Drain the rest of the (non-empty) body stream
|
|
152
|
+
function buildEncoding(schema, encodingHint) {
|
|
153
|
+
// Should never happen (required for type safety)
|
|
154
|
+
if (!schema.encoding) {
|
|
155
|
+
throw new TypeError('Unexpected payload');
|
|
156
|
+
}
|
|
157
|
+
if (encodingHint?.length) {
|
|
158
|
+
if (!schema.matchesEncoding(encodingHint)) {
|
|
159
|
+
throw new TypeError(`Cannot send a body with content-type "${encodingHint}" for "${schema.encoding}" encoding`);
|
|
170
160
|
}
|
|
171
|
-
|
|
161
|
+
return encodingHint;
|
|
162
|
+
}
|
|
163
|
+
// Fallback
|
|
164
|
+
if (schema.encoding === '*/*') {
|
|
165
|
+
return 'application/octet-stream';
|
|
172
166
|
}
|
|
173
|
-
if (encoding
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
// @TODO verify statement above
|
|
178
|
-
return (0, lex_json_1.lexParse)(await response.text());
|
|
167
|
+
if (schema.encoding.startsWith('text/')) {
|
|
168
|
+
return schema.encoding.includes('*')
|
|
169
|
+
? 'text/plain; charset=utf-8'
|
|
170
|
+
: `${schema.encoding}; charset=utf-8`;
|
|
179
171
|
}
|
|
180
|
-
if (encoding.
|
|
181
|
-
return
|
|
172
|
+
if (!schema.encoding.includes('*')) {
|
|
173
|
+
return schema.encoding;
|
|
182
174
|
}
|
|
183
|
-
|
|
175
|
+
throw new TypeError(`Unable to determine payload encoding. Please provide a 'content-type' header matching ${schema.encoding}.`);
|
|
184
176
|
}
|
|
185
177
|
//# sourceMappingURL=xrpc.js.map
|
package/dist/xrpc.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"xrpc.js","sourceRoot":"","sources":["../src/xrpc.ts"],"names":[],"mappings":"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","sourcesContent":["import { LexValue } from '@atproto/lex-data'\nimport { lexParse, lexStringify } from '@atproto/lex-json'\nimport {\n DidString,\n InferParamsSchema,\n InferPayloadBody,\n Params,\n ParamsSchema,\n Procedure,\n Query,\n Restricted,\n Subscription,\n} from '@atproto/lex-schema'\nimport { Agent } from './agent.js'\nimport {\n KnownError,\n XrpcResponseError,\n XrpcServiceError,\n xrpcErrorBodySchema,\n} from './error.js'\nimport { XrpcResponse, XrpcResponseBody } from './response.js'\nimport { CallOptions, Namespace, Service, getMain } from './types.js'\n\nexport type XrpcOptions<M extends Procedure | Query = Procedure | Query> =\n CallOptions & XrpcRequestUrlOptions<M> & XrpcRequestInitOptions<M>\n\nexport async function xrpc<const M extends Query | Procedure>(\n agent: Agent,\n ns: NonNullable<unknown> extends XrpcOptions<M>\n ? Namespace<M>\n : Restricted<'This XRPC method requires an \"options\" argument'>,\n): Promise<XrpcResponse<M>>\nexport async function xrpc<const M extends Query | Procedure>(\n agent: Agent,\n ns: Namespace<M>,\n options: XrpcOptions<M>,\n): Promise<XrpcResponse<M>>\nexport async function xrpc<const M extends Query | Procedure>(\n agent: Agent,\n ns: Namespace<M>,\n options: XrpcOptions<M> = {} as XrpcOptions<M>,\n): Promise<XrpcResponse<M>> {\n options.signal?.throwIfAborted()\n const method = getMain(ns)\n const url = xrpcRequestUrl(method, options)\n const request = xrpcRequestInit(method, options)\n const response = await agent.fetchHandler(url, request)\n return xrpcResponseHandler<M>(response, method, options)\n}\n\nexport type XrpcRequestUrlOptions<M extends Query | Procedure | Subscription> =\n CallOptions &\n (undefined extends InferParamsSchema<M['parameters']>\n ? { params?: InferParamsSchema<M['parameters']> }\n : { params: InferParamsSchema<M['parameters']> })\n\nexport function xrpcRequestUrl<M extends Procedure | Query | Subscription>(\n method: M,\n options: XrpcRequestUrlOptions<M>,\n) {\n const path = `/xrpc/${method.nsid}`\n\n const queryString = options.params\n ? xrpcRequestParams(method.parameters, options.params, options)\n : undefined\n\n return queryString ? `${path}?${queryString}` : path\n}\n\nexport function xrpcRequestParams(\n schema: ParamsSchema | undefined,\n params: Params | undefined,\n options: CallOptions,\n): undefined | string {\n const urlSearchParams = schema?.toURLSearchParams(\n options.validateRequest ? schema.parse(params) : (params as any),\n )\n return urlSearchParams?.size ? urlSearchParams.toString() : undefined\n}\n\nexport type XrpcRequestInitOptions<T extends Query | Procedure> = CallOptions &\n (T extends Procedure\n ? never extends InferPayloadBody<T['input']>\n ? { body?: InferPayloadBody<T['input']> }\n : { body: InferPayloadBody<T['input']> }\n : { body?: never })\n\nexport function xrpcRequestInit<T extends Procedure | Query>(\n schema: T,\n options: XrpcRequestInitOptions<T>,\n): RequestInit & { duplex?: 'half' } {\n const headers = xrpcRequestHeaders(options)\n\n // Requests with body\n if ('input' in schema && schema.input?.encoding) {\n if (\n options.validateRequest &&\n schema.input == null &&\n options.body !== undefined\n ) {\n throw new TypeError(\n `XRPC method ${schema.nsid} does not accept a request body`,\n )\n }\n\n headers.set('content-type', schema.input.encoding)\n return {\n duplex: 'half',\n redirect: 'follow',\n referrerPolicy: 'strict-origin-when-cross-origin', // (default)\n mode: 'cors', // (default)\n signal: options.signal,\n method: 'POST',\n headers,\n body: xrpcRequestBody(\n schema.input?.encoding,\n options.validateRequest\n ? schema.input?.body.parse(options.body)\n : options.body,\n ),\n }\n }\n\n // Requests without body\n return {\n duplex: 'half',\n redirect: 'follow',\n referrerPolicy: 'strict-origin-when-cross-origin', // (default)\n mode: 'cors', // (default)\n signal: options.signal,\n method: schema instanceof Query ? 'GET' : 'POST',\n headers,\n }\n}\n\nexport function xrpcRequestHeaders(options: {\n headers?: HeadersInit\n service?: Service\n labelers?: Iterable<DidString>\n}): Headers {\n const headers = new Headers(options.headers)\n\n if (options.service && !headers.has('atproto-proxy')) {\n headers.set('atproto-proxy', options.service)\n }\n\n if (options.labelers) {\n headers.set(\n 'atproto-accept-labelers',\n [...options.labelers, headers.get('atproto-accept-labelers')?.trim()]\n .filter(Boolean)\n .join(', '),\n )\n }\n\n return headers\n}\n\nfunction xrpcRequestBody(\n encoding: string | undefined,\n body: LexValue | undefined,\n): BodyInit | null {\n if (encoding === undefined) {\n return null\n }\n\n if (encoding === 'application/json') {\n if (body !== undefined) return lexStringify(body)\n } else if (encoding.startsWith('text/')) {\n if (typeof body === 'string') return body\n } else {\n if (ArrayBuffer.isView(body) || body instanceof ArrayBuffer) return body\n }\n\n throw new TypeError(`Invalid ${typeof body} body for ${encoding} encoding`)\n}\n\nexport async function xrpcResponseHandler<M extends Procedure | Query>(\n response: Response,\n schema: M,\n options?: { validateResponse?: boolean },\n): Promise<XrpcResponse<M>> {\n // @NOTE The body MUST either be read or canceled to avoid resource leaks.\n // Since nothing should cause an exception before \"readXrpcResponseBody\" is\n // called, we can safely not use a try/finally here.\n\n const encoding = extractEncoding(response.headers)\n\n const body = await readResponseBody(response, encoding).catch((cause) => {\n throw new XrpcServiceError(\n KnownError.InvalidResponse,\n response.status,\n response.headers,\n undefined,\n 'Failed to read XRPC response',\n { cause },\n )\n })\n\n // @NOTE redirect is set to 'follow', so we shouldn't get 3xx responses here\n if (response.status < 200 || response.status >= 300) {\n // All unsuccessful responses should follow a standard error response\n // schema. The Content-Type should be application/json, and the payload\n // should be a JSON object with the following fields:\n // - error (string, required): type name of the error (generic ASCII\n // constant, no whitespace)\n // - message (string, optional): description of the error, appropriate for\n // display to humans\n if (\n body != null &&\n encoding === 'application/json' &&\n xrpcErrorBodySchema.matches(body)\n ) {\n throw new XrpcResponseError(\n response.status,\n response.headers,\n encoding,\n body,\n )\n }\n\n throw new XrpcServiceError(\n response.status >= 500\n ? KnownError.InternalServerError\n : KnownError.InvalidResponse,\n response.status,\n response.headers,\n body,\n )\n }\n\n // Check response encoding\n if (schema.output.encoding !== encoding) {\n throw new XrpcServiceError(\n KnownError.InvalidResponse,\n response.status,\n response.headers,\n body,\n `Expected response with content-type ${schema.output.encoding}, got ${encoding}`,\n )\n }\n\n if (schema.output.encoding == null) {\n if (body !== undefined) {\n throw new XrpcServiceError(\n KnownError.InvalidResponse,\n response.status,\n response.headers,\n body,\n `Expected empty response body`,\n )\n }\n\n return new XrpcResponse<M>(\n schema,\n response.status,\n response.headers,\n undefined as XrpcResponseBody<M>,\n )\n } else {\n // @NOTE this should already be enforced by readXrpcResponseBody\n if (body === undefined) {\n throw new XrpcServiceError(\n KnownError.InvalidResponse,\n response.status,\n response.headers,\n body,\n `Expected non-empty response body`,\n )\n }\n\n return new XrpcResponse<M>(\n schema,\n response.status,\n response.headers,\n schema.output.schema == null || options?.validateResponse === false\n ? (body as XrpcResponseBody<M>)\n : (schema.output.schema.parse(body) as XrpcResponseBody<M>),\n )\n }\n}\n\nexport function extractEncoding(headers: Headers): string | undefined {\n const contentType = headers.get('content-type')\n if (!contentType) return undefined\n return contentType.split(';')[0].trim()\n}\n\nexport async function readResponseBody(\n response: Response,\n encoding: string,\n): Promise<LexValue>\nexport async function readResponseBody(\n response: Response,\n encoding: string | undefined,\n): Promise<LexValue | undefined>\nexport async function readResponseBody(\n response: Response,\n encoding: string | undefined,\n): Promise<LexValue | undefined> {\n // When encoding is undefined or empty, we expect no body\n if (encoding == null) {\n if (response.body == null) return undefined\n\n // Let's make sure the body is empty (while avoiding reading it all).\n if (!('getReader' in response.body)) {\n // Some environments may not support body.getReader(), fall back to\n // reading the whole body.\n const buffer = await response.arrayBuffer()\n if (buffer.byteLength === 0) return undefined\n } else {\n const reader = response.body.getReader()\n const next = await reader.read()\n if (next.done) return undefined\n await reader.cancel() // Drain the rest of the (non-empty) body stream\n }\n\n throw new SyntaxError('Content-type is undefined but body is not empty')\n }\n\n if (encoding === 'application/json') {\n // @NOTE Using `lexParse(text)` (instead of `jsonToLex(json)`) here as using\n // a reviver function during JSON.parse should be faster than parsing to\n // JSON then converting to Lex (?)\n\n // @TODO verify statement above\n return lexParse(await response.text())\n }\n\n if (encoding.startsWith('text/')) {\n return response.text()\n }\n\n return new Uint8Array(await response.arrayBuffer())\n}\n"]}
|
|
1
|
+
{"version":3,"file":"xrpc.js","sourceRoot":"","sources":["../src/xrpc.ts"],"names":[],"mappings":"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","sourcesContent":["import { LexValue, isLexScalar, isPlainObject } from '@atproto/lex-data'\nimport { lexStringify } from '@atproto/lex-json'\nimport {\n InferMethodInput,\n InferMethodParams,\n Main,\n Params,\n ParamsSchema,\n Payload as LexPayload,\n Procedure,\n Query,\n Restricted,\n Subscription,\n getMain,\n} from '@atproto/lex-schema'\nimport { Agent } from './agent.js'\nimport {\n LexRpcResponseError,\n LexRpcUnexpectedError,\n LexRpcUpstreamError,\n} from './errors.js'\nimport { LexRpcResponse } from './response.js'\nimport { BinaryBodyInit, CallOptions } from './types.js'\nimport {\n Payload,\n buildAtprotoHeaders,\n isAsyncIterable,\n isBlobLike,\n toReadableStream,\n} from './util.js'\n\n// If all params are optional, allow omitting the params object\ntype LexRpcParamsOptions<P extends Params> =\n NonNullable<unknown> extends P ? { params?: P } : { params: P }\n\ntype LexRpcRequestPayload<M extends Procedure | Query> = InferMethodInput<\n M,\n BinaryBodyInit\n>\n\ntype LexRpcInputOptions<In> = In extends { body: infer B; encoding: infer E }\n ? // encoding will be inferred from the schema at runtime if not provided\n { body: B; encoding?: E }\n : { body?: undefined; encoding?: undefined }\n\nexport type LexRpcOptions<M extends Procedure | Query = Procedure | Query> =\n CallOptions &\n LexRpcInputOptions<LexRpcRequestPayload<M>> &\n LexRpcParamsOptions<InferMethodParams<M>>\n\nexport type LexRpcFailure<M extends Procedure | Query> =\n // The server returned a valid XRPC error response\n | LexRpcResponseError<M>\n // The response was not a valid XRPC response, or it does not match the schema\n | LexRpcUpstreamError\n // Something went wrong (network error, etc.)\n | LexRpcUnexpectedError\n\nexport type LexRpcResult<M extends Procedure | Query> =\n | LexRpcResponse<M>\n | LexRpcFailure<M>\n\n/**\n * Utility method to type cast the error thrown by {@link xrpc} to an\n * {@link LexRpcFailure} matching the provided method. Only use this function\n * inside a catch block right after calling {@link xrpc}, and use the same\n * method type parameter as used in the {@link xrpc} call.\n */\nexport function asLexRpcFailure<\n M extends Procedure | Query = Procedure | Query,\n>(err: unknown): LexRpcFailure<M> {\n if (err instanceof LexRpcResponseError) return err\n if (err instanceof LexRpcUpstreamError) return err\n return LexRpcUnexpectedError.from(err)\n}\n\n/**\n * @throws LexRpcFailure<M>\n */\nexport async function xrpc<const M extends Query | Procedure>(\n agent: Agent,\n ns: NonNullable<unknown> extends LexRpcOptions<M>\n ? Main<M>\n : Restricted<'This XRPC method requires an \"options\" argument'>,\n): Promise<LexRpcResponse<M>>\nexport async function xrpc<const M extends Query | Procedure>(\n agent: Agent,\n ns: Main<M>,\n options: LexRpcOptions<M>,\n): Promise<LexRpcResponse<M>>\nexport async function xrpc<const M extends Query | Procedure>(\n agent: Agent,\n ns: Main<M>,\n options: LexRpcOptions<M> = {} as LexRpcOptions<M>,\n): Promise<LexRpcResponse<M>> {\n try {\n return await lexRpcRequest<M>(agent, ns, options)\n } catch (err) {\n throw asLexRpcFailure<M>(err)\n }\n}\n\nexport async function xrpcSafe<const M extends Query | Procedure>(\n agent: Agent,\n ns: NonNullable<unknown> extends LexRpcOptions<M>\n ? Main<M>\n : Restricted<'This XRPC method requires an \"options\" argument'>,\n): Promise<LexRpcResult<M>>\nexport async function xrpcSafe<const M extends Query | Procedure>(\n agent: Agent,\n ns: Main<M>,\n options: LexRpcOptions<M>,\n): Promise<LexRpcResult<M>>\nexport async function xrpcSafe<const M extends Query | Procedure>(\n agent: Agent,\n ns: Main<M>,\n options: LexRpcOptions<M> = {} as LexRpcOptions<M>,\n): Promise<LexRpcResult<M>> {\n return lexRpcRequest<M>(agent, ns, options).catch(asLexRpcFailure<M>)\n}\n\nasync function lexRpcRequest<const M extends Query | Procedure>(\n agent: Agent,\n ns: Main<M>,\n options: LexRpcOptions<M> = {} as LexRpcOptions<M>,\n): Promise<LexRpcResponse<M>> {\n const method = getMain(ns)\n options.signal?.throwIfAborted()\n const url = xrpcRequestUrl(method, options)\n const request = xrpcRequestInit(method, options)\n const response = await agent.fetchHandler(url, request)\n return LexRpcResponse.fromFetchResponse<M>(method, response, options)\n}\n\nfunction xrpcRequestUrl<M extends Procedure | Query | Subscription>(\n method: M,\n options: CallOptions & { params?: Params },\n) {\n const path = `/xrpc/${method.nsid}`\n\n const queryString = options.params\n ? xrpcRequestParams(method.parameters, options.params, options)\n : undefined\n\n return queryString ? `${path}?${queryString}` : path\n}\n\nfunction xrpcRequestParams(\n schema: ParamsSchema | undefined,\n params: Params | undefined,\n options: CallOptions,\n): undefined | string {\n const urlSearchParams = schema?.toURLSearchParams(\n options.validateRequest ? schema.parse(params) : (params as any),\n )\n return urlSearchParams?.size ? urlSearchParams.toString() : undefined\n}\n\nfunction xrpcRequestInit<T extends Procedure | Query>(\n schema: T,\n options: CallOptions & {\n body?: LexValue | BinaryBodyInit\n encoding?: string\n },\n): RequestInit & { duplex?: 'half' } {\n const headers = buildAtprotoHeaders(options)\n\n // Tell the server what type of response we're expecting\n if (schema.output.encoding) {\n headers.set('accept', schema.output.encoding)\n }\n\n // Caller should not set content-type header\n if (headers.has('content-type')) {\n const contentType = headers.get('content-type')\n throw new TypeError(`Unexpected content-type header (${contentType})`)\n }\n\n // Requests with body\n if ('input' in schema) {\n const encodingHint = options.encoding\n const input = xrpcProcedureInput(schema, options, encodingHint)\n\n if (input) {\n headers.set('content-type', input.encoding)\n } else if (encodingHint != null) {\n throw new TypeError(`Unexpected encoding hint (${encodingHint})`)\n }\n\n return {\n duplex: 'half',\n redirect: 'follow',\n referrerPolicy: 'strict-origin-when-cross-origin', // (default)\n mode: 'cors', // (default)\n signal: options.signal,\n method: 'POST',\n headers,\n body: input?.body,\n }\n }\n\n // Requests without body\n return {\n duplex: 'half',\n redirect: 'follow',\n referrerPolicy: 'strict-origin-when-cross-origin', // (default)\n mode: 'cors', // (default)\n signal: options.signal,\n method: 'GET',\n headers,\n }\n}\n\nfunction xrpcProcedureInput(\n method: Procedure,\n options: CallOptions & { body?: LexValue | BinaryBodyInit },\n encodingHint?: string,\n): null | Payload<BodyInit> {\n const { input } = method\n const { body } = options\n\n if (options.validateRequest) {\n input.schema?.check(body)\n }\n\n // Special handling for endpoints expecting application/json input\n if (input.encoding === 'application/json') {\n // @NOTE **NOT** using isLexValue here to avoid deep checks in order to\n // distinguish between LexValue and BinaryBodyInit.\n if (!isLexScalar(body) && !isPlainObject(body) && !Array.isArray(body)) {\n throw new TypeError(`Expected LexValue body, got ${typeof body}`)\n }\n\n return buildPayload(input, lexStringify(body), encodingHint)\n }\n\n // Other encodings will be sent unaltered (ie. as binary data)\n switch (typeof body) {\n case 'undefined':\n case 'string':\n return buildPayload(input, body, encodingHint)\n case 'object': {\n if (body === null) break\n if (\n ArrayBuffer.isView(body) ||\n body instanceof ArrayBuffer ||\n body instanceof ReadableStream\n ) {\n return buildPayload(input, body, encodingHint)\n } else if (isAsyncIterable(body)) {\n return buildPayload(input, toReadableStream(body), encodingHint)\n } else if (isBlobLike(body)) {\n return buildPayload(input, body, encodingHint || body.type)\n }\n }\n }\n\n throw new TypeError(\n `Invalid ${typeof body} body for ${input.encoding} encoding`,\n )\n}\n\nfunction buildPayload(\n schema: LexPayload,\n body: undefined | BodyInit,\n encodingHint?: string,\n): null | Payload<BodyInit> {\n if (schema.encoding === undefined) {\n if (body !== undefined) {\n throw new TypeError(\n `Cannot send a ${typeof body} body with undefined encoding`,\n )\n }\n\n return null\n }\n\n if (body === undefined) {\n // This error would be returned by the server, but we can catch it earlier\n // to avoid un-necessary requests. Note that a content-length of 0 does not\n // necessary mean that the body is \"empty\" (e.g. an empty txt file).\n throw new TypeError(`A request body is expected but none was provided`)\n }\n\n const encoding = buildEncoding(schema, encodingHint)\n return { encoding, body }\n}\n\nfunction buildEncoding(schema: LexPayload, encodingHint?: string): string {\n // Should never happen (required for type safety)\n if (!schema.encoding) {\n throw new TypeError('Unexpected payload')\n }\n\n if (encodingHint?.length) {\n if (!schema.matchesEncoding(encodingHint)) {\n throw new TypeError(\n `Cannot send a body with content-type \"${encodingHint}\" for \"${schema.encoding}\" encoding`,\n )\n }\n return encodingHint\n }\n\n // Fallback\n\n if (schema.encoding === '*/*') {\n return 'application/octet-stream'\n }\n\n if (schema.encoding.startsWith('text/')) {\n return schema.encoding.includes('*')\n ? 'text/plain; charset=utf-8'\n : `${schema.encoding}; charset=utf-8`\n }\n\n if (!schema.encoding.includes('*')) {\n return schema.encoding\n }\n\n throw new TypeError(\n `Unable to determine payload encoding. Please provide a 'content-type' header matching ${schema.encoding}.`,\n )\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atproto/lex-client",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "HTTP client for interacting with Lexicon based APIs",
|
|
6
6
|
"keywords": [
|
|
@@ -29,26 +29,26 @@
|
|
|
29
29
|
"types": "./dist/index.d.ts",
|
|
30
30
|
"exports": {
|
|
31
31
|
".": {
|
|
32
|
+
"types": "./dist/index.d.ts",
|
|
32
33
|
"browser": "./dist/index.js",
|
|
33
34
|
"import": "./dist/index.js",
|
|
34
|
-
"require": "./dist/index.js"
|
|
35
|
-
"types": "./dist/index.d.ts"
|
|
35
|
+
"require": "./dist/index.js"
|
|
36
36
|
}
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"tslib": "^2.8.1",
|
|
40
|
-
"@atproto/lex-data": "0.0.
|
|
41
|
-
"@atproto/lex-json": "0.0.
|
|
42
|
-
"@atproto/lex-schema": "0.0.
|
|
40
|
+
"@atproto/lex-data": "0.0.5",
|
|
41
|
+
"@atproto/lex-json": "0.0.5",
|
|
42
|
+
"@atproto/lex-schema": "0.0.6"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
|
-
"
|
|
46
|
-
"@atproto/lex-cbor": "0.0.
|
|
47
|
-
"@atproto/lex-builder": "0.0.
|
|
45
|
+
"vitest": "^4.0.16",
|
|
46
|
+
"@atproto/lex-cbor": "0.0.5",
|
|
47
|
+
"@atproto/lex-builder": "0.0.8"
|
|
48
48
|
},
|
|
49
49
|
"scripts": {
|
|
50
50
|
"prebuild": "node ./scripts/lex-build.mjs",
|
|
51
51
|
"build": "tsc --build tsconfig.build.json",
|
|
52
|
-
"test": "
|
|
52
|
+
"test": "vitest run"
|
|
53
53
|
}
|
|
54
54
|
}
|
package/src/agent.ts
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { DidString } from '@atproto/lex-schema'
|
|
2
2
|
|
|
3
|
-
export
|
|
4
|
-
|
|
3
|
+
export type FetchHandler = (
|
|
4
|
+
/**
|
|
5
|
+
* The URL (pathname + query parameters) to make the request to, without the
|
|
6
|
+
* origin. The origin (protocol, hostname, and port) must be added by this
|
|
7
|
+
* {@link FetchHandler}, typically based on authentication or other factors.
|
|
8
|
+
*/
|
|
9
|
+
path: string,
|
|
10
|
+
init: RequestInit,
|
|
11
|
+
) => Promise<Response>
|
|
5
12
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
* The URL (pathname + query parameters) to make the request to, without the
|
|
10
|
-
* origin. The origin (protocol, hostname, and port) must be added by this
|
|
11
|
-
* {@link FetchHandler}, typically based on authentication or other factors.
|
|
12
|
-
*/
|
|
13
|
-
path: string,
|
|
14
|
-
init: RequestInit,
|
|
15
|
-
) => Promise<Response>
|
|
13
|
+
export interface Agent {
|
|
14
|
+
readonly did?: DidString
|
|
15
|
+
fetchHandler: FetchHandler
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
export type AgentConfig = {
|
|
@@ -39,8 +39,12 @@ export type AgentConfig = {
|
|
|
39
39
|
|
|
40
40
|
export type AgentOptions = AgentConfig | string | URL
|
|
41
41
|
|
|
42
|
-
export function buildAgent(options: AgentOptions): Agent {
|
|
43
|
-
|
|
42
|
+
export function buildAgent(options: Agent | AgentOptions): Agent {
|
|
43
|
+
if (typeof options === 'object' && 'fetchHandler' in options) {
|
|
44
|
+
return options
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const config: Agent | AgentConfig =
|
|
44
48
|
typeof options === 'string' || options instanceof URL
|
|
45
49
|
? { did: undefined, service: options }
|
|
46
50
|
: options
|