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