@zshannon/streamstore 0.22.3

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 (444) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +93 -0
  3. package/dist/cjs/accessTokens.d.ts +51 -0
  4. package/dist/cjs/accessTokens.d.ts.map +1 -0
  5. package/dist/cjs/accessTokens.js +127 -0
  6. package/dist/cjs/accessTokens.js.map +1 -0
  7. package/dist/cjs/auth/biscuit.d.ts +42 -0
  8. package/dist/cjs/auth/biscuit.d.ts.map +1 -0
  9. package/dist/cjs/auth/biscuit.js +72 -0
  10. package/dist/cjs/auth/biscuit.js.map +1 -0
  11. package/dist/cjs/auth/index.d.ts +5 -0
  12. package/dist/cjs/auth/index.d.ts.map +1 -0
  13. package/dist/cjs/auth/index.js +14 -0
  14. package/dist/cjs/auth/index.js.map +1 -0
  15. package/dist/cjs/auth/pki-auth.d.ts +60 -0
  16. package/dist/cjs/auth/pki-auth.d.ts.map +1 -0
  17. package/dist/cjs/auth/pki-auth.js +102 -0
  18. package/dist/cjs/auth/pki-auth.js.map +1 -0
  19. package/dist/cjs/auth/sign.d.ts +39 -0
  20. package/dist/cjs/auth/sign.d.ts.map +1 -0
  21. package/dist/cjs/auth/sign.js +128 -0
  22. package/dist/cjs/auth/sign.js.map +1 -0
  23. package/dist/cjs/auth/signing-key.d.ts +42 -0
  24. package/dist/cjs/auth/signing-key.d.ts.map +1 -0
  25. package/dist/cjs/auth/signing-key.js +66 -0
  26. package/dist/cjs/auth/signing-key.js.map +1 -0
  27. package/dist/cjs/basin.d.ts +33 -0
  28. package/dist/cjs/basin.d.ts.map +1 -0
  29. package/dist/cjs/basin.js +54 -0
  30. package/dist/cjs/basin.js.map +1 -0
  31. package/dist/cjs/basins.d.ts +62 -0
  32. package/dist/cjs/basins.d.ts.map +1 -0
  33. package/dist/cjs/basins.js +201 -0
  34. package/dist/cjs/basins.js.map +1 -0
  35. package/dist/cjs/batch-transform.d.ts +60 -0
  36. package/dist/cjs/batch-transform.d.ts.map +1 -0
  37. package/dist/cjs/batch-transform.js +171 -0
  38. package/dist/cjs/batch-transform.js.map +1 -0
  39. package/dist/cjs/common.d.ts +156 -0
  40. package/dist/cjs/common.d.ts.map +1 -0
  41. package/dist/cjs/common.js +54 -0
  42. package/dist/cjs/common.js.map +1 -0
  43. package/dist/cjs/endpoints.d.ts +63 -0
  44. package/dist/cjs/endpoints.d.ts.map +1 -0
  45. package/dist/cjs/endpoints.js +120 -0
  46. package/dist/cjs/endpoints.js.map +1 -0
  47. package/dist/cjs/error.d.ts +119 -0
  48. package/dist/cjs/error.d.ts.map +1 -0
  49. package/dist/cjs/error.js +373 -0
  50. package/dist/cjs/error.js.map +1 -0
  51. package/dist/cjs/generated/client/client.gen.d.ts +3 -0
  52. package/dist/cjs/generated/client/client.gen.d.ts.map +1 -0
  53. package/dist/cjs/generated/client/client.gen.js +209 -0
  54. package/dist/cjs/generated/client/client.gen.js.map +1 -0
  55. package/dist/cjs/generated/client/index.d.ts +9 -0
  56. package/dist/cjs/generated/client/index.d.ts.map +1 -0
  57. package/dist/cjs/generated/client/index.js +18 -0
  58. package/dist/cjs/generated/client/index.js.map +1 -0
  59. package/dist/cjs/generated/client/types.gen.d.ts +125 -0
  60. package/dist/cjs/generated/client/types.gen.d.ts.map +1 -0
  61. package/dist/cjs/generated/client/types.gen.js +4 -0
  62. package/dist/cjs/generated/client/types.gen.js.map +1 -0
  63. package/dist/cjs/generated/client/utils.gen.d.ts +34 -0
  64. package/dist/cjs/generated/client/utils.gen.d.ts.map +1 -0
  65. package/dist/cjs/generated/client/utils.gen.js +243 -0
  66. package/dist/cjs/generated/client/utils.gen.js.map +1 -0
  67. package/dist/cjs/generated/client.gen.d.ts +13 -0
  68. package/dist/cjs/generated/client.gen.d.ts.map +1 -0
  69. package/dist/cjs/generated/client.gen.js +9 -0
  70. package/dist/cjs/generated/client.gen.js.map +1 -0
  71. package/dist/cjs/generated/core/auth.gen.d.ts +19 -0
  72. package/dist/cjs/generated/core/auth.gen.d.ts.map +1 -0
  73. package/dist/cjs/generated/core/auth.gen.js +19 -0
  74. package/dist/cjs/generated/core/auth.gen.js.map +1 -0
  75. package/dist/cjs/generated/core/bodySerializer.gen.d.ts +26 -0
  76. package/dist/cjs/generated/core/bodySerializer.gen.d.ts.map +1 -0
  77. package/dist/cjs/generated/core/bodySerializer.gen.js +61 -0
  78. package/dist/cjs/generated/core/bodySerializer.gen.js.map +1 -0
  79. package/dist/cjs/generated/core/params.gen.d.ts +44 -0
  80. package/dist/cjs/generated/core/params.gen.d.ts.map +1 -0
  81. package/dist/cjs/generated/core/params.gen.js +105 -0
  82. package/dist/cjs/generated/core/params.gen.js.map +1 -0
  83. package/dist/cjs/generated/core/pathSerializer.gen.d.ts +34 -0
  84. package/dist/cjs/generated/core/pathSerializer.gen.d.ts.map +1 -0
  85. package/dist/cjs/generated/core/pathSerializer.gen.js +124 -0
  86. package/dist/cjs/generated/core/pathSerializer.gen.js.map +1 -0
  87. package/dist/cjs/generated/core/queryKeySerializer.gen.d.ts +19 -0
  88. package/dist/cjs/generated/core/queryKeySerializer.gen.d.ts.map +1 -0
  89. package/dist/cjs/generated/core/queryKeySerializer.gen.js +106 -0
  90. package/dist/cjs/generated/core/queryKeySerializer.gen.js.map +1 -0
  91. package/dist/cjs/generated/core/serverSentEvents.gen.d.ts +72 -0
  92. package/dist/cjs/generated/core/serverSentEvents.gen.d.ts.map +1 -0
  93. package/dist/cjs/generated/core/serverSentEvents.gen.js +140 -0
  94. package/dist/cjs/generated/core/serverSentEvents.gen.js.map +1 -0
  95. package/dist/cjs/generated/core/types.gen.d.ts +79 -0
  96. package/dist/cjs/generated/core/types.gen.d.ts.map +1 -0
  97. package/dist/cjs/generated/core/types.gen.js +4 -0
  98. package/dist/cjs/generated/core/types.gen.js.map +1 -0
  99. package/dist/cjs/generated/core/utils.gen.d.ts +20 -0
  100. package/dist/cjs/generated/core/utils.gen.d.ts.map +1 -0
  101. package/dist/cjs/generated/core/utils.gen.js +94 -0
  102. package/dist/cjs/generated/core/utils.gen.js.map +1 -0
  103. package/dist/cjs/generated/index.d.ts +3 -0
  104. package/dist/cjs/generated/index.d.ts.map +1 -0
  105. package/dist/cjs/generated/index.js +19 -0
  106. package/dist/cjs/generated/index.js.map +1 -0
  107. package/dist/cjs/generated/proto/s2.d.ts +250 -0
  108. package/dist/cjs/generated/proto/s2.d.ts.map +1 -0
  109. package/dist/cjs/generated/proto/s2.js +426 -0
  110. package/dist/cjs/generated/proto/s2.js.map +1 -0
  111. package/dist/cjs/generated/sdk.gen.d.ts +100 -0
  112. package/dist/cjs/generated/sdk.gen.d.ts.map +1 -0
  113. package/dist/cjs/generated/sdk.gen.js +374 -0
  114. package/dist/cjs/generated/sdk.gen.js.map +1 -0
  115. package/dist/cjs/generated/types.gen.d.ts +1064 -0
  116. package/dist/cjs/generated/types.gen.d.ts.map +1 -0
  117. package/dist/cjs/generated/types.gen.js +4 -0
  118. package/dist/cjs/generated/types.gen.js.map +1 -0
  119. package/dist/cjs/index.d.ts +42 -0
  120. package/dist/cjs/index.d.ts.map +1 -0
  121. package/dist/cjs/index.js +81 -0
  122. package/dist/cjs/index.js.map +1 -0
  123. package/dist/cjs/internal/case-transform.d.ts +59 -0
  124. package/dist/cjs/internal/case-transform.d.ts.map +1 -0
  125. package/dist/cjs/internal/case-transform.js +80 -0
  126. package/dist/cjs/internal/case-transform.js.map +1 -0
  127. package/dist/cjs/internal/mappers.d.ts +51 -0
  128. package/dist/cjs/internal/mappers.d.ts.map +1 -0
  129. package/dist/cjs/internal/mappers.js +225 -0
  130. package/dist/cjs/internal/mappers.js.map +1 -0
  131. package/dist/cjs/internal/sdk-types.d.ts +127 -0
  132. package/dist/cjs/internal/sdk-types.d.ts.map +1 -0
  133. package/dist/cjs/internal/sdk-types.js +9 -0
  134. package/dist/cjs/internal/sdk-types.js.map +1 -0
  135. package/dist/cjs/lib/base64.d.ts +12 -0
  136. package/dist/cjs/lib/base64.d.ts.map +1 -0
  137. package/dist/cjs/lib/base64.js +172 -0
  138. package/dist/cjs/lib/base64.js.map +1 -0
  139. package/dist/cjs/lib/event-stream.d.ts +26 -0
  140. package/dist/cjs/lib/event-stream.d.ts.map +1 -0
  141. package/dist/cjs/lib/event-stream.js +154 -0
  142. package/dist/cjs/lib/event-stream.js.map +1 -0
  143. package/dist/cjs/lib/paginate.d.ts +61 -0
  144. package/dist/cjs/lib/paginate.d.ts.map +1 -0
  145. package/dist/cjs/lib/paginate.js +51 -0
  146. package/dist/cjs/lib/paginate.js.map +1 -0
  147. package/dist/cjs/lib/redacted.d.ts +17 -0
  148. package/dist/cjs/lib/redacted.d.ts.map +1 -0
  149. package/dist/cjs/lib/redacted.js +34 -0
  150. package/dist/cjs/lib/redacted.js.map +1 -0
  151. package/dist/cjs/lib/result.d.ts +57 -0
  152. package/dist/cjs/lib/result.d.ts.map +1 -0
  153. package/dist/cjs/lib/result.js +43 -0
  154. package/dist/cjs/lib/result.js.map +1 -0
  155. package/dist/cjs/lib/retry.d.ts +167 -0
  156. package/dist/cjs/lib/retry.d.ts.map +1 -0
  157. package/dist/cjs/lib/retry.js +1011 -0
  158. package/dist/cjs/lib/retry.js.map +1 -0
  159. package/dist/cjs/lib/stream/factory.d.ts +14 -0
  160. package/dist/cjs/lib/stream/factory.d.ts.map +1 -0
  161. package/dist/cjs/lib/stream/factory.js +35 -0
  162. package/dist/cjs/lib/stream/factory.js.map +1 -0
  163. package/dist/cjs/lib/stream/runtime.d.ts +27 -0
  164. package/dist/cjs/lib/stream/runtime.d.ts.map +1 -0
  165. package/dist/cjs/lib/stream/runtime.js +70 -0
  166. package/dist/cjs/lib/stream/runtime.js.map +1 -0
  167. package/dist/cjs/lib/stream/transport/fetch/index.d.ts +64 -0
  168. package/dist/cjs/lib/stream/transport/fetch/index.d.ts.map +1 -0
  169. package/dist/cjs/lib/stream/transport/fetch/index.js +462 -0
  170. package/dist/cjs/lib/stream/transport/fetch/index.js.map +1 -0
  171. package/dist/cjs/lib/stream/transport/fetch/shared.d.ts +11 -0
  172. package/dist/cjs/lib/stream/transport/fetch/shared.d.ts.map +1 -0
  173. package/dist/cjs/lib/stream/transport/fetch/shared.js +118 -0
  174. package/dist/cjs/lib/stream/transport/fetch/shared.js.map +1 -0
  175. package/dist/cjs/lib/stream/transport/proto.d.ts +9 -0
  176. package/dist/cjs/lib/stream/transport/proto.d.ts.map +1 -0
  177. package/dist/cjs/lib/stream/transport/proto.js +118 -0
  178. package/dist/cjs/lib/stream/transport/proto.js.map +1 -0
  179. package/dist/cjs/lib/stream/transport/s2s/framing.d.ts +47 -0
  180. package/dist/cjs/lib/stream/transport/s2s/framing.d.ts.map +1 -0
  181. package/dist/cjs/lib/stream/transport/s2s/framing.js +123 -0
  182. package/dist/cjs/lib/stream/transport/s2s/framing.js.map +1 -0
  183. package/dist/cjs/lib/stream/transport/s2s/index.d.ts +24 -0
  184. package/dist/cjs/lib/stream/transport/s2s/index.d.ts.map +1 -0
  185. package/dist/cjs/lib/stream/transport/s2s/index.js +823 -0
  186. package/dist/cjs/lib/stream/transport/s2s/index.js.map +1 -0
  187. package/dist/cjs/lib/stream/types.d.ts +199 -0
  188. package/dist/cjs/lib/stream/types.d.ts.map +1 -0
  189. package/dist/cjs/lib/stream/types.js +21 -0
  190. package/dist/cjs/lib/stream/types.js.map +1 -0
  191. package/dist/cjs/metrics.d.ts +46 -0
  192. package/dist/cjs/metrics.d.ts.map +1 -0
  193. package/dist/cjs/metrics.js +127 -0
  194. package/dist/cjs/metrics.js.map +1 -0
  195. package/dist/cjs/package.json +3 -0
  196. package/dist/cjs/producer.d.ts +82 -0
  197. package/dist/cjs/producer.d.ts.map +1 -0
  198. package/dist/cjs/producer.js +305 -0
  199. package/dist/cjs/producer.js.map +1 -0
  200. package/dist/cjs/s2.d.ts +41 -0
  201. package/dist/cjs/s2.d.ts.map +1 -0
  202. package/dist/cjs/s2.js +119 -0
  203. package/dist/cjs/s2.js.map +1 -0
  204. package/dist/cjs/stream.d.ts +78 -0
  205. package/dist/cjs/stream.d.ts.map +1 -0
  206. package/dist/cjs/stream.js +176 -0
  207. package/dist/cjs/stream.js.map +1 -0
  208. package/dist/cjs/streams.d.ts +61 -0
  209. package/dist/cjs/streams.d.ts.map +1 -0
  210. package/dist/cjs/streams.js +201 -0
  211. package/dist/cjs/streams.js.map +1 -0
  212. package/dist/cjs/types.d.ts +633 -0
  213. package/dist/cjs/types.d.ts.map +1 -0
  214. package/dist/cjs/types.js +129 -0
  215. package/dist/cjs/types.js.map +1 -0
  216. package/dist/cjs/utils.d.ts +25 -0
  217. package/dist/cjs/utils.d.ts.map +1 -0
  218. package/dist/cjs/utils.js +108 -0
  219. package/dist/cjs/utils.js.map +1 -0
  220. package/dist/cjs/version.d.ts +8 -0
  221. package/dist/cjs/version.d.ts.map +1 -0
  222. package/dist/cjs/version.js +11 -0
  223. package/dist/cjs/version.js.map +1 -0
  224. package/dist/esm/accessTokens.d.ts +51 -0
  225. package/dist/esm/accessTokens.d.ts.map +1 -0
  226. package/dist/esm/accessTokens.js +123 -0
  227. package/dist/esm/accessTokens.js.map +1 -0
  228. package/dist/esm/auth/biscuit.d.ts +42 -0
  229. package/dist/esm/auth/biscuit.d.ts.map +1 -0
  230. package/dist/esm/auth/biscuit.js +68 -0
  231. package/dist/esm/auth/biscuit.js.map +1 -0
  232. package/dist/esm/auth/index.d.ts +5 -0
  233. package/dist/esm/auth/index.d.ts.map +1 -0
  234. package/dist/esm/auth/index.js +5 -0
  235. package/dist/esm/auth/index.js.map +1 -0
  236. package/dist/esm/auth/pki-auth.d.ts +60 -0
  237. package/dist/esm/auth/pki-auth.d.ts.map +1 -0
  238. package/dist/esm/auth/pki-auth.js +99 -0
  239. package/dist/esm/auth/pki-auth.js.map +1 -0
  240. package/dist/esm/auth/sign.d.ts +39 -0
  241. package/dist/esm/auth/sign.d.ts.map +1 -0
  242. package/dist/esm/auth/sign.js +125 -0
  243. package/dist/esm/auth/sign.js.map +1 -0
  244. package/dist/esm/auth/signing-key.d.ts +42 -0
  245. package/dist/esm/auth/signing-key.d.ts.map +1 -0
  246. package/dist/esm/auth/signing-key.js +62 -0
  247. package/dist/esm/auth/signing-key.js.map +1 -0
  248. package/dist/esm/basin.d.ts +33 -0
  249. package/dist/esm/basin.d.ts.map +1 -0
  250. package/dist/esm/basin.js +50 -0
  251. package/dist/esm/basin.js.map +1 -0
  252. package/dist/esm/basins.d.ts +62 -0
  253. package/dist/esm/basins.d.ts.map +1 -0
  254. package/dist/esm/basins.js +197 -0
  255. package/dist/esm/basins.js.map +1 -0
  256. package/dist/esm/batch-transform.d.ts +60 -0
  257. package/dist/esm/batch-transform.d.ts.map +1 -0
  258. package/dist/esm/batch-transform.js +167 -0
  259. package/dist/esm/batch-transform.js.map +1 -0
  260. package/dist/esm/common.d.ts +156 -0
  261. package/dist/esm/common.d.ts.map +1 -0
  262. package/dist/esm/common.js +49 -0
  263. package/dist/esm/common.js.map +1 -0
  264. package/dist/esm/endpoints.d.ts +63 -0
  265. package/dist/esm/endpoints.d.ts.map +1 -0
  266. package/dist/esm/endpoints.js +115 -0
  267. package/dist/esm/endpoints.js.map +1 -0
  268. package/dist/esm/error.d.ts +119 -0
  269. package/dist/esm/error.d.ts.map +1 -0
  270. package/dist/esm/error.js +358 -0
  271. package/dist/esm/error.js.map +1 -0
  272. package/dist/esm/generated/client/client.gen.d.ts +3 -0
  273. package/dist/esm/generated/client/client.gen.d.ts.map +1 -0
  274. package/dist/esm/generated/client/client.gen.js +205 -0
  275. package/dist/esm/generated/client/client.gen.js.map +1 -0
  276. package/dist/esm/generated/client/index.d.ts +9 -0
  277. package/dist/esm/generated/client/index.d.ts.map +1 -0
  278. package/dist/esm/generated/client/index.js +7 -0
  279. package/dist/esm/generated/client/index.js.map +1 -0
  280. package/dist/esm/generated/client/types.gen.d.ts +125 -0
  281. package/dist/esm/generated/client/types.gen.d.ts.map +1 -0
  282. package/dist/esm/generated/client/types.gen.js +3 -0
  283. package/dist/esm/generated/client/types.gen.js.map +1 -0
  284. package/dist/esm/generated/client/utils.gen.d.ts +34 -0
  285. package/dist/esm/generated/client/utils.gen.d.ts.map +1 -0
  286. package/dist/esm/generated/client/utils.gen.js +232 -0
  287. package/dist/esm/generated/client/utils.gen.js.map +1 -0
  288. package/dist/esm/generated/client.gen.d.ts +13 -0
  289. package/dist/esm/generated/client.gen.d.ts.map +1 -0
  290. package/dist/esm/generated/client.gen.js +6 -0
  291. package/dist/esm/generated/client.gen.js.map +1 -0
  292. package/dist/esm/generated/core/auth.gen.d.ts +19 -0
  293. package/dist/esm/generated/core/auth.gen.d.ts.map +1 -0
  294. package/dist/esm/generated/core/auth.gen.js +15 -0
  295. package/dist/esm/generated/core/auth.gen.js.map +1 -0
  296. package/dist/esm/generated/core/bodySerializer.gen.d.ts +26 -0
  297. package/dist/esm/generated/core/bodySerializer.gen.d.ts.map +1 -0
  298. package/dist/esm/generated/core/bodySerializer.gen.js +58 -0
  299. package/dist/esm/generated/core/bodySerializer.gen.js.map +1 -0
  300. package/dist/esm/generated/core/params.gen.d.ts +44 -0
  301. package/dist/esm/generated/core/params.gen.d.ts.map +1 -0
  302. package/dist/esm/generated/core/params.gen.js +101 -0
  303. package/dist/esm/generated/core/params.gen.js.map +1 -0
  304. package/dist/esm/generated/core/pathSerializer.gen.d.ts +34 -0
  305. package/dist/esm/generated/core/pathSerializer.gen.d.ts.map +1 -0
  306. package/dist/esm/generated/core/pathSerializer.gen.js +115 -0
  307. package/dist/esm/generated/core/pathSerializer.gen.js.map +1 -0
  308. package/dist/esm/generated/core/queryKeySerializer.gen.d.ts +19 -0
  309. package/dist/esm/generated/core/queryKeySerializer.gen.d.ts.map +1 -0
  310. package/dist/esm/generated/core/queryKeySerializer.gen.js +100 -0
  311. package/dist/esm/generated/core/queryKeySerializer.gen.js.map +1 -0
  312. package/dist/esm/generated/core/serverSentEvents.gen.d.ts +72 -0
  313. package/dist/esm/generated/core/serverSentEvents.gen.d.ts.map +1 -0
  314. package/dist/esm/generated/core/serverSentEvents.gen.js +136 -0
  315. package/dist/esm/generated/core/serverSentEvents.gen.js.map +1 -0
  316. package/dist/esm/generated/core/types.gen.d.ts +79 -0
  317. package/dist/esm/generated/core/types.gen.d.ts.map +1 -0
  318. package/dist/esm/generated/core/types.gen.js +3 -0
  319. package/dist/esm/generated/core/types.gen.js.map +1 -0
  320. package/dist/esm/generated/core/utils.gen.d.ts +20 -0
  321. package/dist/esm/generated/core/utils.gen.d.ts.map +1 -0
  322. package/dist/esm/generated/core/utils.gen.js +88 -0
  323. package/dist/esm/generated/core/utils.gen.js.map +1 -0
  324. package/dist/esm/generated/index.d.ts +3 -0
  325. package/dist/esm/generated/index.d.ts.map +1 -0
  326. package/dist/esm/generated/index.js +3 -0
  327. package/dist/esm/generated/index.js.map +1 -0
  328. package/dist/esm/generated/proto/s2.d.ts +250 -0
  329. package/dist/esm/generated/proto/s2.d.ts.map +1 -0
  330. package/dist/esm/generated/proto/s2.js +423 -0
  331. package/dist/esm/generated/proto/s2.js.map +1 -0
  332. package/dist/esm/generated/sdk.gen.d.ts +100 -0
  333. package/dist/esm/generated/sdk.gen.d.ts.map +1 -0
  334. package/dist/esm/generated/sdk.gen.js +350 -0
  335. package/dist/esm/generated/sdk.gen.js.map +1 -0
  336. package/dist/esm/generated/types.gen.d.ts +1064 -0
  337. package/dist/esm/generated/types.gen.d.ts.map +1 -0
  338. package/dist/esm/generated/types.gen.js +3 -0
  339. package/dist/esm/generated/types.gen.js.map +1 -0
  340. package/dist/esm/index.d.ts +42 -0
  341. package/dist/esm/index.d.ts.map +1 -0
  342. package/dist/esm/index.js +47 -0
  343. package/dist/esm/index.js.map +1 -0
  344. package/dist/esm/internal/case-transform.d.ts +59 -0
  345. package/dist/esm/internal/case-transform.d.ts.map +1 -0
  346. package/dist/esm/internal/case-transform.js +76 -0
  347. package/dist/esm/internal/case-transform.js.map +1 -0
  348. package/dist/esm/internal/mappers.d.ts +51 -0
  349. package/dist/esm/internal/mappers.d.ts.map +1 -0
  350. package/dist/esm/internal/mappers.js +218 -0
  351. package/dist/esm/internal/mappers.js.map +1 -0
  352. package/dist/esm/internal/sdk-types.d.ts +127 -0
  353. package/dist/esm/internal/sdk-types.d.ts.map +1 -0
  354. package/dist/esm/internal/sdk-types.js +8 -0
  355. package/dist/esm/internal/sdk-types.js.map +1 -0
  356. package/dist/esm/lib/base64.d.ts +12 -0
  357. package/dist/esm/lib/base64.d.ts.map +1 -0
  358. package/dist/esm/lib/base64.js +165 -0
  359. package/dist/esm/lib/base64.js.map +1 -0
  360. package/dist/esm/lib/event-stream.d.ts +26 -0
  361. package/dist/esm/lib/event-stream.d.ts.map +1 -0
  362. package/dist/esm/lib/event-stream.js +150 -0
  363. package/dist/esm/lib/event-stream.js.map +1 -0
  364. package/dist/esm/lib/paginate.d.ts +61 -0
  365. package/dist/esm/lib/paginate.d.ts.map +1 -0
  366. package/dist/esm/lib/paginate.js +48 -0
  367. package/dist/esm/lib/paginate.js.map +1 -0
  368. package/dist/esm/lib/redacted.d.ts +17 -0
  369. package/dist/esm/lib/redacted.d.ts.map +1 -0
  370. package/dist/esm/lib/redacted.js +28 -0
  371. package/dist/esm/lib/redacted.js.map +1 -0
  372. package/dist/esm/lib/result.d.ts +57 -0
  373. package/dist/esm/lib/result.d.ts.map +1 -0
  374. package/dist/esm/lib/result.js +37 -0
  375. package/dist/esm/lib/result.js.map +1 -0
  376. package/dist/esm/lib/retry.d.ts +167 -0
  377. package/dist/esm/lib/retry.d.ts.map +1 -0
  378. package/dist/esm/lib/retry.js +1003 -0
  379. package/dist/esm/lib/retry.js.map +1 -0
  380. package/dist/esm/lib/stream/factory.d.ts +14 -0
  381. package/dist/esm/lib/stream/factory.d.ts.map +1 -0
  382. package/dist/esm/lib/stream/factory.js +32 -0
  383. package/dist/esm/lib/stream/factory.js.map +1 -0
  384. package/dist/esm/lib/stream/runtime.d.ts +27 -0
  385. package/dist/esm/lib/stream/runtime.d.ts.map +1 -0
  386. package/dist/esm/lib/stream/runtime.js +71 -0
  387. package/dist/esm/lib/stream/runtime.js.map +1 -0
  388. package/dist/esm/lib/stream/transport/fetch/index.d.ts +64 -0
  389. package/dist/esm/lib/stream/transport/fetch/index.d.ts.map +1 -0
  390. package/dist/esm/lib/stream/transport/fetch/index.js +456 -0
  391. package/dist/esm/lib/stream/transport/fetch/index.js.map +1 -0
  392. package/dist/esm/lib/stream/transport/fetch/shared.d.ts +11 -0
  393. package/dist/esm/lib/stream/transport/fetch/shared.d.ts.map +1 -0
  394. package/dist/esm/lib/stream/transport/fetch/shared.js +114 -0
  395. package/dist/esm/lib/stream/transport/fetch/shared.js.map +1 -0
  396. package/dist/esm/lib/stream/transport/proto.d.ts +9 -0
  397. package/dist/esm/lib/stream/transport/proto.d.ts.map +1 -0
  398. package/dist/esm/lib/stream/transport/proto.js +110 -0
  399. package/dist/esm/lib/stream/transport/proto.js.map +1 -0
  400. package/dist/esm/lib/stream/transport/s2s/framing.d.ts +47 -0
  401. package/dist/esm/lib/stream/transport/s2s/framing.d.ts.map +1 -0
  402. package/dist/esm/lib/stream/transport/s2s/framing.js +118 -0
  403. package/dist/esm/lib/stream/transport/s2s/framing.js.map +1 -0
  404. package/dist/esm/lib/stream/transport/s2s/index.d.ts +24 -0
  405. package/dist/esm/lib/stream/transport/s2s/index.d.ts.map +1 -0
  406. package/dist/esm/lib/stream/transport/s2s/index.js +819 -0
  407. package/dist/esm/lib/stream/transport/s2s/index.js.map +1 -0
  408. package/dist/esm/lib/stream/types.d.ts +199 -0
  409. package/dist/esm/lib/stream/types.d.ts.map +1 -0
  410. package/dist/esm/lib/stream/types.js +18 -0
  411. package/dist/esm/lib/stream/types.js.map +1 -0
  412. package/dist/esm/metrics.d.ts +46 -0
  413. package/dist/esm/metrics.d.ts.map +1 -0
  414. package/dist/esm/metrics.js +122 -0
  415. package/dist/esm/metrics.js.map +1 -0
  416. package/dist/esm/producer.d.ts +82 -0
  417. package/dist/esm/producer.d.ts.map +1 -0
  418. package/dist/esm/producer.js +300 -0
  419. package/dist/esm/producer.js.map +1 -0
  420. package/dist/esm/s2.d.ts +41 -0
  421. package/dist/esm/s2.d.ts.map +1 -0
  422. package/dist/esm/s2.js +115 -0
  423. package/dist/esm/s2.js.map +1 -0
  424. package/dist/esm/stream.d.ts +78 -0
  425. package/dist/esm/stream.d.ts.map +1 -0
  426. package/dist/esm/stream.js +172 -0
  427. package/dist/esm/stream.js.map +1 -0
  428. package/dist/esm/streams.d.ts +61 -0
  429. package/dist/esm/streams.d.ts.map +1 -0
  430. package/dist/esm/streams.js +197 -0
  431. package/dist/esm/streams.js.map +1 -0
  432. package/dist/esm/types.d.ts +633 -0
  433. package/dist/esm/types.d.ts.map +1 -0
  434. package/dist/esm/types.js +126 -0
  435. package/dist/esm/types.js.map +1 -0
  436. package/dist/esm/utils.d.ts +25 -0
  437. package/dist/esm/utils.d.ts.map +1 -0
  438. package/dist/esm/utils.js +103 -0
  439. package/dist/esm/utils.js.map +1 -0
  440. package/dist/esm/version.d.ts +8 -0
  441. package/dist/esm/version.d.ts.map +1 -0
  442. package/dist/esm/version.js +8 -0
  443. package/dist/esm/version.js.map +1 -0
  444. package/package.json +47 -0
@@ -0,0 +1,1003 @@
1
+ import createDebug from "debug";
2
+ import { abortedError, invariantViolation, S2Error, s2Error, withS2Error, } from "../error.js";
3
+ import * as Types from "../types.js";
4
+ import { meteredBytes } from "../utils.js";
5
+ import { err, errClose, ok, okClose } from "./result.js";
6
+ import { BatchSubmitTicket } from "./stream/types.js";
7
+ const debugWith = createDebug("s2:retry:with");
8
+ const debugRead = createDebug("s2:retry:read");
9
+ const debugSession = createDebug("s2:retry:session");
10
+ /** Type guard for errors with a code property (e.g., Node.js errors). */
11
+ function hasErrorCode(err, code) {
12
+ return (typeof err === "object" &&
13
+ err !== null &&
14
+ "code" in err &&
15
+ err.code === code);
16
+ }
17
+ /**
18
+ * Convert generated StreamPosition to SDK StreamPosition.
19
+ */
20
+ function toSDKStreamPosition(pos) {
21
+ return {
22
+ seqNum: pos.seq_num,
23
+ timestamp: new Date(pos.timestamp),
24
+ };
25
+ }
26
+ /**
27
+ * Convert internal ReadRecord (with headers as object for strings) to SDK ReadRecord (with headers as array).
28
+ */
29
+ function toSDKReadRecord(record) {
30
+ if (record.headers &&
31
+ typeof record.headers === "object" &&
32
+ !Array.isArray(record.headers)) {
33
+ // String format: headers is an object, convert to array of tuples
34
+ const result = {
35
+ seqNum: record.seq_num,
36
+ timestamp: new Date(record.timestamp),
37
+ body: record.body ?? "",
38
+ headers: Object.entries(record.headers),
39
+ };
40
+ return result;
41
+ }
42
+ else {
43
+ // Bytes format: headers is already an array
44
+ const result = {
45
+ seqNum: record.seq_num,
46
+ timestamp: new Date(record.timestamp),
47
+ body: record.body ?? new Uint8Array(),
48
+ headers: record.headers ?? [],
49
+ };
50
+ return result;
51
+ }
52
+ }
53
+ /**
54
+ * Default retry configuration.
55
+ */
56
+ export const DEFAULT_RETRY_CONFIG = {
57
+ maxAttempts: 3,
58
+ minBaseDelayMillis: 100,
59
+ maxBaseDelayMillis: 1000,
60
+ appendRetryPolicy: "all",
61
+ requestTimeoutMillis: 5000, // 5 seconds
62
+ connectionTimeoutMillis: 3000, // 3 seconds
63
+ };
64
+ const RETRYABLE_STATUS_CODES = new Set([
65
+ 408, // request_timeout
66
+ 429, // too_many_requests
67
+ 500, // internal_server_error
68
+ 502, // bad_gateway
69
+ 503, // service_unavailable
70
+ 504, // gateway_timeout
71
+ ]);
72
+ /**
73
+ * Determines if an error should be retried based on its characteristics.
74
+ * 400-level errors (except 408, 429) are non-retryable validation/client errors.
75
+ */
76
+ export function isRetryable(error) {
77
+ if (!error.status)
78
+ return false;
79
+ // Explicit retryable codes (including some 4xx like 408, 429)
80
+ if (RETRYABLE_STATUS_CODES.has(error.status)) {
81
+ return true;
82
+ }
83
+ // 400-level errors are generally non-retryable (validation, bad request)
84
+ if (error.status >= 400 && error.status < 500) {
85
+ return false;
86
+ }
87
+ return false;
88
+ }
89
+ /**
90
+ * Calculates the delay before the next retry attempt using exponential backoff
91
+ * with additive jitter.
92
+ *
93
+ * Formula:
94
+ * baseDelay = min(minBaseDelayMillis * 2^attempt, maxBaseDelayMillis)
95
+ * jitter = random(0, baseDelay)
96
+ * delay = baseDelay + jitter
97
+ *
98
+ * @param attempt - Zero-based retry attempt number (0 = first retry)
99
+ * @param minBaseDelayMillis - Minimum delay for exponential backoff
100
+ * @param maxBaseDelayMillis - Maximum base delay (actual delay can be up to 2x with jitter)
101
+ */
102
+ export function calculateDelay(attempt, minBaseDelayMillis, maxBaseDelayMillis) {
103
+ // Calculate exponential backoff: minDelay * 2^attempt, capped at maxDelay
104
+ const baseDelay = Math.min(minBaseDelayMillis * Math.pow(2, attempt), maxBaseDelayMillis);
105
+ // Add jitter: random value in [0, baseDelay)
106
+ const jitter = Math.random() * baseDelay;
107
+ // Total delay is base + jitter
108
+ return Math.floor(baseDelay + jitter);
109
+ }
110
+ /**
111
+ * Sleeps for the specified duration.
112
+ */
113
+ export function sleep(ms) {
114
+ return new Promise((resolve) => setTimeout(resolve, ms));
115
+ }
116
+ /**
117
+ * Executes an async function with automatic retry logic for transient failures.
118
+ *
119
+ * @param retryConfig Retry configuration (max attempts, backoff duration)
120
+ * @param fn The async function to execute
121
+ * @returns The result of the function
122
+ * @throws The last error if all retry attempts are exhausted
123
+ */
124
+ export async function withRetries(retryConfig, fn, isPolicyCompliant = () => true) {
125
+ const config = {
126
+ ...DEFAULT_RETRY_CONFIG,
127
+ ...retryConfig,
128
+ };
129
+ // Enforce minimum of 1 attempt (1 = no retries)
130
+ if (config.maxAttempts < 1)
131
+ config.maxAttempts = 1;
132
+ let lastError = undefined;
133
+ // attemptNo is 1-based: 1..maxAttempts
134
+ for (let attemptNo = 1; attemptNo <= config.maxAttempts; attemptNo++) {
135
+ try {
136
+ const result = await fn();
137
+ if (attemptNo > 1) {
138
+ debugWith("succeeded after %d retries", attemptNo - 1);
139
+ }
140
+ return result;
141
+ }
142
+ catch (error) {
143
+ // withRetry only handles S2Errors (withS2Error should be called first)
144
+ if (!(error instanceof S2Error)) {
145
+ debugWith("non-S2Error thrown, rethrowing immediately: %s", error);
146
+ throw error;
147
+ }
148
+ lastError = error;
149
+ // Don't retry if this is the last attempt
150
+ if (attemptNo === config.maxAttempts) {
151
+ debugWith("max attempts exhausted, throwing error");
152
+ break;
153
+ }
154
+ // Check if error is retryable
155
+ if (!isPolicyCompliant(config, lastError) || !isRetryable(lastError)) {
156
+ debugWith("error not retryable, throwing immediately");
157
+ throw error;
158
+ }
159
+ // Calculate delay and wait before retrying
160
+ const delay = calculateDelay(attemptNo - 1, config.minBaseDelayMillis, config.maxBaseDelayMillis);
161
+ debugWith("retryable error, backing off for %dms, status=%s", delay, error.status);
162
+ await sleep(delay);
163
+ }
164
+ }
165
+ throw lastError;
166
+ }
167
+ export class RetryReadSession extends ReadableStream {
168
+ _nextReadPosition = undefined;
169
+ _lastObservedTail = undefined;
170
+ _recordsRead = 0;
171
+ _bytesRead = 0;
172
+ static async create(generator, args = {}, config) {
173
+ const retryConfig = {
174
+ ...DEFAULT_RETRY_CONFIG,
175
+ ...config,
176
+ };
177
+ // Establish connection eagerly to fail fast on connection errors
178
+ // This way readSession() throws if we can't connect, rather than
179
+ // returning a stream that immediately errors
180
+ let attempt = 0;
181
+ let lastError;
182
+ while (true) {
183
+ try {
184
+ const session = await generator(args);
185
+ // Connection succeeded - return the retry wrapper
186
+ return new RetryReadSession(args, generator, config, session);
187
+ }
188
+ catch (err) {
189
+ const error = s2Error(err);
190
+ lastError = error;
191
+ const effectiveMax = Math.max(1, retryConfig.maxAttempts);
192
+ if (isRetryable(error) && attempt < effectiveMax - 1) {
193
+ const delay = calculateDelay(attempt, retryConfig.minBaseDelayMillis, retryConfig.maxBaseDelayMillis);
194
+ debugRead("connection error in create, will retry after %dms, status=%s", delay, error.status);
195
+ await sleep(delay);
196
+ attempt++;
197
+ continue;
198
+ }
199
+ // Not retryable or attempts exhausted
200
+ throw lastError;
201
+ }
202
+ }
203
+ }
204
+ constructor(args, generator, config, initialSession) {
205
+ const retryConfig = {
206
+ ...DEFAULT_RETRY_CONFIG,
207
+ ...config,
208
+ };
209
+ let session = initialSession;
210
+ const startTimeMs = performance.now(); // Capture start time before super()
211
+ super({
212
+ start: async (controller) => {
213
+ let nextArgs = { ...args };
214
+ // Capture original request budget so retries compute from a stable baseline
215
+ const baselineCount = args?.count;
216
+ const baselineBytes = args?.bytes;
217
+ const baselineWait = args?.wait;
218
+ let attempt = 0;
219
+ while (true) {
220
+ // Use pre-established session on first iteration if provided
221
+ if (!session) {
222
+ debugRead("starting read session with args: %o", nextArgs);
223
+ // Try to create session - may throw on connection errors
224
+ try {
225
+ session = await generator(nextArgs);
226
+ }
227
+ catch (err) {
228
+ // Convert to S2Error if needed
229
+ const error = s2Error(err);
230
+ // Check if we can retry connection errors
231
+ const effectiveMax = Math.max(1, retryConfig.maxAttempts);
232
+ if (isRetryable(error) && attempt < effectiveMax - 1) {
233
+ const delay = calculateDelay(attempt, retryConfig.minBaseDelayMillis, retryConfig.maxBaseDelayMillis);
234
+ debugRead("connection error, will retry after %dms, status=%s", delay, error.status);
235
+ await sleep(delay);
236
+ attempt++;
237
+ continue; // Retry creating session
238
+ }
239
+ // Error is not retryable or attempts exhausted
240
+ debugRead("connection error not retryable: %s", error);
241
+ controller.error(error);
242
+ return;
243
+ }
244
+ }
245
+ const reader = session.getReader();
246
+ while (true) {
247
+ const { done, value: result } = await reader.read();
248
+ // Update last observed tail if transport exposes it
249
+ try {
250
+ const tail = session.lastObservedTail?.();
251
+ if (tail)
252
+ this._lastObservedTail = tail;
253
+ }
254
+ catch { }
255
+ if (done) {
256
+ reader.releaseLock();
257
+ controller.close();
258
+ return;
259
+ }
260
+ // Check if result is an error
261
+ if (!result.ok) {
262
+ reader.releaseLock();
263
+ const error = result.error;
264
+ // Check if we can retry (track session attempts, not record reads)
265
+ const effectiveMax = Math.max(1, retryConfig.maxAttempts);
266
+ if (isRetryable(error) && attempt < effectiveMax - 1) {
267
+ if (this._nextReadPosition) {
268
+ nextArgs.seq_num = this._nextReadPosition.seq_num;
269
+ // Clear alternative start position fields to avoid conflicting params
270
+ delete nextArgs.timestamp;
271
+ delete nextArgs.tail_offset;
272
+ }
273
+ // Compute planned backoff delay now so we can subtract it from wait budget
274
+ const delay = calculateDelay(attempt, retryConfig.minBaseDelayMillis, retryConfig.maxBaseDelayMillis);
275
+ // Recompute remaining budget from original request each time to avoid double-subtraction
276
+ if (baselineCount !== undefined) {
277
+ nextArgs.count = Math.max(0, baselineCount - this._recordsRead);
278
+ }
279
+ if (baselineBytes !== undefined) {
280
+ nextArgs.bytes = Math.max(0, baselineBytes - this._bytesRead);
281
+ }
282
+ // Adjust wait from original budget based on total elapsed time since start
283
+ if (baselineWait !== undefined) {
284
+ const elapsedSeconds = (performance.now() - startTimeMs) / 1000;
285
+ nextArgs.wait = Math.max(0, Math.floor(baselineWait - (elapsedSeconds + delay / 1000)));
286
+ }
287
+ // Proactively cancel the current transport session before retrying
288
+ try {
289
+ await session.cancel?.("retry");
290
+ }
291
+ catch { }
292
+ // Clear session so a new one gets created on retry
293
+ session = undefined;
294
+ debugRead("will retry after %dms, status=%s", delay, error.status);
295
+ await sleep(delay);
296
+ attempt++;
297
+ break; // Break inner loop to retry
298
+ }
299
+ // Error is not retryable or attempts exhausted
300
+ debugRead("error in retry loop: %s", error);
301
+ controller.error(error);
302
+ return;
303
+ }
304
+ // Success: enqueue the record and reset retry attempt counter
305
+ const record = result.value;
306
+ this._nextReadPosition = {
307
+ seq_num: record.seq_num + 1,
308
+ timestamp: record.timestamp,
309
+ };
310
+ this._recordsRead++;
311
+ this._bytesRead += meteredBytes(record);
312
+ attempt = 0;
313
+ controller.enqueue(toSDKReadRecord(record));
314
+ }
315
+ }
316
+ },
317
+ cancel: async (reason) => {
318
+ try {
319
+ await session?.cancel(reason);
320
+ }
321
+ catch (err) {
322
+ // Ignore ERR_INVALID_STATE - stream may already be closed/cancelled
323
+ if (!hasErrorCode(err, "ERR_INVALID_STATE")) {
324
+ throw err;
325
+ }
326
+ }
327
+ },
328
+ });
329
+ }
330
+ async [Symbol.asyncDispose]() {
331
+ await this.cancel("disposed");
332
+ }
333
+ // Polyfill for older browsers / Node.js environments
334
+ [Symbol.asyncIterator]() {
335
+ const proto = ReadableStream.prototype;
336
+ const fn = proto[Symbol.asyncIterator];
337
+ if (typeof fn === "function") {
338
+ try {
339
+ return fn.call(this);
340
+ }
341
+ catch {
342
+ // Native method may throw "Illegal invocation" when called on subclass
343
+ // Fall through to manual implementation
344
+ }
345
+ }
346
+ const reader = this.getReader();
347
+ return {
348
+ next: async () => {
349
+ const r = await reader.read();
350
+ if (r.done) {
351
+ reader.releaseLock();
352
+ return { done: true, value: undefined };
353
+ }
354
+ return { done: false, value: r.value };
355
+ },
356
+ throw: async (e) => {
357
+ try {
358
+ await reader.cancel(e);
359
+ }
360
+ catch (err) {
361
+ if (!hasErrorCode(err, "ERR_INVALID_STATE"))
362
+ throw err;
363
+ }
364
+ reader.releaseLock();
365
+ return { done: true, value: undefined };
366
+ },
367
+ return: async () => {
368
+ try {
369
+ await reader.cancel("done");
370
+ }
371
+ catch (err) {
372
+ if (!hasErrorCode(err, "ERR_INVALID_STATE"))
373
+ throw err;
374
+ }
375
+ reader.releaseLock();
376
+ return { done: true, value: undefined };
377
+ },
378
+ [Symbol.asyncIterator]() {
379
+ return this;
380
+ },
381
+ };
382
+ }
383
+ lastObservedTail() {
384
+ return this._lastObservedTail
385
+ ? toSDKStreamPosition(this._lastObservedTail)
386
+ : undefined;
387
+ }
388
+ nextReadPosition() {
389
+ return this._nextReadPosition
390
+ ? toSDKStreamPosition(this._nextReadPosition)
391
+ : undefined;
392
+ }
393
+ }
394
+ const MIN_MAX_INFLIGHT_BYTES = 1 * 1024 * 1024; // 1 MiB minimum
395
+ const DEFAULT_MAX_INFLIGHT_BYTES = 3 * 1024 * 1024; // 3 MiB default
396
+ export class RetryAppendSession {
397
+ generator;
398
+ sessionOptions;
399
+ requestTimeoutMillis;
400
+ maxQueuedBytes;
401
+ maxInflightBatches;
402
+ retryConfig;
403
+ inflight = [];
404
+ capacityWaiters = []; // Queue of waiters for capacity
405
+ session;
406
+ queuedBytes = 0;
407
+ pendingBytes = 0;
408
+ pendingBatches = 0;
409
+ consecutiveFailures = 0;
410
+ currentAttempt = 0;
411
+ pumpPromise;
412
+ pumpStopped = false;
413
+ closing = false;
414
+ pumpWakeup;
415
+ closed = false;
416
+ fatalError;
417
+ _lastAckedPosition;
418
+ acksController;
419
+ readable;
420
+ writable;
421
+ streamName;
422
+ /**
423
+ * If the session has failed, returns the original fatal error that caused
424
+ * the pump to stop. Returns undefined when the session has not failed.
425
+ */
426
+ failureCause() {
427
+ return this.fatalError;
428
+ }
429
+ constructor(generator, sessionOptions, config, streamName) {
430
+ this.generator = generator;
431
+ this.sessionOptions = sessionOptions;
432
+ this.streamName = streamName ?? "unknown";
433
+ this.retryConfig = {
434
+ ...DEFAULT_RETRY_CONFIG,
435
+ ...config,
436
+ };
437
+ this.requestTimeoutMillis = this.retryConfig.requestTimeoutMillis;
438
+ // Clamp maxInflightBytes to at least 1 MiB
439
+ this.maxQueuedBytes = Math.max(MIN_MAX_INFLIGHT_BYTES, this.sessionOptions?.maxInflightBytes ?? DEFAULT_MAX_INFLIGHT_BYTES);
440
+ // Clamp maxInflightBatches to at least 1 if set
441
+ this.maxInflightBatches =
442
+ this.sessionOptions?.maxInflightBatches !== undefined
443
+ ? Math.max(1, this.sessionOptions.maxInflightBatches)
444
+ : undefined;
445
+ this.readable = new ReadableStream({
446
+ start: (controller) => {
447
+ this.acksController = controller;
448
+ },
449
+ });
450
+ this.writable = new WritableStream({
451
+ write: async (chunk) => {
452
+ if (this.closed || this.closing) {
453
+ throw new S2Error({ message: "AppendSession is closed" });
454
+ }
455
+ // chunk is already AppendInput with meteredBytes computed
456
+ // Reuse submit() to leverage shared backpressure/pump logic.
457
+ const ticket = await this.submit(chunk);
458
+ // Writable stream API only needs enqueue semantics, so drop ack but
459
+ // suppress rejection noise (pump surfaces fatal errors elsewhere).
460
+ ticket.ack().catch(() => {
461
+ // Intentionally ignored.
462
+ });
463
+ },
464
+ close: async () => {
465
+ await this.close();
466
+ },
467
+ abort: async (reason) => {
468
+ const error = abortedError(`AppendSession aborted: ${reason}`);
469
+ await this.abort(error);
470
+ },
471
+ });
472
+ }
473
+ static async create(generator, sessionOptions, config, streamName) {
474
+ return new RetryAppendSession(generator, sessionOptions, config, streamName);
475
+ }
476
+ /**
477
+ * Wait for capacity to be available for the given batch size.
478
+ * Call this before submit() to apply backpressure based on maxInflightBatches/maxInflightBytes.
479
+ *
480
+ * @param bytes - Size in bytes (use meteredBytes() to calculate)
481
+ * @param numBatches - Number of batches (default: 1)
482
+ * @returns Promise that resolves when capacity is available
483
+ */
484
+ async waitForCapacity(bytes, numBatches = 1) {
485
+ debugSession("[%s] [CAPACITY] checking for %d bytes, %d batches: queuedBytes=%d, pendingBytes=%d, maxQueuedBytes=%d, inflight=%d, pendingBatches=%d, maxInflightBatches=%s", this.streamName, bytes, numBatches, this.queuedBytes, this.pendingBytes, this.maxQueuedBytes, this.inflight.length, this.pendingBatches, this.maxInflightBatches ?? "unlimited");
486
+ // Check if we have capacity
487
+ while (true) {
488
+ // Check for fatal error before adding to pendingBytes
489
+ if (this.fatalError) {
490
+ debugSession("[%s] [CAPACITY] fatal error detected, rejecting: %s", this.streamName, this.fatalError.message);
491
+ throw this.fatalError;
492
+ }
493
+ // Byte-based gating
494
+ if (this.queuedBytes + this.pendingBytes + bytes <= this.maxQueuedBytes) {
495
+ // Batch-based gating (if configured)
496
+ if (this.maxInflightBatches === undefined ||
497
+ this.inflight.length + this.pendingBatches + numBatches <=
498
+ this.maxInflightBatches) {
499
+ debugSession("[%s] [CAPACITY] capacity available, adding %d to pendingBytes and %d to pendingBatches", this.streamName, bytes, numBatches);
500
+ this.pendingBytes += bytes;
501
+ this.pendingBatches += numBatches;
502
+ return;
503
+ }
504
+ }
505
+ // No capacity - wait in queue
506
+ debugSession("[%s] [CAPACITY] no capacity, waiting for release", this.streamName);
507
+ await new Promise((resolve) => {
508
+ this.capacityWaiters.push({
509
+ resolve,
510
+ bytes,
511
+ batches: numBatches,
512
+ });
513
+ });
514
+ debugSession("[%s] [CAPACITY] woke up, rechecking", this.streamName);
515
+ }
516
+ }
517
+ /**
518
+ * Submit an append request.
519
+ * Returns a promise that resolves to a submit ticket once the batch is enqueued (has capacity).
520
+ * The ticket's ack() can be awaited to get the AppendAck once the batch is durable.
521
+ * This method applies backpressure and will block if capacity limits are reached.
522
+ */
523
+ async submit(input) {
524
+ if (this.closed || this.closing) {
525
+ return Promise.reject(new S2Error({ message: "AppendSession is closed" }));
526
+ }
527
+ // Use cached metered size from AppendInput
528
+ const batchMeteredSize = input.meteredBytes;
529
+ // This needs to happen in the sync path.
530
+ this.ensurePump();
531
+ // Wait for capacity (this is where backpressure is applied - outer promise resolves when enqueued)
532
+ await this.waitForCapacity(batchMeteredSize, 1);
533
+ // Move reserved bytes and batches to queued accounting before submission
534
+ this.pendingBytes = Math.max(0, this.pendingBytes - batchMeteredSize);
535
+ this.pendingBatches = Math.max(0, this.pendingBatches - 1);
536
+ // Create the inner promise that resolves when durable
537
+ const innerPromise = this.submitInternal(input, batchMeteredSize).then((result) => {
538
+ if (result.ok) {
539
+ return result.value;
540
+ }
541
+ else {
542
+ throw result.error;
543
+ }
544
+ });
545
+ // Prevent early rejections from surfacing as unhandled when callers delay ack()
546
+ innerPromise.catch(() => { });
547
+ // Return ticket immediately (outer promise has resolved via waitForCapacity)
548
+ return new BatchSubmitTicket(innerPromise, batchMeteredSize, input.records.length);
549
+ }
550
+ /**
551
+ * Internal submit that returns discriminated union.
552
+ * Creates inflight entry and starts pump if needed.
553
+ */
554
+ submitInternal(input, batchMeteredSize) {
555
+ // Check for fatal error (e.g., from abort())
556
+ if (this.fatalError) {
557
+ debugSession("[%s] [SUBMIT] rejecting due to fatal error: %s", this.streamName, this.fatalError.message);
558
+ return Promise.resolve(err(this.fatalError));
559
+ }
560
+ // Create promise for submit() callers
561
+ return new Promise((resolve) => {
562
+ // Create inflight entry (innerPromise will be set when pump processes it)
563
+ const entry = {
564
+ input,
565
+ expectedCount: input.records.length,
566
+ innerPromise: new Promise(() => { }), // Never-resolving placeholder
567
+ maybeResolve: resolve,
568
+ needsSubmit: true, // Mark for pump to submit
569
+ };
570
+ debugSession("[%s] [SUBMIT] enqueueing %d records (%d bytes), match_seq_num=%s: inflight=%d->%d, queuedBytes=%d->%d", this.streamName, input.records.length, batchMeteredSize, input.matchSeqNum ?? "none", this.inflight.length, this.inflight.length + 1, this.queuedBytes, this.queuedBytes + batchMeteredSize);
571
+ this.inflight.push(entry);
572
+ this.queuedBytes += batchMeteredSize;
573
+ // Wake pump if it's sleeping
574
+ if (this.pumpWakeup) {
575
+ this.pumpWakeup();
576
+ }
577
+ // Start pump if not already running
578
+ this.ensurePump();
579
+ });
580
+ }
581
+ /**
582
+ * Release capacity and wake waiter if present.
583
+ */
584
+ releaseCapacity(bytes) {
585
+ debugSession("[%s] [CAPACITY] releasing %d bytes: queuedBytes=%d->%d, pendingBytes=%d->%d, pendingBatches=%d, numWaiters=%d", this.streamName, bytes, this.queuedBytes, this.queuedBytes - bytes, this.pendingBytes, Math.max(0, this.pendingBytes - bytes), this.pendingBatches, this.capacityWaiters.length);
586
+ this.queuedBytes -= bytes;
587
+ this.pendingBytes = Math.max(0, this.pendingBytes - bytes);
588
+ this.wakeCapacityWaiters();
589
+ }
590
+ wakeCapacityWaiters() {
591
+ if (this.capacityWaiters.length === 0) {
592
+ return;
593
+ }
594
+ let availableBytes = Math.max(0, this.maxQueuedBytes - (this.queuedBytes + this.pendingBytes));
595
+ let availableBatches = this.maxInflightBatches === undefined
596
+ ? Number.POSITIVE_INFINITY
597
+ : Math.max(0, this.maxInflightBatches -
598
+ (this.inflight.length + this.pendingBatches));
599
+ while (this.capacityWaiters.length > 0) {
600
+ const next = this.capacityWaiters[0];
601
+ const needsBytes = next.bytes;
602
+ const needsBatches = next.batches;
603
+ const hasBatchCapacity = this.maxInflightBatches === undefined ||
604
+ needsBatches <= availableBatches;
605
+ if (needsBytes <= availableBytes && hasBatchCapacity) {
606
+ this.capacityWaiters.shift();
607
+ availableBytes -= needsBytes;
608
+ if (this.maxInflightBatches !== undefined) {
609
+ availableBatches -= needsBatches;
610
+ }
611
+ debugSession("[%s] [CAPACITY] waking waiter (bytes=%d, batches=%d)", this.streamName, needsBytes, needsBatches);
612
+ next.resolve();
613
+ continue;
614
+ }
615
+ // Not enough capacity for the next waiter yet - keep them queued.
616
+ break;
617
+ }
618
+ }
619
+ /**
620
+ * Ensure pump loop is running.
621
+ */
622
+ ensurePump() {
623
+ if (this.pumpPromise || this.pumpStopped) {
624
+ return;
625
+ }
626
+ this.pumpPromise = this.runPump().catch((e) => {
627
+ debugSession("[%s] pump crashed unexpectedly: %s", this.streamName, e);
628
+ // This should never happen - pump handles all errors internally
629
+ });
630
+ }
631
+ /**
632
+ * Main pump loop: processes inflight queue, handles acks, retries, and recovery.
633
+ */
634
+ async runPump() {
635
+ debugSession("[%s] pump started", this.streamName);
636
+ while (true) {
637
+ debugSession("[%s] [PUMP] loop: inflight=%d, queuedBytes=%d, pendingBytes=%d, pendingBatches=%d, closing=%s, pumpStopped=%s", this.streamName, this.inflight.length, this.queuedBytes, this.pendingBytes, this.pendingBatches, this.closing, this.pumpStopped);
638
+ // Check if we should stop
639
+ if (this.pumpStopped) {
640
+ debugSession("[%s] [PUMP] stopped by flag", this.streamName);
641
+ return;
642
+ }
643
+ // If closing and queue is empty, stop
644
+ // BUT: if there are capacity waiters, they might add to inflight, so keep running
645
+ if (this.closing &&
646
+ this.inflight.length === 0 &&
647
+ this.capacityWaiters.length === 0) {
648
+ debugSession("[%s] [PUMP] closing and queue empty, stopping", this.streamName);
649
+ this.pumpStopped = true;
650
+ return;
651
+ }
652
+ // If no entries, sleep and continue
653
+ if (this.inflight.length === 0) {
654
+ debugSession("[%s] [PUMP] no entries, parking until wakeup", this.streamName);
655
+ await new Promise((resolve) => {
656
+ this.pumpWakeup = resolve;
657
+ });
658
+ this.pumpWakeup = undefined;
659
+ continue;
660
+ }
661
+ // Get head entry (we know it exists because we checked length above)
662
+ const head = this.inflight[0];
663
+ debugSession("[%s] [PUMP] processing head: expectedCount=%d, meteredBytes=%d, match_seq_num=%s", this.streamName, head.expectedCount, head.input.meteredBytes, head.input.matchSeqNum ?? "none");
664
+ // Ensure session exists
665
+ debugSession("[%s] [PUMP] ensuring session exists", this.streamName);
666
+ await this.ensureSession();
667
+ if (!this.session) {
668
+ // Session creation failed - will retry
669
+ this.consecutiveFailures++;
670
+ const delay = calculateDelay(this.consecutiveFailures - 1, this.retryConfig.minBaseDelayMillis, this.retryConfig.maxBaseDelayMillis);
671
+ debugSession("[%s] [PUMP] session creation failed, backing off for %dms", this.streamName, delay);
672
+ await sleep(delay);
673
+ continue;
674
+ }
675
+ // Submit ALL entries that need submitting (enables HTTP/2 pipelining for S2S)
676
+ for (const entry of this.inflight) {
677
+ if (!entry.innerPromise || entry.needsSubmit) {
678
+ debugSession("[%s] [PUMP] submitting entry to inner session (%d records, %d bytes, match_seq_num=%s)", this.streamName, entry.expectedCount, entry.input.meteredBytes, entry.input.matchSeqNum ?? "none");
679
+ const attemptStarted = performance.now();
680
+ entry.attemptStartedMonotonicMs = attemptStarted;
681
+ entry.innerPromise = this.session.submit(entry.input);
682
+ delete entry.needsSubmit;
683
+ }
684
+ }
685
+ // Wait for head with timeout
686
+ debugSession("[%s] [PUMP] waiting for head result", this.streamName);
687
+ const result = await this.waitForHead(head);
688
+ debugSession("[%s] [PUMP] got result: kind=%s", this.streamName, result.kind);
689
+ // Convert result to AppendResult (timeout becomes retryable error)
690
+ let appendResult;
691
+ if (result.kind === "timeout") {
692
+ // Ack timeout - convert to retryable error that flows through retry logic
693
+ const attemptElapsed = head.attemptStartedMonotonicMs != null
694
+ ? Math.round(performance.now() - head.attemptStartedMonotonicMs)
695
+ : undefined;
696
+ const error = new S2Error({
697
+ message: `Request timeout after ${attemptElapsed ?? "unknown"}ms (${head.expectedCount} records, ${head.input.meteredBytes} bytes)`,
698
+ status: 408,
699
+ code: "REQUEST_TIMEOUT",
700
+ origin: "sdk",
701
+ });
702
+ debugSession("[%s] ack timeout for head entry: %s", this.streamName, error.message);
703
+ appendResult = err(error);
704
+ }
705
+ else {
706
+ // Promise settled
707
+ appendResult = result.value;
708
+ }
709
+ if (appendResult.ok) {
710
+ // Success!
711
+ const ack = appendResult.value;
712
+ debugSession("[%s] [PUMP] success, got ack: seq_num=%d-%d", this.streamName, ack.start.seqNum, ack.end.seqNum);
713
+ // Invariant check: ack count matches batch count
714
+ const ackCount = ack.end.seqNum - ack.start.seqNum;
715
+ if (ackCount !== head.expectedCount) {
716
+ const error = invariantViolation(`Ack count mismatch: expected ${head.expectedCount}, got ${ackCount}`);
717
+ debugSession("[%s] invariant violation: %s", this.streamName, error.message);
718
+ await this.abort(error);
719
+ return;
720
+ }
721
+ // Invariant check: sequence numbers must be strictly increasing
722
+ if (this._lastAckedPosition) {
723
+ const prevEnd = this._lastAckedPosition.end.seqNum;
724
+ const currentEnd = ack.end.seqNum;
725
+ if (currentEnd <= prevEnd) {
726
+ const error = invariantViolation(`Sequence number not strictly increasing: previous=${prevEnd}, current=${currentEnd}`);
727
+ debugSession("[%s] invariant violation: %s", this.streamName, error.message);
728
+ await this.abort(error);
729
+ return;
730
+ }
731
+ }
732
+ // Update last acked position
733
+ this._lastAckedPosition = ack;
734
+ // Resolve submit() caller if present
735
+ if (head.maybeResolve) {
736
+ head.maybeResolve(ok(ack));
737
+ }
738
+ // Emit to readable stream
739
+ try {
740
+ this.acksController?.enqueue(ack);
741
+ }
742
+ catch (e) {
743
+ debugSession("[%s] failed to enqueue ack: %s", this.streamName, e);
744
+ }
745
+ // Remove from inflight and release capacity
746
+ debugSession("[%s] [PUMP] removing head from inflight, releasing %d bytes", this.streamName, head.input.meteredBytes);
747
+ this.inflight.shift();
748
+ this.releaseCapacity(head.input.meteredBytes);
749
+ // Reset consecutive failures on success
750
+ this.consecutiveFailures = 0;
751
+ this.currentAttempt = 0;
752
+ }
753
+ else {
754
+ // Error result
755
+ const error = appendResult.error;
756
+ debugSession("[%s] [PUMP] error: status=%s, message=%s", this.streamName, error.status, error.message);
757
+ // Check if retryable
758
+ if (!isRetryable(error)) {
759
+ debugSession("[%s] error not retryable, aborting", this.streamName);
760
+ await this.abort(error);
761
+ return;
762
+ }
763
+ // Check policy compliance
764
+ if (this.retryConfig.appendRetryPolicy === "noSideEffects" &&
765
+ !this.isIdempotent(head)) {
766
+ debugSession("[%s] error not policy-compliant (noSideEffects), aborting", this.streamName);
767
+ await this.abort(error);
768
+ return;
769
+ }
770
+ // Check max attempts (total attempts include initial; retries = max - 1)
771
+ const effectiveMax = Math.max(1, this.retryConfig.maxAttempts);
772
+ const allowedRetries = effectiveMax - 1;
773
+ if (this.currentAttempt >= allowedRetries) {
774
+ debugSession("[%s] max attempts reached (%d), aborting", this.streamName, effectiveMax);
775
+ const wrappedError = new S2Error({
776
+ message: `Max attempts (${effectiveMax}) exhausted: ${error.message}`,
777
+ status: error.status,
778
+ code: error.code,
779
+ });
780
+ await this.abort(wrappedError);
781
+ return;
782
+ }
783
+ // Perform recovery
784
+ this.consecutiveFailures++;
785
+ this.currentAttempt++;
786
+ debugSession("[%s] performing recovery (retry %d/%d)", this.streamName, this.currentAttempt, allowedRetries);
787
+ await this.recover();
788
+ }
789
+ }
790
+ }
791
+ /**
792
+ * Wait for head entry's innerPromise with timeout.
793
+ * Returns either the settled result or a timeout indicator.
794
+ *
795
+ * Per-attempt ack timeout semantics:
796
+ * - The deadline is computed from the current attempt's start time using a
797
+ * monotonic clock (performance.now) to avoid issues with wall clock adjustments.
798
+ * - Each retry gets a fresh timeout window (attemptStartedMonotonicMs is reset
799
+ * during recovery).
800
+ * - If attempt start is missing (for backward compatibility), we measure
801
+ * from "now" with the full timeout window.
802
+ */
803
+ async waitForHead(head) {
804
+ const attemptStart = head.attemptStartedMonotonicMs ?? performance.now();
805
+ const deadline = attemptStart + this.requestTimeoutMillis;
806
+ const remaining = Math.max(0, deadline - performance.now());
807
+ let timer;
808
+ const timeoutP = new Promise((resolve) => {
809
+ timer = setTimeout(() => resolve({ kind: "timeout" }), remaining);
810
+ });
811
+ const settledP = head.innerPromise.then((result) => ({
812
+ kind: "settled",
813
+ value: result,
814
+ }));
815
+ try {
816
+ return await Promise.race([settledP, timeoutP]);
817
+ }
818
+ finally {
819
+ if (timer)
820
+ clearTimeout(timer);
821
+ }
822
+ }
823
+ /**
824
+ * Recover from transient error: recreate session and resubmit all inflight entries.
825
+ */
826
+ async recover() {
827
+ debugSession("[%s] starting recovery", this.streamName);
828
+ // Calculate backoff delay
829
+ const delay = calculateDelay(this.consecutiveFailures - 1, this.retryConfig.minBaseDelayMillis, this.retryConfig.maxBaseDelayMillis);
830
+ debugSession("[%s] backing off for %dms", this.streamName, delay);
831
+ await sleep(delay);
832
+ // Teardown old session
833
+ if (this.session) {
834
+ try {
835
+ const closeResult = await this.session.close();
836
+ if (!closeResult.ok) {
837
+ debugSession("[%s] error closing old session during recovery: %s", this.streamName, closeResult.error.message);
838
+ }
839
+ }
840
+ catch (e) {
841
+ debugSession("[%s] exception closing old session: %s", this.streamName, e);
842
+ }
843
+ this.session = undefined;
844
+ }
845
+ // Create new session
846
+ await this.ensureSession();
847
+ if (!this.session) {
848
+ debugSession("[%s] failed to create new session during recovery", this.streamName);
849
+ // Will retry on next pump iteration
850
+ return;
851
+ }
852
+ // Store session in local variable to help TypeScript type narrowing
853
+ const session = this.session;
854
+ // Resubmit all inflight entries (replace their innerPromise and reset attempt start)
855
+ debugSession("[%s] resubmitting %d inflight entries", this.streamName, this.inflight.length);
856
+ for (const entry of this.inflight) {
857
+ // Attach .catch to superseded promise to avoid unhandled rejection
858
+ entry.innerPromise.catch(() => { });
859
+ // Create new promise from new session
860
+ const attemptStarted = performance.now();
861
+ entry.attemptStartedMonotonicMs = attemptStarted;
862
+ entry.innerPromise = session.submit(entry.input);
863
+ debugSession("[%s] resubmitted entry (%d records, %d bytes, match_seq_num=%s)", this.streamName, entry.expectedCount, entry.input.meteredBytes, entry.input.matchSeqNum ?? "none");
864
+ }
865
+ debugSession("[%s] recovery complete", this.streamName);
866
+ }
867
+ /**
868
+ * Check if append can be retried under noSideEffects policy.
869
+ * For appends, idempotency requires match_seq_num.
870
+ */
871
+ isIdempotent(entry) {
872
+ return entry.input.matchSeqNum !== undefined;
873
+ }
874
+ /**
875
+ * Ensure session exists, creating it if necessary.
876
+ */
877
+ async ensureSession() {
878
+ if (this.session) {
879
+ return;
880
+ }
881
+ try {
882
+ debugSession("[%s] creating new transport session", this.streamName);
883
+ this.session = await this.generator(this.sessionOptions);
884
+ debugSession("[%s] transport session created", this.streamName);
885
+ }
886
+ catch (e) {
887
+ const error = s2Error(e);
888
+ debugSession("[%s] failed to create session: %s", this.streamName, error.message);
889
+ // Don't set this.session - will retry later
890
+ }
891
+ }
892
+ /**
893
+ * Abort the session with a fatal error.
894
+ */
895
+ async abort(error) {
896
+ if (this.pumpStopped) {
897
+ return; // Already aborted
898
+ }
899
+ debugSession("[%s] aborting session: %s", this.streamName, error.message);
900
+ this.fatalError = error;
901
+ this.pumpStopped = true;
902
+ // Resolve all inflight entries with error
903
+ debugSession("[%s] rejecting %d inflight entries", this.streamName, this.inflight.length);
904
+ for (const entry of this.inflight) {
905
+ if (entry.maybeResolve) {
906
+ entry.maybeResolve(err(error));
907
+ }
908
+ }
909
+ this.inflight.length = 0;
910
+ this.queuedBytes = 0;
911
+ this.pendingBytes = 0;
912
+ this.pendingBatches = 0;
913
+ // Error the readable stream
914
+ try {
915
+ this.acksController?.error(error);
916
+ }
917
+ catch (e) {
918
+ debugSession("[%s] failed to error acks controller: %s", this.streamName, e);
919
+ }
920
+ // Wake all capacity waiters to unblock any pending writers
921
+ for (const waiter of this.capacityWaiters) {
922
+ waiter.resolve();
923
+ }
924
+ this.capacityWaiters = [];
925
+ // Close inner session
926
+ if (this.session) {
927
+ debugSession("[%s] closing inner session", this.streamName);
928
+ try {
929
+ await this.session.close();
930
+ }
931
+ catch (e) {
932
+ debugSession("[%s] error closing session during abort: %s", this.streamName, e);
933
+ }
934
+ this.session = undefined;
935
+ }
936
+ }
937
+ /**
938
+ * Close the append session.
939
+ * Waits for all pending appends to complete before resolving.
940
+ * Does not interrupt recovery - allows it to complete.
941
+ */
942
+ async close() {
943
+ if (this.closed) {
944
+ if (this.fatalError) {
945
+ throw this.fatalError;
946
+ }
947
+ return;
948
+ }
949
+ debugSession("[%s] close requested", this.streamName);
950
+ this.closing = true;
951
+ // Wake pump if it's sleeping so it can check closing flag
952
+ if (this.pumpWakeup) {
953
+ this.pumpWakeup();
954
+ }
955
+ // Wait for pump to stop (drains inflight queue, including through recovery)
956
+ if (this.pumpPromise) {
957
+ debugSession("[%s] [CLOSE] awaiting pump to drain inflight queue", this.streamName);
958
+ await this.pumpPromise;
959
+ }
960
+ // Close inner session
961
+ if (this.session) {
962
+ try {
963
+ const result = await this.session.close();
964
+ if (!result.ok) {
965
+ debugSession("[%s] error closing inner session: %s", this.streamName, result.error.message);
966
+ }
967
+ }
968
+ catch (e) {
969
+ debugSession("[%s] exception closing inner session: %s", this.streamName, e);
970
+ }
971
+ this.session = undefined;
972
+ }
973
+ // Close readable stream
974
+ try {
975
+ this.acksController?.close();
976
+ }
977
+ catch (e) {
978
+ debugSession("[%s] error closing acks controller: %s", this.streamName, e);
979
+ }
980
+ this.closed = true;
981
+ // If fatal error occurred, throw it
982
+ if (this.fatalError) {
983
+ throw this.fatalError;
984
+ }
985
+ debugSession("[%s] close complete", this.streamName);
986
+ }
987
+ async [Symbol.asyncDispose]() {
988
+ await this.close();
989
+ }
990
+ /**
991
+ * Get a stream of acknowledgements for appends.
992
+ */
993
+ acks() {
994
+ return this.readable;
995
+ }
996
+ /**
997
+ * Get the last acknowledged position.
998
+ */
999
+ lastAckedPosition() {
1000
+ return this._lastAckedPosition;
1001
+ }
1002
+ }
1003
+ //# sourceMappingURL=retry.js.map