@fgv/ts-extras 5.1.0-5 → 5.1.0-50

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 (488) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +90 -0
  3. package/dist/index.browser.js +6 -2
  4. package/dist/index.browser.js.map +1 -0
  5. package/dist/index.js +2 -1
  6. package/dist/index.js.map +1 -0
  7. package/dist/packlets/ai-assist/chatRequestBuilders.js +282 -0
  8. package/dist/packlets/ai-assist/chatRequestBuilders.js.map +1 -0
  9. package/dist/packlets/ai-assist/{apiClient.js → completionClient.js} +165 -214
  10. package/dist/packlets/ai-assist/completionClient.js.map +1 -0
  11. package/dist/packlets/ai-assist/converters.js +47 -3
  12. package/dist/packlets/ai-assist/converters.js.map +1 -0
  13. package/dist/packlets/ai-assist/embeddingClient.js +345 -0
  14. package/dist/packlets/ai-assist/embeddingClient.js.map +1 -0
  15. package/dist/packlets/ai-assist/endpoint.js +107 -0
  16. package/dist/packlets/ai-assist/endpoint.js.map +1 -0
  17. package/dist/packlets/ai-assist/http.js +104 -0
  18. package/dist/packlets/ai-assist/http.js.map +1 -0
  19. package/dist/packlets/ai-assist/imageGenerationClient.js +454 -0
  20. package/dist/packlets/ai-assist/imageGenerationClient.js.map +1 -0
  21. package/dist/packlets/ai-assist/imageOptionsResolver.js +193 -0
  22. package/dist/packlets/ai-assist/imageOptionsResolver.js.map +1 -0
  23. package/dist/packlets/ai-assist/index.js +12 -4
  24. package/dist/packlets/ai-assist/index.js.map +1 -0
  25. package/dist/packlets/ai-assist/jsonCompletion.js +93 -0
  26. package/dist/packlets/ai-assist/jsonCompletion.js.map +1 -0
  27. package/dist/packlets/ai-assist/jsonResponse.js +423 -0
  28. package/dist/packlets/ai-assist/jsonResponse.js.map +1 -0
  29. package/dist/packlets/ai-assist/listModelsClient.js +294 -0
  30. package/dist/packlets/ai-assist/listModelsClient.js.map +1 -0
  31. package/dist/packlets/ai-assist/model.js +301 -9
  32. package/dist/packlets/ai-assist/model.js.map +1 -0
  33. package/dist/packlets/ai-assist/registry.js +376 -12
  34. package/dist/packlets/ai-assist/registry.js.map +1 -0
  35. package/dist/packlets/ai-assist/sseParser.js +123 -0
  36. package/dist/packlets/ai-assist/sseParser.js.map +1 -0
  37. package/dist/packlets/ai-assist/streamingAdapters/anthropic.js +376 -0
  38. package/dist/packlets/ai-assist/streamingAdapters/anthropic.js.map +1 -0
  39. package/dist/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js +687 -0
  40. package/dist/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js.map +1 -0
  41. package/dist/packlets/ai-assist/streamingAdapters/common.js +187 -0
  42. package/dist/packlets/ai-assist/streamingAdapters/common.js.map +1 -0
  43. package/dist/packlets/ai-assist/streamingAdapters/gemini.js +208 -0
  44. package/dist/packlets/ai-assist/streamingAdapters/gemini.js.map +1 -0
  45. package/dist/packlets/ai-assist/streamingAdapters/openaiChat.js +175 -0
  46. package/dist/packlets/ai-assist/streamingAdapters/openaiChat.js.map +1 -0
  47. package/dist/packlets/ai-assist/streamingAdapters/openaiResponses.js +390 -0
  48. package/dist/packlets/ai-assist/streamingAdapters/openaiResponses.js.map +1 -0
  49. package/dist/packlets/ai-assist/streamingAdapters/proxy.js +178 -0
  50. package/dist/packlets/ai-assist/streamingAdapters/proxy.js.map +1 -0
  51. package/dist/packlets/ai-assist/streamingClient.js +140 -0
  52. package/dist/packlets/ai-assist/streamingClient.js.map +1 -0
  53. package/dist/packlets/ai-assist/thinkingOptionsResolver.js +288 -0
  54. package/dist/packlets/ai-assist/thinkingOptionsResolver.js.map +1 -0
  55. package/dist/packlets/ai-assist/toolFormats.js +106 -10
  56. package/dist/packlets/ai-assist/toolFormats.js.map +1 -0
  57. package/dist/packlets/conversion/converters.js +35 -1
  58. package/dist/packlets/conversion/converters.js.map +1 -0
  59. package/dist/packlets/conversion/index.js.map +1 -0
  60. package/dist/packlets/crypto-utils/constants.js.map +1 -0
  61. package/dist/packlets/crypto-utils/converters.js +42 -4
  62. package/dist/packlets/crypto-utils/converters.js.map +1 -0
  63. package/dist/packlets/crypto-utils/directEncryptionProvider.js.map +1 -0
  64. package/dist/packlets/crypto-utils/encryptedFile.js +37 -0
  65. package/dist/packlets/crypto-utils/encryptedFile.js.map +1 -0
  66. package/dist/packlets/crypto-utils/hpkeProvider.js +355 -0
  67. package/dist/packlets/crypto-utils/hpkeProvider.js.map +1 -0
  68. package/dist/packlets/crypto-utils/index.browser.js +13 -2
  69. package/dist/packlets/crypto-utils/index.browser.js.map +1 -0
  70. package/dist/packlets/crypto-utils/index.js +9 -1
  71. package/dist/packlets/crypto-utils/index.js.map +1 -0
  72. package/dist/packlets/crypto-utils/keyPairAlgorithmParams.js +71 -0
  73. package/dist/packlets/crypto-utils/keyPairAlgorithmParams.js.map +1 -0
  74. package/dist/packlets/crypto-utils/keystore/converters.js +111 -16
  75. package/dist/packlets/crypto-utils/keystore/converters.js.map +1 -0
  76. package/dist/packlets/crypto-utils/keystore/encryptedFilePrivateKeyStorage.js +287 -0
  77. package/dist/packlets/crypto-utils/keystore/encryptedFilePrivateKeyStorage.js.map +1 -0
  78. package/dist/packlets/crypto-utils/keystore/index.browser.js +36 -0
  79. package/dist/packlets/crypto-utils/keystore/index.browser.js.map +1 -0
  80. package/dist/packlets/crypto-utils/keystore/index.js +3 -0
  81. package/dist/packlets/crypto-utils/keystore/index.js.map +1 -0
  82. package/dist/packlets/crypto-utils/keystore/keyStore.js +872 -119
  83. package/dist/packlets/crypto-utils/keystore/keyStore.js.map +1 -0
  84. package/dist/packlets/crypto-utils/keystore/model.js +35 -4
  85. package/dist/packlets/crypto-utils/keystore/model.js.map +1 -0
  86. package/dist/packlets/crypto-utils/keystore/privateKeyStorage.js +21 -0
  87. package/dist/packlets/crypto-utils/keystore/privateKeyStorage.js.map +1 -0
  88. package/dist/packlets/crypto-utils/model.js +32 -0
  89. package/dist/packlets/crypto-utils/model.js.map +1 -0
  90. package/dist/packlets/crypto-utils/nodeCryptoProvider.js +347 -1
  91. package/dist/packlets/crypto-utils/nodeCryptoProvider.js.map +1 -0
  92. package/dist/packlets/crypto-utils/seedDerivedKeyPair.js +120 -0
  93. package/dist/packlets/crypto-utils/seedDerivedKeyPair.js.map +1 -0
  94. package/dist/packlets/crypto-utils/spkiHelpers.js +284 -0
  95. package/dist/packlets/crypto-utils/spkiHelpers.js.map +1 -0
  96. package/dist/packlets/csv/csvFileHelpers.js +0 -14
  97. package/dist/packlets/csv/csvFileHelpers.js.map +1 -0
  98. package/dist/packlets/csv/csvHelpers.js +14 -0
  99. package/dist/packlets/csv/csvHelpers.js.map +1 -0
  100. package/dist/packlets/csv/index.browser.js +1 -3
  101. package/dist/packlets/csv/index.browser.js.map +1 -0
  102. package/dist/packlets/csv/index.js.map +1 -0
  103. package/dist/packlets/experimental/extendedArray.js.map +1 -0
  104. package/dist/packlets/experimental/formatter.js.map +1 -0
  105. package/dist/packlets/experimental/index.js.map +1 -0
  106. package/dist/packlets/experimental/rangeOf.js.map +1 -0
  107. package/dist/packlets/hash/index.browser.js.map +1 -0
  108. package/dist/packlets/hash/index.js.map +1 -0
  109. package/dist/packlets/hash/index.node.js.map +1 -0
  110. package/dist/packlets/hash/md5Normalizer.browser.js.map +1 -0
  111. package/dist/packlets/hash/md5Normalizer.js.map +1 -0
  112. package/dist/packlets/mustache/index.js.map +1 -0
  113. package/dist/packlets/mustache/interfaces.js.map +1 -0
  114. package/dist/packlets/mustache/mustacheTemplate.js +42 -4
  115. package/dist/packlets/mustache/mustacheTemplate.js.map +1 -0
  116. package/dist/packlets/record-jar/index.browser.js +1 -3
  117. package/dist/packlets/record-jar/index.browser.js.map +1 -0
  118. package/dist/packlets/record-jar/index.js.map +1 -0
  119. package/dist/packlets/record-jar/recordJarFileHelpers.js +0 -18
  120. package/dist/packlets/record-jar/recordJarFileHelpers.js.map +1 -0
  121. package/dist/packlets/record-jar/recordJarHelpers.js +18 -0
  122. package/dist/packlets/record-jar/recordJarHelpers.js.map +1 -0
  123. package/dist/packlets/safer-fetch/addressClassification.js +438 -0
  124. package/dist/packlets/safer-fetch/addressClassification.js.map +1 -0
  125. package/dist/packlets/safer-fetch/addressPolicy.js +119 -0
  126. package/dist/packlets/safer-fetch/addressPolicy.js.map +1 -0
  127. package/dist/packlets/safer-fetch/contentType.js +120 -0
  128. package/dist/packlets/safer-fetch/contentType.js.map +1 -0
  129. package/dist/packlets/safer-fetch/deadline.js +254 -0
  130. package/dist/packlets/safer-fetch/deadline.js.map +1 -0
  131. package/dist/packlets/safer-fetch/defaults.js +131 -0
  132. package/dist/packlets/safer-fetch/defaults.js.map +1 -0
  133. package/dist/packlets/safer-fetch/failureReason.js +21 -0
  134. package/dist/packlets/safer-fetch/failureReason.js.map +1 -0
  135. package/dist/packlets/safer-fetch/guards.js +148 -0
  136. package/dist/packlets/safer-fetch/guards.js.map +1 -0
  137. package/dist/packlets/safer-fetch/index.browser.js +58 -0
  138. package/dist/packlets/safer-fetch/index.browser.js.map +1 -0
  139. package/dist/packlets/safer-fetch/index.js +52 -0
  140. package/dist/packlets/safer-fetch/index.js.map +1 -0
  141. package/dist/packlets/safer-fetch/model.js +21 -0
  142. package/dist/packlets/safer-fetch/model.js.map +1 -0
  143. package/dist/packlets/safer-fetch/nodeAddressGuard.js +191 -0
  144. package/dist/packlets/safer-fetch/nodeAddressGuard.js.map +1 -0
  145. package/dist/packlets/safer-fetch/redirect.js +93 -0
  146. package/dist/packlets/safer-fetch/redirect.js.map +1 -0
  147. package/dist/packlets/safer-fetch/retry.js +188 -0
  148. package/dist/packlets/safer-fetch/retry.js.map +1 -0
  149. package/dist/packlets/safer-fetch/saferFetch.js +755 -0
  150. package/dist/packlets/safer-fetch/saferFetch.js.map +1 -0
  151. package/dist/packlets/safer-fetch/transport.js +50 -0
  152. package/dist/packlets/safer-fetch/transport.js.map +1 -0
  153. package/dist/packlets/yaml/converters.js.map +1 -0
  154. package/dist/packlets/yaml/index.js +1 -0
  155. package/dist/packlets/yaml/index.js.map +1 -0
  156. package/dist/packlets/yaml/serializers.js +48 -0
  157. package/dist/packlets/yaml/serializers.js.map +1 -0
  158. package/dist/packlets/zip-file-tree/index.js.map +1 -0
  159. package/dist/packlets/zip-file-tree/zipFileTreeAccessors.js +99 -9
  160. package/dist/packlets/zip-file-tree/zipFileTreeAccessors.js.map +1 -0
  161. package/dist/packlets/zip-file-tree/zipFileTreeWriter.js +16 -1
  162. package/dist/packlets/zip-file-tree/zipFileTreeWriter.js.map +1 -0
  163. package/dist/ts-extras.d.ts +6648 -553
  164. package/dist/tsdoc-metadata.json +1 -1
  165. package/lib/index.browser.d.ts +5 -2
  166. package/lib/index.browser.d.ts.map +1 -0
  167. package/lib/index.browser.js +11 -3
  168. package/lib/index.browser.js.map +1 -0
  169. package/lib/index.d.ts +2 -1
  170. package/lib/index.d.ts.map +1 -0
  171. package/lib/index.js +3 -1
  172. package/lib/index.js.map +1 -0
  173. package/lib/packlets/ai-assist/chatRequestBuilders.d.ts +149 -0
  174. package/lib/packlets/ai-assist/chatRequestBuilders.d.ts.map +1 -0
  175. package/lib/packlets/ai-assist/chatRequestBuilders.js +293 -0
  176. package/lib/packlets/ai-assist/chatRequestBuilders.js.map +1 -0
  177. package/lib/packlets/ai-assist/completionClient.d.ts +74 -0
  178. package/lib/packlets/ai-assist/completionClient.d.ts.map +1 -0
  179. package/lib/packlets/ai-assist/{apiClient.js → completionClient.js} +164 -213
  180. package/lib/packlets/ai-assist/completionClient.js.map +1 -0
  181. package/lib/packlets/ai-assist/converters.d.ts +15 -1
  182. package/lib/packlets/ai-assist/converters.d.ts.map +1 -0
  183. package/lib/packlets/ai-assist/converters.js +47 -3
  184. package/lib/packlets/ai-assist/converters.js.map +1 -0
  185. package/lib/packlets/ai-assist/embeddingClient.d.ts +69 -0
  186. package/lib/packlets/ai-assist/embeddingClient.d.ts.map +1 -0
  187. package/lib/packlets/ai-assist/embeddingClient.js +349 -0
  188. package/lib/packlets/ai-assist/embeddingClient.js.map +1 -0
  189. package/lib/packlets/ai-assist/endpoint.d.ts +49 -0
  190. package/lib/packlets/ai-assist/endpoint.d.ts.map +1 -0
  191. package/lib/packlets/ai-assist/endpoint.js +113 -0
  192. package/lib/packlets/ai-assist/endpoint.js.map +1 -0
  193. package/lib/packlets/ai-assist/http.d.ts +34 -0
  194. package/lib/packlets/ai-assist/http.d.ts.map +1 -0
  195. package/lib/packlets/ai-assist/http.js +109 -0
  196. package/lib/packlets/ai-assist/http.js.map +1 -0
  197. package/lib/packlets/ai-assist/imageGenerationClient.d.ts +46 -0
  198. package/lib/packlets/ai-assist/imageGenerationClient.d.ts.map +1 -0
  199. package/lib/packlets/ai-assist/imageGenerationClient.js +458 -0
  200. package/lib/packlets/ai-assist/imageGenerationClient.js.map +1 -0
  201. package/lib/packlets/ai-assist/imageOptionsResolver.d.ts +66 -0
  202. package/lib/packlets/ai-assist/imageOptionsResolver.d.ts.map +1 -0
  203. package/lib/packlets/ai-assist/imageOptionsResolver.js +197 -0
  204. package/lib/packlets/ai-assist/imageOptionsResolver.js.map +1 -0
  205. package/lib/packlets/ai-assist/index.d.ts +12 -4
  206. package/lib/packlets/ai-assist/index.d.ts.map +1 -0
  207. package/lib/packlets/ai-assist/index.js +47 -4
  208. package/lib/packlets/ai-assist/index.js.map +1 -0
  209. package/lib/packlets/ai-assist/jsonCompletion.d.ts +93 -0
  210. package/lib/packlets/ai-assist/jsonCompletion.d.ts.map +1 -0
  211. package/lib/packlets/ai-assist/jsonCompletion.js +97 -0
  212. package/lib/packlets/ai-assist/jsonCompletion.js.map +1 -0
  213. package/lib/packlets/ai-assist/jsonResponse.d.ts +194 -0
  214. package/lib/packlets/ai-assist/jsonResponse.d.ts.map +1 -0
  215. package/lib/packlets/ai-assist/jsonResponse.js +429 -0
  216. package/lib/packlets/ai-assist/jsonResponse.js.map +1 -0
  217. package/lib/packlets/ai-assist/listModelsClient.d.ts +46 -0
  218. package/lib/packlets/ai-assist/listModelsClient.d.ts.map +1 -0
  219. package/lib/packlets/ai-assist/listModelsClient.js +298 -0
  220. package/lib/packlets/ai-assist/listModelsClient.js.map +1 -0
  221. package/lib/packlets/ai-assist/model.d.ts +1346 -12
  222. package/lib/packlets/ai-assist/model.d.ts.map +1 -0
  223. package/lib/packlets/ai-assist/model.js +309 -10
  224. package/lib/packlets/ai-assist/model.js.map +1 -0
  225. package/lib/packlets/ai-assist/registry.d.ts +76 -1
  226. package/lib/packlets/ai-assist/registry.d.ts.map +1 -0
  227. package/lib/packlets/ai-assist/registry.js +381 -13
  228. package/lib/packlets/ai-assist/registry.js.map +1 -0
  229. package/lib/packlets/ai-assist/sseParser.d.ts +45 -0
  230. package/lib/packlets/ai-assist/sseParser.d.ts.map +1 -0
  231. package/lib/packlets/ai-assist/sseParser.js +128 -0
  232. package/lib/packlets/ai-assist/sseParser.js.map +1 -0
  233. package/lib/packlets/ai-assist/streamingAdapters/anthropic.d.ts +72 -0
  234. package/lib/packlets/ai-assist/streamingAdapters/anthropic.d.ts.map +1 -0
  235. package/lib/packlets/ai-assist/streamingAdapters/anthropic.js +379 -0
  236. package/lib/packlets/ai-assist/streamingAdapters/anthropic.js.map +1 -0
  237. package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.d.ts +269 -0
  238. package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.d.ts.map +1 -0
  239. package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js +694 -0
  240. package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js.map +1 -0
  241. package/lib/packlets/ai-assist/streamingAdapters/common.d.ts +163 -0
  242. package/lib/packlets/ai-assist/streamingAdapters/common.d.ts.map +1 -0
  243. package/lib/packlets/ai-assist/streamingAdapters/common.js +193 -0
  244. package/lib/packlets/ai-assist/streamingAdapters/common.js.map +1 -0
  245. package/lib/packlets/ai-assist/streamingAdapters/gemini.d.ts +43 -0
  246. package/lib/packlets/ai-assist/streamingAdapters/gemini.d.ts.map +1 -0
  247. package/lib/packlets/ai-assist/streamingAdapters/gemini.js +211 -0
  248. package/lib/packlets/ai-assist/streamingAdapters/gemini.js.map +1 -0
  249. package/lib/packlets/ai-assist/streamingAdapters/openaiChat.d.ts +19 -0
  250. package/lib/packlets/ai-assist/streamingAdapters/openaiChat.d.ts.map +1 -0
  251. package/lib/packlets/ai-assist/streamingAdapters/openaiChat.js +178 -0
  252. package/lib/packlets/ai-assist/streamingAdapters/openaiChat.js.map +1 -0
  253. package/lib/packlets/ai-assist/streamingAdapters/openaiResponses.d.ts +33 -0
  254. package/lib/packlets/ai-assist/streamingAdapters/openaiResponses.d.ts.map +1 -0
  255. package/lib/packlets/ai-assist/streamingAdapters/openaiResponses.js +393 -0
  256. package/lib/packlets/ai-assist/streamingAdapters/openaiResponses.js.map +1 -0
  257. package/lib/packlets/ai-assist/streamingAdapters/proxy.d.ts +34 -0
  258. package/lib/packlets/ai-assist/streamingAdapters/proxy.d.ts.map +1 -0
  259. package/lib/packlets/ai-assist/streamingAdapters/proxy.js +181 -0
  260. package/lib/packlets/ai-assist/streamingAdapters/proxy.js.map +1 -0
  261. package/lib/packlets/ai-assist/streamingClient.d.ts +50 -0
  262. package/lib/packlets/ai-assist/streamingClient.d.ts.map +1 -0
  263. package/lib/packlets/ai-assist/streamingClient.js +146 -0
  264. package/lib/packlets/ai-assist/streamingClient.js.map +1 -0
  265. package/lib/packlets/ai-assist/thinkingOptionsResolver.d.ts +87 -0
  266. package/lib/packlets/ai-assist/thinkingOptionsResolver.d.ts.map +1 -0
  267. package/lib/packlets/ai-assist/thinkingOptionsResolver.js +294 -0
  268. package/lib/packlets/ai-assist/thinkingOptionsResolver.js.map +1 -0
  269. package/lib/packlets/ai-assist/toolFormats.d.ts +40 -9
  270. package/lib/packlets/ai-assist/toolFormats.d.ts.map +1 -0
  271. package/lib/packlets/ai-assist/toolFormats.js +107 -10
  272. package/lib/packlets/ai-assist/toolFormats.js.map +1 -0
  273. package/lib/packlets/conversion/converters.d.ts +8 -1
  274. package/lib/packlets/conversion/converters.d.ts.map +1 -0
  275. package/lib/packlets/conversion/converters.js +36 -2
  276. package/lib/packlets/conversion/converters.js.map +1 -0
  277. package/lib/packlets/conversion/index.d.ts.map +1 -0
  278. package/lib/packlets/conversion/index.js.map +1 -0
  279. package/lib/packlets/crypto-utils/constants.d.ts.map +1 -0
  280. package/lib/packlets/crypto-utils/constants.js.map +1 -0
  281. package/lib/packlets/crypto-utils/converters.d.ts +20 -1
  282. package/lib/packlets/crypto-utils/converters.d.ts.map +1 -0
  283. package/lib/packlets/crypto-utils/converters.js +43 -5
  284. package/lib/packlets/crypto-utils/converters.js.map +1 -0
  285. package/lib/packlets/crypto-utils/directEncryptionProvider.d.ts.map +1 -0
  286. package/lib/packlets/crypto-utils/directEncryptionProvider.js.map +1 -0
  287. package/lib/packlets/crypto-utils/encryptedFile.d.ts +25 -0
  288. package/lib/packlets/crypto-utils/encryptedFile.d.ts.map +1 -0
  289. package/lib/packlets/crypto-utils/encryptedFile.js +38 -0
  290. package/lib/packlets/crypto-utils/encryptedFile.js.map +1 -0
  291. package/lib/packlets/crypto-utils/hpkeProvider.d.ts +150 -0
  292. package/lib/packlets/crypto-utils/hpkeProvider.d.ts.map +1 -0
  293. package/lib/packlets/crypto-utils/hpkeProvider.js +359 -0
  294. package/lib/packlets/crypto-utils/hpkeProvider.js.map +1 -0
  295. package/lib/packlets/crypto-utils/index.browser.d.ts +5 -1
  296. package/lib/packlets/crypto-utils/index.browser.d.ts.map +1 -0
  297. package/lib/packlets/crypto-utils/index.browser.js +28 -3
  298. package/lib/packlets/crypto-utils/index.browser.js.map +1 -0
  299. package/lib/packlets/crypto-utils/index.d.ts +5 -1
  300. package/lib/packlets/crypto-utils/index.d.ts.map +1 -0
  301. package/lib/packlets/crypto-utils/index.js +24 -1
  302. package/lib/packlets/crypto-utils/index.js.map +1 -0
  303. package/lib/packlets/crypto-utils/keyPairAlgorithmParams.d.ts +54 -0
  304. package/lib/packlets/crypto-utils/keyPairAlgorithmParams.d.ts.map +1 -0
  305. package/lib/packlets/crypto-utils/keyPairAlgorithmParams.js +74 -0
  306. package/lib/packlets/crypto-utils/keyPairAlgorithmParams.js.map +1 -0
  307. package/lib/packlets/crypto-utils/keystore/converters.d.ts +68 -6
  308. package/lib/packlets/crypto-utils/keystore/converters.d.ts.map +1 -0
  309. package/lib/packlets/crypto-utils/keystore/converters.js +109 -14
  310. package/lib/packlets/crypto-utils/keystore/converters.js.map +1 -0
  311. package/lib/packlets/crypto-utils/keystore/encryptedFilePrivateKeyStorage.d.ts +148 -0
  312. package/lib/packlets/crypto-utils/keystore/encryptedFilePrivateKeyStorage.d.ts.map +1 -0
  313. package/lib/packlets/crypto-utils/keystore/encryptedFilePrivateKeyStorage.js +324 -0
  314. package/lib/packlets/crypto-utils/keystore/encryptedFilePrivateKeyStorage.js.map +1 -0
  315. package/lib/packlets/crypto-utils/keystore/index.browser.d.ts +10 -0
  316. package/lib/packlets/crypto-utils/keystore/index.browser.d.ts.map +1 -0
  317. package/lib/packlets/crypto-utils/keystore/index.browser.js +76 -0
  318. package/lib/packlets/crypto-utils/keystore/index.browser.js.map +1 -0
  319. package/lib/packlets/crypto-utils/keystore/index.d.ts +2 -0
  320. package/lib/packlets/crypto-utils/keystore/index.d.ts.map +1 -0
  321. package/lib/packlets/crypto-utils/keystore/index.js +5 -1
  322. package/lib/packlets/crypto-utils/keystore/index.js.map +1 -0
  323. package/lib/packlets/crypto-utils/keystore/keyStore.d.ts +314 -13
  324. package/lib/packlets/crypto-utils/keystore/keyStore.d.ts.map +1 -0
  325. package/lib/packlets/crypto-utils/keystore/keyStore.js +877 -124
  326. package/lib/packlets/crypto-utils/keystore/keyStore.js.map +1 -0
  327. package/lib/packlets/crypto-utils/keystore/model.d.ts +404 -21
  328. package/lib/packlets/crypto-utils/keystore/model.d.ts.map +1 -0
  329. package/lib/packlets/crypto-utils/keystore/model.js +37 -5
  330. package/lib/packlets/crypto-utils/keystore/model.js.map +1 -0
  331. package/lib/packlets/crypto-utils/keystore/privateKeyStorage.d.ts +53 -0
  332. package/lib/packlets/crypto-utils/keystore/privateKeyStorage.d.ts.map +1 -0
  333. package/lib/packlets/crypto-utils/keystore/privateKeyStorage.js +22 -0
  334. package/lib/packlets/crypto-utils/keystore/privateKeyStorage.js.map +1 -0
  335. package/lib/packlets/crypto-utils/model.d.ts +518 -10
  336. package/lib/packlets/crypto-utils/model.d.ts.map +1 -0
  337. package/lib/packlets/crypto-utils/model.js +33 -1
  338. package/lib/packlets/crypto-utils/model.js.map +1 -0
  339. package/lib/packlets/crypto-utils/nodeCryptoProvider.d.ts +142 -2
  340. package/lib/packlets/crypto-utils/nodeCryptoProvider.d.ts.map +1 -0
  341. package/lib/packlets/crypto-utils/nodeCryptoProvider.js +346 -0
  342. package/lib/packlets/crypto-utils/nodeCryptoProvider.js.map +1 -0
  343. package/lib/packlets/crypto-utils/seedDerivedKeyPair.d.ts +42 -0
  344. package/lib/packlets/crypto-utils/seedDerivedKeyPair.d.ts.map +1 -0
  345. package/lib/packlets/crypto-utils/seedDerivedKeyPair.js +123 -0
  346. package/lib/packlets/crypto-utils/seedDerivedKeyPair.js.map +1 -0
  347. package/lib/packlets/crypto-utils/spkiHelpers.d.ts +151 -0
  348. package/lib/packlets/crypto-utils/spkiHelpers.d.ts.map +1 -0
  349. package/lib/packlets/crypto-utils/spkiHelpers.js +297 -0
  350. package/lib/packlets/crypto-utils/spkiHelpers.js.map +1 -0
  351. package/lib/packlets/csv/csvFileHelpers.d.ts +0 -10
  352. package/lib/packlets/csv/csvFileHelpers.d.ts.map +1 -0
  353. package/lib/packlets/csv/csvFileHelpers.js +0 -15
  354. package/lib/packlets/csv/csvFileHelpers.js.map +1 -0
  355. package/lib/packlets/csv/csvHelpers.d.ts +10 -0
  356. package/lib/packlets/csv/csvHelpers.d.ts.map +1 -0
  357. package/lib/packlets/csv/csvHelpers.js +15 -0
  358. package/lib/packlets/csv/csvHelpers.js.map +1 -0
  359. package/lib/packlets/csv/index.browser.d.ts +0 -1
  360. package/lib/packlets/csv/index.browser.d.ts.map +1 -0
  361. package/lib/packlets/csv/index.browser.js +1 -5
  362. package/lib/packlets/csv/index.browser.js.map +1 -0
  363. package/lib/packlets/csv/index.d.ts.map +1 -0
  364. package/lib/packlets/csv/index.js.map +1 -0
  365. package/lib/packlets/experimental/extendedArray.d.ts.map +1 -0
  366. package/lib/packlets/experimental/extendedArray.js.map +1 -0
  367. package/lib/packlets/experimental/formatter.d.ts.map +1 -0
  368. package/lib/packlets/experimental/formatter.js.map +1 -0
  369. package/lib/packlets/experimental/index.d.ts.map +1 -0
  370. package/lib/packlets/experimental/index.js.map +1 -0
  371. package/lib/packlets/experimental/rangeOf.d.ts.map +1 -0
  372. package/lib/packlets/experimental/rangeOf.js.map +1 -0
  373. package/lib/packlets/hash/index.browser.d.ts.map +1 -0
  374. package/lib/packlets/hash/index.browser.js.map +1 -0
  375. package/lib/packlets/hash/index.d.ts.map +1 -0
  376. package/lib/packlets/hash/index.js.map +1 -0
  377. package/lib/packlets/hash/index.node.d.ts.map +1 -0
  378. package/lib/packlets/hash/index.node.js.map +1 -0
  379. package/lib/packlets/hash/md5Normalizer.browser.d.ts.map +1 -0
  380. package/lib/packlets/hash/md5Normalizer.browser.js.map +1 -0
  381. package/lib/packlets/hash/md5Normalizer.d.ts.map +1 -0
  382. package/lib/packlets/hash/md5Normalizer.js.map +1 -0
  383. package/lib/packlets/mustache/index.d.ts +1 -1
  384. package/lib/packlets/mustache/index.d.ts.map +1 -0
  385. package/lib/packlets/mustache/index.js.map +1 -0
  386. package/lib/packlets/mustache/interfaces.d.ts +34 -0
  387. package/lib/packlets/mustache/interfaces.d.ts.map +1 -0
  388. package/lib/packlets/mustache/interfaces.js.map +1 -0
  389. package/lib/packlets/mustache/mustacheTemplate.d.ts +2 -0
  390. package/lib/packlets/mustache/mustacheTemplate.d.ts.map +1 -0
  391. package/lib/packlets/mustache/mustacheTemplate.js +42 -4
  392. package/lib/packlets/mustache/mustacheTemplate.js.map +1 -0
  393. package/lib/packlets/record-jar/index.browser.d.ts +0 -1
  394. package/lib/packlets/record-jar/index.browser.d.ts.map +1 -0
  395. package/lib/packlets/record-jar/index.browser.js +1 -5
  396. package/lib/packlets/record-jar/index.browser.js.map +1 -0
  397. package/lib/packlets/record-jar/index.d.ts.map +1 -0
  398. package/lib/packlets/record-jar/index.js.map +1 -0
  399. package/lib/packlets/record-jar/recordJarFileHelpers.d.ts +0 -11
  400. package/lib/packlets/record-jar/recordJarFileHelpers.d.ts.map +1 -0
  401. package/lib/packlets/record-jar/recordJarFileHelpers.js +0 -19
  402. package/lib/packlets/record-jar/recordJarFileHelpers.js.map +1 -0
  403. package/lib/packlets/record-jar/recordJarHelpers.d.ts +11 -0
  404. package/lib/packlets/record-jar/recordJarHelpers.d.ts.map +1 -0
  405. package/lib/packlets/record-jar/recordJarHelpers.js +19 -0
  406. package/lib/packlets/record-jar/recordJarHelpers.js.map +1 -0
  407. package/lib/packlets/safer-fetch/addressClassification.d.ts +144 -0
  408. package/lib/packlets/safer-fetch/addressClassification.d.ts.map +1 -0
  409. package/lib/packlets/safer-fetch/addressClassification.js +441 -0
  410. package/lib/packlets/safer-fetch/addressClassification.js.map +1 -0
  411. package/lib/packlets/safer-fetch/addressPolicy.d.ts +113 -0
  412. package/lib/packlets/safer-fetch/addressPolicy.d.ts.map +1 -0
  413. package/lib/packlets/safer-fetch/addressPolicy.js +123 -0
  414. package/lib/packlets/safer-fetch/addressPolicy.js.map +1 -0
  415. package/lib/packlets/safer-fetch/contentType.d.ts +51 -0
  416. package/lib/packlets/safer-fetch/contentType.d.ts.map +1 -0
  417. package/lib/packlets/safer-fetch/contentType.js +127 -0
  418. package/lib/packlets/safer-fetch/contentType.js.map +1 -0
  419. package/lib/packlets/safer-fetch/deadline.d.ts +138 -0
  420. package/lib/packlets/safer-fetch/deadline.d.ts.map +1 -0
  421. package/lib/packlets/safer-fetch/deadline.js +258 -0
  422. package/lib/packlets/safer-fetch/deadline.js.map +1 -0
  423. package/lib/packlets/safer-fetch/defaults.d.ts +108 -0
  424. package/lib/packlets/safer-fetch/defaults.d.ts.map +1 -0
  425. package/lib/packlets/safer-fetch/defaults.js +134 -0
  426. package/lib/packlets/safer-fetch/defaults.js.map +1 -0
  427. package/lib/packlets/safer-fetch/failureReason.d.ts +148 -0
  428. package/lib/packlets/safer-fetch/failureReason.d.ts.map +1 -0
  429. package/lib/packlets/safer-fetch/failureReason.js +22 -0
  430. package/lib/packlets/safer-fetch/failureReason.js.map +1 -0
  431. package/lib/packlets/safer-fetch/guards.d.ts +62 -0
  432. package/lib/packlets/safer-fetch/guards.d.ts.map +1 -0
  433. package/lib/packlets/safer-fetch/guards.js +153 -0
  434. package/lib/packlets/safer-fetch/guards.js.map +1 -0
  435. package/lib/packlets/safer-fetch/index.browser.d.ts +33 -0
  436. package/lib/packlets/safer-fetch/index.browser.d.ts.map +1 -0
  437. package/lib/packlets/safer-fetch/index.browser.js +82 -0
  438. package/lib/packlets/safer-fetch/index.browser.js.map +1 -0
  439. package/lib/packlets/safer-fetch/index.d.ts +27 -0
  440. package/lib/packlets/safer-fetch/index.d.ts.map +1 -0
  441. package/lib/packlets/safer-fetch/index.js +78 -0
  442. package/lib/packlets/safer-fetch/index.js.map +1 -0
  443. package/lib/packlets/safer-fetch/model.d.ts +373 -0
  444. package/lib/packlets/safer-fetch/model.d.ts.map +1 -0
  445. package/lib/packlets/safer-fetch/model.js +22 -0
  446. package/lib/packlets/safer-fetch/model.js.map +1 -0
  447. package/lib/packlets/safer-fetch/nodeAddressGuard.d.ts +129 -0
  448. package/lib/packlets/safer-fetch/nodeAddressGuard.d.ts.map +1 -0
  449. package/lib/packlets/safer-fetch/nodeAddressGuard.js +196 -0
  450. package/lib/packlets/safer-fetch/nodeAddressGuard.js.map +1 -0
  451. package/lib/packlets/safer-fetch/redirect.d.ts +62 -0
  452. package/lib/packlets/safer-fetch/redirect.d.ts.map +1 -0
  453. package/lib/packlets/safer-fetch/redirect.js +98 -0
  454. package/lib/packlets/safer-fetch/redirect.js.map +1 -0
  455. package/lib/packlets/safer-fetch/retry.d.ts +162 -0
  456. package/lib/packlets/safer-fetch/retry.d.ts.map +1 -0
  457. package/lib/packlets/safer-fetch/retry.js +197 -0
  458. package/lib/packlets/safer-fetch/retry.js.map +1 -0
  459. package/lib/packlets/safer-fetch/saferFetch.d.ts +108 -0
  460. package/lib/packlets/safer-fetch/saferFetch.d.ts.map +1 -0
  461. package/lib/packlets/safer-fetch/saferFetch.js +760 -0
  462. package/lib/packlets/safer-fetch/saferFetch.js.map +1 -0
  463. package/lib/packlets/safer-fetch/transport.d.ts +18 -0
  464. package/lib/packlets/safer-fetch/transport.d.ts.map +1 -0
  465. package/lib/packlets/safer-fetch/transport.js +53 -0
  466. package/lib/packlets/safer-fetch/transport.js.map +1 -0
  467. package/lib/packlets/yaml/converters.d.ts.map +1 -0
  468. package/lib/packlets/yaml/converters.js.map +1 -0
  469. package/lib/packlets/yaml/index.d.ts +1 -0
  470. package/lib/packlets/yaml/index.d.ts.map +1 -0
  471. package/lib/packlets/yaml/index.js +1 -0
  472. package/lib/packlets/yaml/index.js.map +1 -0
  473. package/lib/packlets/yaml/serializers.d.ts +45 -0
  474. package/lib/packlets/yaml/serializers.d.ts.map +1 -0
  475. package/lib/packlets/yaml/serializers.js +84 -0
  476. package/lib/packlets/yaml/serializers.js.map +1 -0
  477. package/lib/packlets/zip-file-tree/index.d.ts.map +1 -0
  478. package/lib/packlets/zip-file-tree/index.js.map +1 -0
  479. package/lib/packlets/zip-file-tree/zipFileTreeAccessors.d.ts +84 -8
  480. package/lib/packlets/zip-file-tree/zipFileTreeAccessors.d.ts.map +1 -0
  481. package/lib/packlets/zip-file-tree/zipFileTreeAccessors.js +99 -9
  482. package/lib/packlets/zip-file-tree/zipFileTreeAccessors.js.map +1 -0
  483. package/lib/packlets/zip-file-tree/zipFileTreeWriter.d.ts +26 -1
  484. package/lib/packlets/zip-file-tree/zipFileTreeWriter.d.ts.map +1 -0
  485. package/lib/packlets/zip-file-tree/zipFileTreeWriter.js +17 -1
  486. package/lib/packlets/zip-file-tree/zipFileTreeWriter.js.map +1 -0
  487. package/package.json +30 -15
  488. package/lib/packlets/ai-assist/apiClient.d.ts +0 -60
@@ -0,0 +1,138 @@
1
+ import type { FetchFailureReason, FetchTimeoutPhase } from './failureReason';
2
+ /**
3
+ * Why a {@link DeadlineWatch} stopped waiting.
4
+ * @internal
5
+ */
6
+ export type DeadlineStopCause = 'caller-aborted' | FetchTimeoutPhase;
7
+ /**
8
+ * The outcome of racing a promise against the deadlines.
9
+ * @internal
10
+ */
11
+ export type DeadlineRace<T> = {
12
+ readonly stopped: false;
13
+ readonly value: T;
14
+ } | {
15
+ readonly stopped: true;
16
+ readonly cause: DeadlineStopCause;
17
+ };
18
+ /**
19
+ * Composes the caller's cancellation signal with an overall deadline and a headers deadline
20
+ * into one `AbortSignal`, and remembers which of the three stopped the call.
21
+ *
22
+ * @remarks
23
+ * The composition is done with a plain `AbortController` and listeners rather than
24
+ * `AbortSignal.any`, so there is no runtime-version floor to state and no feature-detection
25
+ * branch that only one of the two runtimes would ever execute.
26
+ *
27
+ * The overall deadline covers the connect, the headers, and the body read, and it is what
28
+ * stops a response that dribbles one byte every 25 seconds — such a response passes every
29
+ * per-read check and never trips a connect timeout.
30
+ * @internal
31
+ */
32
+ export declare class DeadlineWatch {
33
+ private _controller;
34
+ private readonly _startedAt;
35
+ private readonly _timeoutMs;
36
+ private readonly _headersTimeoutMs;
37
+ private readonly _callerSignal;
38
+ private readonly _onCallerAbort;
39
+ private _overallTimer;
40
+ private _headersTimer;
41
+ private _cause;
42
+ /**
43
+ * Whether the current stop ends the whole call rather than just this attempt. The overall
44
+ * deadline and the caller's signal are terminal; the per-attempt headers deadline is not.
45
+ */
46
+ private _terminal;
47
+ private _inBodyPhase;
48
+ private readonly _waiters;
49
+ constructor(timeoutMs: number, headersTimeoutMs: number, callerSignal?: AbortSignal);
50
+ /** The composed signal to hand to the transport. */
51
+ get signal(): AbortSignal;
52
+ /** Why the call was stopped, or `undefined` while it is still running. */
53
+ get cause(): DeadlineStopCause | undefined;
54
+ /**
55
+ * Records that a new attempt is starting: the headers deadline is (re)armed from now.
56
+ *
57
+ * @remarks
58
+ * The headers deadline is **per attempt**, and a redirect walk makes more than one. Without a
59
+ * re-arm, {@link DeadlineWatch.headersReceived} on the first hop would retire the headers
60
+ * deadline for the whole call, leaving every later hop bounded only by the overall deadline —
61
+ * so a chain whose second host simply never answers would hang for the overall budget instead
62
+ * of failing as `timeout.phase === 'headers'`.
63
+ *
64
+ * Called before the address guard rather than before the connect, because guard evaluation
65
+ * (a DNS resolution, in the shipped guard) is part of the time a caller waits for a usable
66
+ * response and is deliberately inside this budget.
67
+ *
68
+ * The overall deadline is untouched: it spans the whole call, redirects included.
69
+ */
70
+ attemptStarted(): void;
71
+ /**
72
+ * Records that response headers have arrived: the headers deadline no longer applies to this
73
+ * attempt, and a subsequent overall-deadline expiry is a body-phase timeout rather than an
74
+ * overall one.
75
+ */
76
+ headersReceived(): void;
77
+ /**
78
+ * Races a promise against the deadlines. A stopped race reports the cause; the underlying
79
+ * promise is abandoned, not cancelled — the caller is responsible for releasing whatever
80
+ * resource it represents (a response body reader, in practice).
81
+ *
82
+ * @remarks
83
+ * The waiter is removed once the race settles. A body read calls this once per chunk, so a
84
+ * waiter set that only grew would be a leak proportional to the number of chunks — in the
85
+ * exact code path whose job is to bound what a hostile response can cost the process.
86
+ */
87
+ race<T>(promise: Promise<T>): Promise<DeadlineRace<T>>;
88
+ /**
89
+ * Records that an attempt has ended and another may follow: the headers deadline is disarmed,
90
+ * and a stop that ended only *that attempt* is cleared.
91
+ *
92
+ * @remarks
93
+ * **The headers deadline is attempt-scoped and the overall deadline is not.** A retry attempt
94
+ * that timed out waiting for headers must not leave the whole call stopped — without this,
95
+ * retry could never answer a `timeout.phase === 'headers'` failure, which is precisely the
96
+ * failure retry exists for. The composed signal is replaced rather than reset, because an
97
+ * aborted `AbortSignal` cannot be un-aborted.
98
+ *
99
+ * The overall deadline and the caller's signal are **terminal** by contrast: neither is about
100
+ * one attempt, and clearing either would let a retry loop outlive the budget the caller set or
101
+ * ignore the cancellation the caller requested. A terminal stop survives this call, so the
102
+ * backoff that follows is answered immediately and the call ends.
103
+ *
104
+ * Called between attempts rather than at the start of one, so the interval spent in a backoff
105
+ * is bounded by the overall deadline alone — arming a headers deadline over a sleep during
106
+ * which no request is outstanding would stop the call for a response nobody is waiting for.
107
+ */
108
+ attemptEnded(): void;
109
+ /**
110
+ * How much of the overall deadline is left, in milliseconds, never below zero.
111
+ *
112
+ * @remarks
113
+ * Read by the retry scheduler, which must not sleep past a deadline it is already inside:
114
+ * "the overall budget is the ceiling" is only enforceable if the remaining budget is
115
+ * observable.
116
+ */
117
+ get remainingMs(): number;
118
+ /**
119
+ * Waits for the given number of milliseconds, or until the call is stopped — whichever comes
120
+ * first.
121
+ *
122
+ * @remarks
123
+ * Backing the retry delay with the same watch the request races against is what keeps a
124
+ * caller's `abort()` responsive *between* attempts. A bare `setTimeout` would leave a caller
125
+ * who cancelled during a five-second backoff waiting out the full delay before being told the
126
+ * call was aborted.
127
+ *
128
+ * The timer is cleared however the wait ends, so a stopped delay leaves nothing pending —
129
+ * which matters in a test runner, where a stray timer keeps the process alive.
130
+ */
131
+ delay(ms: number): Promise<DeadlineRace<true>>;
132
+ /** Builds the failure reason corresponding to why the call was stopped. */
133
+ toFailureReason(cause: DeadlineStopCause): FetchFailureReason;
134
+ /** Clears timers and listeners. Safe to call more than once. */
135
+ dispose(): void;
136
+ private _stop;
137
+ }
138
+ //# sourceMappingURL=deadline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deadline.d.ts","sourceRoot":"","sources":["../../../src/packlets/safer-fetch/deadline.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAE7E;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG,gBAAgB,GAAG,iBAAiB,CAAC;AAErE;;;GAGG;AACH,MAAM,MAAM,YAAY,CAAC,CAAC,IACtB;IAAE,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAA;CAAE,GAC9C;IAAE,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,iBAAiB,CAAA;CAAE,CAAC;AAElE;;;;;;;;;;;;;GAaG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;IAC3C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA0B;IACxD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAa;IAE5C,OAAO,CAAC,aAAa,CAA4C;IACjE,OAAO,CAAC,aAAa,CAA4C;IACjE,OAAO,CAAC,MAAM,CAAgC;IAC9C;;;OAGG;IACH,OAAO,CAAC,SAAS,CAAU;IAC3B,OAAO,CAAC,YAAY,CAAU;IAC9B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA0C;gBAEhD,SAAS,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,WAAW;IAuB1F,oDAAoD;IACpD,IAAW,MAAM,IAAI,WAAW,CAE/B;IAED,0EAA0E;IAC1E,IAAW,KAAK,IAAI,iBAAiB,GAAG,SAAS,CAEhD;IAED;;;;;;;;;;;;;;;OAeG;IACI,cAAc,IAAI,IAAI;IAW7B;;;;OAIG;IACI,eAAe,IAAI,IAAI;IAQ9B;;;;;;;;;OASG;IACU,IAAI,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAoBnE;;;;;;;;;;;;;;;;;;;OAmBG;IACI,YAAY,IAAI,IAAI;IAoB3B;;;;;;;OAOG;IACH,IAAW,WAAW,IAAI,MAAM,CAE/B;IAED;;;;;;;;;;;;OAYG;IACU,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IAe3D,2EAA2E;IACpE,eAAe,CAAC,KAAK,EAAE,iBAAiB,GAAG,kBAAkB;IAYpE,gEAAgE;IACzD,OAAO,IAAI,IAAI;IAetB,OAAO,CAAC,KAAK;CAkBd"}
@@ -0,0 +1,258 @@
1
+ "use strict";
2
+ // Copyright (c) 2026 Erik Fortune
3
+ //
4
+ // Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ // of this software and associated documentation files (the "Software"), to deal
6
+ // in the Software without restriction, including without limitation the rights
7
+ // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ // copies of the Software, and to permit persons to whom the Software is
9
+ // furnished to do so, subject to the following conditions:
10
+ //
11
+ // The above copyright notice and this permission notice shall be included in all
12
+ // copies or substantial portions of the Software.
13
+ //
14
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ // SOFTWARE.
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.DeadlineWatch = void 0;
23
+ /**
24
+ * Composes the caller's cancellation signal with an overall deadline and a headers deadline
25
+ * into one `AbortSignal`, and remembers which of the three stopped the call.
26
+ *
27
+ * @remarks
28
+ * The composition is done with a plain `AbortController` and listeners rather than
29
+ * `AbortSignal.any`, so there is no runtime-version floor to state and no feature-detection
30
+ * branch that only one of the two runtimes would ever execute.
31
+ *
32
+ * The overall deadline covers the connect, the headers, and the body read, and it is what
33
+ * stops a response that dribbles one byte every 25 seconds — such a response passes every
34
+ * per-read check and never trips a connect timeout.
35
+ * @internal
36
+ */
37
+ class DeadlineWatch {
38
+ constructor(timeoutMs, headersTimeoutMs, callerSignal) {
39
+ this._controller = new AbortController();
40
+ this._startedAt = Date.now();
41
+ this._timeoutMs = timeoutMs;
42
+ this._headersTimeoutMs = headersTimeoutMs;
43
+ this._callerSignal = callerSignal;
44
+ this._terminal = false;
45
+ this._inBodyPhase = false;
46
+ this._waiters = new Set();
47
+ this._onCallerAbort = () => this._stop('caller-aborted');
48
+ this._overallTimer = setTimeout(() => this._stop(this._inBodyPhase ? 'body' : 'overall'), timeoutMs);
49
+ this._headersTimer = setTimeout(() => this._stop('headers'), headersTimeoutMs);
50
+ if (callerSignal !== undefined) {
51
+ if (callerSignal.aborted) {
52
+ this._stop('caller-aborted');
53
+ }
54
+ else {
55
+ callerSignal.addEventListener('abort', this._onCallerAbort);
56
+ }
57
+ }
58
+ }
59
+ /** The composed signal to hand to the transport. */
60
+ get signal() {
61
+ return this._controller.signal;
62
+ }
63
+ /** Why the call was stopped, or `undefined` while it is still running. */
64
+ get cause() {
65
+ return this._cause;
66
+ }
67
+ /**
68
+ * Records that a new attempt is starting: the headers deadline is (re)armed from now.
69
+ *
70
+ * @remarks
71
+ * The headers deadline is **per attempt**, and a redirect walk makes more than one. Without a
72
+ * re-arm, {@link DeadlineWatch.headersReceived} on the first hop would retire the headers
73
+ * deadline for the whole call, leaving every later hop bounded only by the overall deadline —
74
+ * so a chain whose second host simply never answers would hang for the overall budget instead
75
+ * of failing as `timeout.phase === 'headers'`.
76
+ *
77
+ * Called before the address guard rather than before the connect, because guard evaluation
78
+ * (a DNS resolution, in the shipped guard) is part of the time a caller waits for a usable
79
+ * response and is deliberately inside this budget.
80
+ *
81
+ * The overall deadline is untouched: it spans the whole call, redirects included.
82
+ */
83
+ attemptStarted() {
84
+ if (this._cause !== undefined) {
85
+ return;
86
+ }
87
+ if (this._headersTimer !== undefined) {
88
+ clearTimeout(this._headersTimer);
89
+ }
90
+ this._headersTimer = setTimeout(() => this._stop('headers'), this._headersTimeoutMs);
91
+ this._inBodyPhase = false;
92
+ }
93
+ /**
94
+ * Records that response headers have arrived: the headers deadline no longer applies to this
95
+ * attempt, and a subsequent overall-deadline expiry is a body-phase timeout rather than an
96
+ * overall one.
97
+ */
98
+ headersReceived() {
99
+ if (this._headersTimer !== undefined) {
100
+ clearTimeout(this._headersTimer);
101
+ this._headersTimer = undefined;
102
+ }
103
+ this._inBodyPhase = true;
104
+ }
105
+ /**
106
+ * Races a promise against the deadlines. A stopped race reports the cause; the underlying
107
+ * promise is abandoned, not cancelled — the caller is responsible for releasing whatever
108
+ * resource it represents (a response body reader, in practice).
109
+ *
110
+ * @remarks
111
+ * The waiter is removed once the race settles. A body read calls this once per chunk, so a
112
+ * waiter set that only grew would be a leak proportional to the number of chunks — in the
113
+ * exact code path whose job is to bound what a hostile response can cost the process.
114
+ */
115
+ async race(promise) {
116
+ if (this._cause !== undefined) {
117
+ return { stopped: true, cause: this._cause };
118
+ }
119
+ // Definitely assigned: a Promise executor runs synchronously.
120
+ let waiter;
121
+ const stop = new Promise((resolve) => {
122
+ waiter = (cause) => resolve({ stopped: true, cause });
123
+ });
124
+ this._waiters.add(waiter);
125
+ try {
126
+ return await Promise.race([
127
+ promise.then((value) => ({ stopped: false, value })),
128
+ stop
129
+ ]);
130
+ }
131
+ finally {
132
+ this._waiters.delete(waiter);
133
+ }
134
+ }
135
+ /**
136
+ * Records that an attempt has ended and another may follow: the headers deadline is disarmed,
137
+ * and a stop that ended only *that attempt* is cleared.
138
+ *
139
+ * @remarks
140
+ * **The headers deadline is attempt-scoped and the overall deadline is not.** A retry attempt
141
+ * that timed out waiting for headers must not leave the whole call stopped — without this,
142
+ * retry could never answer a `timeout.phase === 'headers'` failure, which is precisely the
143
+ * failure retry exists for. The composed signal is replaced rather than reset, because an
144
+ * aborted `AbortSignal` cannot be un-aborted.
145
+ *
146
+ * The overall deadline and the caller's signal are **terminal** by contrast: neither is about
147
+ * one attempt, and clearing either would let a retry loop outlive the budget the caller set or
148
+ * ignore the cancellation the caller requested. A terminal stop survives this call, so the
149
+ * backoff that follows is answered immediately and the call ends.
150
+ *
151
+ * Called between attempts rather than at the start of one, so the interval spent in a backoff
152
+ * is bounded by the overall deadline alone — arming a headers deadline over a sleep during
153
+ * which no request is outstanding would stop the call for a response nobody is waiting for.
154
+ */
155
+ attemptEnded() {
156
+ if (this._headersTimer !== undefined) {
157
+ clearTimeout(this._headersTimer);
158
+ this._headersTimer = undefined;
159
+ }
160
+ // No attempt is in flight between attempts, so the call is not in its body phase — whatever
161
+ // the previous attempt reached. Without this, an attempt that failed *after* headers arrived
162
+ // (a body-read network error, a non-2xx) would leave the flag set through the backoff, and
163
+ // an overall-deadline expiry during that sleep would be reported as `timeout.phase: 'body'`
164
+ // while no bytes were being transferred at all. `phase` is part of the taxonomy's contract,
165
+ // and a phase that names the wrong thing is exactly the kind of small lie this primitive is
166
+ // built not to tell.
167
+ this._inBodyPhase = false;
168
+ if (this._terminal || this._cause === undefined) {
169
+ return;
170
+ }
171
+ this._cause = undefined;
172
+ this._controller = new AbortController();
173
+ }
174
+ /**
175
+ * How much of the overall deadline is left, in milliseconds, never below zero.
176
+ *
177
+ * @remarks
178
+ * Read by the retry scheduler, which must not sleep past a deadline it is already inside:
179
+ * "the overall budget is the ceiling" is only enforceable if the remaining budget is
180
+ * observable.
181
+ */
182
+ get remainingMs() {
183
+ return Math.max(0, this._timeoutMs - (Date.now() - this._startedAt));
184
+ }
185
+ /**
186
+ * Waits for the given number of milliseconds, or until the call is stopped — whichever comes
187
+ * first.
188
+ *
189
+ * @remarks
190
+ * Backing the retry delay with the same watch the request races against is what keeps a
191
+ * caller's `abort()` responsive *between* attempts. A bare `setTimeout` would leave a caller
192
+ * who cancelled during a five-second backoff waiting out the full delay before being told the
193
+ * call was aborted.
194
+ *
195
+ * The timer is cleared however the wait ends, so a stopped delay leaves nothing pending —
196
+ * which matters in a test runner, where a stray timer keeps the process alive.
197
+ */
198
+ async delay(ms) {
199
+ let timer;
200
+ try {
201
+ return await this.race(new Promise((resolve) => {
202
+ timer = setTimeout(() => resolve(true), ms);
203
+ }));
204
+ }
205
+ finally {
206
+ if (timer !== undefined) {
207
+ clearTimeout(timer);
208
+ }
209
+ }
210
+ }
211
+ /** Builds the failure reason corresponding to why the call was stopped. */
212
+ toFailureReason(cause) {
213
+ if (cause === 'caller-aborted') {
214
+ return { kind: 'aborted' };
215
+ }
216
+ return {
217
+ kind: 'timeout',
218
+ phase: cause,
219
+ elapsedMs: Date.now() - this._startedAt,
220
+ limitMs: cause === 'headers' ? this._headersTimeoutMs : this._timeoutMs
221
+ };
222
+ }
223
+ /** Clears timers and listeners. Safe to call more than once. */
224
+ dispose() {
225
+ if (this._overallTimer !== undefined) {
226
+ clearTimeout(this._overallTimer);
227
+ this._overallTimer = undefined;
228
+ }
229
+ if (this._headersTimer !== undefined) {
230
+ clearTimeout(this._headersTimer);
231
+ this._headersTimer = undefined;
232
+ }
233
+ if (this._callerSignal !== undefined) {
234
+ this._callerSignal.removeEventListener('abort', this._onCallerAbort);
235
+ }
236
+ this._waiters.clear();
237
+ }
238
+ _stop(cause) {
239
+ // First cause wins. The overall and headers deadlines can be scheduled for the same instant,
240
+ // and a caller can abort while one of them is already firing; reporting the second would
241
+ // rewrite a phase the caller has arguably already been told about.
242
+ if (this._cause !== undefined) {
243
+ return;
244
+ }
245
+ this._cause = cause;
246
+ // Every cause but the per-attempt headers deadline ends the call: the overall deadline is
247
+ // the whole budget, and the caller's signal is the caller's decision.
248
+ this._terminal = cause !== 'headers';
249
+ const waiters = Array.from(this._waiters);
250
+ this._waiters.clear();
251
+ this._controller.abort();
252
+ for (const waiter of waiters) {
253
+ waiter(cause);
254
+ }
255
+ }
256
+ }
257
+ exports.DeadlineWatch = DeadlineWatch;
258
+ //# sourceMappingURL=deadline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deadline.js","sourceRoot":"","sources":["../../../src/packlets/safer-fetch/deadline.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) 2026 Erik Fortune\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all\n// copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n\nimport type { FetchFailureReason, FetchTimeoutPhase } from './failureReason';\n\n/**\n * Why a {@link DeadlineWatch} stopped waiting.\n * @internal\n */\nexport type DeadlineStopCause = 'caller-aborted' | FetchTimeoutPhase;\n\n/**\n * The outcome of racing a promise against the deadlines.\n * @internal\n */\nexport type DeadlineRace<T> =\n | { readonly stopped: false; readonly value: T }\n | { readonly stopped: true; readonly cause: DeadlineStopCause };\n\n/**\n * Composes the caller's cancellation signal with an overall deadline and a headers deadline\n * into one `AbortSignal`, and remembers which of the three stopped the call.\n *\n * @remarks\n * The composition is done with a plain `AbortController` and listeners rather than\n * `AbortSignal.any`, so there is no runtime-version floor to state and no feature-detection\n * branch that only one of the two runtimes would ever execute.\n *\n * The overall deadline covers the connect, the headers, and the body read, and it is what\n * stops a response that dribbles one byte every 25 seconds — such a response passes every\n * per-read check and never trips a connect timeout.\n * @internal\n */\nexport class DeadlineWatch {\n private _controller: AbortController;\n private readonly _startedAt: number;\n private readonly _timeoutMs: number;\n private readonly _headersTimeoutMs: number;\n private readonly _callerSignal: AbortSignal | undefined;\n private readonly _onCallerAbort: () => void;\n\n private _overallTimer: ReturnType<typeof setTimeout> | undefined;\n private _headersTimer: ReturnType<typeof setTimeout> | undefined;\n private _cause: DeadlineStopCause | undefined;\n /**\n * Whether the current stop ends the whole call rather than just this attempt. The overall\n * deadline and the caller's signal are terminal; the per-attempt headers deadline is not.\n */\n private _terminal: boolean;\n private _inBodyPhase: boolean;\n private readonly _waiters: Set<(cause: DeadlineStopCause) => void>;\n\n public constructor(timeoutMs: number, headersTimeoutMs: number, callerSignal?: AbortSignal) {\n this._controller = new AbortController();\n this._startedAt = Date.now();\n this._timeoutMs = timeoutMs;\n this._headersTimeoutMs = headersTimeoutMs;\n this._callerSignal = callerSignal;\n this._terminal = false;\n this._inBodyPhase = false;\n this._waiters = new Set();\n\n this._onCallerAbort = (): void => this._stop('caller-aborted');\n this._overallTimer = setTimeout(() => this._stop(this._inBodyPhase ? 'body' : 'overall'), timeoutMs);\n this._headersTimer = setTimeout(() => this._stop('headers'), headersTimeoutMs);\n\n if (callerSignal !== undefined) {\n if (callerSignal.aborted) {\n this._stop('caller-aborted');\n } else {\n callerSignal.addEventListener('abort', this._onCallerAbort);\n }\n }\n }\n\n /** The composed signal to hand to the transport. */\n public get signal(): AbortSignal {\n return this._controller.signal;\n }\n\n /** Why the call was stopped, or `undefined` while it is still running. */\n public get cause(): DeadlineStopCause | undefined {\n return this._cause;\n }\n\n /**\n * Records that a new attempt is starting: the headers deadline is (re)armed from now.\n *\n * @remarks\n * The headers deadline is **per attempt**, and a redirect walk makes more than one. Without a\n * re-arm, {@link DeadlineWatch.headersReceived} on the first hop would retire the headers\n * deadline for the whole call, leaving every later hop bounded only by the overall deadline —\n * so a chain whose second host simply never answers would hang for the overall budget instead\n * of failing as `timeout.phase === 'headers'`.\n *\n * Called before the address guard rather than before the connect, because guard evaluation\n * (a DNS resolution, in the shipped guard) is part of the time a caller waits for a usable\n * response and is deliberately inside this budget.\n *\n * The overall deadline is untouched: it spans the whole call, redirects included.\n */\n public attemptStarted(): void {\n if (this._cause !== undefined) {\n return;\n }\n if (this._headersTimer !== undefined) {\n clearTimeout(this._headersTimer);\n }\n this._headersTimer = setTimeout(() => this._stop('headers'), this._headersTimeoutMs);\n this._inBodyPhase = false;\n }\n\n /**\n * Records that response headers have arrived: the headers deadline no longer applies to this\n * attempt, and a subsequent overall-deadline expiry is a body-phase timeout rather than an\n * overall one.\n */\n public headersReceived(): void {\n if (this._headersTimer !== undefined) {\n clearTimeout(this._headersTimer);\n this._headersTimer = undefined;\n }\n this._inBodyPhase = true;\n }\n\n /**\n * Races a promise against the deadlines. A stopped race reports the cause; the underlying\n * promise is abandoned, not cancelled — the caller is responsible for releasing whatever\n * resource it represents (a response body reader, in practice).\n *\n * @remarks\n * The waiter is removed once the race settles. A body read calls this once per chunk, so a\n * waiter set that only grew would be a leak proportional to the number of chunks — in the\n * exact code path whose job is to bound what a hostile response can cost the process.\n */\n public async race<T>(promise: Promise<T>): Promise<DeadlineRace<T>> {\n if (this._cause !== undefined) {\n return { stopped: true, cause: this._cause };\n }\n // Definitely assigned: a Promise executor runs synchronously.\n let waiter!: (cause: DeadlineStopCause) => void;\n const stop: Promise<DeadlineRace<T>> = new Promise((resolve) => {\n waiter = (cause: DeadlineStopCause): void => resolve({ stopped: true, cause });\n });\n this._waiters.add(waiter);\n try {\n return await Promise.race([\n promise.then((value): DeadlineRace<T> => ({ stopped: false, value })),\n stop\n ]);\n } finally {\n this._waiters.delete(waiter);\n }\n }\n\n /**\n * Records that an attempt has ended and another may follow: the headers deadline is disarmed,\n * and a stop that ended only *that attempt* is cleared.\n *\n * @remarks\n * **The headers deadline is attempt-scoped and the overall deadline is not.** A retry attempt\n * that timed out waiting for headers must not leave the whole call stopped — without this,\n * retry could never answer a `timeout.phase === 'headers'` failure, which is precisely the\n * failure retry exists for. The composed signal is replaced rather than reset, because an\n * aborted `AbortSignal` cannot be un-aborted.\n *\n * The overall deadline and the caller's signal are **terminal** by contrast: neither is about\n * one attempt, and clearing either would let a retry loop outlive the budget the caller set or\n * ignore the cancellation the caller requested. A terminal stop survives this call, so the\n * backoff that follows is answered immediately and the call ends.\n *\n * Called between attempts rather than at the start of one, so the interval spent in a backoff\n * is bounded by the overall deadline alone — arming a headers deadline over a sleep during\n * which no request is outstanding would stop the call for a response nobody is waiting for.\n */\n public attemptEnded(): void {\n if (this._headersTimer !== undefined) {\n clearTimeout(this._headersTimer);\n this._headersTimer = undefined;\n }\n // No attempt is in flight between attempts, so the call is not in its body phase — whatever\n // the previous attempt reached. Without this, an attempt that failed *after* headers arrived\n // (a body-read network error, a non-2xx) would leave the flag set through the backoff, and\n // an overall-deadline expiry during that sleep would be reported as `timeout.phase: 'body'`\n // while no bytes were being transferred at all. `phase` is part of the taxonomy's contract,\n // and a phase that names the wrong thing is exactly the kind of small lie this primitive is\n // built not to tell.\n this._inBodyPhase = false;\n if (this._terminal || this._cause === undefined) {\n return;\n }\n this._cause = undefined;\n this._controller = new AbortController();\n }\n\n /**\n * How much of the overall deadline is left, in milliseconds, never below zero.\n *\n * @remarks\n * Read by the retry scheduler, which must not sleep past a deadline it is already inside:\n * \"the overall budget is the ceiling\" is only enforceable if the remaining budget is\n * observable.\n */\n public get remainingMs(): number {\n return Math.max(0, this._timeoutMs - (Date.now() - this._startedAt));\n }\n\n /**\n * Waits for the given number of milliseconds, or until the call is stopped — whichever comes\n * first.\n *\n * @remarks\n * Backing the retry delay with the same watch the request races against is what keeps a\n * caller's `abort()` responsive *between* attempts. A bare `setTimeout` would leave a caller\n * who cancelled during a five-second backoff waiting out the full delay before being told the\n * call was aborted.\n *\n * The timer is cleared however the wait ends, so a stopped delay leaves nothing pending —\n * which matters in a test runner, where a stray timer keeps the process alive.\n */\n public async delay(ms: number): Promise<DeadlineRace<true>> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n try {\n return await this.race(\n new Promise<true>((resolve) => {\n timer = setTimeout(() => resolve(true), ms);\n })\n );\n } finally {\n if (timer !== undefined) {\n clearTimeout(timer);\n }\n }\n }\n\n /** Builds the failure reason corresponding to why the call was stopped. */\n public toFailureReason(cause: DeadlineStopCause): FetchFailureReason {\n if (cause === 'caller-aborted') {\n return { kind: 'aborted' };\n }\n return {\n kind: 'timeout',\n phase: cause,\n elapsedMs: Date.now() - this._startedAt,\n limitMs: cause === 'headers' ? this._headersTimeoutMs : this._timeoutMs\n };\n }\n\n /** Clears timers and listeners. Safe to call more than once. */\n public dispose(): void {\n if (this._overallTimer !== undefined) {\n clearTimeout(this._overallTimer);\n this._overallTimer = undefined;\n }\n if (this._headersTimer !== undefined) {\n clearTimeout(this._headersTimer);\n this._headersTimer = undefined;\n }\n if (this._callerSignal !== undefined) {\n this._callerSignal.removeEventListener('abort', this._onCallerAbort);\n }\n this._waiters.clear();\n }\n\n private _stop(cause: DeadlineStopCause): void {\n // First cause wins. The overall and headers deadlines can be scheduled for the same instant,\n // and a caller can abort while one of them is already firing; reporting the second would\n // rewrite a phase the caller has arguably already been told about.\n if (this._cause !== undefined) {\n return;\n }\n this._cause = cause;\n // Every cause but the per-attempt headers deadline ends the call: the overall deadline is\n // the whole budget, and the caller's signal is the caller's decision.\n this._terminal = cause !== 'headers';\n const waiters = Array.from(this._waiters);\n this._waiters.clear();\n this._controller.abort();\n for (const waiter of waiters) {\n waiter(cause);\n }\n }\n}\n"]}
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Default overall deadline, in milliseconds — comfortably above a slow-but-real API and far
3
+ * below "a hung request pins a socket for minutes". Streaming LLM calls should not use this
4
+ * primitive at all; that is what `AiAssist` is for.
5
+ * @public
6
+ */
7
+ export declare const DEFAULT_TIMEOUT_MS: number;
8
+ /**
9
+ * Default deadline to first response headers, in milliseconds. A host that has not sent
10
+ * headers in ten seconds is not answering.
11
+ * @public
12
+ */
13
+ export declare const DEFAULT_HEADERS_TIMEOUT_MS: number;
14
+ /**
15
+ * Default cap on decoded response bytes (5 MiB) — roughly an order of magnitude above a
16
+ * realistic JSON API response and well below a size that threatens a Node heap.
17
+ *
18
+ * @remarks
19
+ * Raising it is a per-call option, not a construction-time setting, precisely because real
20
+ * documents clear this. See `ISaferFetchOptions.maxResponseBytes`.
21
+ * @public
22
+ */
23
+ export declare const DEFAULT_MAX_RESPONSE_BYTES: number;
24
+ /**
25
+ * Redirect statuses this primitive recognizes as redirects. Other 3xx statuses (`300`, `304`,
26
+ * …) do not direct the client at a new URL and are reported as ordinary non-2xx responses.
27
+ * @public
28
+ */
29
+ export declare const REDIRECT_STATUSES: ReadonlyArray<number>;
30
+ /**
31
+ * Default cap on redirect hops followed under `'validate-each-hop'`.
32
+ *
33
+ * @remarks
34
+ * Five is enough for the ordinary shortener-then-canonicalize-then-CDN chains real services
35
+ * produce and small enough that a chain designed to burn budget is refused quickly. Every hop
36
+ * costs a full guard evaluation — including a DNS resolution — against the same overall
37
+ * deadline, so the cap bounds work, not just politeness.
38
+ * @public
39
+ */
40
+ export declare const DEFAULT_MAX_REDIRECTS: number;
41
+ /**
42
+ * Header names dropped on every cross-origin redirect hop, whatever the caller configured.
43
+ *
44
+ * @remarks
45
+ * Turning on manual redirects makes this primitive responsible for a rule the platform was
46
+ * applying for free: browsers and `curl` both strip credential headers when a redirect leaves
47
+ * the origin, and a hand-rolled loop that replays them hands `Authorization: Bearer …` to
48
+ * whatever host the redirect names. Callers add their own names with
49
+ * `ISaferFetchOptions.sensitiveHeaders`; these three are not removable.
50
+ * @public
51
+ */
52
+ export declare const ALWAYS_STRIPPED_HEADERS: ReadonlyArray<string>;
53
+ /**
54
+ * URL schemes this primitive will ever request.
55
+ *
56
+ * @remarks
57
+ * Core rejects everything else — `file:`, `data:`, `blob:`, `ftp:`, `gopher:`, `ws:` — outright
58
+ * and at every hop, because none of them is a legitimate network fetch and each is a standard
59
+ * SSRF payload. Deciding between `http:` and `https:`, and which ports are acceptable, belongs
60
+ * to the address guard, which is why core does not narrow this further.
61
+ * @public
62
+ */
63
+ export declare const SUPPORTED_SCHEMES: ReadonlyArray<string>;
64
+ /**
65
+ * Default base delay for {@link SaferFetch.IRetryPolicy | retry} backoff, in milliseconds.
66
+ * @public
67
+ */
68
+ export declare const DEFAULT_RETRY_BASE_DELAY_MS: number;
69
+ /**
70
+ * Default ceiling on a single {@link SaferFetch.IRetryPolicy | retry} delay, in milliseconds.
71
+ *
72
+ * @remarks
73
+ * It bounds the computed backoff **and** a server-supplied `Retry-After`. That second role is
74
+ * the security-relevant one: `Retry-After` is a header an attacker-controlled server chooses
75
+ * freely, so an unclamped `Retry-After: 86400` is a denial of service on the caller.
76
+ * @public
77
+ */
78
+ export declare const DEFAULT_RETRY_MAX_DELAY_MS: number;
79
+ /**
80
+ * HTTP statuses a {@link SaferFetch.IRetryPolicy | retry policy} will retry.
81
+ *
82
+ * @remarks
83
+ * Every other status — including every other 4xx — is terminal. A `401`, a `403` and a `404`
84
+ * mean the same thing on the second attempt as on the first, and retrying them turns a client
85
+ * bug into load against a service that already said no.
86
+ * @public
87
+ */
88
+ export declare const RETRYABLE_HTTP_STATUSES: ReadonlyArray<number>;
89
+ /**
90
+ * Statuses whose `Retry-After` header is honored.
91
+ *
92
+ * @remarks
93
+ * `429` and `503` are the two the header is specified for and the two where it carries real
94
+ * scheduling information. Honoring it on a `500` would let any failing endpoint dictate the
95
+ * caller's schedule for no benefit.
96
+ * @public
97
+ */
98
+ export declare const RETRY_AFTER_STATUSES: ReadonlyArray<number>;
99
+ /**
100
+ * Methods retried without an explicit opt-in.
101
+ *
102
+ * @remarks
103
+ * A timeout does not tell you whether the server processed the request, so a retried `POST`
104
+ * can double-charge. `retryNonIdempotent` opts out, per call, visibly.
105
+ * @public
106
+ */
107
+ export declare const IDEMPOTENT_METHODS: ReadonlyArray<string>;
108
+ //# sourceMappingURL=defaults.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../../src/packlets/safer-fetch/defaults.ts"],"names":[],"mappings":"AAoBA;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAAe,CAAC;AAEjD;;;;GAIG;AACH,eAAO,MAAM,0BAA0B,EAAE,MAAe,CAAC;AAEzD;;;;;;;;GAQG;AACH,eAAO,MAAM,0BAA0B,EAAE,MAAwB,CAAC;AAElE;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,aAAa,CAAC,MAAM,CAA6B,CAAC;AAElF;;;;;;;;;GASG;AACH,eAAO,MAAM,qBAAqB,EAAE,MAAU,CAAC;AAE/C;;;;;;;;;;GAUG;AACH,eAAO,MAAM,uBAAuB,EAAE,aAAa,CAAC,MAAM,CAIzD,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,iBAAiB,EAAE,aAAa,CAAC,MAAM,CAAuB,CAAC;AAE5E;;;GAGG;AACH,eAAO,MAAM,2BAA2B,EAAE,MAAY,CAAC;AAEvD;;;;;;;;GAQG;AACH,eAAO,MAAM,0BAA0B,EAAE,MAAc,CAAC;AAExD;;;;;;;;GAQG;AACH,eAAO,MAAM,uBAAuB,EAAE,aAAa,CAAC,MAAM,CAAkC,CAAC;AAE7F;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,EAAE,aAAa,CAAC,MAAM,CAAc,CAAC;AAEtE;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,EAAE,aAAa,CAAC,MAAM,CAAmB,CAAC"}