@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,60 @@
1
+ import type { UploadistaError } from "@uploadista/core/errors";
2
+ import { Context, type Effect } from "effect";
3
+ import type { OptimizeParams } from "./types/optimize-node";
4
+ import type { ResizeParams } from "./types/resize-node";
5
+
6
+ /**
7
+ * Shape definition for the Image Plugin interface.
8
+ * Defines the contract that all image processing implementations must follow.
9
+ */
10
+ export type ImagePluginShape = {
11
+ /**
12
+ * Optimizes an image by adjusting quality and format.
13
+ *
14
+ * @param input - The input image as a Uint8Array
15
+ * @param options - Optimization parameters including quality and format
16
+ * @returns An Effect that resolves to the optimized image as a Uint8Array
17
+ * @throws {UploadistaError} When image optimization fails
18
+ */
19
+ optimize: (
20
+ input: Uint8Array,
21
+ options: OptimizeParams
22
+ ) => Effect.Effect<Uint8Array, UploadistaError>;
23
+
24
+ /**
25
+ * Resizes an image to specified dimensions.
26
+ *
27
+ * @param input - The input image as a Uint8Array
28
+ * @param options - Resize parameters including width, height, and fit mode
29
+ * @returns An Effect that resolves to the resized image as a Uint8Array
30
+ * @throws {UploadistaError} When image resizing fails
31
+ */
32
+ resize: (
33
+ input: Uint8Array,
34
+ options: ResizeParams
35
+ ) => Effect.Effect<Uint8Array, UploadistaError>;
36
+ };
37
+
38
+ /**
39
+ * Context tag for the Image Plugin.
40
+ *
41
+ * This tag provides a type-safe way to access image processing functionality
42
+ * throughout the application using Effect's dependency injection system.
43
+ *
44
+ * @example
45
+ * ```typescript
46
+ * import { ImagePlugin } from "@uploadista/core/flow/plugins";
47
+ *
48
+ * // In your flow node
49
+ * const program = Effect.gen(function* () {
50
+ * const imagePlugin = yield* ImagePlugin;
51
+ * const optimized = yield* imagePlugin.optimize(imageData, { quality: 80, format: "webp" });
52
+ * const resized = yield* imagePlugin.resize(optimized, { width: 800, height: 600, fit: "cover" });
53
+ * return resized;
54
+ * });
55
+ * ```
56
+ */
57
+ export class ImagePlugin extends Context.Tag("ImagePlugin")<
58
+ ImagePlugin,
59
+ ImagePluginShape
60
+ >() {}
@@ -0,0 +1,16 @@
1
+ import { z } from "zod";
2
+
3
+ /**
4
+ * Zod schema for validating describe image node parameters.
5
+ * Defines the structure and validation rules for image description requests.
6
+ */
7
+ export const describeImageParamsSchema = z.object({
8
+ /** Optional service type to use for image description (currently supports "replicate") */
9
+ serviceType: z.enum(["replicate"]).optional(),
10
+ });
11
+
12
+ /**
13
+ * Parameters for the describe image node.
14
+ * Controls which AI service to use for generating image descriptions.
15
+ */
16
+ export type DescribeImageParams = z.infer<typeof describeImageParamsSchema>;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Re-exports all type definitions for flow plugin nodes.
3
+ * This module provides a centralized way to import all plugin node types.
4
+ */
5
+
6
+ export * from "./describe-image-node";
7
+ export * from "./optimize-node";
8
+ export * from "./remove-background-node";
9
+ export * from "./resize-node";
@@ -0,0 +1,18 @@
1
+ import { z } from "zod";
2
+
3
+ /**
4
+ * Zod schema for validating image optimization parameters.
5
+ * Defines the structure and validation rules for image optimization requests.
6
+ */
7
+ export const optimizeParamsSchema = z.object({
8
+ /** Image quality as a percentage (0-100) */
9
+ quality: z.number().min(0).max(100),
10
+ /** Output image format */
11
+ format: z.enum(["jpeg", "webp", "png", "avif"] as const),
12
+ });
13
+
14
+ /**
15
+ * Parameters for the image optimization node.
16
+ * Controls quality and format settings for image optimization.
17
+ */
18
+ export type OptimizeParams = z.infer<typeof optimizeParamsSchema>;
@@ -0,0 +1,18 @@
1
+ import { z } from "zod";
2
+
3
+ /**
4
+ * Zod schema for validating remove background node parameters.
5
+ * Defines the structure and validation rules for background removal requests.
6
+ */
7
+ export const removeBackgroundParamsSchema = z.object({
8
+ /** Optional service type to use for background removal (currently supports "replicate") */
9
+ serviceType: z.enum(["replicate"]).optional(),
10
+ });
11
+
12
+ /**
13
+ * Parameters for the remove background node.
14
+ * Controls which AI service to use for background removal processing.
15
+ */
16
+ export type RemoveBackgroundParams = z.infer<
17
+ typeof removeBackgroundParamsSchema
18
+ >;
@@ -0,0 +1,26 @@
1
+ import { z } from "zod";
2
+
3
+ /**
4
+ * Zod schema for validating image resize parameters.
5
+ * Defines the structure and validation rules for image resizing requests.
6
+ * Requires at least one dimension (width or height) to be specified.
7
+ */
8
+ export const resizeParamsSchema = z
9
+ .object({
10
+ /** Target width in pixels (optional) */
11
+ width: z.number().positive().optional(),
12
+ /** Target height in pixels (optional) */
13
+ height: z.number().positive().optional(),
14
+ /** How the image should fit within the specified dimensions */
15
+ fit: z.enum(["contain", "cover", "fill"]),
16
+ })
17
+ .refine(
18
+ (data) => data.width || data.height,
19
+ "Either width or height must be specified for resize"
20
+ );
21
+
22
+ /**
23
+ * Parameters for the image resize node.
24
+ * Controls the target dimensions and fitting behavior for image resizing.
25
+ */
26
+ export type ResizeParams = z.infer<typeof resizeParamsSchema>;
@@ -0,0 +1,69 @@
1
+ import type { UploadistaError } from "@uploadista/core/errors";
2
+ import { Context, type Effect } from "effect";
3
+ import type { UploadFile } from "@/types";
4
+
5
+ /**
6
+ * Parameters for creating a ZIP archive.
7
+ */
8
+ export type ZipParams = {
9
+ /** Name of the ZIP file to create */
10
+ zipName: string;
11
+ /** Whether to include file metadata in the ZIP archive */
12
+ includeMetadata: boolean;
13
+ };
14
+
15
+ /**
16
+ * Input data structure for ZIP operations.
17
+ * Represents a single file to be included in the ZIP archive.
18
+ */
19
+ export type ZipInput = {
20
+ /** Unique identifier for the file */
21
+ id: string;
22
+ /** Binary data of the file */
23
+ data: Uint8Array;
24
+ /** File metadata including name, size, type, etc. */
25
+ metadata: UploadFile["metadata"];
26
+ };
27
+
28
+ /**
29
+ * Shape definition for the ZIP Plugin interface.
30
+ * Defines the contract that all ZIP implementations must follow.
31
+ */
32
+ export type ZipPluginShape = {
33
+ /**
34
+ * Creates a ZIP archive from multiple input files.
35
+ *
36
+ * @param inputs - Array of files to include in the ZIP archive
37
+ * @param options - Configuration options for the ZIP creation
38
+ * @returns An Effect that resolves to the ZIP file as a Uint8Array
39
+ * @throws {UploadistaError} When ZIP creation fails
40
+ */
41
+ zip: (
42
+ inputs: ZipInput[],
43
+ options: ZipParams
44
+ ) => Effect.Effect<Uint8Array, UploadistaError>;
45
+ // unzip: (input: ZipInput) => Effect.Effect<Uint8Array, UploadistaError>;
46
+ };
47
+
48
+ /**
49
+ * Context tag for the ZIP Plugin.
50
+ *
51
+ * This tag provides a type-safe way to access ZIP functionality
52
+ * throughout the application using Effect's dependency injection system.
53
+ *
54
+ * @example
55
+ * ```typescript
56
+ * import { ZipPlugin } from "@uploadista/core/flow/plugins";
57
+ *
58
+ * // In your flow node
59
+ * const program = Effect.gen(function* () {
60
+ * const zipPlugin = yield* ZipPlugin;
61
+ * const zipData = yield* zipPlugin.zip(files, { zipName: "archive.zip", includeMetadata: true });
62
+ * return zipData;
63
+ * });
64
+ * ```
65
+ */
66
+ export class ZipPlugin extends Context.Tag("ZipPlugin")<
67
+ ZipPlugin,
68
+ ZipPluginShape
69
+ >() {}
@@ -0,0 +1,279 @@
1
+ /**
2
+ * biome-ignore-all lint/suspicious/noExplicitAny: broadly-typed generics require runtime schema placeholders
3
+ */
4
+ import { Effect } from "effect";
5
+ import { z } from "zod";
6
+ import type { UploadistaError as CoreUploadistaError } from "../errors";
7
+ import { UploadistaError } from "../errors";
8
+ import type { UploadServer } from "../upload";
9
+ import type { FlowEvent } from "./event";
10
+ import type { Flow, FlowExecutionResult } from "./flow";
11
+ import { createFlowWithSchema } from "./flow";
12
+ import { NodeType } from "./node";
13
+ import type {
14
+ FlowEdge,
15
+ FlowNode,
16
+ TypeCompatibilityChecker,
17
+ } from "./types/flow-types";
18
+
19
+ export type NodeDefinition<TNodeError = never, TNodeRequirements = never> =
20
+ | FlowNode<any, any, CoreUploadistaError>
21
+ | Effect.Effect<
22
+ FlowNode<any, any, CoreUploadistaError>,
23
+ TNodeError,
24
+ TNodeRequirements
25
+ >;
26
+
27
+ export type NodeDefinitionsRecord = Record<string, NodeDefinition<any, any>>;
28
+
29
+ type NodeDefinitionError<T> = T extends Effect.Effect<
30
+ FlowNode<any, any, CoreUploadistaError>,
31
+ infer TError,
32
+ any
33
+ >
34
+ ? TError
35
+ : never;
36
+
37
+ type NodeDefinitionRequirements<T> = T extends Effect.Effect<
38
+ FlowNode<any, any, CoreUploadistaError>,
39
+ any,
40
+ infer TRequirements
41
+ >
42
+ ? TRequirements
43
+ : never;
44
+
45
+ type NodesErrorUnion<TNodes extends NodeDefinitionsRecord> = {
46
+ [K in keyof TNodes]: NodeDefinitionError<TNodes[K]>;
47
+ }[keyof TNodes];
48
+
49
+ type NodesRequirementsUnion<TNodes extends NodeDefinitionsRecord> = {
50
+ [K in keyof TNodes]: NodeDefinitionRequirements<TNodes[K]>;
51
+ }[keyof TNodes];
52
+
53
+ export type FlowRequirements<TNodes extends NodeDefinitionsRecord> =
54
+ NodesRequirementsUnion<TNodes>;
55
+
56
+ export type FlowPluginRequirements<TNodes extends NodeDefinitionsRecord> =
57
+ Exclude<FlowRequirements<TNodes>, UploadServer>;
58
+
59
+ type InferNode<T> = T extends FlowNode<any, any, CoreUploadistaError>
60
+ ? T
61
+ : T extends Effect.Effect<infer R, any, any>
62
+ ? R extends FlowNode<any, any, CoreUploadistaError>
63
+ ? R
64
+ : never
65
+ : never;
66
+
67
+ type ResolvedNodesRecord<TNodes extends NodeDefinitionsRecord> = {
68
+ [K in keyof TNodes]: InferNode<TNodes[K]>;
69
+ };
70
+
71
+ type ExtractKeysByNodeType<
72
+ TNodes extends NodeDefinitionsRecord,
73
+ TType extends NodeType,
74
+ > = {
75
+ [K in keyof TNodes]: InferNode<TNodes[K]>["type"] extends TType ? K : never;
76
+ }[keyof TNodes];
77
+
78
+ type SchemaInfer<T> = T extends z.ZodTypeAny ? z.infer<T> : never;
79
+
80
+ export type FlowInputMap<TNodes extends NodeDefinitionsRecord> = {
81
+ [K in Extract<
82
+ ExtractKeysByNodeType<TNodes, NodeType.input>,
83
+ string
84
+ >]: SchemaInfer<InferNode<TNodes[K]>["inputSchema"]>;
85
+ };
86
+
87
+ export type FlowOutputMap<TNodes extends NodeDefinitionsRecord> = {
88
+ [K in Extract<
89
+ ExtractKeysByNodeType<TNodes, NodeType.output>,
90
+ string
91
+ >]: SchemaInfer<InferNode<TNodes[K]>["outputSchema"]>;
92
+ };
93
+
94
+ type FlowInputUnion<TNodes extends NodeDefinitionsRecord> = {
95
+ [K in Extract<
96
+ ExtractKeysByNodeType<TNodes, NodeType.input>,
97
+ string
98
+ >]: SchemaInfer<InferNode<TNodes[K]>["inputSchema"]>;
99
+ }[Extract<ExtractKeysByNodeType<TNodes, NodeType.input>, string>];
100
+
101
+ type FlowOutputUnion<TNodes extends NodeDefinitionsRecord> = {
102
+ [K in Extract<
103
+ ExtractKeysByNodeType<TNodes, NodeType.output>,
104
+ string
105
+ >]: SchemaInfer<InferNode<TNodes[K]>["outputSchema"]>;
106
+ }[Extract<ExtractKeysByNodeType<TNodes, NodeType.output>, string>];
107
+
108
+ type NodeKey<TNodes extends NodeDefinitionsRecord> = Extract<
109
+ keyof TNodes,
110
+ string
111
+ >;
112
+
113
+ export type TypedFlowEdge<TNodes extends NodeDefinitionsRecord> = {
114
+ source: NodeKey<TNodes>;
115
+ target: NodeKey<TNodes>;
116
+ sourcePort?: string;
117
+ targetPort?: string;
118
+ };
119
+
120
+ export type TypedFlowConfig<TNodes extends NodeDefinitionsRecord> = {
121
+ flowId: string;
122
+ name: string;
123
+ nodes: TNodes;
124
+ edges: Array<TypedFlowEdge<TNodes>>;
125
+ typeChecker?: TypeCompatibilityChecker;
126
+ onEvent?: (
127
+ event: FlowEvent,
128
+ ) => Effect.Effect<{ eventId: string | null }, CoreUploadistaError>;
129
+ parallelExecution?: {
130
+ enabled?: boolean;
131
+ maxConcurrency?: number;
132
+ };
133
+ inputSchema?: z.ZodTypeAny;
134
+ outputSchema?: z.ZodTypeAny;
135
+ };
136
+
137
+ declare const typedFlowInputsSymbol: unique symbol;
138
+ declare const typedFlowOutputsSymbol: unique symbol;
139
+ declare const typedFlowPluginsSymbol: unique symbol;
140
+
141
+ export type TypedFlow<
142
+ TNodes extends NodeDefinitionsRecord,
143
+ TInputSchema extends z.ZodTypeAny,
144
+ TOutputSchema extends z.ZodTypeAny,
145
+ > = Flow<TInputSchema, TOutputSchema, FlowRequirements<TNodes>> & {
146
+ run: (args: {
147
+ inputs?: Partial<FlowInputMap<TNodes>>;
148
+ storageId: string;
149
+ jobId: string;
150
+ }) => Effect.Effect<
151
+ FlowExecutionResult<FlowOutputMap<TNodes>>,
152
+ CoreUploadistaError,
153
+ FlowRequirements<TNodes>
154
+ >;
155
+ resume: (args: {
156
+ jobId: string;
157
+ storageId: string;
158
+ nodeResults: Record<string, unknown>;
159
+ executionState: {
160
+ executionOrder: string[];
161
+ currentIndex: number;
162
+ inputs: Partial<FlowInputMap<TNodes>>;
163
+ };
164
+ }) => Effect.Effect<
165
+ FlowExecutionResult<FlowOutputMap<TNodes>>,
166
+ CoreUploadistaError,
167
+ FlowRequirements<TNodes>
168
+ >;
169
+ readonly [typedFlowInputsSymbol]?: FlowInputMap<TNodes>;
170
+ readonly [typedFlowOutputsSymbol]?: FlowOutputMap<TNodes>;
171
+ readonly [typedFlowPluginsSymbol]?: FlowPluginRequirements<TNodes>;
172
+ };
173
+
174
+ const buildUnionSchema = (
175
+ schemas: z.ZodTypeAny[],
176
+ fallback: z.ZodTypeAny,
177
+ ): z.ZodTypeAny => {
178
+ if (schemas.length === 0) {
179
+ return fallback;
180
+ }
181
+
182
+ const [first, ...rest] = schemas as [z.ZodTypeAny, ...z.ZodTypeAny[]];
183
+ return rest.reduce<z.ZodTypeAny>(
184
+ (acc, schema) => z.union([acc, schema]),
185
+ first,
186
+ );
187
+ };
188
+
189
+ export function createFlow<TNodes extends NodeDefinitionsRecord>(
190
+ config: TypedFlowConfig<TNodes>,
191
+ ): Effect.Effect<
192
+ TypedFlow<
193
+ TNodes,
194
+ z.ZodType<FlowInputUnion<TNodes>>,
195
+ z.ZodType<FlowOutputUnion<TNodes>>
196
+ >,
197
+ NodesErrorUnion<TNodes> | UploadistaError,
198
+ FlowRequirements<TNodes>
199
+ > {
200
+ return Effect.gen(function* () {
201
+ const nodeEntries = Object.entries(config.nodes) as Array<
202
+ [NodeKey<TNodes>, NodeDefinition]
203
+ >;
204
+
205
+ const resolveNode = (
206
+ node: NodeDefinition,
207
+ ): Effect.Effect<
208
+ FlowNode<any, any, CoreUploadistaError>,
209
+ NodesErrorUnion<TNodes>,
210
+ FlowRequirements<TNodes>
211
+ > =>
212
+ Effect.isEffect(node)
213
+ ? (node as Effect.Effect<
214
+ FlowNode<any, any, CoreUploadistaError>,
215
+ NodesErrorUnion<TNodes>,
216
+ FlowRequirements<TNodes>
217
+ >)
218
+ : Effect.succeed(node as FlowNode<any, any, CoreUploadistaError>);
219
+
220
+ const resolvedEntries = yield* Effect.forEach(nodeEntries, ([key, node]) =>
221
+ Effect.flatMap(resolveNode(node), (resolvedNode) => {
222
+ if (resolvedNode.id !== key) {
223
+ return Effect.fail(
224
+ UploadistaError.fromCode("FLOW_NODE_ERROR", {
225
+ cause: new Error(
226
+ `Node key ${key} does not match node id ${resolvedNode.id}`,
227
+ ),
228
+ }),
229
+ );
230
+ }
231
+ return Effect.succeed([key, resolvedNode] as const);
232
+ }),
233
+ );
234
+
235
+ const resolvedRecord = Object.fromEntries(
236
+ resolvedEntries,
237
+ ) as ResolvedNodesRecord<TNodes>;
238
+ const resolvedNodes = resolvedEntries.map(([, node]) => node);
239
+
240
+ const inputSchemas = resolvedEntries
241
+ .filter(([, node]) => node.type === NodeType.input)
242
+ .map(([, node]) => node.inputSchema);
243
+
244
+ const outputSchemas = resolvedEntries
245
+ .filter(([, node]) => node.type === NodeType.output)
246
+ .map(([, node]) => node.outputSchema);
247
+
248
+ const inputSchema =
249
+ config.inputSchema ?? buildUnionSchema(inputSchemas, z.unknown());
250
+
251
+ const outputSchema =
252
+ config.outputSchema ?? buildUnionSchema(outputSchemas, z.unknown());
253
+
254
+ const flowEdges: FlowEdge[] = config.edges.map((edge) => ({
255
+ source: resolvedRecord[edge.source]?.id ?? edge.source,
256
+ target: resolvedRecord[edge.target]?.id ?? edge.target,
257
+ sourcePort: edge.sourcePort,
258
+ targetPort: edge.targetPort,
259
+ }));
260
+
261
+ const flow = yield* createFlowWithSchema({
262
+ flowId: config.flowId,
263
+ name: config.name,
264
+ nodes: resolvedNodes,
265
+ edges: flowEdges,
266
+ inputSchema,
267
+ outputSchema,
268
+ typeChecker: config.typeChecker,
269
+ onEvent: config.onEvent,
270
+ parallelExecution: config.parallelExecution,
271
+ });
272
+
273
+ return flow as unknown as TypedFlow<
274
+ TNodes,
275
+ z.ZodType<FlowInputUnion<TNodes>>,
276
+ z.ZodType<FlowOutputUnion<TNodes>>
277
+ >;
278
+ });
279
+ }
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Conditional execution rules for flow nodes.
3
+ *
4
+ * Conditions allow nodes to execute conditionally based on file properties or metadata.
5
+ * They are evaluated before node execution and can skip nodes that don't match.
6
+ *
7
+ * @module flow/types/flow-file
8
+ * @see {@link FlowNode} for how conditions are used in nodes
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * // Only process images larger than 1MB
13
+ * const condition: FlowCondition = {
14
+ * field: "size",
15
+ * operator: "greaterThan",
16
+ * value: 1024 * 1024
17
+ * };
18
+ *
19
+ * // Only process JPEG images
20
+ * const jpegCondition: FlowCondition = {
21
+ * field: "mimeType",
22
+ * operator: "startsWith",
23
+ * value: "image/jpeg"
24
+ * };
25
+ * ```
26
+ */
27
+
28
+ /**
29
+ * Represents a conditional rule for node execution.
30
+ *
31
+ * @property field - The file property to check
32
+ * @property operator - The comparison operator to apply
33
+ * @property value - The value to compare against
34
+ *
35
+ * @remarks
36
+ * - Fields can check file metadata (mimeType, size) or image properties (width, height)
37
+ * - String operators (contains, startsWith) work with string values
38
+ * - Numeric operators (greaterThan, lessThan) work with numeric values
39
+ * - The extension field checks the file extension without the dot
40
+ */
41
+ export type FlowCondition = {
42
+ field: "mimeType" | "size" | "width" | "height" | "extension";
43
+ operator:
44
+ | "equals"
45
+ | "notEquals"
46
+ | "greaterThan"
47
+ | "lessThan"
48
+ | "contains"
49
+ | "startsWith";
50
+ value: string | number;
51
+ };
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Flow job tracking and state management types.
3
+ *
4
+ * A FlowJob represents a single execution instance of a flow, tracking its progress,
5
+ * node results, and execution state. Jobs can be paused and resumed, making them
6
+ * suitable for long-running or interactive flows.
7
+ *
8
+ * @module flow/types/flow-job
9
+ * @see {@link FlowServer} for job management operations
10
+ */
11
+
12
+ // import type { FlowData } from "@/flow";
13
+
14
+ /**
15
+ * Status of an individual node within a flow job.
16
+ *
17
+ * Node tasks follow this lifecycle:
18
+ * started → pending → running → (completed | paused | failed)
19
+ */
20
+ export type FlowJobTaskStatus =
21
+ | "started"
22
+ | "pending"
23
+ | "running"
24
+ | "completed"
25
+ | "paused"
26
+ | "failed";
27
+
28
+ /**
29
+ * Represents a single node's execution within a flow job.
30
+ *
31
+ * Tasks track individual node execution, storing results, errors, and retry information.
32
+ * They allow monitoring of which nodes have completed and accessing intermediate results.
33
+ *
34
+ * @property nodeId - Unique identifier of the node this task represents
35
+ * @property status - Current execution status of the node
36
+ * @property result - Output data from the node (if completed successfully)
37
+ * @property error - Error message if the node failed
38
+ * @property retryCount - Number of retry attempts made before success or final failure
39
+ * @property createdAt - When the task was created
40
+ * @property updatedAt - When the task was last updated
41
+ */
42
+ export type FlowJobTask = {
43
+ nodeId: string;
44
+ status: FlowJobTaskStatus;
45
+ result?: unknown; // Node execution result
46
+ error?: string; // Error message from failed execution
47
+ retryCount?: number; // Number of retry attempts made
48
+ createdAt: Date;
49
+ updatedAt: Date;
50
+ };
51
+
52
+ /**
53
+ * Represents a flow execution job with full state tracking.
54
+ *
55
+ * Jobs are created when a flow is executed and track the entire execution lifecycle.
56
+ * They store node results, handle paused states, and manage cleanup of intermediate files.
57
+ *
58
+ * @property id - Unique job identifier (UUID)
59
+ * @property flowId - The flow being executed
60
+ * @property storageId - Storage location for file outputs
61
+ * @property clientId - Client that initiated the job (for authorization)
62
+ * @property status - Overall job status
63
+ * @property createdAt - When the job was created
64
+ * @property updatedAt - When the job was last updated
65
+ * @property tasks - Array of node execution tasks
66
+ * @property error - Error message if the job failed
67
+ * @property endedAt - When the job completed or failed
68
+ * @property result - Final output from the flow (only set when completed)
69
+ * @property pausedAt - Node ID where execution is paused (if applicable)
70
+ * @property executionState - State needed to resume a paused flow
71
+ * @property intermediateFiles - File IDs to cleanup after completion
72
+ *
73
+ * @remarks
74
+ * - Jobs can be paused at nodes that return `{ type: "waiting" }`
75
+ * - Paused jobs store execution state and can be resumed with new data
76
+ * - Intermediate files from non-output nodes are automatically cleaned up
77
+ * - Tasks are updated as nodes progress through their lifecycle
78
+ *
79
+ * @example
80
+ * ```typescript
81
+ * // Create and monitor a job
82
+ * const job = yield* flowServer.runFlow({
83
+ * flowId: "image-pipeline",
84
+ * storageId: "storage-1",
85
+ * inputs: { input: myFile }
86
+ * });
87
+ *
88
+ * // Poll for status
89
+ * const status = yield* flowServer.getJobStatus(job.id);
90
+ * if (status.status === "completed") {
91
+ * console.log("Final result:", status.result);
92
+ * } else if (status.status === "paused") {
93
+ * // Resume with additional data
94
+ * yield* flowServer.continueFlow({
95
+ * jobId: job.id,
96
+ * nodeId: status.pausedAt,
97
+ * newData: additionalChunk
98
+ * });
99
+ * }
100
+ * ```
101
+ */
102
+ export type FlowJob = {
103
+ id: string;
104
+ flowId: string;
105
+ storageId: string;
106
+ clientId: string | null;
107
+ status: FlowJobStatus;
108
+ createdAt: Date;
109
+ updatedAt: Date;
110
+ tasks: FlowJobTask[];
111
+ error?: string;
112
+ endedAt?: Date;
113
+ // Final flow execution result (only populated when completed)
114
+ result?: unknown;
115
+ // Paused execution state
116
+ pausedAt?: string; // nodeId where execution is paused
117
+ executionState?: {
118
+ executionOrder: string[]; // Topological sort order
119
+ currentIndex: number; // Where we are in execution
120
+ inputs: Record<string, unknown>; // Original inputs
121
+ };
122
+ // Intermediate files to cleanup after flow completion
123
+ intermediateFiles?: string[]; // UploadFile IDs from non-output nodes
124
+ };
125
+
126
+ /**
127
+ * Overall status of a flow job.
128
+ *
129
+ * Job lifecycle: started → running → (completed | failed)
130
+ * Or with pauses: started → running → paused → running → (completed | failed)
131
+ */
132
+ export type FlowJobStatus =
133
+ | "pending"
134
+ | "running"
135
+ | "completed"
136
+ | "failed"
137
+ | "started"
138
+ | "paused";