@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,24 @@
1
+ export * from "./edge";
2
+ export * from "./event";
3
+ export * from "./flow";
4
+ // Core flow engine
5
+ export { createFlowWithSchema } from "./flow";
6
+ export * from "./flow-server";
7
+ export * from "./node";
8
+ // Node types and interfaces
9
+ export { createFlowNode, NodeType } from "./node";
10
+ export * from "./nodes";
11
+ // Parallel execution
12
+ export * from "./parallel-scheduler";
13
+ export * from "./plugins/credential-provider";
14
+ export * from "./plugins/image-ai-plugin";
15
+ export * from "./plugins/image-plugin";
16
+ export * from "./plugins/types";
17
+ export * from "./plugins/zip-plugin";
18
+ export * from "./typed-flow";
19
+ export { createFlow } from "./typed-flow";
20
+ export * from "./types/flow-file";
21
+ export * from "./types/flow-job";
22
+ export * from "./types/flow-types";
23
+ export * from "./types/run-args";
24
+ export * from "./utils/resolve-upload-metadata";
@@ -0,0 +1,136 @@
1
+ import { Effect } from "effect";
2
+ import type { z } from "zod";
3
+ import { UploadistaError } from "../errors";
4
+ import type { FlowNode, FlowNodeData, NodeExecutionResult } from "./types/flow-types";
5
+ /**
6
+ * Defines the type of node in a flow, determining its role in the processing pipeline.
7
+ */
8
+ export declare enum NodeType {
9
+ /** Entry point for data into the flow */
10
+ input = "input",
11
+ /** Transforms data during flow execution */
12
+ process = "process",
13
+ /** Saves data to storage backends */
14
+ output = "output",
15
+ /** Routes data based on conditions */
16
+ conditional = "conditional",
17
+ /** Splits data to multiple outputs */
18
+ multiplex = "multiplex",
19
+ /** Combines multiple inputs into one output */
20
+ merge = "merge"
21
+ }
22
+ /**
23
+ * Fields that can be evaluated in conditional node conditions.
24
+ * These fields are typically found in file metadata.
25
+ */
26
+ export type ConditionField = "mimeType" | "size" | "width" | "height" | "extension";
27
+ /**
28
+ * Operators available for comparing values in conditional node conditions.
29
+ */
30
+ export type ConditionOperator = "equals" | "notEquals" | "greaterThan" | "lessThan" | "contains" | "startsWith";
31
+ /**
32
+ * Value used in conditional node comparisons.
33
+ * Can be either a string or number depending on the field being evaluated.
34
+ */
35
+ export type ConditionValue = string | number;
36
+ /**
37
+ * Creates a flow node with automatic input/output validation and retry logic.
38
+ *
39
+ * Flow nodes are the building blocks of processing pipelines. Each node:
40
+ * - Validates its input against a Zod schema
41
+ * - Executes its processing logic
42
+ * - Validates its output against a Zod schema
43
+ * - Can optionally retry on failure with exponential backoff
44
+ *
45
+ * @template Input - The expected input type for this node
46
+ * @template Output - The output type produced by this node
47
+ *
48
+ * @param config - Node configuration
49
+ * @param config.id - Unique identifier for this node in the flow
50
+ * @param config.name - Human-readable name for the node
51
+ * @param config.description - Description of what this node does
52
+ * @param config.type - The type of node (input, process, output, conditional, multiplex, merge)
53
+ * @param config.inputSchema - Zod schema for validating input data
54
+ * @param config.outputSchema - Zod schema for validating output data
55
+ * @param config.run - The processing function to execute for this node
56
+ * @param config.condition - Optional condition for conditional nodes to determine if they should execute
57
+ * @param config.multiInput - If true, node receives all inputs as a record instead of a single input
58
+ * @param config.multiOutput - If true, node can output to multiple targets
59
+ * @param config.pausable - If true, node can pause execution and wait for additional data
60
+ * @param config.retry - Optional retry configuration for handling transient failures
61
+ * @param config.retry.maxRetries - Maximum number of retry attempts (default: 0)
62
+ * @param config.retry.retryDelay - Base delay in milliseconds between retries (default: 1000)
63
+ * @param config.retry.exponentialBackoff - Whether to use exponential backoff for retries (default: true)
64
+ *
65
+ * @returns An Effect that succeeds with the created FlowNode
66
+ *
67
+ * @example
68
+ * ```typescript
69
+ * const resizeNode = createFlowNode({
70
+ * id: "resize-1",
71
+ * name: "Resize Image",
72
+ * description: "Resizes images to 800x600",
73
+ * type: NodeType.process,
74
+ * inputSchema: z.object({
75
+ * stream: z.instanceof(Uint8Array),
76
+ * metadata: z.object({ width: z.number(), height: z.number() })
77
+ * }),
78
+ * outputSchema: z.object({
79
+ * stream: z.instanceof(Uint8Array),
80
+ * metadata: z.object({ width: z.literal(800), height: z.literal(600) })
81
+ * }),
82
+ * run: ({ data }) => Effect.gen(function* () {
83
+ * const resized = yield* resizeImage(data.stream, 800, 600);
84
+ * return {
85
+ * type: "complete",
86
+ * data: { stream: resized, metadata: { width: 800, height: 600 } }
87
+ * };
88
+ * }),
89
+ * retry: {
90
+ * maxRetries: 3,
91
+ * retryDelay: 1000,
92
+ * exponentialBackoff: true
93
+ * }
94
+ * });
95
+ * ```
96
+ */
97
+ export declare function createFlowNode<Input, Output>({ id, name, description, type, inputSchema, outputSchema, run, condition, multiInput, multiOutput, pausable, retry, }: {
98
+ id: string;
99
+ name: string;
100
+ description: string;
101
+ type: NodeType;
102
+ inputSchema: z.ZodSchema<Input>;
103
+ outputSchema: z.ZodSchema<Output>;
104
+ run: (args: {
105
+ data: Input;
106
+ jobId: string;
107
+ storageId: string;
108
+ flowId: string;
109
+ clientId: string | null;
110
+ }) => Effect.Effect<NodeExecutionResult<Output>, UploadistaError>;
111
+ condition?: {
112
+ field: ConditionField;
113
+ operator: ConditionOperator;
114
+ value: ConditionValue;
115
+ };
116
+ multiInput?: boolean;
117
+ multiOutput?: boolean;
118
+ pausable?: boolean;
119
+ retry?: {
120
+ maxRetries?: number;
121
+ retryDelay?: number;
122
+ exponentialBackoff?: boolean;
123
+ };
124
+ }): Effect.Effect<FlowNode<Input, Output, UploadistaError>>;
125
+ /**
126
+ * Extracts serializable node metadata from a FlowNode instance.
127
+ *
128
+ * This function is useful for serializing flow configurations or
129
+ * transmitting node information over the network without including
130
+ * the executable run function or schemas.
131
+ *
132
+ * @param node - The flow node to extract data from
133
+ * @returns A plain object containing the node's metadata (id, name, description, type)
134
+ */
135
+ export declare const getNodeData: (node: FlowNode<any, any, UploadistaError>) => FlowNodeData;
136
+ //# sourceMappingURL=node.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../src/flow/node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,KAAK,EACV,QAAQ,EACR,YAAY,EACZ,mBAAmB,EACpB,MAAM,oBAAoB,CAAC;AAE5B;;GAEG;AACH,oBAAY,QAAQ;IAClB,yCAAyC;IACzC,KAAK,UAAU;IACf,4CAA4C;IAC5C,OAAO,YAAY;IACnB,qCAAqC;IACrC,MAAM,WAAW;IACjB,sCAAsC;IACtC,WAAW,gBAAgB;IAC3B,sCAAsC;IACtC,SAAS,cAAc;IACvB,+CAA+C;IAC/C,KAAK,UAAU;CAChB;AAED;;;GAGG;AACH,MAAM,MAAM,cAAc,GACtB,UAAU,GACV,MAAM,GACN,OAAO,GACP,QAAQ,GACR,WAAW,CAAC;AAEhB;;GAEG;AACH,MAAM,MAAM,iBAAiB,GACzB,QAAQ,GACR,WAAW,GACX,aAAa,GACb,UAAU,GACV,UAAU,GACV,YAAY,CAAC;AAEjB;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,MAAM,CAAC;AAE7C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4DG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,EAC5C,EAAE,EACF,IAAI,EACJ,WAAW,EACX,IAAI,EACJ,WAAW,EACX,YAAY,EACZ,GAAG,EACH,SAAS,EACT,UAAkB,EAClB,WAAmB,EACnB,QAAgB,EAChB,KAAK,GACN,EAAE;IACD,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,QAAQ,CAAC;IACf,WAAW,EAAE,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAChC,YAAY,EAAE,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAClC,GAAG,EAAE,CAAC,IAAI,EAAE;QACV,IAAI,EAAE,KAAK,CAAC;QACZ,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;KACzB,KAAK,MAAM,CAAC,MAAM,CAAC,mBAAmB,CAAC,MAAM,CAAC,EAAE,eAAe,CAAC,CAAC;IAClE,SAAS,CAAC,EAAE;QACV,KAAK,EAAE,cAAc,CAAC;QACtB,QAAQ,EAAE,iBAAiB,CAAC;QAC5B,KAAK,EAAE,cAAc,CAAC;KACvB,CAAC;IACF,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE;QACN,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,kBAAkB,CAAC,EAAE,OAAO,CAAC;KAC9B,CAAC;CACH,GAAG,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,eAAe,CAAC,CAAC,CAsE1D;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,WAAW,GAEtB,MAAM,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,eAAe,CAAC,KACxC,YAOF,CAAC"}
@@ -0,0 +1,153 @@
1
+ import { Effect } from "effect";
2
+ import { UploadistaError } from "../errors";
3
+ /**
4
+ * Defines the type of node in a flow, determining its role in the processing pipeline.
5
+ */
6
+ export var NodeType;
7
+ (function (NodeType) {
8
+ /** Entry point for data into the flow */
9
+ NodeType["input"] = "input";
10
+ /** Transforms data during flow execution */
11
+ NodeType["process"] = "process";
12
+ /** Saves data to storage backends */
13
+ NodeType["output"] = "output";
14
+ /** Routes data based on conditions */
15
+ NodeType["conditional"] = "conditional";
16
+ /** Splits data to multiple outputs */
17
+ NodeType["multiplex"] = "multiplex";
18
+ /** Combines multiple inputs into one output */
19
+ NodeType["merge"] = "merge";
20
+ })(NodeType || (NodeType = {}));
21
+ /**
22
+ * Creates a flow node with automatic input/output validation and retry logic.
23
+ *
24
+ * Flow nodes are the building blocks of processing pipelines. Each node:
25
+ * - Validates its input against a Zod schema
26
+ * - Executes its processing logic
27
+ * - Validates its output against a Zod schema
28
+ * - Can optionally retry on failure with exponential backoff
29
+ *
30
+ * @template Input - The expected input type for this node
31
+ * @template Output - The output type produced by this node
32
+ *
33
+ * @param config - Node configuration
34
+ * @param config.id - Unique identifier for this node in the flow
35
+ * @param config.name - Human-readable name for the node
36
+ * @param config.description - Description of what this node does
37
+ * @param config.type - The type of node (input, process, output, conditional, multiplex, merge)
38
+ * @param config.inputSchema - Zod schema for validating input data
39
+ * @param config.outputSchema - Zod schema for validating output data
40
+ * @param config.run - The processing function to execute for this node
41
+ * @param config.condition - Optional condition for conditional nodes to determine if they should execute
42
+ * @param config.multiInput - If true, node receives all inputs as a record instead of a single input
43
+ * @param config.multiOutput - If true, node can output to multiple targets
44
+ * @param config.pausable - If true, node can pause execution and wait for additional data
45
+ * @param config.retry - Optional retry configuration for handling transient failures
46
+ * @param config.retry.maxRetries - Maximum number of retry attempts (default: 0)
47
+ * @param config.retry.retryDelay - Base delay in milliseconds between retries (default: 1000)
48
+ * @param config.retry.exponentialBackoff - Whether to use exponential backoff for retries (default: true)
49
+ *
50
+ * @returns An Effect that succeeds with the created FlowNode
51
+ *
52
+ * @example
53
+ * ```typescript
54
+ * const resizeNode = createFlowNode({
55
+ * id: "resize-1",
56
+ * name: "Resize Image",
57
+ * description: "Resizes images to 800x600",
58
+ * type: NodeType.process,
59
+ * inputSchema: z.object({
60
+ * stream: z.instanceof(Uint8Array),
61
+ * metadata: z.object({ width: z.number(), height: z.number() })
62
+ * }),
63
+ * outputSchema: z.object({
64
+ * stream: z.instanceof(Uint8Array),
65
+ * metadata: z.object({ width: z.literal(800), height: z.literal(600) })
66
+ * }),
67
+ * run: ({ data }) => Effect.gen(function* () {
68
+ * const resized = yield* resizeImage(data.stream, 800, 600);
69
+ * return {
70
+ * type: "complete",
71
+ * data: { stream: resized, metadata: { width: 800, height: 600 } }
72
+ * };
73
+ * }),
74
+ * retry: {
75
+ * maxRetries: 3,
76
+ * retryDelay: 1000,
77
+ * exponentialBackoff: true
78
+ * }
79
+ * });
80
+ * ```
81
+ */
82
+ export function createFlowNode({ id, name, description, type, inputSchema, outputSchema, run, condition, multiInput = false, multiOutput = false, pausable = false, retry, }) {
83
+ return Effect.succeed({
84
+ id,
85
+ name,
86
+ description,
87
+ type,
88
+ inputSchema,
89
+ outputSchema,
90
+ pausable,
91
+ run: ({ data, jobId, flowId, storageId, clientId, }) => Effect.gen(function* () {
92
+ // Validate input data against schema
93
+ const validatedData = yield* Effect.try({
94
+ try: () => inputSchema.parse(data),
95
+ catch: (error) => {
96
+ const errorMessage = error instanceof Error ? error.message : String(error);
97
+ return UploadistaError.fromCode("FLOW_INPUT_VALIDATION_ERROR", {
98
+ body: `Node '${name}' (${id}) input validation failed: ${errorMessage}`,
99
+ cause: error,
100
+ });
101
+ },
102
+ });
103
+ // Run the node logic
104
+ const result = yield* run({
105
+ data: validatedData,
106
+ jobId,
107
+ storageId,
108
+ flowId,
109
+ clientId,
110
+ });
111
+ // If the node returned waiting state, pass it through
112
+ if (result.type === "waiting") {
113
+ return result;
114
+ }
115
+ // Validate output data against schema for completed results
116
+ const validatedResult = yield* Effect.try({
117
+ try: () => outputSchema.parse(result.data),
118
+ catch: (error) => {
119
+ const errorMessage = error instanceof Error ? error.message : String(error);
120
+ return UploadistaError.fromCode("FLOW_OUTPUT_VALIDATION_ERROR", {
121
+ body: `Node '${name}' (${id}) output validation failed: ${errorMessage}`,
122
+ cause: error,
123
+ });
124
+ },
125
+ });
126
+ return { type: "complete", data: validatedResult };
127
+ }),
128
+ condition,
129
+ multiInput,
130
+ multiOutput,
131
+ retry,
132
+ });
133
+ }
134
+ /**
135
+ * Extracts serializable node metadata from a FlowNode instance.
136
+ *
137
+ * This function is useful for serializing flow configurations or
138
+ * transmitting node information over the network without including
139
+ * the executable run function or schemas.
140
+ *
141
+ * @param node - The flow node to extract data from
142
+ * @returns A plain object containing the node's metadata (id, name, description, type)
143
+ */
144
+ export const getNodeData = (
145
+ // biome-ignore lint/suspicious/noExplicitAny: maybe type later
146
+ node) => {
147
+ return {
148
+ id: node.id,
149
+ name: node.name,
150
+ description: node.description,
151
+ type: node.type,
152
+ };
153
+ };
@@ -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
+ export * from "./input-node";
6
+ export * from "./storage-node";
7
+ export * from "./transform-node";
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/flow/nodes/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Re-exports all flow node implementations.
3
+ * This module provides a centralized way to import all available node types.
4
+ */
5
+ export * from "./input-node";
6
+ export * from "./storage-node";
7
+ export * from "./transform-node";
@@ -0,0 +1,78 @@
1
+ import { Effect } from "effect";
2
+ import { z } from "zod";
3
+ import { UploadistaError } from "../../errors";
4
+ import { UploadServer } from "../../upload";
5
+ /**
6
+ * Union schema for all input operations.
7
+ * Defines the possible input data structures for the input node.
8
+ */
9
+ export declare const inputDataSchema: z.ZodUnion<readonly [z.ZodObject<{
10
+ operation: z.ZodLiteral<"init">;
11
+ storageId: z.ZodString;
12
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
13
+ }, z.core.$strip>, z.ZodObject<{
14
+ operation: z.ZodLiteral<"finalize">;
15
+ uploadId: z.ZodString;
16
+ }, z.core.$strip>, z.ZodObject<{
17
+ operation: z.ZodLiteral<"url">;
18
+ url: z.ZodString;
19
+ storageId: z.ZodOptional<z.ZodString>;
20
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
21
+ }, z.core.$strip>]>;
22
+ /**
23
+ * Type representing the input data for the input node.
24
+ * Can be one of three operation types: init, finalize, or url.
25
+ */
26
+ export type InputData = z.infer<typeof inputDataSchema>;
27
+ /**
28
+ * Schema for input node filtering parameters.
29
+ * Defines validation rules for incoming files.
30
+ */
31
+ export declare const inputNodeParamsSchema: z.ZodObject<{
32
+ allowedMimeTypes: z.ZodOptional<z.ZodArray<z.ZodString>>;
33
+ minSize: z.ZodOptional<z.ZodNumber>;
34
+ maxSize: z.ZodOptional<z.ZodNumber>;
35
+ }, z.core.$strip>;
36
+ /**
37
+ * Parameters for configuring input node validation.
38
+ * Controls which files are accepted based on type and size constraints.
39
+ */
40
+ export type InputNodeParams = z.infer<typeof inputNodeParamsSchema>;
41
+ /**
42
+ * Creates an input node for handling file input through multiple methods.
43
+ *
44
+ * The input node supports three operation types:
45
+ * - `init`: Initialize a streaming upload session
46
+ * - `finalize`: Complete a streaming upload after all chunks are uploaded
47
+ * - `url`: Fetch a file directly from a URL
48
+ *
49
+ * @param id - Unique identifier for the node
50
+ * @param params - Optional validation parameters for filtering incoming files
51
+ * @returns An Effect that creates a flow node configured for file input
52
+ *
53
+ * @example
54
+ * ```typescript
55
+ * // Create input node with validation
56
+ * const inputNode = yield* createInputNode("file-input", {
57
+ * allowedMimeTypes: ["image/*", "application/pdf"],
58
+ * maxSize: 10 * 1024 * 1024, // 10MB
59
+ * });
60
+ *
61
+ * // Create input node without validation
62
+ * const openInputNode = yield* createInputNode("open-input");
63
+ * ```
64
+ */
65
+ export declare function createInputNode(id: string, params?: InputNodeParams): Effect.Effect<import("..").FlowNode<{
66
+ operation: "init";
67
+ storageId: string;
68
+ metadata?: Record<string, any> | undefined;
69
+ } | {
70
+ operation: "finalize";
71
+ uploadId: string;
72
+ } | {
73
+ operation: "url";
74
+ url: string;
75
+ storageId?: string | undefined;
76
+ metadata?: Record<string, any> | undefined;
77
+ }, import("../..").UploadFile, UploadistaError>, never, UploadServer>;
78
+ //# sourceMappingURL=input-node.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input-node.d.ts","sourceRoot":"","sources":["../../../src/flow/nodes/input-node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAG/C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AA6C5C;;;GAGG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;mBAI1B,CAAC;AAEH;;;GAGG;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAExD;;;GAGG;AACH,eAAO,MAAM,qBAAqB;;;;iBAOhC,CAAC;AAEH;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AA6DpE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,eAAe;;;;;;;;;;;;sEA+HnE"}
@@ -0,0 +1,233 @@
1
+ import { Effect } from "effect";
2
+ import { z } from "zod";
3
+ import { UploadistaError } from "../../errors";
4
+ import { uploadFileSchema } from "../../types";
5
+ import { UploadServer } from "../../upload";
6
+ import { arrayBuffer, fetchFile } from "../../upload/upload-url";
7
+ import { createFlowNode, NodeType } from "../node";
8
+ import { completeNodeExecution, waitingNodeExecution } from "../types";
9
+ import { resolveUploadMetadata } from "../utils/resolve-upload-metadata";
10
+ /**
11
+ * Schema for initializing a streaming upload operation.
12
+ * Creates a new upload session for chunked file uploads.
13
+ */
14
+ const initStreamingInputSchema = z.object({
15
+ /** Operation type identifier */
16
+ operation: z.literal("init"),
17
+ /** Storage ID where the file will be stored */
18
+ storageId: z.string(),
19
+ /** Optional metadata for the file */
20
+ metadata: z.record(z.string(), z.any()).optional(),
21
+ });
22
+ /**
23
+ * Schema for finalizing a streaming upload operation.
24
+ * Completes the upload process after all chunks have been uploaded.
25
+ */
26
+ const finalizeStreamingInputSchema = z.object({
27
+ /** Operation type identifier */
28
+ operation: z.literal("finalize"),
29
+ /** Upload ID from the init operation */
30
+ uploadId: z.string(),
31
+ });
32
+ /**
33
+ * Schema for fetching a file from a URL.
34
+ * Downloads and processes a file from a remote URL.
35
+ */
36
+ const urlInputSchema = z.object({
37
+ /** Operation type identifier */
38
+ operation: z.literal("url"),
39
+ /** URL to fetch the file from */
40
+ url: z.string(),
41
+ /** Optional storage ID where the file will be stored */
42
+ storageId: z.string().optional(),
43
+ /** Optional metadata for the file */
44
+ metadata: z.record(z.string(), z.any()).optional(),
45
+ });
46
+ /**
47
+ * Union schema for all input operations.
48
+ * Defines the possible input data structures for the input node.
49
+ */
50
+ export const inputDataSchema = z.union([
51
+ initStreamingInputSchema,
52
+ finalizeStreamingInputSchema,
53
+ urlInputSchema,
54
+ ]);
55
+ /**
56
+ * Schema for input node filtering parameters.
57
+ * Defines validation rules for incoming files.
58
+ */
59
+ export const inputNodeParamsSchema = z.object({
60
+ /** Array of allowed MIME types (supports wildcards like "image/*") */
61
+ allowedMimeTypes: z.array(z.string()).optional(),
62
+ /** Minimum file size in bytes */
63
+ minSize: z.number().positive().optional(),
64
+ /** Maximum file size in bytes */
65
+ maxSize: z.number().positive().optional(),
66
+ });
67
+ /**
68
+ * Helper function to validate file against input parameters.
69
+ * Performs MIME type and size validation based on the provided parameters.
70
+ *
71
+ * @param file - File information to validate
72
+ * @param params - Validation parameters
73
+ * @returns An Effect that succeeds if validation passes or fails with validation error
74
+ */
75
+ function validateFile(file, params) {
76
+ return Effect.gen(function* () {
77
+ if (!params)
78
+ return;
79
+ // Check MIME type
80
+ if (params.allowedMimeTypes && params.allowedMimeTypes.length > 0) {
81
+ const isAllowed = params.allowedMimeTypes.some((allowed) => {
82
+ // Support wildcard patterns like "image/*"
83
+ if (allowed.endsWith("/*")) {
84
+ const prefix = allowed.slice(0, -2);
85
+ return file.type.startsWith(prefix);
86
+ }
87
+ return file.type === allowed;
88
+ });
89
+ if (!isAllowed) {
90
+ throw yield* UploadistaError.fromCode("VALIDATION_ERROR", {
91
+ cause: new Error(`File type "${file.type}" is not allowed. Allowed types: ${params.allowedMimeTypes.join(", ")}`),
92
+ }).toEffect();
93
+ }
94
+ }
95
+ // Check minimum size
96
+ if (params.minSize !== undefined && file.size < params.minSize) {
97
+ throw yield* UploadistaError.fromCode("VALIDATION_ERROR", {
98
+ cause: new Error(`File size (${file.size} bytes) is below minimum (${params.minSize} bytes)`),
99
+ }).toEffect();
100
+ }
101
+ // Check maximum size
102
+ if (params.maxSize !== undefined && file.size > params.maxSize) {
103
+ throw yield* UploadistaError.fromCode("VALIDATION_ERROR", {
104
+ cause: new Error(`File size (${file.size} bytes) exceeds maximum (${params.maxSize} bytes)`),
105
+ }).toEffect();
106
+ }
107
+ });
108
+ }
109
+ /**
110
+ * Creates an input node for handling file input through multiple methods.
111
+ *
112
+ * The input node supports three operation types:
113
+ * - `init`: Initialize a streaming upload session
114
+ * - `finalize`: Complete a streaming upload after all chunks are uploaded
115
+ * - `url`: Fetch a file directly from a URL
116
+ *
117
+ * @param id - Unique identifier for the node
118
+ * @param params - Optional validation parameters for filtering incoming files
119
+ * @returns An Effect that creates a flow node configured for file input
120
+ *
121
+ * @example
122
+ * ```typescript
123
+ * // Create input node with validation
124
+ * const inputNode = yield* createInputNode("file-input", {
125
+ * allowedMimeTypes: ["image/*", "application/pdf"],
126
+ * maxSize: 10 * 1024 * 1024, // 10MB
127
+ * });
128
+ *
129
+ * // Create input node without validation
130
+ * const openInputNode = yield* createInputNode("open-input");
131
+ * ```
132
+ */
133
+ export function createInputNode(id, params) {
134
+ return Effect.gen(function* () {
135
+ const uploadServer = yield* UploadServer;
136
+ return yield* createFlowNode({
137
+ id,
138
+ name: "Input",
139
+ description: "Handles file input through multiple methods - streaming upload (init/finalize) or direct URL fetch",
140
+ type: NodeType.input,
141
+ inputSchema: inputDataSchema,
142
+ outputSchema: uploadFileSchema,
143
+ run: ({ data, flowId, jobId, clientId }) => {
144
+ return Effect.gen(function* () {
145
+ switch (data.operation) {
146
+ case "init": {
147
+ // Create upload using upload server - it handles all state management
148
+ const inputFile = {
149
+ storageId: data.storageId,
150
+ size: data.metadata?.size || 0,
151
+ type: data.metadata?.mimeType || "application/octet-stream",
152
+ fileName: data.metadata?.originalName,
153
+ lastModified: data.metadata?.size ? Date.now() : undefined,
154
+ metadata: data.metadata
155
+ ? JSON.stringify(data.metadata)
156
+ : undefined,
157
+ flow: {
158
+ flowId,
159
+ nodeId: id,
160
+ jobId,
161
+ },
162
+ };
163
+ const uploadFile = yield* uploadServer.createUpload(inputFile, clientId);
164
+ // Return waiting state with the upload file
165
+ // Client will upload chunks directly to the upload API
166
+ return waitingNodeExecution(uploadFile);
167
+ }
168
+ case "finalize": {
169
+ // Get final upload file from upload server's KV store
170
+ const finalUploadFile = yield* uploadServer.getUpload(data.uploadId);
171
+ // Extract type and size from metadata for validation
172
+ const { type } = resolveUploadMetadata(finalUploadFile.metadata);
173
+ const size = finalUploadFile.size || 0;
174
+ // Validate file against params
175
+ yield* validateFile({ type, size }, params);
176
+ // Complete the node execution with the final upload file
177
+ // Flow can now continue to next nodes (e.g., save to storage, optimize)
178
+ return completeNodeExecution(finalUploadFile);
179
+ }
180
+ case "url": {
181
+ // Fetch file from URL directly
182
+ const response = yield* fetchFile(data.url);
183
+ const buffer = yield* arrayBuffer(response);
184
+ // Extract metadata from response or use provided metadata
185
+ const mimeType = data.metadata?.mimeType ||
186
+ response.headers.get("content-type") ||
187
+ "application/octet-stream";
188
+ const size = data.metadata?.size ||
189
+ Number(response.headers.get("content-length") || 0);
190
+ const fileName = data.metadata?.originalName ||
191
+ data.url.split("/").pop() ||
192
+ "file";
193
+ // Validate file against params
194
+ yield* validateFile({ type: mimeType, size }, params);
195
+ // Create a readable stream from the buffer
196
+ const stream = new ReadableStream({
197
+ start(controller) {
198
+ controller.enqueue(new Uint8Array(buffer));
199
+ controller.close();
200
+ },
201
+ });
202
+ // Use upload server to create and store the file
203
+ const inputFile = {
204
+ storageId: data.storageId || "buffer",
205
+ size,
206
+ type: mimeType,
207
+ fileName,
208
+ lastModified: Date.now(),
209
+ metadata: data.metadata
210
+ ? JSON.stringify(data.metadata)
211
+ : undefined,
212
+ };
213
+ const uploadFile = yield* uploadServer.upload(inputFile, clientId, stream);
214
+ // Complete the node execution with the upload file
215
+ return completeNodeExecution({
216
+ ...uploadFile,
217
+ flow: {
218
+ flowId,
219
+ nodeId: id,
220
+ jobId,
221
+ },
222
+ });
223
+ }
224
+ default:
225
+ throw yield* UploadistaError.fromCode("VALIDATION_ERROR", {
226
+ cause: new Error("Invalid operation"),
227
+ }).toEffect();
228
+ }
229
+ });
230
+ },
231
+ });
232
+ });
233
+ }