@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,67 @@
1
+ import { Effect } from "effect";
2
+ import { z } from "zod";
3
+ import { UploadistaError } from "../../errors";
4
+ import { type UploadFile } from "../../types";
5
+ import { UploadServer } from "../../upload";
6
+ /**
7
+ * Schema for storage node parameters.
8
+ * Currently empty but can be extended for storage-specific configuration.
9
+ */
10
+ export declare const storageParamsSchema: z.ZodObject<{}, z.core.$strip>;
11
+ /**
12
+ * Parameters for the storage node.
13
+ * Currently no parameters are required, but the schema is available for future extensions.
14
+ */
15
+ export type StorageParams = z.infer<typeof storageParamsSchema>;
16
+ /**
17
+ * Creates a storage node for storing files in the specified storage.
18
+ *
19
+ * The storage node handles the process of:
20
+ * 1. Reading the input file from the upload server
21
+ * 2. Checking if the file is already in the target storage
22
+ * 3. If not, transferring the file to the target storage
23
+ * 4. Applying optional post-processing
24
+ * 5. Returning the final stored file
25
+ *
26
+ * @param id - Unique identifier for the node
27
+ * @param postProcessFile - Optional function to process the file after storage
28
+ * @returns An Effect that creates a flow node configured for file storage
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * // Create basic storage node
33
+ * const storageNode = yield* createStorageNode("store-file");
34
+ *
35
+ * // Create storage node with post-processing
36
+ * const storageWithProcessing = yield* createStorageNode("store-and-process", (file) => {
37
+ * return Effect.succeed({
38
+ * ...file,
39
+ * metadata: { ...file.metadata, processed: true }
40
+ * });
41
+ * });
42
+ * ```
43
+ */
44
+ export declare function createStorageNode(id: string, postProcessFile?: (file: UploadFile) => Effect.Effect<UploadFile>): Effect.Effect<import("..").FlowNode<{
45
+ id: string;
46
+ offset: number;
47
+ storage: {
48
+ id: string;
49
+ type: string;
50
+ path?: string | undefined;
51
+ uploadId?: string | undefined;
52
+ bucket?: string | undefined;
53
+ };
54
+ size?: number | undefined;
55
+ metadata?: Record<string, string | number | boolean> | undefined;
56
+ creationDate?: string | undefined;
57
+ url?: string | undefined;
58
+ sizeIsDeferred?: boolean | undefined;
59
+ checksum?: string | undefined;
60
+ checksumAlgorithm?: string | undefined;
61
+ flow?: {
62
+ flowId: string;
63
+ nodeId: string;
64
+ jobId: string;
65
+ } | undefined;
66
+ }, UploadFile, UploadistaError>, never, UploadServer>;
67
+ //# sourceMappingURL=storage-node.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage-node.d.ts","sourceRoot":"","sources":["../../../src/flow/nodes/storage-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;AAC/C,OAAO,EAAE,KAAK,UAAU,EAAoB,MAAM,aAAa,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAK5C;;;GAGG;AACH,eAAO,MAAM,mBAAmB,gCAAe,CAAC;AAEhD;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,iBAAiB,CAC/B,EAAE,EAAE,MAAM,EACV,eAAe,GAAE,CAAC,IAAI,EAAE,UAAU,KAAK,MAAM,CAAC,MAAM,CAAC,UAAU,CACzC;;;;;;;;;;;;;;;;;;;;;;sDA2EvB"}
@@ -0,0 +1,94 @@
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 { createFlowNode, NodeType } from "../node";
7
+ import { completeNodeExecution } from "../types";
8
+ import { resolveUploadMetadata } from "../utils/resolve-upload-metadata";
9
+ /**
10
+ * Schema for storage node parameters.
11
+ * Currently empty but can be extended for storage-specific configuration.
12
+ */
13
+ export const storageParamsSchema = z.object({});
14
+ /**
15
+ * Creates a storage node for storing files in the specified storage.
16
+ *
17
+ * The storage node handles the process of:
18
+ * 1. Reading the input file from the upload server
19
+ * 2. Checking if the file is already in the target storage
20
+ * 3. If not, transferring the file to the target storage
21
+ * 4. Applying optional post-processing
22
+ * 5. Returning the final stored file
23
+ *
24
+ * @param id - Unique identifier for the node
25
+ * @param postProcessFile - Optional function to process the file after storage
26
+ * @returns An Effect that creates a flow node configured for file storage
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * // Create basic storage node
31
+ * const storageNode = yield* createStorageNode("store-file");
32
+ *
33
+ * // Create storage node with post-processing
34
+ * const storageWithProcessing = yield* createStorageNode("store-and-process", (file) => {
35
+ * return Effect.succeed({
36
+ * ...file,
37
+ * metadata: { ...file.metadata, processed: true }
38
+ * });
39
+ * });
40
+ * ```
41
+ */
42
+ export function createStorageNode(id, postProcessFile = (file) => Effect.succeed(file)) {
43
+ return Effect.gen(function* () {
44
+ const uploadServer = yield* UploadServer;
45
+ return yield* createFlowNode({
46
+ id,
47
+ name: "Storage",
48
+ description: "Stores a file in the storage",
49
+ type: NodeType.output,
50
+ inputSchema: uploadFileSchema,
51
+ outputSchema: uploadFileSchema,
52
+ run: ({ data: file, storageId, flowId, jobId, clientId }) => {
53
+ return Effect.gen(function* () {
54
+ const { type, fileName, metadata, metadataJson } = resolveUploadMetadata(file.metadata);
55
+ const flow = {
56
+ flowId,
57
+ nodeId: id,
58
+ jobId,
59
+ };
60
+ const normalizedFile = metadata ? { ...file, metadata } : file;
61
+ const upload = yield* uploadServer.getUpload(file.id);
62
+ if (!upload.id) {
63
+ return yield* Effect.fail(UploadistaError.fromCode("FILE_READ_ERROR", new Error("Upload Key is undefined")));
64
+ }
65
+ // If the upload is already in the correct storage, return the file, just update the flow
66
+ if (upload.storage.id === storageId) {
67
+ return completeNodeExecution(yield* postProcessFile({ ...normalizedFile, flow }));
68
+ }
69
+ const inputBytes = yield* uploadServer.read(file.id, clientId);
70
+ const stream = new ReadableStream({
71
+ start(controller) {
72
+ controller.enqueue(inputBytes);
73
+ controller.close();
74
+ },
75
+ });
76
+ const uploadResult = yield* uploadServer.upload({
77
+ storageId,
78
+ size: inputBytes.byteLength,
79
+ type,
80
+ fileName,
81
+ lastModified: 0,
82
+ metadata: metadataJson,
83
+ flow,
84
+ }, clientId, stream);
85
+ const resolvedUploadResult = resolveUploadMetadata(uploadResult.metadata);
86
+ const postProcessed = yield* postProcessFile(resolvedUploadResult.metadata
87
+ ? { ...uploadResult, metadata: resolvedUploadResult.metadata }
88
+ : uploadResult);
89
+ return completeNodeExecution(postProcessed);
90
+ });
91
+ },
92
+ });
93
+ });
94
+ }
@@ -0,0 +1,69 @@
1
+ import { Effect } from "effect";
2
+ import { z } from "zod";
3
+ import { UploadistaError } from "../../errors";
4
+ import { UploadServer } from "../../upload";
5
+ export declare const streamingInputDataSchema: z.ZodUnion<readonly [z.ZodObject<{
6
+ operation: z.ZodLiteral<"init">;
7
+ storageId: z.ZodString;
8
+ metadata: z.ZodOptional<z.ZodObject<{
9
+ originalName: z.ZodOptional<z.ZodString>;
10
+ mimeType: z.ZodOptional<z.ZodString>;
11
+ size: z.ZodOptional<z.ZodNumber>;
12
+ extension: z.ZodOptional<z.ZodString>;
13
+ }, z.core.$strip>>;
14
+ }, z.core.$strip>, z.ZodObject<{
15
+ operation: z.ZodLiteral<"finalize">;
16
+ uploadId: z.ZodString;
17
+ }, z.core.$strip>, z.ZodObject<{
18
+ operation: z.ZodLiteral<"url">;
19
+ url: z.ZodString;
20
+ storageId: z.ZodOptional<z.ZodString>;
21
+ metadata: z.ZodOptional<z.ZodObject<{
22
+ originalName: z.ZodOptional<z.ZodString>;
23
+ mimeType: z.ZodOptional<z.ZodString>;
24
+ size: z.ZodOptional<z.ZodNumber>;
25
+ }, z.core.$strip>>;
26
+ }, z.core.$strip>]>;
27
+ export declare function createStreamingInputNode(id: string): Effect.Effect<import("..").FlowNode<{
28
+ operation: "init";
29
+ storageId: string;
30
+ metadata?: {
31
+ originalName?: string | undefined;
32
+ mimeType?: string | undefined;
33
+ size?: number | undefined;
34
+ extension?: string | undefined;
35
+ } | undefined;
36
+ } | {
37
+ operation: "finalize";
38
+ uploadId: string;
39
+ } | {
40
+ operation: "url";
41
+ url: string;
42
+ storageId?: string | undefined;
43
+ metadata?: {
44
+ originalName?: string | undefined;
45
+ mimeType?: string | undefined;
46
+ size?: number | undefined;
47
+ } | undefined;
48
+ }, {
49
+ id: string;
50
+ offset: number;
51
+ storage: {
52
+ id: string;
53
+ type: string;
54
+ path?: string | undefined;
55
+ uploadId?: string | undefined;
56
+ bucket?: string | undefined;
57
+ };
58
+ size?: number | undefined;
59
+ metadata?: Record<string, string> | undefined;
60
+ creationDate?: string | undefined;
61
+ url?: string | undefined;
62
+ sizeIsDeferred?: boolean | undefined;
63
+ flow?: {
64
+ flowId: string;
65
+ nodeId: string;
66
+ jobId: string;
67
+ } | undefined;
68
+ }, UploadistaError>, never, UploadServer>;
69
+ //# sourceMappingURL=streaming-input-node.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"streaming-input-node.d.ts","sourceRoot":"","sources":["../../../src/flow/nodes/streaming-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;AA+D5C,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;mBAInC,CAAC;AAIH,wBAAgB,wBAAwB,CAAC,EAAE,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;0CAmHlD"}
@@ -0,0 +1,156 @@
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 { createFlowNode, NodeType } from "../node";
7
+ import { completeNodeExecution, waitingNodeExecution } from "../types";
8
+ // Helper functions for URL-based file fetching
9
+ const fetchFile = (url) => {
10
+ return Effect.tryPromise({
11
+ try: async () => {
12
+ return await fetch(url);
13
+ },
14
+ catch: (error) => {
15
+ return UploadistaError.fromCode("UNKNOWN_ERROR", {
16
+ cause: error,
17
+ });
18
+ },
19
+ });
20
+ };
21
+ const arrayBuffer = (response) => {
22
+ return Effect.tryPromise({
23
+ try: async () => {
24
+ return await response.arrayBuffer();
25
+ },
26
+ catch: (error) => {
27
+ return UploadistaError.fromCode("UNKNOWN_ERROR", {
28
+ cause: error,
29
+ });
30
+ },
31
+ });
32
+ };
33
+ // Input schemas for different operations
34
+ const initStreamingInputSchema = z.object({
35
+ operation: z.literal("init"),
36
+ storageId: z.string(),
37
+ metadata: z
38
+ .object({
39
+ originalName: z.string().optional(),
40
+ mimeType: z.string().optional(),
41
+ size: z.number().optional(),
42
+ extension: z.string().optional(),
43
+ })
44
+ .optional(),
45
+ });
46
+ const finalizeStreamingInputSchema = z.object({
47
+ operation: z.literal("finalize"),
48
+ uploadId: z.string(),
49
+ });
50
+ const urlInputSchema = z.object({
51
+ operation: z.literal("url"),
52
+ url: z.string(),
53
+ storageId: z.string().optional(),
54
+ metadata: z
55
+ .object({
56
+ originalName: z.string().optional(),
57
+ mimeType: z.string().optional(),
58
+ size: z.number().optional(),
59
+ })
60
+ .optional(),
61
+ });
62
+ export const streamingInputDataSchema = z.union([
63
+ initStreamingInputSchema,
64
+ finalizeStreamingInputSchema,
65
+ urlInputSchema,
66
+ ]);
67
+ export function createStreamingInputNode(id) {
68
+ return Effect.gen(function* () {
69
+ const uploadServer = yield* UploadServer;
70
+ return yield* createFlowNode({
71
+ id,
72
+ name: "Input",
73
+ description: "Handles file input through multiple methods - streaming upload (init/finalize) or direct URL fetch",
74
+ type: NodeType.input,
75
+ inputSchema: streamingInputDataSchema,
76
+ outputSchema: uploadFileSchema,
77
+ run: ({ data, flowId, jobId, }) => {
78
+ return Effect.gen(function* () {
79
+ switch (data.operation) {
80
+ case "init": {
81
+ // Create upload using upload server - it handles all state management
82
+ const inputFile = {
83
+ storageId: data.storageId,
84
+ size: data.metadata?.size || 0,
85
+ type: data.metadata?.mimeType || "application/octet-stream",
86
+ fileName: data.metadata?.originalName,
87
+ lastModified: data.metadata?.size ? Date.now() : undefined,
88
+ };
89
+ const uploadFile = yield* uploadServer.createUpload(inputFile);
90
+ // Return waiting state with the upload file
91
+ // Client will upload chunks directly to the upload API
92
+ return waitingNodeExecution(uploadFile);
93
+ }
94
+ case "finalize": {
95
+ // Get final upload file from upload server's KV store
96
+ const finalUploadFile = yield* uploadServer.getUpload(data.uploadId);
97
+ // Complete the node execution with the final upload file
98
+ // Flow can now continue to next nodes (e.g., save to storage, optimize)
99
+ return completeNodeExecution({
100
+ ...finalUploadFile,
101
+ flow: {
102
+ flowId,
103
+ nodeId: id,
104
+ jobId,
105
+ },
106
+ });
107
+ }
108
+ case "url": {
109
+ // Fetch file from URL directly
110
+ const response = yield* fetchFile(data.url);
111
+ const buffer = yield* arrayBuffer(response);
112
+ // Extract metadata from response or use provided metadata
113
+ const mimeType = data.metadata?.mimeType ||
114
+ response.headers.get("content-type") ||
115
+ "application/octet-stream";
116
+ const size = data.metadata?.size ||
117
+ Number(response.headers.get("content-length") || 0);
118
+ const fileName = data.metadata?.originalName ||
119
+ data.url.split("/").pop() ||
120
+ "file";
121
+ // Create a readable stream from the buffer
122
+ const stream = new ReadableStream({
123
+ start(controller) {
124
+ controller.enqueue(new Uint8Array(buffer));
125
+ controller.close();
126
+ },
127
+ });
128
+ // Use upload server to create and store the file
129
+ const inputFile = {
130
+ storageId: data.storageId || "buffer",
131
+ size,
132
+ type: mimeType,
133
+ fileName,
134
+ lastModified: Date.now(),
135
+ };
136
+ const uploadFile = yield* uploadServer.upload(inputFile, stream);
137
+ // Complete the node execution with the upload file
138
+ return completeNodeExecution({
139
+ ...uploadFile,
140
+ flow: {
141
+ flowId,
142
+ nodeId: id,
143
+ jobId,
144
+ },
145
+ });
146
+ }
147
+ default:
148
+ throw yield* UploadistaError.fromCode("VALIDATION_ERROR", {
149
+ cause: new Error("Invalid operation"),
150
+ }).toEffect();
151
+ }
152
+ });
153
+ },
154
+ });
155
+ });
156
+ }
@@ -0,0 +1,85 @@
1
+ import { Effect } from "effect";
2
+ import type { UploadistaError } from "../../errors";
3
+ import type { UploadFile } from "../../types";
4
+ import { UploadServer } from "../../upload";
5
+ /**
6
+ * Configuration object for creating a transform node.
7
+ */
8
+ export interface TransformNodeConfig {
9
+ /** Unique identifier for the node */
10
+ id: string;
11
+ /** Human-readable name for the node */
12
+ name: string;
13
+ /** Description of what the node does */
14
+ description: string;
15
+ /** Function that transforms file bytes */
16
+ transform: (bytes: Uint8Array, file: UploadFile) => Effect.Effect<Uint8Array | {
17
+ bytes: Uint8Array;
18
+ type?: string;
19
+ fileName?: string;
20
+ }, UploadistaError>;
21
+ }
22
+ /**
23
+ * Creates a transform node that handles the common pattern of:
24
+ * 1. Reading bytes from an UploadFile
25
+ * 2. Transforming the bytes
26
+ * 3. Uploading the result as a new UploadFile
27
+ *
28
+ * This simplifies nodes that just need to transform file bytes without
29
+ * worrying about upload server interactions.
30
+ *
31
+ * @param config - Configuration object for the transform node
32
+ * @returns An Effect that creates a flow node configured for file transformation
33
+ *
34
+ * @example
35
+ * ```typescript
36
+ * // Create an image resize transform node
37
+ * const resizeNode = yield* createTransformNode({
38
+ * id: "resize-image",
39
+ * name: "Resize Image",
40
+ * description: "Resizes images to specified dimensions",
41
+ * transform: (bytes, file) => {
42
+ * // Your transformation logic here
43
+ * return Effect.succeed(transformedBytes);
44
+ * }
45
+ * });
46
+ *
47
+ * // Create a transform node that changes file metadata
48
+ * const metadataTransformNode = yield* createTransformNode({
49
+ * id: "add-metadata",
50
+ * name: "Add Metadata",
51
+ * description: "Adds custom metadata to files",
52
+ * transform: (bytes, file) => {
53
+ * return Effect.succeed({
54
+ * bytes,
55
+ * type: "application/custom",
56
+ * fileName: `processed-${file.fileName}`
57
+ * });
58
+ * }
59
+ * });
60
+ * ```
61
+ */
62
+ export declare function createTransformNode({ id, name, description, transform, }: TransformNodeConfig): Effect.Effect<import("..").FlowNode<{
63
+ id: string;
64
+ offset: number;
65
+ storage: {
66
+ id: string;
67
+ type: string;
68
+ path?: string | undefined;
69
+ uploadId?: string | undefined;
70
+ bucket?: string | undefined;
71
+ };
72
+ size?: number | undefined;
73
+ metadata?: Record<string, string | number | boolean> | undefined;
74
+ creationDate?: string | undefined;
75
+ url?: string | undefined;
76
+ sizeIsDeferred?: boolean | undefined;
77
+ checksum?: string | undefined;
78
+ checksumAlgorithm?: string | undefined;
79
+ flow?: {
80
+ flowId: string;
81
+ nodeId: string;
82
+ jobId: string;
83
+ } | undefined;
84
+ }, UploadFile, UploadistaError>, never, UploadServer>;
85
+ //# sourceMappingURL=transform-node.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transform-node.d.ts","sourceRoot":"","sources":["../../../src/flow/nodes/transform-node.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAK5C;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,qCAAqC;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,uCAAuC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,wCAAwC;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,0CAA0C;IAC1C,SAAS,EAAE,CACT,KAAK,EAAE,UAAU,EACjB,IAAI,EAAE,UAAU,KACb,MAAM,CAAC,MAAM,CAChB,UAAU,GAAG;QAAE,KAAK,EAAE,UAAU,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,EACpE,eAAe,CAChB,CAAC;CACH;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,EAAE,EACF,IAAI,EACJ,WAAW,EACX,SAAS,GACV,EAAE,mBAAmB;;;;;;;;;;;;;;;;;;;;;;sDA+ErB"}
@@ -0,0 +1,107 @@
1
+ import { Effect } from "effect";
2
+ import { uploadFileSchema } from "../../types";
3
+ import { UploadServer } from "../../upload";
4
+ import { createFlowNode, NodeType } from "../node";
5
+ import { completeNodeExecution } from "../types";
6
+ import { resolveUploadMetadata } from "../utils/resolve-upload-metadata";
7
+ /**
8
+ * Creates a transform node that handles the common pattern of:
9
+ * 1. Reading bytes from an UploadFile
10
+ * 2. Transforming the bytes
11
+ * 3. Uploading the result as a new UploadFile
12
+ *
13
+ * This simplifies nodes that just need to transform file bytes without
14
+ * worrying about upload server interactions.
15
+ *
16
+ * @param config - Configuration object for the transform node
17
+ * @returns An Effect that creates a flow node configured for file transformation
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * // Create an image resize transform node
22
+ * const resizeNode = yield* createTransformNode({
23
+ * id: "resize-image",
24
+ * name: "Resize Image",
25
+ * description: "Resizes images to specified dimensions",
26
+ * transform: (bytes, file) => {
27
+ * // Your transformation logic here
28
+ * return Effect.succeed(transformedBytes);
29
+ * }
30
+ * });
31
+ *
32
+ * // Create a transform node that changes file metadata
33
+ * const metadataTransformNode = yield* createTransformNode({
34
+ * id: "add-metadata",
35
+ * name: "Add Metadata",
36
+ * description: "Adds custom metadata to files",
37
+ * transform: (bytes, file) => {
38
+ * return Effect.succeed({
39
+ * bytes,
40
+ * type: "application/custom",
41
+ * fileName: `processed-${file.fileName}`
42
+ * });
43
+ * }
44
+ * });
45
+ * ```
46
+ */
47
+ export function createTransformNode({ id, name, description, transform, }) {
48
+ return Effect.gen(function* () {
49
+ const uploadServer = yield* UploadServer;
50
+ return yield* createFlowNode({
51
+ id,
52
+ name,
53
+ description,
54
+ type: NodeType.process,
55
+ inputSchema: uploadFileSchema,
56
+ outputSchema: uploadFileSchema,
57
+ run: ({ data: file, storageId, flowId, jobId, clientId }) => {
58
+ return Effect.gen(function* () {
59
+ const flow = {
60
+ flowId,
61
+ nodeId: id,
62
+ jobId,
63
+ };
64
+ // Read input bytes from upload server
65
+ const inputBytes = yield* uploadServer.read(file.id, clientId);
66
+ // Transform the bytes using the provided function
67
+ const transformResult = yield* transform(inputBytes, file);
68
+ // Handle both simple Uint8Array and object with metadata
69
+ const outputBytes = transformResult instanceof Uint8Array
70
+ ? transformResult
71
+ : transformResult.bytes;
72
+ const outputType = transformResult instanceof Uint8Array
73
+ ? undefined
74
+ : transformResult.type;
75
+ const outputFileName = transformResult instanceof Uint8Array
76
+ ? undefined
77
+ : transformResult.fileName;
78
+ // Create a stream from the output bytes
79
+ const stream = new ReadableStream({
80
+ start(controller) {
81
+ controller.enqueue(outputBytes);
82
+ controller.close();
83
+ },
84
+ });
85
+ const { type, fileName, metadata, metadataJson } = resolveUploadMetadata(file.metadata);
86
+ // Upload the transformed bytes back to the upload server
87
+ // Use output metadata if provided, otherwise fall back to original
88
+ const result = yield* uploadServer.upload({
89
+ storageId,
90
+ size: outputBytes.byteLength,
91
+ type: outputType ?? type,
92
+ fileName: outputFileName ?? fileName,
93
+ lastModified: 0,
94
+ metadata: metadataJson,
95
+ flow,
96
+ }, clientId, stream);
97
+ return completeNodeExecution(metadata
98
+ ? {
99
+ ...result,
100
+ metadata,
101
+ }
102
+ : result);
103
+ });
104
+ },
105
+ });
106
+ });
107
+ }