@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,352 @@
1
+ # Flow Engine
2
+
3
+ A flexible and extensible flow engine for executing directed acyclic graphs (DAGs) of processing nodes.
4
+
5
+ ## Overview
6
+
7
+ The Flow Engine allows you to create complex processing pipelines by connecting nodes together. Each node represents a processing step, and edges define the data flow between nodes.
8
+
9
+ ## Architecture
10
+
11
+ ### Core Components
12
+
13
+ - **Flow**: The main container that holds nodes and edges
14
+ - **Node**: Individual processing units with input/output capabilities
15
+ - **Edge**: Connections between nodes defining data flow
16
+ - **Result**: Typed results for success, error, and cancellation states
17
+
18
+ ### Node Types
19
+
20
+ - **Input**: Entry point nodes that receive initial data
21
+ - **Process**: Processing nodes that transform data
22
+ - **Output**: Final nodes that produce the end result
23
+ - **Conditional**: Nodes that route flow based on conditions
24
+ - **Multiplex**: Nodes that split input into multiple parallel outputs
25
+ - **Merge**: Nodes that combine multiple inputs into a single output
26
+
27
+ ## New Advanced Features
28
+
29
+ ### 1. Zip Node
30
+
31
+ The zip node allows you to combine multiple files into a single archive:
32
+
33
+ ```typescript
34
+ import { createZipNode } from "./nodes/zip-node";
35
+
36
+ const zipNode = createZipNode("zip-files", {
37
+ zipName: "archive.zip",
38
+ includeMetadata: true,
39
+ });
40
+ ```
41
+
42
+ **Features:**
43
+
44
+ - Combines multiple input files into a single zip archive
45
+ - Supports both single files and file batches
46
+ - Optional metadata inclusion
47
+ - Customizable archive name
48
+
49
+ ### 2. Conditional Node
50
+
51
+ The conditional node routes flow based on file properties:
52
+
53
+ ```typescript
54
+ import { createConditionalNode } from "./nodes/conditional-node";
55
+
56
+ const conditionalNode = createConditionalNode("size-check", {
57
+ field: "size",
58
+ operator: "greaterThan",
59
+ value: 1024 * 1024, // 1MB
60
+ trueBranch: "large-file-processor",
61
+ falseBranch: "small-file-processor",
62
+ });
63
+ ```
64
+
65
+ **Supported Conditions:**
66
+
67
+ - **Fields**: `mimeType`, `size`, `width`, `height`, `extension`
68
+ - **Operators**: `equals`, `notEquals`, `greaterThan`, `lessThan`, `contains`, `startsWith`
69
+
70
+ ### 3. Multiplex Node
71
+
72
+ The multiplex node splits a single input into multiple parallel outputs:
73
+
74
+ ```typescript
75
+ import { createMultiplexNode } from "./nodes/multiplex-node";
76
+
77
+ const multiplexNode = createMultiplexNode("multiplex", {
78
+ outputCount: 3,
79
+ strategy: "copy", // or "split"
80
+ });
81
+ ```
82
+
83
+ **Strategies:**
84
+
85
+ - **Copy**: Creates multiple copies of the same file
86
+ - **Split**: Splits the file into chunks
87
+
88
+ ### 4. Merge Node
89
+
90
+ The merge node combines multiple inputs into a single output:
91
+
92
+ ```typescript
93
+ import { createMergeNode } from "./nodes/merge-node";
94
+
95
+ const mergeNode = createMergeNode("merge-files", {
96
+ strategy: "batch", // or "concat"
97
+ });
98
+ ```
99
+
100
+ **Strategies:**
101
+
102
+ - **Batch**: Returns files as a batch
103
+ - **Concat**: Concatenates all files into one
104
+
105
+ ## Usage
106
+
107
+ ### Basic Example
108
+
109
+ ```typescript
110
+ import type { FlowNode } from "./node";
111
+
112
+ import { createFlow } from "./flow";
113
+ import { NodeType } from "./node";
114
+ import { successResult } from "./result";
115
+
116
+ // Define your data type
117
+ type MyData = {
118
+ value: number;
119
+ processed: boolean;
120
+ };
121
+
122
+ // Create nodes
123
+ const inputNode: FlowNode<MyData, MyData> = {
124
+ id: "input",
125
+ name: "Input",
126
+ description: "Input node",
127
+ type: NodeType.input,
128
+ run: async ({ data }) => {
129
+ return successResult(data);
130
+ },
131
+ };
132
+
133
+ const processNode: FlowNode<MyData, MyData> = {
134
+ id: "process",
135
+ name: "Process",
136
+ description: "Process node",
137
+ type: NodeType.process,
138
+ run: async ({ data }) => {
139
+ return successResult({
140
+ ...data,
141
+ value: data.value * 2,
142
+ processed: true,
143
+ });
144
+ },
145
+ };
146
+
147
+ const outputNode: FlowNode<MyData, MyData> = {
148
+ id: "output",
149
+ name: "Output",
150
+ description: "Output node",
151
+ type: NodeType.output,
152
+ run: async ({ data }) => {
153
+ return successResult(data);
154
+ },
155
+ };
156
+
157
+ // Create the flow
158
+ const flow = createFlow({
159
+ flowId: "simple-flow",
160
+ nodes: [inputNode, processNode, outputNode],
161
+ edges: [
162
+ { source: "input", target: "process" },
163
+ { source: "process", target: "output" },
164
+ ],
165
+ });
166
+
167
+ // Run the flow
168
+ const result = await flow.run({
169
+ value: 5,
170
+ processed: false,
171
+ });
172
+
173
+ if (result.type === "success") {
174
+ console.log("Result:", result.value);
175
+ // Output: { value: 10, processed: true }
176
+ }
177
+ ```
178
+
179
+ ### Error Handling
180
+
181
+ The flow engine provides comprehensive error handling:
182
+
183
+ ```typescript
184
+ const errorNode: FlowNode<MyData, MyData> = {
185
+ id: "error",
186
+ name: "Error Node",
187
+ type: NodeType.process,
188
+ run: async () => {
189
+ throw new Error("Something went wrong");
190
+ },
191
+ };
192
+
193
+ const flow = createFlow({
194
+ nodes: [inputNode, errorNode],
195
+ edges: [{ source: "input", target: "error" }],
196
+ });
197
+
198
+ const result = await flow.run(inputData);
199
+
200
+ if (result.type === "error") {
201
+ console.error("Flow failed:", result.error);
202
+ }
203
+ ```
204
+
205
+ ### Cancellation
206
+
207
+ Flows can be cancelled during execution:
208
+
209
+ ```typescript
210
+ const longRunningNode: FlowNode<MyData, MyData> = {
211
+ id: "long-running",
212
+ name: "Long Running",
213
+ type: NodeType.process,
214
+ run: async ({ runId }) => {
215
+ // Simulate long-running task
216
+ await new Promise(resolve => setTimeout(resolve, 5000));
217
+ return successResult(data);
218
+ },
219
+ cancel: (runId) => {
220
+ // Handle cancellation
221
+ console.log(`Cancelling node ${runId}`);
222
+ },
223
+ };
224
+
225
+ const flow = createFlow({
226
+ nodes: [inputNode, longRunningNode],
227
+ edges: [{ source: "input", target: "long-running" }],
228
+ });
229
+
230
+ // Start the flow
231
+ const promise = flow.run(inputData);
232
+
233
+ // Cancel after 1 second
234
+ setTimeout(() => {
235
+ flow.cancel?.(runId);
236
+ }, 1000);
237
+
238
+ const result = await promise;
239
+ if (result.type === "cancelled") {
240
+ console.log("Flow was cancelled");
241
+ }
242
+ ```
243
+
244
+ ## Features
245
+
246
+ ### Topological Sorting
247
+
248
+ The engine automatically determines the correct execution order using topological sorting, ensuring nodes are executed in the right sequence based on their dependencies.
249
+
250
+ ### Cycle Detection
251
+
252
+ The engine detects cycles in the flow graph and returns an error if any are found.
253
+
254
+ ### Type Safety
255
+
256
+ Full TypeScript support with generic types for input and output data.
257
+
258
+ ### Async Support
259
+
260
+ All nodes support asynchronous operations and proper error propagation.
261
+
262
+ ### Cancellation Support
263
+
264
+ Nodes can implement cancellation logic to handle graceful shutdowns.
265
+
266
+ ## Advanced Usage
267
+
268
+ ### Multiple Inputs
269
+
270
+ For nodes with multiple incoming edges, you can implement custom logic to merge inputs:
271
+
272
+ ```typescript
273
+ const mergeNode: FlowNode<MyData[], MyData> = {
274
+ id: "merge",
275
+ name: "Merge",
276
+ type: NodeType.process,
277
+ run: async ({ data }) => {
278
+ // Merge multiple inputs
279
+ const merged = data.reduce((acc, item) => ({
280
+ value: acc.value + item.value,
281
+ processed: acc.processed && item.processed,
282
+ }));
283
+ return successResult(merged);
284
+ },
285
+ };
286
+ ```
287
+
288
+ ### Conditional Execution
289
+
290
+ You can implement conditional logic in nodes:
291
+
292
+ ```typescript
293
+ const conditionalNode: FlowNode<MyData, MyData> = {
294
+ id: "conditional",
295
+ name: "Conditional",
296
+ type: NodeType.process,
297
+ run: async ({ data }) => {
298
+ if (data.value > 10) {
299
+ return successResult({ ...data, processed: true });
300
+ }
301
+ else {
302
+ return successResult({ ...data, processed: false });
303
+ }
304
+ },
305
+ };
306
+ ```
307
+
308
+ ## Best Practices
309
+
310
+ 1. **Use descriptive node names**: Make your nodes easy to understand and debug
311
+ 2. **Handle errors gracefully**: Always return proper error results from nodes
312
+ 3. **Keep nodes focused**: Each node should have a single responsibility
313
+ 4. **Test your flows**: Create unit tests for individual nodes and integration tests for flows
314
+ 5. **Monitor performance**: Use the runId and flowId for logging and monitoring
315
+
316
+ ## API Reference
317
+
318
+ ### Flow
319
+
320
+ ```typescript
321
+ type Flow<Input, Output> = {
322
+ nodes: FlowNode<Input, Output>[];
323
+ edges: FlowEdge[];
324
+ run: (input?: Input) => Promise<FlowResult<Output>>;
325
+ cancel?: (runId: string) => void;
326
+ };
327
+ ```
328
+
329
+ ### FlowNode
330
+
331
+ ```typescript
332
+ type FlowNode<Input, Output> = {
333
+ id: string;
334
+ name: string;
335
+ type: NodeType;
336
+ run: (args: {
337
+ data: Input;
338
+ runId: string;
339
+ flowId: string;
340
+ }) => Promise<FlowResult<Output>>;
341
+ cancel?: (runId: string) => void;
342
+ };
343
+ ```
344
+
345
+ ### FlowResult
346
+
347
+ ```typescript
348
+ type FlowResult<Value>
349
+ = | { type: "success"; value: Value }
350
+ | { type: "error"; error: string }
351
+ | { type: "cancelled" };
352
+ ```
@@ -0,0 +1,146 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { createFlowEdge, type FlowEdge } from "./edge";
3
+
4
+ describe("FlowEdge", () => {
5
+ describe("createFlowEdge", () => {
6
+ it("should create a basic edge with source and target", () => {
7
+ const edge = createFlowEdge({
8
+ source: "node1",
9
+ target: "node2",
10
+ });
11
+
12
+ expect(edge).toEqual({
13
+ source: "node1",
14
+ target: "node2",
15
+ sourcePort: undefined,
16
+ targetPort: undefined,
17
+ });
18
+ });
19
+
20
+ it("should create edge with source and target ports", () => {
21
+ const edge = createFlowEdge({
22
+ source: "node1",
23
+ target: "node2",
24
+ sourcePort: "output1",
25
+ targetPort: "input1",
26
+ });
27
+
28
+ expect(edge).toEqual({
29
+ source: "node1",
30
+ target: "node2",
31
+ sourcePort: "output1",
32
+ targetPort: "input1",
33
+ });
34
+ });
35
+
36
+ it("should create edge with only source port", () => {
37
+ const edge = createFlowEdge({
38
+ source: "node1",
39
+ target: "node2",
40
+ sourcePort: "output1",
41
+ });
42
+
43
+ expect(edge).toEqual({
44
+ source: "node1",
45
+ target: "node2",
46
+ sourcePort: "output1",
47
+ targetPort: undefined,
48
+ });
49
+ });
50
+
51
+ it("should create edge with only target port", () => {
52
+ const edge = createFlowEdge({
53
+ source: "node1",
54
+ target: "node2",
55
+ targetPort: "input1",
56
+ });
57
+
58
+ expect(edge).toEqual({
59
+ source: "node1",
60
+ target: "node2",
61
+ sourcePort: undefined,
62
+ targetPort: "input1",
63
+ });
64
+ });
65
+
66
+ it("should handle empty string ports", () => {
67
+ const edge = createFlowEdge({
68
+ source: "node1",
69
+ target: "node2",
70
+ sourcePort: "",
71
+ targetPort: "",
72
+ });
73
+
74
+ expect(edge).toEqual({
75
+ source: "node1",
76
+ target: "node2",
77
+ sourcePort: "",
78
+ targetPort: "",
79
+ });
80
+ });
81
+
82
+ it("should preserve all provided properties", () => {
83
+ const edgeData = {
84
+ source: "input-node",
85
+ target: "transform-node",
86
+ sourcePort: "file-output",
87
+ targetPort: "file-input",
88
+ };
89
+
90
+ const edge = createFlowEdge(edgeData);
91
+
92
+ expect(edge.source).toBe(edgeData.source);
93
+ expect(edge.target).toBe(edgeData.target);
94
+ expect(edge.sourcePort).toBe(edgeData.sourcePort);
95
+ expect(edge.targetPort).toBe(edgeData.targetPort);
96
+ });
97
+
98
+ it("should create valid FlowEdge type", () => {
99
+ const edge: FlowEdge = createFlowEdge({
100
+ source: "node1",
101
+ target: "node2",
102
+ });
103
+
104
+ // Type assertion test - if this compiles, the types are compatible
105
+ expect(edge).toHaveProperty("source");
106
+ expect(edge).toHaveProperty("target");
107
+ expect(edge).toHaveProperty("sourcePort");
108
+ expect(edge).toHaveProperty("targetPort");
109
+ });
110
+
111
+ it("should handle special characters in node names", () => {
112
+ const edge = createFlowEdge({
113
+ source: "node-with-dashes_and_underscores.123",
114
+ target: "another.node@domain.com",
115
+ sourcePort: "port/with/slashes",
116
+ targetPort: "port:with:colons",
117
+ });
118
+
119
+ expect(edge.source).toBe("node-with-dashes_and_underscores.123");
120
+ expect(edge.target).toBe("another.node@domain.com");
121
+ expect(edge.sourcePort).toBe("port/with/slashes");
122
+ expect(edge.targetPort).toBe("port:with:colons");
123
+ });
124
+
125
+ it("should create multiple edges with different configurations", () => {
126
+ const edges = [
127
+ createFlowEdge({ source: "a", target: "b" }),
128
+ createFlowEdge({ source: "b", target: "c", sourcePort: "out" }),
129
+ createFlowEdge({ source: "c", target: "d", targetPort: "in" }),
130
+ createFlowEdge({
131
+ source: "d",
132
+ target: "e",
133
+ sourcePort: "out",
134
+ targetPort: "in",
135
+ }),
136
+ ];
137
+
138
+ expect(edges).toHaveLength(4);
139
+ expect(edges[0]?.sourcePort).toBeUndefined();
140
+ expect(edges[1]?.sourcePort).toBe("out");
141
+ expect(edges[2]?.targetPort).toBe("in");
142
+ expect(edges[3]?.sourcePort).toBe("out");
143
+ expect(edges[3]?.targetPort).toBe("in");
144
+ });
145
+ });
146
+ });
@@ -0,0 +1,60 @@
1
+ import type { FlowEdge as EnhancedFlowEdge } from "./types/flow-types";
2
+
3
+ /**
4
+ * Represents a connection between two nodes in a flow, defining the data flow direction.
5
+ *
6
+ * Edges connect the output of a source node to the input of a target node,
7
+ * enabling data to flow through the processing pipeline in a directed acyclic graph (DAG).
8
+ */
9
+ export type FlowEdge = EnhancedFlowEdge;
10
+
11
+ /**
12
+ * Creates a flow edge connecting two nodes in a processing pipeline.
13
+ *
14
+ * Edges define how data flows between nodes. The data output from the source node
15
+ * becomes the input for the target node. For nodes with multiple inputs/outputs,
16
+ * ports can be specified to route data to specific connections.
17
+ *
18
+ * @param config - Edge configuration
19
+ * @param config.source - ID of the source node (data originates here)
20
+ * @param config.target - ID of the target node (data flows to here)
21
+ * @param config.sourcePort - Optional port name on the source node for multi-output nodes
22
+ * @param config.targetPort - Optional port name on the target node for multi-input nodes
23
+ *
24
+ * @returns A FlowEdge object representing the connection
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * // Simple edge connecting two nodes
29
+ * const edge = createFlowEdge({
30
+ * source: "input-1",
31
+ * target: "process-1"
32
+ * });
33
+ *
34
+ * // Edge with ports for multi-input/output nodes
35
+ * const portEdge = createFlowEdge({
36
+ * source: "multiplex-1",
37
+ * target: "merge-1",
38
+ * sourcePort: "out-a",
39
+ * targetPort: "in-1"
40
+ * });
41
+ * ```
42
+ */
43
+ export function createFlowEdge({
44
+ source,
45
+ target,
46
+ sourcePort,
47
+ targetPort,
48
+ }: {
49
+ source: string;
50
+ target: string;
51
+ sourcePort?: string;
52
+ targetPort?: string;
53
+ }): FlowEdge {
54
+ return {
55
+ source,
56
+ target,
57
+ sourcePort,
58
+ targetPort,
59
+ };
60
+ }