@nocobase/plugin-idp-oauth 2.1.0-alpha.16 → 2.1.0-alpha.18

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.
Files changed (217) hide show
  1. package/build.config.ts +1 -1
  2. package/dist/externalVersion.js +4 -4
  3. package/dist/node_modules/light-my-request/package.json +1 -1
  4. package/dist/node_modules/undici/LICENSE +21 -0
  5. package/dist/node_modules/undici/README.md +741 -0
  6. package/dist/node_modules/undici/docs/docs/api/Agent.md +84 -0
  7. package/dist/node_modules/undici/docs/docs/api/BalancedPool.md +99 -0
  8. package/dist/node_modules/undici/docs/docs/api/CacheStorage.md +30 -0
  9. package/dist/node_modules/undici/docs/docs/api/CacheStore.md +164 -0
  10. package/dist/node_modules/undici/docs/docs/api/Client.md +285 -0
  11. package/dist/node_modules/undici/docs/docs/api/ClientStats.md +27 -0
  12. package/dist/node_modules/undici/docs/docs/api/Connector.md +115 -0
  13. package/dist/node_modules/undici/docs/docs/api/ContentType.md +57 -0
  14. package/dist/node_modules/undici/docs/docs/api/Cookies.md +101 -0
  15. package/dist/node_modules/undici/docs/docs/api/Debug.md +62 -0
  16. package/dist/node_modules/undici/docs/docs/api/DiagnosticsChannel.md +315 -0
  17. package/dist/node_modules/undici/docs/docs/api/Dispatcher.md +1392 -0
  18. package/dist/node_modules/undici/docs/docs/api/EnvHttpProxyAgent.md +159 -0
  19. package/dist/node_modules/undici/docs/docs/api/Errors.md +49 -0
  20. package/dist/node_modules/undici/docs/docs/api/EventSource.md +45 -0
  21. package/dist/node_modules/undici/docs/docs/api/Fetch.md +60 -0
  22. package/dist/node_modules/undici/docs/docs/api/GlobalInstallation.md +139 -0
  23. package/dist/node_modules/undici/docs/docs/api/H2CClient.md +263 -0
  24. package/dist/node_modules/undici/docs/docs/api/MockAgent.md +603 -0
  25. package/dist/node_modules/undici/docs/docs/api/MockCallHistory.md +197 -0
  26. package/dist/node_modules/undici/docs/docs/api/MockCallHistoryLog.md +43 -0
  27. package/dist/node_modules/undici/docs/docs/api/MockClient.md +81 -0
  28. package/dist/node_modules/undici/docs/docs/api/MockErrors.md +12 -0
  29. package/dist/node_modules/undici/docs/docs/api/MockPool.md +555 -0
  30. package/dist/node_modules/undici/docs/docs/api/Pool.md +84 -0
  31. package/dist/node_modules/undici/docs/docs/api/PoolStats.md +35 -0
  32. package/dist/node_modules/undici/docs/docs/api/ProxyAgent.md +229 -0
  33. package/dist/node_modules/undici/docs/docs/api/RedirectHandler.md +93 -0
  34. package/dist/node_modules/undici/docs/docs/api/RetryAgent.md +50 -0
  35. package/dist/node_modules/undici/docs/docs/api/RetryHandler.md +118 -0
  36. package/dist/node_modules/undici/docs/docs/api/RoundRobinPool.md +145 -0
  37. package/dist/node_modules/undici/docs/docs/api/SnapshotAgent.md +616 -0
  38. package/dist/node_modules/undici/docs/docs/api/Socks5ProxyAgent.md +274 -0
  39. package/dist/node_modules/undici/docs/docs/api/Util.md +25 -0
  40. package/dist/node_modules/undici/docs/docs/api/WebSocket.md +141 -0
  41. package/dist/node_modules/undici/docs/docs/api/api-lifecycle.md +91 -0
  42. package/dist/node_modules/undici/docs/docs/best-practices/client-certificate.md +64 -0
  43. package/dist/node_modules/undici/docs/docs/best-practices/crawling.md +58 -0
  44. package/dist/node_modules/undici/docs/docs/best-practices/mocking-request.md +190 -0
  45. package/dist/node_modules/undici/docs/docs/best-practices/proxy.md +127 -0
  46. package/dist/node_modules/undici/docs/docs/best-practices/undici-vs-builtin-fetch.md +224 -0
  47. package/dist/node_modules/undici/docs/docs/best-practices/writing-tests.md +63 -0
  48. package/dist/node_modules/undici/index-fetch.js +65 -0
  49. package/dist/node_modules/undici/index.d.ts +3 -0
  50. package/dist/node_modules/undici/index.js +234 -0
  51. package/dist/node_modules/undici/lib/api/abort-signal.js +59 -0
  52. package/dist/node_modules/undici/lib/api/api-connect.js +110 -0
  53. package/dist/node_modules/undici/lib/api/api-pipeline.js +252 -0
  54. package/dist/node_modules/undici/lib/api/api-request.js +214 -0
  55. package/dist/node_modules/undici/lib/api/api-stream.js +209 -0
  56. package/dist/node_modules/undici/lib/api/api-upgrade.js +111 -0
  57. package/dist/node_modules/undici/lib/api/index.js +7 -0
  58. package/dist/node_modules/undici/lib/api/readable.js +580 -0
  59. package/dist/node_modules/undici/lib/cache/memory-cache-store.js +234 -0
  60. package/dist/node_modules/undici/lib/cache/sqlite-cache-store.js +461 -0
  61. package/dist/node_modules/undici/lib/core/connect.js +137 -0
  62. package/dist/node_modules/undici/lib/core/constants.js +143 -0
  63. package/dist/node_modules/undici/lib/core/diagnostics.js +227 -0
  64. package/dist/node_modules/undici/lib/core/errors.js +477 -0
  65. package/dist/node_modules/undici/lib/core/request.js +438 -0
  66. package/dist/node_modules/undici/lib/core/socks5-client.js +407 -0
  67. package/dist/node_modules/undici/lib/core/socks5-utils.js +203 -0
  68. package/dist/node_modules/undici/lib/core/symbols.js +75 -0
  69. package/dist/node_modules/undici/lib/core/tree.js +160 -0
  70. package/dist/node_modules/undici/lib/core/util.js +992 -0
  71. package/dist/node_modules/undici/lib/dispatcher/agent.js +158 -0
  72. package/dist/node_modules/undici/lib/dispatcher/balanced-pool.js +219 -0
  73. package/dist/node_modules/undici/lib/dispatcher/client-h1.js +1610 -0
  74. package/dist/node_modules/undici/lib/dispatcher/client-h2.js +995 -0
  75. package/dist/node_modules/undici/lib/dispatcher/client.js +659 -0
  76. package/dist/node_modules/undici/lib/dispatcher/dispatcher-base.js +165 -0
  77. package/dist/node_modules/undici/lib/dispatcher/dispatcher.js +48 -0
  78. package/dist/node_modules/undici/lib/dispatcher/env-http-proxy-agent.js +146 -0
  79. package/dist/node_modules/undici/lib/dispatcher/fixed-queue.js +135 -0
  80. package/dist/node_modules/undici/lib/dispatcher/h2c-client.js +51 -0
  81. package/dist/node_modules/undici/lib/dispatcher/pool-base.js +214 -0
  82. package/dist/node_modules/undici/lib/dispatcher/pool.js +118 -0
  83. package/dist/node_modules/undici/lib/dispatcher/proxy-agent.js +318 -0
  84. package/dist/node_modules/undici/lib/dispatcher/retry-agent.js +35 -0
  85. package/dist/node_modules/undici/lib/dispatcher/round-robin-pool.js +137 -0
  86. package/dist/node_modules/undici/lib/dispatcher/socks5-proxy-agent.js +249 -0
  87. package/dist/node_modules/undici/lib/encoding/index.js +33 -0
  88. package/dist/node_modules/undici/lib/global.js +50 -0
  89. package/dist/node_modules/undici/lib/handler/cache-handler.js +578 -0
  90. package/dist/node_modules/undici/lib/handler/cache-revalidation-handler.js +124 -0
  91. package/dist/node_modules/undici/lib/handler/decorator-handler.js +67 -0
  92. package/dist/node_modules/undici/lib/handler/deduplication-handler.js +460 -0
  93. package/dist/node_modules/undici/lib/handler/redirect-handler.js +238 -0
  94. package/dist/node_modules/undici/lib/handler/retry-handler.js +394 -0
  95. package/dist/node_modules/undici/lib/handler/unwrap-handler.js +100 -0
  96. package/dist/node_modules/undici/lib/handler/wrap-handler.js +105 -0
  97. package/dist/node_modules/undici/lib/interceptor/cache.js +495 -0
  98. package/dist/node_modules/undici/lib/interceptor/decompress.js +259 -0
  99. package/dist/node_modules/undici/lib/interceptor/deduplicate.js +117 -0
  100. package/dist/node_modules/undici/lib/interceptor/dns.js +571 -0
  101. package/dist/node_modules/undici/lib/interceptor/dump.js +112 -0
  102. package/dist/node_modules/undici/lib/interceptor/redirect.js +21 -0
  103. package/dist/node_modules/undici/lib/interceptor/response-error.js +95 -0
  104. package/dist/node_modules/undici/lib/interceptor/retry.js +19 -0
  105. package/dist/node_modules/undici/lib/llhttp/.gitkeep +0 -0
  106. package/dist/node_modules/undici/lib/llhttp/constants.d.ts +195 -0
  107. package/dist/node_modules/undici/lib/llhttp/constants.js +531 -0
  108. package/dist/node_modules/undici/lib/llhttp/llhttp-wasm.js +15 -0
  109. package/dist/node_modules/undici/lib/llhttp/llhttp_simd-wasm.js +15 -0
  110. package/dist/node_modules/undici/lib/llhttp/utils.d.ts +2 -0
  111. package/dist/node_modules/undici/lib/llhttp/utils.js +12 -0
  112. package/dist/node_modules/undici/lib/mock/mock-agent.js +232 -0
  113. package/dist/node_modules/undici/lib/mock/mock-call-history.js +248 -0
  114. package/dist/node_modules/undici/lib/mock/mock-client.js +68 -0
  115. package/dist/node_modules/undici/lib/mock/mock-errors.js +29 -0
  116. package/dist/node_modules/undici/lib/mock/mock-interceptor.js +209 -0
  117. package/dist/node_modules/undici/lib/mock/mock-pool.js +68 -0
  118. package/dist/node_modules/undici/lib/mock/mock-symbols.js +32 -0
  119. package/dist/node_modules/undici/lib/mock/mock-utils.js +486 -0
  120. package/dist/node_modules/undici/lib/mock/pending-interceptors-formatter.js +43 -0
  121. package/dist/node_modules/undici/lib/mock/snapshot-agent.js +353 -0
  122. package/dist/node_modules/undici/lib/mock/snapshot-recorder.js +588 -0
  123. package/dist/node_modules/undici/lib/mock/snapshot-utils.js +158 -0
  124. package/dist/node_modules/undici/lib/util/cache.js +407 -0
  125. package/dist/node_modules/undici/lib/util/date.js +653 -0
  126. package/dist/node_modules/undici/lib/util/promise.js +28 -0
  127. package/dist/node_modules/undici/lib/util/runtime-features.js +124 -0
  128. package/dist/node_modules/undici/lib/util/stats.js +32 -0
  129. package/dist/node_modules/undici/lib/util/timers.js +425 -0
  130. package/dist/node_modules/undici/lib/web/cache/cache.js +864 -0
  131. package/dist/node_modules/undici/lib/web/cache/cachestorage.js +152 -0
  132. package/dist/node_modules/undici/lib/web/cache/util.js +45 -0
  133. package/dist/node_modules/undici/lib/web/cookies/constants.js +12 -0
  134. package/dist/node_modules/undici/lib/web/cookies/index.js +199 -0
  135. package/dist/node_modules/undici/lib/web/cookies/parse.js +322 -0
  136. package/dist/node_modules/undici/lib/web/cookies/util.js +282 -0
  137. package/dist/node_modules/undici/lib/web/eventsource/eventsource-stream.js +399 -0
  138. package/dist/node_modules/undici/lib/web/eventsource/eventsource.js +501 -0
  139. package/dist/node_modules/undici/lib/web/eventsource/util.js +29 -0
  140. package/dist/node_modules/undici/lib/web/fetch/LICENSE +21 -0
  141. package/dist/node_modules/undici/lib/web/fetch/body.js +509 -0
  142. package/dist/node_modules/undici/lib/web/fetch/constants.js +131 -0
  143. package/dist/node_modules/undici/lib/web/fetch/data-url.js +596 -0
  144. package/dist/node_modules/undici/lib/web/fetch/formdata-parser.js +575 -0
  145. package/dist/node_modules/undici/lib/web/fetch/formdata.js +259 -0
  146. package/dist/node_modules/undici/lib/web/fetch/global.js +40 -0
  147. package/dist/node_modules/undici/lib/web/fetch/headers.js +719 -0
  148. package/dist/node_modules/undici/lib/web/fetch/index.js +2397 -0
  149. package/dist/node_modules/undici/lib/web/fetch/request.js +1115 -0
  150. package/dist/node_modules/undici/lib/web/fetch/response.js +641 -0
  151. package/dist/node_modules/undici/lib/web/fetch/util.js +1520 -0
  152. package/dist/node_modules/undici/lib/web/infra/index.js +229 -0
  153. package/dist/node_modules/undici/lib/web/subresource-integrity/Readme.md +9 -0
  154. package/dist/node_modules/undici/lib/web/subresource-integrity/subresource-integrity.js +307 -0
  155. package/dist/node_modules/undici/lib/web/webidl/index.js +1006 -0
  156. package/dist/node_modules/undici/lib/web/websocket/connection.js +329 -0
  157. package/dist/node_modules/undici/lib/web/websocket/constants.js +126 -0
  158. package/dist/node_modules/undici/lib/web/websocket/events.js +331 -0
  159. package/dist/node_modules/undici/lib/web/websocket/frame.js +133 -0
  160. package/dist/node_modules/undici/lib/web/websocket/permessage-deflate.js +118 -0
  161. package/dist/node_modules/undici/lib/web/websocket/receiver.js +450 -0
  162. package/dist/node_modules/undici/lib/web/websocket/sender.js +109 -0
  163. package/dist/node_modules/undici/lib/web/websocket/stream/websocketerror.js +104 -0
  164. package/dist/node_modules/undici/lib/web/websocket/stream/websocketstream.js +497 -0
  165. package/dist/node_modules/undici/lib/web/websocket/util.js +347 -0
  166. package/dist/node_modules/undici/lib/web/websocket/websocket.js +751 -0
  167. package/dist/node_modules/undici/package.json +152 -0
  168. package/dist/node_modules/undici/scripts/strip-comments.js +10 -0
  169. package/dist/node_modules/undici/types/README.md +6 -0
  170. package/dist/node_modules/undici/types/agent.d.ts +32 -0
  171. package/dist/node_modules/undici/types/api.d.ts +43 -0
  172. package/dist/node_modules/undici/types/balanced-pool.d.ts +30 -0
  173. package/dist/node_modules/undici/types/cache-interceptor.d.ts +179 -0
  174. package/dist/node_modules/undici/types/cache.d.ts +36 -0
  175. package/dist/node_modules/undici/types/client-stats.d.ts +15 -0
  176. package/dist/node_modules/undici/types/client.d.ts +123 -0
  177. package/dist/node_modules/undici/types/connector.d.ts +36 -0
  178. package/dist/node_modules/undici/types/content-type.d.ts +21 -0
  179. package/dist/node_modules/undici/types/cookies.d.ts +30 -0
  180. package/dist/node_modules/undici/types/diagnostics-channel.d.ts +74 -0
  181. package/dist/node_modules/undici/types/dispatcher.d.ts +273 -0
  182. package/dist/node_modules/undici/types/env-http-proxy-agent.d.ts +22 -0
  183. package/dist/node_modules/undici/types/errors.d.ts +177 -0
  184. package/dist/node_modules/undici/types/eventsource.d.ts +66 -0
  185. package/dist/node_modules/undici/types/fetch.d.ts +231 -0
  186. package/dist/node_modules/undici/types/formdata.d.ts +114 -0
  187. package/dist/node_modules/undici/types/global-dispatcher.d.ts +9 -0
  188. package/dist/node_modules/undici/types/global-origin.d.ts +7 -0
  189. package/dist/node_modules/undici/types/h2c-client.d.ts +73 -0
  190. package/dist/node_modules/undici/types/handlers.d.ts +14 -0
  191. package/dist/node_modules/undici/types/header.d.ts +160 -0
  192. package/dist/node_modules/undici/types/index.d.ts +91 -0
  193. package/dist/node_modules/undici/types/interceptors.d.ts +80 -0
  194. package/dist/node_modules/undici/types/mock-agent.d.ts +68 -0
  195. package/dist/node_modules/undici/types/mock-call-history.d.ts +111 -0
  196. package/dist/node_modules/undici/types/mock-client.d.ts +27 -0
  197. package/dist/node_modules/undici/types/mock-errors.d.ts +12 -0
  198. package/dist/node_modules/undici/types/mock-interceptor.d.ts +94 -0
  199. package/dist/node_modules/undici/types/mock-pool.d.ts +27 -0
  200. package/dist/node_modules/undici/types/patch.d.ts +29 -0
  201. package/dist/node_modules/undici/types/pool-stats.d.ts +19 -0
  202. package/dist/node_modules/undici/types/pool.d.ts +41 -0
  203. package/dist/node_modules/undici/types/proxy-agent.d.ts +29 -0
  204. package/dist/node_modules/undici/types/readable.d.ts +68 -0
  205. package/dist/node_modules/undici/types/retry-agent.d.ts +8 -0
  206. package/dist/node_modules/undici/types/retry-handler.d.ts +125 -0
  207. package/dist/node_modules/undici/types/round-robin-pool.d.ts +41 -0
  208. package/dist/node_modules/undici/types/snapshot-agent.d.ts +109 -0
  209. package/dist/node_modules/undici/types/socks5-proxy-agent.d.ts +25 -0
  210. package/dist/node_modules/undici/types/util.d.ts +18 -0
  211. package/dist/node_modules/undici/types/utility.d.ts +7 -0
  212. package/dist/node_modules/undici/types/webidl.d.ts +347 -0
  213. package/dist/node_modules/undici/types/websocket.d.ts +188 -0
  214. package/dist/server/plugin.d.ts +1 -0
  215. package/dist/server/plugin.js +13 -0
  216. package/dist/server/service.js +11 -3
  217. package/package.json +2 -2
@@ -0,0 +1,353 @@
1
+ 'use strict'
2
+
3
+ const Agent = require('../dispatcher/agent')
4
+ const MockAgent = require('./mock-agent')
5
+ const { SnapshotRecorder } = require('./snapshot-recorder')
6
+ const WrapHandler = require('../handler/wrap-handler')
7
+ const { InvalidArgumentError, UndiciError } = require('../core/errors')
8
+ const { validateSnapshotMode } = require('./snapshot-utils')
9
+
10
+ const kSnapshotRecorder = Symbol('kSnapshotRecorder')
11
+ const kSnapshotMode = Symbol('kSnapshotMode')
12
+ const kSnapshotPath = Symbol('kSnapshotPath')
13
+ const kSnapshotLoaded = Symbol('kSnapshotLoaded')
14
+ const kRealAgent = Symbol('kRealAgent')
15
+
16
+ // Static flag to ensure warning is only emitted once per process
17
+ let warningEmitted = false
18
+
19
+ class SnapshotAgent extends MockAgent {
20
+ constructor (opts = {}) {
21
+ // Emit experimental warning only once
22
+ if (!warningEmitted) {
23
+ process.emitWarning(
24
+ 'SnapshotAgent is experimental and subject to change',
25
+ 'ExperimentalWarning'
26
+ )
27
+ warningEmitted = true
28
+ }
29
+
30
+ const {
31
+ mode = 'record',
32
+ snapshotPath = null,
33
+ ...mockAgentOpts
34
+ } = opts
35
+
36
+ super(mockAgentOpts)
37
+
38
+ validateSnapshotMode(mode)
39
+
40
+ // Validate snapshotPath is provided when required
41
+ if ((mode === 'playback' || mode === 'update') && !snapshotPath) {
42
+ throw new InvalidArgumentError(`snapshotPath is required when mode is '${mode}'`)
43
+ }
44
+
45
+ this[kSnapshotMode] = mode
46
+ this[kSnapshotPath] = snapshotPath
47
+
48
+ this[kSnapshotRecorder] = new SnapshotRecorder({
49
+ snapshotPath: this[kSnapshotPath],
50
+ mode: this[kSnapshotMode],
51
+ maxSnapshots: opts.maxSnapshots,
52
+ autoFlush: opts.autoFlush,
53
+ flushInterval: opts.flushInterval,
54
+ matchHeaders: opts.matchHeaders,
55
+ ignoreHeaders: opts.ignoreHeaders,
56
+ excludeHeaders: opts.excludeHeaders,
57
+ matchBody: opts.matchBody,
58
+ matchQuery: opts.matchQuery,
59
+ caseSensitive: opts.caseSensitive,
60
+ shouldRecord: opts.shouldRecord,
61
+ shouldPlayback: opts.shouldPlayback,
62
+ excludeUrls: opts.excludeUrls
63
+ })
64
+ this[kSnapshotLoaded] = false
65
+
66
+ // For recording/update mode, we need a real agent to make actual requests
67
+ // For playback mode, we need a real agent if there are excluded URLs
68
+ if (this[kSnapshotMode] === 'record' || this[kSnapshotMode] === 'update' ||
69
+ (this[kSnapshotMode] === 'playback' && opts.excludeUrls && opts.excludeUrls.length > 0)) {
70
+ this[kRealAgent] = new Agent(opts)
71
+ }
72
+
73
+ // Auto-load snapshots in playback/update mode
74
+ if ((this[kSnapshotMode] === 'playback' || this[kSnapshotMode] === 'update') && this[kSnapshotPath]) {
75
+ this.loadSnapshots().catch(() => {
76
+ // Ignore load errors - file might not exist yet
77
+ })
78
+ }
79
+ }
80
+
81
+ dispatch (opts, handler) {
82
+ handler = WrapHandler.wrap(handler)
83
+ const mode = this[kSnapshotMode]
84
+
85
+ // Check if URL should be excluded (pass through without mocking/recording)
86
+ if (this[kSnapshotRecorder].isUrlExcluded(opts)) {
87
+ // Real agent is guaranteed by constructor when excludeUrls is configured
88
+ return this[kRealAgent].dispatch(opts, handler)
89
+ }
90
+
91
+ if (mode === 'playback' || mode === 'update') {
92
+ // Ensure snapshots are loaded
93
+ if (!this[kSnapshotLoaded]) {
94
+ // Need to load asynchronously, delegate to async version
95
+ return this.#asyncDispatch(opts, handler)
96
+ }
97
+
98
+ // Try to find existing snapshot (synchronous)
99
+ const snapshot = this[kSnapshotRecorder].findSnapshot(opts)
100
+
101
+ if (snapshot) {
102
+ // Use recorded response (synchronous)
103
+ return this.#replaySnapshot(snapshot, handler)
104
+ } else if (mode === 'update') {
105
+ // Make real request and record it (async required)
106
+ return this.#recordAndReplay(opts, handler)
107
+ } else {
108
+ // Playback mode but no snapshot found
109
+ const error = new UndiciError(`No snapshot found for ${opts.method || 'GET'} ${opts.path}`)
110
+ if (handler.onError) {
111
+ handler.onError(error)
112
+ return
113
+ }
114
+ throw error
115
+ }
116
+ } else if (mode === 'record') {
117
+ // Record mode - make real request and save response (async required)
118
+ return this.#recordAndReplay(opts, handler)
119
+ }
120
+ }
121
+
122
+ /**
123
+ * Async version of dispatch for when we need to load snapshots first
124
+ */
125
+ async #asyncDispatch (opts, handler) {
126
+ await this.loadSnapshots()
127
+ return this.dispatch(opts, handler)
128
+ }
129
+
130
+ /**
131
+ * Records a real request and replays the response
132
+ */
133
+ #recordAndReplay (opts, handler) {
134
+ const responseData = {
135
+ statusCode: null,
136
+ headers: {},
137
+ trailers: {},
138
+ body: []
139
+ }
140
+
141
+ const self = this // Capture 'this' context for use within nested handler callbacks
142
+
143
+ const recordingHandler = {
144
+ onRequestStart (controller, context) {
145
+ return handler.onRequestStart(controller, { ...context, history: this.history })
146
+ },
147
+
148
+ onRequestUpgrade (controller, statusCode, headers, socket) {
149
+ return handler.onRequestUpgrade(controller, statusCode, headers, socket)
150
+ },
151
+
152
+ onResponseStart (controller, statusCode, headers, statusMessage) {
153
+ responseData.statusCode = statusCode
154
+ responseData.headers = headers
155
+ return handler.onResponseStart(controller, statusCode, headers, statusMessage)
156
+ },
157
+
158
+ onResponseData (controller, chunk) {
159
+ responseData.body.push(chunk)
160
+ return handler.onResponseData(controller, chunk)
161
+ },
162
+
163
+ onResponseEnd (controller, trailers) {
164
+ responseData.trailers = trailers
165
+
166
+ // Record the interaction using captured 'self' context (fire and forget)
167
+ const responseBody = Buffer.concat(responseData.body)
168
+ self[kSnapshotRecorder].record(opts, {
169
+ statusCode: responseData.statusCode,
170
+ headers: responseData.headers,
171
+ body: responseBody,
172
+ trailers: responseData.trailers
173
+ })
174
+ .then(() => handler.onResponseEnd(controller, trailers))
175
+ .catch((error) => handler.onResponseError(controller, error))
176
+ }
177
+ }
178
+
179
+ // Use composed agent if available (includes interceptors), otherwise use real agent
180
+ const agent = this[kRealAgent]
181
+ return agent.dispatch(opts, recordingHandler)
182
+ }
183
+
184
+ /**
185
+ * Replays a recorded response
186
+ *
187
+ * @param {Object} snapshot - The recorded snapshot to replay.
188
+ * @param {Object} handler - The handler to call with the response data.
189
+ * @returns {void}
190
+ */
191
+ #replaySnapshot (snapshot, handler) {
192
+ try {
193
+ const { response } = snapshot
194
+
195
+ const controller = {
196
+ pause () { },
197
+ resume () { },
198
+ abort (reason) {
199
+ this.aborted = true
200
+ this.reason = reason
201
+ },
202
+
203
+ aborted: false,
204
+ paused: false
205
+ }
206
+
207
+ handler.onRequestStart(controller)
208
+
209
+ handler.onResponseStart(controller, response.statusCode, response.headers)
210
+
211
+ // Body is always stored as base64 string
212
+ const body = Buffer.from(response.body, 'base64')
213
+ handler.onResponseData(controller, body)
214
+
215
+ handler.onResponseEnd(controller, response.trailers)
216
+ } catch (error) {
217
+ handler.onError?.(error)
218
+ }
219
+ }
220
+
221
+ /**
222
+ * Loads snapshots from file
223
+ *
224
+ * @param {string} [filePath] - Optional file path to load snapshots from.
225
+ * @returns {Promise<void>} - Resolves when snapshots are loaded.
226
+ */
227
+ async loadSnapshots (filePath) {
228
+ await this[kSnapshotRecorder].loadSnapshots(filePath || this[kSnapshotPath])
229
+ this[kSnapshotLoaded] = true
230
+
231
+ // In playback mode, set up MockAgent interceptors for all snapshots
232
+ if (this[kSnapshotMode] === 'playback') {
233
+ this.#setupMockInterceptors()
234
+ }
235
+ }
236
+
237
+ /**
238
+ * Saves snapshots to file
239
+ *
240
+ * @param {string} [filePath] - Optional file path to save snapshots to.
241
+ * @returns {Promise<void>} - Resolves when snapshots are saved.
242
+ */
243
+ async saveSnapshots (filePath) {
244
+ return this[kSnapshotRecorder].saveSnapshots(filePath || this[kSnapshotPath])
245
+ }
246
+
247
+ /**
248
+ * Sets up MockAgent interceptors based on recorded snapshots.
249
+ *
250
+ * This method creates MockAgent interceptors for each recorded snapshot,
251
+ * allowing the SnapshotAgent to fall back to MockAgent's standard intercept
252
+ * mechanism in playback mode. Each interceptor is configured to persist
253
+ * (remain active for multiple requests) and responds with the recorded
254
+ * response data.
255
+ *
256
+ * Called automatically when loading snapshots in playback mode.
257
+ *
258
+ * @returns {void}
259
+ */
260
+ #setupMockInterceptors () {
261
+ for (const snapshot of this[kSnapshotRecorder].getSnapshots()) {
262
+ const { request, responses, response } = snapshot
263
+ const url = new URL(request.url)
264
+
265
+ const mockPool = this.get(url.origin)
266
+
267
+ // Handle both new format (responses array) and legacy format (response object)
268
+ const responseData = responses ? responses[0] : response
269
+ if (!responseData) continue
270
+
271
+ mockPool.intercept({
272
+ path: url.pathname + url.search,
273
+ method: request.method,
274
+ headers: request.headers,
275
+ body: request.body
276
+ }).reply(responseData.statusCode, responseData.body, {
277
+ headers: responseData.headers,
278
+ trailers: responseData.trailers
279
+ }).persist()
280
+ }
281
+ }
282
+
283
+ /**
284
+ * Gets the snapshot recorder
285
+ * @return {SnapshotRecorder} - The snapshot recorder instance
286
+ */
287
+ getRecorder () {
288
+ return this[kSnapshotRecorder]
289
+ }
290
+
291
+ /**
292
+ * Gets the current mode
293
+ * @return {import('./snapshot-utils').SnapshotMode} - The current snapshot mode
294
+ */
295
+ getMode () {
296
+ return this[kSnapshotMode]
297
+ }
298
+
299
+ /**
300
+ * Clears all snapshots
301
+ * @returns {void}
302
+ */
303
+ clearSnapshots () {
304
+ this[kSnapshotRecorder].clear()
305
+ }
306
+
307
+ /**
308
+ * Resets call counts for all snapshots (useful for test cleanup)
309
+ * @returns {void}
310
+ */
311
+ resetCallCounts () {
312
+ this[kSnapshotRecorder].resetCallCounts()
313
+ }
314
+
315
+ /**
316
+ * Deletes a specific snapshot by request options
317
+ * @param {import('./snapshot-recorder').SnapshotRequestOptions} requestOpts - Request options to identify the snapshot
318
+ * @return {Promise<boolean>} - Returns true if the snapshot was deleted, false if not found
319
+ */
320
+ deleteSnapshot (requestOpts) {
321
+ return this[kSnapshotRecorder].deleteSnapshot(requestOpts)
322
+ }
323
+
324
+ /**
325
+ * Gets information about a specific snapshot
326
+ * @returns {import('./snapshot-recorder').SnapshotInfo|null} - Snapshot information or null if not found
327
+ */
328
+ getSnapshotInfo (requestOpts) {
329
+ return this[kSnapshotRecorder].getSnapshotInfo(requestOpts)
330
+ }
331
+
332
+ /**
333
+ * Replaces all snapshots with new data (full replacement)
334
+ * @param {Array<{hash: string; snapshot: import('./snapshot-recorder').SnapshotEntryshotEntry}>|Record<string, import('./snapshot-recorder').SnapshotEntry>} snapshotData - New snapshot data to replace existing snapshots
335
+ * @returns {void}
336
+ */
337
+ replaceSnapshots (snapshotData) {
338
+ this[kSnapshotRecorder].replaceSnapshots(snapshotData)
339
+ }
340
+
341
+ /**
342
+ * Closes the agent, saving snapshots and cleaning up resources.
343
+ *
344
+ * @returns {Promise<void>}
345
+ */
346
+ async close () {
347
+ await this[kSnapshotRecorder].close()
348
+ await this[kRealAgent]?.close()
349
+ await super.close()
350
+ }
351
+ }
352
+
353
+ module.exports = SnapshotAgent