@openclaw/discord 2026.6.33 → 2026.6.35
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/action-runtime-api.js +1 -1
- package/dist/{api-CjnGBhM3.js → api-1GXlSrYP.js} +42 -21
- package/dist/api.js +14 -14
- package/dist/{approval-handler.runtime-BWPQrzpP.js → approval-handler.runtime-Dv4p7REU.js} +3 -3
- package/dist/{audit-BwJ_2OjL.js → audit-DEVi9nIs.js} +3 -3
- package/dist/{channel-Ddnonoy4.js → channel-CQIRiosn.js} +15 -15
- package/dist/{channel-actions-CwmIqnYN.js → channel-actions-JziPEcBU.js} +2 -2
- package/dist/{channel-actions.runtime-DvpTfaJ4.js → channel-actions.runtime-D7L47LY3.js} +5 -5
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel.setup-glZ5Y98a.js → channel.setup-oMeR19Cc.js} +2 -2
- package/dist/{components-j6lTZBsT.js → components-_s5UPJqU.js} +1 -1
- package/dist/{conversation-identity-36FFBwm5.js → conversation-identity-B0k94-bz.js} +2 -2
- package/dist/{directory-config-BYMFzL29.js → directory-config-CD1svkyN.js} +1 -1
- package/dist/directory-contract-api.js +1 -1
- package/dist/{directory-live-9JtJCiu8.js → directory-live-DBTsSRxl.js} +5 -5
- package/dist/{handle-action.guild-admin-xxGYrp-I.js → handle-action.guild-admin-CYIFMxh-.js} +2 -2
- package/dist/index.js +1 -1
- package/dist/{manager.runtime-BK6cf2Zu.js → manager.runtime-BZVdGX2d.js} +17 -9
- package/dist/{message-handler-BqpJIavO.js → message-handler-DZd9Bpq8.js} +7 -6
- package/dist/{message-handler.preflight-C90MxCcv.js → message-handler.preflight-Axv9J9EO.js} +12 -11
- package/dist/{message-handler.process-CeQ7Bd_3.js → message-handler.process-CG0zFS-Z.js} +10 -10
- package/dist/{message-utils-CJeAoISH.js → message-utils-Dbuw27gd.js} +1 -1
- package/dist/{outbound-adapter-Dxs6iKEq.js → outbound-adapter-CKC_kmUN.js} +6 -6
- package/dist/pluralkit-CfTReLl3.js +40 -0
- package/dist/{probe-esE_Oqdm.js → probe-DcgZIpyF.js} +3 -2
- package/dist/{probe.runtime-C3Atgpvr.js → probe.runtime-CVwM9L5E.js} +1 -1
- package/dist/{provider-C7376XFH.js → provider-CwwSXIIj.js} +102 -37
- package/dist/{provider-session.runtime-CCdqogGf.js → provider-session.runtime-reBWkqHZ.js} +3 -3
- package/dist/provider.runtime-BsmTLYS_.js +2 -0
- package/dist/{resolve-allowlist-common-3gB2Gpmm.js → resolve-allowlist-common-D7bZqAw3.js} +3 -3
- package/dist/{resolve-channels-B3gQf8QL.js → resolve-channels--oE-RnO6.js} +6 -6
- package/dist/{resolve-users-BO10y5fJ.js → resolve-users-QXo8CXBU.js} +5 -5
- package/dist/{runtime-CFlR3L9X.js → runtime-CF7ramAs.js} +7 -7
- package/dist/runtime-api.actions.js +2 -2
- package/dist/runtime-api.js +19 -19
- package/dist/runtime-api.lookup.js +5 -5
- package/dist/runtime-api.monitor-CzF8MUl_.js +6 -0
- package/dist/runtime-api.monitor.js +5 -5
- package/dist/runtime-api.send.js +5 -5
- package/dist/runtime-api.threads.js +3 -3
- package/dist/{send-JHxfT4Pk.js → send-Bb295iHT.js} +5 -5
- package/dist/{send.components-CN35E2Ck.js → send.components-COkDUO3B.js} +4 -4
- package/dist/{send.outbound-B-cA1Esv.js → send.outbound-B_sk0hNe.js} +3 -3
- package/dist/{send.receipt-CGecJDin.js → send.receipt-Cli6_9Sn.js} +19 -7
- package/dist/{send.shared-vcbfThdy.js → send.shared-BCG7MWnP.js} +2 -2
- package/dist/session-binding-contract-api.js +1 -1
- package/dist/setup-plugin-api.js +1 -1
- package/dist/{subagent-hooks-20wXhVzZ.js → subagent-hooks-CtqoWK4x.js} +2 -2
- package/dist/subagent-hooks-api.js +1 -1
- package/dist/{system-events-DR27TE7p.js → system-events-BxGNk_wE.js} +1 -1
- package/dist/{target-resolver-CDi1gI90.js → target-resolver-BcoK6b0g.js} +2 -2
- package/dist/targets-Q-ZoP7K4.js +3 -0
- package/dist/{thread-bindings-DU4T6nDo.js → thread-bindings-DJ_HT6GJ.js} +4 -4
- package/dist/{thread-bindings.discord-api-CYkr-3Gj.js → thread-bindings.discord-api-OPyjvgyz.js} +4 -4
- package/dist/{thread-bindings.manager-BqWs1UE2.js → thread-bindings.manager-Cd2HAVw_.js} +3 -3
- package/dist/{transcripts-source-D-lBI5ZD.js → transcripts-source-CPf5gURy.js} +1 -1
- package/dist/transcripts-source-api.js +1 -1
- package/dist/{typing-xr05bL-r.js → typing-DY0cwLdg.js} +1 -1
- package/node_modules/undici/README.md +8 -2
- package/node_modules/undici/docs/docs/api/Agent.md +248 -44
- package/node_modules/undici/docs/docs/api/BalancedPool.md +246 -48
- package/node_modules/undici/docs/docs/api/CacheStorage.md +171 -13
- package/node_modules/undici/docs/docs/api/CacheStore.md +294 -98
- package/node_modules/undici/docs/docs/api/Client.md +386 -179
- package/node_modules/undici/docs/docs/api/ClientStats.md +80 -14
- package/node_modules/undici/docs/docs/api/Connector.md +118 -36
- package/node_modules/undici/docs/docs/api/ContentType.md +65 -25
- package/node_modules/undici/docs/docs/api/Cookies.md +122 -71
- package/node_modules/undici/docs/docs/api/Debug.md +34 -18
- package/node_modules/undici/docs/docs/api/DiagnosticsChannel.md +364 -164
- package/node_modules/undici/docs/docs/api/Dispatcher.md +485 -1102
- package/node_modules/undici/docs/docs/api/EnvHttpProxyAgent.md +102 -87
- package/node_modules/undici/docs/docs/api/Errors.md +503 -40
- package/node_modules/undici/docs/docs/api/EventSource.md +298 -32
- package/node_modules/undici/docs/docs/api/Fetch.md +680 -31
- package/node_modules/undici/docs/docs/api/GlobalInstallation.md +78 -98
- package/node_modules/undici/docs/docs/api/H2CClient.md +298 -176
- package/node_modules/undici/docs/docs/api/Interceptors.md +418 -0
- package/node_modules/undici/docs/docs/api/MockAgent.md +333 -314
- package/node_modules/undici/docs/docs/api/MockCallHistory.md +272 -98
- package/node_modules/undici/docs/docs/api/MockCallHistoryLog.md +189 -26
- package/node_modules/undici/docs/docs/api/MockClient.md +151 -33
- package/node_modules/undici/docs/docs/api/MockErrors.md +56 -5
- package/node_modules/undici/docs/docs/api/MockPool.md +321 -258
- package/node_modules/undici/docs/docs/api/Pool.md +235 -43
- package/node_modules/undici/docs/docs/api/PoolStats.md +119 -13
- package/node_modules/undici/docs/docs/api/ProxyAgent.md +179 -160
- package/node_modules/undici/docs/docs/api/RedirectHandler.md +238 -63
- package/node_modules/undici/docs/docs/api/RetryAgent.md +113 -26
- package/node_modules/undici/docs/docs/api/RetryHandler.md +161 -77
- package/node_modules/undici/docs/docs/api/RoundRobinPool.md +166 -72
- package/node_modules/undici/docs/docs/api/SnapshotAgent.md +264 -542
- package/node_modules/undici/docs/docs/api/Socks5ProxyAgent.md +177 -196
- package/node_modules/undici/docs/docs/api/Util.md +68 -11
- package/node_modules/undici/docs/docs/api/WebSocket.md +475 -80
- package/node_modules/undici/docs/docs/api/api-lifecycle.md +100 -32
- package/node_modules/undici/docs/docs/best-practices/client-certificate.md +2 -0
- package/node_modules/undici/docs/docs/best-practices/crawling.md +3 -1
- package/node_modules/undici/docs/docs/best-practices/migrating-from-v7-to-v8.md +6 -4
- package/node_modules/undici/docs/docs/best-practices/mocking-request.md +9 -7
- package/node_modules/undici/docs/docs/best-practices/proxy.md +3 -1
- package/node_modules/undici/docs/docs/best-practices/undici-vs-builtin-fetch.md +10 -8
- package/node_modules/undici/docs/docs/best-practices/writing-tests.md +2 -0
- package/node_modules/undici/docs/docs/{GettingStarted.md → getting-started.md} +22 -19
- package/node_modules/undici/docs/docs/index.md +784 -0
- package/node_modules/undici/docs/docs/site.json +125 -0
- package/node_modules/undici/docs/docs/type-map.json +79 -0
- package/node_modules/undici/lib/api/api-request.js +7 -1
- package/node_modules/undici/lib/api/readable.js +42 -7
- package/node_modules/undici/lib/cache/memory-cache-store.js +56 -11
- package/node_modules/undici/lib/cache/sqlite-cache-store.js +7 -1
- package/node_modules/undici/lib/core/connect.js +16 -2
- package/node_modules/undici/lib/core/errors.js +20 -0
- package/node_modules/undici/lib/core/request.js +14 -3
- package/node_modules/undici/lib/core/symbols.js +3 -0
- package/node_modules/undici/lib/core/util.js +30 -2
- package/node_modules/undici/lib/dispatcher/agent.js +10 -5
- package/node_modules/undici/lib/dispatcher/balanced-pool.js +7 -4
- package/node_modules/undici/lib/dispatcher/client-h1.js +74 -9
- package/node_modules/undici/lib/dispatcher/client-h2.js +483 -151
- package/node_modules/undici/lib/dispatcher/client.js +76 -30
- package/node_modules/undici/lib/dispatcher/dispatcher-base.js +13 -1
- package/node_modules/undici/lib/dispatcher/dispatcher.js +15 -1
- package/node_modules/undici/lib/dispatcher/dispatcher1-wrapper.js +3 -0
- package/node_modules/undici/lib/dispatcher/env-http-proxy-agent.js +37 -8
- package/node_modules/undici/lib/dispatcher/proxy-agent.js +58 -7
- package/node_modules/undici/lib/dispatcher/retry-agent.js +3 -0
- package/node_modules/undici/lib/dispatcher/round-robin-pool.js +1 -1
- package/node_modules/undici/lib/dispatcher/socks5-proxy-agent.js +106 -22
- package/node_modules/undici/lib/global.js +36 -16
- package/node_modules/undici/lib/handler/cache-handler.js +297 -65
- package/node_modules/undici/lib/handler/cache-revalidation-handler.js +13 -3
- package/node_modules/undici/lib/handler/decorator-handler.js +7 -1
- package/node_modules/undici/lib/handler/deduplication-handler.js +12 -6
- package/node_modules/undici/lib/handler/redirect-handler.js +26 -5
- package/node_modules/undici/lib/handler/retry-handler.js +238 -51
- package/node_modules/undici/lib/interceptor/cache.js +221 -58
- package/node_modules/undici/lib/interceptor/decompress.js +124 -15
- package/node_modules/undici/lib/interceptor/deduplicate.js +5 -4
- package/node_modules/undici/lib/interceptor/dns.js +7 -0
- package/node_modules/undici/lib/interceptor/dump.js +10 -23
- package/node_modules/undici/lib/mock/mock-agent.js +13 -1
- package/node_modules/undici/lib/mock/mock-interceptor.js +25 -7
- package/node_modules/undici/lib/mock/mock-utils.js +246 -27
- package/node_modules/undici/lib/util/cache.js +415 -71
- package/node_modules/undici/lib/util/date.js +23 -6
- package/node_modules/undici/lib/web/cookies/parse.js +150 -146
- package/node_modules/undici/lib/web/cookies/util.js +79 -9
- package/node_modules/undici/lib/web/eventsource/eventsource-stream.js +28 -1
- package/node_modules/undici/lib/web/eventsource/eventsource.js +13 -3
- package/node_modules/undici/lib/web/eventsource/util.js +1 -1
- package/node_modules/undici/lib/web/fetch/body.js +2 -1
- package/node_modules/undici/lib/web/fetch/constants.js +1 -1
- package/node_modules/undici/lib/web/fetch/index.js +17 -2
- package/node_modules/undici/lib/web/fetch/request.js +2 -3
- package/node_modules/undici/lib/web/fetch/response.js +1 -3
- package/node_modules/undici/lib/web/fetch/util.js +10 -2
- package/node_modules/undici/lib/web/webidl/index.js +3 -3
- package/node_modules/undici/lib/web/websocket/connection.js +1 -1
- package/node_modules/undici/lib/web/websocket/permessage-deflate.js +5 -0
- package/node_modules/undici/lib/web/websocket/stream/websocketstream.js +8 -10
- package/node_modules/undici/lib/web/websocket/websocket.js +22 -0
- package/node_modules/undici/package.json +4 -4
- package/node_modules/undici/types/client.d.ts +53 -3
- package/node_modules/undici/types/cookies.d.ts +1 -1
- package/node_modules/undici/types/dispatcher.d.ts +3 -3
- package/node_modules/undici/types/errors.d.ts +10 -0
- package/node_modules/undici/types/handlers.d.ts +2 -0
- package/node_modules/undici/types/interceptors.d.ts +2 -0
- package/node_modules/undici/types/mock-agent.d.ts +11 -10
- package/node_modules/undici/types/mock-interceptor.d.ts +5 -1
- package/node_modules/undici/types/proxy-agent.d.ts +7 -0
- package/node_modules/undici/types/socks5-proxy-agent.d.ts +2 -0
- package/npm-shrinkwrap.json +7 -7
- package/package.json +6 -5
- package/dist/pluralkit-DI6RYaVj.js +0 -24
- package/dist/provider.runtime-D1m66kDS.js +0 -2
- package/dist/runtime-api.monitor-4oc58TSk.js +0 -6
- package/dist/targets-C6yd3y8R.js +0 -3
|
@@ -3,6 +3,7 @@ const { isIP } = require('node:net')
|
|
|
3
3
|
const { lookup } = require('node:dns')
|
|
4
4
|
const DecoratorHandler = require('../handler/decorator-handler')
|
|
5
5
|
const { InvalidArgumentError, InformationalError } = require('../core/errors')
|
|
6
|
+
const { kRequestOrigin } = require('../core/symbols')
|
|
6
7
|
const maxInt = Math.pow(2, 31) - 1
|
|
7
8
|
|
|
8
9
|
function hasSafeIterator (headers) {
|
|
@@ -434,6 +435,9 @@ class DNSDispatchHandler extends DecoratorHandler {
|
|
|
434
435
|
origin: `${this.#origin.protocol}//${
|
|
435
436
|
ip.family === 6 ? `[${ip.address}]` : ip.address
|
|
436
437
|
}${port}`,
|
|
438
|
+
[kRequestOrigin]: this.#opts[kRequestOrigin] === undefined
|
|
439
|
+
? this.#origin
|
|
440
|
+
: this.#opts[kRequestOrigin],
|
|
437
441
|
headers: withHostHeader(this.#origin.host, this.#opts.headers)
|
|
438
442
|
}
|
|
439
443
|
this.#dispatch(dispatchOpts, this)
|
|
@@ -557,6 +561,9 @@ module.exports = interceptorOpts => {
|
|
|
557
561
|
...origDispatchOpts,
|
|
558
562
|
servername: origin.hostname, // For SNI on TLS
|
|
559
563
|
origin: newOrigin.origin,
|
|
564
|
+
[kRequestOrigin]: origDispatchOpts[kRequestOrigin] === undefined
|
|
565
|
+
? origin
|
|
566
|
+
: origDispatchOpts[kRequestOrigin],
|
|
560
567
|
headers: withHostHeader(origin.host, origDispatchOpts.headers)
|
|
561
568
|
}
|
|
562
569
|
|
|
@@ -7,7 +7,6 @@ class DumpHandler extends DecoratorHandler {
|
|
|
7
7
|
#maxSize = 1024 * 1024
|
|
8
8
|
#dumped = false
|
|
9
9
|
#size = 0
|
|
10
|
-
#controller = null
|
|
11
10
|
aborted = false
|
|
12
11
|
reason = false
|
|
13
12
|
|
|
@@ -29,7 +28,6 @@ class DumpHandler extends DecoratorHandler {
|
|
|
29
28
|
|
|
30
29
|
onRequestStart (controller, context) {
|
|
31
30
|
controller.abort = this.#abort.bind(this)
|
|
32
|
-
this.#controller = controller
|
|
33
31
|
|
|
34
32
|
return super.onRequestStart(controller, context)
|
|
35
33
|
}
|
|
@@ -53,43 +51,32 @@ class DumpHandler extends DecoratorHandler {
|
|
|
53
51
|
}
|
|
54
52
|
|
|
55
53
|
onResponseError (controller, err) {
|
|
56
|
-
|
|
57
|
-
return
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// On network errors before connect, controller will be null
|
|
61
|
-
err = this.#controller?.reason ?? err
|
|
62
|
-
|
|
63
|
-
super.onResponseError(controller, err)
|
|
54
|
+
super.onResponseError(controller, this.aborted === true ? this.reason : err)
|
|
64
55
|
}
|
|
65
56
|
|
|
66
57
|
onResponseData (controller, chunk) {
|
|
67
58
|
this.#size = this.#size + chunk.length
|
|
68
59
|
|
|
69
|
-
if (this.#size
|
|
70
|
-
|
|
60
|
+
if (this.#size > this.#maxSize) {
|
|
61
|
+
throw new RequestAbortedError(
|
|
62
|
+
`Response size (${this.#size}) larger than maxSize (${this.#maxSize})`
|
|
63
|
+
)
|
|
64
|
+
}
|
|
71
65
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
} else {
|
|
75
|
-
super.onResponseEnd(controller, {})
|
|
76
|
-
}
|
|
66
|
+
if (this.#size === this.#maxSize) {
|
|
67
|
+
this.#dumped = true
|
|
77
68
|
}
|
|
78
69
|
|
|
79
70
|
return true
|
|
80
71
|
}
|
|
81
72
|
|
|
82
73
|
onResponseEnd (controller, trailers) {
|
|
83
|
-
if (this
|
|
84
|
-
return
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
if (this.#controller.aborted === true) {
|
|
74
|
+
if (this.aborted === true) {
|
|
88
75
|
super.onResponseError(controller, this.reason)
|
|
89
76
|
return
|
|
90
77
|
}
|
|
91
78
|
|
|
92
|
-
super.onResponseEnd(controller, trailers)
|
|
79
|
+
super.onResponseEnd(controller, this.#dumped ? {} : trailers)
|
|
93
80
|
}
|
|
94
81
|
}
|
|
95
82
|
|
|
@@ -73,7 +73,7 @@ class MockAgent extends Dispatcher {
|
|
|
73
73
|
opts.origin = normalizeOrigin(opts.origin)
|
|
74
74
|
|
|
75
75
|
// Call MockAgent.get to perform additional setup before dispatching as normal
|
|
76
|
-
this.get(opts.origin)
|
|
76
|
+
const mockDispatcher = this.get(opts.origin)
|
|
77
77
|
|
|
78
78
|
this[kMockAgentAddCallHistoryLog](opts)
|
|
79
79
|
|
|
@@ -81,6 +81,18 @@ class MockAgent extends Dispatcher {
|
|
|
81
81
|
|
|
82
82
|
const dispatchOpts = { ...opts }
|
|
83
83
|
|
|
84
|
+
// Agent keeps HTTP/1.1-only dispatchers under a separate key. Legacy
|
|
85
|
+
// global dispatcher consumers use that path, so mirror the mock dispatches
|
|
86
|
+
// before delegating to the internal Agent.
|
|
87
|
+
if (dispatchOpts.allowH2 === false) {
|
|
88
|
+
const http1OnlyKey = `${dispatchOpts.origin}#http1-only`
|
|
89
|
+
if (!this[kClients].has(http1OnlyKey)) {
|
|
90
|
+
const http1OnlyDispatcher = this[kFactory](dispatchOpts.origin)
|
|
91
|
+
http1OnlyDispatcher[kDispatches] = mockDispatcher[kDispatches]
|
|
92
|
+
this[kMockAgentSet](http1OnlyKey, http1OnlyDispatcher)
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
84
96
|
if (acceptNonStandardSearchParameters && dispatchOpts.path) {
|
|
85
97
|
const [path, searchParams] = dispatchOpts.path.split('?')
|
|
86
98
|
const normalizedSearchParams = normalizeSearchParams(searchParams, acceptNonStandardSearchParameters)
|
|
@@ -12,6 +12,11 @@ const {
|
|
|
12
12
|
} = require('./mock-symbols')
|
|
13
13
|
const { InvalidArgumentError } = require('../core/errors')
|
|
14
14
|
const { serializePathWithQuery } = require('../core/util')
|
|
15
|
+
const {
|
|
16
|
+
types: {
|
|
17
|
+
isPromise
|
|
18
|
+
}
|
|
19
|
+
} = require('node:util')
|
|
15
20
|
|
|
16
21
|
/**
|
|
17
22
|
* Defines the scope API for an interceptor reply
|
|
@@ -117,13 +122,9 @@ class MockInterceptor {
|
|
|
117
122
|
// Values of reply aren't available right now as they
|
|
118
123
|
// can only be available when the reply callback is invoked.
|
|
119
124
|
if (typeof replyOptionsCallbackOrStatusCode === 'function') {
|
|
120
|
-
//
|
|
121
|
-
//
|
|
122
|
-
|
|
123
|
-
const wrappedDefaultsCallback = (opts) => {
|
|
124
|
-
// Our reply options callback contains the parameter for statusCode, data and options.
|
|
125
|
-
const resolvedData = replyOptionsCallbackOrStatusCode(opts)
|
|
126
|
-
|
|
125
|
+
// Resolves the data returned by a reply options callback into
|
|
126
|
+
// dispatch data, validating its format along the way.
|
|
127
|
+
const resolveReplyCallbackData = (resolvedData) => {
|
|
127
128
|
// Check if it is in the right format
|
|
128
129
|
if (typeof resolvedData !== 'object' || resolvedData === null) {
|
|
129
130
|
throw new InvalidArgumentError('reply options callback must return an object')
|
|
@@ -138,6 +139,23 @@ class MockInterceptor {
|
|
|
138
139
|
}
|
|
139
140
|
}
|
|
140
141
|
|
|
142
|
+
// We'll first wrap the provided callback in another function,
|
|
143
|
+
// this function will properly resolve the data from the callback
|
|
144
|
+
// when invoked.
|
|
145
|
+
const wrappedDefaultsCallback = (opts) => {
|
|
146
|
+
// Our reply options callback contains the parameter for statusCode, data and options.
|
|
147
|
+
const resolvedData = replyOptionsCallbackOrStatusCode(opts)
|
|
148
|
+
|
|
149
|
+
// An asynchronous reply options callback resolves to the reply
|
|
150
|
+
// parameters, so the dispatch data can only be resolved once the
|
|
151
|
+
// returned promise settles.
|
|
152
|
+
if (isPromise(resolvedData)) {
|
|
153
|
+
return resolvedData.then(resolveReplyCallbackData)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return resolveReplyCallbackData(resolvedData)
|
|
157
|
+
}
|
|
158
|
+
|
|
141
159
|
// Add usual dispatch data, but this time set the data parameter to function that will eventually provide data.
|
|
142
160
|
const newMockDispatch = addMockDispatch(this[kDispatches], this[kDispatchKey], wrappedDefaultsCallback, { ignoreTrailingSlash: this[kIgnoreTrailingSlash] })
|
|
143
161
|
return new MockScope(newMockDispatch)
|
|
@@ -17,6 +17,7 @@ const {
|
|
|
17
17
|
}
|
|
18
18
|
} = require('node:util')
|
|
19
19
|
const { InvalidArgumentError } = require('../core/errors')
|
|
20
|
+
const requestAborted = Symbol('request aborted')
|
|
20
21
|
|
|
21
22
|
function matchValue (match, value) {
|
|
22
23
|
if (typeof match === 'string') {
|
|
@@ -153,6 +154,11 @@ function getResponseData (data) {
|
|
|
153
154
|
return data
|
|
154
155
|
} else if (data instanceof ArrayBuffer) {
|
|
155
156
|
return data
|
|
157
|
+
} else if (ArrayBuffer.isView(data)) {
|
|
158
|
+
// A DataView, or any non-Uint8Array typed array, is a byte container
|
|
159
|
+
// rather than a plain object. Buffer.from() cannot read one directly, so
|
|
160
|
+
// expose the bytes it covers instead of letting it reach JSON.stringify.
|
|
161
|
+
return new Uint8Array(data.buffer, data.byteOffset, data.byteLength)
|
|
156
162
|
} else if (typeof data === 'object') {
|
|
157
163
|
return JSON.stringify(data)
|
|
158
164
|
} else if (data) {
|
|
@@ -225,9 +231,15 @@ function deleteMockDispatch (mockDispatches, key) {
|
|
|
225
231
|
}
|
|
226
232
|
|
|
227
233
|
/**
|
|
228
|
-
* @param {string} path Path to remove trailing slash from
|
|
234
|
+
* @param {string|RegExp|Function} path Path, or path matcher, to remove trailing slash from
|
|
229
235
|
*/
|
|
230
236
|
function removeTrailingSlash (path) {
|
|
237
|
+
// Registered path matchers may be a RegExp or a function, which have no
|
|
238
|
+
// trailing slash to strip; hand those back for matchValue to apply.
|
|
239
|
+
if (typeof path !== 'string') {
|
|
240
|
+
return path
|
|
241
|
+
}
|
|
242
|
+
|
|
231
243
|
while (path.endsWith('/')) {
|
|
232
244
|
path = path.slice(0, -1)
|
|
233
245
|
}
|
|
@@ -292,26 +304,69 @@ function mockDispatch (opts, handler) {
|
|
|
292
304
|
// Get mock dispatch from built key
|
|
293
305
|
const key = buildKey(opts)
|
|
294
306
|
const mockDispatch = getMockDispatch(this[kDispatches], key)
|
|
307
|
+
const mockDispatches = this[kDispatches]
|
|
295
308
|
|
|
296
309
|
mockDispatch.timesInvoked++
|
|
297
310
|
|
|
298
|
-
// Here's where we resolve a callback if a callback is present for the dispatch data.
|
|
299
|
-
if (mockDispatch.data.callback) {
|
|
300
|
-
mockDispatch.data = { ...mockDispatch.data, ...mockDispatch.data.callback(opts) }
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
// Parse mockDispatch data
|
|
304
|
-
const { data: { statusCode, data, headers, trailers, error }, delay, persist } = mockDispatch
|
|
305
311
|
const { timesInvoked, times } = mockDispatch
|
|
306
312
|
|
|
307
313
|
// If it's used up and not persistent, mark as consumed
|
|
308
|
-
mockDispatch.consumed = !persist && timesInvoked >= times
|
|
314
|
+
mockDispatch.consumed = !mockDispatch.persist && timesInvoked >= times
|
|
309
315
|
mockDispatch.pending = timesInvoked < times
|
|
310
316
|
|
|
317
|
+
const hasBodyHooks = typeof handler.onBodySent === 'function' ||
|
|
318
|
+
typeof handler.onRequestSent === 'function'
|
|
319
|
+
|
|
320
|
+
// Here's where we resolve a callback if a callback is present for the dispatch data.
|
|
321
|
+
if (mockDispatch.data.callback && (!hasBodyHooks || opts.body == null)) {
|
|
322
|
+
const { callback, ...responseDefaults } = mockDispatch.data
|
|
323
|
+
const callbackResult = callback(opts)
|
|
324
|
+
|
|
325
|
+
// An asynchronous reply options callback resolves to the reply data, so
|
|
326
|
+
// the dispatch can only continue once the returned promise settles.
|
|
327
|
+
// A rejection cannot be thrown synchronously from the dispatch at that
|
|
328
|
+
// point, so it is surfaced as a response error instead.
|
|
329
|
+
if (isPromise(callbackResult)) {
|
|
330
|
+
callbackResult.then(
|
|
331
|
+
(resolvedData) => {
|
|
332
|
+
if (resolvedData == null || typeof resolvedData !== 'object') {
|
|
333
|
+
handler.onResponseError(null, new InvalidArgumentError('reply options callback must return an object'))
|
|
334
|
+
return
|
|
335
|
+
}
|
|
336
|
+
dispatchMockReply(mockDispatches, mockDispatch, key, opts, handler, { ...responseDefaults, ...resolvedData })
|
|
337
|
+
},
|
|
338
|
+
(error) => {
|
|
339
|
+
handler.onResponseError(null, error)
|
|
340
|
+
}
|
|
341
|
+
)
|
|
342
|
+
return true
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
if (callbackResult == null || typeof callbackResult !== 'object') {
|
|
346
|
+
throw new InvalidArgumentError('reply options callback must return an object')
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
return dispatchMockReply(mockDispatches, mockDispatch, key, opts, handler, { ...responseDefaults, ...callbackResult })
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
return dispatchMockReply(mockDispatches, mockDispatch, key, opts, handler)
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Replies to a request once the mock dispatch data is fully resolved
|
|
357
|
+
*/
|
|
358
|
+
function dispatchMockReply (mockDispatches, mockDispatch, key, opts, handler, resolvedResponse) {
|
|
359
|
+
// Parse mockDispatch data. When a reply callback has already been resolved
|
|
360
|
+
// in mockDispatch() (i.e. no body lifecycle hooks are involved), the resolved
|
|
361
|
+
// response is passed in here, leaving mockDispatch.data untouched so the
|
|
362
|
+
// callback can be re-invoked for persistent / times() replies.
|
|
363
|
+
const { data: responseData, delay } = mockDispatch
|
|
364
|
+
const response = resolvedResponse ?? responseData
|
|
365
|
+
|
|
311
366
|
// If specified, trigger dispatch error
|
|
312
|
-
if (error !== null) {
|
|
313
|
-
deleteMockDispatch(
|
|
314
|
-
handler.onResponseError(null, error)
|
|
367
|
+
if (response.error !== null) {
|
|
368
|
+
deleteMockDispatch(mockDispatches, key)
|
|
369
|
+
handler.onResponseError(null, response.error)
|
|
315
370
|
return true
|
|
316
371
|
}
|
|
317
372
|
|
|
@@ -346,32 +401,105 @@ function mockDispatch (opts, handler) {
|
|
|
346
401
|
}
|
|
347
402
|
}
|
|
348
403
|
|
|
404
|
+
let replyOpts = opts
|
|
405
|
+
const dispatches = mockDispatches
|
|
406
|
+
|
|
349
407
|
// Call onRequestStart to allow the handler to receive the controller
|
|
350
408
|
handler.onRequestStart?.(controller, null)
|
|
351
409
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
410
|
+
if (aborted) {
|
|
411
|
+
return true
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
const requestBody = dispatchRequestBody(opts.body, handler, controller, () => aborted)
|
|
415
|
+
|
|
416
|
+
if (isPromise(requestBody)) {
|
|
417
|
+
requestBody.then((body) => {
|
|
418
|
+
if (body === requestAborted) {
|
|
419
|
+
return
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
if (body !== opts.body) {
|
|
423
|
+
replyOpts = { ...opts, body }
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
sendReply()
|
|
427
|
+
}, (error) => controller.abort(error))
|
|
428
|
+
return true
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
if (requestBody === requestAborted) {
|
|
432
|
+
return true
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
if (requestBody !== opts.body) {
|
|
436
|
+
replyOpts = { ...opts, body: requestBody }
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
sendReply()
|
|
440
|
+
|
|
441
|
+
function sendReply () {
|
|
442
|
+
if (response.callback) {
|
|
443
|
+
const { callback, ...responseDefaults } = response
|
|
444
|
+
let callbackResult
|
|
445
|
+
try {
|
|
446
|
+
callbackResult = callback(replyOpts)
|
|
447
|
+
} catch (err) {
|
|
448
|
+
deleteMockDispatch(mockDispatches, key)
|
|
449
|
+
handler.onResponseError(null, err)
|
|
450
|
+
return
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
if (isPromise(callbackResult)) {
|
|
454
|
+
callbackResult.then(
|
|
455
|
+
(resolvedData) => {
|
|
456
|
+
if (resolvedData == null || typeof resolvedData !== 'object') {
|
|
457
|
+
handler.onResponseError(null, new InvalidArgumentError('reply options callback must return an object'))
|
|
458
|
+
return
|
|
459
|
+
}
|
|
460
|
+
handleReply(dispatches, { ...responseDefaults, ...resolvedData })
|
|
461
|
+
},
|
|
462
|
+
(err) => {
|
|
463
|
+
handler.onResponseError(null, err)
|
|
464
|
+
}
|
|
465
|
+
)
|
|
466
|
+
return
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
if (callbackResult == null || typeof callbackResult !== 'object') {
|
|
470
|
+
throw new InvalidArgumentError('reply options callback must return an object')
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
handleReply(dispatches, { ...responseDefaults, ...callbackResult })
|
|
474
|
+
return
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
// Handle the request with a delay if necessary
|
|
478
|
+
if (typeof delay === 'number' && delay > 0) {
|
|
479
|
+
timer = setTimeout(() => {
|
|
480
|
+
timer = null
|
|
481
|
+
handleReply(dispatches)
|
|
482
|
+
}, delay)
|
|
483
|
+
} else {
|
|
484
|
+
handleReply(dispatches)
|
|
485
|
+
}
|
|
360
486
|
}
|
|
361
487
|
|
|
362
|
-
function handleReply (mockDispatches,
|
|
488
|
+
function handleReply (mockDispatches, _response = response) {
|
|
363
489
|
// Don't send response if the request was aborted
|
|
364
490
|
if (aborted) {
|
|
365
491
|
return
|
|
366
492
|
}
|
|
367
493
|
|
|
494
|
+
const { statusCode, data, headers, trailers } = _response
|
|
495
|
+
|
|
368
496
|
// fetch's HeadersList is a 1D string array
|
|
369
497
|
const optsHeaders = Array.isArray(opts.headers)
|
|
370
498
|
? buildHeadersFromArray(opts.headers)
|
|
371
499
|
: opts.headers
|
|
372
|
-
const body = typeof
|
|
373
|
-
?
|
|
374
|
-
:
|
|
500
|
+
const body = typeof data === 'function'
|
|
501
|
+
? data({ ...replyOpts, headers: optsHeaders })
|
|
502
|
+
: data
|
|
375
503
|
|
|
376
504
|
// util.types.isPromise is likely needed for jest.
|
|
377
505
|
if (isPromise(body)) {
|
|
@@ -380,7 +508,7 @@ function mockDispatch (opts, handler) {
|
|
|
380
508
|
// synchronously throw the error, which breaks some tests.
|
|
381
509
|
// Rather, we wait for the callback to resolve if it is a
|
|
382
510
|
// promise, and then re-run handleReply with the new body.
|
|
383
|
-
return body.then((newData) => handleReply(mockDispatches, newData))
|
|
511
|
+
return body.then((newData) => handleReply(mockDispatches, { ..._response, data: newData }))
|
|
384
512
|
}
|
|
385
513
|
|
|
386
514
|
// Check again if aborted after async body resolution
|
|
@@ -389,8 +517,8 @@ function mockDispatch (opts, handler) {
|
|
|
389
517
|
}
|
|
390
518
|
|
|
391
519
|
const responseData = getResponseData(body)
|
|
392
|
-
const responseHeaders = generateKeyValues(headers)
|
|
393
|
-
const responseTrailers = generateKeyValues(trailers)
|
|
520
|
+
const responseHeaders = generateKeyValues(headers ?? {})
|
|
521
|
+
const responseTrailers = generateKeyValues(trailers ?? {})
|
|
394
522
|
|
|
395
523
|
// Update the controller with response data
|
|
396
524
|
controller.rawHeaders = responseHeaders
|
|
@@ -405,6 +533,97 @@ function mockDispatch (opts, handler) {
|
|
|
405
533
|
return true
|
|
406
534
|
}
|
|
407
535
|
|
|
536
|
+
function dispatchRequestBody (body, handler, controller, isAborted) {
|
|
537
|
+
if (typeof handler.onBodySent !== 'function' && typeof handler.onRequestSent !== 'function') {
|
|
538
|
+
return body
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
if (body == null) {
|
|
542
|
+
return callOnRequestSent(handler, controller, isAborted) ? body : requestAborted
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
if (body && typeof body[Symbol.asyncIterator] === 'function') {
|
|
546
|
+
return dispatchAsyncIterableBody(body, handler, controller, isAborted)
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
if (isIterableBody(body)) {
|
|
550
|
+
const chunks = []
|
|
551
|
+
|
|
552
|
+
for (const chunk of body) {
|
|
553
|
+
if (isAborted()) {
|
|
554
|
+
return requestAborted
|
|
555
|
+
}
|
|
556
|
+
chunks.push(chunk)
|
|
557
|
+
if (!callOnBodySent(handler, controller, chunk) || isAborted()) {
|
|
558
|
+
return requestAborted
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
return callOnRequestSent(handler, controller, isAborted) ? chunks : requestAborted
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
if (isAborted()) {
|
|
566
|
+
return requestAborted
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
if (!callOnBodySent(handler, controller, body)) {
|
|
570
|
+
return requestAborted
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
return callOnRequestSent(handler, controller, isAborted) ? body : requestAborted
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
async function dispatchAsyncIterableBody (body, handler, controller, isAborted) {
|
|
577
|
+
const chunks = []
|
|
578
|
+
|
|
579
|
+
for await (const chunk of body) {
|
|
580
|
+
if (isAborted()) {
|
|
581
|
+
return requestAborted
|
|
582
|
+
}
|
|
583
|
+
chunks.push(chunk)
|
|
584
|
+
if (!callOnBodySent(handler, controller, chunk) || isAborted()) {
|
|
585
|
+
return requestAborted
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
if (!callOnRequestSent(handler, controller, isAborted)) {
|
|
590
|
+
return requestAborted
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
return {
|
|
594
|
+
async * [Symbol.asyncIterator] () {
|
|
595
|
+
yield * chunks
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
function callOnBodySent (handler, controller, chunk) {
|
|
601
|
+
try {
|
|
602
|
+
handler.onBodySent?.(chunk)
|
|
603
|
+
return true
|
|
604
|
+
} catch (error) {
|
|
605
|
+
controller.abort(error)
|
|
606
|
+
return false
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
function callOnRequestSent (handler, controller, isAborted) {
|
|
611
|
+
try {
|
|
612
|
+
handler.onRequestSent?.()
|
|
613
|
+
return !isAborted()
|
|
614
|
+
} catch (error) {
|
|
615
|
+
controller.abort(error)
|
|
616
|
+
return false
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
function isIterableBody (body) {
|
|
621
|
+
return typeof body !== 'string' &&
|
|
622
|
+
!Buffer.isBuffer(body) &&
|
|
623
|
+
!ArrayBuffer.isView(body) &&
|
|
624
|
+
typeof body[Symbol.iterator] === 'function'
|
|
625
|
+
}
|
|
626
|
+
|
|
408
627
|
function buildMockDispatch () {
|
|
409
628
|
const agent = this[kMockAgent]
|
|
410
629
|
const origin = this[kOrigin]
|