@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,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
|
+
}
|