@uploadista/core 0.0.2

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 (359) hide show
  1. package/.turbo/turbo-build.log +5 -0
  2. package/.turbo/turbo-check.log +231 -0
  3. package/.turbo/turbo-format.log +5 -0
  4. package/LICENSE +21 -0
  5. package/README.md +1120 -0
  6. package/dist/chunk-CUT6urMc.cjs +1 -0
  7. package/dist/debounce-C2SeqcxD.js +2 -0
  8. package/dist/debounce-C2SeqcxD.js.map +1 -0
  9. package/dist/debounce-LZK7yS7Z.cjs +1 -0
  10. package/dist/errors/index.cjs +1 -0
  11. package/dist/errors/index.d.cts +3 -0
  12. package/dist/errors/index.d.ts +3 -0
  13. package/dist/errors/index.d.ts.map +1 -0
  14. package/dist/errors/index.js +2 -0
  15. package/dist/errors/uploadista-error.d.ts +209 -0
  16. package/dist/errors/uploadista-error.d.ts.map +1 -0
  17. package/dist/errors/uploadista-error.js +322 -0
  18. package/dist/errors-8i_aMxOE.js +1 -0
  19. package/dist/errors-CRm1FHHT.cjs +0 -0
  20. package/dist/flow/edge.d.ts +47 -0
  21. package/dist/flow/edge.d.ts.map +1 -0
  22. package/dist/flow/edge.js +40 -0
  23. package/dist/flow/event.d.ts +206 -0
  24. package/dist/flow/event.d.ts.map +1 -0
  25. package/dist/flow/event.js +53 -0
  26. package/dist/flow/flow-server.d.ts +223 -0
  27. package/dist/flow/flow-server.d.ts.map +1 -0
  28. package/dist/flow/flow-server.js +614 -0
  29. package/dist/flow/flow.d.ts +238 -0
  30. package/dist/flow/flow.d.ts.map +1 -0
  31. package/dist/flow/flow.js +629 -0
  32. package/dist/flow/index.cjs +1 -0
  33. package/dist/flow/index.d.cts +6 -0
  34. package/dist/flow/index.d.ts +24 -0
  35. package/dist/flow/index.d.ts.map +1 -0
  36. package/dist/flow/index.js +24 -0
  37. package/dist/flow/node.d.ts +136 -0
  38. package/dist/flow/node.d.ts.map +1 -0
  39. package/dist/flow/node.js +153 -0
  40. package/dist/flow/nodes/index.d.ts +8 -0
  41. package/dist/flow/nodes/index.d.ts.map +1 -0
  42. package/dist/flow/nodes/index.js +7 -0
  43. package/dist/flow/nodes/input-node.d.ts +78 -0
  44. package/dist/flow/nodes/input-node.d.ts.map +1 -0
  45. package/dist/flow/nodes/input-node.js +233 -0
  46. package/dist/flow/nodes/storage-node.d.ts +67 -0
  47. package/dist/flow/nodes/storage-node.d.ts.map +1 -0
  48. package/dist/flow/nodes/storage-node.js +94 -0
  49. package/dist/flow/nodes/streaming-input-node.d.ts +69 -0
  50. package/dist/flow/nodes/streaming-input-node.d.ts.map +1 -0
  51. package/dist/flow/nodes/streaming-input-node.js +156 -0
  52. package/dist/flow/nodes/transform-node.d.ts +85 -0
  53. package/dist/flow/nodes/transform-node.d.ts.map +1 -0
  54. package/dist/flow/nodes/transform-node.js +107 -0
  55. package/dist/flow/parallel-scheduler.d.ts +175 -0
  56. package/dist/flow/parallel-scheduler.d.ts.map +1 -0
  57. package/dist/flow/parallel-scheduler.js +193 -0
  58. package/dist/flow/plugins/credential-provider.d.ts +47 -0
  59. package/dist/flow/plugins/credential-provider.d.ts.map +1 -0
  60. package/dist/flow/plugins/credential-provider.js +24 -0
  61. package/dist/flow/plugins/image-ai-plugin.d.ts +61 -0
  62. package/dist/flow/plugins/image-ai-plugin.d.ts.map +1 -0
  63. package/dist/flow/plugins/image-ai-plugin.js +21 -0
  64. package/dist/flow/plugins/image-plugin.d.ts +52 -0
  65. package/dist/flow/plugins/image-plugin.d.ts.map +1 -0
  66. package/dist/flow/plugins/image-plugin.js +22 -0
  67. package/dist/flow/plugins/types/describe-image-node.d.ts +16 -0
  68. package/dist/flow/plugins/types/describe-image-node.d.ts.map +1 -0
  69. package/dist/flow/plugins/types/describe-image-node.js +9 -0
  70. package/dist/flow/plugins/types/index.d.ts +9 -0
  71. package/dist/flow/plugins/types/index.d.ts.map +1 -0
  72. package/dist/flow/plugins/types/index.js +8 -0
  73. package/dist/flow/plugins/types/optimize-node.d.ts +20 -0
  74. package/dist/flow/plugins/types/optimize-node.d.ts.map +1 -0
  75. package/dist/flow/plugins/types/optimize-node.js +11 -0
  76. package/dist/flow/plugins/types/remove-background-node.d.ts +16 -0
  77. package/dist/flow/plugins/types/remove-background-node.d.ts.map +1 -0
  78. package/dist/flow/plugins/types/remove-background-node.js +9 -0
  79. package/dist/flow/plugins/types/resize-node.d.ts +21 -0
  80. package/dist/flow/plugins/types/resize-node.d.ts.map +1 -0
  81. package/dist/flow/plugins/types/resize-node.js +16 -0
  82. package/dist/flow/plugins/zip-plugin.d.ts +62 -0
  83. package/dist/flow/plugins/zip-plugin.d.ts.map +1 -0
  84. package/dist/flow/plugins/zip-plugin.js +21 -0
  85. package/dist/flow/typed-flow.d.ts +90 -0
  86. package/dist/flow/typed-flow.d.ts.map +1 -0
  87. package/dist/flow/typed-flow.js +59 -0
  88. package/dist/flow/types/flow-file.d.ts +45 -0
  89. package/dist/flow/types/flow-file.d.ts.map +1 -0
  90. package/dist/flow/types/flow-file.js +27 -0
  91. package/dist/flow/types/flow-job.d.ts +118 -0
  92. package/dist/flow/types/flow-job.d.ts.map +1 -0
  93. package/dist/flow/types/flow-job.js +11 -0
  94. package/dist/flow/types/flow-types.d.ts +321 -0
  95. package/dist/flow/types/flow-types.d.ts.map +1 -0
  96. package/dist/flow/types/flow-types.js +52 -0
  97. package/dist/flow/types/index.d.ts +4 -0
  98. package/dist/flow/types/index.d.ts.map +1 -0
  99. package/dist/flow/types/index.js +3 -0
  100. package/dist/flow/types/run-args.d.ts +38 -0
  101. package/dist/flow/types/run-args.d.ts.map +1 -0
  102. package/dist/flow/types/run-args.js +30 -0
  103. package/dist/flow/types/type-validator.d.ts +26 -0
  104. package/dist/flow/types/type-validator.d.ts.map +1 -0
  105. package/dist/flow/types/type-validator.js +134 -0
  106. package/dist/flow/utils/resolve-upload-metadata.d.ts +11 -0
  107. package/dist/flow/utils/resolve-upload-metadata.d.ts.map +1 -0
  108. package/dist/flow/utils/resolve-upload-metadata.js +28 -0
  109. package/dist/flow-2zXnEiWL.cjs +1 -0
  110. package/dist/flow-CRaKy7Vj.js +2 -0
  111. package/dist/flow-CRaKy7Vj.js.map +1 -0
  112. package/dist/generate-id-Dm-Vboxq.d.ts +34 -0
  113. package/dist/generate-id-Dm-Vboxq.d.ts.map +1 -0
  114. package/dist/generate-id-LjJRLD6N.d.cts +34 -0
  115. package/dist/generate-id-LjJRLD6N.d.cts.map +1 -0
  116. package/dist/generate-id-xHp_Z7Cl.cjs +1 -0
  117. package/dist/generate-id-yohS1ZDk.js +2 -0
  118. package/dist/generate-id-yohS1ZDk.js.map +1 -0
  119. package/dist/index-BO8GZlbD.d.cts +1040 -0
  120. package/dist/index-BO8GZlbD.d.cts.map +1 -0
  121. package/dist/index-BoGG5KAY.d.ts +1 -0
  122. package/dist/index-BtBZHVmz.d.cts +1 -0
  123. package/dist/index-D-CoVpkZ.d.ts +1004 -0
  124. package/dist/index-D-CoVpkZ.d.ts.map +1 -0
  125. package/dist/index.cjs +1 -0
  126. package/dist/index.d.cts +6 -0
  127. package/dist/index.d.ts +5 -0
  128. package/dist/index.d.ts.map +1 -0
  129. package/dist/index.js +5 -0
  130. package/dist/logger/logger.cjs +1 -0
  131. package/dist/logger/logger.d.cts +8 -0
  132. package/dist/logger/logger.d.cts.map +1 -0
  133. package/dist/logger/logger.d.ts +5 -0
  134. package/dist/logger/logger.d.ts.map +1 -0
  135. package/dist/logger/logger.js +10 -0
  136. package/dist/logger/logger.js.map +1 -0
  137. package/dist/semaphore-0ZwjVpyF.js +2 -0
  138. package/dist/semaphore-0ZwjVpyF.js.map +1 -0
  139. package/dist/semaphore-BHprIjFI.d.cts +37 -0
  140. package/dist/semaphore-BHprIjFI.d.cts.map +1 -0
  141. package/dist/semaphore-DThupBkc.d.ts +37 -0
  142. package/dist/semaphore-DThupBkc.d.ts.map +1 -0
  143. package/dist/semaphore-DVrONiAV.cjs +1 -0
  144. package/dist/stream-limiter-CoWKv39w.js +2 -0
  145. package/dist/stream-limiter-CoWKv39w.js.map +1 -0
  146. package/dist/stream-limiter-JgOwmkMa.cjs +1 -0
  147. package/dist/streams/multi-stream.cjs +1 -0
  148. package/dist/streams/multi-stream.d.cts +91 -0
  149. package/dist/streams/multi-stream.d.cts.map +1 -0
  150. package/dist/streams/multi-stream.d.ts +86 -0
  151. package/dist/streams/multi-stream.d.ts.map +1 -0
  152. package/dist/streams/multi-stream.js +149 -0
  153. package/dist/streams/multi-stream.js.map +1 -0
  154. package/dist/streams/stream-limiter.cjs +1 -0
  155. package/dist/streams/stream-limiter.d.cts +36 -0
  156. package/dist/streams/stream-limiter.d.cts.map +1 -0
  157. package/dist/streams/stream-limiter.d.ts +27 -0
  158. package/dist/streams/stream-limiter.d.ts.map +1 -0
  159. package/dist/streams/stream-limiter.js +49 -0
  160. package/dist/streams/stream-splitter.cjs +1 -0
  161. package/dist/streams/stream-splitter.d.cts +68 -0
  162. package/dist/streams/stream-splitter.d.cts.map +1 -0
  163. package/dist/streams/stream-splitter.d.ts +51 -0
  164. package/dist/streams/stream-splitter.d.ts.map +1 -0
  165. package/dist/streams/stream-splitter.js +175 -0
  166. package/dist/streams/stream-splitter.js.map +1 -0
  167. package/dist/types/data-store-registry.d.ts +13 -0
  168. package/dist/types/data-store-registry.d.ts.map +1 -0
  169. package/dist/types/data-store-registry.js +4 -0
  170. package/dist/types/data-store.d.ts +316 -0
  171. package/dist/types/data-store.d.ts.map +1 -0
  172. package/dist/types/data-store.js +157 -0
  173. package/dist/types/event-broadcaster.d.ts +28 -0
  174. package/dist/types/event-broadcaster.d.ts.map +1 -0
  175. package/dist/types/event-broadcaster.js +6 -0
  176. package/dist/types/event-emitter.d.ts +378 -0
  177. package/dist/types/event-emitter.d.ts.map +1 -0
  178. package/dist/types/event-emitter.js +223 -0
  179. package/dist/types/index.cjs +1 -0
  180. package/dist/types/index.d.cts +6 -0
  181. package/dist/types/index.d.ts +10 -0
  182. package/dist/types/index.d.ts.map +1 -0
  183. package/dist/types/index.js +9 -0
  184. package/dist/types/input-file.d.ts +104 -0
  185. package/dist/types/input-file.d.ts.map +1 -0
  186. package/dist/types/input-file.js +27 -0
  187. package/dist/types/kv-store.d.ts +281 -0
  188. package/dist/types/kv-store.d.ts.map +1 -0
  189. package/dist/types/kv-store.js +234 -0
  190. package/dist/types/middleware.d.ts +17 -0
  191. package/dist/types/middleware.d.ts.map +1 -0
  192. package/dist/types/middleware.js +21 -0
  193. package/dist/types/upload-event.d.ts +105 -0
  194. package/dist/types/upload-event.d.ts.map +1 -0
  195. package/dist/types/upload-event.js +71 -0
  196. package/dist/types/upload-file.d.ts +136 -0
  197. package/dist/types/upload-file.d.ts.map +1 -0
  198. package/dist/types/upload-file.js +34 -0
  199. package/dist/types/websocket.d.ts +144 -0
  200. package/dist/types/websocket.d.ts.map +1 -0
  201. package/dist/types/websocket.js +40 -0
  202. package/dist/types-BT-cvi7T.cjs +1 -0
  203. package/dist/types-DhU2j-XF.js +2 -0
  204. package/dist/types-DhU2j-XF.js.map +1 -0
  205. package/dist/upload/convert-to-stream.d.ts +38 -0
  206. package/dist/upload/convert-to-stream.d.ts.map +1 -0
  207. package/dist/upload/convert-to-stream.js +43 -0
  208. package/dist/upload/convert-upload-to-flow-file.d.ts +14 -0
  209. package/dist/upload/convert-upload-to-flow-file.d.ts.map +1 -0
  210. package/dist/upload/convert-upload-to-flow-file.js +21 -0
  211. package/dist/upload/create-upload.d.ts +68 -0
  212. package/dist/upload/create-upload.d.ts.map +1 -0
  213. package/dist/upload/create-upload.js +157 -0
  214. package/dist/upload/index.cjs +1 -0
  215. package/dist/upload/index.d.cts +6 -0
  216. package/dist/upload/index.d.ts +4 -0
  217. package/dist/upload/index.d.ts.map +1 -0
  218. package/dist/upload/index.js +3 -0
  219. package/dist/upload/mime.d.ts +24 -0
  220. package/dist/upload/mime.d.ts.map +1 -0
  221. package/dist/upload/mime.js +351 -0
  222. package/dist/upload/upload-chunk.d.ts +58 -0
  223. package/dist/upload/upload-chunk.d.ts.map +1 -0
  224. package/dist/upload/upload-chunk.js +277 -0
  225. package/dist/upload/upload-server.d.ts +221 -0
  226. package/dist/upload/upload-server.d.ts.map +1 -0
  227. package/dist/upload/upload-server.js +181 -0
  228. package/dist/upload/upload-strategy-negotiator.d.ts +148 -0
  229. package/dist/upload/upload-strategy-negotiator.d.ts.map +1 -0
  230. package/dist/upload/upload-strategy-negotiator.js +217 -0
  231. package/dist/upload/upload-url.d.ts +68 -0
  232. package/dist/upload/upload-url.d.ts.map +1 -0
  233. package/dist/upload/upload-url.js +142 -0
  234. package/dist/upload/write-to-store.d.ts +77 -0
  235. package/dist/upload/write-to-store.d.ts.map +1 -0
  236. package/dist/upload/write-to-store.js +147 -0
  237. package/dist/upload-DLuICjpP.cjs +1 -0
  238. package/dist/upload-DaXO34dE.js +2 -0
  239. package/dist/upload-DaXO34dE.js.map +1 -0
  240. package/dist/uploadista-error-BB-Wdiz9.cjs +22 -0
  241. package/dist/uploadista-error-BVsVxqvz.js +23 -0
  242. package/dist/uploadista-error-BVsVxqvz.js.map +1 -0
  243. package/dist/uploadista-error-CwxYs4EB.d.ts +52 -0
  244. package/dist/uploadista-error-CwxYs4EB.d.ts.map +1 -0
  245. package/dist/uploadista-error-kKlhLRhY.d.cts +52 -0
  246. package/dist/uploadista-error-kKlhLRhY.d.cts.map +1 -0
  247. package/dist/utils/checksum.d.ts +22 -0
  248. package/dist/utils/checksum.d.ts.map +1 -0
  249. package/dist/utils/checksum.js +49 -0
  250. package/dist/utils/debounce.cjs +1 -0
  251. package/dist/utils/debounce.d.cts +38 -0
  252. package/dist/utils/debounce.d.cts.map +1 -0
  253. package/dist/utils/debounce.d.ts +36 -0
  254. package/dist/utils/debounce.d.ts.map +1 -0
  255. package/dist/utils/debounce.js +73 -0
  256. package/dist/utils/generate-id.cjs +1 -0
  257. package/dist/utils/generate-id.d.cts +2 -0
  258. package/dist/utils/generate-id.d.ts +32 -0
  259. package/dist/utils/generate-id.d.ts.map +1 -0
  260. package/dist/utils/generate-id.js +23 -0
  261. package/dist/utils/md5.cjs +1 -0
  262. package/dist/utils/md5.d.cts +73 -0
  263. package/dist/utils/md5.d.cts.map +1 -0
  264. package/dist/utils/md5.d.ts +71 -0
  265. package/dist/utils/md5.d.ts.map +1 -0
  266. package/dist/utils/md5.js +417 -0
  267. package/dist/utils/md5.js.map +1 -0
  268. package/dist/utils/once.cjs +1 -0
  269. package/dist/utils/once.d.cts +25 -0
  270. package/dist/utils/once.d.cts.map +1 -0
  271. package/dist/utils/once.d.ts +21 -0
  272. package/dist/utils/once.d.ts.map +1 -0
  273. package/dist/utils/once.js +54 -0
  274. package/dist/utils/once.js.map +1 -0
  275. package/dist/utils/semaphore.cjs +1 -0
  276. package/dist/utils/semaphore.d.cts +3 -0
  277. package/dist/utils/semaphore.d.ts +78 -0
  278. package/dist/utils/semaphore.d.ts.map +1 -0
  279. package/dist/utils/semaphore.js +134 -0
  280. package/dist/utils/throttle.cjs +1 -0
  281. package/dist/utils/throttle.d.cts +24 -0
  282. package/dist/utils/throttle.d.cts.map +1 -0
  283. package/dist/utils/throttle.d.ts +18 -0
  284. package/dist/utils/throttle.d.ts.map +1 -0
  285. package/dist/utils/throttle.js +20 -0
  286. package/dist/utils/throttle.js.map +1 -0
  287. package/docs/PARALLEL_EXECUTION.md +206 -0
  288. package/docs/PARALLEL_EXECUTION_QUICKSTART.md +142 -0
  289. package/docs/PARALLEL_EXECUTION_REFACTOR.md +184 -0
  290. package/package.json +80 -0
  291. package/src/errors/__tests__/uploadista-error.test.ts +251 -0
  292. package/src/errors/index.ts +2 -0
  293. package/src/errors/uploadista-error.ts +394 -0
  294. package/src/flow/README.md +352 -0
  295. package/src/flow/edge.test.ts +146 -0
  296. package/src/flow/edge.ts +60 -0
  297. package/src/flow/event.ts +229 -0
  298. package/src/flow/flow-server.ts +1089 -0
  299. package/src/flow/flow.ts +1050 -0
  300. package/src/flow/index.ts +28 -0
  301. package/src/flow/node.ts +249 -0
  302. package/src/flow/nodes/index.ts +8 -0
  303. package/src/flow/nodes/input-node.ts +296 -0
  304. package/src/flow/nodes/storage-node.ts +128 -0
  305. package/src/flow/nodes/transform-node.ts +154 -0
  306. package/src/flow/parallel-scheduler.ts +259 -0
  307. package/src/flow/plugins/credential-provider.ts +48 -0
  308. package/src/flow/plugins/image-ai-plugin.ts +66 -0
  309. package/src/flow/plugins/image-plugin.ts +60 -0
  310. package/src/flow/plugins/types/describe-image-node.ts +16 -0
  311. package/src/flow/plugins/types/index.ts +9 -0
  312. package/src/flow/plugins/types/optimize-node.ts +18 -0
  313. package/src/flow/plugins/types/remove-background-node.ts +18 -0
  314. package/src/flow/plugins/types/resize-node.ts +26 -0
  315. package/src/flow/plugins/zip-plugin.ts +69 -0
  316. package/src/flow/typed-flow.ts +279 -0
  317. package/src/flow/types/flow-file.ts +51 -0
  318. package/src/flow/types/flow-job.ts +138 -0
  319. package/src/flow/types/flow-types.ts +353 -0
  320. package/src/flow/types/index.ts +6 -0
  321. package/src/flow/types/run-args.ts +40 -0
  322. package/src/flow/types/type-validator.ts +204 -0
  323. package/src/flow/utils/resolve-upload-metadata.ts +48 -0
  324. package/src/index.ts +5 -0
  325. package/src/logger/logger.ts +14 -0
  326. package/src/streams/stream-limiter.test.ts +150 -0
  327. package/src/streams/stream-limiter.ts +75 -0
  328. package/src/types/data-store.ts +427 -0
  329. package/src/types/event-broadcaster.ts +39 -0
  330. package/src/types/event-emitter.ts +349 -0
  331. package/src/types/index.ts +9 -0
  332. package/src/types/input-file.ts +107 -0
  333. package/src/types/kv-store.ts +375 -0
  334. package/src/types/middleware.ts +54 -0
  335. package/src/types/upload-event.ts +75 -0
  336. package/src/types/upload-file.ts +139 -0
  337. package/src/types/websocket.ts +65 -0
  338. package/src/upload/convert-to-stream.ts +48 -0
  339. package/src/upload/create-upload.ts +214 -0
  340. package/src/upload/index.ts +3 -0
  341. package/src/upload/mime.ts +436 -0
  342. package/src/upload/upload-chunk.ts +364 -0
  343. package/src/upload/upload-server.ts +390 -0
  344. package/src/upload/upload-strategy-negotiator.ts +316 -0
  345. package/src/upload/upload-url.ts +173 -0
  346. package/src/upload/write-to-store.ts +211 -0
  347. package/src/utils/checksum.ts +61 -0
  348. package/src/utils/debounce.test.ts +126 -0
  349. package/src/utils/debounce.ts +89 -0
  350. package/src/utils/generate-id.ts +35 -0
  351. package/src/utils/md5.ts +475 -0
  352. package/src/utils/once.test.ts +83 -0
  353. package/src/utils/once.ts +63 -0
  354. package/src/utils/throttle.test.ts +101 -0
  355. package/src/utils/throttle.ts +29 -0
  356. package/tsconfig.json +20 -0
  357. package/tsconfig.tsbuildinfo +1 -0
  358. package/tsdown.config.ts +25 -0
  359. package/vitest.config.ts +15 -0
@@ -0,0 +1,316 @@
1
+ import { Context, Effect, Layer, type Stream } from "effect";
2
+ import { UploadistaError } from "../errors/uploadista-error";
3
+ import type { UploadFileKVStore } from "./kv-store";
4
+ import type { UploadFile } from "./upload-file";
5
+ /**
6
+ * Options for writing data to a DataStore.
7
+ *
8
+ * @property file_id - Unique identifier for the file being written
9
+ * @property stream - Stream of byte chunks to write to storage
10
+ * @property offset - Byte offset where writing should begin (for resumable uploads)
11
+ */
12
+ export type DataStoreWriteOptions = {
13
+ file_id: string;
14
+ stream: Stream.Stream<Uint8Array, UploadistaError>;
15
+ offset: number;
16
+ };
17
+ /**
18
+ * Upload strategy type indicating how chunks are uploaded.
19
+ *
20
+ * - `single`: Upload file in a single request (traditional upload)
21
+ * - `parallel`: Upload file chunks in parallel (for large files)
22
+ */
23
+ export type UploadStrategy = "single" | "parallel";
24
+ /**
25
+ * Capabilities and constraints of a DataStore implementation.
26
+ *
27
+ * This type describes what features a storage backend supports and what
28
+ * limitations it has. Use this to determine the optimal upload strategy
29
+ * and validate client requests.
30
+ *
31
+ * @property supportsParallelUploads - Can upload chunks in parallel (e.g., S3 multipart)
32
+ * @property supportsConcatenation - Can concatenate multiple uploads into one file
33
+ * @property supportsDeferredLength - Can start upload without knowing final size
34
+ * @property supportsResumableUploads - Can resume interrupted uploads from last offset
35
+ * @property supportsTransactionalUploads - Guarantees atomic upload success/failure
36
+ * @property maxConcurrentUploads - Maximum parallel upload parts (if parallel supported)
37
+ * @property minChunkSize - Minimum size in bytes for each chunk (except last)
38
+ * @property maxChunkSize - Maximum size in bytes for each chunk
39
+ * @property maxParts - Maximum number of parts in a multipart upload
40
+ * @property optimalChunkSize - Recommended chunk size for best performance
41
+ * @property requiresOrderedChunks - Must receive chunks in sequential order
42
+ * @property requiresMimeTypeValidation - Validates file MIME type matches declaration
43
+ * @property maxValidationSize - Maximum file size for MIME type validation
44
+ *
45
+ * @example
46
+ * ```typescript
47
+ * const capabilities = dataStore.getCapabilities();
48
+ *
49
+ * if (capabilities.supportsParallelUploads && fileSize > 10_000_000) {
50
+ * // Use parallel upload for large files
51
+ * const chunkSize = capabilities.optimalChunkSize || 5_242_880; // 5MB default
52
+ * uploadInParallel(file, chunkSize);
53
+ * } else {
54
+ * // Use single upload
55
+ * uploadAsSingleChunk(file);
56
+ * }
57
+ * ```
58
+ */
59
+ export type DataStoreCapabilities = {
60
+ supportsParallelUploads: boolean;
61
+ supportsConcatenation: boolean;
62
+ supportsDeferredLength: boolean;
63
+ supportsResumableUploads: boolean;
64
+ supportsTransactionalUploads: boolean;
65
+ maxConcurrentUploads?: number;
66
+ minChunkSize?: number;
67
+ maxChunkSize?: number;
68
+ maxParts?: number;
69
+ optimalChunkSize?: number;
70
+ requiresOrderedChunks: boolean;
71
+ requiresMimeTypeValidation?: boolean;
72
+ maxValidationSize?: number;
73
+ };
74
+ /**
75
+ * Core interface for all storage backend implementations.
76
+ *
77
+ * DataStore abstracts file storage operations across different backends
78
+ * (S3, Azure Blob, GCS, local filesystem, etc.). All storage adapters
79
+ * must implement this interface.
80
+ *
81
+ * @template TData - The data type stored (typically UploadFile)
82
+ *
83
+ * @property bucket - Optional storage bucket or container name
84
+ * @property path - Optional base path prefix for all stored files
85
+ * @property create - Creates a new file record in storage
86
+ * @property remove - Deletes a file from storage
87
+ * @property read - Reads complete file contents as bytes
88
+ * @property write - Writes data stream to storage at specified offset
89
+ * @property deleteExpired - Optional cleanup of expired files
90
+ * @property getCapabilities - Returns storage backend capabilities
91
+ * @property validateUploadStrategy - Validates if strategy is supported
92
+ *
93
+ * @example
94
+ * ```typescript
95
+ * // Implement a custom DataStore
96
+ * const myDataStore: DataStore<UploadFile> = {
97
+ * bucket: "my-uploads",
98
+ * path: "files/",
99
+ *
100
+ * create: (file) => Effect.gen(function* () {
101
+ * // Store file metadata
102
+ * yield* saveMetadata(file);
103
+ * return file;
104
+ * }),
105
+ *
106
+ * write: ({ file_id, stream, offset }, { onProgress }) => Effect.gen(function* () {
107
+ * // Write chunks to storage
108
+ * let bytesWritten = offset;
109
+ * yield* Stream.runForEach(stream, (chunk) => Effect.sync(() => {
110
+ * writeChunk(file_id, chunk, bytesWritten);
111
+ * bytesWritten += chunk.byteLength;
112
+ * onProgress?.(chunk.byteLength);
113
+ * }));
114
+ * return bytesWritten;
115
+ * }),
116
+ *
117
+ * read: (file_id) => Effect.gen(function* () {
118
+ * // Read complete file
119
+ * const data = yield* readFromStorage(file_id);
120
+ * return data;
121
+ * }),
122
+ *
123
+ * remove: (file_id) => Effect.gen(function* () {
124
+ * yield* deleteFromStorage(file_id);
125
+ * }),
126
+ *
127
+ * getCapabilities: () => ({
128
+ * supportsParallelUploads: true,
129
+ * supportsConcatenation: false,
130
+ * supportsDeferredLength: true,
131
+ * supportsResumableUploads: true,
132
+ * supportsTransactionalUploads: false,
133
+ * maxConcurrentUploads: 10,
134
+ * optimalChunkSize: 5_242_880, // 5MB
135
+ * requiresOrderedChunks: false,
136
+ * }),
137
+ *
138
+ * validateUploadStrategy: (strategy) =>
139
+ * Effect.succeed(strategy === "parallel" || strategy === "single"),
140
+ * };
141
+ * ```
142
+ */
143
+ export type DataStore<TData = unknown> = {
144
+ readonly bucket?: string;
145
+ readonly path?: string;
146
+ readonly create: (file: TData) => Effect.Effect<TData, UploadistaError>;
147
+ readonly remove: (file_id: string) => Effect.Effect<void, UploadistaError>;
148
+ readonly read: (file_id: string) => Effect.Effect<Uint8Array, UploadistaError>;
149
+ readonly write: (options: DataStoreWriteOptions, dependencies: {
150
+ onProgress?: (chunkSize: number) => void;
151
+ }) => Effect.Effect<number, UploadistaError>;
152
+ readonly deleteExpired?: Effect.Effect<number, UploadistaError>;
153
+ readonly getCapabilities: () => DataStoreCapabilities;
154
+ readonly validateUploadStrategy: (strategy: UploadStrategy) => Effect.Effect<boolean, never>;
155
+ };
156
+ declare const UploadFileDataStore_base: Context.TagClass<UploadFileDataStore, "UploadFileDataStore", DataStore<UploadFile>>;
157
+ /**
158
+ * Effect-TS context tag for UploadFile DataStore.
159
+ *
160
+ * Use this tag to access the primary DataStore in an Effect context.
161
+ * This is the standard storage backend for uploaded files.
162
+ *
163
+ * @example
164
+ * ```typescript
165
+ * const uploadEffect = Effect.gen(function* () {
166
+ * const dataStore = yield* UploadFileDataStore;
167
+ * const file = yield* dataStore.create(uploadFile);
168
+ * return file;
169
+ * });
170
+ * ```
171
+ */
172
+ export declare class UploadFileDataStore extends UploadFileDataStore_base {
173
+ }
174
+ declare const BufferedUploadFileDataStore_base: Context.TagClass<BufferedUploadFileDataStore, "BufferedUploadFileDataStore", DataStore<UploadFile>>;
175
+ /**
176
+ * Effect-TS context tag for buffered/temporary DataStore.
177
+ *
178
+ * This is an optional storage backend used for temporary or intermediate files
179
+ * during flow processing. Not all implementations provide a buffered store.
180
+ *
181
+ * @example
182
+ * ```typescript
183
+ * const processEffect = Effect.gen(function* () {
184
+ * const bufferedStore = yield* BufferedUploadFileDataStore;
185
+ * // Store intermediate processing results
186
+ * const tempFile = yield* bufferedStore.create(intermediateFile);
187
+ * return tempFile;
188
+ * });
189
+ * ```
190
+ */
191
+ export declare class BufferedUploadFileDataStore extends BufferedUploadFileDataStore_base {
192
+ }
193
+ /**
194
+ * Service interface for managing multiple DataStore instances.
195
+ *
196
+ * This allows routing files to different storage backends based on
197
+ * storageId (e.g., different S3 buckets, Azure containers, or storage tiers).
198
+ *
199
+ * @property getDataStore - Retrieves the appropriate DataStore for a given storage ID
200
+ * @property bufferedDataStore - Optional temporary storage for intermediate files
201
+ */
202
+ export type UploadFileDataStoresShape = {
203
+ getDataStore: (storageId: string, clientId: string | null) => Effect.Effect<DataStore<UploadFile>, UploadistaError>;
204
+ bufferedDataStore: Effect.Effect<DataStore<UploadFile> | undefined, UploadistaError>;
205
+ };
206
+ declare const UploadFileDataStores_base: Context.TagClass<UploadFileDataStores, "UploadFileDataStores", UploadFileDataStoresShape>;
207
+ /**
208
+ * Effect-TS context tag for the DataStore routing service.
209
+ *
210
+ * Provides access to multiple DataStore instances with routing logic.
211
+ *
212
+ * @example
213
+ * ```typescript
214
+ * const uploadEffect = Effect.gen(function* () {
215
+ * const dataStores = yield* UploadFileDataStores;
216
+ * // Route to specific storage based on storageId
217
+ * const dataStore = yield* dataStores.getDataStore("s3-production", clientId);
218
+ * const file = yield* dataStore.create(uploadFile);
219
+ * return file;
220
+ * });
221
+ * ```
222
+ */
223
+ export declare class UploadFileDataStores extends UploadFileDataStores_base {
224
+ }
225
+ /**
226
+ * Simplified DataStore configuration for easy setup.
227
+ *
228
+ * This type allows flexible configuration:
229
+ * - Single DataStore instance
230
+ * - Multiple named stores with routing
231
+ * - Effect that resolves to a DataStore
232
+ * - Pre-built Effect Layer
233
+ *
234
+ * @example
235
+ * ```typescript
236
+ * // Single store
237
+ * const config: DataStoreConfig = s3DataStore;
238
+ *
239
+ * // Multiple stores with routing
240
+ * const config: DataStoreConfig = {
241
+ * stores: {
242
+ * "s3-prod": s3ProdStore,
243
+ * "s3-dev": s3DevStore,
244
+ * "local": localFileStore,
245
+ * },
246
+ * default: "s3-prod"
247
+ * };
248
+ *
249
+ * // Effect that creates a store
250
+ * const config: DataStoreConfig = Effect.gen(function* () {
251
+ * const kvStore = yield* UploadFileKVStore;
252
+ * return createS3Store(kvStore);
253
+ * });
254
+ *
255
+ * // Pre-built Layer
256
+ * const config: DataStoreConfig = Layer.succeed(UploadFileDataStores, {...});
257
+ * ```
258
+ */
259
+ export type DataStoreConfig = DataStore<UploadFile> | Effect.Effect<DataStore<UploadFile>, never, UploadFileKVStore> | {
260
+ stores: Record<string, DataStore<UploadFile> | Effect.Effect<DataStore<UploadFile>, never, UploadFileKVStore>>;
261
+ default?: string;
262
+ } | Layer.Layer<UploadFileDataStores, never, UploadFileKVStore>;
263
+ /**
264
+ * Type guard to check if a value is a DataStore instance.
265
+ *
266
+ * @param config - The value to check
267
+ * @returns True if the value is a DataStore
268
+ *
269
+ * @example
270
+ * ```typescript
271
+ * if (isDataStore(config)) {
272
+ * const capabilities = config.getCapabilities();
273
+ * }
274
+ * ```
275
+ */
276
+ export declare const isDataStore: (config: DataStoreConfig) => config is DataStore<UploadFile>;
277
+ /**
278
+ * Creates an Effect Layer from simplified DataStoreConfig.
279
+ *
280
+ * This function converts any DataStoreConfig format into a proper Effect Layer
281
+ * that can be provided to the UploadFileDataStores context tag.
282
+ *
283
+ * It handles:
284
+ * - Single DataStore: Wraps in a Layer that always returns that store
285
+ * - Multiple stores: Creates routing logic with optional default
286
+ * - Effect<DataStore>: Executes the Effect and wraps the result
287
+ * - Layer: Returns as-is
288
+ *
289
+ * @param config - The DataStore configuration
290
+ * @returns A Layer that provides UploadFileDataStores service
291
+ *
292
+ * @example
293
+ * ```typescript
294
+ * // Create from single store
295
+ * const layer = await createDataStoreLayer(s3DataStore);
296
+ *
297
+ * // Create from multiple stores
298
+ * const layer = await createDataStoreLayer({
299
+ * stores: {
300
+ * "production": s3Store,
301
+ * "development": localStore,
302
+ * },
303
+ * default: "development"
304
+ * });
305
+ *
306
+ * // Use the layer
307
+ * const program = Effect.gen(function* () {
308
+ * const stores = yield* UploadFileDataStores;
309
+ * const store = yield* stores.getDataStore("production", null);
310
+ * return store;
311
+ * }).pipe(Effect.provide(layer));
312
+ * ```
313
+ */
314
+ export declare const createDataStoreLayer: (config: DataStoreConfig) => Promise<Layer.Layer<UploadFileDataStores, never, UploadFileKVStore>>;
315
+ export {};
316
+ //# sourceMappingURL=data-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-store.d.ts","sourceRoot":"","sources":["../../src/types/data-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,157 @@
1
+ import { Context, Effect, Layer } from "effect";
2
+ import { UploadistaError } from "../errors/uploadista-error";
3
+ /**
4
+ * Effect-TS context tag for UploadFile DataStore.
5
+ *
6
+ * Use this tag to access the primary DataStore in an Effect context.
7
+ * This is the standard storage backend for uploaded files.
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * const uploadEffect = Effect.gen(function* () {
12
+ * const dataStore = yield* UploadFileDataStore;
13
+ * const file = yield* dataStore.create(uploadFile);
14
+ * return file;
15
+ * });
16
+ * ```
17
+ */
18
+ export class UploadFileDataStore extends Context.Tag("UploadFileDataStore")() {
19
+ }
20
+ /**
21
+ * Effect-TS context tag for buffered/temporary DataStore.
22
+ *
23
+ * This is an optional storage backend used for temporary or intermediate files
24
+ * during flow processing. Not all implementations provide a buffered store.
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * const processEffect = Effect.gen(function* () {
29
+ * const bufferedStore = yield* BufferedUploadFileDataStore;
30
+ * // Store intermediate processing results
31
+ * const tempFile = yield* bufferedStore.create(intermediateFile);
32
+ * return tempFile;
33
+ * });
34
+ * ```
35
+ */
36
+ export class BufferedUploadFileDataStore extends Context.Tag("BufferedUploadFileDataStore")() {
37
+ }
38
+ /**
39
+ * Effect-TS context tag for the DataStore routing service.
40
+ *
41
+ * Provides access to multiple DataStore instances with routing logic.
42
+ *
43
+ * @example
44
+ * ```typescript
45
+ * const uploadEffect = Effect.gen(function* () {
46
+ * const dataStores = yield* UploadFileDataStores;
47
+ * // Route to specific storage based on storageId
48
+ * const dataStore = yield* dataStores.getDataStore("s3-production", clientId);
49
+ * const file = yield* dataStore.create(uploadFile);
50
+ * return file;
51
+ * });
52
+ * ```
53
+ */
54
+ export class UploadFileDataStores extends Context.Tag("UploadFileDataStores")() {
55
+ }
56
+ /**
57
+ * Type guard to check if a value is a DataStore instance.
58
+ *
59
+ * @param config - The value to check
60
+ * @returns True if the value is a DataStore
61
+ *
62
+ * @example
63
+ * ```typescript
64
+ * if (isDataStore(config)) {
65
+ * const capabilities = config.getCapabilities();
66
+ * }
67
+ * ```
68
+ */
69
+ export const isDataStore = (config) => {
70
+ return "create" in config && "write" in config;
71
+ };
72
+ /**
73
+ * Creates an Effect Layer from simplified DataStoreConfig.
74
+ *
75
+ * This function converts any DataStoreConfig format into a proper Effect Layer
76
+ * that can be provided to the UploadFileDataStores context tag.
77
+ *
78
+ * It handles:
79
+ * - Single DataStore: Wraps in a Layer that always returns that store
80
+ * - Multiple stores: Creates routing logic with optional default
81
+ * - Effect<DataStore>: Executes the Effect and wraps the result
82
+ * - Layer: Returns as-is
83
+ *
84
+ * @param config - The DataStore configuration
85
+ * @returns A Layer that provides UploadFileDataStores service
86
+ *
87
+ * @example
88
+ * ```typescript
89
+ * // Create from single store
90
+ * const layer = await createDataStoreLayer(s3DataStore);
91
+ *
92
+ * // Create from multiple stores
93
+ * const layer = await createDataStoreLayer({
94
+ * stores: {
95
+ * "production": s3Store,
96
+ * "development": localStore,
97
+ * },
98
+ * default: "development"
99
+ * });
100
+ *
101
+ * // Use the layer
102
+ * const program = Effect.gen(function* () {
103
+ * const stores = yield* UploadFileDataStores;
104
+ * const store = yield* stores.getDataStore("production", null);
105
+ * return store;
106
+ * }).pipe(Effect.provide(layer));
107
+ * ```
108
+ */
109
+ export const createDataStoreLayer = async (config) => {
110
+ // Already a Layer, return as-is
111
+ if (Layer.isLayer(config)) {
112
+ return config;
113
+ }
114
+ // Check if it's an Effect
115
+ if (Effect.isEffect(config)) {
116
+ return Layer.effect(UploadFileDataStores, Effect.gen(function* () {
117
+ const dataStore = config;
118
+ const resolvedStore = yield* dataStore;
119
+ return {
120
+ getDataStore: (_storageId) => Effect.succeed(resolvedStore),
121
+ bufferedDataStore: Effect.succeed(undefined),
122
+ };
123
+ }));
124
+ }
125
+ // Single store (most common case)
126
+ if (isDataStore(config)) {
127
+ const store = config;
128
+ return Layer.succeed(UploadFileDataStores, {
129
+ getDataStore: (_storageId) => Effect.succeed(store),
130
+ bufferedDataStore: Effect.succeed(undefined),
131
+ });
132
+ }
133
+ // Multiple stores with routing
134
+ const multiConfig = config;
135
+ const defaultKey = multiConfig.default || Object.keys(multiConfig.stores)[0];
136
+ // Resolve any Effects in the stores
137
+ const resolvedStores = {};
138
+ for (const [key, storeOrEffect] of Object.entries(multiConfig.stores)) {
139
+ if ("pipe" in storeOrEffect && !("create" in storeOrEffect)) {
140
+ resolvedStores[key] = await Effect.runPromise(storeOrEffect);
141
+ }
142
+ else {
143
+ resolvedStores[key] = storeOrEffect;
144
+ }
145
+ }
146
+ return Layer.succeed(UploadFileDataStores, {
147
+ getDataStore: (storageId) => {
148
+ const store = resolvedStores[storageId] ||
149
+ (defaultKey ? resolvedStores[defaultKey] : undefined);
150
+ if (store) {
151
+ return Effect.succeed(store);
152
+ }
153
+ return Effect.fail(UploadistaError.fromCode("FILE_NOT_FOUND"));
154
+ },
155
+ bufferedDataStore: Effect.succeed(undefined),
156
+ });
157
+ };
@@ -0,0 +1,28 @@
1
+ import { Context, type Effect } from "effect";
2
+ import type { UploadistaError } from "../errors";
3
+ /**
4
+ * Event broadcaster interface for pub/sub messaging across distributed instances.
5
+ * Used by WebSocketManager to broadcast upload events to all connected instances.
6
+ */
7
+ export interface EventBroadcaster {
8
+ /**
9
+ * Publish a message to a channel
10
+ */
11
+ readonly publish: (channel: string, message: string) => Effect.Effect<void, UploadistaError>;
12
+ /**
13
+ * Subscribe to messages on a channel
14
+ */
15
+ readonly subscribe: (channel: string, handler: (message: string) => void) => Effect.Effect<void, UploadistaError>;
16
+ /**
17
+ * Unsubscribe from a channel (optional - not all implementations may support)
18
+ */
19
+ readonly unsubscribe?: (channel: string) => Effect.Effect<void, UploadistaError>;
20
+ }
21
+ declare const EventBroadcasterService_base: Context.TagClass<EventBroadcasterService, "EventBroadcaster", EventBroadcaster>;
22
+ /**
23
+ * Context tag for EventBroadcaster service
24
+ */
25
+ export declare class EventBroadcasterService extends EventBroadcasterService_base {
26
+ }
27
+ export {};
28
+ //# sourceMappingURL=event-broadcaster.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-broadcaster.d.ts","sourceRoot":"","sources":["../../src/types/event-broadcaster.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEjD;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,CAChB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,KACZ,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;IAE1C;;OAEG;IACH,QAAQ,CAAC,SAAS,EAAE,CAClB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,KAC/B,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;IAE1C;;OAEG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,CACrB,OAAO,EAAE,MAAM,KACZ,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;CAC3C;;AAED;;GAEG;AACH,qBAAa,uBAAwB,SAAQ,4BAG1C;CAAG"}
@@ -0,0 +1,6 @@
1
+ import { Context } from "effect";
2
+ /**
3
+ * Context tag for EventBroadcaster service
4
+ */
5
+ export class EventBroadcasterService extends Context.Tag("EventBroadcaster")() {
6
+ }