@nocobase/plugin-idp-oauth 2.1.0-alpha.17 → 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 (214) 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/package.json +2 -2
@@ -0,0 +1,100 @@
1
+ 'use strict'
2
+
3
+ const { parseHeaders } = require('../core/util')
4
+ const { InvalidArgumentError } = require('../core/errors')
5
+
6
+ const kResume = Symbol('resume')
7
+
8
+ class UnwrapController {
9
+ #paused = false
10
+ #reason = null
11
+ #aborted = false
12
+ #abort
13
+
14
+ [kResume] = null
15
+
16
+ constructor (abort) {
17
+ this.#abort = abort
18
+ }
19
+
20
+ pause () {
21
+ this.#paused = true
22
+ }
23
+
24
+ resume () {
25
+ if (this.#paused) {
26
+ this.#paused = false
27
+ this[kResume]?.()
28
+ }
29
+ }
30
+
31
+ abort (reason) {
32
+ if (!this.#aborted) {
33
+ this.#aborted = true
34
+ this.#reason = reason
35
+ this.#abort(reason)
36
+ }
37
+ }
38
+
39
+ get aborted () {
40
+ return this.#aborted
41
+ }
42
+
43
+ get reason () {
44
+ return this.#reason
45
+ }
46
+
47
+ get paused () {
48
+ return this.#paused
49
+ }
50
+ }
51
+
52
+ module.exports = class UnwrapHandler {
53
+ #handler
54
+ #controller
55
+
56
+ constructor (handler) {
57
+ this.#handler = handler
58
+ }
59
+
60
+ static unwrap (handler) {
61
+ // TODO (fix): More checks...
62
+ return !handler.onRequestStart ? handler : new UnwrapHandler(handler)
63
+ }
64
+
65
+ onConnect (abort, context) {
66
+ this.#controller = new UnwrapController(abort)
67
+ this.#handler.onRequestStart?.(this.#controller, context)
68
+ }
69
+
70
+ onResponseStarted () {
71
+ return this.#handler.onResponseStarted?.()
72
+ }
73
+
74
+ onUpgrade (statusCode, rawHeaders, socket) {
75
+ this.#handler.onRequestUpgrade?.(this.#controller, statusCode, parseHeaders(rawHeaders), socket)
76
+ }
77
+
78
+ onHeaders (statusCode, rawHeaders, resume, statusMessage) {
79
+ this.#controller[kResume] = resume
80
+ this.#handler.onResponseStart?.(this.#controller, statusCode, parseHeaders(rawHeaders), statusMessage)
81
+ return !this.#controller.paused
82
+ }
83
+
84
+ onData (data) {
85
+ this.#handler.onResponseData?.(this.#controller, data)
86
+ return !this.#controller.paused
87
+ }
88
+
89
+ onComplete (rawTrailers) {
90
+ this.#handler.onResponseEnd?.(this.#controller, parseHeaders(rawTrailers))
91
+ }
92
+
93
+ onError (err) {
94
+ if (!this.#handler.onResponseError) {
95
+ throw new InvalidArgumentError('invalid onError method')
96
+ }
97
+
98
+ this.#handler.onResponseError?.(this.#controller, err)
99
+ }
100
+ }
@@ -0,0 +1,105 @@
1
+ 'use strict'
2
+
3
+ const { InvalidArgumentError } = require('../core/errors')
4
+
5
+ module.exports = class WrapHandler {
6
+ #handler
7
+
8
+ constructor (handler) {
9
+ this.#handler = handler
10
+ }
11
+
12
+ static wrap (handler) {
13
+ // TODO (fix): More checks...
14
+ return handler.onRequestStart ? handler : new WrapHandler(handler)
15
+ }
16
+
17
+ // Unwrap Interface
18
+
19
+ onConnect (abort, context) {
20
+ return this.#handler.onConnect?.(abort, context)
21
+ }
22
+
23
+ onResponseStarted () {
24
+ return this.#handler.onResponseStarted?.()
25
+ }
26
+
27
+ onHeaders (statusCode, rawHeaders, resume, statusMessage) {
28
+ return this.#handler.onHeaders?.(statusCode, rawHeaders, resume, statusMessage)
29
+ }
30
+
31
+ onUpgrade (statusCode, rawHeaders, socket) {
32
+ return this.#handler.onUpgrade?.(statusCode, rawHeaders, socket)
33
+ }
34
+
35
+ onData (data) {
36
+ return this.#handler.onData?.(data)
37
+ }
38
+
39
+ onComplete (trailers) {
40
+ return this.#handler.onComplete?.(trailers)
41
+ }
42
+
43
+ onError (err) {
44
+ if (!this.#handler.onError) {
45
+ throw err
46
+ }
47
+
48
+ return this.#handler.onError?.(err)
49
+ }
50
+
51
+ // Wrap Interface
52
+
53
+ onRequestStart (controller, context) {
54
+ this.#handler.onConnect?.((reason) => controller.abort(reason), context)
55
+ }
56
+
57
+ onRequestUpgrade (controller, statusCode, headers, socket) {
58
+ const rawHeaders = []
59
+ for (const [key, val] of Object.entries(headers)) {
60
+ rawHeaders.push(Buffer.from(key, 'latin1'), toRawHeaderValue(val))
61
+ }
62
+
63
+ this.#handler.onUpgrade?.(statusCode, rawHeaders, socket)
64
+ }
65
+
66
+ onResponseStart (controller, statusCode, headers, statusMessage) {
67
+ const rawHeaders = []
68
+ for (const [key, val] of Object.entries(headers)) {
69
+ rawHeaders.push(Buffer.from(key, 'latin1'), toRawHeaderValue(val))
70
+ }
71
+
72
+ if (this.#handler.onHeaders?.(statusCode, rawHeaders, () => controller.resume(), statusMessage) === false) {
73
+ controller.pause()
74
+ }
75
+ }
76
+
77
+ onResponseData (controller, data) {
78
+ if (this.#handler.onData?.(data) === false) {
79
+ controller.pause()
80
+ }
81
+ }
82
+
83
+ onResponseEnd (controller, trailers) {
84
+ const rawTrailers = []
85
+ for (const [key, val] of Object.entries(trailers)) {
86
+ rawTrailers.push(Buffer.from(key, 'latin1'), toRawHeaderValue(val))
87
+ }
88
+
89
+ this.#handler.onComplete?.(rawTrailers)
90
+ }
91
+
92
+ onResponseError (controller, err) {
93
+ if (!this.#handler.onError) {
94
+ throw new InvalidArgumentError('invalid onError method')
95
+ }
96
+
97
+ this.#handler.onError?.(err)
98
+ }
99
+ }
100
+
101
+ function toRawHeaderValue (value) {
102
+ return Array.isArray(value)
103
+ ? value.map((item) => Buffer.from(item, 'latin1'))
104
+ : Buffer.from(value, 'latin1')
105
+ }
@@ -0,0 +1,495 @@
1
+ 'use strict'
2
+
3
+ const assert = require('node:assert')
4
+ const { Readable } = require('node:stream')
5
+ const util = require('../core/util')
6
+ const CacheHandler = require('../handler/cache-handler')
7
+ const MemoryCacheStore = require('../cache/memory-cache-store')
8
+ const CacheRevalidationHandler = require('../handler/cache-revalidation-handler')
9
+ const { assertCacheStore, assertCacheMethods, makeCacheKey, normalizeHeaders, parseCacheControlHeader } = require('../util/cache.js')
10
+ const { AbortError } = require('../core/errors.js')
11
+
12
+ /**
13
+ * @param {(string | RegExp)[] | undefined} origins
14
+ * @param {string} name
15
+ */
16
+ function assertCacheOrigins (origins, name) {
17
+ if (origins === undefined) return
18
+ if (!Array.isArray(origins)) {
19
+ throw new TypeError(`expected ${name} to be an array or undefined, got ${typeof origins}`)
20
+ }
21
+ for (let i = 0; i < origins.length; i++) {
22
+ const origin = origins[i]
23
+ if (typeof origin !== 'string' && !(origin instanceof RegExp)) {
24
+ throw new TypeError(`expected ${name}[${i}] to be a string or RegExp, got ${typeof origin}`)
25
+ }
26
+ }
27
+ }
28
+
29
+ const nop = () => {}
30
+
31
+ /**
32
+ * @typedef {(options: import('../../types/dispatcher.d.ts').default.DispatchOptions, handler: import('../../types/dispatcher.d.ts').default.DispatchHandler) => void} DispatchFn
33
+ */
34
+
35
+ /**
36
+ * @param {import('../../types/cache-interceptor.d.ts').default.GetResult} result
37
+ * @param {import('../../types/cache-interceptor.d.ts').default.CacheControlDirectives | undefined} cacheControlDirectives
38
+ * @param {import('../../types/dispatcher.d.ts').default.RequestOptions} opts
39
+ * @returns {boolean}
40
+ */
41
+ function needsRevalidation (result, cacheControlDirectives, { headers = {} }) {
42
+ // Always revalidate requests with the no-cache request directive.
43
+ if (cacheControlDirectives?.['no-cache']) {
44
+ return true
45
+ }
46
+
47
+ // Always revalidate requests with unqualified no-cache response directive.
48
+ if (result.cacheControlDirectives?.['no-cache'] && !Array.isArray(result.cacheControlDirectives['no-cache'])) {
49
+ return true
50
+ }
51
+
52
+ // Always revalidate requests with conditional headers.
53
+ if (headers['if-modified-since'] || headers['if-none-match']) {
54
+ return true
55
+ }
56
+
57
+ return false
58
+ }
59
+
60
+ /**
61
+ * @param {import('../../types/cache-interceptor.d.ts').default.GetResult} result
62
+ * @param {import('../../types/cache-interceptor.d.ts').default.CacheControlDirectives | undefined} cacheControlDirectives
63
+ * @returns {boolean}
64
+ */
65
+ function isStale (result, cacheControlDirectives) {
66
+ const now = Date.now()
67
+ if (now > result.staleAt) {
68
+ // Response is stale
69
+ if (cacheControlDirectives?.['max-stale']) {
70
+ // There's a threshold where we can serve stale responses, let's see if
71
+ // we're in it
72
+ // https://www.rfc-editor.org/rfc/rfc9111.html#name-max-stale
73
+ const gracePeriod = result.staleAt + (cacheControlDirectives['max-stale'] * 1000)
74
+ return now > gracePeriod
75
+ }
76
+
77
+ return true
78
+ }
79
+
80
+ if (cacheControlDirectives?.['min-fresh']) {
81
+ // https://www.rfc-editor.org/rfc/rfc9111.html#section-5.2.1.3
82
+
83
+ // At this point, staleAt is always > now
84
+ const timeLeftTillStale = result.staleAt - now
85
+ const threshold = cacheControlDirectives['min-fresh'] * 1000
86
+
87
+ return timeLeftTillStale <= threshold
88
+ }
89
+
90
+ return false
91
+ }
92
+
93
+ /**
94
+ * Check if we're within the stale-while-revalidate window for a stale response
95
+ * @param {import('../../types/cache-interceptor.d.ts').default.GetResult} result
96
+ * @returns {boolean}
97
+ */
98
+ function withinStaleWhileRevalidateWindow (result) {
99
+ const staleWhileRevalidate = result.cacheControlDirectives?.['stale-while-revalidate']
100
+ if (!staleWhileRevalidate) {
101
+ return false
102
+ }
103
+
104
+ const now = Date.now()
105
+ const staleWhileRevalidateExpiry = result.staleAt + (staleWhileRevalidate * 1000)
106
+ return now <= staleWhileRevalidateExpiry
107
+ }
108
+
109
+ /**
110
+ * @param {DispatchFn} dispatch
111
+ * @param {import('../../types/cache-interceptor.d.ts').default.CacheHandlerOptions} globalOpts
112
+ * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} cacheKey
113
+ * @param {import('../../types/dispatcher.d.ts').default.DispatchHandler} handler
114
+ * @param {import('../../types/dispatcher.d.ts').default.RequestOptions} opts
115
+ * @param {import('../../types/cache-interceptor.d.ts').default.CacheControlDirectives | undefined} reqCacheControl
116
+ */
117
+ function handleUncachedResponse (
118
+ dispatch,
119
+ globalOpts,
120
+ cacheKey,
121
+ handler,
122
+ opts,
123
+ reqCacheControl
124
+ ) {
125
+ if (reqCacheControl?.['only-if-cached']) {
126
+ let aborted = false
127
+ try {
128
+ if (typeof handler.onConnect === 'function') {
129
+ handler.onConnect(() => {
130
+ aborted = true
131
+ })
132
+
133
+ if (aborted) {
134
+ return
135
+ }
136
+ }
137
+
138
+ if (typeof handler.onHeaders === 'function') {
139
+ handler.onHeaders(504, [], nop, 'Gateway Timeout')
140
+ if (aborted) {
141
+ return
142
+ }
143
+ }
144
+
145
+ if (typeof handler.onComplete === 'function') {
146
+ handler.onComplete([])
147
+ }
148
+ } catch (err) {
149
+ if (typeof handler.onError === 'function') {
150
+ handler.onError(err)
151
+ }
152
+ }
153
+
154
+ return true
155
+ }
156
+
157
+ return dispatch(opts, new CacheHandler(globalOpts, cacheKey, handler))
158
+ }
159
+
160
+ /**
161
+ * @param {import('../../types/dispatcher.d.ts').default.DispatchHandler} handler
162
+ * @param {import('../../types/dispatcher.d.ts').default.RequestOptions} opts
163
+ * @param {import('../../types/cache-interceptor.d.ts').default.GetResult} result
164
+ * @param {number} age
165
+ * @param {any} context
166
+ * @param {boolean} isStale
167
+ */
168
+ function sendCachedValue (handler, opts, result, age, context, isStale) {
169
+ // TODO (perf): Readable.from path can be optimized...
170
+ const stream = util.isStream(result.body)
171
+ ? result.body
172
+ : Readable.from(result.body ?? [])
173
+
174
+ assert(!stream.destroyed, 'stream should not be destroyed')
175
+ assert(!stream.readableDidRead, 'stream should not be readableDidRead')
176
+
177
+ const controller = {
178
+ resume () {
179
+ stream.resume()
180
+ },
181
+ pause () {
182
+ stream.pause()
183
+ },
184
+ get paused () {
185
+ return stream.isPaused()
186
+ },
187
+ get aborted () {
188
+ return stream.destroyed
189
+ },
190
+ get reason () {
191
+ return stream.errored
192
+ },
193
+ abort (reason) {
194
+ stream.destroy(reason ?? new AbortError())
195
+ }
196
+ }
197
+
198
+ stream
199
+ .on('error', function (err) {
200
+ if (!this.readableEnded) {
201
+ if (typeof handler.onResponseError === 'function') {
202
+ handler.onResponseError(controller, err)
203
+ } else {
204
+ throw err
205
+ }
206
+ }
207
+ })
208
+ .on('close', function () {
209
+ if (!this.errored) {
210
+ handler.onResponseEnd?.(controller, {})
211
+ }
212
+ })
213
+
214
+ handler.onRequestStart?.(controller, context)
215
+
216
+ if (stream.destroyed) {
217
+ return
218
+ }
219
+
220
+ // Add the age header
221
+ // https://www.rfc-editor.org/rfc/rfc9111.html#name-age
222
+ const headers = { ...result.headers, age: String(age) }
223
+
224
+ if (isStale) {
225
+ // Add warning header
226
+ // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Warning
227
+ headers.warning = '110 - "response is stale"'
228
+ }
229
+
230
+ handler.onResponseStart?.(controller, result.statusCode, headers, result.statusMessage)
231
+
232
+ if (opts.method === 'HEAD') {
233
+ stream.destroy()
234
+ } else {
235
+ stream.on('data', function (chunk) {
236
+ handler.onResponseData?.(controller, chunk)
237
+ })
238
+ }
239
+ }
240
+
241
+ /**
242
+ * @param {DispatchFn} dispatch
243
+ * @param {import('../../types/cache-interceptor.d.ts').default.CacheHandlerOptions} globalOpts
244
+ * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} cacheKey
245
+ * @param {import('../../types/dispatcher.d.ts').default.DispatchHandler} handler
246
+ * @param {import('../../types/dispatcher.d.ts').default.RequestOptions} opts
247
+ * @param {import('../../types/cache-interceptor.d.ts').default.CacheControlDirectives | undefined} reqCacheControl
248
+ * @param {import('../../types/cache-interceptor.d.ts').default.GetResult | undefined} result
249
+ */
250
+ function handleResult (
251
+ dispatch,
252
+ globalOpts,
253
+ cacheKey,
254
+ handler,
255
+ opts,
256
+ reqCacheControl,
257
+ result
258
+ ) {
259
+ if (!result) {
260
+ return handleUncachedResponse(dispatch, globalOpts, cacheKey, handler, opts, reqCacheControl)
261
+ }
262
+
263
+ const now = Date.now()
264
+ if (now > result.deleteAt) {
265
+ // Response is expired, cache store shouldn't have given this to us
266
+ return dispatch(opts, new CacheHandler(globalOpts, cacheKey, handler))
267
+ }
268
+
269
+ const age = Math.round((now - result.cachedAt) / 1000)
270
+ if (reqCacheControl?.['max-age'] && age >= reqCacheControl['max-age']) {
271
+ // Response is considered expired for this specific request
272
+ // https://www.rfc-editor.org/rfc/rfc9111.html#section-5.2.1.1
273
+ return dispatch(opts, handler)
274
+ }
275
+
276
+ const stale = isStale(result, reqCacheControl)
277
+ const revalidate = needsRevalidation(result, reqCacheControl, opts)
278
+
279
+ // Check if the response is stale
280
+ if (stale || revalidate) {
281
+ if (util.isStream(opts.body) && util.bodyLength(opts.body) !== 0) {
282
+ // If body is a stream we can't revalidate...
283
+ // TODO (fix): This could be less strict...
284
+ return dispatch(opts, new CacheHandler(globalOpts, cacheKey, handler))
285
+ }
286
+
287
+ // RFC 5861: If we're within stale-while-revalidate window, serve stale immediately
288
+ // and revalidate in background, unless immediate revalidation is necessary
289
+ if (!revalidate && withinStaleWhileRevalidateWindow(result)) {
290
+ // Serve stale response immediately
291
+ sendCachedValue(handler, opts, result, age, null, true)
292
+
293
+ // Start background revalidation (fire-and-forget)
294
+ queueMicrotask(() => {
295
+ const headers = {
296
+ ...opts.headers,
297
+ 'if-modified-since': new Date(result.cachedAt).toUTCString()
298
+ }
299
+
300
+ if (result.etag) {
301
+ headers['if-none-match'] = result.etag
302
+ }
303
+
304
+ if (result.vary) {
305
+ for (const key in result.vary) {
306
+ if (result.vary[key] != null) {
307
+ headers[key] = result.vary[key]
308
+ }
309
+ }
310
+ }
311
+
312
+ // Background revalidation - update cache if we get new data
313
+ dispatch(
314
+ {
315
+ ...opts,
316
+ headers
317
+ },
318
+ new CacheHandler(globalOpts, cacheKey, {
319
+ // Silent handler that just updates the cache
320
+ onRequestStart () {},
321
+ onRequestUpgrade () {},
322
+ onResponseStart () {},
323
+ onResponseData () {},
324
+ onResponseEnd () {},
325
+ onResponseError () {}
326
+ })
327
+ )
328
+ })
329
+
330
+ return true
331
+ }
332
+
333
+ let withinStaleIfErrorThreshold = false
334
+ const staleIfErrorExpiry = result.cacheControlDirectives['stale-if-error'] ?? reqCacheControl?.['stale-if-error']
335
+ if (staleIfErrorExpiry) {
336
+ withinStaleIfErrorThreshold = now < (result.staleAt + (staleIfErrorExpiry * 1000))
337
+ }
338
+
339
+ const headers = {
340
+ ...opts.headers,
341
+ 'if-modified-since': new Date(result.cachedAt).toUTCString()
342
+ }
343
+
344
+ if (result.etag) {
345
+ headers['if-none-match'] = result.etag
346
+ }
347
+
348
+ if (result.vary) {
349
+ for (const key in result.vary) {
350
+ if (result.vary[key] != null) {
351
+ headers[key] = result.vary[key]
352
+ }
353
+ }
354
+ }
355
+
356
+ // We need to revalidate the response
357
+ return dispatch(
358
+ {
359
+ ...opts,
360
+ headers
361
+ },
362
+ new CacheRevalidationHandler(
363
+ (success, context) => {
364
+ if (success) {
365
+ // TODO: successful revalidation should be considered fresh (not give stale warning).
366
+ sendCachedValue(handler, opts, result, age, context, stale)
367
+ } else if (util.isStream(result.body)) {
368
+ result.body.on('error', nop).destroy()
369
+ }
370
+ },
371
+ new CacheHandler(globalOpts, cacheKey, handler),
372
+ withinStaleIfErrorThreshold
373
+ )
374
+ )
375
+ }
376
+
377
+ // Dump request body.
378
+ if (util.isStream(opts.body)) {
379
+ opts.body.on('error', nop).destroy()
380
+ }
381
+
382
+ sendCachedValue(handler, opts, result, age, null, false)
383
+ }
384
+
385
+ /**
386
+ * @param {import('../../types/cache-interceptor.d.ts').default.CacheOptions} [opts]
387
+ * @returns {import('../../types/dispatcher.d.ts').default.DispatcherComposeInterceptor}
388
+ */
389
+ module.exports = (opts = {}) => {
390
+ const {
391
+ store = new MemoryCacheStore(),
392
+ methods = ['GET'],
393
+ cacheByDefault = undefined,
394
+ type = 'shared',
395
+ origins = undefined
396
+ } = opts
397
+
398
+ if (typeof opts !== 'object' || opts === null) {
399
+ throw new TypeError(`expected type of opts to be an Object, got ${opts === null ? 'null' : typeof opts}`)
400
+ }
401
+
402
+ assertCacheStore(store, 'opts.store')
403
+ assertCacheMethods(methods, 'opts.methods')
404
+ assertCacheOrigins(origins, 'opts.origins')
405
+
406
+ if (typeof cacheByDefault !== 'undefined' && typeof cacheByDefault !== 'number') {
407
+ throw new TypeError(`expected opts.cacheByDefault to be number or undefined, got ${typeof cacheByDefault}`)
408
+ }
409
+
410
+ if (typeof type !== 'undefined' && type !== 'shared' && type !== 'private') {
411
+ throw new TypeError(`expected opts.type to be shared, private, or undefined, got ${typeof type}`)
412
+ }
413
+
414
+ const globalOpts = {
415
+ store,
416
+ methods,
417
+ cacheByDefault,
418
+ type
419
+ }
420
+
421
+ const safeMethodsToNotCache = util.safeHTTPMethods.filter(method => methods.includes(method) === false)
422
+
423
+ return dispatch => {
424
+ return (opts, handler) => {
425
+ if (!opts.origin || safeMethodsToNotCache.includes(opts.method)) {
426
+ // Not a method we want to cache or we don't have the origin, skip
427
+ return dispatch(opts, handler)
428
+ }
429
+
430
+ // Check if origin is in whitelist
431
+ if (origins !== undefined) {
432
+ const requestOrigin = opts.origin.toString().toLowerCase()
433
+ let isAllowed = false
434
+
435
+ for (let i = 0; i < origins.length; i++) {
436
+ const allowed = origins[i]
437
+ if (typeof allowed === 'string') {
438
+ if (allowed.toLowerCase() === requestOrigin) {
439
+ isAllowed = true
440
+ break
441
+ }
442
+ } else if (allowed.test(requestOrigin)) {
443
+ isAllowed = true
444
+ break
445
+ }
446
+ }
447
+
448
+ if (!isAllowed) {
449
+ return dispatch(opts, handler)
450
+ }
451
+ }
452
+
453
+ opts = {
454
+ ...opts,
455
+ headers: normalizeHeaders(opts)
456
+ }
457
+
458
+ const reqCacheControl = opts.headers?.['cache-control']
459
+ ? parseCacheControlHeader(opts.headers['cache-control'])
460
+ : undefined
461
+
462
+ if (reqCacheControl?.['no-store']) {
463
+ return dispatch(opts, handler)
464
+ }
465
+
466
+ /**
467
+ * @type {import('../../types/cache-interceptor.d.ts').default.CacheKey}
468
+ */
469
+ const cacheKey = makeCacheKey(opts)
470
+ const result = store.get(cacheKey)
471
+
472
+ if (result && typeof result.then === 'function') {
473
+ return result
474
+ .then(result => handleResult(dispatch,
475
+ globalOpts,
476
+ cacheKey,
477
+ handler,
478
+ opts,
479
+ reqCacheControl,
480
+ result
481
+ ))
482
+ } else {
483
+ return handleResult(
484
+ dispatch,
485
+ globalOpts,
486
+ cacheKey,
487
+ handler,
488
+ opts,
489
+ reqCacheControl,
490
+ result
491
+ )
492
+ }
493
+ }
494
+ }
495
+ }