@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,349 @@
1
+ import { Context, Effect, Layer } from "effect";
2
+ import type { UploadistaError } from "../errors";
3
+ import type { FlowEvent } from "../flow/event";
4
+ import type { UploadEvent } from "./upload-event";
5
+ import type { WebSocketConnection } from "./websocket";
6
+
7
+ /**
8
+ * Base event emitter interface for raw string message broadcasting.
9
+ *
10
+ * This is the low-level interface that event broadcasting implementations
11
+ * (WebSocket, Server-Sent Events, etc.) implement. It emits raw string messages
12
+ * without type safety or serialization.
13
+ *
14
+ * @property subscribe - Registers a WebSocket connection to receive events for a key
15
+ * @property unsubscribe - Removes subscription for a key
16
+ * @property emit - Broadcasts a string message to all subscribers of a key
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * // Implement BaseEventEmitter with WebSocket broadcast
21
+ * const websocketEmitter: BaseEventEmitter = {
22
+ * subscribe: (key, connection) => Effect.sync(() => {
23
+ * connections.set(key, [...(connections.get(key) || []), connection]);
24
+ * }),
25
+ *
26
+ * unsubscribe: (key) => Effect.sync(() => {
27
+ * connections.delete(key);
28
+ * }),
29
+ *
30
+ * emit: (key, event) => Effect.sync(() => {
31
+ * const subs = connections.get(key) || [];
32
+ * subs.forEach(conn => conn.send(event));
33
+ * })
34
+ * };
35
+ * ```
36
+ */
37
+ export interface BaseEventEmitter {
38
+ readonly subscribe: (
39
+ key: string,
40
+ connection: WebSocketConnection,
41
+ ) => Effect.Effect<void, UploadistaError>;
42
+ readonly unsubscribe: (key: string) => Effect.Effect<void, UploadistaError>;
43
+ readonly emit: (
44
+ key: string,
45
+ event: string,
46
+ ) => Effect.Effect<void, UploadistaError>;
47
+ }
48
+
49
+ /**
50
+ * Type-safe event emitter interface with automatic serialization.
51
+ *
52
+ * This wraps a BaseEventEmitter and handles event serialization to JSON messages,
53
+ * providing type safety for events and ensuring consistent message format.
54
+ *
55
+ * @template TEvent - The type of events emitted by this emitter
56
+ *
57
+ * @property subscribe - Registers a WebSocket connection to receive typed events
58
+ * @property unsubscribe - Removes subscription
59
+ * @property emit - Serializes and broadcasts a typed event
60
+ *
61
+ * @example
62
+ * ```typescript
63
+ * // Use a typed event emitter
64
+ * const uploadEmitter: EventEmitter<UploadEvent> = new TypedEventEmitter(
65
+ * baseEmitter,
66
+ * (event) => JSON.stringify({ type: 'upload', payload: event })
67
+ * );
68
+ *
69
+ * // Emit type-safe events
70
+ * const program = Effect.gen(function* () {
71
+ * const event: UploadEvent = {
72
+ * uploadId: "upload123",
73
+ * type: "progress",
74
+ * offset: 1024,
75
+ * size: 2048
76
+ * };
77
+ *
78
+ * // Automatic serialization
79
+ * yield* uploadEmitter.emit("upload123", event);
80
+ * });
81
+ * ```
82
+ */
83
+ export type EventEmitter<TEvent> = {
84
+ readonly subscribe: (
85
+ key: string,
86
+ connection: WebSocketConnection,
87
+ ) => Effect.Effect<void, UploadistaError>;
88
+ readonly unsubscribe: (key: string) => Effect.Effect<void, UploadistaError>;
89
+ readonly emit: (
90
+ key: string,
91
+ event: TEvent,
92
+ ) => Effect.Effect<void, UploadistaError>;
93
+ };
94
+
95
+ /**
96
+ * Typed wrapper class that adds event serialization to a BaseEventEmitter.
97
+ *
98
+ * This class implements the EventEmitter interface by wrapping a BaseEventEmitter
99
+ * and handling serialization for a specific event type. It converts typed events
100
+ * to JSON message strings before broadcasting.
101
+ *
102
+ * @template TEvent - The type of events to emit
103
+ *
104
+ * @example
105
+ * ```typescript
106
+ * // Create a typed emitter for UploadEvent
107
+ * const uploadEmitter = new TypedEventEmitter<UploadEvent>(
108
+ * baseEmitter,
109
+ * (event) => JSON.stringify({
110
+ * type: "upload_event",
111
+ * payload: event,
112
+ * timestamp: new Date().toISOString()
113
+ * })
114
+ * );
115
+ *
116
+ * // Use the emitter
117
+ * const effect = Effect.gen(function* () {
118
+ * // Subscribe a WebSocket connection
119
+ * yield* uploadEmitter.subscribe("upload123", websocket);
120
+ *
121
+ * // Emit an event (automatically serialized)
122
+ * yield* uploadEmitter.emit("upload123", {
123
+ * uploadId: "upload123",
124
+ * type: "completed",
125
+ * offset: 2048,
126
+ * size: 2048
127
+ * });
128
+ *
129
+ * // Unsubscribe when done
130
+ * yield* uploadEmitter.unsubscribe("upload123");
131
+ * });
132
+ *
133
+ * // Custom message format
134
+ * const customEmitter = new TypedEventEmitter<MyEvent>(
135
+ * baseEmitter,
136
+ * (event) => `EVENT:${event.type}:${JSON.stringify(event.data)}`
137
+ * );
138
+ * ```
139
+ */
140
+ export class TypedEventEmitter<TEvent> implements EventEmitter<TEvent> {
141
+ constructor(
142
+ private baseEmitter: BaseEventEmitter,
143
+ private eventToMessage: (event: TEvent) => string,
144
+ ) {}
145
+
146
+ subscribe = (
147
+ key: string,
148
+ connection: WebSocketConnection,
149
+ ): Effect.Effect<void, UploadistaError> =>
150
+ this.baseEmitter.subscribe(key, connection);
151
+
152
+ unsubscribe = (key: string): Effect.Effect<void, UploadistaError> =>
153
+ this.baseEmitter.unsubscribe(key);
154
+
155
+ emit = (key: string, event: TEvent): Effect.Effect<void, UploadistaError> => {
156
+ const message = this.eventToMessage(event);
157
+ return this.baseEmitter.emit(key, message);
158
+ };
159
+ }
160
+
161
+ /**
162
+ * Default event-to-message serialization helper.
163
+ *
164
+ * Creates a standardized JSON message format with type, payload, and timestamp.
165
+ * This is the recommended way to serialize events for WebSocket transmission.
166
+ *
167
+ * @param messageType - The message type identifier ("upload_event" or "flow_event")
168
+ * @returns An object with an eventToMessage function
169
+ *
170
+ * @example
171
+ * ```typescript
172
+ * // Create emitter with standard serialization
173
+ * const emitter = new TypedEventEmitter<UploadEvent>(
174
+ * baseEmitter,
175
+ * eventToMessageSerializer("upload_event").eventToMessage
176
+ * );
177
+ *
178
+ * // Messages will be formatted as:
179
+ * // {
180
+ * // "type": "upload_event",
181
+ * // "payload": { ...event data... },
182
+ * // "timestamp": "2024-01-15T10:30:00.000Z"
183
+ * // }
184
+ * ```
185
+ */
186
+ export const eventToMessageSerializer = (
187
+ messageType: "upload_event" | "flow_event",
188
+ ) => ({
189
+ eventToMessage: <T>(event: T): string =>
190
+ JSON.stringify({
191
+ type: messageType,
192
+ payload: event,
193
+ timestamp: new Date().toISOString(),
194
+ }),
195
+ });
196
+
197
+ /**
198
+ * Effect-TS context tag for the base untyped event emitter.
199
+ *
200
+ * This is the low-level emitter that broadcasting implementations provide.
201
+ * Most application code should use typed emitters like UploadEventEmitter instead.
202
+ *
203
+ * @example
204
+ * ```typescript
205
+ * // Provide a base emitter implementation
206
+ * const baseEmitterLayer = Layer.succeed(BaseEventEmitterService, websocketEmitter);
207
+ *
208
+ * // Use in an Effect
209
+ * const effect = Effect.gen(function* () {
210
+ * const baseEmitter = yield* BaseEventEmitterService;
211
+ * yield* baseEmitter.emit("channel1", "raw message");
212
+ * });
213
+ * ```
214
+ */
215
+ export class BaseEventEmitterService extends Context.Tag("BaseEventEmitter")<
216
+ BaseEventEmitterService,
217
+ BaseEventEmitter
218
+ >() {}
219
+
220
+ /**
221
+ * Effect-TS context tag for the UploadEvent typed emitter.
222
+ *
223
+ * This provides type-safe event emission for upload progress and lifecycle events.
224
+ * It's the primary way to broadcast upload events to connected clients.
225
+ *
226
+ * @example
227
+ * ```typescript
228
+ * const uploadEffect = Effect.gen(function* () {
229
+ * const emitter = yield* UploadEventEmitter;
230
+ *
231
+ * // Subscribe a client to upload events
232
+ * yield* emitter.subscribe("upload123", websocketConnection);
233
+ *
234
+ * // Emit progress event
235
+ * yield* emitter.emit("upload123", {
236
+ * uploadId: "upload123",
237
+ * type: "progress",
238
+ * offset: 512000,
239
+ * size: 1024000
240
+ * });
241
+ *
242
+ * // Emit completion event
243
+ * yield* emitter.emit("upload123", {
244
+ * uploadId: "upload123",
245
+ * type: "completed",
246
+ * offset: 1024000,
247
+ * size: 1024000
248
+ * });
249
+ * });
250
+ * ```
251
+ */
252
+ export class UploadEventEmitter extends Context.Tag("UploadEventEmitter")<
253
+ UploadEventEmitter,
254
+ EventEmitter<UploadEvent>
255
+ >() {}
256
+
257
+ /**
258
+ * Effect Layer that creates the UploadEventEmitter from a BaseEventEmitter.
259
+ *
260
+ * This layer automatically wires up JSON serialization for UploadEvent objects
261
+ * with the standard "upload_event" message format.
262
+ *
263
+ * @example
264
+ * ```typescript
265
+ * const program = Effect.gen(function* () {
266
+ * const emitter = yield* UploadEventEmitter;
267
+ * // Use the emitter...
268
+ * }).pipe(
269
+ * Effect.provide(uploadEventEmitter),
270
+ * Effect.provide(baseEmitterLayer)
271
+ * );
272
+ * ```
273
+ */
274
+ export const uploadEventEmitter = Layer.effect(
275
+ UploadEventEmitter,
276
+ Effect.gen(function* () {
277
+ const baseEmitter = yield* BaseEventEmitterService;
278
+ return new TypedEventEmitter<UploadEvent>(
279
+ baseEmitter,
280
+ eventToMessageSerializer("upload_event").eventToMessage,
281
+ );
282
+ }),
283
+ );
284
+
285
+ /**
286
+ * Effect-TS context tag for the FlowEvent typed emitter.
287
+ *
288
+ * This provides type-safe event emission for flow processing lifecycle events.
289
+ * It's used to broadcast flow execution progress, node completion, and errors.
290
+ *
291
+ * @example
292
+ * ```typescript
293
+ * const flowEffect = Effect.gen(function* () {
294
+ * const emitter = yield* FlowEventEmitter;
295
+ *
296
+ * // Subscribe a client to flow job events
297
+ * yield* emitter.subscribe("job123", websocketConnection);
298
+ *
299
+ * // Emit node start event
300
+ * yield* emitter.emit("job123", {
301
+ * jobId: "job123",
302
+ * eventType: "NodeStart",
303
+ * flowId: "flow_resize",
304
+ * nodeId: "resize_1"
305
+ * });
306
+ *
307
+ * // Emit node completion event
308
+ * yield* emitter.emit("job123", {
309
+ * jobId: "job123",
310
+ * eventType: "NodeEnd",
311
+ * flowId: "flow_resize",
312
+ * nodeId: "resize_1",
313
+ * result: { width: 800, height: 600 }
314
+ * });
315
+ * });
316
+ * ```
317
+ */
318
+ export class FlowEventEmitter extends Context.Tag("FlowEventEmitter")<
319
+ FlowEventEmitter,
320
+ EventEmitter<FlowEvent>
321
+ >() {}
322
+
323
+ /**
324
+ * Effect Layer that creates the FlowEventEmitter from a BaseEventEmitter.
325
+ *
326
+ * This layer automatically wires up JSON serialization for FlowEvent objects
327
+ * with the standard "flow_event" message format.
328
+ *
329
+ * @example
330
+ * ```typescript
331
+ * const program = Effect.gen(function* () {
332
+ * const emitter = yield* FlowEventEmitter;
333
+ * // Use the emitter...
334
+ * }).pipe(
335
+ * Effect.provide(flowEventEmitter),
336
+ * Effect.provide(baseEmitterLayer)
337
+ * );
338
+ * ```
339
+ */
340
+ export const flowEventEmitter = Layer.effect(
341
+ FlowEventEmitter,
342
+ Effect.gen(function* () {
343
+ const baseEmitter = yield* BaseEventEmitterService;
344
+ return new TypedEventEmitter<FlowEvent>(
345
+ baseEmitter,
346
+ eventToMessageSerializer("flow_event").eventToMessage,
347
+ );
348
+ }),
349
+ );
@@ -0,0 +1,9 @@
1
+ export * from "./data-store";
2
+ export * from "./event-broadcaster";
3
+ export * from "./event-emitter";
4
+ export * from "./input-file";
5
+ export * from "./kv-store";
6
+ export * from "./middleware";
7
+ export * from "./upload-event";
8
+ export * from "./upload-file";
9
+ export * from "./websocket";
@@ -0,0 +1,107 @@
1
+ import { z } from "zod";
2
+
3
+ /**
4
+ * Zod schema for validating InputFile objects.
5
+ *
6
+ * This schema defines the structure and validation rules for file upload requests.
7
+ * Use this schema to parse and validate input data when creating new uploads.
8
+ *
9
+ * @see {@link InputFile} for the TypeScript type
10
+ */
11
+ export const inputFileSchema = z.object({
12
+ uploadLengthDeferred: z.boolean().optional(),
13
+ storageId: z.string(),
14
+ size: z.number(),
15
+ type: z.string(),
16
+ fileName: z.string().optional(),
17
+ lastModified: z.number().optional(),
18
+ metadata: z.string().optional(),
19
+ checksum: z.string().optional(),
20
+ checksumAlgorithm: z.string().optional(),
21
+ flow: z
22
+ .object({
23
+ flowId: z.string(),
24
+ nodeId: z.string(),
25
+ jobId: z.string(),
26
+ })
27
+ .optional(),
28
+ });
29
+
30
+ /**
31
+ * Represents the input data for creating a new file upload.
32
+ *
33
+ * This type defines the information required to initiate an upload.
34
+ * It's used by clients to provide upload metadata before sending file data.
35
+ *
36
+ * @property storageId - Target storage backend identifier (e.g., "s3-production", "azure-blob")
37
+ * @property size - File size in bytes
38
+ * @property type - MIME type of the file (e.g., "image/jpeg", "application/pdf")
39
+ * @property uploadLengthDeferred - If true, file size is not known upfront (streaming upload)
40
+ * @property fileName - Original filename from the client
41
+ * @property lastModified - File's last modified timestamp in milliseconds since epoch
42
+ * @property metadata - Base64-encoded metadata string (as per tus protocol)
43
+ * @property checksum - Expected file checksum for validation
44
+ * @property checksumAlgorithm - Algorithm used for checksum (e.g., "md5", "sha256")
45
+ * @property flow - Optional flow processing configuration
46
+ * @property flow.flowId - ID of the flow to execute on this file
47
+ * @property flow.nodeId - Starting node ID in the flow
48
+ * @property flow.jobId - Flow job execution ID
49
+ *
50
+ * @example
51
+ * ```typescript
52
+ * // Basic file upload
53
+ * const inputFile: InputFile = {
54
+ * storageId: "s3-production",
55
+ * size: 1024000,
56
+ * type: "image/jpeg",
57
+ * fileName: "photo.jpg",
58
+ * lastModified: Date.now()
59
+ * };
60
+ *
61
+ * // Upload with metadata (base64 encoded as per tus protocol)
62
+ * const metadata = btoa(JSON.stringify({
63
+ * userId: "user_123",
64
+ * albumId: "album_456"
65
+ * }));
66
+ * const inputWithMetadata: InputFile = {
67
+ * storageId: "s3-production",
68
+ * size: 2048000,
69
+ * type: "image/png",
70
+ * fileName: "screenshot.png",
71
+ * metadata
72
+ * };
73
+ *
74
+ * // Upload with checksum validation
75
+ * const inputWithChecksum: InputFile = {
76
+ * storageId: "s3-production",
77
+ * size: 512000,
78
+ * type: "application/pdf",
79
+ * fileName: "document.pdf",
80
+ * checksum: "5d41402abc4b2a76b9719d911017c592",
81
+ * checksumAlgorithm: "md5"
82
+ * };
83
+ *
84
+ * // Upload that triggers a flow
85
+ * const inputWithFlow: InputFile = {
86
+ * storageId: "s3-temp",
87
+ * size: 4096000,
88
+ * type: "image/jpeg",
89
+ * fileName: "large-image.jpg",
90
+ * flow: {
91
+ * flowId: "resize-and-optimize",
92
+ * nodeId: "input_1",
93
+ * jobId: "job_789"
94
+ * }
95
+ * };
96
+ *
97
+ * // Streaming upload (size unknown)
98
+ * const streamingInput: InputFile = {
99
+ * storageId: "s3-production",
100
+ * size: 0, // Will be updated as data arrives
101
+ * type: "video/mp4",
102
+ * uploadLengthDeferred: true,
103
+ * fileName: "live-stream.mp4"
104
+ * };
105
+ * ```
106
+ */
107
+ export type InputFile = z.infer<typeof inputFileSchema>;