@atproto-labs/fetch 0.2.3 → 0.3.0-next.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/CHANGELOG.md +19 -0
- package/LICENSE.txt +1 -1
- package/dist/fetch-error.js +2 -11
- package/dist/fetch-error.js.map +1 -1
- package/dist/fetch-request.js +21 -34
- package/dist/fetch-request.js.map +1 -1
- package/dist/fetch-response.js +29 -52
- package/dist/fetch-response.js.map +1 -1
- package/dist/fetch-wrap.js +16 -22
- package/dist/fetch-wrap.js.map +1 -1
- package/dist/fetch.js +2 -6
- package/dist/fetch.js.map +1 -1
- package/dist/index.js +6 -22
- package/dist/index.js.map +1 -1
- package/dist/transformed-response.js +7 -24
- package/dist/transformed-response.js.map +1 -1
- package/dist/util.js +8 -19
- package/dist/util.js.map +1 -1
- package/package.json +7 -6
- package/tsconfig.build.tsbuildinfo +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @atproto-labs/fetch
|
|
2
2
|
|
|
3
|
+
## 0.3.0-next.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#4929](https://github.com/bluesky-social/atproto/pull/4929) [`bb7491c`](https://github.com/bluesky-social/atproto/commit/bb7491c29e06181e1d2f8cf6eb454f9bb8ab961b) Thanks [@devinivy](https://github.com/devinivy)! - **BREAKING:** Drop support for Node.js 18 and 20. Node.js 22 is now the minimum supported version. Docker images now use Node.js 24.
|
|
8
|
+
|
|
9
|
+
- [#4943](https://github.com/bluesky-social/atproto/pull/4943) [`07ae5d4`](https://github.com/bluesky-social/atproto/commit/07ae5d4452df51e045e0239da7a04cf0bc154028) Thanks [@devinivy](https://github.com/devinivy)! - **BREAKING:** Convert to pure ESM. All packages now ship `"type": "module"` with ES module output and Node16 module resolution.
|
|
10
|
+
|
|
11
|
+
Node.js 22's `require()` compatibility layer can still load these packages in CommonJS code.
|
|
12
|
+
|
|
13
|
+
- [#4930](https://github.com/bluesky-social/atproto/pull/4930) [`042df15`](https://github.com/bluesky-social/atproto/commit/042df15087c0e62cd1e715fcbf58852fab875af9) Thanks [@devinivy](https://github.com/devinivy)! - Build with TypeScript 6.0. Emitted `.d.ts` files now use TypeScript 6's stricter `Uint8Array<ArrayBuffer>` typing in places where Web/Node APIs require buffer-backed (not shared-memory) byte arrays. Consumers compiling against these types on older TypeScript should see no runtime impact, but may need to widen or cast in spots that previously relied on `Uint8Array` defaulting to `<ArrayBufferLike>`.
|
|
14
|
+
|
|
15
|
+
Internal: tsconfig `moduleResolution: "node"` is silenced via `ignoreDeprecations: "6.0"` for now; the proper migration to `node16`/`bundler` resolution is deferred.
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- Updated dependencies [[`bb7491c`](https://github.com/bluesky-social/atproto/commit/bb7491c29e06181e1d2f8cf6eb454f9bb8ab961b), [`07ae5d4`](https://github.com/bluesky-social/atproto/commit/07ae5d4452df51e045e0239da7a04cf0bc154028), [`042df15`](https://github.com/bluesky-social/atproto/commit/042df15087c0e62cd1e715fcbf58852fab875af9)]:
|
|
20
|
+
- @atproto-labs/pipe@0.2.0-next.0
|
|
21
|
+
|
|
3
22
|
## 0.2.3
|
|
4
23
|
|
|
5
24
|
### Patch Changes
|
package/LICENSE.txt
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Dual MIT/Apache-2.0 License
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2022-
|
|
3
|
+
Copyright (c) 2022-2026 Bluesky Social PBC, and Contributors
|
|
4
4
|
|
|
5
5
|
Except as otherwise noted in individual files, this software is licensed under the MIT license (<http://opensource.org/licenses/MIT>), or the Apache License, Version 2.0 (<http://www.apache.org/licenses/LICENSE-2.0>).
|
|
6
6
|
|
package/dist/fetch-error.js
CHANGED
|
@@ -1,19 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.FetchError = void 0;
|
|
4
|
-
class FetchError extends Error {
|
|
1
|
+
export class FetchError extends Error {
|
|
5
2
|
constructor(statusCode, message, options) {
|
|
6
3
|
super(message, options);
|
|
7
|
-
|
|
8
|
-
enumerable: true,
|
|
9
|
-
configurable: true,
|
|
10
|
-
writable: true,
|
|
11
|
-
value: statusCode
|
|
12
|
-
});
|
|
4
|
+
this.statusCode = statusCode;
|
|
13
5
|
}
|
|
14
6
|
get expose() {
|
|
15
7
|
return true;
|
|
16
8
|
}
|
|
17
9
|
}
|
|
18
|
-
exports.FetchError = FetchError;
|
|
19
10
|
//# sourceMappingURL=fetch-error.js.map
|
package/dist/fetch-error.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch-error.js","sourceRoot":"","sources":["../src/fetch-error.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"fetch-error.js","sourceRoot":"","sources":["../src/fetch-error.ts"],"names":[],"mappings":"AAAA,MAAM,OAAgB,UAAW,SAAQ,KAAK;IAC5C,YACkB,UAAkB,EAClC,OAAgB,EAChB,OAAsB;QAEtB,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;QAJP,eAAU,GAAV,UAAU,CAAQ;IAKpC,CAAC;IAED,IAAI,MAAM;QACR,OAAO,IAAI,CAAA;IACb,CAAC;CACF","sourcesContent":["export abstract class FetchError extends Error {\n constructor(\n public readonly statusCode: number,\n message?: string,\n options?: ErrorOptions,\n ) {\n super(message, options)\n }\n\n get expose() {\n return true\n }\n}\n"]}
|
package/dist/fetch-request.js
CHANGED
|
@@ -1,27 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
exports.explicitRedirectCheckRequestTransform = explicitRedirectCheckRequestTransform;
|
|
6
|
-
exports.requireHostHeaderTransform = requireHostHeaderTransform;
|
|
7
|
-
exports.forbiddenDomainNameRequestTransform = forbiddenDomainNameRequestTransform;
|
|
8
|
-
const fetch_error_js_1 = require("./fetch-error.js");
|
|
9
|
-
const fetch_js_1 = require("./fetch.js");
|
|
10
|
-
const util_js_1 = require("./util.js");
|
|
11
|
-
class FetchRequestError extends fetch_error_js_1.FetchError {
|
|
1
|
+
import { FetchError } from './fetch-error.js';
|
|
2
|
+
import { asRequest } from './fetch.js';
|
|
3
|
+
import { extractUrl, isIp } from './util.js';
|
|
4
|
+
export class FetchRequestError extends FetchError {
|
|
12
5
|
constructor(request, statusCode, message, options) {
|
|
13
6
|
if (statusCode == null || !message) {
|
|
14
7
|
const info = extractInfo(extractRootCause(options?.cause));
|
|
15
|
-
statusCode
|
|
16
|
-
message
|
|
8
|
+
statusCode ??= info[0];
|
|
9
|
+
message ||= info[1];
|
|
17
10
|
}
|
|
18
11
|
super(statusCode, message, options);
|
|
19
|
-
|
|
20
|
-
enumerable: true,
|
|
21
|
-
configurable: true,
|
|
22
|
-
writable: true,
|
|
23
|
-
value: request
|
|
24
|
-
});
|
|
12
|
+
this.request = request;
|
|
25
13
|
}
|
|
26
14
|
get expose() {
|
|
27
15
|
// A 500 request error means that the request was not made due to an infra,
|
|
@@ -35,7 +23,6 @@ class FetchRequestError extends fetch_error_js_1.FetchError {
|
|
|
35
23
|
return new FetchRequestError(request, undefined, undefined, { cause });
|
|
36
24
|
}
|
|
37
25
|
}
|
|
38
|
-
exports.FetchRequestError = FetchRequestError;
|
|
39
26
|
function extractRootCause(err) {
|
|
40
27
|
// Unwrap the Network error from undici (i.e. Node's internal fetch() implementation)
|
|
41
28
|
// https://github.com/nodejs/undici/blob/3274c975947ce11a08508743df026f73598bfead/lib/web/fetch/index.js#L223-L228
|
|
@@ -86,10 +73,10 @@ function extractInfo(err) {
|
|
|
86
73
|
}
|
|
87
74
|
return [500, err.message];
|
|
88
75
|
}
|
|
89
|
-
function protocolCheckRequestTransform(protocols) {
|
|
76
|
+
export function protocolCheckRequestTransform(protocols) {
|
|
90
77
|
return (input, init) => {
|
|
91
|
-
const { protocol, port } =
|
|
92
|
-
const request =
|
|
78
|
+
const { protocol, port } = extractUrl(input);
|
|
79
|
+
const request = asRequest(input, init);
|
|
93
80
|
const config = Object.hasOwn(protocols, protocol) ? protocols[protocol] : undefined;
|
|
94
81
|
if (!config) {
|
|
95
82
|
throw new FetchRequestError(request, 400, `Forbidden protocol "${protocol}"`);
|
|
@@ -103,9 +90,9 @@ function protocolCheckRequestTransform(protocols) {
|
|
|
103
90
|
return request;
|
|
104
91
|
};
|
|
105
92
|
}
|
|
106
|
-
function explicitRedirectCheckRequestTransform() {
|
|
93
|
+
export function explicitRedirectCheckRequestTransform() {
|
|
107
94
|
return (input, init) => {
|
|
108
|
-
const request =
|
|
95
|
+
const request = asRequest(input, init);
|
|
109
96
|
// We want to avoid the case where the user of this code forgot to explicit
|
|
110
97
|
// a redirect strategy.
|
|
111
98
|
if (init?.redirect != null)
|
|
@@ -120,23 +107,23 @@ function explicitRedirectCheckRequestTransform() {
|
|
|
120
107
|
return request;
|
|
121
108
|
};
|
|
122
109
|
}
|
|
123
|
-
function requireHostHeaderTransform() {
|
|
110
|
+
export function requireHostHeaderTransform() {
|
|
124
111
|
return (input, init) => {
|
|
125
112
|
// Note that fetch() will automatically add the Host header from the URL and
|
|
126
113
|
// discard any Host header manually set in the request.
|
|
127
|
-
const { protocol, hostname } =
|
|
128
|
-
const request =
|
|
114
|
+
const { protocol, hostname } = extractUrl(input);
|
|
115
|
+
const request = asRequest(input, init);
|
|
129
116
|
// "Host" header only makes sense in the context of an HTTP request
|
|
130
117
|
if (protocol !== 'http:' && protocol !== 'https:') {
|
|
131
118
|
throw new FetchRequestError(request, 400, `"${protocol}" requests are not allowed`);
|
|
132
119
|
}
|
|
133
|
-
if (!hostname ||
|
|
120
|
+
if (!hostname || isIp(hostname)) {
|
|
134
121
|
throw new FetchRequestError(request, 400, 'Invalid hostname');
|
|
135
122
|
}
|
|
136
123
|
return request;
|
|
137
124
|
};
|
|
138
125
|
}
|
|
139
|
-
|
|
126
|
+
export const DEFAULT_FORBIDDEN_DOMAIN_NAMES = [
|
|
140
127
|
'example.com',
|
|
141
128
|
'*.example.com',
|
|
142
129
|
'example.org',
|
|
@@ -146,16 +133,16 @@ exports.DEFAULT_FORBIDDEN_DOMAIN_NAMES = [
|
|
|
146
133
|
'googleusercontent.com',
|
|
147
134
|
'*.googleusercontent.com',
|
|
148
135
|
];
|
|
149
|
-
function forbiddenDomainNameRequestTransform(denyList =
|
|
136
|
+
export function forbiddenDomainNameRequestTransform(denyList = DEFAULT_FORBIDDEN_DOMAIN_NAMES) {
|
|
150
137
|
const denySet = new Set(denyList);
|
|
151
138
|
// Optimization: if no forbidden domain names are provided, we can skip the
|
|
152
139
|
// check entirely.
|
|
153
140
|
if (denySet.size === 0) {
|
|
154
|
-
return
|
|
141
|
+
return asRequest;
|
|
155
142
|
}
|
|
156
143
|
return async (input, init) => {
|
|
157
|
-
const { hostname } =
|
|
158
|
-
const request =
|
|
144
|
+
const { hostname } = extractUrl(input);
|
|
145
|
+
const request = asRequest(input, init);
|
|
159
146
|
// Full domain name check
|
|
160
147
|
if (denySet.has(hostname)) {
|
|
161
148
|
throw new FetchRequestError(request, 403, 'Forbidden hostname');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch-request.js","sourceRoot":"","sources":["../src/fetch-request.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"fetch-request.js","sourceRoot":"","sources":["../src/fetch-request.ts"],"names":[],"mappings":"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","sourcesContent":["import { FetchError } from './fetch-error.js'\nimport { asRequest } from './fetch.js'\nimport { extractUrl, isIp } from './util.js'\n\nexport class FetchRequestError extends FetchError {\n constructor(\n public readonly request: Request,\n statusCode?: number,\n message?: string,\n options?: ErrorOptions,\n ) {\n if (statusCode == null || !message) {\n const info = extractInfo(extractRootCause(options?.cause))\n statusCode ??= info[0]\n message ||= info[1]\n }\n\n super(statusCode, message, options)\n }\n\n get expose() {\n // A 500 request error means that the request was not made due to an infra,\n // programming or server side issue. The message should no be exposed to\n // downstream clients.\n return this.statusCode !== 500\n }\n\n static from(request: Request, cause: unknown): FetchRequestError {\n if (cause instanceof FetchRequestError) return cause\n return new FetchRequestError(request, undefined, undefined, { cause })\n }\n}\n\nfunction extractRootCause(err: unknown): unknown {\n // Unwrap the Network error from undici (i.e. Node's internal fetch() implementation)\n // https://github.com/nodejs/undici/blob/3274c975947ce11a08508743df026f73598bfead/lib/web/fetch/index.js#L223-L228\n if (\n err instanceof TypeError &&\n err.message === 'fetch failed' &&\n err.cause !== undefined\n ) {\n return err.cause\n }\n\n return err\n}\n\nfunction extractInfo(err: unknown): [statusCode: number, message: string] {\n if (typeof err === 'string' && err.length > 0) {\n return [500, err]\n }\n\n if (!(err instanceof Error)) {\n return [500, 'Failed to fetch']\n }\n\n // Undici fetch() \"network\" errors\n switch (err.message) {\n case 'failed to fetch the data URL':\n return [400, err.message]\n case 'unexpected redirect':\n case 'cors failure':\n case 'blocked':\n case 'proxy authentication required':\n // These cases could be represented either as a 4xx user error (invalid\n // URL provided), or as a 5xx server error (server didn't behave as\n // expected).\n return [502, err.message]\n }\n\n // NodeJS errors\n const code = err['code']\n if (typeof code === 'string') {\n switch (true) {\n case code === 'ENOTFOUND':\n return [400, 'Invalid hostname']\n case code === 'ECONNREFUSED':\n return [502, 'Connection refused']\n case code === 'DEPTH_ZERO_SELF_SIGNED_CERT':\n return [502, 'Self-signed certificate']\n case code.startsWith('ERR_TLS'):\n return [502, 'TLS error']\n case code.startsWith('ECONN'):\n return [502, 'Connection error']\n default:\n return [500, `${code} error`]\n }\n }\n\n return [500, err.message]\n}\n\nexport function protocolCheckRequestTransform(protocols: {\n 'about:'?: boolean\n 'blob:'?: boolean\n 'data:'?: boolean\n 'file:'?: boolean\n 'http:'?: boolean | { allowCustomPort: boolean }\n 'https:'?: boolean | { allowCustomPort: boolean }\n}) {\n return (input: Request | string | URL, init?: RequestInit) => {\n const { protocol, port } = extractUrl(input)\n\n const request = asRequest(input, init)\n\n const config: undefined | boolean | { allowCustomPort?: boolean } =\n Object.hasOwn(protocols, protocol) ? protocols[protocol] : undefined\n\n if (!config) {\n throw new FetchRequestError(\n request,\n 400,\n `Forbidden protocol \"${protocol}\"`,\n )\n } else if (config === true) {\n // Safe to proceed\n } else if (!config['allowCustomPort'] && port !== '') {\n throw new FetchRequestError(\n request,\n 400,\n `Custom ${protocol} ports not allowed`,\n )\n }\n\n return request\n }\n}\n\nexport function explicitRedirectCheckRequestTransform() {\n return (input: Request | string | URL, init?: RequestInit): Request => {\n const request = asRequest(input, init)\n\n // We want to avoid the case where the user of this code forgot to explicit\n // a redirect strategy.\n if (init?.redirect != null) return request\n\n // Sadly, if the `input` is a request, and `init` was omitted, there is no\n // way to tell if the `redirect === 'follow'` value comes from the user, or\n // fetch's default. In order to prevent accidental omission, this case is\n // forbidden.\n if (request.redirect === 'follow') {\n throw new FetchRequestError(\n request,\n 500,\n 'Request redirect must be \"error\" or \"manual\"',\n )\n }\n\n return request\n }\n}\n\nexport function requireHostHeaderTransform() {\n return (input: Request | string | URL, init?: RequestInit) => {\n // Note that fetch() will automatically add the Host header from the URL and\n // discard any Host header manually set in the request.\n\n const { protocol, hostname } = extractUrl(input)\n\n const request = asRequest(input, init)\n\n // \"Host\" header only makes sense in the context of an HTTP request\n if (protocol !== 'http:' && protocol !== 'https:') {\n throw new FetchRequestError(\n request,\n 400,\n `\"${protocol}\" requests are not allowed`,\n )\n }\n\n if (!hostname || isIp(hostname)) {\n throw new FetchRequestError(request, 400, 'Invalid hostname')\n }\n\n return request\n }\n}\n\nexport const DEFAULT_FORBIDDEN_DOMAIN_NAMES = [\n 'example.com',\n '*.example.com',\n 'example.org',\n '*.example.org',\n 'example.net',\n '*.example.net',\n 'googleusercontent.com',\n '*.googleusercontent.com',\n]\n\nexport function forbiddenDomainNameRequestTransform(\n denyList: Iterable<string> = DEFAULT_FORBIDDEN_DOMAIN_NAMES,\n) {\n const denySet = new Set<string>(denyList)\n\n // Optimization: if no forbidden domain names are provided, we can skip the\n // check entirely.\n if (denySet.size === 0) {\n return asRequest\n }\n\n return async (input: Request | string | URL, init?: RequestInit) => {\n const { hostname } = extractUrl(input)\n\n const request = asRequest(input, init)\n\n // Full domain name check\n if (denySet.has(hostname)) {\n throw new FetchRequestError(request, 403, 'Forbidden hostname')\n }\n\n // Sub domain name check\n let curDot = hostname.indexOf('.')\n while (curDot !== -1) {\n const subdomain = hostname.slice(curDot + 1)\n if (denySet.has(`*.${subdomain}`)) {\n throw new FetchRequestError(request, 403, 'Forbidden hostname')\n }\n curDot = hostname.indexOf('.', curDot + 1)\n }\n\n return request\n }\n}\n"]}
|
package/dist/fetch-response.js
CHANGED
|
@@ -1,24 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
exports.checkLength = checkLength;
|
|
6
|
-
exports.extractLength = extractLength;
|
|
7
|
-
exports.extractMime = extractMime;
|
|
8
|
-
exports.cancelBodyOnError = cancelBodyOnError;
|
|
9
|
-
exports.fetchOkProcessor = fetchOkProcessor;
|
|
10
|
-
exports.fetchOkTransformer = fetchOkTransformer;
|
|
11
|
-
exports.fetchMaxSizeProcessor = fetchMaxSizeProcessor;
|
|
12
|
-
exports.fetchResponseMaxSizeChecker = fetchResponseMaxSizeChecker;
|
|
13
|
-
exports.fetchTypeProcessor = fetchTypeProcessor;
|
|
14
|
-
exports.fetchResponseTypeChecker = fetchResponseTypeChecker;
|
|
15
|
-
exports.fetchResponseJsonTransformer = fetchResponseJsonTransformer;
|
|
16
|
-
exports.fetchJsonProcessor = fetchJsonProcessor;
|
|
17
|
-
exports.fetchJsonValidatorProcessor = fetchJsonValidatorProcessor;
|
|
18
|
-
const pipe_1 = require("@atproto-labs/pipe");
|
|
19
|
-
const fetch_error_js_1 = require("./fetch-error.js");
|
|
20
|
-
const transformed_response_js_1 = require("./transformed-response.js");
|
|
21
|
-
const util_js_1 = require("./util.js");
|
|
1
|
+
import { pipe } from '@atproto-labs/pipe';
|
|
2
|
+
import { FetchError } from './fetch-error.js';
|
|
3
|
+
import { TransformedResponse } from './transformed-response.js';
|
|
4
|
+
import { MaxBytesTransformStream, cancelBody, ifString, logCancellationError, } from './util.js';
|
|
22
5
|
/**
|
|
23
6
|
* media-type = type "/" subtype *( ";" parameter )
|
|
24
7
|
* type = token
|
|
@@ -35,15 +18,10 @@ const util_js_1 = require("./util.js");
|
|
|
35
18
|
* @see {@link https://datatracker.ietf.org/doc/html/rfc2616#autoid-23}
|
|
36
19
|
*/
|
|
37
20
|
const JSON_MIME = /^application\/(?:[^()<>@,;:/[\]\\?={} \t]+\+)?json$/i;
|
|
38
|
-
class FetchResponseError extends
|
|
21
|
+
export class FetchResponseError extends FetchError {
|
|
39
22
|
constructor(response, statusCode = response.status, message = response.statusText, options) {
|
|
40
23
|
super(statusCode, message, options);
|
|
41
|
-
|
|
42
|
-
enumerable: true,
|
|
43
|
-
configurable: true,
|
|
44
|
-
writable: true,
|
|
45
|
-
value: response
|
|
46
|
-
});
|
|
24
|
+
this.response = response;
|
|
47
25
|
}
|
|
48
26
|
static async from(response, customMessage = extractResponseMessage, statusCode = response.status, options) {
|
|
49
27
|
const message = typeof customMessage === 'string'
|
|
@@ -54,7 +32,6 @@ class FetchResponseError extends fetch_error_js_1.FetchError {
|
|
|
54
32
|
return new FetchResponseError(response, statusCode, message, options);
|
|
55
33
|
}
|
|
56
34
|
}
|
|
57
|
-
exports.FetchResponseError = FetchResponseError;
|
|
58
35
|
const extractResponseMessage = async (response) => {
|
|
59
36
|
const mimeType = extractMime(response);
|
|
60
37
|
if (!mimeType)
|
|
@@ -68,13 +45,13 @@ const extractResponseMessage = async (response) => {
|
|
|
68
45
|
if (typeof json === 'string')
|
|
69
46
|
return json;
|
|
70
47
|
if (typeof json === 'object' && json != null) {
|
|
71
|
-
const errorDescription =
|
|
48
|
+
const errorDescription = ifString(json['error_description']);
|
|
72
49
|
if (errorDescription)
|
|
73
50
|
return errorDescription;
|
|
74
|
-
const error =
|
|
51
|
+
const error = ifString(json['error']);
|
|
75
52
|
if (error)
|
|
76
53
|
return error;
|
|
77
|
-
const message =
|
|
54
|
+
const message = ifString(json['message']);
|
|
78
55
|
if (message)
|
|
79
56
|
return message;
|
|
80
57
|
}
|
|
@@ -85,7 +62,7 @@ const extractResponseMessage = async (response) => {
|
|
|
85
62
|
}
|
|
86
63
|
return undefined;
|
|
87
64
|
};
|
|
88
|
-
async function peekJson(response, maxSize = Infinity) {
|
|
65
|
+
export async function peekJson(response, maxSize = Infinity) {
|
|
89
66
|
const type = extractMime(response);
|
|
90
67
|
if (type !== 'application/json')
|
|
91
68
|
return undefined;
|
|
@@ -94,13 +71,13 @@ async function peekJson(response, maxSize = Infinity) {
|
|
|
94
71
|
const clonedResponse = response.clone();
|
|
95
72
|
// 2) Make sure the request's body is not too large
|
|
96
73
|
const limitedResponse = response.body && maxSize < Infinity
|
|
97
|
-
? new
|
|
74
|
+
? new TransformedResponse(clonedResponse, new MaxBytesTransformStream(maxSize))
|
|
98
75
|
: // Note: some runtimes (e.g. react-native) don't expose a body property
|
|
99
76
|
clonedResponse;
|
|
100
77
|
// 3) Parse the JSON
|
|
101
78
|
return limitedResponse.json();
|
|
102
79
|
}
|
|
103
|
-
function checkLength(response, maxBytes) {
|
|
80
|
+
export function checkLength(response, maxBytes) {
|
|
104
81
|
// Note: negation accounts for invalid value types (NaN, non numbers)
|
|
105
82
|
if (!(maxBytes >= 0)) {
|
|
106
83
|
throw new TypeError('maxBytes must be a non-negative number');
|
|
@@ -111,7 +88,7 @@ function checkLength(response, maxBytes) {
|
|
|
111
88
|
}
|
|
112
89
|
return length;
|
|
113
90
|
}
|
|
114
|
-
function extractLength(response) {
|
|
91
|
+
export function extractLength(response) {
|
|
115
92
|
const contentLength = response.headers.get('Content-Length');
|
|
116
93
|
if (contentLength == null)
|
|
117
94
|
return undefined;
|
|
@@ -124,7 +101,7 @@ function extractLength(response) {
|
|
|
124
101
|
}
|
|
125
102
|
return length;
|
|
126
103
|
}
|
|
127
|
-
function extractMime(response) {
|
|
104
|
+
export function extractMime(response) {
|
|
128
105
|
const contentType = response.headers.get('Content-Type');
|
|
129
106
|
if (contentType == null)
|
|
130
107
|
return undefined;
|
|
@@ -140,28 +117,28 @@ function extractMime(response) {
|
|
|
140
117
|
* error. Defaults to logging the error. Do not use `null` if the request is
|
|
141
118
|
* cloned.
|
|
142
119
|
*/
|
|
143
|
-
function cancelBodyOnError(transformer, onCancellationError =
|
|
120
|
+
export function cancelBodyOnError(transformer, onCancellationError = logCancellationError) {
|
|
144
121
|
return async (response) => {
|
|
145
122
|
try {
|
|
146
123
|
return await transformer(response);
|
|
147
124
|
}
|
|
148
125
|
catch (err) {
|
|
149
|
-
await
|
|
126
|
+
await cancelBody(response, onCancellationError ?? undefined);
|
|
150
127
|
throw err;
|
|
151
128
|
}
|
|
152
129
|
};
|
|
153
130
|
}
|
|
154
|
-
function fetchOkProcessor(customMessage) {
|
|
131
|
+
export function fetchOkProcessor(customMessage) {
|
|
155
132
|
return cancelBodyOnError((response) => {
|
|
156
133
|
return fetchOkTransformer(response, customMessage);
|
|
157
134
|
});
|
|
158
135
|
}
|
|
159
|
-
async function fetchOkTransformer(response, customMessage) {
|
|
136
|
+
export async function fetchOkTransformer(response, customMessage) {
|
|
160
137
|
if (response.ok)
|
|
161
138
|
return response;
|
|
162
139
|
throw await FetchResponseError.from(response, customMessage);
|
|
163
140
|
}
|
|
164
|
-
function fetchMaxSizeProcessor(maxBytes) {
|
|
141
|
+
export function fetchMaxSizeProcessor(maxBytes) {
|
|
165
142
|
if (maxBytes === Infinity)
|
|
166
143
|
return (response) => response;
|
|
167
144
|
if (!Number.isFinite(maxBytes) || maxBytes < 0) {
|
|
@@ -171,7 +148,7 @@ function fetchMaxSizeProcessor(maxBytes) {
|
|
|
171
148
|
return fetchResponseMaxSizeChecker(response, maxBytes);
|
|
172
149
|
});
|
|
173
150
|
}
|
|
174
|
-
function fetchResponseMaxSizeChecker(response, maxBytes) {
|
|
151
|
+
export function fetchResponseMaxSizeChecker(response, maxBytes) {
|
|
175
152
|
if (maxBytes === Infinity)
|
|
176
153
|
return response;
|
|
177
154
|
checkLength(response, maxBytes);
|
|
@@ -179,10 +156,10 @@ function fetchResponseMaxSizeChecker(response, maxBytes) {
|
|
|
179
156
|
// we will only rely on the Content-Length header.
|
|
180
157
|
if (!response.body)
|
|
181
158
|
return response;
|
|
182
|
-
const transform = new
|
|
183
|
-
return new
|
|
159
|
+
const transform = new MaxBytesTransformStream(maxBytes);
|
|
160
|
+
return new TransformedResponse(response, transform);
|
|
184
161
|
}
|
|
185
|
-
function fetchTypeProcessor(expectedMime, contentTypeRequired = true) {
|
|
162
|
+
export function fetchTypeProcessor(expectedMime, contentTypeRequired = true) {
|
|
186
163
|
const isExpected = typeof expectedMime === 'string'
|
|
187
164
|
? (mimeType) => mimeType === expectedMime
|
|
188
165
|
: expectedMime instanceof RegExp
|
|
@@ -192,7 +169,7 @@ function fetchTypeProcessor(expectedMime, contentTypeRequired = true) {
|
|
|
192
169
|
return fetchResponseTypeChecker(response, isExpected, contentTypeRequired);
|
|
193
170
|
});
|
|
194
171
|
}
|
|
195
|
-
async function fetchResponseTypeChecker(response, isExpectedMime, contentTypeRequired = true) {
|
|
172
|
+
export async function fetchResponseTypeChecker(response, isExpectedMime, contentTypeRequired = true) {
|
|
196
173
|
const mimeType = extractMime(response);
|
|
197
174
|
if (mimeType) {
|
|
198
175
|
if (!isExpectedMime(mimeType.toLowerCase())) {
|
|
@@ -204,7 +181,7 @@ async function fetchResponseTypeChecker(response, isExpectedMime, contentTypeReq
|
|
|
204
181
|
}
|
|
205
182
|
return response;
|
|
206
183
|
}
|
|
207
|
-
async function fetchResponseJsonTransformer(response) {
|
|
184
|
+
export async function fetchResponseJsonTransformer(response) {
|
|
208
185
|
try {
|
|
209
186
|
const json = (await response.json());
|
|
210
187
|
return { response, json };
|
|
@@ -213,10 +190,10 @@ async function fetchResponseJsonTransformer(response) {
|
|
|
213
190
|
throw new FetchResponseError(response, 502, 'Unable to parse response as JSON', { cause });
|
|
214
191
|
}
|
|
215
192
|
}
|
|
216
|
-
function fetchJsonProcessor(expectedMime = JSON_MIME, contentTypeRequired = true) {
|
|
217
|
-
return
|
|
193
|
+
export function fetchJsonProcessor(expectedMime = JSON_MIME, contentTypeRequired = true) {
|
|
194
|
+
return pipe(fetchTypeProcessor(expectedMime, contentTypeRequired), cancelBodyOnError((fetchResponseJsonTransformer)));
|
|
218
195
|
}
|
|
219
|
-
function fetchJsonValidatorProcessor(schema, params) {
|
|
196
|
+
export function fetchJsonValidatorProcessor(schema, params) {
|
|
220
197
|
if ('parseAsync' in schema && typeof schema.parseAsync === 'function') {
|
|
221
198
|
return async (jsonResponse) => schema.parseAsync(jsonResponse.json, params);
|
|
222
199
|
}
|
|
@@ -227,5 +204,5 @@ function fetchJsonValidatorProcessor(schema, params) {
|
|
|
227
204
|
throw new TypeError('Invalid schema');
|
|
228
205
|
}
|
|
229
206
|
/** @note Use {@link fetchJsonValidatorProcessor} instead */
|
|
230
|
-
|
|
207
|
+
export const fetchJsonZodProcessor = fetchJsonValidatorProcessor;
|
|
231
208
|
//# sourceMappingURL=fetch-response.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch-response.js","sourceRoot":"","sources":["../src/fetch-response.ts"],"names":[],"mappings":";;;AAuFA,4BAuBC;AAED,kCAUC;AAED,sCAWC;AAED,kCAKC;AAYD,8CAYC;AAED,4CAMC;AAED,gDAMC;AAED,sDAQC;AAED,kEAaC;AAKD,gDAcC;AAED,4DAuBC;AAOD,oEAcC;AAED,gDAQC;AAUD,kEAgBC;AApTD,6CAAsD;AACtD,qDAA6C;AAC7C,uEAA+D;AAC/D,uCAMkB;AAElB;;;;;;;;;;;;;;GAcG;AACH,MAAM,SAAS,GAAG,sDAAsD,CAAA;AAKxE,MAAa,kBAAmB,SAAQ,2BAAU;IAChD,YACkB,QAAkB,EAClC,aAAqB,QAAQ,CAAC,MAAM,EACpC,UAAkB,QAAQ,CAAC,UAAU,EACrC,OAAsB;QAEtB,KAAK,CAAC,UAAU,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;QALnC;;;;mBAAgB,QAAQ;WAAU;IAMpC,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,IAAI,CACf,QAAkB,EAClB,gBAAgD,sBAAsB,EACtE,UAAU,GAAG,QAAQ,CAAC,MAAM,EAC5B,OAAsB;QAEtB,MAAM,OAAO,GACX,OAAO,aAAa,KAAK,QAAQ;YAC/B,CAAC,CAAC,aAAa;YACf,CAAC,CAAC,OAAO,aAAa,KAAK,UAAU;gBACnC,CAAC,CAAC,MAAM,aAAa,CAAC,QAAQ,CAAC;gBAC/B,CAAC,CAAC,SAAS,CAAA;QAEjB,OAAO,IAAI,kBAAkB,CAAC,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;IACvE,CAAC;CACF;AAzBD,gDAyBC;AAED,MAAM,sBAAsB,GAA0B,KAAK,EAAE,QAAQ,EAAE,EAAE;IACvE,MAAM,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAA;IACtC,IAAI,CAAC,QAAQ;QAAE,OAAO,SAAS,CAAA;IAE/B,IAAI,CAAC;QACH,IAAI,QAAQ,KAAK,YAAY,EAAE,CAAC;YAC9B,OAAO,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;QAC9B,CAAC;aAAM,IAAI,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YACpC,MAAM,IAAI,GAAY,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;YAE3C,IAAI,OAAO,IAAI,KAAK,QAAQ;gBAAE,OAAO,IAAI,CAAA;YACzC,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC;gBAC7C,MAAM,gBAAgB,GAAG,IAAA,kBAAQ,EAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAA;gBAC5D,IAAI,gBAAgB;oBAAE,OAAO,gBAAgB,CAAA;gBAE7C,MAAM,KAAK,GAAG,IAAA,kBAAQ,EAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAA;gBACrC,IAAI,KAAK;oBAAE,OAAO,KAAK,CAAA;gBAEvB,MAAM,OAAO,GAAG,IAAA,kBAAQ,EAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAA;gBACzC,IAAI,OAAO;oBAAE,OAAO,OAAO,CAAA;YAC7B,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;IACT,CAAC;IAED,OAAO,SAAS,CAAA;AAClB,CAAC,CAAA;AAEM,KAAK,UAAU,QAAQ,CAC5B,QAAkB,EAClB,OAAO,GAAG,QAAQ;IAElB,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAA;IAClC,IAAI,IAAI,KAAK,kBAAkB;QAAE,OAAO,SAAS,CAAA;IACjD,WAAW,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;IAE9B,kDAAkD;IAClD,MAAM,cAAc,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAA;IAEvC,mDAAmD;IACnD,MAAM,eAAe,GACnB,QAAQ,CAAC,IAAI,IAAI,OAAO,GAAG,QAAQ;QACjC,CAAC,CAAC,IAAI,6CAAmB,CACrB,cAAc,EACd,IAAI,iCAAuB,CAAC,OAAO,CAAC,CACrC;QACH,CAAC,CAAC,uEAAuE;YACvE,cAAc,CAAA;IAEpB,oBAAoB;IACpB,OAAO,eAAe,CAAC,IAAI,EAAE,CAAA;AAC/B,CAAC;AAED,SAAgB,WAAW,CAAC,QAAkB,EAAE,QAAgB;IAC9D,qEAAqE;IACrE,IAAI,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,SAAS,CAAC,wCAAwC,CAAC,CAAA;IAC/D,CAAC;IACD,MAAM,MAAM,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAA;IACtC,IAAI,MAAM,IAAI,IAAI,IAAI,MAAM,GAAG,QAAQ,EAAE,CAAC;QACxC,MAAM,IAAI,kBAAkB,CAAC,QAAQ,EAAE,GAAG,EAAE,oBAAoB,CAAC,CAAA;IACnE,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC;AAED,SAAgB,aAAa,CAAC,QAAkB;IAC9C,MAAM,aAAa,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAA;IAC5D,IAAI,aAAa,IAAI,IAAI;QAAE,OAAO,SAAS,CAAA;IAC3C,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,kBAAkB,CAAC,QAAQ,EAAE,GAAG,EAAE,wBAAwB,CAAC,CAAA;IACvE,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,CAAC,aAAa,CAAC,CAAA;IACpC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,kBAAkB,CAAC,QAAQ,EAAE,GAAG,EAAE,0BAA0B,CAAC,CAAA;IACzE,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC;AAED,SAAgB,WAAW,CAAC,QAAkB;IAC5C,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAA;IACxD,IAAI,WAAW,IAAI,IAAI;QAAE,OAAO,SAAS,CAAA;IAEzC,OAAO,WAAW,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,CAAA;AAC7C,CAAC;AAED;;;;;;;;;GASG;AACH,SAAgB,iBAAiB,CAC/B,WAAqC,EACrC,sBAAuD,8BAAoB;IAE3E,OAAO,KAAK,EAAE,QAAQ,EAAE,EAAE;QACxB,IAAI,CAAC;YACH,OAAO,MAAM,WAAW,CAAC,QAAQ,CAAC,CAAA;QACpC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,IAAA,oBAAU,EAAC,QAAQ,EAAE,mBAAmB,IAAI,SAAS,CAAC,CAAA;YAC5D,MAAM,GAAG,CAAA;QACX,CAAC;IACH,CAAC,CAAA;AACH,CAAC;AAED,SAAgB,gBAAgB,CAC9B,aAA8C;IAE9C,OAAO,iBAAiB,CAAC,CAAC,QAAQ,EAAE,EAAE;QACpC,OAAO,kBAAkB,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAA;IACpD,CAAC,CAAC,CAAA;AACJ,CAAC;AAEM,KAAK,UAAU,kBAAkB,CACtC,QAAkB,EAClB,aAA8C;IAE9C,IAAI,QAAQ,CAAC,EAAE;QAAE,OAAO,QAAQ,CAAA;IAChC,MAAM,MAAM,kBAAkB,CAAC,IAAI,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAA;AAC9D,CAAC;AAED,SAAgB,qBAAqB,CAAC,QAAgB;IACpD,IAAI,QAAQ,KAAK,QAAQ;QAAE,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAA;IACxD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,QAAQ,GAAG,CAAC,EAAE,CAAC;QAC/C,MAAM,IAAI,SAAS,CAAC,qDAAqD,CAAC,CAAA;IAC5E,CAAC;IACD,OAAO,iBAAiB,CAAC,CAAC,QAAQ,EAAE,EAAE;QACpC,OAAO,2BAA2B,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;IACxD,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,SAAgB,2BAA2B,CACzC,QAAkB,EAClB,QAAgB;IAEhB,IAAI,QAAQ,KAAK,QAAQ;QAAE,OAAO,QAAQ,CAAA;IAC1C,WAAW,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;IAE/B,6EAA6E;IAC7E,kDAAkD;IAClD,IAAI,CAAC,QAAQ,CAAC,IAAI;QAAE,OAAO,QAAQ,CAAA;IAEnC,MAAM,SAAS,GAAG,IAAI,iCAAuB,CAAC,QAAQ,CAAC,CAAA;IACvD,OAAO,IAAI,6CAAmB,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAA;AACrD,CAAC;AAKD,SAAgB,kBAAkB,CAChC,YAA2B,EAC3B,mBAAmB,GAAG,IAAI;IAE1B,MAAM,UAAU,GACd,OAAO,YAAY,KAAK,QAAQ;QAC9B,CAAC,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,KAAK,YAAY;QACzC,CAAC,CAAC,YAAY,YAAY,MAAM;YAC9B,CAAC,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC;YAC3C,CAAC,CAAC,YAAY,CAAA;IAEpB,OAAO,iBAAiB,CAAC,CAAC,QAAQ,EAAE,EAAE;QACpC,OAAO,wBAAwB,CAAC,QAAQ,EAAE,UAAU,EAAE,mBAAmB,CAAC,CAAA;IAC5E,CAAC,CAAC,CAAA;AACJ,CAAC;AAEM,KAAK,UAAU,wBAAwB,CAC5C,QAAkB,EAClB,cAA+B,EAC/B,mBAAmB,GAAG,IAAI;IAE1B,MAAM,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAA;IACtC,IAAI,QAAQ,EAAE,CAAC;QACb,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;YAC5C,MAAM,MAAM,kBAAkB,CAAC,IAAI,CACjC,QAAQ,EACR,qCAAqC,QAAQ,GAAG,EAChD,GAAG,CACJ,CAAA;QACH,CAAC;IACH,CAAC;SAAM,IAAI,mBAAmB,EAAE,CAAC;QAC/B,MAAM,MAAM,kBAAkB,CAAC,IAAI,CACjC,QAAQ,EACR,sCAAsC,EACtC,GAAG,CACJ,CAAA;IACH,CAAC;IAED,OAAO,QAAQ,CAAA;AACjB,CAAC;AAOM,KAAK,UAAU,4BAA4B,CAChD,QAAkB;IAElB,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAM,CAAA;QACzC,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAA;IAC3B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,kBAAkB,CAC1B,QAAQ,EACR,GAAG,EACH,kCAAkC,EAClC,EAAE,KAAK,EAAE,CACV,CAAA;IACH,CAAC;AACH,CAAC;AAED,SAAgB,kBAAkB,CAChC,eAA8B,SAAS,EACvC,mBAAmB,GAAG,IAAI;IAE1B,OAAO,IAAA,WAAI,EACT,kBAAkB,CAAC,YAAY,EAAE,mBAAmB,CAAC,EACrD,iBAAiB,CAAC,CAAA,4BAA+B,CAAA,CAAC,CACnD,CAAA;AACH,CAAC;AAUD,SAAgB,2BAA2B,CACzC,MAAgE,EAChE,MAAU;IAEV,IAAI,YAAY,IAAI,MAAM,IAAI,OAAO,MAAM,CAAC,UAAU,KAAK,UAAU,EAAE,CAAC;QACtE,OAAO,KAAK,EAAE,YAAgC,EAAc,EAAE,CAC5D,MAAM,CAAC,UAAU,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IAChD,CAAC;IAED,IAAI,OAAO,IAAI,MAAM,IAAI,OAAO,MAAM,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;QAC5D,OAAO,KAAK,EAAE,YAAgC,EAAc,EAAE,CAC5D,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IAC3C,CAAC;IAED,+EAA+E;IAC/E,MAAM,IAAI,SAAS,CAAC,gBAAgB,CAAC,CAAA;AACvC,CAAC;AAED,4DAA4D;AAC/C,QAAA,qBAAqB,GAAG,2BAA2B,CAAA"}
|
|
1
|
+
{"version":3,"file":"fetch-response.js","sourceRoot":"","sources":["../src/fetch-response.ts"],"names":[],"mappings":"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","sourcesContent":["import { Transformer, pipe } from '@atproto-labs/pipe'\nimport { FetchError } from './fetch-error.js'\nimport { TransformedResponse } from './transformed-response.js'\nimport {\n Json,\n MaxBytesTransformStream,\n cancelBody,\n ifString,\n logCancellationError,\n} from './util.js'\n\n/**\n * media-type = type \"/\" subtype *( \";\" parameter )\n * type = token\n * subtype = token\n * token = 1*<any CHAR except CTLs or separators>\n * separators = \"(\" | \")\" | \"<\" | \">\" | \"@\"\n * | \",\" | \";\" | \":\" | \"\\\" | <\">\n * | \"/\" | \"[\" | \"]\" | \"?\" | \"=\"\n * | \"{\" | \"}\" | SP | HT\n * CTL = <any US-ASCII control character (octets 0 - 31) and DEL (127)>\n * SP = <US-ASCII SP, space (32)>\n * HT = <US-ASCII HT, horizontal-tab (9)>\n * @note The type, subtype, and parameter attribute names are case-insensitive.\n * @see {@link https://datatracker.ietf.org/doc/html/rfc2616#autoid-23}\n */\nconst JSON_MIME = /^application\\/(?:[^()<>@,;:/[\\]\\\\?={} \\t]+\\+)?json$/i\n\nexport type ResponseTransformer = Transformer<Response>\nexport type ResponseMessageGetter = Transformer<Response, string | undefined>\n\nexport class FetchResponseError extends FetchError {\n constructor(\n public readonly response: Response,\n statusCode: number = response.status,\n message: string = response.statusText,\n options?: ErrorOptions,\n ) {\n super(statusCode, message, options)\n }\n\n static async from(\n response: Response,\n customMessage: string | ResponseMessageGetter = extractResponseMessage,\n statusCode = response.status,\n options?: ErrorOptions,\n ) {\n const message =\n typeof customMessage === 'string'\n ? customMessage\n : typeof customMessage === 'function'\n ? await customMessage(response)\n : undefined\n\n return new FetchResponseError(response, statusCode, message, options)\n }\n}\n\nconst extractResponseMessage: ResponseMessageGetter = async (response) => {\n const mimeType = extractMime(response)\n if (!mimeType) return undefined\n\n try {\n if (mimeType === 'text/plain') {\n return await response.text()\n } else if (JSON_MIME.test(mimeType)) {\n const json: unknown = await response.json()\n\n if (typeof json === 'string') return json\n if (typeof json === 'object' && json != null) {\n const errorDescription = ifString(json['error_description'])\n if (errorDescription) return errorDescription\n\n const error = ifString(json['error'])\n if (error) return error\n\n const message = ifString(json['message'])\n if (message) return message\n }\n }\n } catch {\n // noop\n }\n\n return undefined\n}\n\nexport async function peekJson(\n response: Response,\n maxSize = Infinity,\n): Promise<undefined | Json> {\n const type = extractMime(response)\n if (type !== 'application/json') return undefined\n checkLength(response, maxSize)\n\n // 1) Clone the request so we can consume the body\n const clonedResponse = response.clone()\n\n // 2) Make sure the request's body is not too large\n const limitedResponse =\n response.body && maxSize < Infinity\n ? new TransformedResponse(\n clonedResponse,\n new MaxBytesTransformStream(maxSize),\n )\n : // Note: some runtimes (e.g. react-native) don't expose a body property\n clonedResponse\n\n // 3) Parse the JSON\n return limitedResponse.json()\n}\n\nexport function checkLength(response: Response, maxBytes: number) {\n // Note: negation accounts for invalid value types (NaN, non numbers)\n if (!(maxBytes >= 0)) {\n throw new TypeError('maxBytes must be a non-negative number')\n }\n const length = extractLength(response)\n if (length != null && length > maxBytes) {\n throw new FetchResponseError(response, 502, 'Response too large')\n }\n return length\n}\n\nexport function extractLength(response: Response) {\n const contentLength = response.headers.get('Content-Length')\n if (contentLength == null) return undefined\n if (!/^\\d+$/.test(contentLength)) {\n throw new FetchResponseError(response, 502, 'Invalid Content-Length')\n }\n const length = Number(contentLength)\n if (!Number.isSafeInteger(length)) {\n throw new FetchResponseError(response, 502, 'Content-Length too large')\n }\n return length\n}\n\nexport function extractMime(response: Response) {\n const contentType = response.headers.get('Content-Type')\n if (contentType == null) return undefined\n\n return contentType.split(';', 1)[0]!.trim()\n}\n\n/**\n * If the transformer results in an error, ensure that the response body is\n * consumed as, in some environments (Node 👀), the response will not\n * automatically be GC'd.\n *\n * @see {@link https://undici.nodejs.org/#/?id=garbage-collection}\n * @param [onCancellationError] - Callback to handle any async body cancelling\n * error. Defaults to logging the error. Do not use `null` if the request is\n * cloned.\n */\nexport function cancelBodyOnError<T>(\n transformer: Transformer<Response, T>,\n onCancellationError: null | ((err: unknown) => void) = logCancellationError,\n): (response: Response) => Promise<T> {\n return async (response) => {\n try {\n return await transformer(response)\n } catch (err) {\n await cancelBody(response, onCancellationError ?? undefined)\n throw err\n }\n }\n}\n\nexport function fetchOkProcessor(\n customMessage?: string | ResponseMessageGetter,\n): ResponseTransformer {\n return cancelBodyOnError((response) => {\n return fetchOkTransformer(response, customMessage)\n })\n}\n\nexport async function fetchOkTransformer(\n response: Response,\n customMessage?: string | ResponseMessageGetter,\n) {\n if (response.ok) return response\n throw await FetchResponseError.from(response, customMessage)\n}\n\nexport function fetchMaxSizeProcessor(maxBytes: number): ResponseTransformer {\n if (maxBytes === Infinity) return (response) => response\n if (!Number.isFinite(maxBytes) || maxBytes < 0) {\n throw new TypeError('maxBytes must be a 0, Infinity or a positive number')\n }\n return cancelBodyOnError((response) => {\n return fetchResponseMaxSizeChecker(response, maxBytes)\n })\n}\n\nexport function fetchResponseMaxSizeChecker(\n response: Response,\n maxBytes: number,\n): Response {\n if (maxBytes === Infinity) return response\n checkLength(response, maxBytes)\n\n // Some engines (react-native 👀) don't expose a body property. In that case,\n // we will only rely on the Content-Length header.\n if (!response.body) return response\n\n const transform = new MaxBytesTransformStream(maxBytes)\n return new TransformedResponse(response, transform)\n}\n\nexport type MimeTypeCheckFn = (mimeType: string) => boolean\nexport type MimeTypeCheck = string | RegExp | MimeTypeCheckFn\n\nexport function fetchTypeProcessor(\n expectedMime: MimeTypeCheck,\n contentTypeRequired = true,\n): ResponseTransformer {\n const isExpected: MimeTypeCheckFn =\n typeof expectedMime === 'string'\n ? (mimeType) => mimeType === expectedMime\n : expectedMime instanceof RegExp\n ? (mimeType) => expectedMime.test(mimeType)\n : expectedMime\n\n return cancelBodyOnError((response) => {\n return fetchResponseTypeChecker(response, isExpected, contentTypeRequired)\n })\n}\n\nexport async function fetchResponseTypeChecker(\n response: Response,\n isExpectedMime: MimeTypeCheckFn,\n contentTypeRequired = true,\n): Promise<Response> {\n const mimeType = extractMime(response)\n if (mimeType) {\n if (!isExpectedMime(mimeType.toLowerCase())) {\n throw await FetchResponseError.from(\n response,\n `Unexpected response Content-Type (${mimeType})`,\n 502,\n )\n }\n } else if (contentTypeRequired) {\n throw await FetchResponseError.from(\n response,\n 'Missing response Content-Type header',\n 502,\n )\n }\n\n return response\n}\n\nexport type ParsedJsonResponse<T = Json> = {\n response: Response\n json: T\n}\n\nexport async function fetchResponseJsonTransformer<T = Json>(\n response: Response,\n): Promise<ParsedJsonResponse<T>> {\n try {\n const json = (await response.json()) as T\n return { response, json }\n } catch (cause) {\n throw new FetchResponseError(\n response,\n 502,\n 'Unable to parse response as JSON',\n { cause },\n )\n }\n}\n\nexport function fetchJsonProcessor<T = Json>(\n expectedMime: MimeTypeCheck = JSON_MIME,\n contentTypeRequired = true,\n): Transformer<Response, ParsedJsonResponse<T>> {\n return pipe(\n fetchTypeProcessor(expectedMime, contentTypeRequired),\n cancelBodyOnError(fetchResponseJsonTransformer<T>),\n )\n}\n\nexport type SyncValidationSchema<S, P = unknown> = {\n parse(value: unknown, params?: P): S\n}\n\nexport type AsyncValidationSchema<S, P = unknown> = {\n parseAsync(value: unknown, params?: P): Promise<S>\n}\n\nexport function fetchJsonValidatorProcessor<S, P = unknown>(\n schema: SyncValidationSchema<S, P> | AsyncValidationSchema<S, P>,\n params?: P,\n): Transformer<ParsedJsonResponse, S> {\n if ('parseAsync' in schema && typeof schema.parseAsync === 'function') {\n return async (jsonResponse: ParsedJsonResponse): Promise<S> =>\n schema.parseAsync(jsonResponse.json, params)\n }\n\n if ('parse' in schema && typeof schema.parse === 'function') {\n return async (jsonResponse: ParsedJsonResponse): Promise<S> =>\n schema.parse(jsonResponse.json, params)\n }\n\n // Needed for type safety (and allows fool proofing the usage of this function)\n throw new TypeError('Invalid schema')\n}\n\n/** @note Use {@link fetchJsonValidatorProcessor} instead */\nexport const fetchJsonZodProcessor = fetchJsonValidatorProcessor\n"]}
|
package/dist/fetch-wrap.js
CHANGED
|
@@ -1,23 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const fetch_request_js_1 = require("./fetch-request.js");
|
|
7
|
-
const fetch_js_1 = require("./fetch.js");
|
|
8
|
-
const transformed_response_js_1 = require("./transformed-response.js");
|
|
9
|
-
const util_js_1 = require("./util.js");
|
|
10
|
-
function loggedFetch({ fetch = globalThis.fetch, logRequest = true, logResponse = true, logError = true, }) {
|
|
1
|
+
import { FetchRequestError } from './fetch-request.js';
|
|
2
|
+
import { toRequestTransformer } from './fetch.js';
|
|
3
|
+
import { TransformedResponse } from './transformed-response.js';
|
|
4
|
+
import { padLines, stringifyMessage } from './util.js';
|
|
5
|
+
export function loggedFetch({ fetch = globalThis.fetch, logRequest = true, logResponse = true, logError = true, }) {
|
|
11
6
|
const onRequest = logRequest === true
|
|
12
7
|
? async (request) => {
|
|
13
|
-
const requestMessage = await
|
|
14
|
-
console.info(`> ${request.method} ${request.url}\n${
|
|
8
|
+
const requestMessage = await stringifyMessage(request);
|
|
9
|
+
console.info(`> ${request.method} ${request.url}\n${padLines(requestMessage, ' ')}`);
|
|
15
10
|
}
|
|
16
11
|
: logRequest || undefined;
|
|
17
12
|
const onResponse = logResponse === true
|
|
18
13
|
? async (response) => {
|
|
19
|
-
const responseMessage = await
|
|
20
|
-
console.info(`< HTTP/1.1 ${response.status} ${response.statusText}\n${
|
|
14
|
+
const responseMessage = await stringifyMessage(response.clone());
|
|
15
|
+
console.info(`< HTTP/1.1 ${response.status} ${response.statusText}\n${padLines(responseMessage, ' ')}`);
|
|
21
16
|
}
|
|
22
17
|
: logResponse || undefined;
|
|
23
18
|
const onError = logError === true
|
|
@@ -27,7 +22,7 @@ function loggedFetch({ fetch = globalThis.fetch, logRequest = true, logResponse
|
|
|
27
22
|
: logError || undefined;
|
|
28
23
|
if (!onRequest && !onResponse && !onError)
|
|
29
24
|
return fetch;
|
|
30
|
-
return
|
|
25
|
+
return toRequestTransformer(async function (request) {
|
|
31
26
|
if (onRequest)
|
|
32
27
|
await onRequest(request);
|
|
33
28
|
try {
|
|
@@ -43,13 +38,13 @@ function loggedFetch({ fetch = globalThis.fetch, logRequest = true, logResponse
|
|
|
43
38
|
}
|
|
44
39
|
});
|
|
45
40
|
}
|
|
46
|
-
const timedFetch = (timeout = 60e3, fetch = globalThis.fetch) => {
|
|
41
|
+
export const timedFetch = (timeout = 60e3, fetch = globalThis.fetch) => {
|
|
47
42
|
if (timeout === Infinity)
|
|
48
43
|
return fetch;
|
|
49
44
|
if (!Number.isFinite(timeout) || timeout <= 0) {
|
|
50
45
|
throw new TypeError('Timeout must be positive');
|
|
51
46
|
}
|
|
52
|
-
return
|
|
47
|
+
return toRequestTransformer(async function (request) {
|
|
53
48
|
const controller = new AbortController();
|
|
54
49
|
const signal = controller.signal;
|
|
55
50
|
const abort = () => {
|
|
@@ -72,11 +67,10 @@ const timedFetch = (timeout = 60e3, fetch = globalThis.fetch) => {
|
|
|
72
67
|
else {
|
|
73
68
|
// Cleanup the timer & event listeners when the body stream is closed
|
|
74
69
|
const transform = new TransformStream({ flush: cleanup });
|
|
75
|
-
return new
|
|
70
|
+
return new TransformedResponse(response, transform);
|
|
76
71
|
}
|
|
77
72
|
});
|
|
78
73
|
};
|
|
79
|
-
exports.timedFetch = timedFetch;
|
|
80
74
|
/**
|
|
81
75
|
* Wraps a fetch function to bind it to a specific context, and wrap any thrown
|
|
82
76
|
* errors into a FetchRequestError.
|
|
@@ -111,13 +105,13 @@ exports.timedFetch = timedFetch;
|
|
|
111
105
|
* }
|
|
112
106
|
* ```
|
|
113
107
|
*/
|
|
114
|
-
function bindFetch(fetch = globalThis.fetch, context = globalThis) {
|
|
115
|
-
return
|
|
108
|
+
export function bindFetch(fetch = globalThis.fetch, context = globalThis) {
|
|
109
|
+
return toRequestTransformer(async (request) => {
|
|
116
110
|
try {
|
|
117
111
|
return await fetch.call(context, request);
|
|
118
112
|
}
|
|
119
113
|
catch (err) {
|
|
120
|
-
throw
|
|
114
|
+
throw FetchRequestError.from(request, err);
|
|
121
115
|
}
|
|
122
116
|
});
|
|
123
117
|
}
|
package/dist/fetch-wrap.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch-wrap.js","sourceRoot":"","sources":["../src/fetch-wrap.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"fetch-wrap.js","sourceRoot":"","sources":["../src/fetch-wrap.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AACtD,OAAO,EAAuB,oBAAoB,EAAE,MAAM,YAAY,CAAA;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAA;AAC/D,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAA;AAItD,MAAM,UAAU,WAAW,CAAmB,EAC5C,KAAK,GAAG,UAAU,CAAC,KAAiB,EACpC,UAAU,GAAG,IAA2C,EACxD,WAAW,GAAG,IAA+D,EAC7E,QAAQ,GAAG,IAA2D,GACvE;IACC,MAAM,SAAS,GACb,UAAU,KAAK,IAAI;QACjB,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;YAChB,MAAM,cAAc,GAAG,MAAM,gBAAgB,CAAC,OAAO,CAAC,CAAA;YACtD,OAAO,CAAC,IAAI,CACV,KAAK,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,KAAK,QAAQ,CAAC,cAAc,EAAE,IAAI,CAAC,EAAE,CACxE,CAAA;QACH,CAAC;QACH,CAAC,CAAC,UAAU,IAAI,SAAS,CAAA;IAE7B,MAAM,UAAU,GACd,WAAW,KAAK,IAAI;QAClB,CAAC,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE;YACjB,MAAM,eAAe,GAAG,MAAM,gBAAgB,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAA;YAChE,OAAO,CAAC,IAAI,CACV,cAAc,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,KAAK,QAAQ,CAAC,eAAe,EAAE,IAAI,CAAC,EAAE,CAC3F,CAAA;QACH,CAAC;QACH,CAAC,CAAC,WAAW,IAAI,SAAS,CAAA;IAE9B,MAAM,OAAO,GACX,QAAQ,KAAK,IAAI;QACf,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;YACd,OAAO,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,CAAA;QAClC,CAAC;QACH,CAAC,CAAC,QAAQ,IAAI,SAAS,CAAA;IAE3B,IAAI,CAAC,SAAS,IAAI,CAAC,UAAU,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,CAAA;IAEvD,OAAO,oBAAoB,CAAC,KAAK,WAE/B,OAAO;QAEP,IAAI,SAAS;YAAE,MAAM,SAAS,CAAC,OAAO,CAAC,CAAA;QAEvC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;YAEhD,IAAI,UAAU;gBAAE,MAAM,UAAU,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;YAEnD,OAAO,QAAQ,CAAA;QACjB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,OAAO;gBAAE,MAAM,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;YAE1C,MAAM,KAAK,CAAA;QACb,CAAC;IACH,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,CACxB,OAAO,GAAG,IAAI,EACd,QAAkB,UAAU,CAAC,KAAK,EACxB,EAAE;IACZ,IAAI,OAAO,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAA;IACtC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,IAAI,CAAC,EAAE,CAAC;QAC9C,MAAM,IAAI,SAAS,CAAC,0BAA0B,CAAC,CAAA;IACjD,CAAC;IACD,OAAO,oBAAoB,CAAC,KAAK,WAE/B,OAAO;QAEP,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAA;QACxC,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAA;QAEhC,MAAM,KAAK,GAAG,GAAG,EAAE;YACjB,UAAU,CAAC,KAAK,EAAE,CAAA;QACpB,CAAC,CAAA;QACD,MAAM,OAAO,GAAG,GAAG,EAAE;YACnB,YAAY,CAAC,KAAK,CAAC,CAAA;YACnB,OAAO,CAAC,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;QACrD,CAAC,CAAA;QAED,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;QACxC,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,KAAK,CAAC,KAAK,EAAE,EAAE,CAAA,CAAC,eAAe;QAC9D,OAAO,CAAC,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;QAEhD,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;QAEzC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,CAAC,CAAA;QAE5D,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnB,OAAO,EAAE,CAAA;YACT,OAAO,QAAQ,CAAA;QACjB,CAAC;aAAM,CAAC;YACN,qEAAqE;YACrE,MAAM,SAAS,GAAG,IAAI,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAA;YACzD,OAAO,IAAI,mBAAmB,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAA;QACrD,CAAC;IACH,CAAC,CAAC,CAAA;AACJ,CAAC,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,MAAM,UAAU,SAAS,CACvB,QAAkB,UAAU,CAAC,KAAK,EAClC,UAAa,UAAe;IAE5B,OAAO,oBAAoB,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;QAC5C,IAAI,CAAC;YACH,OAAO,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;QAC3C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,iBAAiB,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAA;QAC5C,CAAC;IACH,CAAC,CAAC,CAAA;AACJ,CAAC","sourcesContent":["import { FetchRequestError } from './fetch-request.js'\nimport { Fetch, FetchContext, toRequestTransformer } from './fetch.js'\nimport { TransformedResponse } from './transformed-response.js'\nimport { padLines, stringifyMessage } from './util.js'\n\ntype LogFn<Args extends unknown[]> = (...args: Args) => void | PromiseLike<void>\n\nexport function loggedFetch<C = FetchContext>({\n fetch = globalThis.fetch as Fetch<C>,\n logRequest = true as boolean | LogFn<[request: Request]>,\n logResponse = true as boolean | LogFn<[response: Response, request: Request]>,\n logError = true as boolean | LogFn<[error: unknown, request: Request]>,\n}) {\n const onRequest =\n logRequest === true\n ? async (request) => {\n const requestMessage = await stringifyMessage(request)\n console.info(\n `> ${request.method} ${request.url}\\n${padLines(requestMessage, ' ')}`,\n )\n }\n : logRequest || undefined\n\n const onResponse =\n logResponse === true\n ? async (response) => {\n const responseMessage = await stringifyMessage(response.clone())\n console.info(\n `< HTTP/1.1 ${response.status} ${response.statusText}\\n${padLines(responseMessage, ' ')}`,\n )\n }\n : logResponse || undefined\n\n const onError =\n logError === true\n ? async (error) => {\n console.error(`< Error:`, error)\n }\n : logError || undefined\n\n if (!onRequest && !onResponse && !onError) return fetch\n\n return toRequestTransformer(async function (\n this: C,\n request,\n ): Promise<Response> {\n if (onRequest) await onRequest(request)\n\n try {\n const response = await fetch.call(this, request)\n\n if (onResponse) await onResponse(response, request)\n\n return response\n } catch (error) {\n if (onError) await onError(error, request)\n\n throw error\n }\n })\n}\n\nexport const timedFetch = <C = FetchContext>(\n timeout = 60e3,\n fetch: Fetch<C> = globalThis.fetch,\n): Fetch<C> => {\n if (timeout === Infinity) return fetch\n if (!Number.isFinite(timeout) || timeout <= 0) {\n throw new TypeError('Timeout must be positive')\n }\n return toRequestTransformer(async function (\n this: C,\n request,\n ): Promise<Response> {\n const controller = new AbortController()\n const signal = controller.signal\n\n const abort = () => {\n controller.abort()\n }\n const cleanup = () => {\n clearTimeout(timer)\n request.signal?.removeEventListener('abort', abort)\n }\n\n const timer = setTimeout(abort, timeout)\n if (typeof timer === 'object') timer.unref?.() // only on node\n request.signal?.addEventListener('abort', abort)\n\n signal.addEventListener('abort', cleanup)\n\n const response = await fetch.call(this, request, { signal })\n\n if (!response.body) {\n cleanup()\n return response\n } else {\n // Cleanup the timer & event listeners when the body stream is closed\n const transform = new TransformStream({ flush: cleanup })\n return new TransformedResponse(response, transform)\n }\n })\n}\n\n/**\n * Wraps a fetch function to bind it to a specific context, and wrap any thrown\n * errors into a FetchRequestError.\n *\n * @example\n *\n * ```ts\n * class MyClient {\n * constructor(private fetch = globalThis.fetch) {}\n *\n * async get(url: string) {\n * // This will generate an error, because the context used is not a\n * // FetchContext (it's a MyClient instance).\n * return this.fetch(url)\n * }\n * }\n * ```\n *\n * @example\n *\n * ```ts\n * class MyClient {\n * private fetch: Fetch<unknown>\n *\n * constructor(fetch = globalThis.fetch) {\n * this.fetch = bindFetch(fetch)\n * }\n *\n * async get(url: string) {\n * return this.fetch(url) // no more error\n * }\n * }\n * ```\n */\nexport function bindFetch<C = FetchContext>(\n fetch: Fetch<C> = globalThis.fetch,\n context: C = globalThis as C,\n) {\n return toRequestTransformer(async (request) => {\n try {\n return await fetch.call(context, request)\n } catch (err) {\n throw FetchRequestError.from(request, err)\n }\n })\n}\n"]}
|
package/dist/fetch.js
CHANGED
|
@@ -1,13 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.toRequestTransformer = toRequestTransformer;
|
|
4
|
-
exports.asRequest = asRequest;
|
|
5
|
-
function toRequestTransformer(requestTransformer) {
|
|
1
|
+
export function toRequestTransformer(requestTransformer) {
|
|
6
2
|
return function (input, init) {
|
|
7
3
|
return requestTransformer.call(this, asRequest(input, init));
|
|
8
4
|
};
|
|
9
5
|
}
|
|
10
|
-
function asRequest(input, init) {
|
|
6
|
+
export function asRequest(input, init) {
|
|
11
7
|
if (!init && input instanceof Request)
|
|
12
8
|
return input;
|
|
13
9
|
return new Request(input, init);
|
package/dist/fetch.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch.js","sourceRoot":"","sources":["../src/fetch.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"fetch.js","sourceRoot":"","sources":["../src/fetch.ts"],"names":[],"mappings":"AAqBA,MAAM,UAAU,oBAAoB,CAClC,kBAAkD;IAKlD,OAAO,UAAmB,KAAK,EAAE,IAAI;QACnC,OAAO,kBAAkB,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAA;IAC9D,CAAC,CAAA;AACH,CAAC;AAED,MAAM,UAAU,SAAS,CACvB,KAA6B,EAC7B,IAAkB;IAElB,IAAI,CAAC,IAAI,IAAI,KAAK,YAAY,OAAO;QAAE,OAAO,KAAK,CAAA;IACnD,OAAO,IAAI,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;AACjC,CAAC","sourcesContent":["import { ThisParameterOverride } from './util.js'\n\nexport type FetchContext = void | null | typeof globalThis\n\nexport type FetchBound = (\n input: string | URL | Request,\n init?: RequestInit,\n) => Promise<Response>\n\n// NOT using \"typeof globalThis.fetch\" here because \"globalThis.fetch\" does not\n// have a \"this\" parameter, while runtimes do ensure that \"fetch\" is called with\n// the correct \"this\" parameter (either null, undefined, or window).\n\nexport type Fetch<C = FetchContext> = ThisParameterOverride<C, FetchBound>\n\nexport type SimpleFetchBound = (input: Request) => Promise<Response>\nexport type SimpleFetch<C = FetchContext> = ThisParameterOverride<\n C,\n SimpleFetchBound\n>\n\nexport function toRequestTransformer<C, O>(\n requestTransformer: (this: C, input: Request) => O,\n): ThisParameterOverride<\n C,\n (input: string | URL | Request, init?: RequestInit) => O\n> {\n return function (this: C, input, init) {\n return requestTransformer.call(this, asRequest(input, init))\n }\n}\n\nexport function asRequest(\n input: string | URL | Request,\n init?: RequestInit,\n): Request {\n if (!init && input instanceof Request) return input\n return new Request(input, init)\n}\n"]}
|
package/dist/index.js
CHANGED
|
@@ -1,23 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
-
};
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./fetch-error.js"), exports);
|
|
18
|
-
__exportStar(require("./fetch-request.js"), exports);
|
|
19
|
-
__exportStar(require("./fetch-response.js"), exports);
|
|
20
|
-
__exportStar(require("./fetch-wrap.js"), exports);
|
|
21
|
-
__exportStar(require("./fetch.js"), exports);
|
|
22
|
-
__exportStar(require("./util.js"), exports);
|
|
1
|
+
export * from './fetch-error.js';
|
|
2
|
+
export * from './fetch-request.js';
|
|
3
|
+
export * from './fetch-response.js';
|
|
4
|
+
export * from './fetch-wrap.js';
|
|
5
|
+
export * from './fetch.js';
|
|
6
|
+
export * from './util.js';
|
|
23
7
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAA;AAChC,cAAc,oBAAoB,CAAA;AAClC,cAAc,qBAAqB,CAAA;AACnC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,YAAY,CAAA;AAC1B,cAAc,WAAW,CAAA","sourcesContent":["export * from './fetch-error.js'\nexport * from './fetch-request.js'\nexport * from './fetch-response.js'\nexport * from './fetch-wrap.js'\nexport * from './fetch.js'\nexport * from './util.js'\n"]}
|
|
@@ -1,19 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
4
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
5
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
6
|
-
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
7
|
-
};
|
|
8
|
-
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
9
|
-
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
10
|
-
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
11
|
-
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
12
|
-
};
|
|
13
|
-
var _TransformedResponse_response;
|
|
14
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.TransformedResponse = void 0;
|
|
16
|
-
class TransformedResponse extends Response {
|
|
1
|
+
export class TransformedResponse extends Response {
|
|
2
|
+
#response;
|
|
17
3
|
constructor(response, transform) {
|
|
18
4
|
if (!response.body) {
|
|
19
5
|
throw new TypeError('Response body is not available');
|
|
@@ -26,25 +12,22 @@ class TransformedResponse extends Response {
|
|
|
26
12
|
statusText: response.statusText,
|
|
27
13
|
headers: response.headers,
|
|
28
14
|
});
|
|
29
|
-
|
|
30
|
-
__classPrivateFieldSet(this, _TransformedResponse_response, response, "f");
|
|
15
|
+
this.#response = response;
|
|
31
16
|
}
|
|
32
17
|
/**
|
|
33
18
|
* Some props can't be set through ResponseInit, so we need to proxy them
|
|
34
19
|
*/
|
|
35
20
|
get url() {
|
|
36
|
-
return
|
|
21
|
+
return this.#response.url;
|
|
37
22
|
}
|
|
38
23
|
get redirected() {
|
|
39
|
-
return
|
|
24
|
+
return this.#response.redirected;
|
|
40
25
|
}
|
|
41
26
|
get type() {
|
|
42
|
-
return
|
|
27
|
+
return this.#response.type;
|
|
43
28
|
}
|
|
44
29
|
get statusText() {
|
|
45
|
-
return
|
|
30
|
+
return this.#response.statusText;
|
|
46
31
|
}
|
|
47
32
|
}
|
|
48
|
-
exports.TransformedResponse = TransformedResponse;
|
|
49
|
-
_TransformedResponse_response = new WeakMap();
|
|
50
33
|
//# sourceMappingURL=transformed-response.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transformed-response.js","sourceRoot":"","sources":["../src/transformed-response.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"transformed-response.js","sourceRoot":"","sources":["../src/transformed-response.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,mBAAoB,SAAQ,QAAQ;IAC/C,SAAS,CAAU;IAEnB,YAAY,QAAkB,EAAE,SAA0B;QACxD,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnB,MAAM,IAAI,SAAS,CAAC,gCAAgC,CAAC,CAAA;QACvD,CAAC;QACD,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;YACtB,MAAM,IAAI,SAAS,CAAC,+BAA+B,CAAC,CAAA;QACtD,CAAC;QAED,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE;YAC1C,MAAM,EAAE,QAAQ,CAAC,MAAM;YACvB,UAAU,EAAE,QAAQ,CAAC,UAAU;YAC/B,OAAO,EAAE,QAAQ,CAAC,OAAO;SAC1B,CAAC,CAAA;QAEF,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAA;IAC3B,CAAC;IAED;;OAEG;IACH,IAAI,GAAG;QACL,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAA;IAC3B,CAAC;IACD,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,SAAS,CAAC,UAAU,CAAA;IAClC,CAAC;IACD,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAA;IAC5B,CAAC;IACD,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,SAAS,CAAC,UAAU,CAAA;IAClC,CAAC;CACF","sourcesContent":["export class TransformedResponse extends Response {\n #response: Response\n\n constructor(response: Response, transform: TransformStream) {\n if (!response.body) {\n throw new TypeError('Response body is not available')\n }\n if (response.bodyUsed) {\n throw new TypeError('Response body is already used')\n }\n\n super(response.body.pipeThrough(transform), {\n status: response.status,\n statusText: response.statusText,\n headers: response.headers,\n })\n\n this.#response = response\n }\n\n /**\n * Some props can't be set through ResponseInit, so we need to proxy them\n */\n get url() {\n return this.#response.url\n }\n get redirected() {\n return this.#response.redirected\n }\n get type() {\n return this.#response.type\n }\n get statusText() {\n return this.#response.statusText\n }\n}\n"]}
|
package/dist/util.js
CHANGED
|
@@ -1,13 +1,5 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
// @TODO: Move some of these to a shared package ?
|
|
3
|
-
|
|
4
|
-
exports.extractUrl = exports.MaxBytesTransformStream = exports.ifString = void 0;
|
|
5
|
-
exports.isIp = isIp;
|
|
6
|
-
exports.padLines = padLines;
|
|
7
|
-
exports.cancelBody = cancelBody;
|
|
8
|
-
exports.logCancellationError = logCancellationError;
|
|
9
|
-
exports.stringifyMessage = stringifyMessage;
|
|
10
|
-
function isIp(hostname) {
|
|
2
|
+
export function isIp(hostname) {
|
|
11
3
|
// IPv4
|
|
12
4
|
if (hostname.match(/^\d+\.\d+\.\d+\.\d+$/))
|
|
13
5
|
return true;
|
|
@@ -16,9 +8,8 @@ function isIp(hostname) {
|
|
|
16
8
|
return true;
|
|
17
9
|
return false;
|
|
18
10
|
}
|
|
19
|
-
const ifString = (v) => (typeof v === 'string' ? v : undefined);
|
|
20
|
-
|
|
21
|
-
class MaxBytesTransformStream extends TransformStream {
|
|
11
|
+
export const ifString = (v) => (typeof v === 'string' ? v : undefined);
|
|
12
|
+
export class MaxBytesTransformStream extends TransformStream {
|
|
22
13
|
constructor(maxBytes) {
|
|
23
14
|
// Note: negation accounts for invalid value types (NaN, non numbers)
|
|
24
15
|
if (!(maxBytes >= 0)) {
|
|
@@ -37,9 +28,8 @@ class MaxBytesTransformStream extends TransformStream {
|
|
|
37
28
|
});
|
|
38
29
|
}
|
|
39
30
|
}
|
|
40
|
-
exports.MaxBytesTransformStream = MaxBytesTransformStream;
|
|
41
31
|
const LINE_BREAK = /\r?\n/g;
|
|
42
|
-
function padLines(input, pad) {
|
|
32
|
+
export function padLines(input, pad) {
|
|
43
33
|
if (!input)
|
|
44
34
|
return input;
|
|
45
35
|
return pad + input.replace(LINE_BREAK, `$&${pad}`);
|
|
@@ -75,7 +65,7 @@ function padLines(input, pad) {
|
|
|
75
65
|
* await cancelBody(response, (err) => { throw err })
|
|
76
66
|
* ```
|
|
77
67
|
*/
|
|
78
|
-
async function cancelBody(body, onCancellationError) {
|
|
68
|
+
export async function cancelBody(body, onCancellationError) {
|
|
79
69
|
if (body.body &&
|
|
80
70
|
!body.bodyUsed &&
|
|
81
71
|
!body.body.locked &&
|
|
@@ -92,10 +82,10 @@ async function cancelBody(body, onCancellationError) {
|
|
|
92
82
|
}
|
|
93
83
|
}
|
|
94
84
|
}
|
|
95
|
-
function logCancellationError(err) {
|
|
85
|
+
export function logCancellationError(err) {
|
|
96
86
|
console.warn('Failed to cancel response body', err);
|
|
97
87
|
}
|
|
98
|
-
async function stringifyMessage(input) {
|
|
88
|
+
export async function stringifyMessage(input) {
|
|
99
89
|
try {
|
|
100
90
|
const headers = stringifyHeaders(input.headers);
|
|
101
91
|
const payload = await stringifyBody(input);
|
|
@@ -127,10 +117,9 @@ async function stringifyBody(body) {
|
|
|
127
117
|
return '[Body could not be read]';
|
|
128
118
|
}
|
|
129
119
|
}
|
|
130
|
-
const extractUrl = (input) => typeof input === 'string'
|
|
120
|
+
export const extractUrl = (input) => typeof input === 'string'
|
|
131
121
|
? new URL(input)
|
|
132
122
|
: input instanceof URL
|
|
133
123
|
? input
|
|
134
124
|
: new URL(input.url);
|
|
135
|
-
exports.extractUrl = extractUrl;
|
|
136
125
|
//# sourceMappingURL=util.js.map
|
package/dist/util.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"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","sourcesContent":["// @TODO: Move some of these to a shared package ?\n\nexport type JsonScalar = string | number | boolean | null\nexport type Json = JsonScalar | Json[] | { [key: string]: undefined | Json }\nexport type JsonObject = { [key: string]: Json }\nexport type JsonArray = Json[]\n\nexport type ThisParameterOverride<\n C,\n Fn extends (...a: any) => any,\n> = Fn extends (...args: infer P) => infer R\n ? ((this: C, ...args: P) => R) & {\n bind(context: C): (...args: P) => R\n }\n : never\n\nexport function isIp(hostname: string) {\n // IPv4\n if (hostname.match(/^\\d+\\.\\d+\\.\\d+\\.\\d+$/)) return true\n\n // IPv6\n if (hostname.startsWith('[') && hostname.endsWith(']')) return true\n\n return false\n}\n\nexport const ifString = <V>(v: V) => (typeof v === 'string' ? v : undefined)\n\nexport class MaxBytesTransformStream extends TransformStream<\n Uint8Array,\n Uint8Array\n> {\n constructor(maxBytes: number) {\n // Note: negation accounts for invalid value types (NaN, non numbers)\n if (!(maxBytes >= 0)) {\n throw new TypeError('maxBytes must be a non-negative number')\n }\n\n let bytesRead = 0\n\n super({\n transform: (\n chunk: Uint8Array,\n ctrl: TransformStreamDefaultController<Uint8Array>,\n ) => {\n if ((bytesRead += chunk.length) <= maxBytes) {\n ctrl.enqueue(chunk)\n } else {\n ctrl.error(new Error('Response too large'))\n }\n },\n })\n }\n}\n\nconst LINE_BREAK = /\\r?\\n/g\nexport function padLines(input: string, pad: string) {\n if (!input) return input\n return pad + input.replace(LINE_BREAK, `$&${pad}`)\n}\n\n/**\n * @param [onCancellationError] - Callback that will trigger to asynchronously\n * handle any error that occurs while cancelling the response body. Providing\n * this will speed up the process and avoid potential deadlocks. Defaults to\n * awaiting the cancellation operation. use `\"log\"` to log the error.\n * @see {@link https://undici.nodejs.org/#/?id=garbage-collection}\n * @note awaiting this function's result, when no `onCancellationError` is\n * provided, might result in a dead lock. Indeed, if the response was cloned(),\n * the response.body.cancel() method will not resolve until the other response's\n * body is consumed/cancelled.\n *\n * @example\n * ```ts\n * // Make sure response was not cloned, or that every cloned response was\n * // consumed/cancelled before awaiting this function's result.\n * await cancelBody(response)\n * ```\n * @example\n * ```ts\n * await cancelBody(response, (err) => {\n * // No biggie, let's just log the error\n * console.warn('Failed to cancel response body', err)\n * })\n * ```\n * @example\n * ```ts\n * // Will generate an \"unhandledRejection\" if an error occurs while cancelling\n * // the response body. This will likely crash the process.\n * await cancelBody(response, (err) => { throw err })\n * ```\n */\nexport async function cancelBody(\n body: Body,\n onCancellationError?: 'log' | ((err: unknown) => void),\n): Promise<void> {\n if (\n body.body &&\n !body.bodyUsed &&\n !body.body.locked &&\n // Support for alternative fetch implementations\n typeof body.body.cancel === 'function'\n ) {\n if (typeof onCancellationError === 'function') {\n void body.body.cancel().catch(onCancellationError)\n } else if (onCancellationError === 'log') {\n void body.body.cancel().catch(logCancellationError)\n } else {\n await body.body.cancel()\n }\n }\n}\n\nexport function logCancellationError(err: unknown): void {\n console.warn('Failed to cancel response body', err)\n}\n\nexport async function stringifyMessage(input: Body & { headers: Headers }) {\n try {\n const headers = stringifyHeaders(input.headers)\n const payload = await stringifyBody(input)\n return headers && payload ? `${headers}\\n${payload}` : headers || payload\n } finally {\n void cancelBody(input, 'log')\n }\n}\n\nfunction stringifyHeaders(headers: Headers) {\n return Array.from(headers)\n .map(([name, value]) => `${name}: ${value}`)\n .join('\\n')\n}\n\nasync function stringifyBody(body: Body) {\n try {\n const blob = await body.blob()\n if (blob.type?.startsWith('text/')) {\n const text = await blob.text()\n return JSON.stringify(text)\n }\n\n if (/application\\/(?:\\w+\\+)?json/.test(blob.type)) {\n const text = await blob.text()\n return text.includes('\\n') ? JSON.stringify(JSON.parse(text)) : text\n }\n\n return `[Body size: ${blob.size}, type: ${JSON.stringify(blob.type)} ]`\n } catch {\n return '[Body could not be read]'\n }\n}\n\nexport const extractUrl = (input: Request | string | URL) =>\n typeof input === 'string'\n ? new URL(input)\n : input instanceof URL\n ? input\n : new URL(input.url)\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atproto-labs/fetch",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0-next.0",
|
|
4
|
+
"engines": {
|
|
5
|
+
"node": ">=22"
|
|
6
|
+
},
|
|
4
7
|
"license": "MIT",
|
|
5
8
|
"description": "Isomorphic wrapper utilities for fetch API",
|
|
6
9
|
"keywords": [
|
|
@@ -13,9 +16,7 @@
|
|
|
13
16
|
"url": "https://github.com/bluesky-social/atproto",
|
|
14
17
|
"directory": "packages/internal/fetch"
|
|
15
18
|
},
|
|
16
|
-
"type": "
|
|
17
|
-
"main": "dist/index.js",
|
|
18
|
-
"types": "dist/index.d.ts",
|
|
19
|
+
"type": "module",
|
|
19
20
|
"exports": {
|
|
20
21
|
".": {
|
|
21
22
|
"types": "./dist/index.d.ts",
|
|
@@ -23,10 +24,10 @@
|
|
|
23
24
|
}
|
|
24
25
|
},
|
|
25
26
|
"dependencies": {
|
|
26
|
-
"@atproto-labs/pipe": "0.
|
|
27
|
+
"@atproto-labs/pipe": "^0.2.0-next.0"
|
|
27
28
|
},
|
|
28
29
|
"devDependencies": {
|
|
29
|
-
"typescript": "^
|
|
30
|
+
"typescript": "^6.0.3"
|
|
30
31
|
},
|
|
31
32
|
"scripts": {
|
|
32
33
|
"build": "tsc --build tsconfig.json"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["./src/fetch-error.ts","./src/fetch-request.ts","./src/fetch-response.ts","./src/fetch-wrap.ts","./src/fetch.ts","./src/index.ts","./src/transformed-response.ts","./src/util.ts"],"version":"
|
|
1
|
+
{"root":["./src/fetch-error.ts","./src/fetch-request.ts","./src/fetch-response.ts","./src/fetch-wrap.ts","./src/fetch.ts","./src/index.ts","./src/transformed-response.ts","./src/util.ts"],"version":"6.0.3"}
|