@doist/comms-sdk 0.7.0 → 0.7.1
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/dist/cjs/testUtils/msw-setup.js +14 -0
- package/dist/cjs/transport/fetch-with-retry.js +15 -5
- package/dist/cjs/transport/http-dispatcher.js +62 -26
- package/dist/esm/testUtils/msw-setup.js +15 -1
- package/dist/esm/transport/fetch-with-retry.js +16 -6
- package/dist/esm/transport/http-dispatcher.js +60 -26
- package/dist/types/transport/http-dispatcher.d.ts +36 -0
- package/package.json +1 -1
|
@@ -3,6 +3,20 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.server = void 0;
|
|
4
4
|
const node_1 = require("msw/node");
|
|
5
5
|
const vitest_1 = require("vitest");
|
|
6
|
+
// In production the transport uses undici's own `fetch` (paired with the
|
|
7
|
+
// dispatcher) so the request client and dispatcher stay on one undici version.
|
|
8
|
+
// MSW intercepts the *global* `fetch`, not that separate undici instance, so
|
|
9
|
+
// force the transport onto the global `fetch` for every test in the suite;
|
|
10
|
+
// MSW then intercepts requests as usual. The real undici transport is covered
|
|
11
|
+
// directly by `http-dispatcher.test.ts` and `fetch-with-retry.test.ts`, which
|
|
12
|
+
// opt out of this seam.
|
|
13
|
+
vitest_1.vi.mock('../transport/http-dispatcher', async (importOriginal) => {
|
|
14
|
+
const actual = await importOriginal();
|
|
15
|
+
return {
|
|
16
|
+
...actual,
|
|
17
|
+
getDefaultTransport: vitest_1.vi.fn(async () => undefined),
|
|
18
|
+
};
|
|
19
|
+
});
|
|
6
20
|
// Create MSW server instance
|
|
7
21
|
exports.server = (0, node_1.setupServer)();
|
|
8
22
|
// Start server before all tests
|
|
@@ -62,15 +62,25 @@ async function fetchWithRetry(url, options, maxRetries = 3, customFetch) {
|
|
|
62
62
|
throw new errors_1.CommsRequestError(lastError?.message ?? 'Request failed');
|
|
63
63
|
}
|
|
64
64
|
async function fetchWithDefaultTransport(url, options, signal) {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
65
|
+
// Read the dispatcher and its paired `fetch` as one value so they can never
|
|
66
|
+
// be mismatched. On Node, `fetch` is undici's own — paired with the
|
|
67
|
+
// dispatcher — so the request client and dispatcher stay on one undici
|
|
68
|
+
// version; otherwise the `decompress` interceptor terminates gzip responses
|
|
69
|
+
// when the global `fetch`'s bundled undici differs. Browser/edge (and Bun)
|
|
70
|
+
// have no paired `fetch` and fall back to the global one.
|
|
71
|
+
const transport = await (0, http_dispatcher_1.getDefaultTransport)();
|
|
72
|
+
// undici's `fetch` and the global `fetch` are the same function at runtime
|
|
73
|
+
// but carry different (undici vs DOM) `RequestInit`/`Response` types. Call
|
|
74
|
+
// through the global signature, which matches the global-typed `options`.
|
|
75
|
+
const fetchImpl = (transport?.fetch ?? fetch);
|
|
76
|
+
const response = transport?.dispatcher
|
|
77
|
+
? await fetchImpl(url, {
|
|
68
78
|
...options,
|
|
69
79
|
signal,
|
|
70
80
|
// @ts-expect-error - dispatcher is valid for Node.js fetch but not in TS types
|
|
71
|
-
dispatcher,
|
|
81
|
+
dispatcher: transport.dispatcher,
|
|
72
82
|
})
|
|
73
|
-
: await
|
|
83
|
+
: await fetchImpl(url, {
|
|
74
84
|
...options,
|
|
75
85
|
signal,
|
|
76
86
|
});
|
|
@@ -33,29 +33,39 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.getDefaultTransport = getDefaultTransport;
|
|
36
37
|
exports.getDefaultDispatcher = getDefaultDispatcher;
|
|
37
38
|
exports.closeDefaultDispatcher = closeDefaultDispatcher;
|
|
38
39
|
exports.resetDefaultDispatcherForTests = resetDefaultDispatcherForTests;
|
|
40
|
+
exports.getDefaultFetch = getDefaultFetch;
|
|
39
41
|
exports.suppressExperimentalWarningsSync = suppressExperimentalWarningsSync;
|
|
40
|
-
let
|
|
41
|
-
let
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
let defaultTransport;
|
|
43
|
+
let defaultTransportPromise;
|
|
44
|
+
/**
|
|
45
|
+
* The default dispatcher and its paired `fetch`, as a single value so the two
|
|
46
|
+
* are always read consistently. Resolves to `undefined` outside Node (browser/
|
|
47
|
+
* edge), where callers use the global `fetch` with no dispatcher.
|
|
48
|
+
*/
|
|
49
|
+
async function getDefaultTransport() {
|
|
50
|
+
if (defaultTransport) {
|
|
51
|
+
return defaultTransport;
|
|
45
52
|
}
|
|
46
|
-
if (!
|
|
47
|
-
|
|
48
|
-
.then((
|
|
49
|
-
|
|
50
|
-
return
|
|
53
|
+
if (!defaultTransportPromise) {
|
|
54
|
+
defaultTransportPromise = createDefaultTransport()
|
|
55
|
+
.then((transport) => {
|
|
56
|
+
defaultTransport = transport;
|
|
57
|
+
return transport;
|
|
51
58
|
})
|
|
52
59
|
.catch((error) => {
|
|
53
|
-
|
|
54
|
-
|
|
60
|
+
defaultTransport = undefined;
|
|
61
|
+
defaultTransportPromise = undefined;
|
|
55
62
|
throw error;
|
|
56
63
|
});
|
|
57
64
|
}
|
|
58
|
-
return
|
|
65
|
+
return defaultTransportPromise;
|
|
66
|
+
}
|
|
67
|
+
async function getDefaultDispatcher() {
|
|
68
|
+
return (await getDefaultTransport())?.dispatcher;
|
|
59
69
|
}
|
|
60
70
|
/**
|
|
61
71
|
* Drains the default dispatcher's connection pool. CLIs and scripts should
|
|
@@ -64,17 +74,17 @@ async function getDefaultDispatcher() {
|
|
|
64
74
|
*/
|
|
65
75
|
async function closeDefaultDispatcher() {
|
|
66
76
|
// Clear the singleton *before* awaiting init, so any concurrent
|
|
67
|
-
// `
|
|
77
|
+
// `getDefaultTransport()` after this point creates a fresh dispatcher
|
|
68
78
|
// instead of receiving a reference to the one we're about to close.
|
|
69
|
-
const initPromise =
|
|
70
|
-
|
|
71
|
-
|
|
79
|
+
const initPromise = defaultTransportPromise;
|
|
80
|
+
defaultTransport = undefined;
|
|
81
|
+
defaultTransportPromise = undefined;
|
|
72
82
|
if (!initPromise)
|
|
73
83
|
return;
|
|
74
84
|
try {
|
|
75
|
-
const
|
|
76
|
-
if (
|
|
77
|
-
await dispatcher.close();
|
|
85
|
+
const transport = await initPromise;
|
|
86
|
+
if (transport) {
|
|
87
|
+
await transport.dispatcher.close();
|
|
78
88
|
}
|
|
79
89
|
}
|
|
80
90
|
catch {
|
|
@@ -82,20 +92,39 @@ async function closeDefaultDispatcher() {
|
|
|
82
92
|
}
|
|
83
93
|
}
|
|
84
94
|
function resetDefaultDispatcherForTests() {
|
|
85
|
-
|
|
86
|
-
|
|
95
|
+
defaultTransport = undefined;
|
|
96
|
+
defaultTransportPromise = undefined;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* The `fetch` implementation that must be used with the default dispatcher.
|
|
100
|
+
* Returns undici's own `fetch` on the full-undici Node path, or `undefined`
|
|
101
|
+
* (meaning: use the global `fetch`) in the browser/edge/Bun paths.
|
|
102
|
+
*
|
|
103
|
+
* Node's global `fetch` is backed by whatever undici version ships inside that
|
|
104
|
+
* Node release (6.x on Node 22 … 8.x on Node 26). Our dispatcher — and its
|
|
105
|
+
* `decompress` interceptor — comes from the npm `undici` package, which is a
|
|
106
|
+
* different version. Handing an npm-undici dispatcher to a mismatched built-in
|
|
107
|
+
* client makes gzip responses fail mid-stream with `terminated`. Sourcing
|
|
108
|
+
* `fetch` from the same npm `undici` keeps the whole request path on one
|
|
109
|
+
* version and removes the split.
|
|
110
|
+
*
|
|
111
|
+
* Only meaningful after {@link getDefaultTransport} has resolved, which is the
|
|
112
|
+
* one place that populates it.
|
|
113
|
+
*/
|
|
114
|
+
function getDefaultFetch() {
|
|
115
|
+
return defaultTransport?.fetch;
|
|
87
116
|
}
|
|
88
117
|
function isNodeEnvironment() {
|
|
89
118
|
return typeof process !== 'undefined' && typeof process.versions?.node === 'string';
|
|
90
119
|
}
|
|
91
|
-
async function
|
|
120
|
+
async function createDefaultTransport() {
|
|
92
121
|
if (!isNodeEnvironment()) {
|
|
93
122
|
return undefined;
|
|
94
123
|
}
|
|
95
124
|
// Dynamic import so non-Node consumers (browser, edge runtimes) don't pull
|
|
96
125
|
// undici into their bundle. `isNodeEnvironment()` above already gated this
|
|
97
126
|
// branch, so undici is safe to load when we get here.
|
|
98
|
-
const { EnvHttpProxyAgent, interceptors } = await Promise.resolve().then(() => __importStar(require('undici')));
|
|
127
|
+
const { EnvHttpProxyAgent, interceptors, fetch: undiciFetch } = await Promise.resolve().then(() => __importStar(require('undici')));
|
|
99
128
|
// `EnvHttpProxyAgent` (with `allowH2`) and `interceptors.decompress()` both
|
|
100
129
|
// emit an ExperimentalWarning on first use, so build the whole dispatcher
|
|
101
130
|
// inside the suppression block.
|
|
@@ -112,14 +141,21 @@ async function createDefaultDispatcher() {
|
|
|
112
141
|
// crashing on the missing API. Optional chaining also guards a runtime
|
|
113
142
|
// that omits the `interceptors` export entirely.
|
|
114
143
|
if (typeof interceptors?.decompress !== 'function') {
|
|
115
|
-
|
|
144
|
+
// Bun: pair the agent with the global `fetch` (undefined), which
|
|
145
|
+
// decompresses natively.
|
|
146
|
+
return { dispatcher: agent, fetch: undefined };
|
|
116
147
|
}
|
|
117
148
|
// `interceptors.decompress()` decodes gzip/deflate/br/zstd bodies. On
|
|
118
149
|
// Node 24+, attaching any custom dispatcher to global `fetch` strips
|
|
119
150
|
// `content-encoding` without actually decompressing the body.
|
|
120
151
|
// See https://github.com/Doist/todoist-cli/issues/318.
|
|
121
152
|
const decompress = interceptors.decompress();
|
|
122
|
-
|
|
153
|
+
// Pair undici's own `fetch` with this dispatcher so the request client
|
|
154
|
+
// and the dispatcher stay on one undici version (see `getDefaultFetch`).
|
|
155
|
+
// The global `fetch` is backed by a different, Node-bundled undici;
|
|
156
|
+
// mixing the two makes the decompress interceptor terminate gzip
|
|
157
|
+
// responses on some Node versions.
|
|
158
|
+
return { dispatcher: agent.compose(decompress), fetch: undiciFetch };
|
|
123
159
|
});
|
|
124
160
|
}
|
|
125
161
|
// `suppressExperimentalWarningsSync` is exported for direct unit testing —
|
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
import { setupServer } from 'msw/node';
|
|
2
|
-
import { afterAll, afterEach, beforeAll } from 'vitest';
|
|
2
|
+
import { afterAll, afterEach, beforeAll, vi } from 'vitest';
|
|
3
|
+
// In production the transport uses undici's own `fetch` (paired with the
|
|
4
|
+
// dispatcher) so the request client and dispatcher stay on one undici version.
|
|
5
|
+
// MSW intercepts the *global* `fetch`, not that separate undici instance, so
|
|
6
|
+
// force the transport onto the global `fetch` for every test in the suite;
|
|
7
|
+
// MSW then intercepts requests as usual. The real undici transport is covered
|
|
8
|
+
// directly by `http-dispatcher.test.ts` and `fetch-with-retry.test.ts`, which
|
|
9
|
+
// opt out of this seam.
|
|
10
|
+
vi.mock('../transport/http-dispatcher', async (importOriginal) => {
|
|
11
|
+
const actual = await importOriginal();
|
|
12
|
+
return {
|
|
13
|
+
...actual,
|
|
14
|
+
getDefaultTransport: vi.fn(async () => undefined),
|
|
15
|
+
};
|
|
16
|
+
});
|
|
3
17
|
// Create MSW server instance
|
|
4
18
|
export const server = setupServer();
|
|
5
19
|
// Start server before all tests
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { CommsRequestError } from '../types/errors.js';
|
|
2
2
|
import { camelCaseKeys } from '../utils/case-conversion.js';
|
|
3
3
|
import { transformTimestamps } from '../utils/timestamp-conversion.js';
|
|
4
|
-
import {
|
|
4
|
+
import { getDefaultTransport } from './http-dispatcher.js';
|
|
5
5
|
export async function fetchWithRetry(url, options, maxRetries = 3, customFetch) {
|
|
6
6
|
let lastError;
|
|
7
7
|
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
@@ -59,15 +59,25 @@ export async function fetchWithRetry(url, options, maxRetries = 3, customFetch)
|
|
|
59
59
|
throw new CommsRequestError(lastError?.message ?? 'Request failed');
|
|
60
60
|
}
|
|
61
61
|
async function fetchWithDefaultTransport(url, options, signal) {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
62
|
+
// Read the dispatcher and its paired `fetch` as one value so they can never
|
|
63
|
+
// be mismatched. On Node, `fetch` is undici's own — paired with the
|
|
64
|
+
// dispatcher — so the request client and dispatcher stay on one undici
|
|
65
|
+
// version; otherwise the `decompress` interceptor terminates gzip responses
|
|
66
|
+
// when the global `fetch`'s bundled undici differs. Browser/edge (and Bun)
|
|
67
|
+
// have no paired `fetch` and fall back to the global one.
|
|
68
|
+
const transport = await getDefaultTransport();
|
|
69
|
+
// undici's `fetch` and the global `fetch` are the same function at runtime
|
|
70
|
+
// but carry different (undici vs DOM) `RequestInit`/`Response` types. Call
|
|
71
|
+
// through the global signature, which matches the global-typed `options`.
|
|
72
|
+
const fetchImpl = (transport?.fetch ?? fetch);
|
|
73
|
+
const response = transport?.dispatcher
|
|
74
|
+
? await fetchImpl(url, {
|
|
65
75
|
...options,
|
|
66
76
|
signal,
|
|
67
77
|
// @ts-expect-error - dispatcher is valid for Node.js fetch but not in TS types
|
|
68
|
-
dispatcher,
|
|
78
|
+
dispatcher: transport.dispatcher,
|
|
69
79
|
})
|
|
70
|
-
: await
|
|
80
|
+
: await fetchImpl(url, {
|
|
71
81
|
...options,
|
|
72
82
|
signal,
|
|
73
83
|
});
|
|
@@ -1,22 +1,30 @@
|
|
|
1
|
-
let
|
|
2
|
-
let
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
let defaultTransport;
|
|
2
|
+
let defaultTransportPromise;
|
|
3
|
+
/**
|
|
4
|
+
* The default dispatcher and its paired `fetch`, as a single value so the two
|
|
5
|
+
* are always read consistently. Resolves to `undefined` outside Node (browser/
|
|
6
|
+
* edge), where callers use the global `fetch` with no dispatcher.
|
|
7
|
+
*/
|
|
8
|
+
export async function getDefaultTransport() {
|
|
9
|
+
if (defaultTransport) {
|
|
10
|
+
return defaultTransport;
|
|
6
11
|
}
|
|
7
|
-
if (!
|
|
8
|
-
|
|
9
|
-
.then((
|
|
10
|
-
|
|
11
|
-
return
|
|
12
|
+
if (!defaultTransportPromise) {
|
|
13
|
+
defaultTransportPromise = createDefaultTransport()
|
|
14
|
+
.then((transport) => {
|
|
15
|
+
defaultTransport = transport;
|
|
16
|
+
return transport;
|
|
12
17
|
})
|
|
13
18
|
.catch((error) => {
|
|
14
|
-
|
|
15
|
-
|
|
19
|
+
defaultTransport = undefined;
|
|
20
|
+
defaultTransportPromise = undefined;
|
|
16
21
|
throw error;
|
|
17
22
|
});
|
|
18
23
|
}
|
|
19
|
-
return
|
|
24
|
+
return defaultTransportPromise;
|
|
25
|
+
}
|
|
26
|
+
export async function getDefaultDispatcher() {
|
|
27
|
+
return (await getDefaultTransport())?.dispatcher;
|
|
20
28
|
}
|
|
21
29
|
/**
|
|
22
30
|
* Drains the default dispatcher's connection pool. CLIs and scripts should
|
|
@@ -25,17 +33,17 @@ export async function getDefaultDispatcher() {
|
|
|
25
33
|
*/
|
|
26
34
|
export async function closeDefaultDispatcher() {
|
|
27
35
|
// Clear the singleton *before* awaiting init, so any concurrent
|
|
28
|
-
// `
|
|
36
|
+
// `getDefaultTransport()` after this point creates a fresh dispatcher
|
|
29
37
|
// instead of receiving a reference to the one we're about to close.
|
|
30
|
-
const initPromise =
|
|
31
|
-
|
|
32
|
-
|
|
38
|
+
const initPromise = defaultTransportPromise;
|
|
39
|
+
defaultTransport = undefined;
|
|
40
|
+
defaultTransportPromise = undefined;
|
|
33
41
|
if (!initPromise)
|
|
34
42
|
return;
|
|
35
43
|
try {
|
|
36
|
-
const
|
|
37
|
-
if (
|
|
38
|
-
await dispatcher.close();
|
|
44
|
+
const transport = await initPromise;
|
|
45
|
+
if (transport) {
|
|
46
|
+
await transport.dispatcher.close();
|
|
39
47
|
}
|
|
40
48
|
}
|
|
41
49
|
catch {
|
|
@@ -43,20 +51,39 @@ export async function closeDefaultDispatcher() {
|
|
|
43
51
|
}
|
|
44
52
|
}
|
|
45
53
|
export function resetDefaultDispatcherForTests() {
|
|
46
|
-
|
|
47
|
-
|
|
54
|
+
defaultTransport = undefined;
|
|
55
|
+
defaultTransportPromise = undefined;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* The `fetch` implementation that must be used with the default dispatcher.
|
|
59
|
+
* Returns undici's own `fetch` on the full-undici Node path, or `undefined`
|
|
60
|
+
* (meaning: use the global `fetch`) in the browser/edge/Bun paths.
|
|
61
|
+
*
|
|
62
|
+
* Node's global `fetch` is backed by whatever undici version ships inside that
|
|
63
|
+
* Node release (6.x on Node 22 … 8.x on Node 26). Our dispatcher — and its
|
|
64
|
+
* `decompress` interceptor — comes from the npm `undici` package, which is a
|
|
65
|
+
* different version. Handing an npm-undici dispatcher to a mismatched built-in
|
|
66
|
+
* client makes gzip responses fail mid-stream with `terminated`. Sourcing
|
|
67
|
+
* `fetch` from the same npm `undici` keeps the whole request path on one
|
|
68
|
+
* version and removes the split.
|
|
69
|
+
*
|
|
70
|
+
* Only meaningful after {@link getDefaultTransport} has resolved, which is the
|
|
71
|
+
* one place that populates it.
|
|
72
|
+
*/
|
|
73
|
+
export function getDefaultFetch() {
|
|
74
|
+
return defaultTransport?.fetch;
|
|
48
75
|
}
|
|
49
76
|
function isNodeEnvironment() {
|
|
50
77
|
return typeof process !== 'undefined' && typeof process.versions?.node === 'string';
|
|
51
78
|
}
|
|
52
|
-
async function
|
|
79
|
+
async function createDefaultTransport() {
|
|
53
80
|
if (!isNodeEnvironment()) {
|
|
54
81
|
return undefined;
|
|
55
82
|
}
|
|
56
83
|
// Dynamic import so non-Node consumers (browser, edge runtimes) don't pull
|
|
57
84
|
// undici into their bundle. `isNodeEnvironment()` above already gated this
|
|
58
85
|
// branch, so undici is safe to load when we get here.
|
|
59
|
-
const { EnvHttpProxyAgent, interceptors } = await import('undici');
|
|
86
|
+
const { EnvHttpProxyAgent, interceptors, fetch: undiciFetch } = await import('undici');
|
|
60
87
|
// `EnvHttpProxyAgent` (with `allowH2`) and `interceptors.decompress()` both
|
|
61
88
|
// emit an ExperimentalWarning on first use, so build the whole dispatcher
|
|
62
89
|
// inside the suppression block.
|
|
@@ -73,14 +100,21 @@ async function createDefaultDispatcher() {
|
|
|
73
100
|
// crashing on the missing API. Optional chaining also guards a runtime
|
|
74
101
|
// that omits the `interceptors` export entirely.
|
|
75
102
|
if (typeof interceptors?.decompress !== 'function') {
|
|
76
|
-
|
|
103
|
+
// Bun: pair the agent with the global `fetch` (undefined), which
|
|
104
|
+
// decompresses natively.
|
|
105
|
+
return { dispatcher: agent, fetch: undefined };
|
|
77
106
|
}
|
|
78
107
|
// `interceptors.decompress()` decodes gzip/deflate/br/zstd bodies. On
|
|
79
108
|
// Node 24+, attaching any custom dispatcher to global `fetch` strips
|
|
80
109
|
// `content-encoding` without actually decompressing the body.
|
|
81
110
|
// See https://github.com/Doist/todoist-cli/issues/318.
|
|
82
111
|
const decompress = interceptors.decompress();
|
|
83
|
-
|
|
112
|
+
// Pair undici's own `fetch` with this dispatcher so the request client
|
|
113
|
+
// and the dispatcher stay on one undici version (see `getDefaultFetch`).
|
|
114
|
+
// The global `fetch` is backed by a different, Node-bundled undici;
|
|
115
|
+
// mixing the two makes the decompress interceptor terminate gzip
|
|
116
|
+
// responses on some Node versions.
|
|
117
|
+
return { dispatcher: agent.compose(decompress), fetch: undiciFetch };
|
|
84
118
|
});
|
|
85
119
|
}
|
|
86
120
|
// `suppressExperimentalWarningsSync` is exported for direct unit testing —
|
|
@@ -1,4 +1,22 @@
|
|
|
1
1
|
import type { Dispatcher } from 'undici';
|
|
2
|
+
type UndiciFetch = typeof import('undici').fetch;
|
|
3
|
+
/**
|
|
4
|
+
* A dispatcher and the `fetch` that must be used with it. `fetch` is undici's
|
|
5
|
+
* own `fetch` on the full-undici Node path, or `undefined` (meaning: use the
|
|
6
|
+
* global `fetch`) on the Bun path. The two are cached together so callers can
|
|
7
|
+
* never observe a dispatcher paired with a mismatched `fetch` — see
|
|
8
|
+
* {@link getDefaultFetch} for why the pairing matters.
|
|
9
|
+
*/
|
|
10
|
+
type DefaultTransport = {
|
|
11
|
+
dispatcher: Dispatcher;
|
|
12
|
+
fetch: UndiciFetch | undefined;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* The default dispatcher and its paired `fetch`, as a single value so the two
|
|
16
|
+
* are always read consistently. Resolves to `undefined` outside Node (browser/
|
|
17
|
+
* edge), where callers use the global `fetch` with no dispatcher.
|
|
18
|
+
*/
|
|
19
|
+
export declare function getDefaultTransport(): Promise<DefaultTransport | undefined>;
|
|
2
20
|
export declare function getDefaultDispatcher(): Promise<Dispatcher | undefined>;
|
|
3
21
|
/**
|
|
4
22
|
* Drains the default dispatcher's connection pool. CLIs and scripts should
|
|
@@ -7,4 +25,22 @@ export declare function getDefaultDispatcher(): Promise<Dispatcher | undefined>;
|
|
|
7
25
|
*/
|
|
8
26
|
export declare function closeDefaultDispatcher(): Promise<void>;
|
|
9
27
|
export declare function resetDefaultDispatcherForTests(): void;
|
|
28
|
+
/**
|
|
29
|
+
* The `fetch` implementation that must be used with the default dispatcher.
|
|
30
|
+
* Returns undici's own `fetch` on the full-undici Node path, or `undefined`
|
|
31
|
+
* (meaning: use the global `fetch`) in the browser/edge/Bun paths.
|
|
32
|
+
*
|
|
33
|
+
* Node's global `fetch` is backed by whatever undici version ships inside that
|
|
34
|
+
* Node release (6.x on Node 22 … 8.x on Node 26). Our dispatcher — and its
|
|
35
|
+
* `decompress` interceptor — comes from the npm `undici` package, which is a
|
|
36
|
+
* different version. Handing an npm-undici dispatcher to a mismatched built-in
|
|
37
|
+
* client makes gzip responses fail mid-stream with `terminated`. Sourcing
|
|
38
|
+
* `fetch` from the same npm `undici` keeps the whole request path on one
|
|
39
|
+
* version and removes the split.
|
|
40
|
+
*
|
|
41
|
+
* Only meaningful after {@link getDefaultTransport} has resolved, which is the
|
|
42
|
+
* one place that populates it.
|
|
43
|
+
*/
|
|
44
|
+
export declare function getDefaultFetch(): UndiciFetch | undefined;
|
|
10
45
|
export declare function suppressExperimentalWarningsSync<T>(fn: () => T): T;
|
|
46
|
+
export {};
|