@milaboratories/pl-drivers 1.11.59 → 1.11.60

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 (330) hide show
  1. package/dist/_virtual/_rolldown/runtime.cjs +29 -0
  2. package/dist/clients/constructors.cjs +28 -28
  3. package/dist/clients/constructors.cjs.map +1 -1
  4. package/dist/clients/constructors.d.ts +17 -13
  5. package/dist/clients/constructors.js +28 -26
  6. package/dist/clients/constructors.js.map +1 -1
  7. package/dist/clients/crc32c.cjs +8 -13
  8. package/dist/clients/crc32c.cjs.map +1 -1
  9. package/dist/clients/crc32c.js +8 -12
  10. package/dist/clients/crc32c.js.map +1 -1
  11. package/dist/clients/download.cjs +119 -160
  12. package/dist/clients/download.cjs.map +1 -1
  13. package/dist/clients/download.d.ts +45 -41
  14. package/dist/clients/download.js +115 -137
  15. package/dist/clients/download.js.map +1 -1
  16. package/dist/clients/logs.cjs +78 -82
  17. package/dist/clients/logs.cjs.map +1 -1
  18. package/dist/clients/logs.d.ts +34 -24
  19. package/dist/clients/logs.js +77 -80
  20. package/dist/clients/logs.js.map +1 -1
  21. package/dist/clients/ls_api.cjs +62 -68
  22. package/dist/clients/ls_api.cjs.map +1 -1
  23. package/dist/clients/ls_api.d.ts +15 -11
  24. package/dist/clients/ls_api.js +61 -66
  25. package/dist/clients/ls_api.js.map +1 -1
  26. package/dist/clients/progress.cjs +49 -59
  27. package/dist/clients/progress.cjs.map +1 -1
  28. package/dist/clients/progress.d.ts +27 -20
  29. package/dist/clients/progress.js +48 -57
  30. package/dist/clients/progress.js.map +1 -1
  31. package/dist/clients/upload.cjs +189 -250
  32. package/dist/clients/upload.cjs.map +1 -1
  33. package/dist/clients/upload.d.ts +44 -34
  34. package/dist/clients/upload.js +187 -229
  35. package/dist/clients/upload.js.map +1 -1
  36. package/dist/drivers/download_blob/blob_key.cjs +9 -26
  37. package/dist/drivers/download_blob/blob_key.cjs.map +1 -1
  38. package/dist/drivers/download_blob/blob_key.js +7 -5
  39. package/dist/drivers/download_blob/blob_key.js.map +1 -1
  40. package/dist/drivers/download_blob/download_blob.cjs +395 -478
  41. package/dist/drivers/download_blob/download_blob.cjs.map +1 -1
  42. package/dist/drivers/download_blob/download_blob.d.ts +102 -100
  43. package/dist/drivers/download_blob/download_blob.js +388 -453
  44. package/dist/drivers/download_blob/download_blob.js.map +1 -1
  45. package/dist/drivers/download_blob/download_blob_task.cjs +128 -163
  46. package/dist/drivers/download_blob/download_blob_task.cjs.map +1 -1
  47. package/dist/drivers/download_blob/download_blob_task.js +125 -141
  48. package/dist/drivers/download_blob/download_blob_task.js.map +1 -1
  49. package/dist/drivers/download_blob/sparse_cache/cache.cjs +166 -195
  50. package/dist/drivers/download_blob/sparse_cache/cache.cjs.map +1 -1
  51. package/dist/drivers/download_blob/sparse_cache/cache.js +164 -193
  52. package/dist/drivers/download_blob/sparse_cache/cache.js.map +1 -1
  53. package/dist/drivers/download_blob/sparse_cache/file.cjs +29 -50
  54. package/dist/drivers/download_blob/sparse_cache/file.cjs.map +1 -1
  55. package/dist/drivers/download_blob/sparse_cache/file.js +28 -29
  56. package/dist/drivers/download_blob/sparse_cache/file.js.map +1 -1
  57. package/dist/drivers/download_blob/sparse_cache/ranges.cjs +48 -76
  58. package/dist/drivers/download_blob/sparse_cache/ranges.cjs.map +1 -1
  59. package/dist/drivers/download_blob/sparse_cache/ranges.js +47 -54
  60. package/dist/drivers/download_blob/sparse_cache/ranges.js.map +1 -1
  61. package/dist/drivers/download_blob_url/driver.cjs +125 -165
  62. package/dist/drivers/download_blob_url/driver.cjs.map +1 -1
  63. package/dist/drivers/download_blob_url/driver.d.ts +45 -42
  64. package/dist/drivers/download_blob_url/driver.js +123 -144
  65. package/dist/drivers/download_blob_url/driver.js.map +1 -1
  66. package/dist/drivers/download_blob_url/driver_id.cjs +4 -4
  67. package/dist/drivers/download_blob_url/driver_id.cjs.map +1 -1
  68. package/dist/drivers/download_blob_url/driver_id.js +4 -3
  69. package/dist/drivers/download_blob_url/driver_id.js.map +1 -1
  70. package/dist/drivers/download_blob_url/snapshot.cjs +7 -11
  71. package/dist/drivers/download_blob_url/snapshot.cjs.map +1 -1
  72. package/dist/drivers/download_blob_url/snapshot.d.ts +10 -5
  73. package/dist/drivers/download_blob_url/snapshot.js +5 -8
  74. package/dist/drivers/download_blob_url/snapshot.js.map +1 -1
  75. package/dist/drivers/download_blob_url/task.cjs +147 -194
  76. package/dist/drivers/download_blob_url/task.cjs.map +1 -1
  77. package/dist/drivers/download_blob_url/task.d.ts +55 -57
  78. package/dist/drivers/download_blob_url/task.js +140 -170
  79. package/dist/drivers/download_blob_url/task.js.map +1 -1
  80. package/dist/drivers/download_url/driver.cjs +109 -146
  81. package/dist/drivers/download_url/driver.cjs.map +1 -1
  82. package/dist/drivers/download_url/driver.d.ts +59 -57
  83. package/dist/drivers/download_url/driver.js +107 -125
  84. package/dist/drivers/download_url/driver.js.map +1 -1
  85. package/dist/drivers/download_url/task.cjs +104 -137
  86. package/dist/drivers/download_url/task.cjs.map +1 -1
  87. package/dist/drivers/download_url/task.d.ts +33 -37
  88. package/dist/drivers/download_url/task.js +99 -113
  89. package/dist/drivers/download_url/task.js.map +1 -1
  90. package/dist/drivers/helpers/download_local_handle.cjs +13 -14
  91. package/dist/drivers/helpers/download_local_handle.cjs.map +1 -1
  92. package/dist/drivers/helpers/download_local_handle.js +13 -13
  93. package/dist/drivers/helpers/download_local_handle.js.map +1 -1
  94. package/dist/drivers/helpers/download_remote_handle.cjs +23 -24
  95. package/dist/drivers/helpers/download_remote_handle.cjs.map +1 -1
  96. package/dist/drivers/helpers/download_remote_handle.js +22 -22
  97. package/dist/drivers/helpers/download_remote_handle.js.map +1 -1
  98. package/dist/drivers/helpers/files_cache.cjs +53 -64
  99. package/dist/drivers/helpers/files_cache.cjs.map +1 -1
  100. package/dist/drivers/helpers/files_cache.js +52 -62
  101. package/dist/drivers/helpers/files_cache.js.map +1 -1
  102. package/dist/drivers/helpers/helpers.cjs +24 -28
  103. package/dist/drivers/helpers/helpers.cjs.map +1 -1
  104. package/dist/drivers/helpers/helpers.d.ts +10 -7
  105. package/dist/drivers/helpers/helpers.js +24 -27
  106. package/dist/drivers/helpers/helpers.js.map +1 -1
  107. package/dist/drivers/helpers/logs_handle.cjs +24 -33
  108. package/dist/drivers/helpers/logs_handle.cjs.map +1 -1
  109. package/dist/drivers/helpers/logs_handle.js +24 -29
  110. package/dist/drivers/helpers/logs_handle.js.map +1 -1
  111. package/dist/drivers/helpers/ls_remote_import_handle.cjs +20 -20
  112. package/dist/drivers/helpers/ls_remote_import_handle.cjs.map +1 -1
  113. package/dist/drivers/helpers/ls_remote_import_handle.js +20 -18
  114. package/dist/drivers/helpers/ls_remote_import_handle.js.map +1 -1
  115. package/dist/drivers/helpers/ls_storage_entry.cjs +36 -40
  116. package/dist/drivers/helpers/ls_storage_entry.cjs.map +1 -1
  117. package/dist/drivers/helpers/ls_storage_entry.js +36 -37
  118. package/dist/drivers/helpers/ls_storage_entry.js.map +1 -1
  119. package/dist/drivers/helpers/polling_ops.d.ts +6 -5
  120. package/dist/drivers/helpers/read_file.cjs +34 -57
  121. package/dist/drivers/helpers/read_file.cjs.map +1 -1
  122. package/dist/drivers/helpers/read_file.js +30 -34
  123. package/dist/drivers/helpers/read_file.js.map +1 -1
  124. package/dist/drivers/logs.cjs +94 -112
  125. package/dist/drivers/logs.cjs.map +1 -1
  126. package/dist/drivers/logs.d.ts +35 -32
  127. package/dist/drivers/logs.js +93 -110
  128. package/dist/drivers/logs.js.map +1 -1
  129. package/dist/drivers/logs_stream.cjs +210 -242
  130. package/dist/drivers/logs_stream.cjs.map +1 -1
  131. package/dist/drivers/logs_stream.d.ts +55 -53
  132. package/dist/drivers/logs_stream.js +209 -240
  133. package/dist/drivers/logs_stream.js.map +1 -1
  134. package/dist/drivers/ls.cjs +151 -238
  135. package/dist/drivers/ls.cjs.map +1 -1
  136. package/dist/drivers/ls.d.ts +53 -49
  137. package/dist/drivers/ls.js +148 -216
  138. package/dist/drivers/ls.js.map +1 -1
  139. package/dist/drivers/types.cjs +25 -53
  140. package/dist/drivers/types.cjs.map +1 -1
  141. package/dist/drivers/types.d.ts +91 -106
  142. package/dist/drivers/types.js +23 -50
  143. package/dist/drivers/types.js.map +1 -1
  144. package/dist/drivers/upload.cjs +127 -153
  145. package/dist/drivers/upload.cjs.map +1 -1
  146. package/dist/drivers/upload.d.ts +52 -50
  147. package/dist/drivers/upload.js +126 -151
  148. package/dist/drivers/upload.js.map +1 -1
  149. package/dist/drivers/upload_task.cjs +223 -260
  150. package/dist/drivers/upload_task.cjs.map +1 -1
  151. package/dist/drivers/upload_task.d.ts +54 -52
  152. package/dist/drivers/upload_task.js +221 -258
  153. package/dist/drivers/upload_task.js.map +1 -1
  154. package/dist/drivers/urls/url.cjs +30 -35
  155. package/dist/drivers/urls/url.cjs.map +1 -1
  156. package/dist/drivers/urls/url.js +28 -33
  157. package/dist/drivers/urls/url.js.map +1 -1
  158. package/dist/drivers/virtual_storages.cjs +36 -48
  159. package/dist/drivers/virtual_storages.cjs.map +1 -1
  160. package/dist/drivers/virtual_storages.d.ts +6 -2
  161. package/dist/drivers/virtual_storages.js +32 -46
  162. package/dist/drivers/virtual_storages.js.map +1 -1
  163. package/dist/helpers/download.cjs +72 -95
  164. package/dist/helpers/download.cjs.map +1 -1
  165. package/dist/helpers/download.d.ts +13 -9
  166. package/dist/helpers/download.js +71 -93
  167. package/dist/helpers/download.js.map +1 -1
  168. package/dist/helpers/download_errors.cjs +28 -27
  169. package/dist/helpers/download_errors.cjs.map +1 -1
  170. package/dist/helpers/download_errors.d.ts +16 -13
  171. package/dist/helpers/download_errors.js +28 -26
  172. package/dist/helpers/download_errors.js.map +1 -1
  173. package/dist/helpers/validate.cjs +8 -7
  174. package/dist/helpers/validate.cjs.map +1 -1
  175. package/dist/helpers/validate.d.ts +4 -1
  176. package/dist/helpers/validate.js +6 -5
  177. package/dist/helpers/validate.js.map +1 -1
  178. package/dist/index.cjs +75 -79
  179. package/dist/index.d.ts +22 -22
  180. package/dist/index.js +22 -21
  181. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/downloadapi/protocol.cjs +238 -249
  182. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/downloadapi/protocol.cjs.map +1 -1
  183. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/downloadapi/protocol.client.cjs +27 -27
  184. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/downloadapi/protocol.client.cjs.map +1 -1
  185. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/downloadapi/protocol.client.d.ts +25 -23
  186. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/downloadapi/protocol.client.js +26 -25
  187. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/downloadapi/protocol.client.js.map +1 -1
  188. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/downloadapi/protocol.d.ts +51 -87
  189. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/downloadapi/protocol.js +238 -245
  190. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/downloadapi/protocol.js.map +1 -1
  191. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.cjs +295 -289
  192. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.cjs.map +1 -1
  193. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.client.cjs +30 -30
  194. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.client.cjs.map +1 -1
  195. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.client.js +29 -28
  196. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.client.js.map +1 -1
  197. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.d.ts +86 -150
  198. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.js +295 -285
  199. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.js.map +1 -1
  200. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/progressapi/protocol.cjs +385 -393
  201. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/progressapi/protocol.cjs.map +1 -1
  202. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/progressapi/protocol.client.cjs +34 -34
  203. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/progressapi/protocol.client.cjs.map +1 -1
  204. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/progressapi/protocol.client.d.ts +33 -34
  205. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/progressapi/protocol.client.js +33 -32
  206. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/progressapi/protocol.client.js.map +1 -1
  207. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/progressapi/protocol.d.ts +78 -129
  208. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/progressapi/protocol.js +385 -387
  209. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/progressapi/protocol.js.map +1 -1
  210. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol.cjs +570 -468
  211. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol.cjs.map +1 -1
  212. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol.client.cjs +82 -82
  213. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol.client.cjs.map +1 -1
  214. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol.client.d.ts +109 -112
  215. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol.client.js +81 -80
  216. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol.client.js.map +1 -1
  217. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol.d.ts +243 -264
  218. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol.js +569 -460
  219. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol.js.map +1 -1
  220. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/uploadapi/protocol.cjs +751 -729
  221. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/uploadapi/protocol.cjs.map +1 -1
  222. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/uploadapi/protocol.client.cjs +67 -67
  223. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/uploadapi/protocol.client.cjs.map +1 -1
  224. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/uploadapi/protocol.client.js +66 -65
  225. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/uploadapi/protocol.client.js.map +1 -1
  226. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/uploadapi/protocol.d.ts +15 -381
  227. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/uploadapi/protocol.js +749 -718
  228. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/uploadapi/protocol.js.map +1 -1
  229. package/dist/proto-grpc/google/protobuf/duration.cjs +92 -100
  230. package/dist/proto-grpc/google/protobuf/duration.cjs.map +1 -1
  231. package/dist/proto-grpc/google/protobuf/duration.d.ts +38 -43
  232. package/dist/proto-grpc/google/protobuf/duration.js +91 -98
  233. package/dist/proto-grpc/google/protobuf/duration.js.map +1 -1
  234. package/dist/proto-grpc/google/protobuf/timestamp.cjs +117 -128
  235. package/dist/proto-grpc/google/protobuf/timestamp.cjs.map +1 -1
  236. package/dist/proto-grpc/google/protobuf/timestamp.d.ts +50 -55
  237. package/dist/proto-grpc/google/protobuf/timestamp.js +116 -126
  238. package/dist/proto-grpc/google/protobuf/timestamp.js.map +1 -1
  239. package/dist/proto-rest/downloadapi.d.ts +85 -91
  240. package/dist/proto-rest/index.d.ts +11 -16
  241. package/dist/proto-rest/progressapi.d.ts +130 -140
  242. package/dist/proto-rest/streamingapi.d.ts +413 -434
  243. package/package.json +12 -12
  244. package/dist/clients/constructors.d.ts.map +0 -1
  245. package/dist/clients/crc32c.d.ts +0 -2
  246. package/dist/clients/crc32c.d.ts.map +0 -1
  247. package/dist/clients/download.d.ts.map +0 -1
  248. package/dist/clients/logs.d.ts.map +0 -1
  249. package/dist/clients/ls_api.d.ts.map +0 -1
  250. package/dist/clients/progress.d.ts.map +0 -1
  251. package/dist/clients/upload.d.ts.map +0 -1
  252. package/dist/drivers/download_blob/blob_key.d.ts +0 -5
  253. package/dist/drivers/download_blob/blob_key.d.ts.map +0 -1
  254. package/dist/drivers/download_blob/download_blob.d.ts.map +0 -1
  255. package/dist/drivers/download_blob/download_blob_task.d.ts +0 -56
  256. package/dist/drivers/download_blob/download_blob_task.d.ts.map +0 -1
  257. package/dist/drivers/download_blob/sparse_cache/cache.d.ts +0 -82
  258. package/dist/drivers/download_blob/sparse_cache/cache.d.ts.map +0 -1
  259. package/dist/drivers/download_blob/sparse_cache/file.d.ts +0 -8
  260. package/dist/drivers/download_blob/sparse_cache/file.d.ts.map +0 -1
  261. package/dist/drivers/download_blob/sparse_cache/ranges.d.ts +0 -46
  262. package/dist/drivers/download_blob/sparse_cache/ranges.d.ts.map +0 -1
  263. package/dist/drivers/download_blob_url/driver.d.ts.map +0 -1
  264. package/dist/drivers/download_blob_url/driver_id.d.ts +0 -6
  265. package/dist/drivers/download_blob_url/driver_id.d.ts.map +0 -1
  266. package/dist/drivers/download_blob_url/snapshot.d.ts.map +0 -1
  267. package/dist/drivers/download_blob_url/task.d.ts.map +0 -1
  268. package/dist/drivers/download_url/driver.d.ts.map +0 -1
  269. package/dist/drivers/download_url/task.d.ts.map +0 -1
  270. package/dist/drivers/helpers/download_local_handle.d.ts +0 -11
  271. package/dist/drivers/helpers/download_local_handle.d.ts.map +0 -1
  272. package/dist/drivers/helpers/download_remote_handle.d.ts +0 -13
  273. package/dist/drivers/helpers/download_remote_handle.d.ts.map +0 -1
  274. package/dist/drivers/helpers/files_cache.d.ts +0 -29
  275. package/dist/drivers/helpers/files_cache.d.ts.map +0 -1
  276. package/dist/drivers/helpers/helpers.d.ts.map +0 -1
  277. package/dist/drivers/helpers/logs_handle.d.ts +0 -15
  278. package/dist/drivers/helpers/logs_handle.d.ts.map +0 -1
  279. package/dist/drivers/helpers/ls_remote_import_handle.d.ts +0 -8
  280. package/dist/drivers/helpers/ls_remote_import_handle.d.ts.map +0 -1
  281. package/dist/drivers/helpers/ls_storage_entry.d.ts +0 -23
  282. package/dist/drivers/helpers/ls_storage_entry.d.ts.map +0 -1
  283. package/dist/drivers/helpers/polling_ops.d.ts.map +0 -1
  284. package/dist/drivers/helpers/read_file.d.ts +0 -12
  285. package/dist/drivers/helpers/read_file.d.ts.map +0 -1
  286. package/dist/drivers/helpers/test_helpers.d.ts +0 -2
  287. package/dist/drivers/helpers/test_helpers.d.ts.map +0 -1
  288. package/dist/drivers/logs.d.ts.map +0 -1
  289. package/dist/drivers/logs_stream.d.ts.map +0 -1
  290. package/dist/drivers/ls.d.ts.map +0 -1
  291. package/dist/drivers/types.d.ts.map +0 -1
  292. package/dist/drivers/upload.d.ts.map +0 -1
  293. package/dist/drivers/upload_task.d.ts.map +0 -1
  294. package/dist/drivers/urls/url.d.ts +0 -13
  295. package/dist/drivers/urls/url.d.ts.map +0 -1
  296. package/dist/drivers/virtual_storages.d.ts.map +0 -1
  297. package/dist/helpers/download.d.ts.map +0 -1
  298. package/dist/helpers/download_errors.d.ts.map +0 -1
  299. package/dist/helpers/validate.d.ts.map +0 -1
  300. package/dist/index.cjs.map +0 -1
  301. package/dist/index.d.ts.map +0 -1
  302. package/dist/index.js.map +0 -1
  303. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/downloadapi/protocol.client.d.ts.map +0 -1
  304. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/downloadapi/protocol.d.ts.map +0 -1
  305. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.client.d.ts +0 -46
  306. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.client.d.ts.map +0 -1
  307. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.d.ts.map +0 -1
  308. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/progressapi/protocol.client.d.ts.map +0 -1
  309. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/progressapi/protocol.d.ts.map +0 -1
  310. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol.client.d.ts.map +0 -1
  311. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol.d.ts.map +0 -1
  312. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/uploadapi/protocol.client.d.ts +0 -108
  313. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/uploadapi/protocol.client.d.ts.map +0 -1
  314. package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/uploadapi/protocol.d.ts.map +0 -1
  315. package/dist/proto-grpc/google/api/http.d.ts +0 -460
  316. package/dist/proto-grpc/google/api/http.d.ts.map +0 -1
  317. package/dist/proto-grpc/google/protobuf/descriptor.d.ts +0 -2340
  318. package/dist/proto-grpc/google/protobuf/descriptor.d.ts.map +0 -1
  319. package/dist/proto-grpc/google/protobuf/duration.d.ts.map +0 -1
  320. package/dist/proto-grpc/google/protobuf/timestamp.d.ts.map +0 -1
  321. package/dist/proto-rest/downloadapi.d.ts.map +0 -1
  322. package/dist/proto-rest/index.d.ts.map +0 -1
  323. package/dist/proto-rest/lsapi.d.ts +0 -148
  324. package/dist/proto-rest/lsapi.d.ts.map +0 -1
  325. package/dist/proto-rest/progressapi.d.ts.map +0 -1
  326. package/dist/proto-rest/streamingapi.d.ts.map +0 -1
  327. package/dist/proto-rest/uploadapi.d.ts +0 -355
  328. package/dist/proto-rest/uploadapi.d.ts.map +0 -1
  329. package/dist/test_env.d.ts +0 -6
  330. package/dist/test_env.d.ts.map +0 -1
@@ -1,45 +1,55 @@
1
- import type { WireClientProviderFactory, PlClient } from "@milaboratories/pl-client";
2
- import type { ResourceInfo } from "@milaboratories/pl-tree";
3
- import type { MiLogger } from "@milaboratories/ts-helpers";
4
- import type { RpcOptions } from "@protobuf-ts/runtime-rpc";
5
- import type { Dispatcher } from "undici";
6
- import { UploadAPI_ChecksumAlgorithm } from "../proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/uploadapi/protocol";
7
- export declare class MTimeError extends Error {
8
- name: string;
1
+ import { UploadAPI_ChecksumAlgorithm } from "../proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/uploadapi/protocol.js";
2
+ import { PlClient, WireClientProviderFactory } from "@milaboratories/pl-client";
3
+ import { Dispatcher } from "undici";
4
+ import { RpcOptions } from "@protobuf-ts/runtime-rpc";
5
+ import { MiLogger } from "@milaboratories/ts-helpers";
6
+ import { ResourceInfo } from "@milaboratories/pl-tree";
7
+
8
+ //#region src/clients/upload.d.ts
9
+ declare class MTimeError extends Error {
10
+ name: string;
9
11
  }
10
- export declare class UnexpectedEOF extends Error {
11
- name: string;
12
+ declare class UnexpectedEOF extends Error {
13
+ name: string;
12
14
  }
13
- export declare class NetworkError extends Error {
14
- name: string;
15
+ declare class NetworkError extends Error {
16
+ name: string;
15
17
  }
16
18
  /** Happens when the file doesn't exist */
17
- export declare class NoFileForUploading extends Error {
18
- name: string;
19
+ declare class NoFileForUploading extends Error {
20
+ name: string;
19
21
  }
20
- export declare class BadRequestError extends Error {
21
- name: string;
22
+ declare class BadRequestError extends Error {
23
+ name: string;
22
24
  }
23
25
  /** Low-level client for grpc uploadapi.
24
26
  * The user should pass here a concrete BlobUpload/<storageId> resource,
25
27
  * it can be got from handle field of BlobUpload. */
26
- export declare class ClientUpload {
27
- readonly httpClient: Dispatcher;
28
- readonly logger: MiLogger;
29
- private readonly wire;
30
- constructor(wireClientProviderFactory: WireClientProviderFactory, httpClient: Dispatcher, _: PlClient, logger: MiLogger);
31
- close(): void;
32
- initUpload({ id, type }: ResourceInfo, options?: RpcOptions): Promise<{
33
- overall: bigint;
34
- toUpload: bigint[];
35
- checksumAlgorithm: UploadAPI_ChecksumAlgorithm;
36
- checksumHeader: string;
37
- }>;
38
- partUpload({ id, type }: ResourceInfo, path: string, expectedMTimeUnix: bigint, partNumber: bigint, checksumAlgorithm: UploadAPI_ChecksumAlgorithm, checksumHeader: string, options?: RpcOptions): Promise<void>;
39
- finalize(info: ResourceInfo, options?: RpcOptions): Promise<void>;
40
- /** Calculates parts that need to be uploaded from the parts that were
41
- * already uploaded. */
42
- private partsToUpload;
43
- private updateProgress;
28
+ declare class ClientUpload {
29
+ readonly httpClient: Dispatcher;
30
+ readonly logger: MiLogger;
31
+ private readonly wire;
32
+ constructor(wireClientProviderFactory: WireClientProviderFactory, httpClient: Dispatcher, _: PlClient, logger: MiLogger);
33
+ close(): void;
34
+ initUpload({
35
+ id,
36
+ type
37
+ }: ResourceInfo, options?: RpcOptions): Promise<{
38
+ overall: bigint;
39
+ toUpload: bigint[];
40
+ checksumAlgorithm: UploadAPI_ChecksumAlgorithm;
41
+ checksumHeader: string;
42
+ }>;
43
+ partUpload({
44
+ id,
45
+ type
46
+ }: ResourceInfo, path: string, expectedMTimeUnix: bigint, partNumber: bigint, checksumAlgorithm: UploadAPI_ChecksumAlgorithm, checksumHeader: string, options?: RpcOptions): Promise<void>;
47
+ finalize(info: ResourceInfo, options?: RpcOptions): Promise<void>;
48
+ /** Calculates parts that need to be uploaded from the parts that were
49
+ * already uploaded. */
50
+ private partsToUpload;
51
+ private updateProgress;
44
52
  }
53
+ //#endregion
54
+ export { BadRequestError, ClientUpload, MTimeError, NetworkError, NoFileForUploading, UnexpectedEOF };
45
55
  //# sourceMappingURL=upload.d.ts.map
@@ -1,246 +1,204 @@
1
- import { RestAPI, addRTypeToMetadata, createRTypeRoutingHeader } from '@milaboratories/pl-client';
2
- import * as fsp from 'node:fs/promises';
3
- import { request } from 'undici';
4
- import { UploadAPI_ChecksumAlgorithm } from '../proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/uploadapi/protocol.js';
5
- import { UploadClient } from '../proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/uploadapi/protocol.client.js';
6
- import { crc32c } from './crc32c.js';
1
+ import { UploadAPI_ChecksumAlgorithm } from "../proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/uploadapi/protocol.js";
2
+ import { UploadClient } from "../proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/uploadapi/protocol.client.js";
3
+ import { crc32c } from "./crc32c.js";
4
+ import { RestAPI, addRTypeToMetadata, createRTypeRoutingHeader } from "@milaboratories/pl-client";
5
+ import * as fs from "node:fs/promises";
6
+ import { request } from "undici";
7
7
 
8
- class MTimeError extends Error {
9
- name = "MTimeError";
10
- }
11
- class UnexpectedEOF extends Error {
12
- name = "UnexpectedEOF";
13
- }
14
- class NetworkError extends Error {
15
- name = "NetworkError";
16
- }
8
+ //#region src/clients/upload.ts
9
+ var MTimeError = class extends Error {
10
+ name = "MTimeError";
11
+ };
12
+ var UnexpectedEOF = class extends Error {
13
+ name = "UnexpectedEOF";
14
+ };
15
+ var NetworkError = class extends Error {
16
+ name = "NetworkError";
17
+ };
17
18
  /** Happens when the file doesn't exist */
18
- class NoFileForUploading extends Error {
19
- name = "NoFileForUploading";
20
- }
21
- class BadRequestError extends Error {
22
- name = "BadRequestError";
23
- }
19
+ var NoFileForUploading = class extends Error {
20
+ name = "NoFileForUploading";
21
+ };
22
+ var BadRequestError = class extends Error {
23
+ name = "BadRequestError";
24
+ };
24
25
  /** Low-level client for grpc uploadapi.
25
- * The user should pass here a concrete BlobUpload/<storageId> resource,
26
- * it can be got from handle field of BlobUpload. */
27
- class ClientUpload {
28
- httpClient;
29
- logger;
30
- wire;
31
- constructor(wireClientProviderFactory, httpClient, _, logger) {
32
- this.httpClient = httpClient;
33
- this.logger = logger;
34
- this.wire = wireClientProviderFactory.createWireClientProvider((wire) => {
35
- if (wire.type === "grpc") {
36
- return new UploadClient(wire.Transport);
37
- }
38
- return RestAPI.createClient({
39
- hostAndPort: wire.Config.hostAndPort,
40
- ssl: wire.Config.ssl,
41
- dispatcher: wire.Dispatcher,
42
- middlewares: wire.Middlewares,
43
- });
44
- });
45
- }
46
- close() { }
47
- async initUpload({ id, type }, options) {
48
- const client = this.wire.get();
49
- if (client instanceof UploadClient) {
50
- const init = (await client.init({ resourceId: id }, addRTypeToMetadata(type, options)))
51
- .response;
52
- return {
53
- overall: init.partsCount,
54
- toUpload: this.partsToUpload(init.partsCount, init.uploadedParts),
55
- checksumAlgorithm: init.checksumAlgorithm,
56
- checksumHeader: init.checksumHeader,
57
- };
58
- }
59
- const init = (await client.POST("/v1/upload/init", {
60
- body: {
61
- resourceId: id.toString(),
62
- },
63
- headers: { ...createRTypeRoutingHeader(type) },
64
- })).data;
65
- return {
66
- overall: BigInt(init.partsCount),
67
- toUpload: this.partsToUpload(BigInt(init.partsCount), init.uploadedParts.map(BigInt)),
68
- checksumAlgorithm: init.checksumAlgorithm,
69
- checksumHeader: init.checksumHeader,
70
- };
71
- }
72
- async partUpload({ id, type }, path, expectedMTimeUnix, partNumber, checksumAlgorithm, checksumHeader, options) {
73
- const client = this.wire.get();
74
- let info;
75
- if (client instanceof UploadClient) {
76
- // partChecksum isn't used for now but protoc requires it to be set
77
- info = (await client.getPartURL({
78
- resourceId: id,
79
- partNumber,
80
- uploadedPartSize: 0n,
81
- isInternalUse: false,
82
- partChecksum: "",
83
- }, addRTypeToMetadata(type, options))).response;
84
- }
85
- else {
86
- const resp = (await client.POST("/v1/upload/get-part-url", {
87
- body: {
88
- resourceId: id.toString(),
89
- partNumber: partNumber.toString(),
90
- uploadedPartSize: "0",
91
- isInternalUse: false,
92
- partChecksum: "",
93
- },
94
- headers: { ...createRTypeRoutingHeader(type) },
95
- })).data;
96
- info = {
97
- uploadUrl: resp.uploadUrl,
98
- method: resp.method,
99
- headers: resp.headers,
100
- chunkStart: BigInt(resp.chunkStart),
101
- chunkEnd: BigInt(resp.chunkEnd),
102
- };
103
- }
104
- const chunk = await readFileChunk(path, info.chunkStart, info.chunkEnd);
105
- await checkExpectedMTime(path, expectedMTimeUnix);
106
- if (checksumHeader && checksumAlgorithm === UploadAPI_ChecksumAlgorithm.CRC32C) {
107
- info.headers.push({ name: checksumHeader, value: calculateCrc32cChecksum(chunk) });
108
- }
109
- const contentLength = Number(info.chunkEnd - info.chunkStart);
110
- if (chunk.length !== contentLength) {
111
- throw new Error(`Chunk size mismatch: expected ${contentLength} bytes, but read ${chunk.length} bytes from file`);
112
- }
113
- const headers = Object.fromEntries(info.headers.map(({ name, value }) => [name.toLowerCase(), value]));
114
- try {
115
- const { body: rawBody, statusCode, headers: responseHeaders, } = await request(info.uploadUrl, {
116
- dispatcher: this.httpClient,
117
- body: chunk,
118
- // We got headers only after we send
119
- // the whole body (in case of S3 PUT requests it's 5 MB).
120
- // It might be slow with a slow connection (or with SSH),
121
- // that's why we got big timeout here.
122
- headersTimeout: 60000,
123
- bodyTimeout: 60000,
124
- // Prevent connection reuse by setting "Connection: close" header.
125
- // This works around an issue with the backend's built-in S3 implementation
126
- // that caused HTTP/1.1 protocol lines to be included in the uploaded file content.
127
- reset: true,
128
- headers,
129
- method: info.method.toUpperCase(),
130
- });
131
- // always read the body for resources to be garbage collected.
132
- const body = await rawBody.text();
133
- checkStatusCodeOk(statusCode, body, responseHeaders, info);
134
- }
135
- catch (e) {
136
- if (e instanceof NetworkError)
137
- throw e;
138
- if (e instanceof BadRequestError)
139
- throw e;
140
- throw new Error(`partUpload: error ${JSON.stringify(e)} happened while trying to do part upload to the url ${info.uploadUrl}, headers: ${JSON.stringify(info.headers)}`);
141
- }
142
- await this.updateProgress({ id, type }, BigInt(info.chunkEnd - info.chunkStart), options);
143
- }
144
- async finalize(info, options) {
145
- const client = this.wire.get();
146
- if (client instanceof UploadClient) {
147
- await client.finalize({ resourceId: info.id }, addRTypeToMetadata(info.type, options));
148
- }
149
- else {
150
- await client.POST("/v1/upload/finalize", {
151
- body: {
152
- resourceId: info.id.toString(),
153
- },
154
- headers: { ...createRTypeRoutingHeader(info.type) },
155
- });
156
- }
157
- }
158
- /** Calculates parts that need to be uploaded from the parts that were
159
- * already uploaded. */
160
- partsToUpload(partsCount, uploadedParts) {
161
- const toUpload = [];
162
- const uploaded = new Set(uploadedParts);
163
- for (let i = 1n; i <= partsCount; i++) {
164
- if (!uploaded.has(i))
165
- toUpload.push(i);
166
- }
167
- return toUpload;
168
- }
169
- async updateProgress({ id, type }, bytesProcessed, options) {
170
- const client = this.wire.get();
171
- if (client instanceof UploadClient) {
172
- await client.updateProgress({
173
- resourceId: id,
174
- bytesProcessed,
175
- }, addRTypeToMetadata(type, options)).response;
176
- return;
177
- }
178
- await client.POST("/v1/upload/update-progress", {
179
- body: {
180
- resourceId: id.toString(),
181
- bytesProcessed: bytesProcessed.toString(),
182
- },
183
- headers: { ...createRTypeRoutingHeader(type) },
184
- });
185
- return;
186
- }
187
- }
26
+ * The user should pass here a concrete BlobUpload/<storageId> resource,
27
+ * it can be got from handle field of BlobUpload. */
28
+ var ClientUpload = class {
29
+ wire;
30
+ constructor(wireClientProviderFactory, httpClient, _, logger) {
31
+ this.httpClient = httpClient;
32
+ this.logger = logger;
33
+ this.wire = wireClientProviderFactory.createWireClientProvider((wire) => {
34
+ if (wire.type === "grpc") return new UploadClient(wire.Transport);
35
+ return RestAPI.createClient({
36
+ hostAndPort: wire.Config.hostAndPort,
37
+ ssl: wire.Config.ssl,
38
+ dispatcher: wire.Dispatcher,
39
+ middlewares: wire.Middlewares
40
+ });
41
+ });
42
+ }
43
+ close() {}
44
+ async initUpload({ id, type }, options) {
45
+ const client = this.wire.get();
46
+ if (client instanceof UploadClient) {
47
+ const init = (await client.init({ resourceId: id }, addRTypeToMetadata(type, options))).response;
48
+ return {
49
+ overall: init.partsCount,
50
+ toUpload: this.partsToUpload(init.partsCount, init.uploadedParts),
51
+ checksumAlgorithm: init.checksumAlgorithm,
52
+ checksumHeader: init.checksumHeader
53
+ };
54
+ }
55
+ const init = (await client.POST("/v1/upload/init", {
56
+ body: { resourceId: id.toString() },
57
+ headers: { ...createRTypeRoutingHeader(type) }
58
+ })).data;
59
+ return {
60
+ overall: BigInt(init.partsCount),
61
+ toUpload: this.partsToUpload(BigInt(init.partsCount), init.uploadedParts.map(BigInt)),
62
+ checksumAlgorithm: init.checksumAlgorithm,
63
+ checksumHeader: init.checksumHeader
64
+ };
65
+ }
66
+ async partUpload({ id, type }, path, expectedMTimeUnix, partNumber, checksumAlgorithm, checksumHeader, options) {
67
+ const client = this.wire.get();
68
+ let info;
69
+ if (client instanceof UploadClient) info = (await client.getPartURL({
70
+ resourceId: id,
71
+ partNumber,
72
+ uploadedPartSize: 0n,
73
+ isInternalUse: false,
74
+ partChecksum: ""
75
+ }, addRTypeToMetadata(type, options))).response;
76
+ else {
77
+ const resp = (await client.POST("/v1/upload/get-part-url", {
78
+ body: {
79
+ resourceId: id.toString(),
80
+ partNumber: partNumber.toString(),
81
+ uploadedPartSize: "0",
82
+ isInternalUse: false,
83
+ partChecksum: ""
84
+ },
85
+ headers: { ...createRTypeRoutingHeader(type) }
86
+ })).data;
87
+ info = {
88
+ uploadUrl: resp.uploadUrl,
89
+ method: resp.method,
90
+ headers: resp.headers,
91
+ chunkStart: BigInt(resp.chunkStart),
92
+ chunkEnd: BigInt(resp.chunkEnd)
93
+ };
94
+ }
95
+ const chunk = await readFileChunk(path, info.chunkStart, info.chunkEnd);
96
+ await checkExpectedMTime(path, expectedMTimeUnix);
97
+ if (checksumHeader && checksumAlgorithm === UploadAPI_ChecksumAlgorithm.CRC32C) info.headers.push({
98
+ name: checksumHeader,
99
+ value: calculateCrc32cChecksum(chunk)
100
+ });
101
+ const contentLength = Number(info.chunkEnd - info.chunkStart);
102
+ if (chunk.length !== contentLength) throw new Error(`Chunk size mismatch: expected ${contentLength} bytes, but read ${chunk.length} bytes from file`);
103
+ const headers = Object.fromEntries(info.headers.map(({ name, value }) => [name.toLowerCase(), value]));
104
+ try {
105
+ const { body: rawBody, statusCode, headers: responseHeaders } = await request(info.uploadUrl, {
106
+ dispatcher: this.httpClient,
107
+ body: chunk,
108
+ headersTimeout: 6e4,
109
+ bodyTimeout: 6e4,
110
+ reset: true,
111
+ headers,
112
+ method: info.method.toUpperCase()
113
+ });
114
+ checkStatusCodeOk(statusCode, await rawBody.text(), responseHeaders, info);
115
+ } catch (e) {
116
+ if (e instanceof NetworkError) throw e;
117
+ if (e instanceof BadRequestError) throw e;
118
+ throw new Error(`partUpload: error ${JSON.stringify(e)} happened while trying to do part upload to the url ${info.uploadUrl}, headers: ${JSON.stringify(info.headers)}`);
119
+ }
120
+ await this.updateProgress({
121
+ id,
122
+ type
123
+ }, BigInt(info.chunkEnd - info.chunkStart), options);
124
+ }
125
+ async finalize(info, options) {
126
+ const client = this.wire.get();
127
+ if (client instanceof UploadClient) await client.finalize({ resourceId: info.id }, addRTypeToMetadata(info.type, options));
128
+ else await client.POST("/v1/upload/finalize", {
129
+ body: { resourceId: info.id.toString() },
130
+ headers: { ...createRTypeRoutingHeader(info.type) }
131
+ });
132
+ }
133
+ /** Calculates parts that need to be uploaded from the parts that were
134
+ * already uploaded. */
135
+ partsToUpload(partsCount, uploadedParts) {
136
+ const toUpload = [];
137
+ const uploaded = new Set(uploadedParts);
138
+ for (let i = 1n; i <= partsCount; i++) if (!uploaded.has(i)) toUpload.push(i);
139
+ return toUpload;
140
+ }
141
+ async updateProgress({ id, type }, bytesProcessed, options) {
142
+ const client = this.wire.get();
143
+ if (client instanceof UploadClient) {
144
+ await client.updateProgress({
145
+ resourceId: id,
146
+ bytesProcessed
147
+ }, addRTypeToMetadata(type, options)).response;
148
+ return;
149
+ }
150
+ await client.POST("/v1/upload/update-progress", {
151
+ body: {
152
+ resourceId: id.toString(),
153
+ bytesProcessed: bytesProcessed.toString()
154
+ },
155
+ headers: { ...createRTypeRoutingHeader(type) }
156
+ });
157
+ }
158
+ };
188
159
  async function readFileChunk(path, chunkStart, chunkEnd) {
189
- let f;
190
- try {
191
- f = await fsp.open(path);
192
- const len = Number(chunkEnd - chunkStart);
193
- const pos = Number(chunkStart);
194
- const b = Buffer.alloc(len);
195
- const bytesRead = await readBytesFromPosition(f, b, len, pos);
196
- return b.subarray(0, bytesRead);
197
- }
198
- catch (e) {
199
- if (e && typeof e === "object" && "code" in e && e.code == "ENOENT")
200
- throw new NoFileForUploading(`there is no file ${path} for uploading`);
201
- throw e;
202
- }
203
- finally {
204
- await f?.close();
205
- }
160
+ let f;
161
+ try {
162
+ f = await fs.open(path);
163
+ const len = Number(chunkEnd - chunkStart);
164
+ const pos = Number(chunkStart);
165
+ const b = Buffer.alloc(len);
166
+ const bytesRead = await readBytesFromPosition(f, b, len, pos);
167
+ return b.subarray(0, bytesRead);
168
+ } catch (e) {
169
+ if (e && typeof e === "object" && "code" in e && e.code == "ENOENT") throw new NoFileForUploading(`there is no file ${path} for uploading`);
170
+ throw e;
171
+ } finally {
172
+ await f?.close();
173
+ }
206
174
  }
207
175
  /** Read len bytes from a given position.
208
- * Without this, `FileHandle.read` can read less bytes than needed. */
176
+ * Without this, `FileHandle.read` can read less bytes than needed. */
209
177
  async function readBytesFromPosition(f, b, len, position) {
210
- let bytesReadTotal = 0;
211
- while (bytesReadTotal < len) {
212
- const { bytesRead } = await f.read(b, bytesReadTotal, len - bytesReadTotal, position + bytesReadTotal);
213
- if (bytesRead === 0) {
214
- throw new UnexpectedEOF("file ended earlier than expected.");
215
- }
216
- bytesReadTotal += bytesRead;
217
- }
218
- return bytesReadTotal;
178
+ let bytesReadTotal = 0;
179
+ while (bytesReadTotal < len) {
180
+ const { bytesRead } = await f.read(b, bytesReadTotal, len - bytesReadTotal, position + bytesReadTotal);
181
+ if (bytesRead === 0) throw new UnexpectedEOF("file ended earlier than expected.");
182
+ bytesReadTotal += bytesRead;
183
+ }
184
+ return bytesReadTotal;
219
185
  }
220
186
  async function checkExpectedMTime(path, expectedMTimeUnix) {
221
- const mTime = BigInt(Math.floor((await fsp.stat(path)).mtimeMs / 1000));
222
- if (mTime > expectedMTimeUnix) {
223
- throw new MTimeError(`file was modified, expected mtime: ${expectedMTimeUnix}, got: ${mTime}.`);
224
- }
187
+ const mTime = BigInt(Math.floor((await fs.stat(path)).mtimeMs / 1e3));
188
+ if (mTime > expectedMTimeUnix) throw new MTimeError(`file was modified, expected mtime: ${expectedMTimeUnix}, got: ${mTime}.`);
225
189
  }
226
190
  function checkStatusCodeOk(statusCode, body, headers, info) {
227
- if (statusCode == 400) {
228
- throw new BadRequestError(`response is not ok, status code: ${statusCode},` +
229
- ` body: ${body}, headers: ${JSON.stringify(headers)}, url: ${info.uploadUrl}`);
230
- }
231
- if (statusCode != 200) {
232
- throw new NetworkError(`response is not ok, status code: ${statusCode},` +
233
- ` body: ${body}, headers: ${JSON.stringify(headers)}, url: ${info.uploadUrl}`);
234
- }
191
+ if (statusCode == 400) throw new BadRequestError(`response is not ok, status code: ${statusCode}, body: ${body}, headers: ${JSON.stringify(headers)}, url: ${info.uploadUrl}`);
192
+ if (statusCode != 200) throw new NetworkError(`response is not ok, status code: ${statusCode}, body: ${body}, headers: ${JSON.stringify(headers)}, url: ${info.uploadUrl}`);
235
193
  }
236
194
  /** Calculate CRC32C checksum of a buffer and return as base64 string */
237
195
  function calculateCrc32cChecksum(data) {
238
- const checksum = crc32c(data);
239
- // Convert to unsigned 32-bit integer and then to base64
240
- const buffer = Buffer.alloc(4);
241
- buffer.writeUInt32BE(checksum, 0);
242
- return buffer.toString("base64");
196
+ const checksum = crc32c(data);
197
+ const buffer = Buffer.alloc(4);
198
+ buffer.writeUInt32BE(checksum, 0);
199
+ return buffer.toString("base64");
243
200
  }
244
201
 
202
+ //#endregion
245
203
  export { BadRequestError, ClientUpload, MTimeError, NetworkError, NoFileForUploading, UnexpectedEOF };
246
- //# sourceMappingURL=upload.js.map
204
+ //# sourceMappingURL=upload.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"upload.js","sources":["../../src/clients/upload.ts"],"sourcesContent":["import type {\n WireClientProvider,\n WireClientProviderFactory,\n PlClient,\n} from \"@milaboratories/pl-client\";\nimport { addRTypeToMetadata, createRTypeRoutingHeader, RestAPI } from \"@milaboratories/pl-client\";\nimport type { ResourceInfo } from \"@milaboratories/pl-tree\";\nimport type { MiLogger } from \"@milaboratories/ts-helpers\";\nimport type { RpcOptions } from \"@protobuf-ts/runtime-rpc\";\nimport * as fs from \"node:fs/promises\";\nimport type { Dispatcher } from \"undici\";\nimport { request } from \"undici\";\nimport {\n UploadAPI_ChecksumAlgorithm,\n type UploadAPI_GetPartURL_Response,\n} from \"../proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/uploadapi/protocol\";\nimport { UploadClient } from \"../proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/uploadapi/protocol.client\";\nimport type { UploadApiPaths, UploadRestClientType } from \"../proto-rest\";\nimport { crc32c } from \"./crc32c\";\n\nimport type { IncomingHttpHeaders } from \"undici/types/header\";\n\nexport class MTimeError extends Error {\n name = \"MTimeError\";\n}\n\nexport class UnexpectedEOF extends Error {\n name = \"UnexpectedEOF\";\n}\n\nexport class NetworkError extends Error {\n name = \"NetworkError\";\n}\n\n/** Happens when the file doesn't exist */\nexport class NoFileForUploading extends Error {\n name = \"NoFileForUploading\";\n}\n\nexport class BadRequestError extends Error {\n name = \"BadRequestError\";\n}\n\n/** Low-level client for grpc uploadapi.\n * The user should pass here a concrete BlobUpload/<storageId> resource,\n * it can be got from handle field of BlobUpload. */\nexport class ClientUpload {\n private readonly wire: WireClientProvider<UploadRestClientType | UploadClient>;\n\n constructor(\n wireClientProviderFactory: WireClientProviderFactory,\n public readonly httpClient: Dispatcher,\n _: PlClient,\n public readonly logger: MiLogger,\n ) {\n this.wire = wireClientProviderFactory.createWireClientProvider((wire) => {\n if (wire.type === \"grpc\") {\n return new UploadClient(wire.Transport);\n }\n\n return RestAPI.createClient<UploadApiPaths>({\n hostAndPort: wire.Config.hostAndPort,\n ssl: wire.Config.ssl,\n dispatcher: wire.Dispatcher,\n middlewares: wire.Middlewares,\n });\n });\n }\n\n close() {}\n\n public async initUpload(\n { id, type }: ResourceInfo,\n options?: RpcOptions,\n ): Promise<{\n overall: bigint;\n toUpload: bigint[];\n checksumAlgorithm: UploadAPI_ChecksumAlgorithm;\n checksumHeader: string;\n }> {\n const client = this.wire.get();\n\n if (client instanceof UploadClient) {\n const init = (await client.init({ resourceId: id }, addRTypeToMetadata(type, options)))\n .response;\n\n return {\n overall: init.partsCount,\n toUpload: this.partsToUpload(init.partsCount, init.uploadedParts),\n checksumAlgorithm: init.checksumAlgorithm,\n checksumHeader: init.checksumHeader,\n };\n }\n\n const init = (\n await client.POST(\"/v1/upload/init\", {\n body: {\n resourceId: id.toString(),\n },\n headers: { ...createRTypeRoutingHeader(type) },\n })\n ).data!;\n\n return {\n overall: BigInt(init.partsCount),\n toUpload: this.partsToUpload(BigInt(init.partsCount), init.uploadedParts.map(BigInt)),\n checksumAlgorithm: init.checksumAlgorithm,\n checksumHeader: init.checksumHeader,\n };\n }\n\n public async partUpload(\n { id, type }: ResourceInfo,\n path: string,\n expectedMTimeUnix: bigint,\n partNumber: bigint,\n checksumAlgorithm: UploadAPI_ChecksumAlgorithm,\n checksumHeader: string,\n options?: RpcOptions,\n ) {\n const client = this.wire.get();\n\n let info: UploadAPI_GetPartURL_Response;\n if (client instanceof UploadClient) {\n // partChecksum isn't used for now but protoc requires it to be set\n info = (\n await client.getPartURL(\n {\n resourceId: id,\n partNumber,\n uploadedPartSize: 0n,\n isInternalUse: false,\n partChecksum: \"\",\n },\n addRTypeToMetadata(type, options),\n )\n ).response;\n } else {\n const resp = (\n await client.POST(\"/v1/upload/get-part-url\", {\n body: {\n resourceId: id.toString(),\n partNumber: partNumber.toString(),\n uploadedPartSize: \"0\",\n isInternalUse: false,\n partChecksum: \"\",\n },\n headers: { ...createRTypeRoutingHeader(type) },\n })\n ).data!;\n info = {\n uploadUrl: resp.uploadUrl,\n method: resp.method,\n headers: resp.headers,\n chunkStart: BigInt(resp.chunkStart),\n chunkEnd: BigInt(resp.chunkEnd),\n };\n }\n\n const chunk = await readFileChunk(path, info.chunkStart, info.chunkEnd);\n await checkExpectedMTime(path, expectedMTimeUnix);\n\n if (checksumHeader && checksumAlgorithm === UploadAPI_ChecksumAlgorithm.CRC32C) {\n info.headers.push({ name: checksumHeader, value: calculateCrc32cChecksum(chunk) });\n }\n\n const contentLength = Number(info.chunkEnd - info.chunkStart);\n if (chunk.length !== contentLength) {\n throw new Error(\n `Chunk size mismatch: expected ${contentLength} bytes, but read ${chunk.length} bytes from file`,\n );\n }\n\n const headers = Object.fromEntries(\n info.headers.map(({ name, value }) => [name.toLowerCase(), value]),\n );\n\n try {\n const {\n body: rawBody,\n statusCode,\n headers: responseHeaders,\n } = await request(info.uploadUrl, {\n dispatcher: this.httpClient,\n body: chunk,\n // We got headers only after we send\n // the whole body (in case of S3 PUT requests it's 5 MB).\n // It might be slow with a slow connection (or with SSH),\n // that's why we got big timeout here.\n headersTimeout: 60000,\n bodyTimeout: 60000,\n // Prevent connection reuse by setting \"Connection: close\" header.\n // This works around an issue with the backend's built-in S3 implementation\n // that caused HTTP/1.1 protocol lines to be included in the uploaded file content.\n reset: true,\n headers,\n method: info.method.toUpperCase() as Dispatcher.HttpMethod,\n });\n\n // always read the body for resources to be garbage collected.\n const body = await rawBody.text();\n checkStatusCodeOk(statusCode, body, responseHeaders, info);\n } catch (e: unknown) {\n if (e instanceof NetworkError) throw e;\n\n if (e instanceof BadRequestError) throw e;\n\n throw new Error(\n `partUpload: error ${JSON.stringify(e)} happened while trying to do part upload to the url ${info.uploadUrl}, headers: ${JSON.stringify(info.headers)}`,\n );\n }\n\n await this.updateProgress({ id, type }, BigInt(info.chunkEnd - info.chunkStart), options);\n }\n\n public async finalize(info: ResourceInfo, options?: RpcOptions) {\n const client = this.wire.get();\n\n if (client instanceof UploadClient) {\n await client.finalize({ resourceId: info.id }, addRTypeToMetadata(info.type, options));\n } else {\n await client.POST(\"/v1/upload/finalize\", {\n body: {\n resourceId: info.id.toString(),\n },\n headers: { ...createRTypeRoutingHeader(info.type) },\n });\n }\n }\n\n /** Calculates parts that need to be uploaded from the parts that were\n * already uploaded. */\n private partsToUpload(partsCount: bigint, uploadedParts: bigint[]): bigint[] {\n const toUpload: bigint[] = [];\n const uploaded = new Set(uploadedParts);\n\n for (let i = 1n; i <= partsCount; i++) {\n if (!uploaded.has(i)) toUpload.push(i);\n }\n\n return toUpload;\n }\n\n private async updateProgress(\n { id, type }: ResourceInfo,\n bytesProcessed: bigint,\n options?: RpcOptions,\n ): Promise<void> {\n const client = this.wire.get();\n\n if (client instanceof UploadClient) {\n await client.updateProgress(\n {\n resourceId: id,\n bytesProcessed,\n },\n addRTypeToMetadata(type, options),\n ).response;\n return;\n }\n\n await client.POST(\"/v1/upload/update-progress\", {\n body: {\n resourceId: id.toString(),\n bytesProcessed: bytesProcessed.toString(),\n },\n headers: { ...createRTypeRoutingHeader(type) },\n });\n return;\n }\n}\n\nasync function readFileChunk(path: string, chunkStart: bigint, chunkEnd: bigint): Promise<Buffer> {\n let f: fs.FileHandle | undefined;\n try {\n f = await fs.open(path);\n const len = Number(chunkEnd - chunkStart);\n const pos = Number(chunkStart);\n const b = Buffer.alloc(len);\n const bytesRead = await readBytesFromPosition(f, b, len, pos);\n\n return b.subarray(0, bytesRead);\n } catch (e: unknown) {\n if (e && typeof e === \"object\" && \"code\" in e && e.code == \"ENOENT\")\n throw new NoFileForUploading(`there is no file ${path} for uploading`);\n throw e;\n } finally {\n await f?.close();\n }\n}\n\n/** Read len bytes from a given position.\n * Without this, `FileHandle.read` can read less bytes than needed. */\nasync function readBytesFromPosition(f: fs.FileHandle, b: Buffer, len: number, position: number) {\n let bytesReadTotal = 0;\n while (bytesReadTotal < len) {\n const { bytesRead } = await f.read(\n b,\n bytesReadTotal,\n len - bytesReadTotal,\n position + bytesReadTotal,\n );\n if (bytesRead === 0) {\n throw new UnexpectedEOF(\"file ended earlier than expected.\");\n }\n bytesReadTotal += bytesRead;\n }\n\n return bytesReadTotal;\n}\n\nasync function checkExpectedMTime(path: string, expectedMTimeUnix: bigint) {\n const mTime = BigInt(Math.floor((await fs.stat(path)).mtimeMs / 1000));\n if (mTime > expectedMTimeUnix) {\n throw new MTimeError(`file was modified, expected mtime: ${expectedMTimeUnix}, got: ${mTime}.`);\n }\n}\n\nfunction checkStatusCodeOk(\n statusCode: number,\n body: string,\n headers: IncomingHttpHeaders,\n info: UploadAPI_GetPartURL_Response,\n) {\n if (statusCode == 400) {\n throw new BadRequestError(\n `response is not ok, status code: ${statusCode},` +\n ` body: ${body}, headers: ${JSON.stringify(headers)}, url: ${info.uploadUrl}`,\n );\n }\n\n if (statusCode != 200) {\n throw new NetworkError(\n `response is not ok, status code: ${statusCode},` +\n ` body: ${body}, headers: ${JSON.stringify(headers)}, url: ${info.uploadUrl}`,\n );\n }\n}\n\n/** Calculate CRC32C checksum of a buffer and return as base64 string */\nfunction calculateCrc32cChecksum(data: Buffer): string {\n const checksum = crc32c(data);\n // Convert to unsigned 32-bit integer and then to base64\n const buffer = Buffer.alloc(4);\n\n buffer.writeUInt32BE(checksum, 0);\n return buffer.toString(\"base64\");\n}\n"],"names":["fs"],"mappings":"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"}
1
+ {"version":3,"file":"upload.js","names":[],"sources":["../../src/clients/upload.ts"],"sourcesContent":["import type {\n WireClientProvider,\n WireClientProviderFactory,\n PlClient,\n} from \"@milaboratories/pl-client\";\nimport { addRTypeToMetadata, createRTypeRoutingHeader, RestAPI } from \"@milaboratories/pl-client\";\nimport type { ResourceInfo } from \"@milaboratories/pl-tree\";\nimport type { MiLogger } from \"@milaboratories/ts-helpers\";\nimport type { RpcOptions } from \"@protobuf-ts/runtime-rpc\";\nimport * as fs from \"node:fs/promises\";\nimport type { Dispatcher } from \"undici\";\nimport { request } from \"undici\";\nimport {\n UploadAPI_ChecksumAlgorithm,\n type UploadAPI_GetPartURL_Response,\n} from \"../proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/uploadapi/protocol\";\nimport { UploadClient } from \"../proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/uploadapi/protocol.client\";\nimport type { UploadApiPaths, UploadRestClientType } from \"../proto-rest\";\nimport { crc32c } from \"./crc32c\";\n\nimport type { IncomingHttpHeaders } from \"undici/types/header\";\n\nexport class MTimeError extends Error {\n name = \"MTimeError\";\n}\n\nexport class UnexpectedEOF extends Error {\n name = \"UnexpectedEOF\";\n}\n\nexport class NetworkError extends Error {\n name = \"NetworkError\";\n}\n\n/** Happens when the file doesn't exist */\nexport class NoFileForUploading extends Error {\n name = \"NoFileForUploading\";\n}\n\nexport class BadRequestError extends Error {\n name = \"BadRequestError\";\n}\n\n/** Low-level client for grpc uploadapi.\n * The user should pass here a concrete BlobUpload/<storageId> resource,\n * it can be got from handle field of BlobUpload. */\nexport class ClientUpload {\n private readonly wire: WireClientProvider<UploadRestClientType | UploadClient>;\n\n constructor(\n wireClientProviderFactory: WireClientProviderFactory,\n public readonly httpClient: Dispatcher,\n _: PlClient,\n public readonly logger: MiLogger,\n ) {\n this.wire = wireClientProviderFactory.createWireClientProvider((wire) => {\n if (wire.type === \"grpc\") {\n return new UploadClient(wire.Transport);\n }\n\n return RestAPI.createClient<UploadApiPaths>({\n hostAndPort: wire.Config.hostAndPort,\n ssl: wire.Config.ssl,\n dispatcher: wire.Dispatcher,\n middlewares: wire.Middlewares,\n });\n });\n }\n\n close() {}\n\n public async initUpload(\n { id, type }: ResourceInfo,\n options?: RpcOptions,\n ): Promise<{\n overall: bigint;\n toUpload: bigint[];\n checksumAlgorithm: UploadAPI_ChecksumAlgorithm;\n checksumHeader: string;\n }> {\n const client = this.wire.get();\n\n if (client instanceof UploadClient) {\n const init = (await client.init({ resourceId: id }, addRTypeToMetadata(type, options)))\n .response;\n\n return {\n overall: init.partsCount,\n toUpload: this.partsToUpload(init.partsCount, init.uploadedParts),\n checksumAlgorithm: init.checksumAlgorithm,\n checksumHeader: init.checksumHeader,\n };\n }\n\n const init = (\n await client.POST(\"/v1/upload/init\", {\n body: {\n resourceId: id.toString(),\n },\n headers: { ...createRTypeRoutingHeader(type) },\n })\n ).data!;\n\n return {\n overall: BigInt(init.partsCount),\n toUpload: this.partsToUpload(BigInt(init.partsCount), init.uploadedParts.map(BigInt)),\n checksumAlgorithm: init.checksumAlgorithm,\n checksumHeader: init.checksumHeader,\n };\n }\n\n public async partUpload(\n { id, type }: ResourceInfo,\n path: string,\n expectedMTimeUnix: bigint,\n partNumber: bigint,\n checksumAlgorithm: UploadAPI_ChecksumAlgorithm,\n checksumHeader: string,\n options?: RpcOptions,\n ) {\n const client = this.wire.get();\n\n let info: UploadAPI_GetPartURL_Response;\n if (client instanceof UploadClient) {\n // partChecksum isn't used for now but protoc requires it to be set\n info = (\n await client.getPartURL(\n {\n resourceId: id,\n partNumber,\n uploadedPartSize: 0n,\n isInternalUse: false,\n partChecksum: \"\",\n },\n addRTypeToMetadata(type, options),\n )\n ).response;\n } else {\n const resp = (\n await client.POST(\"/v1/upload/get-part-url\", {\n body: {\n resourceId: id.toString(),\n partNumber: partNumber.toString(),\n uploadedPartSize: \"0\",\n isInternalUse: false,\n partChecksum: \"\",\n },\n headers: { ...createRTypeRoutingHeader(type) },\n })\n ).data!;\n info = {\n uploadUrl: resp.uploadUrl,\n method: resp.method,\n headers: resp.headers,\n chunkStart: BigInt(resp.chunkStart),\n chunkEnd: BigInt(resp.chunkEnd),\n };\n }\n\n const chunk = await readFileChunk(path, info.chunkStart, info.chunkEnd);\n await checkExpectedMTime(path, expectedMTimeUnix);\n\n if (checksumHeader && checksumAlgorithm === UploadAPI_ChecksumAlgorithm.CRC32C) {\n info.headers.push({ name: checksumHeader, value: calculateCrc32cChecksum(chunk) });\n }\n\n const contentLength = Number(info.chunkEnd - info.chunkStart);\n if (chunk.length !== contentLength) {\n throw new Error(\n `Chunk size mismatch: expected ${contentLength} bytes, but read ${chunk.length} bytes from file`,\n );\n }\n\n const headers = Object.fromEntries(\n info.headers.map(({ name, value }) => [name.toLowerCase(), value]),\n );\n\n try {\n const {\n body: rawBody,\n statusCode,\n headers: responseHeaders,\n } = await request(info.uploadUrl, {\n dispatcher: this.httpClient,\n body: chunk,\n // We got headers only after we send\n // the whole body (in case of S3 PUT requests it's 5 MB).\n // It might be slow with a slow connection (or with SSH),\n // that's why we got big timeout here.\n headersTimeout: 60000,\n bodyTimeout: 60000,\n // Prevent connection reuse by setting \"Connection: close\" header.\n // This works around an issue with the backend's built-in S3 implementation\n // that caused HTTP/1.1 protocol lines to be included in the uploaded file content.\n reset: true,\n headers,\n method: info.method.toUpperCase() as Dispatcher.HttpMethod,\n });\n\n // always read the body for resources to be garbage collected.\n const body = await rawBody.text();\n checkStatusCodeOk(statusCode, body, responseHeaders, info);\n } catch (e: unknown) {\n if (e instanceof NetworkError) throw e;\n\n if (e instanceof BadRequestError) throw e;\n\n throw new Error(\n `partUpload: error ${JSON.stringify(e)} happened while trying to do part upload to the url ${info.uploadUrl}, headers: ${JSON.stringify(info.headers)}`,\n );\n }\n\n await this.updateProgress({ id, type }, BigInt(info.chunkEnd - info.chunkStart), options);\n }\n\n public async finalize(info: ResourceInfo, options?: RpcOptions) {\n const client = this.wire.get();\n\n if (client instanceof UploadClient) {\n await client.finalize({ resourceId: info.id }, addRTypeToMetadata(info.type, options));\n } else {\n await client.POST(\"/v1/upload/finalize\", {\n body: {\n resourceId: info.id.toString(),\n },\n headers: { ...createRTypeRoutingHeader(info.type) },\n });\n }\n }\n\n /** Calculates parts that need to be uploaded from the parts that were\n * already uploaded. */\n private partsToUpload(partsCount: bigint, uploadedParts: bigint[]): bigint[] {\n const toUpload: bigint[] = [];\n const uploaded = new Set(uploadedParts);\n\n for (let i = 1n; i <= partsCount; i++) {\n if (!uploaded.has(i)) toUpload.push(i);\n }\n\n return toUpload;\n }\n\n private async updateProgress(\n { id, type }: ResourceInfo,\n bytesProcessed: bigint,\n options?: RpcOptions,\n ): Promise<void> {\n const client = this.wire.get();\n\n if (client instanceof UploadClient) {\n await client.updateProgress(\n {\n resourceId: id,\n bytesProcessed,\n },\n addRTypeToMetadata(type, options),\n ).response;\n return;\n }\n\n await client.POST(\"/v1/upload/update-progress\", {\n body: {\n resourceId: id.toString(),\n bytesProcessed: bytesProcessed.toString(),\n },\n headers: { ...createRTypeRoutingHeader(type) },\n });\n return;\n }\n}\n\nasync function readFileChunk(path: string, chunkStart: bigint, chunkEnd: bigint): Promise<Buffer> {\n let f: fs.FileHandle | undefined;\n try {\n f = await fs.open(path);\n const len = Number(chunkEnd - chunkStart);\n const pos = Number(chunkStart);\n const b = Buffer.alloc(len);\n const bytesRead = await readBytesFromPosition(f, b, len, pos);\n\n return b.subarray(0, bytesRead);\n } catch (e: unknown) {\n if (e && typeof e === \"object\" && \"code\" in e && e.code == \"ENOENT\")\n throw new NoFileForUploading(`there is no file ${path} for uploading`);\n throw e;\n } finally {\n await f?.close();\n }\n}\n\n/** Read len bytes from a given position.\n * Without this, `FileHandle.read` can read less bytes than needed. */\nasync function readBytesFromPosition(f: fs.FileHandle, b: Buffer, len: number, position: number) {\n let bytesReadTotal = 0;\n while (bytesReadTotal < len) {\n const { bytesRead } = await f.read(\n b,\n bytesReadTotal,\n len - bytesReadTotal,\n position + bytesReadTotal,\n );\n if (bytesRead === 0) {\n throw new UnexpectedEOF(\"file ended earlier than expected.\");\n }\n bytesReadTotal += bytesRead;\n }\n\n return bytesReadTotal;\n}\n\nasync function checkExpectedMTime(path: string, expectedMTimeUnix: bigint) {\n const mTime = BigInt(Math.floor((await fs.stat(path)).mtimeMs / 1000));\n if (mTime > expectedMTimeUnix) {\n throw new MTimeError(`file was modified, expected mtime: ${expectedMTimeUnix}, got: ${mTime}.`);\n }\n}\n\nfunction checkStatusCodeOk(\n statusCode: number,\n body: string,\n headers: IncomingHttpHeaders,\n info: UploadAPI_GetPartURL_Response,\n) {\n if (statusCode == 400) {\n throw new BadRequestError(\n `response is not ok, status code: ${statusCode},` +\n ` body: ${body}, headers: ${JSON.stringify(headers)}, url: ${info.uploadUrl}`,\n );\n }\n\n if (statusCode != 200) {\n throw new NetworkError(\n `response is not ok, status code: ${statusCode},` +\n ` body: ${body}, headers: ${JSON.stringify(headers)}, url: ${info.uploadUrl}`,\n );\n }\n}\n\n/** Calculate CRC32C checksum of a buffer and return as base64 string */\nfunction calculateCrc32cChecksum(data: Buffer): string {\n const checksum = crc32c(data);\n // Convert to unsigned 32-bit integer and then to base64\n const buffer = Buffer.alloc(4);\n\n buffer.writeUInt32BE(checksum, 0);\n return buffer.toString(\"base64\");\n}\n"],"mappings":"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"}