deepv-code 1.0.182

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 (223) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +3 -0
  3. package/bundle/assets/help/README.md +113 -0
  4. package/bundle/assets/help/cli-help-knowledge.md +1382 -0
  5. package/bundle/assets/sounds/README.md +74 -0
  6. package/bundle/assets/sounds/confirmation-required.wav +0 -0
  7. package/bundle/assets/sounds/response-complete.wav +0 -0
  8. package/bundle/assets/sounds/selection-made.wav +0 -0
  9. package/bundle/dvcode.js +4442 -0
  10. package/bundle/fix-binary-permissions.js +215 -0
  11. package/bundle/login/templates/authSelectPage.html +870 -0
  12. package/bundle/login/templates/deepv.ico +0 -0
  13. package/bundle/login/templates/feishu.ico +0 -0
  14. package/bundle/node_modules/@vscode/ripgrep/bin/darwin-arm64-rg +0 -0
  15. package/bundle/node_modules/@vscode/ripgrep/bin/darwin-x64-rg +0 -0
  16. package/bundle/node_modules/@vscode/ripgrep/bin/linux-arm-rg +0 -0
  17. package/bundle/node_modules/@vscode/ripgrep/bin/linux-arm64-rg +0 -0
  18. package/bundle/node_modules/@vscode/ripgrep/bin/linux-x64-rg +0 -0
  19. package/bundle/node_modules/@vscode/ripgrep/bin/rg.exe +0 -0
  20. package/bundle/node_modules/@vscode/ripgrep/bin/win32-arm64-rg.exe +0 -0
  21. package/bundle/node_modules/@vscode/ripgrep/bin/win32-ia32-rg.exe +0 -0
  22. package/bundle/node_modules/@vscode/ripgrep/bin/win32-x64-rg.exe +0 -0
  23. package/bundle/node_modules/@vscode/ripgrep/lib/download.js +357 -0
  24. package/bundle/node_modules/@vscode/ripgrep/lib/index.d.ts +1 -0
  25. package/bundle/node_modules/@vscode/ripgrep/lib/index.js +42 -0
  26. package/bundle/node_modules/@vscode/ripgrep/lib/postinstall.js +121 -0
  27. package/bundle/node_modules/@vscode/ripgrep/package.json +24 -0
  28. package/bundle/node_modules/undici/LICENSE +21 -0
  29. package/bundle/node_modules/undici/README.md +472 -0
  30. package/bundle/node_modules/undici/docs/docs/api/Agent.md +83 -0
  31. package/bundle/node_modules/undici/docs/docs/api/BalancedPool.md +99 -0
  32. package/bundle/node_modules/undici/docs/docs/api/CacheStorage.md +30 -0
  33. package/bundle/node_modules/undici/docs/docs/api/CacheStore.md +151 -0
  34. package/bundle/node_modules/undici/docs/docs/api/Client.md +281 -0
  35. package/bundle/node_modules/undici/docs/docs/api/ClientStats.md +27 -0
  36. package/bundle/node_modules/undici/docs/docs/api/Connector.md +115 -0
  37. package/bundle/node_modules/undici/docs/docs/api/ContentType.md +57 -0
  38. package/bundle/node_modules/undici/docs/docs/api/Cookies.md +101 -0
  39. package/bundle/node_modules/undici/docs/docs/api/Debug.md +62 -0
  40. package/bundle/node_modules/undici/docs/docs/api/DiagnosticsChannel.md +204 -0
  41. package/bundle/node_modules/undici/docs/docs/api/Dispatcher.md +1200 -0
  42. package/bundle/node_modules/undici/docs/docs/api/EnvHttpProxyAgent.md +159 -0
  43. package/bundle/node_modules/undici/docs/docs/api/Errors.md +49 -0
  44. package/bundle/node_modules/undici/docs/docs/api/EventSource.md +45 -0
  45. package/bundle/node_modules/undici/docs/docs/api/Fetch.md +52 -0
  46. package/bundle/node_modules/undici/docs/docs/api/H2CClient.md +262 -0
  47. package/bundle/node_modules/undici/docs/docs/api/MockAgent.md +603 -0
  48. package/bundle/node_modules/undici/docs/docs/api/MockCallHistory.md +197 -0
  49. package/bundle/node_modules/undici/docs/docs/api/MockCallHistoryLog.md +43 -0
  50. package/bundle/node_modules/undici/docs/docs/api/MockClient.md +77 -0
  51. package/bundle/node_modules/undici/docs/docs/api/MockErrors.md +12 -0
  52. package/bundle/node_modules/undici/docs/docs/api/MockPool.md +548 -0
  53. package/bundle/node_modules/undici/docs/docs/api/Pool.md +84 -0
  54. package/bundle/node_modules/undici/docs/docs/api/PoolStats.md +35 -0
  55. package/bundle/node_modules/undici/docs/docs/api/ProxyAgent.md +227 -0
  56. package/bundle/node_modules/undici/docs/docs/api/RedirectHandler.md +96 -0
  57. package/bundle/node_modules/undici/docs/docs/api/RetryAgent.md +45 -0
  58. package/bundle/node_modules/undici/docs/docs/api/RetryHandler.md +117 -0
  59. package/bundle/node_modules/undici/docs/docs/api/Util.md +25 -0
  60. package/bundle/node_modules/undici/docs/docs/api/WebSocket.md +85 -0
  61. package/bundle/node_modules/undici/docs/docs/api/api-lifecycle.md +91 -0
  62. package/bundle/node_modules/undici/docs/docs/best-practices/client-certificate.md +64 -0
  63. package/bundle/node_modules/undici/docs/docs/best-practices/mocking-request.md +190 -0
  64. package/bundle/node_modules/undici/docs/docs/best-practices/proxy.md +127 -0
  65. package/bundle/node_modules/undici/docs/docs/best-practices/writing-tests.md +20 -0
  66. package/bundle/node_modules/undici/index-fetch.js +35 -0
  67. package/bundle/node_modules/undici/index.d.ts +3 -0
  68. package/bundle/node_modules/undici/index.js +183 -0
  69. package/bundle/node_modules/undici/lib/api/abort-signal.js +59 -0
  70. package/bundle/node_modules/undici/lib/api/api-connect.js +110 -0
  71. package/bundle/node_modules/undici/lib/api/api-pipeline.js +252 -0
  72. package/bundle/node_modules/undici/lib/api/api-request.js +199 -0
  73. package/bundle/node_modules/undici/lib/api/api-stream.js +209 -0
  74. package/bundle/node_modules/undici/lib/api/api-upgrade.js +110 -0
  75. package/bundle/node_modules/undici/lib/api/index.js +7 -0
  76. package/bundle/node_modules/undici/lib/api/readable.js +558 -0
  77. package/bundle/node_modules/undici/lib/api/util.js +95 -0
  78. package/bundle/node_modules/undici/lib/cache/memory-cache-store.js +234 -0
  79. package/bundle/node_modules/undici/lib/cache/sqlite-cache-store.js +461 -0
  80. package/bundle/node_modules/undici/lib/core/connect.js +164 -0
  81. package/bundle/node_modules/undici/lib/core/constants.js +143 -0
  82. package/bundle/node_modules/undici/lib/core/diagnostics.js +196 -0
  83. package/bundle/node_modules/undici/lib/core/errors.js +244 -0
  84. package/bundle/node_modules/undici/lib/core/request.js +397 -0
  85. package/bundle/node_modules/undici/lib/core/symbols.js +68 -0
  86. package/bundle/node_modules/undici/lib/core/tree.js +160 -0
  87. package/bundle/node_modules/undici/lib/core/util.js +988 -0
  88. package/bundle/node_modules/undici/lib/dispatcher/agent.js +135 -0
  89. package/bundle/node_modules/undici/lib/dispatcher/balanced-pool.js +206 -0
  90. package/bundle/node_modules/undici/lib/dispatcher/client-h1.js +1615 -0
  91. package/bundle/node_modules/undici/lib/dispatcher/client-h2.js +798 -0
  92. package/bundle/node_modules/undici/lib/dispatcher/client.js +614 -0
  93. package/bundle/node_modules/undici/lib/dispatcher/dispatcher-base.js +161 -0
  94. package/bundle/node_modules/undici/lib/dispatcher/dispatcher.js +48 -0
  95. package/bundle/node_modules/undici/lib/dispatcher/env-http-proxy-agent.js +151 -0
  96. package/bundle/node_modules/undici/lib/dispatcher/fixed-queue.js +159 -0
  97. package/bundle/node_modules/undici/lib/dispatcher/h2c-client.js +122 -0
  98. package/bundle/node_modules/undici/lib/dispatcher/pool-base.js +191 -0
  99. package/bundle/node_modules/undici/lib/dispatcher/pool.js +118 -0
  100. package/bundle/node_modules/undici/lib/dispatcher/proxy-agent.js +275 -0
  101. package/bundle/node_modules/undici/lib/dispatcher/retry-agent.js +35 -0
  102. package/bundle/node_modules/undici/lib/global.js +32 -0
  103. package/bundle/node_modules/undici/lib/handler/cache-handler.js +448 -0
  104. package/bundle/node_modules/undici/lib/handler/cache-revalidation-handler.js +124 -0
  105. package/bundle/node_modules/undici/lib/handler/decorator-handler.js +67 -0
  106. package/bundle/node_modules/undici/lib/handler/redirect-handler.js +227 -0
  107. package/bundle/node_modules/undici/lib/handler/retry-handler.js +342 -0
  108. package/bundle/node_modules/undici/lib/handler/unwrap-handler.js +96 -0
  109. package/bundle/node_modules/undici/lib/handler/wrap-handler.js +95 -0
  110. package/bundle/node_modules/undici/lib/interceptor/cache.js +372 -0
  111. package/bundle/node_modules/undici/lib/interceptor/dns.js +432 -0
  112. package/bundle/node_modules/undici/lib/interceptor/dump.js +111 -0
  113. package/bundle/node_modules/undici/lib/interceptor/redirect.js +21 -0
  114. package/bundle/node_modules/undici/lib/interceptor/response-error.js +95 -0
  115. package/bundle/node_modules/undici/lib/interceptor/retry.js +19 -0
  116. package/bundle/node_modules/undici/lib/llhttp/.gitkeep +0 -0
  117. package/bundle/node_modules/undici/lib/llhttp/constants.d.ts +97 -0
  118. package/bundle/node_modules/undici/lib/llhttp/constants.js +498 -0
  119. package/bundle/node_modules/undici/lib/llhttp/constants.js.map +1 -0
  120. package/bundle/node_modules/undici/lib/llhttp/llhttp-wasm.js +15 -0
  121. package/bundle/node_modules/undici/lib/llhttp/llhttp_simd-wasm.js +15 -0
  122. package/bundle/node_modules/undici/lib/llhttp/utils.d.ts +2 -0
  123. package/bundle/node_modules/undici/lib/llhttp/utils.js +15 -0
  124. package/bundle/node_modules/undici/lib/llhttp/utils.js.map +1 -0
  125. package/bundle/node_modules/undici/lib/mock/mock-agent.js +224 -0
  126. package/bundle/node_modules/undici/lib/mock/mock-call-history.js +248 -0
  127. package/bundle/node_modules/undici/lib/mock/mock-client.js +64 -0
  128. package/bundle/node_modules/undici/lib/mock/mock-errors.js +19 -0
  129. package/bundle/node_modules/undici/lib/mock/mock-interceptor.js +209 -0
  130. package/bundle/node_modules/undici/lib/mock/mock-pool.js +64 -0
  131. package/bundle/node_modules/undici/lib/mock/mock-symbols.js +31 -0
  132. package/bundle/node_modules/undici/lib/mock/mock-utils.js +433 -0
  133. package/bundle/node_modules/undici/lib/mock/pending-interceptors-formatter.js +43 -0
  134. package/bundle/node_modules/undici/lib/util/cache.js +368 -0
  135. package/bundle/node_modules/undici/lib/util/date.js +259 -0
  136. package/bundle/node_modules/undici/lib/util/stats.js +32 -0
  137. package/bundle/node_modules/undici/lib/util/timers.js +423 -0
  138. package/bundle/node_modules/undici/lib/web/cache/cache.js +862 -0
  139. package/bundle/node_modules/undici/lib/web/cache/cachestorage.js +152 -0
  140. package/bundle/node_modules/undici/lib/web/cache/util.js +45 -0
  141. package/bundle/node_modules/undici/lib/web/cookies/constants.js +12 -0
  142. package/bundle/node_modules/undici/lib/web/cookies/index.js +199 -0
  143. package/bundle/node_modules/undici/lib/web/cookies/parse.js +322 -0
  144. package/bundle/node_modules/undici/lib/web/cookies/util.js +282 -0
  145. package/bundle/node_modules/undici/lib/web/eventsource/eventsource-stream.js +399 -0
  146. package/bundle/node_modules/undici/lib/web/eventsource/eventsource.js +484 -0
  147. package/bundle/node_modules/undici/lib/web/eventsource/util.js +37 -0
  148. package/bundle/node_modules/undici/lib/web/fetch/LICENSE +21 -0
  149. package/bundle/node_modules/undici/lib/web/fetch/body.js +532 -0
  150. package/bundle/node_modules/undici/lib/web/fetch/constants.js +131 -0
  151. package/bundle/node_modules/undici/lib/web/fetch/data-url.js +744 -0
  152. package/bundle/node_modules/undici/lib/web/fetch/dispatcher-weakref.js +46 -0
  153. package/bundle/node_modules/undici/lib/web/fetch/formdata-parser.js +501 -0
  154. package/bundle/node_modules/undici/lib/web/fetch/formdata.js +263 -0
  155. package/bundle/node_modules/undici/lib/web/fetch/global.js +40 -0
  156. package/bundle/node_modules/undici/lib/web/fetch/headers.js +719 -0
  157. package/bundle/node_modules/undici/lib/web/fetch/index.js +2258 -0
  158. package/bundle/node_modules/undici/lib/web/fetch/request.js +1099 -0
  159. package/bundle/node_modules/undici/lib/web/fetch/response.js +636 -0
  160. package/bundle/node_modules/undici/lib/web/fetch/util.js +1782 -0
  161. package/bundle/node_modules/undici/lib/web/fetch/webidl.js +740 -0
  162. package/bundle/node_modules/undici/lib/web/websocket/connection.js +325 -0
  163. package/bundle/node_modules/undici/lib/web/websocket/constants.js +126 -0
  164. package/bundle/node_modules/undici/lib/web/websocket/events.js +331 -0
  165. package/bundle/node_modules/undici/lib/web/websocket/frame.js +138 -0
  166. package/bundle/node_modules/undici/lib/web/websocket/permessage-deflate.js +70 -0
  167. package/bundle/node_modules/undici/lib/web/websocket/receiver.js +454 -0
  168. package/bundle/node_modules/undici/lib/web/websocket/sender.js +109 -0
  169. package/bundle/node_modules/undici/lib/web/websocket/stream/websocketerror.js +83 -0
  170. package/bundle/node_modules/undici/lib/web/websocket/stream/websocketstream.js +485 -0
  171. package/bundle/node_modules/undici/lib/web/websocket/util.js +338 -0
  172. package/bundle/node_modules/undici/lib/web/websocket/websocket.js +686 -0
  173. package/bundle/node_modules/undici/package.json +149 -0
  174. package/bundle/node_modules/undici/scripts/strip-comments.js +10 -0
  175. package/bundle/node_modules/undici/types/README.md +6 -0
  176. package/bundle/node_modules/undici/types/agent.d.ts +35 -0
  177. package/bundle/node_modules/undici/types/api.d.ts +43 -0
  178. package/bundle/node_modules/undici/types/balanced-pool.d.ts +29 -0
  179. package/bundle/node_modules/undici/types/cache-interceptor.d.ts +172 -0
  180. package/bundle/node_modules/undici/types/cache.d.ts +36 -0
  181. package/bundle/node_modules/undici/types/client-stats.d.ts +15 -0
  182. package/bundle/node_modules/undici/types/client.d.ts +110 -0
  183. package/bundle/node_modules/undici/types/connector.d.ts +34 -0
  184. package/bundle/node_modules/undici/types/content-type.d.ts +21 -0
  185. package/bundle/node_modules/undici/types/cookies.d.ts +30 -0
  186. package/bundle/node_modules/undici/types/diagnostics-channel.d.ts +66 -0
  187. package/bundle/node_modules/undici/types/dispatcher.d.ts +281 -0
  188. package/bundle/node_modules/undici/types/env-http-proxy-agent.d.ts +21 -0
  189. package/bundle/node_modules/undici/types/errors.d.ts +171 -0
  190. package/bundle/node_modules/undici/types/eventsource.d.ts +61 -0
  191. package/bundle/node_modules/undici/types/fetch.d.ts +210 -0
  192. package/bundle/node_modules/undici/types/formdata.d.ts +108 -0
  193. package/bundle/node_modules/undici/types/global-dispatcher.d.ts +9 -0
  194. package/bundle/node_modules/undici/types/global-origin.d.ts +7 -0
  195. package/bundle/node_modules/undici/types/h2c-client.d.ts +75 -0
  196. package/bundle/node_modules/undici/types/handlers.d.ts +15 -0
  197. package/bundle/node_modules/undici/types/header.d.ts +160 -0
  198. package/bundle/node_modules/undici/types/index.d.ts +75 -0
  199. package/bundle/node_modules/undici/types/interceptors.d.ts +34 -0
  200. package/bundle/node_modules/undici/types/mock-agent.d.ts +68 -0
  201. package/bundle/node_modules/undici/types/mock-call-history.d.ts +111 -0
  202. package/bundle/node_modules/undici/types/mock-client.d.ts +25 -0
  203. package/bundle/node_modules/undici/types/mock-errors.d.ts +12 -0
  204. package/bundle/node_modules/undici/types/mock-interceptor.d.ts +93 -0
  205. package/bundle/node_modules/undici/types/mock-pool.d.ts +25 -0
  206. package/bundle/node_modules/undici/types/patch.d.ts +29 -0
  207. package/bundle/node_modules/undici/types/pool-stats.d.ts +19 -0
  208. package/bundle/node_modules/undici/types/pool.d.ts +41 -0
  209. package/bundle/node_modules/undici/types/proxy-agent.d.ts +29 -0
  210. package/bundle/node_modules/undici/types/readable.d.ts +68 -0
  211. package/bundle/node_modules/undici/types/retry-agent.d.ts +8 -0
  212. package/bundle/node_modules/undici/types/retry-handler.d.ts +116 -0
  213. package/bundle/node_modules/undici/types/util.d.ts +18 -0
  214. package/bundle/node_modules/undici/types/utility.d.ts +7 -0
  215. package/bundle/node_modules/undici/types/webidl.d.ts +266 -0
  216. package/bundle/node_modules/undici/types/websocket.d.ts +184 -0
  217. package/bundle/sandbox-macos-permissive-closed.sb +26 -0
  218. package/bundle/sandbox-macos-permissive-open.sb +19 -0
  219. package/bundle/sandbox-macos-permissive-proxied.sb +31 -0
  220. package/bundle/sandbox-macos-restrictive-closed.sb +87 -0
  221. package/bundle/sandbox-macos-restrictive-open.sb +90 -0
  222. package/bundle/sandbox-macos-restrictive-proxied.sb +92 -0
  223. package/package.json +137 -0
@@ -0,0 +1,448 @@
1
+ 'use strict'
2
+
3
+ const util = require('../core/util')
4
+ const {
5
+ parseCacheControlHeader,
6
+ parseVaryHeader,
7
+ isEtagUsable
8
+ } = require('../util/cache')
9
+ const { parseHttpDate } = require('../util/date.js')
10
+
11
+ function noop () {}
12
+
13
+ // Status codes that we can use some heuristics on to cache
14
+ const HEURISTICALLY_CACHEABLE_STATUS_CODES = [
15
+ 200, 203, 204, 206, 300, 301, 308, 404, 405, 410, 414, 501
16
+ ]
17
+
18
+ const MAX_RESPONSE_AGE = 2147483647000
19
+
20
+ /**
21
+ * @typedef {import('../../types/dispatcher.d.ts').default.DispatchHandler} DispatchHandler
22
+ *
23
+ * @implements {DispatchHandler}
24
+ */
25
+ class CacheHandler {
26
+ /**
27
+ * @type {import('../../types/cache-interceptor.d.ts').default.CacheKey}
28
+ */
29
+ #cacheKey
30
+
31
+ /**
32
+ * @type {import('../../types/cache-interceptor.d.ts').default.CacheHandlerOptions['type']}
33
+ */
34
+ #cacheType
35
+
36
+ /**
37
+ * @type {number | undefined}
38
+ */
39
+ #cacheByDefault
40
+
41
+ /**
42
+ * @type {import('../../types/cache-interceptor.d.ts').default.CacheStore}
43
+ */
44
+ #store
45
+
46
+ /**
47
+ * @type {import('../../types/dispatcher.d.ts').default.DispatchHandler}
48
+ */
49
+ #handler
50
+
51
+ /**
52
+ * @type {import('node:stream').Writable | undefined}
53
+ */
54
+ #writeStream
55
+
56
+ /**
57
+ * @param {import('../../types/cache-interceptor.d.ts').default.CacheHandlerOptions} opts
58
+ * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} cacheKey
59
+ * @param {import('../../types/dispatcher.d.ts').default.DispatchHandler} handler
60
+ */
61
+ constructor ({ store, type, cacheByDefault }, cacheKey, handler) {
62
+ this.#store = store
63
+ this.#cacheType = type
64
+ this.#cacheByDefault = cacheByDefault
65
+ this.#cacheKey = cacheKey
66
+ this.#handler = handler
67
+ }
68
+
69
+ onRequestStart (controller, context) {
70
+ this.#writeStream?.destroy()
71
+ this.#writeStream = undefined
72
+ this.#handler.onRequestStart?.(controller, context)
73
+ }
74
+
75
+ onRequestUpgrade (controller, statusCode, headers, socket) {
76
+ this.#handler.onRequestUpgrade?.(controller, statusCode, headers, socket)
77
+ }
78
+
79
+ /**
80
+ * @param {import('../../types/dispatcher.d.ts').default.DispatchController} controller
81
+ * @param {number} statusCode
82
+ * @param {import('../../types/header.d.ts').IncomingHttpHeaders} resHeaders
83
+ * @param {string} statusMessage
84
+ */
85
+ onResponseStart (
86
+ controller,
87
+ statusCode,
88
+ resHeaders,
89
+ statusMessage
90
+ ) {
91
+ const downstreamOnHeaders = () =>
92
+ this.#handler.onResponseStart?.(
93
+ controller,
94
+ statusCode,
95
+ resHeaders,
96
+ statusMessage
97
+ )
98
+
99
+ if (
100
+ !util.safeHTTPMethods.includes(this.#cacheKey.method) &&
101
+ statusCode >= 200 &&
102
+ statusCode <= 399
103
+ ) {
104
+ // Successful response to an unsafe method, delete it from cache
105
+ // https://www.rfc-editor.org/rfc/rfc9111.html#name-invalidating-stored-response
106
+ try {
107
+ this.#store.delete(this.#cacheKey)?.catch?.(noop)
108
+ } catch {
109
+ // Fail silently
110
+ }
111
+ return downstreamOnHeaders()
112
+ }
113
+
114
+ const cacheControlHeader = resHeaders['cache-control']
115
+ const heuristicallyCacheable = resHeaders['last-modified'] && HEURISTICALLY_CACHEABLE_STATUS_CODES.includes(statusCode)
116
+ if (
117
+ !cacheControlHeader &&
118
+ !resHeaders['expires'] &&
119
+ !heuristicallyCacheable &&
120
+ !this.#cacheByDefault
121
+ ) {
122
+ // Don't have anything to tell us this response is cachable and we're not
123
+ // caching by default
124
+ return downstreamOnHeaders()
125
+ }
126
+
127
+ const cacheControlDirectives = cacheControlHeader ? parseCacheControlHeader(cacheControlHeader) : {}
128
+ if (!canCacheResponse(this.#cacheType, statusCode, resHeaders, cacheControlDirectives)) {
129
+ return downstreamOnHeaders()
130
+ }
131
+
132
+ const now = Date.now()
133
+ const resAge = resHeaders.age ? getAge(resHeaders.age) : undefined
134
+ if (resAge && resAge >= MAX_RESPONSE_AGE) {
135
+ // Response considered stale
136
+ return downstreamOnHeaders()
137
+ }
138
+
139
+ const resDate = typeof resHeaders.date === 'string'
140
+ ? parseHttpDate(resHeaders.date)
141
+ : undefined
142
+
143
+ const staleAt =
144
+ determineStaleAt(this.#cacheType, now, resAge, resHeaders, resDate, cacheControlDirectives) ??
145
+ this.#cacheByDefault
146
+ if (staleAt === undefined || (resAge && resAge > staleAt)) {
147
+ return downstreamOnHeaders()
148
+ }
149
+
150
+ const baseTime = resDate ? resDate.getTime() : now
151
+ const absoluteStaleAt = staleAt + baseTime
152
+ if (now >= absoluteStaleAt) {
153
+ // Response is already stale
154
+ return downstreamOnHeaders()
155
+ }
156
+
157
+ let varyDirectives
158
+ if (this.#cacheKey.headers && resHeaders.vary) {
159
+ varyDirectives = parseVaryHeader(resHeaders.vary, this.#cacheKey.headers)
160
+ if (!varyDirectives) {
161
+ // Parse error
162
+ return downstreamOnHeaders()
163
+ }
164
+ }
165
+
166
+ const deleteAt = determineDeleteAt(baseTime, cacheControlDirectives, absoluteStaleAt)
167
+ const strippedHeaders = stripNecessaryHeaders(resHeaders, cacheControlDirectives)
168
+
169
+ /**
170
+ * @type {import('../../types/cache-interceptor.d.ts').default.CacheValue}
171
+ */
172
+ const value = {
173
+ statusCode,
174
+ statusMessage,
175
+ headers: strippedHeaders,
176
+ vary: varyDirectives,
177
+ cacheControlDirectives,
178
+ cachedAt: resAge ? now - resAge : now,
179
+ staleAt: absoluteStaleAt,
180
+ deleteAt
181
+ }
182
+
183
+ if (typeof resHeaders.etag === 'string' && isEtagUsable(resHeaders.etag)) {
184
+ value.etag = resHeaders.etag
185
+ }
186
+
187
+ this.#writeStream = this.#store.createWriteStream(this.#cacheKey, value)
188
+ if (!this.#writeStream) {
189
+ return downstreamOnHeaders()
190
+ }
191
+
192
+ const handler = this
193
+ this.#writeStream
194
+ .on('drain', () => controller.resume())
195
+ .on('error', function () {
196
+ // TODO (fix): Make error somehow observable?
197
+ handler.#writeStream = undefined
198
+
199
+ // Delete the value in case the cache store is holding onto state from
200
+ // the call to createWriteStream
201
+ handler.#store.delete(handler.#cacheKey)
202
+ })
203
+ .on('close', function () {
204
+ if (handler.#writeStream === this) {
205
+ handler.#writeStream = undefined
206
+ }
207
+
208
+ // TODO (fix): Should we resume even if was paused downstream?
209
+ controller.resume()
210
+ })
211
+
212
+ return downstreamOnHeaders()
213
+ }
214
+
215
+ onResponseData (controller, chunk) {
216
+ if (this.#writeStream?.write(chunk) === false) {
217
+ controller.pause()
218
+ }
219
+
220
+ this.#handler.onResponseData?.(controller, chunk)
221
+ }
222
+
223
+ onResponseEnd (controller, trailers) {
224
+ this.#writeStream?.end()
225
+ this.#handler.onResponseEnd?.(controller, trailers)
226
+ }
227
+
228
+ onResponseError (controller, err) {
229
+ this.#writeStream?.destroy(err)
230
+ this.#writeStream = undefined
231
+ this.#handler.onResponseError?.(controller, err)
232
+ }
233
+ }
234
+
235
+ /**
236
+ * @see https://www.rfc-editor.org/rfc/rfc9111.html#name-storing-responses-to-authen
237
+ *
238
+ * @param {import('../../types/cache-interceptor.d.ts').default.CacheOptions['type']} cacheType
239
+ * @param {number} statusCode
240
+ * @param {import('../../types/header.d.ts').IncomingHttpHeaders} resHeaders
241
+ * @param {import('../../types/cache-interceptor.d.ts').default.CacheControlDirectives} cacheControlDirectives
242
+ */
243
+ function canCacheResponse (cacheType, statusCode, resHeaders, cacheControlDirectives) {
244
+ if (statusCode !== 200 && statusCode !== 307) {
245
+ return false
246
+ }
247
+
248
+ if (cacheControlDirectives['no-store']) {
249
+ return false
250
+ }
251
+
252
+ if (cacheType === 'shared' && cacheControlDirectives.private === true) {
253
+ return false
254
+ }
255
+
256
+ // https://www.rfc-editor.org/rfc/rfc9111.html#section-4.1-5
257
+ if (resHeaders.vary?.includes('*')) {
258
+ return false
259
+ }
260
+
261
+ // https://www.rfc-editor.org/rfc/rfc9111.html#name-storing-responses-to-authen
262
+ if (resHeaders.authorization) {
263
+ if (!cacheControlDirectives.public || typeof resHeaders.authorization !== 'string') {
264
+ return false
265
+ }
266
+
267
+ if (
268
+ Array.isArray(cacheControlDirectives['no-cache']) &&
269
+ cacheControlDirectives['no-cache'].includes('authorization')
270
+ ) {
271
+ return false
272
+ }
273
+
274
+ if (
275
+ Array.isArray(cacheControlDirectives['private']) &&
276
+ cacheControlDirectives['private'].includes('authorization')
277
+ ) {
278
+ return false
279
+ }
280
+ }
281
+
282
+ return true
283
+ }
284
+
285
+ /**
286
+ * @param {string | string[]} ageHeader
287
+ * @returns {number | undefined}
288
+ */
289
+ function getAge (ageHeader) {
290
+ const age = parseInt(Array.isArray(ageHeader) ? ageHeader[0] : ageHeader)
291
+
292
+ return isNaN(age) ? undefined : age * 1000
293
+ }
294
+
295
+ /**
296
+ * @param {import('../../types/cache-interceptor.d.ts').default.CacheOptions['type']} cacheType
297
+ * @param {number} now
298
+ * @param {number | undefined} age
299
+ * @param {import('../../types/header.d.ts').IncomingHttpHeaders} resHeaders
300
+ * @param {Date | undefined} responseDate
301
+ * @param {import('../../types/cache-interceptor.d.ts').default.CacheControlDirectives} cacheControlDirectives
302
+ *
303
+ * @returns {number | undefined} time that the value is stale at in seconds or undefined if it shouldn't be cached
304
+ */
305
+ function determineStaleAt (cacheType, now, age, resHeaders, responseDate, cacheControlDirectives) {
306
+ if (cacheType === 'shared') {
307
+ // Prioritize s-maxage since we're a shared cache
308
+ // s-maxage > max-age > Expire
309
+ // https://www.rfc-editor.org/rfc/rfc9111.html#section-5.2.2.10-3
310
+ const sMaxAge = cacheControlDirectives['s-maxage']
311
+ if (sMaxAge !== undefined) {
312
+ return sMaxAge > 0 ? sMaxAge * 1000 : undefined
313
+ }
314
+ }
315
+
316
+ const maxAge = cacheControlDirectives['max-age']
317
+ if (maxAge !== undefined) {
318
+ return maxAge > 0 ? maxAge * 1000 : undefined
319
+ }
320
+
321
+ if (typeof resHeaders.expires === 'string') {
322
+ // https://www.rfc-editor.org/rfc/rfc9111.html#section-5.3
323
+ const expiresDate = parseHttpDate(resHeaders.expires)
324
+ if (expiresDate) {
325
+ if (now >= expiresDate.getTime()) {
326
+ return undefined
327
+ }
328
+
329
+ if (responseDate) {
330
+ if (responseDate >= expiresDate) {
331
+ return undefined
332
+ }
333
+
334
+ if (age !== undefined && age > (expiresDate - responseDate)) {
335
+ return undefined
336
+ }
337
+ }
338
+
339
+ return expiresDate.getTime() - now
340
+ }
341
+ }
342
+
343
+ if (typeof resHeaders['last-modified'] === 'string') {
344
+ // https://www.rfc-editor.org/rfc/rfc9111.html#name-calculating-heuristic-fresh
345
+ const lastModified = new Date(resHeaders['last-modified'])
346
+ if (isValidDate(lastModified)) {
347
+ if (lastModified.getTime() >= now) {
348
+ return undefined
349
+ }
350
+
351
+ const responseAge = now - lastModified.getTime()
352
+
353
+ return responseAge * 0.1
354
+ }
355
+ }
356
+
357
+ if (cacheControlDirectives.immutable) {
358
+ // https://www.rfc-editor.org/rfc/rfc8246.html#section-2.2
359
+ return 31536000
360
+ }
361
+
362
+ return undefined
363
+ }
364
+
365
+ /**
366
+ * @param {number} now
367
+ * @param {import('../../types/cache-interceptor.d.ts').default.CacheControlDirectives} cacheControlDirectives
368
+ * @param {number} staleAt
369
+ */
370
+ function determineDeleteAt (now, cacheControlDirectives, staleAt) {
371
+ let staleWhileRevalidate = -Infinity
372
+ let staleIfError = -Infinity
373
+ let immutable = -Infinity
374
+
375
+ if (cacheControlDirectives['stale-while-revalidate']) {
376
+ staleWhileRevalidate = staleAt + (cacheControlDirectives['stale-while-revalidate'] * 1000)
377
+ }
378
+
379
+ if (cacheControlDirectives['stale-if-error']) {
380
+ staleIfError = staleAt + (cacheControlDirectives['stale-if-error'] * 1000)
381
+ }
382
+
383
+ if (staleWhileRevalidate === -Infinity && staleIfError === -Infinity) {
384
+ immutable = now + 31536000000
385
+ }
386
+
387
+ return Math.max(staleAt, staleWhileRevalidate, staleIfError, immutable)
388
+ }
389
+
390
+ /**
391
+ * Strips headers required to be removed in cached responses
392
+ * @param {import('../../types/header.d.ts').IncomingHttpHeaders} resHeaders
393
+ * @param {import('../../types/cache-interceptor.d.ts').default.CacheControlDirectives} cacheControlDirectives
394
+ * @returns {Record<string, string | string []>}
395
+ */
396
+ function stripNecessaryHeaders (resHeaders, cacheControlDirectives) {
397
+ const headersToRemove = [
398
+ 'connection',
399
+ 'proxy-authenticate',
400
+ 'proxy-authentication-info',
401
+ 'proxy-authorization',
402
+ 'proxy-connection',
403
+ 'te',
404
+ 'transfer-encoding',
405
+ 'upgrade',
406
+ // We'll add age back when serving it
407
+ 'age'
408
+ ]
409
+
410
+ if (resHeaders['connection']) {
411
+ if (Array.isArray(resHeaders['connection'])) {
412
+ // connection: a
413
+ // connection: b
414
+ headersToRemove.push(...resHeaders['connection'].map(header => header.trim()))
415
+ } else {
416
+ // connection: a, b
417
+ headersToRemove.push(...resHeaders['connection'].split(',').map(header => header.trim()))
418
+ }
419
+ }
420
+
421
+ if (Array.isArray(cacheControlDirectives['no-cache'])) {
422
+ headersToRemove.push(...cacheControlDirectives['no-cache'])
423
+ }
424
+
425
+ if (Array.isArray(cacheControlDirectives['private'])) {
426
+ headersToRemove.push(...cacheControlDirectives['private'])
427
+ }
428
+
429
+ let strippedHeaders
430
+ for (const headerName of headersToRemove) {
431
+ if (resHeaders[headerName]) {
432
+ strippedHeaders ??= { ...resHeaders }
433
+ delete strippedHeaders[headerName]
434
+ }
435
+ }
436
+
437
+ return strippedHeaders ?? resHeaders
438
+ }
439
+
440
+ /**
441
+ * @param {Date} date
442
+ * @returns {boolean}
443
+ */
444
+ function isValidDate (date) {
445
+ return date instanceof Date && Number.isFinite(date.valueOf())
446
+ }
447
+
448
+ module.exports = CacheHandler
@@ -0,0 +1,124 @@
1
+ 'use strict'
2
+
3
+ const assert = require('node:assert')
4
+
5
+ /**
6
+ * This takes care of revalidation requests we send to the origin. If we get
7
+ * a response indicating that what we have is cached (via a HTTP 304), we can
8
+ * continue using the cached value. Otherwise, we'll receive the new response
9
+ * here, which we then just pass on to the next handler (most likely a
10
+ * CacheHandler). Note that this assumes the proper headers were already
11
+ * included in the request to tell the origin that we want to revalidate the
12
+ * response (i.e. if-modified-since or if-none-match).
13
+ *
14
+ * @see https://www.rfc-editor.org/rfc/rfc9111.html#name-validation
15
+ *
16
+ * @implements {import('../../types/dispatcher.d.ts').default.DispatchHandler}
17
+ */
18
+ class CacheRevalidationHandler {
19
+ #successful = false
20
+
21
+ /**
22
+ * @type {((boolean, any) => void) | null}
23
+ */
24
+ #callback
25
+
26
+ /**
27
+ * @type {(import('../../types/dispatcher.d.ts').default.DispatchHandler)}
28
+ */
29
+ #handler
30
+
31
+ #context
32
+
33
+ /**
34
+ * @type {boolean}
35
+ */
36
+ #allowErrorStatusCodes
37
+
38
+ /**
39
+ * @param {(boolean) => void} callback Function to call if the cached value is valid
40
+ * @param {import('../../types/dispatcher.d.ts').default.DispatchHandlers} handler
41
+ * @param {boolean} allowErrorStatusCodes
42
+ */
43
+ constructor (callback, handler, allowErrorStatusCodes) {
44
+ if (typeof callback !== 'function') {
45
+ throw new TypeError('callback must be a function')
46
+ }
47
+
48
+ this.#callback = callback
49
+ this.#handler = handler
50
+ this.#allowErrorStatusCodes = allowErrorStatusCodes
51
+ }
52
+
53
+ onRequestStart (_, context) {
54
+ this.#successful = false
55
+ this.#context = context
56
+ }
57
+
58
+ onRequestUpgrade (controller, statusCode, headers, socket) {
59
+ this.#handler.onRequestUpgrade?.(controller, statusCode, headers, socket)
60
+ }
61
+
62
+ onResponseStart (
63
+ controller,
64
+ statusCode,
65
+ headers,
66
+ statusMessage
67
+ ) {
68
+ assert(this.#callback != null)
69
+
70
+ // https://www.rfc-editor.org/rfc/rfc9111.html#name-handling-a-validation-respo
71
+ // https://datatracker.ietf.org/doc/html/rfc5861#section-4
72
+ this.#successful = statusCode === 304 ||
73
+ (this.#allowErrorStatusCodes && statusCode >= 500 && statusCode <= 504)
74
+ this.#callback(this.#successful, this.#context)
75
+ this.#callback = null
76
+
77
+ if (this.#successful) {
78
+ return true
79
+ }
80
+
81
+ this.#handler.onRequestStart?.(controller, this.#context)
82
+ this.#handler.onResponseStart?.(
83
+ controller,
84
+ statusCode,
85
+ headers,
86
+ statusMessage
87
+ )
88
+ }
89
+
90
+ onResponseData (controller, chunk) {
91
+ if (this.#successful) {
92
+ return
93
+ }
94
+
95
+ return this.#handler.onResponseData?.(controller, chunk)
96
+ }
97
+
98
+ onResponseEnd (controller, trailers) {
99
+ if (this.#successful) {
100
+ return
101
+ }
102
+
103
+ this.#handler.onResponseEnd?.(controller, trailers)
104
+ }
105
+
106
+ onResponseError (controller, err) {
107
+ if (this.#successful) {
108
+ return
109
+ }
110
+
111
+ if (this.#callback) {
112
+ this.#callback(false)
113
+ this.#callback = null
114
+ }
115
+
116
+ if (typeof this.#handler.onResponseError === 'function') {
117
+ this.#handler.onResponseError(controller, err)
118
+ } else {
119
+ throw err
120
+ }
121
+ }
122
+ }
123
+
124
+ module.exports = CacheRevalidationHandler
@@ -0,0 +1,67 @@
1
+ 'use strict'
2
+
3
+ const assert = require('node:assert')
4
+ const WrapHandler = require('./wrap-handler')
5
+
6
+ /**
7
+ * @deprecated
8
+ */
9
+ module.exports = class DecoratorHandler {
10
+ #handler
11
+ #onCompleteCalled = false
12
+ #onErrorCalled = false
13
+ #onResponseStartCalled = false
14
+
15
+ constructor (handler) {
16
+ if (typeof handler !== 'object' || handler === null) {
17
+ throw new TypeError('handler must be an object')
18
+ }
19
+ this.#handler = WrapHandler.wrap(handler)
20
+ }
21
+
22
+ onRequestStart (...args) {
23
+ this.#handler.onRequestStart?.(...args)
24
+ }
25
+
26
+ onRequestUpgrade (...args) {
27
+ assert(!this.#onCompleteCalled)
28
+ assert(!this.#onErrorCalled)
29
+
30
+ return this.#handler.onRequestUpgrade?.(...args)
31
+ }
32
+
33
+ onResponseStart (...args) {
34
+ assert(!this.#onCompleteCalled)
35
+ assert(!this.#onErrorCalled)
36
+ assert(!this.#onResponseStartCalled)
37
+
38
+ this.#onResponseStartCalled = true
39
+
40
+ return this.#handler.onResponseStart?.(...args)
41
+ }
42
+
43
+ onResponseData (...args) {
44
+ assert(!this.#onCompleteCalled)
45
+ assert(!this.#onErrorCalled)
46
+
47
+ return this.#handler.onResponseData?.(...args)
48
+ }
49
+
50
+ onResponseEnd (...args) {
51
+ assert(!this.#onCompleteCalled)
52
+ assert(!this.#onErrorCalled)
53
+
54
+ this.#onCompleteCalled = true
55
+ return this.#handler.onResponseEnd?.(...args)
56
+ }
57
+
58
+ onResponseError (...args) {
59
+ this.#onErrorCalled = true
60
+ return this.#handler.onResponseError?.(...args)
61
+ }
62
+
63
+ /**
64
+ * @deprecated
65
+ */
66
+ onBodySent () {}
67
+ }