@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,28 @@
1
+ // Edge types
2
+ export type { FlowEdge } from "./edge";
3
+ export * from "./edge";
4
+
5
+ export * from "./event";
6
+ export type { Flow, FlowData } from "./flow";
7
+ export * from "./flow";
8
+ // Core flow engine
9
+ export { createFlowWithSchema } from "./flow";
10
+ export * from "./flow-server";
11
+ export * from "./node";
12
+ // Node types and interfaces
13
+ export { createFlowNode, NodeType } from "./node";
14
+ export * from "./nodes";
15
+ // Parallel execution
16
+ export * from "./parallel-scheduler";
17
+ export * from "./plugins/credential-provider";
18
+ export * from "./plugins/image-ai-plugin";
19
+ export * from "./plugins/image-plugin";
20
+ export * from "./plugins/types";
21
+ export * from "./plugins/zip-plugin";
22
+ export * from "./typed-flow";
23
+ export { createFlow } from "./typed-flow";
24
+ export * from "./types/flow-file";
25
+ export * from "./types/flow-job";
26
+ export * from "./types/flow-types";
27
+ export * from "./types/run-args";
28
+ export * from "./utils/resolve-upload-metadata";
@@ -0,0 +1,249 @@
1
+ import { Effect } from "effect";
2
+ import type { z } from "zod";
3
+ import { UploadistaError } from "../errors";
4
+ import type {
5
+ FlowNode,
6
+ FlowNodeData,
7
+ NodeExecutionResult,
8
+ } from "./types/flow-types";
9
+
10
+ /**
11
+ * Defines the type of node in a flow, determining its role in the processing pipeline.
12
+ */
13
+ export enum NodeType {
14
+ /** Entry point for data into the flow */
15
+ input = "input",
16
+ /** Transforms data during flow execution */
17
+ process = "process",
18
+ /** Saves data to storage backends */
19
+ output = "output",
20
+ /** Routes data based on conditions */
21
+ conditional = "conditional",
22
+ /** Splits data to multiple outputs */
23
+ multiplex = "multiplex",
24
+ /** Combines multiple inputs into one output */
25
+ merge = "merge",
26
+ }
27
+
28
+ /**
29
+ * Fields that can be evaluated in conditional node conditions.
30
+ * These fields are typically found in file metadata.
31
+ */
32
+ export type ConditionField =
33
+ | "mimeType"
34
+ | "size"
35
+ | "width"
36
+ | "height"
37
+ | "extension";
38
+
39
+ /**
40
+ * Operators available for comparing values in conditional node conditions.
41
+ */
42
+ export type ConditionOperator =
43
+ | "equals"
44
+ | "notEquals"
45
+ | "greaterThan"
46
+ | "lessThan"
47
+ | "contains"
48
+ | "startsWith";
49
+
50
+ /**
51
+ * Value used in conditional node comparisons.
52
+ * Can be either a string or number depending on the field being evaluated.
53
+ */
54
+ export type ConditionValue = string | number;
55
+
56
+ /**
57
+ * Creates a flow node with automatic input/output validation and retry logic.
58
+ *
59
+ * Flow nodes are the building blocks of processing pipelines. Each node:
60
+ * - Validates its input against a Zod schema
61
+ * - Executes its processing logic
62
+ * - Validates its output against a Zod schema
63
+ * - Can optionally retry on failure with exponential backoff
64
+ *
65
+ * @template Input - The expected input type for this node
66
+ * @template Output - The output type produced by this node
67
+ *
68
+ * @param config - Node configuration
69
+ * @param config.id - Unique identifier for this node in the flow
70
+ * @param config.name - Human-readable name for the node
71
+ * @param config.description - Description of what this node does
72
+ * @param config.type - The type of node (input, process, output, conditional, multiplex, merge)
73
+ * @param config.inputSchema - Zod schema for validating input data
74
+ * @param config.outputSchema - Zod schema for validating output data
75
+ * @param config.run - The processing function to execute for this node
76
+ * @param config.condition - Optional condition for conditional nodes to determine if they should execute
77
+ * @param config.multiInput - If true, node receives all inputs as a record instead of a single input
78
+ * @param config.multiOutput - If true, node can output to multiple targets
79
+ * @param config.pausable - If true, node can pause execution and wait for additional data
80
+ * @param config.retry - Optional retry configuration for handling transient failures
81
+ * @param config.retry.maxRetries - Maximum number of retry attempts (default: 0)
82
+ * @param config.retry.retryDelay - Base delay in milliseconds between retries (default: 1000)
83
+ * @param config.retry.exponentialBackoff - Whether to use exponential backoff for retries (default: true)
84
+ *
85
+ * @returns An Effect that succeeds with the created FlowNode
86
+ *
87
+ * @example
88
+ * ```typescript
89
+ * const resizeNode = createFlowNode({
90
+ * id: "resize-1",
91
+ * name: "Resize Image",
92
+ * description: "Resizes images to 800x600",
93
+ * type: NodeType.process,
94
+ * inputSchema: z.object({
95
+ * stream: z.instanceof(Uint8Array),
96
+ * metadata: z.object({ width: z.number(), height: z.number() })
97
+ * }),
98
+ * outputSchema: z.object({
99
+ * stream: z.instanceof(Uint8Array),
100
+ * metadata: z.object({ width: z.literal(800), height: z.literal(600) })
101
+ * }),
102
+ * run: ({ data }) => Effect.gen(function* () {
103
+ * const resized = yield* resizeImage(data.stream, 800, 600);
104
+ * return {
105
+ * type: "complete",
106
+ * data: { stream: resized, metadata: { width: 800, height: 600 } }
107
+ * };
108
+ * }),
109
+ * retry: {
110
+ * maxRetries: 3,
111
+ * retryDelay: 1000,
112
+ * exponentialBackoff: true
113
+ * }
114
+ * });
115
+ * ```
116
+ */
117
+ export function createFlowNode<Input, Output>({
118
+ id,
119
+ name,
120
+ description,
121
+ type,
122
+ inputSchema,
123
+ outputSchema,
124
+ run,
125
+ condition,
126
+ multiInput = false,
127
+ multiOutput = false,
128
+ pausable = false,
129
+ retry,
130
+ }: {
131
+ id: string;
132
+ name: string;
133
+ description: string;
134
+ type: NodeType;
135
+ inputSchema: z.ZodSchema<Input>;
136
+ outputSchema: z.ZodSchema<Output>;
137
+ run: (args: {
138
+ data: Input;
139
+ jobId: string;
140
+ storageId: string;
141
+ flowId: string;
142
+ clientId: string | null;
143
+ }) => Effect.Effect<NodeExecutionResult<Output>, UploadistaError>;
144
+ condition?: {
145
+ field: ConditionField;
146
+ operator: ConditionOperator;
147
+ value: ConditionValue;
148
+ };
149
+ multiInput?: boolean;
150
+ multiOutput?: boolean;
151
+ pausable?: boolean;
152
+ retry?: {
153
+ maxRetries?: number;
154
+ retryDelay?: number;
155
+ exponentialBackoff?: boolean;
156
+ };
157
+ }): Effect.Effect<FlowNode<Input, Output, UploadistaError>> {
158
+ return Effect.succeed({
159
+ id,
160
+ name,
161
+ description,
162
+ type,
163
+ inputSchema,
164
+ outputSchema,
165
+ pausable,
166
+ run: ({
167
+ data,
168
+ jobId,
169
+ flowId,
170
+ storageId,
171
+ clientId,
172
+ }: {
173
+ data: Input;
174
+ jobId: string;
175
+ flowId: string;
176
+ storageId: string;
177
+ clientId: string | null;
178
+ }) =>
179
+ Effect.gen(function* () {
180
+ // Validate input data against schema
181
+ const validatedData = yield* Effect.try({
182
+ try: () => inputSchema.parse(data),
183
+ catch: (error) => {
184
+ const errorMessage =
185
+ error instanceof Error ? error.message : String(error);
186
+ return UploadistaError.fromCode("FLOW_INPUT_VALIDATION_ERROR", {
187
+ body: `Node '${name}' (${id}) input validation failed: ${errorMessage}`,
188
+ cause: error,
189
+ });
190
+ },
191
+ });
192
+
193
+ // Run the node logic
194
+ const result = yield* run({
195
+ data: validatedData,
196
+ jobId,
197
+ storageId,
198
+ flowId,
199
+ clientId,
200
+ });
201
+
202
+ // If the node returned waiting state, pass it through
203
+ if (result.type === "waiting") {
204
+ return result;
205
+ }
206
+
207
+ // Validate output data against schema for completed results
208
+ const validatedResult = yield* Effect.try({
209
+ try: () => outputSchema.parse(result.data),
210
+ catch: (error) => {
211
+ const errorMessage =
212
+ error instanceof Error ? error.message : String(error);
213
+ return UploadistaError.fromCode("FLOW_OUTPUT_VALIDATION_ERROR", {
214
+ body: `Node '${name}' (${id}) output validation failed: ${errorMessage}`,
215
+ cause: error,
216
+ });
217
+ },
218
+ });
219
+
220
+ return { type: "complete" as const, data: validatedResult };
221
+ }),
222
+ condition,
223
+ multiInput,
224
+ multiOutput,
225
+ retry,
226
+ });
227
+ }
228
+
229
+ /**
230
+ * Extracts serializable node metadata from a FlowNode instance.
231
+ *
232
+ * This function is useful for serializing flow configurations or
233
+ * transmitting node information over the network without including
234
+ * the executable run function or schemas.
235
+ *
236
+ * @param node - The flow node to extract data from
237
+ * @returns A plain object containing the node's metadata (id, name, description, type)
238
+ */
239
+ export const getNodeData = (
240
+ // biome-ignore lint/suspicious/noExplicitAny: maybe type later
241
+ node: FlowNode<any, any, UploadistaError>,
242
+ ): FlowNodeData => {
243
+ return {
244
+ id: node.id,
245
+ name: node.name,
246
+ description: node.description,
247
+ type: node.type,
248
+ };
249
+ };
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Re-exports all flow node implementations.
3
+ * This module provides a centralized way to import all available node types.
4
+ */
5
+
6
+ export * from "./input-node";
7
+ export * from "./storage-node";
8
+ export * from "./transform-node";
@@ -0,0 +1,296 @@
1
+ import { Effect } from "effect";
2
+ import { z } from "zod";
3
+ import { UploadistaError } from "../../errors";
4
+ import type { InputFile } from "../../types";
5
+ import { uploadFileSchema } from "../../types";
6
+ import { UploadServer } from "../../upload";
7
+ import { arrayBuffer, fetchFile } from "../../upload/upload-url";
8
+ import { createFlowNode, NodeType } from "../node";
9
+ import { completeNodeExecution, waitingNodeExecution } from "../types";
10
+ import { resolveUploadMetadata } from "../utils/resolve-upload-metadata";
11
+
12
+ /**
13
+ * Schema for initializing a streaming upload operation.
14
+ * Creates a new upload session for chunked file uploads.
15
+ */
16
+ const initStreamingInputSchema = z.object({
17
+ /** Operation type identifier */
18
+ operation: z.literal("init"),
19
+ /** Storage ID where the file will be stored */
20
+ storageId: z.string(),
21
+ /** Optional metadata for the file */
22
+ metadata: z.record(z.string(), z.any()).optional(),
23
+ });
24
+
25
+ /**
26
+ * Schema for finalizing a streaming upload operation.
27
+ * Completes the upload process after all chunks have been uploaded.
28
+ */
29
+ const finalizeStreamingInputSchema = z.object({
30
+ /** Operation type identifier */
31
+ operation: z.literal("finalize"),
32
+ /** Upload ID from the init operation */
33
+ uploadId: z.string(),
34
+ });
35
+
36
+ /**
37
+ * Schema for fetching a file from a URL.
38
+ * Downloads and processes a file from a remote URL.
39
+ */
40
+ const urlInputSchema = z.object({
41
+ /** Operation type identifier */
42
+ operation: z.literal("url"),
43
+ /** URL to fetch the file from */
44
+ url: z.string(),
45
+ /** Optional storage ID where the file will be stored */
46
+ storageId: z.string().optional(),
47
+ /** Optional metadata for the file */
48
+ metadata: z.record(z.string(), z.any()).optional(),
49
+ });
50
+
51
+ /**
52
+ * Union schema for all input operations.
53
+ * Defines the possible input data structures for the input node.
54
+ */
55
+ export const inputDataSchema = z.union([
56
+ initStreamingInputSchema,
57
+ finalizeStreamingInputSchema,
58
+ urlInputSchema,
59
+ ]);
60
+
61
+ /**
62
+ * Type representing the input data for the input node.
63
+ * Can be one of three operation types: init, finalize, or url.
64
+ */
65
+ export type InputData = z.infer<typeof inputDataSchema>;
66
+
67
+ /**
68
+ * Schema for input node filtering parameters.
69
+ * Defines validation rules for incoming files.
70
+ */
71
+ export const inputNodeParamsSchema = z.object({
72
+ /** Array of allowed MIME types (supports wildcards like "image/*") */
73
+ allowedMimeTypes: z.array(z.string()).optional(),
74
+ /** Minimum file size in bytes */
75
+ minSize: z.number().positive().optional(),
76
+ /** Maximum file size in bytes */
77
+ maxSize: z.number().positive().optional(),
78
+ });
79
+
80
+ /**
81
+ * Parameters for configuring input node validation.
82
+ * Controls which files are accepted based on type and size constraints.
83
+ */
84
+ export type InputNodeParams = z.infer<typeof inputNodeParamsSchema>;
85
+
86
+ /**
87
+ * Helper function to validate file against input parameters.
88
+ * Performs MIME type and size validation based on the provided parameters.
89
+ *
90
+ * @param file - File information to validate
91
+ * @param params - Validation parameters
92
+ * @returns An Effect that succeeds if validation passes or fails with validation error
93
+ */
94
+ function validateFile(
95
+ file: { type: string; size: number },
96
+ params?: InputNodeParams
97
+ ): Effect.Effect<void, UploadistaError> {
98
+ return Effect.gen(function* () {
99
+ if (!params) return;
100
+
101
+ // Check MIME type
102
+ if (params.allowedMimeTypes && params.allowedMimeTypes.length > 0) {
103
+ const isAllowed = params.allowedMimeTypes.some((allowed) => {
104
+ // Support wildcard patterns like "image/*"
105
+ if (allowed.endsWith("/*")) {
106
+ const prefix = allowed.slice(0, -2);
107
+ return file.type.startsWith(prefix);
108
+ }
109
+ return file.type === allowed;
110
+ });
111
+
112
+ if (!isAllowed) {
113
+ throw yield* UploadistaError.fromCode("VALIDATION_ERROR", {
114
+ cause: new Error(
115
+ `File type "${
116
+ file.type
117
+ }" is not allowed. Allowed types: ${params.allowedMimeTypes.join(
118
+ ", "
119
+ )}`
120
+ ),
121
+ }).toEffect();
122
+ }
123
+ }
124
+
125
+ // Check minimum size
126
+ if (params.minSize !== undefined && file.size < params.minSize) {
127
+ throw yield* UploadistaError.fromCode("VALIDATION_ERROR", {
128
+ cause: new Error(
129
+ `File size (${file.size} bytes) is below minimum (${params.minSize} bytes)`
130
+ ),
131
+ }).toEffect();
132
+ }
133
+
134
+ // Check maximum size
135
+ if (params.maxSize !== undefined && file.size > params.maxSize) {
136
+ throw yield* UploadistaError.fromCode("VALIDATION_ERROR", {
137
+ cause: new Error(
138
+ `File size (${file.size} bytes) exceeds maximum (${params.maxSize} bytes)`
139
+ ),
140
+ }).toEffect();
141
+ }
142
+ });
143
+ }
144
+
145
+ /**
146
+ * Creates an input node for handling file input through multiple methods.
147
+ *
148
+ * The input node supports three operation types:
149
+ * - `init`: Initialize a streaming upload session
150
+ * - `finalize`: Complete a streaming upload after all chunks are uploaded
151
+ * - `url`: Fetch a file directly from a URL
152
+ *
153
+ * @param id - Unique identifier for the node
154
+ * @param params - Optional validation parameters for filtering incoming files
155
+ * @returns An Effect that creates a flow node configured for file input
156
+ *
157
+ * @example
158
+ * ```typescript
159
+ * // Create input node with validation
160
+ * const inputNode = yield* createInputNode("file-input", {
161
+ * allowedMimeTypes: ["image/*", "application/pdf"],
162
+ * maxSize: 10 * 1024 * 1024, // 10MB
163
+ * });
164
+ *
165
+ * // Create input node without validation
166
+ * const openInputNode = yield* createInputNode("open-input");
167
+ * ```
168
+ */
169
+ export function createInputNode(id: string, params?: InputNodeParams) {
170
+ return Effect.gen(function* () {
171
+ const uploadServer = yield* UploadServer;
172
+ return yield* createFlowNode({
173
+ id,
174
+ name: "Input",
175
+ description:
176
+ "Handles file input through multiple methods - streaming upload (init/finalize) or direct URL fetch",
177
+ type: NodeType.input,
178
+ inputSchema: inputDataSchema,
179
+ outputSchema: uploadFileSchema,
180
+ run: ({ data, flowId, jobId, clientId }) => {
181
+ return Effect.gen(function* () {
182
+ switch (data.operation) {
183
+ case "init": {
184
+ // Create upload using upload server - it handles all state management
185
+ const inputFile: InputFile = {
186
+ storageId: data.storageId,
187
+ size: data.metadata?.size || 0,
188
+ type: data.metadata?.mimeType || "application/octet-stream",
189
+ fileName: data.metadata?.originalName,
190
+ lastModified: data.metadata?.size ? Date.now() : undefined,
191
+ metadata: data.metadata
192
+ ? JSON.stringify(data.metadata)
193
+ : undefined,
194
+ flow: {
195
+ flowId,
196
+ nodeId: id,
197
+ jobId,
198
+ },
199
+ };
200
+
201
+ const uploadFile = yield* uploadServer.createUpload(
202
+ inputFile,
203
+ clientId
204
+ );
205
+
206
+ // Return waiting state with the upload file
207
+ // Client will upload chunks directly to the upload API
208
+ return waitingNodeExecution(uploadFile);
209
+ }
210
+
211
+ case "finalize": {
212
+ // Get final upload file from upload server's KV store
213
+ const finalUploadFile = yield* uploadServer.getUpload(
214
+ data.uploadId
215
+ );
216
+
217
+ // Extract type and size from metadata for validation
218
+ const { type } = resolveUploadMetadata(finalUploadFile.metadata);
219
+ const size = finalUploadFile.size || 0;
220
+
221
+ // Validate file against params
222
+ yield* validateFile({ type, size }, params);
223
+
224
+ // Complete the node execution with the final upload file
225
+ // Flow can now continue to next nodes (e.g., save to storage, optimize)
226
+ return completeNodeExecution(finalUploadFile);
227
+ }
228
+
229
+ case "url": {
230
+ // Fetch file from URL directly
231
+ const response = yield* fetchFile(data.url);
232
+ const buffer = yield* arrayBuffer(response);
233
+
234
+ // Extract metadata from response or use provided metadata
235
+ const mimeType =
236
+ data.metadata?.mimeType ||
237
+ response.headers.get("content-type") ||
238
+ "application/octet-stream";
239
+ const size =
240
+ data.metadata?.size ||
241
+ Number(response.headers.get("content-length") || 0);
242
+ const fileName =
243
+ data.metadata?.originalName ||
244
+ data.url.split("/").pop() ||
245
+ "file";
246
+
247
+ // Validate file against params
248
+ yield* validateFile({ type: mimeType, size }, params);
249
+
250
+ // Create a readable stream from the buffer
251
+ const stream = new ReadableStream({
252
+ start(controller) {
253
+ controller.enqueue(new Uint8Array(buffer));
254
+ controller.close();
255
+ },
256
+ });
257
+
258
+ // Use upload server to create and store the file
259
+ const inputFile: InputFile = {
260
+ storageId: data.storageId || "buffer",
261
+ size,
262
+ type: mimeType,
263
+ fileName,
264
+ lastModified: Date.now(),
265
+ metadata: data.metadata
266
+ ? JSON.stringify(data.metadata)
267
+ : undefined,
268
+ };
269
+
270
+ const uploadFile = yield* uploadServer.upload(
271
+ inputFile,
272
+ clientId,
273
+ stream
274
+ );
275
+
276
+ // Complete the node execution with the upload file
277
+ return completeNodeExecution({
278
+ ...uploadFile,
279
+ flow: {
280
+ flowId,
281
+ nodeId: id,
282
+ jobId,
283
+ },
284
+ });
285
+ }
286
+
287
+ default:
288
+ throw yield* UploadistaError.fromCode("VALIDATION_ERROR", {
289
+ cause: new Error("Invalid operation"),
290
+ }).toEffect();
291
+ }
292
+ });
293
+ },
294
+ });
295
+ });
296
+ }