@backblaze-labs/b2-sdk 0.1.0 → 0.2.0

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 (701) hide show
  1. package/CHANGELOG.md +110 -5
  2. package/README.md +144 -33
  3. package/dist/_virtual/_b2-sdk-version-json.cjs +4 -0
  4. package/dist/_virtual/_b2-sdk-version-json.js +4 -0
  5. package/dist/auth/account-info.d.cts +32 -0
  6. package/dist/auth/account-info.d.cts.map +1 -1
  7. package/dist/auth/account-info.d.ts +32 -0
  8. package/dist/auth/account-info.d.ts.map +1 -1
  9. package/dist/auth/file.cjs +408 -207
  10. package/dist/auth/file.cjs.map +1 -1
  11. package/dist/auth/file.d.cts +77 -3
  12. package/dist/auth/file.d.cts.map +1 -1
  13. package/dist/auth/file.d.ts +77 -3
  14. package/dist/auth/file.d.ts.map +1 -1
  15. package/dist/auth/file.js +407 -207
  16. package/dist/auth/file.js.map +1 -1
  17. package/dist/auth/in-memory.cjs +212 -183
  18. package/dist/auth/in-memory.cjs.map +1 -1
  19. package/dist/auth/in-memory.d.cts +8 -0
  20. package/dist/auth/in-memory.d.cts.map +1 -1
  21. package/dist/auth/in-memory.d.ts +8 -0
  22. package/dist/auth/in-memory.d.ts.map +1 -1
  23. package/dist/auth/in-memory.js +211 -182
  24. package/dist/auth/in-memory.js.map +1 -1
  25. package/dist/auth/index.cjs +7 -9
  26. package/dist/auth/index.d.cts +3 -2
  27. package/dist/auth/index.d.cts.map +1 -1
  28. package/dist/auth/index.d.ts +3 -2
  29. package/dist/auth/index.d.ts.map +1 -1
  30. package/dist/auth/index.js +2 -8
  31. package/dist/auth/realms.cjs +80 -7
  32. package/dist/auth/realms.cjs.map +1 -1
  33. package/dist/auth/realms.d.cts +27 -4
  34. package/dist/auth/realms.d.cts.map +1 -1
  35. package/dist/auth/realms.d.ts +27 -4
  36. package/dist/auth/realms.d.ts.map +1 -1
  37. package/dist/auth/realms.js +80 -9
  38. package/dist/auth/realms.js.map +1 -1
  39. package/dist/auth/upload-url-pool.cjs +55 -51
  40. package/dist/auth/upload-url-pool.cjs.map +1 -1
  41. package/dist/auth/upload-url-pool.js +55 -51
  42. package/dist/auth/upload-url-pool.js.map +1 -1
  43. package/dist/bucket.cjs +785 -787
  44. package/dist/bucket.cjs.map +1 -1
  45. package/dist/bucket.d.cts +35 -47
  46. package/dist/bucket.d.cts.map +1 -1
  47. package/dist/bucket.d.ts +35 -47
  48. package/dist/bucket.d.ts.map +1 -1
  49. package/dist/bucket.js +780 -782
  50. package/dist/bucket.js.map +1 -1
  51. package/dist/client.cjs +246 -228
  52. package/dist/client.cjs.map +1 -1
  53. package/dist/client.d.cts +25 -17
  54. package/dist/client.d.cts.map +1 -1
  55. package/dist/client.d.ts +25 -17
  56. package/dist/client.d.ts.map +1 -1
  57. package/dist/client.js +243 -225
  58. package/dist/client.js.map +1 -1
  59. package/dist/copy/large.cjs +114 -71
  60. package/dist/copy/large.cjs.map +1 -1
  61. package/dist/copy/large.d.cts +6 -0
  62. package/dist/copy/large.d.cts.map +1 -1
  63. package/dist/copy/large.d.ts +6 -0
  64. package/dist/copy/large.d.ts.map +1 -1
  65. package/dist/copy/large.js +112 -69
  66. package/dist/copy/large.js.map +1 -1
  67. package/dist/download/checksum.cjs +89 -0
  68. package/dist/download/checksum.cjs.map +1 -0
  69. package/dist/download/checksum.d.cts +40 -0
  70. package/dist/download/checksum.d.cts.map +1 -0
  71. package/dist/download/checksum.d.ts +40 -0
  72. package/dist/download/checksum.d.ts.map +1 -0
  73. package/dist/download/checksum.js +87 -0
  74. package/dist/download/checksum.js.map +1 -0
  75. package/dist/download/parallel.cjs +214 -118
  76. package/dist/download/parallel.cjs.map +1 -1
  77. package/dist/download/parallel.d.cts +5 -1
  78. package/dist/download/parallel.d.cts.map +1 -1
  79. package/dist/download/parallel.d.ts +5 -1
  80. package/dist/download/parallel.d.ts.map +1 -1
  81. package/dist/download/parallel.js +212 -116
  82. package/dist/download/parallel.js.map +1 -1
  83. package/dist/download/single.cjs +188 -97
  84. package/dist/download/single.cjs.map +1 -1
  85. package/dist/download/single.d.cts +6 -1
  86. package/dist/download/single.d.cts.map +1 -1
  87. package/dist/download/single.d.ts +6 -1
  88. package/dist/download/single.d.ts.map +1 -1
  89. package/dist/download/single.js +186 -98
  90. package/dist/download/single.js.map +1 -1
  91. package/dist/errors/index.cjs +699 -243
  92. package/dist/errors/index.cjs.map +1 -1
  93. package/dist/errors/index.d.cts +285 -82
  94. package/dist/errors/index.d.cts.map +1 -1
  95. package/dist/errors/index.d.ts +285 -82
  96. package/dist/errors/index.d.ts.map +1 -1
  97. package/dist/errors/index.js +678 -261
  98. package/dist/errors/index.js.map +1 -1
  99. package/dist/http/retry.cjs +45 -28
  100. package/dist/http/retry.cjs.map +1 -1
  101. package/dist/http/retry.d.cts +15 -2
  102. package/dist/http/retry.d.cts.map +1 -1
  103. package/dist/http/retry.d.ts +15 -2
  104. package/dist/http/retry.d.ts.map +1 -1
  105. package/dist/http/retry.js +46 -31
  106. package/dist/http/retry.js.map +1 -1
  107. package/dist/http/transport.cjs +438 -140
  108. package/dist/http/transport.cjs.map +1 -1
  109. package/dist/http/transport.d.cts +21 -2
  110. package/dist/http/transport.d.cts.map +1 -1
  111. package/dist/http/transport.d.ts +21 -2
  112. package/dist/http/transport.d.ts.map +1 -1
  113. package/dist/http/transport.js +437 -140
  114. package/dist/http/transport.js.map +1 -1
  115. package/dist/http/url-guard.cjs +154 -89
  116. package/dist/http/url-guard.cjs.map +1 -1
  117. package/dist/http/url-guard.d.cts +25 -3
  118. package/dist/http/url-guard.d.cts.map +1 -1
  119. package/dist/http/url-guard.d.ts +25 -3
  120. package/dist/http/url-guard.d.ts.map +1 -1
  121. package/dist/http/url-guard.js +152 -90
  122. package/dist/http/url-guard.js.map +1 -1
  123. package/dist/http/user-agent.cjs +84 -44
  124. package/dist/http/user-agent.cjs.map +1 -1
  125. package/dist/http/user-agent.js +84 -46
  126. package/dist/http/user-agent.js.map +1 -1
  127. package/dist/index.cjs +101 -77
  128. package/dist/index.d.cts +27 -21
  129. package/dist/index.d.cts.map +1 -1
  130. package/dist/index.d.ts +27 -21
  131. package/dist/index.d.ts.map +1 -1
  132. package/dist/index.js +15 -71
  133. package/dist/internal/b2-naming.cjs +66 -0
  134. package/dist/internal/b2-naming.cjs.map +1 -0
  135. package/dist/internal/b2-naming.d.cts +43 -0
  136. package/dist/internal/b2-naming.d.cts.map +1 -0
  137. package/dist/internal/b2-naming.d.ts +43 -0
  138. package/dist/internal/b2-naming.d.ts.map +1 -0
  139. package/dist/internal/b2-naming.js +60 -0
  140. package/dist/internal/b2-naming.js.map +1 -0
  141. package/dist/internal/upload-retry-options.cjs +21 -0
  142. package/dist/internal/upload-retry-options.cjs.map +1 -0
  143. package/dist/internal/upload-retry-options.d.cts +12 -0
  144. package/dist/internal/upload-retry-options.d.cts.map +1 -0
  145. package/dist/internal/upload-retry-options.d.ts +12 -0
  146. package/dist/internal/upload-retry-options.d.ts.map +1 -0
  147. package/dist/internal/upload-retry-options.js +21 -0
  148. package/dist/internal/upload-retry-options.js.map +1 -0
  149. package/dist/internal/url-redaction.cjs +31 -0
  150. package/dist/internal/url-redaction.cjs.map +1 -0
  151. package/dist/internal/url-redaction.d.cts +17 -0
  152. package/dist/internal/url-redaction.d.cts.map +1 -0
  153. package/dist/internal/url-redaction.d.ts +17 -0
  154. package/dist/internal/url-redaction.d.ts.map +1 -0
  155. package/dist/internal/url-redaction.js +31 -0
  156. package/dist/internal/url-redaction.js.map +1 -0
  157. package/dist/notifications/index.cjs +4 -6
  158. package/dist/notifications/index.d.cts +1 -1
  159. package/dist/notifications/index.d.cts.map +1 -1
  160. package/dist/notifications/index.d.ts +1 -1
  161. package/dist/notifications/index.d.ts.map +1 -1
  162. package/dist/notifications/index.js +1 -6
  163. package/dist/notifications/webhook.cjs +195 -85
  164. package/dist/notifications/webhook.cjs.map +1 -1
  165. package/dist/notifications/webhook.d.cts.map +1 -1
  166. package/dist/notifications/webhook.d.ts.map +1 -1
  167. package/dist/notifications/webhook.js +195 -87
  168. package/dist/notifications/webhook.js.map +1 -1
  169. package/dist/object.cjs +253 -210
  170. package/dist/object.cjs.map +1 -1
  171. package/dist/object.d.cts +9 -55
  172. package/dist/object.d.cts.map +1 -1
  173. package/dist/object.d.ts +9 -55
  174. package/dist/object.d.ts.map +1 -1
  175. package/dist/object.js +249 -206
  176. package/dist/object.js.map +1 -1
  177. package/dist/raw/encoding.cjs +74 -35
  178. package/dist/raw/encoding.cjs.map +1 -1
  179. package/dist/raw/encoding.js +74 -38
  180. package/dist/raw/encoding.js.map +1 -1
  181. package/dist/raw/index.cjs +678 -587
  182. package/dist/raw/index.cjs.map +1 -1
  183. package/dist/raw/index.d.cts +121 -18
  184. package/dist/raw/index.d.cts.map +1 -1
  185. package/dist/raw/index.d.ts +121 -18
  186. package/dist/raw/index.d.ts.map +1 -1
  187. package/dist/raw/index.js +674 -589
  188. package/dist/raw/index.js.map +1 -1
  189. package/dist/s3/index.cjs +355 -18
  190. package/dist/s3/index.cjs.map +1 -1
  191. package/dist/s3/index.d.cts +233 -5
  192. package/dist/s3/index.d.cts.map +1 -1
  193. package/dist/s3/index.d.ts +233 -5
  194. package/dist/s3/index.d.ts.map +1 -1
  195. package/dist/s3/index.js +351 -22
  196. package/dist/s3/index.js.map +1 -1
  197. package/dist/s3/sigv4.cjs +149 -0
  198. package/dist/s3/sigv4.cjs.map +1 -0
  199. package/dist/s3/sigv4.d.cts +43 -0
  200. package/dist/s3/sigv4.d.cts.map +1 -0
  201. package/dist/s3/sigv4.d.ts +43 -0
  202. package/dist/s3/sigv4.d.ts.map +1 -0
  203. package/dist/s3/sigv4.js +148 -0
  204. package/dist/s3/sigv4.js.map +1 -0
  205. package/dist/s3/validation.cjs +69 -0
  206. package/dist/s3/validation.cjs.map +1 -0
  207. package/dist/s3/validation.d.cts +43 -0
  208. package/dist/s3/validation.d.cts.map +1 -0
  209. package/dist/s3/validation.d.ts +43 -0
  210. package/dist/s3/validation.d.ts.map +1 -0
  211. package/dist/s3/validation.js +66 -0
  212. package/dist/s3/validation.js.map +1 -0
  213. package/dist/simulator/capabilities.cjs +63 -48
  214. package/dist/simulator/capabilities.cjs.map +1 -1
  215. package/dist/simulator/capabilities.js +63 -49
  216. package/dist/simulator/capabilities.js.map +1 -1
  217. package/dist/simulator/index.cjs +2124 -1548
  218. package/dist/simulator/index.cjs.map +1 -1
  219. package/dist/simulator/index.d.cts +79 -11
  220. package/dist/simulator/index.d.cts.map +1 -1
  221. package/dist/simulator/index.d.ts +79 -11
  222. package/dist/simulator/index.d.ts.map +1 -1
  223. package/dist/simulator/index.js +2112 -1546
  224. package/dist/simulator/index.js.map +1 -1
  225. package/dist/simulator/validation.cjs +191 -153
  226. package/dist/simulator/validation.cjs.map +1 -1
  227. package/dist/simulator/validation.d.cts +3 -21
  228. package/dist/simulator/validation.d.cts.map +1 -1
  229. package/dist/simulator/validation.d.ts +3 -21
  230. package/dist/simulator/validation.d.ts.map +1 -1
  231. package/dist/simulator/validation.js +188 -162
  232. package/dist/simulator/validation.js.map +1 -1
  233. package/dist/streams/collect.cjs +74 -24
  234. package/dist/streams/collect.cjs.map +1 -1
  235. package/dist/streams/collect.d.cts +14 -1
  236. package/dist/streams/collect.d.cts.map +1 -1
  237. package/dist/streams/collect.d.ts +14 -1
  238. package/dist/streams/collect.d.ts.map +1 -1
  239. package/dist/streams/collect.js +74 -25
  240. package/dist/streams/collect.js.map +1 -1
  241. package/dist/streams/file-source.cjs +287 -0
  242. package/dist/streams/file-source.cjs.map +1 -0
  243. package/dist/streams/file-source.d.cts +96 -0
  244. package/dist/streams/file-source.d.cts.map +1 -0
  245. package/dist/streams/file-source.d.ts +96 -0
  246. package/dist/streams/file-source.d.ts.map +1 -0
  247. package/dist/streams/file-source.js +286 -0
  248. package/dist/streams/file-source.js.map +1 -0
  249. package/dist/streams/hash.cjs +207 -115
  250. package/dist/streams/hash.cjs.map +1 -1
  251. package/dist/streams/hash.d.cts +5 -4
  252. package/dist/streams/hash.d.cts.map +1 -1
  253. package/dist/streams/hash.d.ts +5 -4
  254. package/dist/streams/hash.d.ts.map +1 -1
  255. package/dist/streams/hash.js +208 -95
  256. package/dist/streams/hash.js.map +1 -1
  257. package/dist/streams/index.cjs +12 -12
  258. package/dist/streams/index.d.cts +3 -3
  259. package/dist/streams/index.d.cts.map +1 -1
  260. package/dist/streams/index.d.ts +3 -3
  261. package/dist/streams/index.d.ts.map +1 -1
  262. package/dist/streams/index.js +2 -10
  263. package/dist/streams/progress.cjs +60 -46
  264. package/dist/streams/progress.cjs.map +1 -1
  265. package/dist/streams/progress.js +60 -46
  266. package/dist/streams/progress.js.map +1 -1
  267. package/dist/streams/source.cjs +316 -146
  268. package/dist/streams/source.cjs.map +1 -1
  269. package/dist/streams/source.d.cts +56 -18
  270. package/dist/streams/source.d.cts.map +1 -1
  271. package/dist/streams/source.d.ts +56 -18
  272. package/dist/streams/source.d.ts.map +1 -1
  273. package/dist/streams/source.js +312 -149
  274. package/dist/streams/source.js.map +1 -1
  275. package/dist/sync/actions/index.cjs +236 -184
  276. package/dist/sync/actions/index.cjs.map +1 -1
  277. package/dist/sync/actions/index.d.cts +29 -21
  278. package/dist/sync/actions/index.d.cts.map +1 -1
  279. package/dist/sync/actions/index.d.ts +29 -21
  280. package/dist/sync/actions/index.d.ts.map +1 -1
  281. package/dist/sync/actions/index.js +236 -190
  282. package/dist/sync/actions/index.js.map +1 -1
  283. package/dist/sync/b2-sha1-reader.cjs +148 -0
  284. package/dist/sync/b2-sha1-reader.cjs.map +1 -0
  285. package/dist/sync/b2-sha1-reader.d.cts +58 -0
  286. package/dist/sync/b2-sha1-reader.d.cts.map +1 -0
  287. package/dist/sync/b2-sha1-reader.d.ts +58 -0
  288. package/dist/sync/b2-sha1-reader.d.ts.map +1 -0
  289. package/dist/sync/b2-sha1-reader.js +145 -0
  290. package/dist/sync/b2-sha1-reader.js.map +1 -0
  291. package/dist/sync/download-staging.cjs +265 -0
  292. package/dist/sync/download-staging.cjs.map +1 -0
  293. package/dist/sync/download-staging.d.cts +54 -0
  294. package/dist/sync/download-staging.d.cts.map +1 -0
  295. package/dist/sync/download-staging.d.ts +54 -0
  296. package/dist/sync/download-staging.d.ts.map +1 -0
  297. package/dist/sync/download-staging.js +259 -0
  298. package/dist/sync/download-staging.js.map +1 -0
  299. package/dist/sync/filesystem-errors.cjs +32 -0
  300. package/dist/sync/filesystem-errors.cjs.map +1 -0
  301. package/dist/sync/filesystem-errors.d.cts +8 -0
  302. package/dist/sync/filesystem-errors.d.cts.map +1 -0
  303. package/dist/sync/filesystem-errors.d.ts +8 -0
  304. package/dist/sync/filesystem-errors.d.ts.map +1 -0
  305. package/dist/sync/filesystem-errors.js +32 -0
  306. package/dist/sync/filesystem-errors.js.map +1 -0
  307. package/dist/sync/filters.cjs +217 -0
  308. package/dist/sync/filters.cjs.map +1 -0
  309. package/dist/sync/filters.d.cts +51 -0
  310. package/dist/sync/filters.d.cts.map +1 -0
  311. package/dist/sync/filters.d.ts +51 -0
  312. package/dist/sync/filters.d.ts.map +1 -0
  313. package/dist/sync/filters.js +213 -0
  314. package/dist/sync/filters.js.map +1 -0
  315. package/dist/sync/index.cjs +39 -22
  316. package/dist/sync/index.d.cts +14 -9
  317. package/dist/sync/index.d.cts.map +1 -1
  318. package/dist/sync/index.d.ts +14 -9
  319. package/dist/sync/index.d.ts.map +1 -1
  320. package/dist/sync/index.js +9 -20
  321. package/dist/sync/local-file-identity.cjs +61 -0
  322. package/dist/sync/local-file-identity.cjs.map +1 -0
  323. package/dist/sync/local-file-identity.d.cts +37 -0
  324. package/dist/sync/local-file-identity.d.cts.map +1 -0
  325. package/dist/sync/local-file-identity.d.ts +37 -0
  326. package/dist/sync/local-file-identity.d.ts.map +1 -0
  327. package/dist/sync/local-file-identity.js +60 -0
  328. package/dist/sync/local-file-identity.js.map +1 -0
  329. package/dist/sync/local-file-io.cjs +364 -0
  330. package/dist/sync/local-file-io.cjs.map +1 -0
  331. package/dist/sync/local-file-io.d.cts +75 -0
  332. package/dist/sync/local-file-io.d.cts.map +1 -0
  333. package/dist/sync/local-file-io.d.ts +75 -0
  334. package/dist/sync/local-file-io.d.ts.map +1 -0
  335. package/dist/sync/local-file-io.js +360 -0
  336. package/dist/sync/local-file-io.js.map +1 -0
  337. package/dist/sync/local-filesystem-root.cjs +27 -0
  338. package/dist/sync/local-filesystem-root.cjs.map +1 -0
  339. package/dist/sync/local-filesystem-root.d.cts +18 -0
  340. package/dist/sync/local-filesystem-root.d.cts.map +1 -0
  341. package/dist/sync/local-filesystem-root.d.ts +18 -0
  342. package/dist/sync/local-filesystem-root.d.ts.map +1 -0
  343. package/dist/sync/local-filesystem-root.js +26 -0
  344. package/dist/sync/local-filesystem-root.js.map +1 -0
  345. package/dist/sync/local-sha1.cjs +119 -0
  346. package/dist/sync/local-sha1.cjs.map +1 -0
  347. package/dist/sync/local-sha1.d.cts +39 -0
  348. package/dist/sync/local-sha1.d.cts.map +1 -0
  349. package/dist/sync/local-sha1.d.ts +39 -0
  350. package/dist/sync/local-sha1.d.ts.map +1 -0
  351. package/dist/sync/local-sha1.js +117 -0
  352. package/dist/sync/local-sha1.js.map +1 -0
  353. package/dist/sync/pairing.cjs +118 -29
  354. package/dist/sync/pairing.cjs.map +1 -1
  355. package/dist/sync/pairing.d.cts +7 -2
  356. package/dist/sync/pairing.d.cts.map +1 -1
  357. package/dist/sync/pairing.d.ts +7 -2
  358. package/dist/sync/pairing.d.ts.map +1 -1
  359. package/dist/sync/pairing.js +120 -31
  360. package/dist/sync/pairing.js.map +1 -1
  361. package/dist/sync/path-order.cjs +30 -0
  362. package/dist/sync/path-order.cjs.map +1 -0
  363. package/dist/sync/path-order.d.cts +28 -0
  364. package/dist/sync/path-order.d.cts.map +1 -0
  365. package/dist/sync/path-order.d.ts +28 -0
  366. package/dist/sync/path-order.d.ts.map +1 -0
  367. package/dist/sync/path-order.js +29 -0
  368. package/dist/sync/path-order.js.map +1 -0
  369. package/dist/sync/path-safety.cjs +111 -0
  370. package/dist/sync/path-safety.cjs.map +1 -0
  371. package/dist/sync/path-safety.d.cts +78 -0
  372. package/dist/sync/path-safety.d.cts.map +1 -0
  373. package/dist/sync/path-safety.d.ts +78 -0
  374. package/dist/sync/path-safety.d.ts.map +1 -0
  375. package/dist/sync/path-safety.js +105 -0
  376. package/dist/sync/path-safety.js.map +1 -0
  377. package/dist/sync/paths.d.cts +19 -0
  378. package/dist/sync/paths.d.cts.map +1 -0
  379. package/dist/sync/paths.d.ts +19 -0
  380. package/dist/sync/paths.d.ts.map +1 -0
  381. package/dist/sync/policies/compare.cjs +389 -11
  382. package/dist/sync/policies/compare.cjs.map +1 -1
  383. package/dist/sync/policies/compare.d.cts +100 -2
  384. package/dist/sync/policies/compare.d.cts.map +1 -1
  385. package/dist/sync/policies/compare.d.ts +100 -2
  386. package/dist/sync/policies/compare.d.ts.map +1 -1
  387. package/dist/sync/policies/compare.js +387 -13
  388. package/dist/sync/policies/compare.js.map +1 -1
  389. package/dist/sync/policies/index.cjs +76 -65
  390. package/dist/sync/policies/index.cjs.map +1 -1
  391. package/dist/sync/policies/index.d.cts +35 -6
  392. package/dist/sync/policies/index.d.cts.map +1 -1
  393. package/dist/sync/policies/index.d.ts +35 -6
  394. package/dist/sync/policies/index.d.ts.map +1 -1
  395. package/dist/sync/policies/index.js +76 -65
  396. package/dist/sync/policies/index.js.map +1 -1
  397. package/dist/sync/prefix.cjs +96 -0
  398. package/dist/sync/prefix.cjs.map +1 -0
  399. package/dist/sync/prefix.d.cts +55 -0
  400. package/dist/sync/prefix.d.cts.map +1 -0
  401. package/dist/sync/prefix.d.ts +55 -0
  402. package/dist/sync/prefix.d.ts.map +1 -0
  403. package/dist/sync/prefix.js +92 -0
  404. package/dist/sync/prefix.js.map +1 -0
  405. package/dist/sync/regexp-safety.cjs +192 -0
  406. package/dist/sync/regexp-safety.cjs.map +1 -0
  407. package/dist/sync/regexp-safety.d.cts +29 -0
  408. package/dist/sync/regexp-safety.d.cts.map +1 -0
  409. package/dist/sync/regexp-safety.d.ts +29 -0
  410. package/dist/sync/regexp-safety.d.ts.map +1 -0
  411. package/dist/sync/regexp-safety.js +190 -0
  412. package/dist/sync/regexp-safety.js.map +1 -0
  413. package/dist/sync/scan-events.cjs +33 -0
  414. package/dist/sync/scan-events.cjs.map +1 -0
  415. package/dist/sync/scan-events.d.cts +17 -0
  416. package/dist/sync/scan-events.d.cts.map +1 -0
  417. package/dist/sync/scan-events.d.ts +17 -0
  418. package/dist/sync/scan-events.d.ts.map +1 -0
  419. package/dist/sync/scan-events.js +32 -0
  420. package/dist/sync/scan-events.js.map +1 -0
  421. package/dist/sync/scan-limit.cjs +33 -0
  422. package/dist/sync/scan-limit.cjs.map +1 -0
  423. package/dist/sync/scan-limit.d.cts +21 -0
  424. package/dist/sync/scan-limit.d.cts.map +1 -0
  425. package/dist/sync/scan-limit.d.ts +21 -0
  426. package/dist/sync/scan-limit.d.ts.map +1 -0
  427. package/dist/sync/scan-limit.js +31 -0
  428. package/dist/sync/scan-limit.js.map +1 -0
  429. package/dist/sync/scanners/b2.cjs +239 -55
  430. package/dist/sync/scanners/b2.cjs.map +1 -1
  431. package/dist/sync/scanners/b2.d.cts +26 -7
  432. package/dist/sync/scanners/b2.d.cts.map +1 -1
  433. package/dist/sync/scanners/b2.d.ts +26 -7
  434. package/dist/sync/scanners/b2.d.ts.map +1 -1
  435. package/dist/sync/scanners/b2.js +239 -55
  436. package/dist/sync/scanners/b2.js.map +1 -1
  437. package/dist/sync/scanners/local.cjs +215 -56
  438. package/dist/sync/scanners/local.cjs.map +1 -1
  439. package/dist/sync/scanners/local.d.cts +22 -7
  440. package/dist/sync/scanners/local.d.cts.map +1 -1
  441. package/dist/sync/scanners/local.d.ts +22 -7
  442. package/dist/sync/scanners/local.d.ts.map +1 -1
  443. package/dist/sync/scanners/local.js +216 -57
  444. package/dist/sync/scanners/local.js.map +1 -1
  445. package/dist/sync/sha1-metadata.cjs +94 -0
  446. package/dist/sync/sha1-metadata.cjs.map +1 -0
  447. package/dist/sync/sha1-metadata.d.cts +82 -0
  448. package/dist/sync/sha1-metadata.d.cts.map +1 -0
  449. package/dist/sync/sha1-metadata.d.ts +82 -0
  450. package/dist/sync/sha1-metadata.d.ts.map +1 -0
  451. package/dist/sync/sha1-metadata.js +89 -0
  452. package/dist/sync/sha1-metadata.js.map +1 -0
  453. package/dist/sync/sha1-options.cjs +23 -0
  454. package/dist/sync/sha1-options.cjs.map +1 -0
  455. package/dist/sync/sha1-options.d.cts +14 -0
  456. package/dist/sync/sha1-options.d.cts.map +1 -0
  457. package/dist/sync/sha1-options.d.ts +14 -0
  458. package/dist/sync/sha1-options.d.ts.map +1 -0
  459. package/dist/sync/sha1-options.js +21 -0
  460. package/dist/sync/sha1-options.js.map +1 -0
  461. package/dist/sync/synchronizer.cjs +782 -197
  462. package/dist/sync/synchronizer.cjs.map +1 -1
  463. package/dist/sync/synchronizer.d.cts +47 -1
  464. package/dist/sync/synchronizer.d.cts.map +1 -1
  465. package/dist/sync/synchronizer.d.ts +47 -1
  466. package/dist/sync/synchronizer.d.ts.map +1 -1
  467. package/dist/sync/synchronizer.js +779 -173
  468. package/dist/sync/synchronizer.js.map +1 -1
  469. package/dist/sync/types.d.cts +208 -16
  470. package/dist/sync/types.d.cts.map +1 -1
  471. package/dist/sync/types.d.ts +208 -16
  472. package/dist/sync/types.d.ts.map +1 -1
  473. package/dist/types/auth.cjs +76 -56
  474. package/dist/types/auth.cjs.map +1 -1
  475. package/dist/types/auth.d.cts +67 -9
  476. package/dist/types/auth.d.cts.map +1 -1
  477. package/dist/types/auth.d.ts +67 -9
  478. package/dist/types/auth.d.ts.map +1 -1
  479. package/dist/types/auth.js +77 -57
  480. package/dist/types/auth.js.map +1 -1
  481. package/dist/types/bucket.cjs +74 -38
  482. package/dist/types/bucket.cjs.map +1 -1
  483. package/dist/types/bucket.js +75 -41
  484. package/dist/types/bucket.js.map +1 -1
  485. package/dist/types/encryption.cjs +364 -327
  486. package/dist/types/encryption.cjs.map +1 -1
  487. package/dist/types/encryption.d.cts +16 -0
  488. package/dist/types/encryption.d.cts.map +1 -1
  489. package/dist/types/encryption.d.ts +16 -0
  490. package/dist/types/encryption.d.ts.map +1 -1
  491. package/dist/types/encryption.js +364 -310
  492. package/dist/types/encryption.js.map +1 -1
  493. package/dist/types/errors.cjs +47 -0
  494. package/dist/types/errors.cjs.map +1 -0
  495. package/dist/types/errors.d.cts +13 -4
  496. package/dist/types/errors.d.cts.map +1 -1
  497. package/dist/types/errors.d.ts +13 -4
  498. package/dist/types/errors.d.ts.map +1 -1
  499. package/dist/types/errors.js +47 -0
  500. package/dist/types/errors.js.map +1 -0
  501. package/dist/types/file.cjs +36 -19
  502. package/dist/types/file.cjs.map +1 -1
  503. package/dist/types/file.d.cts +2 -2
  504. package/dist/types/file.d.cts.map +1 -1
  505. package/dist/types/file.d.ts +2 -2
  506. package/dist/types/file.d.ts.map +1 -1
  507. package/dist/types/file.js +37 -21
  508. package/dist/types/file.js.map +1 -1
  509. package/dist/types/ids.cjs +53 -9
  510. package/dist/types/ids.cjs.map +1 -1
  511. package/dist/types/ids.js +54 -15
  512. package/dist/types/ids.js.map +1 -1
  513. package/dist/types/index.d.cts +12 -11
  514. package/dist/types/index.d.cts.map +1 -1
  515. package/dist/types/index.d.ts +12 -11
  516. package/dist/types/index.d.ts.map +1 -1
  517. package/dist/types/key.d.cts +44 -8
  518. package/dist/types/key.d.cts.map +1 -1
  519. package/dist/types/key.d.ts +44 -8
  520. package/dist/types/key.d.ts.map +1 -1
  521. package/dist/types/lock.cjs +33 -13
  522. package/dist/types/lock.cjs.map +1 -1
  523. package/dist/types/lock.js +34 -15
  524. package/dist/types/lock.js.map +1 -1
  525. package/dist/types/notifications.cjs +44 -22
  526. package/dist/types/notifications.cjs.map +1 -1
  527. package/dist/types/notifications.js +45 -23
  528. package/dist/types/notifications.js.map +1 -1
  529. package/dist/types/upload.d.cts +39 -5
  530. package/dist/types/upload.d.cts.map +1 -1
  531. package/dist/types/upload.d.ts +39 -5
  532. package/dist/types/upload.d.ts.map +1 -1
  533. package/dist/upload/abort-scope.cjs +91 -0
  534. package/dist/upload/abort-scope.cjs.map +1 -0
  535. package/dist/upload/abort-scope.d.cts +48 -0
  536. package/dist/upload/abort-scope.d.cts.map +1 -0
  537. package/dist/upload/abort-scope.d.ts +48 -0
  538. package/dist/upload/abort-scope.d.ts.map +1 -0
  539. package/dist/upload/abort-scope.js +88 -0
  540. package/dist/upload/abort-scope.js.map +1 -0
  541. package/dist/upload/cancel.cjs +183 -8
  542. package/dist/upload/cancel.cjs.map +1 -1
  543. package/dist/upload/cancel.d.cts +110 -2
  544. package/dist/upload/cancel.d.cts.map +1 -1
  545. package/dist/upload/cancel.d.ts +110 -2
  546. package/dist/upload/cancel.d.ts.map +1 -1
  547. package/dist/upload/cancel.js +178 -9
  548. package/dist/upload/cancel.js.map +1 -1
  549. package/dist/upload/concurrency.cjs +79 -52
  550. package/dist/upload/concurrency.cjs.map +1 -1
  551. package/dist/upload/concurrency.js +79 -53
  552. package/dist/upload/concurrency.js.map +1 -1
  553. package/dist/upload/finish.cjs +59 -0
  554. package/dist/upload/finish.cjs.map +1 -0
  555. package/dist/upload/finish.d.cts +26 -0
  556. package/dist/upload/finish.d.cts.map +1 -0
  557. package/dist/upload/finish.d.ts +26 -0
  558. package/dist/upload/finish.d.ts.map +1 -0
  559. package/dist/upload/finish.js +59 -0
  560. package/dist/upload/finish.js.map +1 -0
  561. package/dist/upload/large.cjs +301 -218
  562. package/dist/upload/large.cjs.map +1 -1
  563. package/dist/upload/large.d.cts +76 -9
  564. package/dist/upload/large.d.cts.map +1 -1
  565. package/dist/upload/large.d.ts +76 -9
  566. package/dist/upload/large.d.ts.map +1 -1
  567. package/dist/upload/large.js +301 -218
  568. package/dist/upload/large.js.map +1 -1
  569. package/dist/upload/options.cjs +28 -0
  570. package/dist/upload/options.cjs.map +1 -0
  571. package/dist/upload/options.d.cts +104 -0
  572. package/dist/upload/options.d.cts.map +1 -0
  573. package/dist/upload/options.d.ts +104 -0
  574. package/dist/upload/options.d.ts.map +1 -0
  575. package/dist/upload/options.js +27 -0
  576. package/dist/upload/options.js.map +1 -0
  577. package/dist/upload/resume.cjs +333 -33
  578. package/dist/upload/resume.cjs.map +1 -1
  579. package/dist/upload/resume.d.cts +82 -12
  580. package/dist/upload/resume.d.cts.map +1 -1
  581. package/dist/upload/resume.d.ts +82 -12
  582. package/dist/upload/resume.d.ts.map +1 -1
  583. package/dist/upload/resume.js +330 -33
  584. package/dist/upload/resume.js.map +1 -1
  585. package/dist/upload/retry.cjs +186 -0
  586. package/dist/upload/retry.cjs.map +1 -0
  587. package/dist/upload/retry.d.cts +127 -0
  588. package/dist/upload/retry.d.cts.map +1 -0
  589. package/dist/upload/retry.d.ts +127 -0
  590. package/dist/upload/retry.d.ts.map +1 -0
  591. package/dist/upload/retry.js +182 -0
  592. package/dist/upload/retry.js.map +1 -0
  593. package/dist/upload/single.cjs +68 -44
  594. package/dist/upload/single.cjs.map +1 -1
  595. package/dist/upload/single.d.cts +2 -1
  596. package/dist/upload/single.d.cts.map +1 -1
  597. package/dist/upload/single.d.ts +2 -1
  598. package/dist/upload/single.d.ts.map +1 -1
  599. package/dist/upload/single.js +68 -44
  600. package/dist/upload/single.js.map +1 -1
  601. package/dist/upload/stream.cjs +317 -193
  602. package/dist/upload/stream.cjs.map +1 -1
  603. package/dist/upload/stream.d.cts +3 -1
  604. package/dist/upload/stream.d.cts.map +1 -1
  605. package/dist/upload/stream.d.ts +3 -1
  606. package/dist/upload/stream.d.ts.map +1 -1
  607. package/dist/upload/stream.js +316 -192
  608. package/dist/upload/stream.js.map +1 -1
  609. package/dist/util/best-effort.cjs +42 -8
  610. package/dist/util/best-effort.cjs.map +1 -1
  611. package/dist/util/best-effort.d.cts +2 -1
  612. package/dist/util/best-effort.d.cts.map +1 -1
  613. package/dist/util/best-effort.d.ts +2 -1
  614. package/dist/util/best-effort.d.ts.map +1 -1
  615. package/dist/util/best-effort.js +43 -9
  616. package/dist/util/best-effort.js.map +1 -1
  617. package/dist/util/bytes.cjs +23 -0
  618. package/dist/util/bytes.cjs.map +1 -0
  619. package/dist/util/bytes.d.cts +15 -0
  620. package/dist/util/bytes.d.cts.map +1 -0
  621. package/dist/util/bytes.d.ts +15 -0
  622. package/dist/util/bytes.d.ts.map +1 -0
  623. package/dist/util/bytes.js +23 -0
  624. package/dist/util/bytes.js.map +1 -0
  625. package/dist/util/crypto.cjs +68 -0
  626. package/dist/util/crypto.cjs.map +1 -0
  627. package/dist/util/crypto.d.cts +26 -0
  628. package/dist/util/crypto.d.cts.map +1 -0
  629. package/dist/util/crypto.d.ts +26 -0
  630. package/dist/util/crypto.d.ts.map +1 -0
  631. package/dist/util/crypto.js +66 -0
  632. package/dist/util/crypto.js.map +1 -0
  633. package/dist/util/defaults.cjs +25 -9
  634. package/dist/util/defaults.cjs.map +1 -1
  635. package/dist/util/defaults.js +26 -11
  636. package/dist/util/defaults.js.map +1 -1
  637. package/dist/util/error-reason.cjs +41 -0
  638. package/dist/util/error-reason.cjs.map +1 -0
  639. package/dist/util/error-reason.d.cts +9 -0
  640. package/dist/util/error-reason.d.cts.map +1 -0
  641. package/dist/util/error-reason.d.ts +9 -0
  642. package/dist/util/error-reason.d.ts.map +1 -0
  643. package/dist/util/error-reason.js +41 -0
  644. package/dist/util/error-reason.js.map +1 -0
  645. package/dist/util/http.cjs +23 -0
  646. package/dist/util/http.cjs.map +1 -0
  647. package/dist/util/http.d.cts +13 -0
  648. package/dist/util/http.d.cts.map +1 -0
  649. package/dist/util/http.d.ts +13 -0
  650. package/dist/util/http.d.ts.map +1 -0
  651. package/dist/util/http.js +23 -0
  652. package/dist/util/http.js.map +1 -0
  653. package/dist/util/normalize.cjs +66 -7
  654. package/dist/util/normalize.cjs.map +1 -1
  655. package/dist/util/normalize.js +67 -10
  656. package/dist/util/normalize.js.map +1 -1
  657. package/dist/util/paginator.cjs +63 -14
  658. package/dist/util/paginator.cjs.map +1 -1
  659. package/dist/util/paginator.js +64 -16
  660. package/dist/util/paginator.js.map +1 -1
  661. package/dist/util/plan-ranges.cjs +47 -22
  662. package/dist/util/plan-ranges.cjs.map +1 -1
  663. package/dist/util/plan-ranges.js +48 -24
  664. package/dist/util/plan-ranges.js.map +1 -1
  665. package/dist/util/sha1.cjs +27 -0
  666. package/dist/util/sha1.cjs.map +1 -0
  667. package/dist/util/sha1.d.cts +17 -0
  668. package/dist/util/sha1.d.cts.map +1 -0
  669. package/dist/util/sha1.d.ts +17 -0
  670. package/dist/util/sha1.d.ts.map +1 -0
  671. package/dist/util/sha1.js +26 -0
  672. package/dist/util/sha1.js.map +1 -0
  673. package/dist/util/text-codec.cjs +29 -5
  674. package/dist/util/text-codec.cjs.map +1 -1
  675. package/dist/util/text-codec.js +30 -7
  676. package/dist/util/text-codec.js.map +1 -1
  677. package/dist/util/to-error.cjs +18 -4
  678. package/dist/util/to-error.cjs.map +1 -1
  679. package/dist/util/to-error.js +19 -5
  680. package/dist/util/to-error.js.map +1 -1
  681. package/dist/version.cjs +17 -5
  682. package/dist/version.cjs.map +1 -1
  683. package/dist/version.d.cts +3 -3
  684. package/dist/version.d.ts +3 -3
  685. package/dist/version.js +19 -6
  686. package/dist/version.js.map +1 -1
  687. package/package.json +19 -16
  688. package/dist/auth/index.cjs.map +0 -1
  689. package/dist/auth/index.js.map +0 -1
  690. package/dist/index.cjs.map +0 -1
  691. package/dist/index.js.map +0 -1
  692. package/dist/notifications/index.cjs.map +0 -1
  693. package/dist/notifications/index.js.map +0 -1
  694. package/dist/package.json.cjs +0 -9
  695. package/dist/package.json.cjs.map +0 -1
  696. package/dist/package.json.js +0 -9
  697. package/dist/package.json.js.map +0 -1
  698. package/dist/streams/index.cjs.map +0 -1
  699. package/dist/streams/index.js.map +0 -1
  700. package/dist/sync/index.cjs.map +0 -1
  701. package/dist/sync/index.js.map +0 -1
@@ -1,26 +1,75 @@
1
- async function collectStream(stream) {
2
- const reader = stream.getReader();
3
- try {
4
- const chunks = [];
5
- let total = 0;
6
- while (true) {
7
- const { done, value } = await reader.read();
8
- if (done) break;
9
- chunks.push(value);
10
- total += value.byteLength;
11
- }
12
- const result = new Uint8Array(total);
13
- let offset = 0;
14
- for (const chunk of chunks) {
15
- result.set(chunk, offset);
16
- offset += chunk.byteLength;
17
- }
18
- return result;
19
- } finally {
20
- reader.releaseLock();
21
- }
1
+ //#region src/streams/collect.ts
2
+ /**
3
+ * Drain a `ReadableStream<Uint8Array>` into a single contiguous
4
+ * `Uint8Array`. Releases the reader lock on both the happy and error
5
+ * paths so the underlying stream can propagate close / error events to
6
+ * the upstream producer.
7
+ *
8
+ * Used by both `createParallelDownloadStream` (per-range fetch) and
9
+ * `StreamSource.toArrayBuffer` (whole-source materialisation). The two
10
+ * code paths previously hand-rolled the same accumulate-then-concat
11
+ * loop; consolidating here removes ~25 duplicated lines and a class of
12
+ * lock-leak bugs.
13
+ *
14
+ * @param stream - Readable stream to consume. Will be fully drained.
15
+ * @param options - Optional abort signal used to stop a pending read.
16
+ *
17
+ * @returns A new `Uint8Array` containing every byte the stream produced.
18
+ */
19
+ async function collectStream(stream, options = {}) {
20
+ const reader = stream.getReader();
21
+ try {
22
+ const chunks = [];
23
+ let total = 0;
24
+ while (true) {
25
+ const { done, value } = await readStreamChunkWithSignal(reader, options.signal);
26
+ if (done) break;
27
+ chunks.push(value);
28
+ total += value.byteLength;
29
+ }
30
+ const result = new Uint8Array(total);
31
+ let offset = 0;
32
+ for (const chunk of chunks) {
33
+ result.set(chunk, offset);
34
+ offset += chunk.byteLength;
35
+ }
36
+ return result;
37
+ } finally {
38
+ reader.releaseLock();
39
+ }
22
40
  }
23
- export {
24
- collectStream
25
- };
26
- //# sourceMappingURL=collect.js.map
41
+ /**
42
+ * Reads one chunk and rejects when the supplied signal aborts.
43
+ * @param reader - Stream reader to read from.
44
+ * @param signal - Optional abort signal that cancels the read.
45
+ *
46
+ * @returns The next stream read result.
47
+ *
48
+ * @internal
49
+ */
50
+ async function readStreamChunkWithSignal(reader, signal) {
51
+ if (signal === void 0) return reader.read();
52
+ signal.throwIfAborted();
53
+ let removeAbortListener;
54
+ const abortPromise = new Promise((_, reject) => {
55
+ const onAbort = () => {
56
+ const reason = abortReason(signal);
57
+ reject(reason);
58
+ reader.cancel(reason).catch(() => {});
59
+ };
60
+ signal.addEventListener("abort", onAbort, { once: true });
61
+ removeAbortListener = () => signal.removeEventListener("abort", onAbort);
62
+ });
63
+ try {
64
+ return await Promise.race([reader.read(), abortPromise]);
65
+ } finally {
66
+ removeAbortListener?.();
67
+ }
68
+ }
69
+ function abortReason(signal) {
70
+ return signal.reason ?? new DOMException("The operation was aborted.", "AbortError");
71
+ }
72
+ //#endregion
73
+ export { collectStream, readStreamChunkWithSignal };
74
+
75
+ //# sourceMappingURL=collect.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"collect.js","sources":["../../src/streams/collect.ts"],"sourcesContent":["/**\n * Drain a `ReadableStream<Uint8Array>` into a single contiguous\n * `Uint8Array`. Releases the reader lock on both the happy and error\n * paths so the underlying stream can propagate close / error events to\n * the upstream producer.\n *\n * Used by both `createParallelDownloadStream` (per-range fetch) and\n * `StreamSource.toArrayBuffer` (whole-source materialisation). The two\n * code paths previously hand-rolled the same accumulate-then-concat\n * loop; consolidating here removes ~25 duplicated lines and a class of\n * lock-leak bugs.\n *\n * @param stream - Readable stream to consume. Will be fully drained.\n *\n * @returns A new `Uint8Array` containing every byte the stream produced.\n */\nexport async function collectStream(stream: ReadableStream<Uint8Array>): Promise<Uint8Array> {\n const reader = stream.getReader()\n try {\n const chunks: Uint8Array[] = []\n let total = 0\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n chunks.push(value)\n total += value.byteLength\n }\n const result = new Uint8Array(total)\n let offset = 0\n for (const chunk of chunks) {\n result.set(chunk, offset)\n offset += chunk.byteLength\n }\n return result\n } finally {\n // Releasing here lets the underlying stream propagate close / error\n // events to any upstream producer (e.g. a Node `Readable`) even on\n // the error path where a mid-read throw left the reader locked.\n reader.releaseLock()\n }\n}\n"],"names":[],"mappings":"AAgBA,eAAsB,cAAc,QAAyD;AAC3F,QAAM,SAAS,OAAO,UAAA;AACtB,MAAI;AACF,UAAM,SAAuB,CAAA;AAC7B,QAAI,QAAQ;AACZ,WAAO,MAAM;AACX,YAAM,EAAE,MAAM,MAAA,IAAU,MAAM,OAAO,KAAA;AACrC,UAAI,KAAM;AACV,aAAO,KAAK,KAAK;AACjB,eAAS,MAAM;AAAA,IACjB;AACA,UAAM,SAAS,IAAI,WAAW,KAAK;AACnC,QAAI,SAAS;AACb,eAAW,SAAS,QAAQ;AAC1B,aAAO,IAAI,OAAO,MAAM;AACxB,gBAAU,MAAM;AAAA,IAClB;AACA,WAAO;AAAA,EACT,UAAA;AAIE,WAAO,YAAA;AAAA,EACT;AACF;"}
1
+ {"version":3,"file":"collect.js","names":[],"sources":["../../src/streams/collect.ts"],"sourcesContent":["/**\n * Drain a `ReadableStream<Uint8Array>` into a single contiguous\n * `Uint8Array`. Releases the reader lock on both the happy and error\n * paths so the underlying stream can propagate close / error events to\n * the upstream producer.\n *\n * Used by both `createParallelDownloadStream` (per-range fetch) and\n * `StreamSource.toArrayBuffer` (whole-source materialisation). The two\n * code paths previously hand-rolled the same accumulate-then-concat\n * loop; consolidating here removes ~25 duplicated lines and a class of\n * lock-leak bugs.\n *\n * @param stream - Readable stream to consume. Will be fully drained.\n * @param options - Optional abort signal used to stop a pending read.\n *\n * @returns A new `Uint8Array` containing every byte the stream produced.\n */\nexport async function collectStream(\n stream: ReadableStream<Uint8Array>,\n options: { readonly signal?: AbortSignal } = {},\n): Promise<Uint8Array> {\n const reader = stream.getReader()\n try {\n const chunks: Uint8Array[] = []\n let total = 0\n while (true) {\n const { done, value } = await readStreamChunkWithSignal(reader, options.signal)\n if (done) break\n chunks.push(value)\n total += value.byteLength\n }\n const result = new Uint8Array(total)\n let offset = 0\n for (const chunk of chunks) {\n result.set(chunk, offset)\n offset += chunk.byteLength\n }\n return result\n } finally {\n // Releasing here lets the underlying stream propagate close / error\n // events to any upstream producer (e.g. a Node `Readable`) even on\n // the error path where a mid-read throw left the reader locked.\n reader.releaseLock()\n }\n}\n\n/**\n * Reads one chunk and rejects when the supplied signal aborts.\n * @param reader - Stream reader to read from.\n * @param signal - Optional abort signal that cancels the read.\n *\n * @returns The next stream read result.\n *\n * @internal\n */\nexport async function readStreamChunkWithSignal<T>(\n reader: ReadableStreamDefaultReader<T>,\n signal: AbortSignal | undefined,\n): Promise<ReadableStreamReadResult<T>> {\n if (signal === undefined) return reader.read()\n signal.throwIfAborted()\n\n let removeAbortListener: (() => void) | undefined\n const abortPromise = new Promise<never>((_, reject) => {\n const onAbort = (): void => {\n const reason = abortReason(signal)\n reject(reason)\n void reader.cancel(reason).catch(() => {})\n }\n signal.addEventListener('abort', onAbort, { once: true })\n removeAbortListener = () => signal.removeEventListener('abort', onAbort)\n })\n\n try {\n return await Promise.race([reader.read(), abortPromise])\n } finally {\n removeAbortListener?.()\n }\n}\n\nfunction abortReason(signal: AbortSignal): unknown {\n return signal.reason ?? new DOMException('The operation was aborted.', 'AbortError')\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAiBA,eAAsB,cACpB,QACA,UAA6C,CAAC,GACzB;CACrB,MAAM,SAAS,OAAO,UAAU;CAChC,IAAI;EACF,MAAM,SAAuB,CAAC;EAC9B,IAAI,QAAQ;EACZ,OAAO,MAAM;GACX,MAAM,EAAE,MAAM,UAAU,MAAM,0BAA0B,QAAQ,QAAQ,MAAM;GAC9E,IAAI,MAAM;GACV,OAAO,KAAK,KAAK;GACjB,SAAS,MAAM;EACjB;EACA,MAAM,SAAS,IAAI,WAAW,KAAK;EACnC,IAAI,SAAS;EACb,KAAK,MAAM,SAAS,QAAQ;GAC1B,OAAO,IAAI,OAAO,MAAM;GACxB,UAAU,MAAM;EAClB;EACA,OAAO;CACT,UAAU;EAIR,OAAO,YAAY;CACrB;AACF;;;;;;;;;;AAWA,eAAsB,0BACpB,QACA,QACsC;CACtC,IAAI,WAAW,KAAA,GAAW,OAAO,OAAO,KAAK;CAC7C,OAAO,eAAe;CAEtB,IAAI;CACJ,MAAM,eAAe,IAAI,SAAgB,GAAG,WAAW;EACrD,MAAM,gBAAsB;GAC1B,MAAM,SAAS,YAAY,MAAM;GACjC,OAAO,MAAM;GACb,OAAY,OAAO,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;EAC3C;EACA,OAAO,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;EACxD,4BAA4B,OAAO,oBAAoB,SAAS,OAAO;CACzE,CAAC;CAED,IAAI;EACF,OAAO,MAAM,QAAQ,KAAK,CAAC,OAAO,KAAK,GAAG,YAAY,CAAC;CACzD,UAAU;EACR,sBAAsB;CACxB;AACF;AAEA,SAAS,YAAY,QAA8B;CACjD,OAAO,OAAO,UAAU,IAAI,aAAa,8BAA8B,YAAY;AACrF"}
@@ -0,0 +1,287 @@
1
+ //#region src/streams/file-source.ts
2
+ var FILE_STREAM_CHUNK_SIZE = 16 * 1024 * 1024;
3
+ var FILE_SOURCE_INTERNAL = Symbol("FileSource.internal");
4
+ /** @internal */
5
+ var fileSourceTestHooks = {};
6
+ function getNodeFsSync() {
7
+ const fs = globalThis.process?.getBuiltinModule?.("node:fs");
8
+ if (!isNodeFsSync(fs)) throw new Error("FileSource constructor requires Node.js 22.3+ synchronous filesystem APIs; use FileSource.fromPath() when synchronous filesystem access is unavailable.");
9
+ return fs;
10
+ }
11
+ function isNodeFsSync(value) {
12
+ if (typeof value !== "object" || value === null) return false;
13
+ return typeof value["lstatSync"] === "function";
14
+ }
15
+ async function fileOpenFlags() {
16
+ const { constants } = await import("node:fs");
17
+ return constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0) | (constants.O_NONBLOCK ?? 0);
18
+ }
19
+ function normalizeSliceOffset(value, size) {
20
+ if (!Number.isFinite(value)) throw new RangeError("FileSource slice offsets must be finite.");
21
+ const integer = Math.trunc(value);
22
+ const offset = integer < 0 ? size + integer : integer;
23
+ return Math.min(Math.max(offset, 0), size);
24
+ }
25
+ function formatFilePath(path) {
26
+ return path instanceof URL ? path.href : path;
27
+ }
28
+ function identityFromStats(stats) {
29
+ return {
30
+ dev: stats.dev,
31
+ ino: stats.ino,
32
+ size: stats.size,
33
+ mtimeMs: stats.mtimeMs,
34
+ ctimeMs: stats.ctimeMs
35
+ };
36
+ }
37
+ function assertStableIdentity(path, stats) {
38
+ if (stats.dev === 0 && stats.ino === 0) throw new Error(`FileSource: ${formatFilePath(path)} is on a filesystem that does not expose stable file identity.`);
39
+ }
40
+ function assertRegularFile(path, stats) {
41
+ if (!stats.isFile()) throw new Error(`FileSource: ${formatFilePath(path)} is not a regular file.`);
42
+ }
43
+ function validatedIdentityFromStats(path, stats) {
44
+ assertRegularFile(path, stats);
45
+ if (shouldComparePosixFileIdentity()) assertStableIdentity(path, stats);
46
+ return identityFromStats(stats);
47
+ }
48
+ function assertSameIdentity(path, expected, actual, when) {
49
+ if (shouldComparePosixFileIdentity()) assertStableIdentity(path, actual);
50
+ if (shouldComparePosixFileIdentity() && (actual.dev !== expected.dev || actual.ino !== expected.ino)) throw new Error(`FileSource: ${formatFilePath(path)} changed ${when}.`);
51
+ if (actual.size !== expected.size || actual.mtimeMs !== expected.mtimeMs) throw new Error(`FileSource: ${formatFilePath(path)} was modified ${when}.`);
52
+ if (shouldComparePosixChangeTime() && actual.ctimeMs !== expected.ctimeMs) throw new Error(`FileSource: ${formatFilePath(path)} was modified ${when}.`);
53
+ }
54
+ function isWindows() {
55
+ if (fileSourceTestHooks.platform !== void 0) return fileSourceTestHooks.platform === "win32";
56
+ return globalThis.process?.platform === "win32";
57
+ }
58
+ function shouldComparePosixFileIdentity() {
59
+ return !isWindows();
60
+ }
61
+ function shouldComparePosixChangeTime() {
62
+ return !isWindows();
63
+ }
64
+ function throwIfAborted(signal) {
65
+ if (signal === void 0 || !signal.aborted) return;
66
+ throw signal.reason ?? new DOMException("Aborted", "AbortError");
67
+ }
68
+ function maxReadSize() {
69
+ return fileSourceTestHooks.maxReadSize ?? FILE_STREAM_CHUNK_SIZE;
70
+ }
71
+ /* v8 ignore start -- Requires a file to pass identity checks and still EOF mid-range. */
72
+ function rangeEndedEarlyError(path, offset, size) {
73
+ const end = offset + size;
74
+ return /* @__PURE__ */ new Error(`FileSource: ${formatFilePath(path)} ended before byte range [${offset}, ${end}) was fully read.`);
75
+ }
76
+ /* v8 ignore stop */
77
+ async function openValidatedFile(path, identity) {
78
+ const open = fileSourceTestHooks.openFile ?? (await import("node:fs/promises")).open;
79
+ let file;
80
+ try {
81
+ file = await open(path, await fileOpenFlags());
82
+ } catch (err) {
83
+ const message = err instanceof Error ? err.message : String(err);
84
+ throw new Error(`FileSource: ${formatFilePath(path)} could not be opened: ${message}`);
85
+ }
86
+ try {
87
+ const stats = await file.stat();
88
+ assertRegularFile(path, stats);
89
+ assertSameIdentity(path, identity, stats, "before read");
90
+ return file;
91
+ } catch (err) {
92
+ /* v8 ignore next -- Cleanup failure is deliberately best-effort. */
93
+ await file.close().catch(() => {});
94
+ throw err;
95
+ }
96
+ }
97
+ async function lstatNodeFile(path) {
98
+ const { lstat } = await import("node:fs/promises");
99
+ return lstat(path);
100
+ }
101
+ async function readFileRange(path, identity, offset, size, signal) {
102
+ throwIfAborted(signal);
103
+ if (size === 0) {
104
+ await verifyFileIdentityForEmptyRead(path, identity, signal);
105
+ return /* @__PURE__ */ new Uint8Array(0);
106
+ }
107
+ throwIfAborted(signal);
108
+ const file = await openValidatedFile(path, identity);
109
+ const data = new Uint8Array(size);
110
+ let filled = 0;
111
+ try {
112
+ while (filled < data.byteLength) {
113
+ throwIfAborted(signal);
114
+ const length = Math.min(maxReadSize(), data.byteLength - filled);
115
+ const { bytesRead } = await file.read(data, filled, length, offset + filled);
116
+ if (bytesRead === 0) throw rangeEndedEarlyError(path, offset, size);
117
+ filled += bytesRead;
118
+ await fileSourceTestHooks.afterReadIteration?.(filled);
119
+ }
120
+ throwIfAborted(signal);
121
+ assertSameIdentity(path, identity, await file.stat(), "while being read");
122
+ return data;
123
+ } finally {
124
+ /* v8 ignore next -- Cleanup failure is deliberately best-effort. */
125
+ await file.close().catch(() => {});
126
+ }
127
+ }
128
+ async function verifyFileIdentityForEmptyRead(path, identity, signal) {
129
+ throwIfAborted(signal);
130
+ const file = await openValidatedFile(path, identity);
131
+ try {
132
+ throwIfAborted(signal);
133
+ return;
134
+ } finally {
135
+ /* v8 ignore next -- Cleanup failure is deliberately best-effort. */
136
+ await file.close().catch(() => {});
137
+ }
138
+ }
139
+ function sliceFileRange(path, identity, offset, size, start, end) {
140
+ const normalizedStart = normalizeSliceOffset(start, size);
141
+ const normalizedEnd = normalizeSliceOffset(end, size);
142
+ return new FileSliceSource(path, identity, offset + normalizedStart, Math.max(normalizedEnd - normalizedStart, 0));
143
+ }
144
+ function streamFileRange(path, identity, offset, size) {
145
+ let position = offset;
146
+ let remaining = size;
147
+ let verifiedEmpty = false;
148
+ const abortController = new AbortController();
149
+ return new ReadableStream({
150
+ async pull(controller) {
151
+ try {
152
+ if (remaining === 0) {
153
+ if (!verifiedEmpty) {
154
+ verifiedEmpty = true;
155
+ await verifyFileIdentityForEmptyRead(path, identity);
156
+ }
157
+ controller.close();
158
+ return;
159
+ }
160
+ const data = await readFileRange(path, identity, position, Math.min(FILE_STREAM_CHUNK_SIZE, remaining), abortController.signal);
161
+ position += data.byteLength;
162
+ remaining -= data.byteLength;
163
+ controller.enqueue(data);
164
+ if (remaining === 0) controller.close();
165
+ } catch (err) {
166
+ controller.error(err);
167
+ }
168
+ },
169
+ cancel(reason) {
170
+ abortController.abort(reason);
171
+ }
172
+ });
173
+ }
174
+ async function fileRangeToArrayBuffer(path, identity, offset, size, options = {}) {
175
+ return (await readFileRange(path, identity, offset, size, options.signal)).buffer;
176
+ }
177
+ var FileSliceSource = class {
178
+ path;
179
+ identity;
180
+ offset;
181
+ size;
182
+ canSlice = true;
183
+ constructor(path, identity, offset, size) {
184
+ this.path = path;
185
+ this.identity = identity;
186
+ this.offset = offset;
187
+ this.size = size;
188
+ }
189
+ slice(start, end) {
190
+ return sliceFileRange(this.path, this.identity, this.offset, this.size, start, end);
191
+ }
192
+ stream() {
193
+ return streamFileRange(this.path, this.identity, this.offset, this.size);
194
+ }
195
+ toArrayBuffer(options = {}) {
196
+ return fileRangeToArrayBuffer(this.path, this.identity, this.offset, this.size, options);
197
+ }
198
+ };
199
+ /**
200
+ * ContentSource backed by a local filesystem path.
201
+ *
202
+ * `FileSource` is Node-only but safe to import in browser builds: it touches
203
+ * Node filesystem APIs only when constructed or read. The constructor performs
204
+ * synchronous filesystem validation so `size` is immediately available; request
205
+ * handlers, sync loops, and other latency-sensitive code should use
206
+ * {@link FileSource.fromPath}. Both paths capture a best-effort regular file
207
+ * identity and reject a symlink as the final path component; parent directory
208
+ * symlinks are followed by the operating system, so callers that constrain
209
+ * paths under a trusted root should validate those parents separately. Reads
210
+ * reject if the path is replaced, if the filesystem cannot report stable
211
+ * identity on POSIX platforms, or if size/mtime/ctime changes before the
212
+ * configured byte range is read. On Windows, reads avoid unreliable dev/inode
213
+ * identity comparisons and validate size/mtime instead.
214
+ * Slices preserve the captured identity, so multipart uploads can read
215
+ * disjoint ranges without materialising the whole file in memory or following
216
+ * later leaf path swaps.
217
+ */
218
+ var FileSource = class {
219
+ /** Random-access: file ranges are read by absolute byte offset. */
220
+ canSlice = true;
221
+ /** File size captured at construction time. */
222
+ size;
223
+ path;
224
+ identity;
225
+ /**
226
+ * Internal constructor path for async validation.
227
+ * @param path - Local filesystem path or file URL.
228
+ * @param internal - Module-private validated identity payload.
229
+ *
230
+ * @internal
231
+ */
232
+ constructor(path, internal) {
233
+ const resolvedIdentity = internal?.key === FILE_SOURCE_INTERNAL ? internal.identity : validatedIdentityFromStats(path, getNodeFsSync().lstatSync(path));
234
+ this.path = path;
235
+ this.identity = resolvedIdentity;
236
+ this.size = resolvedIdentity.size;
237
+ }
238
+ /**
239
+ * Return a new file-backed source covering the specified byte range.
240
+ * @param start - The zero-based byte offset to begin the slice.
241
+ * @param end - The exclusive byte offset where the slice ends.
242
+ *
243
+ * @returns A new ContentSource representing the requested sub-range.
244
+ */
245
+ slice(start, end) {
246
+ return sliceFileRange(this.path, this.identity, 0, this.size, start, end);
247
+ }
248
+ /**
249
+ * Open this file as a Web ReadableStream.
250
+ * @returns A ReadableStream that reads the file lazily.
251
+ */
252
+ stream() {
253
+ return streamFileRange(this.path, this.identity, 0, this.size);
254
+ }
255
+ /**
256
+ * Read this file into an ArrayBuffer.
257
+ * @param options - Optional abort signal used while reading.
258
+ *
259
+ * @returns A promise resolving with the file bytes.
260
+ */
261
+ toArrayBuffer(options = {}) {
262
+ return fileRangeToArrayBuffer(this.path, this.identity, 0, this.size, options);
263
+ }
264
+ /**
265
+ * Create a FileSource using asynchronous filesystem validation.
266
+ * @param path - Local filesystem path or file URL.
267
+ *
268
+ * @returns A FileSource bound to the validated file identity.
269
+ *
270
+ * @throws If the path does not reference a regular non-symlink file.
271
+ * @throws If a POSIX filesystem cannot report stable file identity.
272
+ */
273
+ static async fromPath(path) {
274
+ return constructFileSourceFromIdentity(path, validatedIdentityFromStats(path, await lstatNodeFile(path)));
275
+ }
276
+ };
277
+ function constructFileSourceFromIdentity(path, identity) {
278
+ return Reflect.construct(FileSource, [path, {
279
+ key: FILE_SOURCE_INTERNAL,
280
+ identity
281
+ }]);
282
+ }
283
+ //#endregion
284
+ exports.FileSource = FileSource;
285
+ exports.fileSourceTestHooks = fileSourceTestHooks;
286
+
287
+ //# sourceMappingURL=file-source.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-source.cjs","names":[],"sources":["../../src/streams/file-source.ts"],"sourcesContent":["import type { ContentSource } from './source.ts'\n\nconst FILE_STREAM_CHUNK_SIZE = 16 * 1024 * 1024\n\n/** Filesystem path accepted by {@link FileSource}. */\nexport type FileSourcePath = string | URL\n\ninterface FileStatsLike {\n readonly dev: number\n readonly ino: number\n readonly mode: number\n readonly size: number\n readonly mtimeMs: number\n readonly ctimeMs: number\n isFile(): boolean\n}\n\ninterface FileHandleLike {\n read(\n buffer: Uint8Array,\n offset: number,\n length: number,\n position: number,\n ): Promise<{ bytesRead: number }>\n stat(): Promise<FileStatsLike>\n close(): Promise<void>\n}\n\ninterface NodeFsSync {\n lstatSync(path: FileSourcePath): FileStatsLike\n}\n\ninterface FileIdentity {\n readonly dev: number\n readonly ino: number\n readonly size: number\n readonly mtimeMs: number\n readonly ctimeMs: number\n}\n\ninterface ToArrayBufferOptions {\n readonly signal?: AbortSignal\n}\n\nconst FILE_SOURCE_INTERNAL = Symbol('FileSource.internal')\n\ninterface FileSourceInternalOptions {\n readonly key: typeof FILE_SOURCE_INTERNAL\n readonly identity: FileIdentity\n}\n\n/** @internal */\nexport const fileSourceTestHooks: {\n afterReadIteration?: (filled: number) => Promise<void> | void\n maxReadSize?: number\n openFile?: (path: FileSourcePath, flags: number) => Promise<FileHandleLike>\n platform?: string\n} = {}\n\nfunction getNodeFsSync(): NodeFsSync {\n // FileSource exposes `size` synchronously, so the constructor cannot use the\n // repo's usual `await import('node:...')` pattern for Node-only APIs. Keep the\n // synchronous lookup here; async callers should prefer `FileSource.fromPath()`.\n const processLike = (\n globalThis as {\n process?: { getBuiltinModule?: (id: string) => unknown }\n }\n ).process\n const fs = processLike?.getBuiltinModule?.('node:fs')\n if (!isNodeFsSync(fs)) {\n throw new Error(\n 'FileSource constructor requires Node.js 22.3+ synchronous filesystem APIs; use FileSource.fromPath() when synchronous filesystem access is unavailable.',\n )\n }\n return fs\n}\n\nfunction isNodeFsSync(value: unknown): value is NodeFsSync {\n if (typeof value !== 'object' || value === null) return false\n const candidate = value as Record<string, unknown>\n return typeof candidate['lstatSync'] === 'function'\n}\n\nasync function fileOpenFlags(): Promise<number> {\n const { constants } = await import('node:fs')\n // O_NOFOLLOW and O_NONBLOCK are unavailable on some platforms. When\n // O_NOFOLLOW is absent, the post-open fstat identity check below is the\n // symlink-swap defense. O_NONBLOCK avoids blocking indefinitely if a path is\n // swapped to a FIFO or another blocking special file before fstat rejects it.\n return (\n constants.O_RDONLY |\n (constants.O_NOFOLLOW ?? 0) |\n ((constants as { O_NONBLOCK?: number }).O_NONBLOCK ?? 0)\n )\n}\n\nfunction normalizeSliceOffset(value: number, size: number): number {\n if (!Number.isFinite(value)) throw new RangeError('FileSource slice offsets must be finite.')\n const integer = Math.trunc(value)\n const offset = integer < 0 ? size + integer : integer\n return Math.min(Math.max(offset, 0), size)\n}\n\nfunction formatFilePath(path: FileSourcePath): string {\n return path instanceof URL ? path.href : path\n}\n\nfunction identityFromStats(stats: FileStatsLike): FileIdentity {\n return {\n dev: stats.dev,\n ino: stats.ino,\n size: stats.size,\n mtimeMs: stats.mtimeMs,\n ctimeMs: stats.ctimeMs,\n }\n}\n\nfunction assertStableIdentity(path: FileSourcePath, stats: FileStatsLike): void {\n if (stats.dev === 0 && stats.ino === 0) {\n throw new Error(\n `FileSource: ${formatFilePath(path)} is on a filesystem that does not expose stable file identity.`,\n )\n }\n}\n\nfunction assertRegularFile(path: FileSourcePath, stats: FileStatsLike): void {\n if (!stats.isFile()) {\n throw new Error(`FileSource: ${formatFilePath(path)} is not a regular file.`)\n }\n}\n\nfunction validatedIdentityFromStats(path: FileSourcePath, stats: FileStatsLike): FileIdentity {\n assertRegularFile(path, stats)\n if (shouldComparePosixFileIdentity()) assertStableIdentity(path, stats)\n return identityFromStats(stats)\n}\n\nfunction assertSameIdentity(\n path: FileSourcePath,\n expected: FileIdentity,\n actual: FileStatsLike,\n when: string,\n): void {\n if (shouldComparePosixFileIdentity()) assertStableIdentity(path, actual)\n if (\n shouldComparePosixFileIdentity() &&\n (actual.dev !== expected.dev || actual.ino !== expected.ino)\n ) {\n throw new Error(`FileSource: ${formatFilePath(path)} changed ${when}.`)\n }\n if (actual.size !== expected.size || actual.mtimeMs !== expected.mtimeMs) {\n throw new Error(`FileSource: ${formatFilePath(path)} was modified ${when}.`)\n }\n if (shouldComparePosixChangeTime() && actual.ctimeMs !== expected.ctimeMs) {\n throw new Error(`FileSource: ${formatFilePath(path)} was modified ${when}.`)\n }\n}\n\nfunction isWindows(): boolean {\n if (fileSourceTestHooks.platform !== undefined) return fileSourceTestHooks.platform === 'win32'\n const processLike = (globalThis as { process?: { platform?: string } }).process\n return processLike?.platform === 'win32'\n}\n\nfunction shouldComparePosixFileIdentity(): boolean {\n return !isWindows()\n}\n\nfunction shouldComparePosixChangeTime(): boolean {\n return !isWindows()\n}\n\nfunction throwIfAborted(signal: AbortSignal | undefined): void {\n if (signal === undefined || !signal.aborted) return\n throw signal.reason ?? new DOMException('Aborted', 'AbortError')\n}\n\nfunction maxReadSize(): number {\n return fileSourceTestHooks.maxReadSize ?? FILE_STREAM_CHUNK_SIZE\n}\n\n/* v8 ignore start -- Requires a file to pass identity checks and still EOF mid-range. */\nfunction rangeEndedEarlyError(path: FileSourcePath, offset: number, size: number): Error {\n const end = offset + size\n return new Error(\n `FileSource: ${formatFilePath(path)} ended before byte range [${offset}, ${end}) was fully read.`,\n )\n}\n/* v8 ignore stop */\n\nasync function openValidatedFile(\n path: FileSourcePath,\n identity: FileIdentity,\n): Promise<FileHandleLike> {\n const open =\n fileSourceTestHooks.openFile ??\n (\n (await import('node:fs/promises')) as {\n open(path: FileSourcePath, flags: number): Promise<FileHandleLike>\n }\n ).open\n let file: FileHandleLike\n try {\n file = await open(path, await fileOpenFlags())\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n throw new Error(`FileSource: ${formatFilePath(path)} could not be opened: ${message}`)\n }\n\n try {\n const stats = await file.stat()\n assertRegularFile(path, stats)\n assertSameIdentity(path, identity, stats, 'before read')\n return file\n } catch (err) {\n /* v8 ignore next -- Cleanup failure is deliberately best-effort. */\n await file.close().catch(() => {})\n throw err\n }\n}\n\nasync function lstatNodeFile(path: FileSourcePath): Promise<FileStatsLike> {\n const { lstat } = (await import('node:fs/promises')) as {\n lstat(path: FileSourcePath): Promise<FileStatsLike>\n }\n return lstat(path)\n}\n\nasync function readFileRange(\n path: FileSourcePath,\n identity: FileIdentity,\n offset: number,\n size: number,\n signal?: AbortSignal,\n): Promise<Uint8Array> {\n throwIfAborted(signal)\n if (size === 0) {\n await verifyFileIdentityForEmptyRead(path, identity, signal)\n return new Uint8Array(0)\n }\n\n throwIfAborted(signal)\n const file = await openValidatedFile(path, identity)\n const data = new Uint8Array(size)\n let filled = 0\n try {\n while (filled < data.byteLength) {\n throwIfAborted(signal)\n const length = Math.min(maxReadSize(), data.byteLength - filled)\n const { bytesRead } = await file.read(data, filled, length, offset + filled)\n if (bytesRead === 0) throw rangeEndedEarlyError(path, offset, size)\n filled += bytesRead\n await fileSourceTestHooks.afterReadIteration?.(filled)\n }\n throwIfAborted(signal)\n const stats = await file.stat()\n assertSameIdentity(path, identity, stats, 'while being read')\n return data\n } finally {\n /* v8 ignore next -- Cleanup failure is deliberately best-effort. */\n await file.close().catch(() => {})\n }\n}\n\nasync function verifyFileIdentityForEmptyRead(\n path: FileSourcePath,\n identity: FileIdentity,\n signal?: AbortSignal,\n): Promise<void> {\n throwIfAborted(signal)\n const file = await openValidatedFile(path, identity)\n try {\n throwIfAborted(signal)\n return\n } finally {\n /* v8 ignore next -- Cleanup failure is deliberately best-effort. */\n await file.close().catch(() => {})\n }\n}\n\nfunction sliceFileRange(\n path: FileSourcePath,\n identity: FileIdentity,\n offset: number,\n size: number,\n start: number,\n end: number,\n): ContentSource {\n const normalizedStart = normalizeSliceOffset(start, size)\n const normalizedEnd = normalizeSliceOffset(end, size)\n return new FileSliceSource(\n path,\n identity,\n offset + normalizedStart,\n Math.max(normalizedEnd - normalizedStart, 0),\n )\n}\n\nfunction streamFileRange(\n path: FileSourcePath,\n identity: FileIdentity,\n offset: number,\n size: number,\n): ReadableStream<Uint8Array> {\n let position = offset\n let remaining = size\n let verifiedEmpty = false\n const abortController = new AbortController()\n\n // Open per pull so abandoned public streams do not strand file handles or\n // retain Windows locks. Each chunk still verifies identity around its read.\n return new ReadableStream<Uint8Array>({\n async pull(controller) {\n try {\n if (remaining === 0) {\n if (!verifiedEmpty) {\n verifiedEmpty = true\n await verifyFileIdentityForEmptyRead(path, identity)\n }\n controller.close()\n return\n }\n\n const length = Math.min(FILE_STREAM_CHUNK_SIZE, remaining)\n const data = await readFileRange(path, identity, position, length, abortController.signal)\n position += data.byteLength\n remaining -= data.byteLength\n controller.enqueue(data)\n if (remaining === 0) controller.close()\n } catch (err) {\n controller.error(err)\n }\n },\n cancel(reason) {\n abortController.abort(reason)\n },\n })\n}\n\nasync function fileRangeToArrayBuffer(\n path: FileSourcePath,\n identity: FileIdentity,\n offset: number,\n size: number,\n options: ToArrayBufferOptions = {},\n): Promise<ArrayBuffer> {\n const data = await readFileRange(path, identity, offset, size, options.signal)\n return data.buffer as ArrayBuffer\n}\n\nclass FileSliceSource implements ContentSource {\n readonly canSlice = true\n\n constructor(\n private readonly path: FileSourcePath,\n private readonly identity: FileIdentity,\n private readonly offset: number,\n readonly size: number,\n ) {}\n\n slice(start: number, end: number): ContentSource {\n return sliceFileRange(this.path, this.identity, this.offset, this.size, start, end)\n }\n\n stream(): ReadableStream<Uint8Array> {\n return streamFileRange(this.path, this.identity, this.offset, this.size)\n }\n\n toArrayBuffer(options: ToArrayBufferOptions = {}): Promise<ArrayBuffer> {\n return fileRangeToArrayBuffer(this.path, this.identity, this.offset, this.size, options)\n }\n}\n\n/**\n * ContentSource backed by a local filesystem path.\n *\n * `FileSource` is Node-only but safe to import in browser builds: it touches\n * Node filesystem APIs only when constructed or read. The constructor performs\n * synchronous filesystem validation so `size` is immediately available; request\n * handlers, sync loops, and other latency-sensitive code should use\n * {@link FileSource.fromPath}. Both paths capture a best-effort regular file\n * identity and reject a symlink as the final path component; parent directory\n * symlinks are followed by the operating system, so callers that constrain\n * paths under a trusted root should validate those parents separately. Reads\n * reject if the path is replaced, if the filesystem cannot report stable\n * identity on POSIX platforms, or if size/mtime/ctime changes before the\n * configured byte range is read. On Windows, reads avoid unreliable dev/inode\n * identity comparisons and validate size/mtime instead.\n * Slices preserve the captured identity, so multipart uploads can read\n * disjoint ranges without materialising the whole file in memory or following\n * later leaf path swaps.\n */\nexport class FileSource implements ContentSource {\n /** Random-access: file ranges are read by absolute byte offset. */\n readonly canSlice = true\n /** File size captured at construction time. */\n readonly size: number\n private readonly path: FileSourcePath\n private readonly identity: FileIdentity\n\n /**\n * Create a FileSource for a local file path.\n * @param path - Local filesystem path or file URL.\n *\n * @throws If the runtime has no Node-compatible filesystem API.\n * @throws If the path does not reference a regular non-symlink file.\n * @throws If a POSIX filesystem cannot report stable file identity.\n */\n constructor(path: FileSourcePath)\n /**\n * Internal constructor path for async validation.\n * @param path - Local filesystem path or file URL.\n * @param internal - Module-private validated identity payload.\n *\n * @internal\n */\n constructor(path: FileSourcePath, internal?: FileSourceInternalOptions) {\n const resolvedIdentity =\n internal?.key === FILE_SOURCE_INTERNAL\n ? internal.identity\n : validatedIdentityFromStats(path, getNodeFsSync().lstatSync(path))\n this.path = path\n this.identity = resolvedIdentity\n this.size = resolvedIdentity.size\n }\n\n /**\n * Return a new file-backed source covering the specified byte range.\n * @param start - The zero-based byte offset to begin the slice.\n * @param end - The exclusive byte offset where the slice ends.\n *\n * @returns A new ContentSource representing the requested sub-range.\n */\n slice(start: number, end: number): ContentSource {\n return sliceFileRange(this.path, this.identity, 0, this.size, start, end)\n }\n\n /**\n * Open this file as a Web ReadableStream.\n * @returns A ReadableStream that reads the file lazily.\n */\n stream(): ReadableStream<Uint8Array> {\n return streamFileRange(this.path, this.identity, 0, this.size)\n }\n\n /**\n * Read this file into an ArrayBuffer.\n * @param options - Optional abort signal used while reading.\n *\n * @returns A promise resolving with the file bytes.\n */\n toArrayBuffer(options: { readonly signal?: AbortSignal } = {}): Promise<ArrayBuffer> {\n return fileRangeToArrayBuffer(this.path, this.identity, 0, this.size, options)\n }\n\n /**\n * Create a FileSource using asynchronous filesystem validation.\n * @param path - Local filesystem path or file URL.\n *\n * @returns A FileSource bound to the validated file identity.\n *\n * @throws If the path does not reference a regular non-symlink file.\n * @throws If a POSIX filesystem cannot report stable file identity.\n */\n static async fromPath(path: FileSourcePath): Promise<FileSource> {\n const identity = validatedIdentityFromStats(path, await lstatNodeFile(path))\n return constructFileSourceFromIdentity(path, identity)\n }\n}\n\nfunction constructFileSourceFromIdentity(path: FileSourcePath, identity: FileIdentity): FileSource {\n // The public overload is intentionally single-argument; Reflect.construct\n // lets fromPath pass the module-private validated identity without exposing\n // that constructor shape in the public type surface.\n return Reflect.construct(FileSource, [\n path,\n { key: FILE_SOURCE_INTERNAL, identity },\n ]) as FileSource\n}\n"],"mappings":"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"}
@@ -0,0 +1,96 @@
1
+ import { ContentSource } from './source.js';
2
+ /** Filesystem path accepted by {@link FileSource}. */
3
+ export type FileSourcePath = string | URL;
4
+ interface FileStatsLike {
5
+ readonly dev: number;
6
+ readonly ino: number;
7
+ readonly mode: number;
8
+ readonly size: number;
9
+ readonly mtimeMs: number;
10
+ readonly ctimeMs: number;
11
+ isFile(): boolean;
12
+ }
13
+ interface FileHandleLike {
14
+ read(buffer: Uint8Array, offset: number, length: number, position: number): Promise<{
15
+ bytesRead: number;
16
+ }>;
17
+ stat(): Promise<FileStatsLike>;
18
+ close(): Promise<void>;
19
+ }
20
+ /** @internal */
21
+ export declare const fileSourceTestHooks: {
22
+ afterReadIteration?: (filled: number) => Promise<void> | void;
23
+ maxReadSize?: number;
24
+ openFile?: (path: FileSourcePath, flags: number) => Promise<FileHandleLike>;
25
+ platform?: string;
26
+ };
27
+ /**
28
+ * ContentSource backed by a local filesystem path.
29
+ *
30
+ * `FileSource` is Node-only but safe to import in browser builds: it touches
31
+ * Node filesystem APIs only when constructed or read. The constructor performs
32
+ * synchronous filesystem validation so `size` is immediately available; request
33
+ * handlers, sync loops, and other latency-sensitive code should use
34
+ * {@link FileSource.fromPath}. Both paths capture a best-effort regular file
35
+ * identity and reject a symlink as the final path component; parent directory
36
+ * symlinks are followed by the operating system, so callers that constrain
37
+ * paths under a trusted root should validate those parents separately. Reads
38
+ * reject if the path is replaced, if the filesystem cannot report stable
39
+ * identity on POSIX platforms, or if size/mtime/ctime changes before the
40
+ * configured byte range is read. On Windows, reads avoid unreliable dev/inode
41
+ * identity comparisons and validate size/mtime instead.
42
+ * Slices preserve the captured identity, so multipart uploads can read
43
+ * disjoint ranges without materialising the whole file in memory or following
44
+ * later leaf path swaps.
45
+ */
46
+ export declare class FileSource implements ContentSource {
47
+ /** Random-access: file ranges are read by absolute byte offset. */
48
+ readonly canSlice = true;
49
+ /** File size captured at construction time. */
50
+ readonly size: number;
51
+ private readonly path;
52
+ private readonly identity;
53
+ /**
54
+ * Create a FileSource for a local file path.
55
+ * @param path - Local filesystem path or file URL.
56
+ *
57
+ * @throws If the runtime has no Node-compatible filesystem API.
58
+ * @throws If the path does not reference a regular non-symlink file.
59
+ * @throws If a POSIX filesystem cannot report stable file identity.
60
+ */
61
+ constructor(path: FileSourcePath);
62
+ /**
63
+ * Return a new file-backed source covering the specified byte range.
64
+ * @param start - The zero-based byte offset to begin the slice.
65
+ * @param end - The exclusive byte offset where the slice ends.
66
+ *
67
+ * @returns A new ContentSource representing the requested sub-range.
68
+ */
69
+ slice(start: number, end: number): ContentSource;
70
+ /**
71
+ * Open this file as a Web ReadableStream.
72
+ * @returns A ReadableStream that reads the file lazily.
73
+ */
74
+ stream(): ReadableStream<Uint8Array>;
75
+ /**
76
+ * Read this file into an ArrayBuffer.
77
+ * @param options - Optional abort signal used while reading.
78
+ *
79
+ * @returns A promise resolving with the file bytes.
80
+ */
81
+ toArrayBuffer(options?: {
82
+ readonly signal?: AbortSignal;
83
+ }): Promise<ArrayBuffer>;
84
+ /**
85
+ * Create a FileSource using asynchronous filesystem validation.
86
+ * @param path - Local filesystem path or file URL.
87
+ *
88
+ * @returns A FileSource bound to the validated file identity.
89
+ *
90
+ * @throws If the path does not reference a regular non-symlink file.
91
+ * @throws If a POSIX filesystem cannot report stable file identity.
92
+ */
93
+ static fromPath(path: FileSourcePath): Promise<FileSource>;
94
+ }
95
+ export {};
96
+ //# sourceMappingURL=file-source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-source.d.ts","sourceRoot":"","sources":["../../src/streams/file-source.js"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAIhD,sDAAsD;AACtD,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,GAAG,CAAA;AAEzC,UAAU,aAAa;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,MAAM,IAAI,OAAO,CAAA;CAClB;AAED,UAAU,cAAc;IACtB,IAAI,CACF,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACjC,IAAI,IAAI,OAAO,CAAC,aAAa,CAAC,CAAA;IAC9B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACvB;AAyBD,gBAAgB;AAChB,eAAO,MAAM,mBAAmB,EAAE;IAChC,kBAAkB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IAC7D,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,CAAA;IAC3E,QAAQ,CAAC,EAAE,MAAM,CAAA;CACb,CAAA;AA4TN;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,UAAW,YAAW,aAAa;IAC9C,mEAAmE;IACnE,QAAQ,CAAC,QAAQ,QAAO;IACxB,+CAA+C;IAC/C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAgB;IACrC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAc;IAEvC;;;;;;;OAOG;gBACS,IAAI,EAAE,cAAc;IAkBhC;;;;;;OAMG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,aAAa;IAIhD;;;OAGG;IACH,MAAM,IAAI,cAAc,CAAC,UAAU,CAAC;IAIpC;;;;;OAKG;IACH,aAAa,CAAC,OAAO,GAAE;QAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAO,GAAG,OAAO,CAAC,WAAW,CAAC;IAIpF;;;;;;;;OAQG;WACU,QAAQ,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC;CAIjE"}
@@ -0,0 +1,96 @@
1
+ import { ContentSource } from './source.js';
2
+ /** Filesystem path accepted by {@link FileSource}. */
3
+ export type FileSourcePath = string | URL;
4
+ interface FileStatsLike {
5
+ readonly dev: number;
6
+ readonly ino: number;
7
+ readonly mode: number;
8
+ readonly size: number;
9
+ readonly mtimeMs: number;
10
+ readonly ctimeMs: number;
11
+ isFile(): boolean;
12
+ }
13
+ interface FileHandleLike {
14
+ read(buffer: Uint8Array, offset: number, length: number, position: number): Promise<{
15
+ bytesRead: number;
16
+ }>;
17
+ stat(): Promise<FileStatsLike>;
18
+ close(): Promise<void>;
19
+ }
20
+ /** @internal */
21
+ export declare const fileSourceTestHooks: {
22
+ afterReadIteration?: (filled: number) => Promise<void> | void;
23
+ maxReadSize?: number;
24
+ openFile?: (path: FileSourcePath, flags: number) => Promise<FileHandleLike>;
25
+ platform?: string;
26
+ };
27
+ /**
28
+ * ContentSource backed by a local filesystem path.
29
+ *
30
+ * `FileSource` is Node-only but safe to import in browser builds: it touches
31
+ * Node filesystem APIs only when constructed or read. The constructor performs
32
+ * synchronous filesystem validation so `size` is immediately available; request
33
+ * handlers, sync loops, and other latency-sensitive code should use
34
+ * {@link FileSource.fromPath}. Both paths capture a best-effort regular file
35
+ * identity and reject a symlink as the final path component; parent directory
36
+ * symlinks are followed by the operating system, so callers that constrain
37
+ * paths under a trusted root should validate those parents separately. Reads
38
+ * reject if the path is replaced, if the filesystem cannot report stable
39
+ * identity on POSIX platforms, or if size/mtime/ctime changes before the
40
+ * configured byte range is read. On Windows, reads avoid unreliable dev/inode
41
+ * identity comparisons and validate size/mtime instead.
42
+ * Slices preserve the captured identity, so multipart uploads can read
43
+ * disjoint ranges without materialising the whole file in memory or following
44
+ * later leaf path swaps.
45
+ */
46
+ export declare class FileSource implements ContentSource {
47
+ /** Random-access: file ranges are read by absolute byte offset. */
48
+ readonly canSlice = true;
49
+ /** File size captured at construction time. */
50
+ readonly size: number;
51
+ private readonly path;
52
+ private readonly identity;
53
+ /**
54
+ * Create a FileSource for a local file path.
55
+ * @param path - Local filesystem path or file URL.
56
+ *
57
+ * @throws If the runtime has no Node-compatible filesystem API.
58
+ * @throws If the path does not reference a regular non-symlink file.
59
+ * @throws If a POSIX filesystem cannot report stable file identity.
60
+ */
61
+ constructor(path: FileSourcePath);
62
+ /**
63
+ * Return a new file-backed source covering the specified byte range.
64
+ * @param start - The zero-based byte offset to begin the slice.
65
+ * @param end - The exclusive byte offset where the slice ends.
66
+ *
67
+ * @returns A new ContentSource representing the requested sub-range.
68
+ */
69
+ slice(start: number, end: number): ContentSource;
70
+ /**
71
+ * Open this file as a Web ReadableStream.
72
+ * @returns A ReadableStream that reads the file lazily.
73
+ */
74
+ stream(): ReadableStream<Uint8Array>;
75
+ /**
76
+ * Read this file into an ArrayBuffer.
77
+ * @param options - Optional abort signal used while reading.
78
+ *
79
+ * @returns A promise resolving with the file bytes.
80
+ */
81
+ toArrayBuffer(options?: {
82
+ readonly signal?: AbortSignal;
83
+ }): Promise<ArrayBuffer>;
84
+ /**
85
+ * Create a FileSource using asynchronous filesystem validation.
86
+ * @param path - Local filesystem path or file URL.
87
+ *
88
+ * @returns A FileSource bound to the validated file identity.
89
+ *
90
+ * @throws If the path does not reference a regular non-symlink file.
91
+ * @throws If a POSIX filesystem cannot report stable file identity.
92
+ */
93
+ static fromPath(path: FileSourcePath): Promise<FileSource>;
94
+ }
95
+ export {};
96
+ //# sourceMappingURL=file-source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-source.d.ts","sourceRoot":"","sources":["../../src/streams/file-source.js"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAIhD,sDAAsD;AACtD,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,GAAG,CAAA;AAEzC,UAAU,aAAa;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,MAAM,IAAI,OAAO,CAAA;CAClB;AAED,UAAU,cAAc;IACtB,IAAI,CACF,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACjC,IAAI,IAAI,OAAO,CAAC,aAAa,CAAC,CAAA;IAC9B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACvB;AAyBD,gBAAgB;AAChB,eAAO,MAAM,mBAAmB,EAAE;IAChC,kBAAkB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IAC7D,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,CAAA;IAC3E,QAAQ,CAAC,EAAE,MAAM,CAAA;CACb,CAAA;AA4TN;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,UAAW,YAAW,aAAa;IAC9C,mEAAmE;IACnE,QAAQ,CAAC,QAAQ,QAAO;IACxB,+CAA+C;IAC/C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAgB;IACrC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAc;IAEvC;;;;;;;OAOG;gBACS,IAAI,EAAE,cAAc;IAkBhC;;;;;;OAMG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,aAAa;IAIhD;;;OAGG;IACH,MAAM,IAAI,cAAc,CAAC,UAAU,CAAC;IAIpC;;;;;OAKG;IACH,aAAa,CAAC,OAAO,GAAE;QAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAO,GAAG,OAAO,CAAC,WAAW,CAAC;IAIpF;;;;;;;;OAQG;WACU,QAAQ,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC;CAIjE"}