@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,353 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core flow type definitions and node specifications.
|
|
3
|
+
*
|
|
4
|
+
* This module defines the fundamental types for the Flow Engine, including node
|
|
5
|
+
* definitions, execution results, edges, and configuration. These types form the
|
|
6
|
+
* foundation of the DAG processing system.
|
|
7
|
+
*
|
|
8
|
+
* @module flow/types/flow-types
|
|
9
|
+
* @see {@link FlowNode} for node specification
|
|
10
|
+
* @see {@link FlowConfig} for flow configuration
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/** biome-ignore-all lint/suspicious/noExplicitAny: any is used to allow for dynamic types */
|
|
14
|
+
|
|
15
|
+
import type { Effect } from "effect";
|
|
16
|
+
import type { z } from "zod";
|
|
17
|
+
import type { UploadistaError } from "../../errors";
|
|
18
|
+
import type { FlowEvent, FlowEventFlowEnd, FlowEventFlowStart } from "../event";
|
|
19
|
+
import { NodeType } from "../node";
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Type mapping for node input/output schemas.
|
|
23
|
+
* Used for type-safe node connections in typed flows.
|
|
24
|
+
*/
|
|
25
|
+
export type NodeTypeMap = Record<string, { input: unknown; output: unknown }>;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Minimal node data without execution logic.
|
|
29
|
+
* Used for serialization and UI display.
|
|
30
|
+
*
|
|
31
|
+
* @property id - Unique node identifier
|
|
32
|
+
* @property name - Human-readable node name
|
|
33
|
+
* @property description - Explanation of what the node does
|
|
34
|
+
* @property type - Node category (input, transform, conditional, output, etc.)
|
|
35
|
+
*/
|
|
36
|
+
export type FlowNodeData = {
|
|
37
|
+
id: string;
|
|
38
|
+
name: string;
|
|
39
|
+
description: string;
|
|
40
|
+
type: NodeType;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Result of a node execution - either complete or waiting for more data.
|
|
45
|
+
*
|
|
46
|
+
* @template TOutput - Type of the node's output data
|
|
47
|
+
*
|
|
48
|
+
* @remarks
|
|
49
|
+
* Nodes can return "waiting" to pause flow execution when they need additional
|
|
50
|
+
* data (e.g., chunked uploads, external service responses). The flow can be
|
|
51
|
+
* resumed later with the missing data.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```typescript
|
|
55
|
+
* // Node completes immediately
|
|
56
|
+
* return completeNodeExecution({ processedData });
|
|
57
|
+
*
|
|
58
|
+
* // Node waits for more chunks
|
|
59
|
+
* if (needsMoreData) {
|
|
60
|
+
* return waitingNodeExecution({ receivedChunks: 3, totalChunks: 10 });
|
|
61
|
+
* }
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
export type NodeExecutionResult<TOutput> =
|
|
65
|
+
| { type: "complete"; data: TOutput }
|
|
66
|
+
| { type: "waiting"; partialData?: unknown };
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Helper function to create a complete node execution result.
|
|
70
|
+
*
|
|
71
|
+
* @template TOutput - Type of the output data
|
|
72
|
+
* @param data - The output data from the node
|
|
73
|
+
* @returns A complete execution result
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* ```typescript
|
|
77
|
+
* return completeNodeExecution({
|
|
78
|
+
* url: uploadedFile.url,
|
|
79
|
+
* size: uploadedFile.size
|
|
80
|
+
* });
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
export const completeNodeExecution = <TOutput>(data: TOutput) => ({
|
|
84
|
+
type: "complete" as const,
|
|
85
|
+
data,
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Helper function to create a waiting node execution result.
|
|
90
|
+
*
|
|
91
|
+
* @param partialData - Optional partial data available so far
|
|
92
|
+
* @returns A waiting execution result that pauses the flow
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```typescript
|
|
96
|
+
* // Wait for more upload chunks
|
|
97
|
+
* return waitingNodeExecution({
|
|
98
|
+
* receivedBytes: currentSize,
|
|
99
|
+
* totalBytes: expectedSize
|
|
100
|
+
* });
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
export const waitingNodeExecution = (partialData?: unknown) => ({
|
|
104
|
+
type: "waiting" as const,
|
|
105
|
+
partialData,
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* A flow node represents a single processing step in the DAG.
|
|
110
|
+
*
|
|
111
|
+
* Nodes are the building blocks of flows. Each node has typed inputs/outputs,
|
|
112
|
+
* execution logic, and optional features like conditions, retries, and pausing.
|
|
113
|
+
*
|
|
114
|
+
* @template TInput - Type of data the node accepts
|
|
115
|
+
* @template TOutput - Type of data the node produces
|
|
116
|
+
* @template TError - Type of errors the node can throw
|
|
117
|
+
*
|
|
118
|
+
* @property inputSchema - Zod schema for validating input data
|
|
119
|
+
* @property outputSchema - Zod schema for validating output data
|
|
120
|
+
* @property run - Effect-based execution function
|
|
121
|
+
* @property condition - Optional conditional execution rule
|
|
122
|
+
* @property multiInput - Whether node accepts multiple inputs (default: false)
|
|
123
|
+
* @property multiOutput - Whether node produces multiple outputs (default: false)
|
|
124
|
+
* @property pausable - Whether node can pause execution (default: false)
|
|
125
|
+
* @property retry - Optional retry configuration
|
|
126
|
+
*
|
|
127
|
+
* @remarks
|
|
128
|
+
* - Nodes use Effect for composable error handling and dependency injection
|
|
129
|
+
* - Input/output schemas ensure type safety at runtime
|
|
130
|
+
* - Conditions are evaluated before execution
|
|
131
|
+
* - Retry logic supports exponential backoff
|
|
132
|
+
* - Pausable nodes can halt flow execution and resume later
|
|
133
|
+
*
|
|
134
|
+
* @example
|
|
135
|
+
* ```typescript
|
|
136
|
+
* const resizeNode: FlowNode<InputFile, UploadFile> = {
|
|
137
|
+
* id: "resize",
|
|
138
|
+
* name: "Resize Image",
|
|
139
|
+
* description: "Resize image to specified dimensions",
|
|
140
|
+
* type: NodeType.transform,
|
|
141
|
+
* inputSchema: inputFileSchema,
|
|
142
|
+
* outputSchema: uploadFileSchema,
|
|
143
|
+
* run: ({ data, storageId }) => Effect.gen(function* () {
|
|
144
|
+
* const resized = yield* resizeImage(data, { width: 1920, height: 1080 });
|
|
145
|
+
* return completeNodeExecution(resized);
|
|
146
|
+
* }),
|
|
147
|
+
* retry: {
|
|
148
|
+
* maxRetries: 3,
|
|
149
|
+
* retryDelay: 1000,
|
|
150
|
+
* exponentialBackoff: true
|
|
151
|
+
* }
|
|
152
|
+
* };
|
|
153
|
+
* ```
|
|
154
|
+
*
|
|
155
|
+
* @see {@link NodeExecutionResult} for return type options
|
|
156
|
+
* @see {@link FlowCondition} for conditional execution
|
|
157
|
+
*/
|
|
158
|
+
export type FlowNode<
|
|
159
|
+
TInput = unknown,
|
|
160
|
+
TOutput = unknown,
|
|
161
|
+
TError = UploadistaError,
|
|
162
|
+
> = FlowNodeData & {
|
|
163
|
+
inputSchema: z.ZodSchema<TInput>;
|
|
164
|
+
outputSchema: z.ZodSchema<TOutput>;
|
|
165
|
+
run: (args: {
|
|
166
|
+
data: TInput;
|
|
167
|
+
jobId: string;
|
|
168
|
+
storageId: string;
|
|
169
|
+
flowId: string;
|
|
170
|
+
inputs?: Record<string, unknown>;
|
|
171
|
+
clientId: string | null;
|
|
172
|
+
}) => Effect.Effect<NodeExecutionResult<TOutput>, TError>;
|
|
173
|
+
condition?: {
|
|
174
|
+
field: string;
|
|
175
|
+
operator: string;
|
|
176
|
+
value: unknown;
|
|
177
|
+
};
|
|
178
|
+
multiInput?: boolean;
|
|
179
|
+
multiOutput?: boolean;
|
|
180
|
+
pausable?: boolean; // Flag to indicate this node can pause execution
|
|
181
|
+
retry?: {
|
|
182
|
+
maxRetries?: number; // Maximum number of retry attempts (default: 0)
|
|
183
|
+
retryDelay?: number; // Base delay in ms between retries (default: 1000)
|
|
184
|
+
exponentialBackoff?: boolean; // Use exponential backoff (default: true)
|
|
185
|
+
};
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Represents a directed edge connecting two nodes in the flow graph.
|
|
190
|
+
*
|
|
191
|
+
* Edges define the data flow direction and can specify ports for multi-input/output nodes.
|
|
192
|
+
*
|
|
193
|
+
* @property source - ID of the source node
|
|
194
|
+
* @property target - ID of the target node
|
|
195
|
+
* @property sourcePort - Optional output port name for multi-output nodes
|
|
196
|
+
* @property targetPort - Optional input port name for multi-input nodes
|
|
197
|
+
*
|
|
198
|
+
* @remarks
|
|
199
|
+
* - Edges must not create cycles (DAG constraint)
|
|
200
|
+
* - Source node's output type should be compatible with target node's input type
|
|
201
|
+
* - Ports allow routing specific outputs to specific inputs
|
|
202
|
+
*
|
|
203
|
+
* @example
|
|
204
|
+
* ```typescript
|
|
205
|
+
* // Simple edge
|
|
206
|
+
* const edge: FlowEdge = {
|
|
207
|
+
* source: "resize-node",
|
|
208
|
+
* target: "optimize-node"
|
|
209
|
+
* };
|
|
210
|
+
*
|
|
211
|
+
* // Edge with ports (for multiplex nodes)
|
|
212
|
+
* const multiplexEdge: FlowEdge = {
|
|
213
|
+
* source: "multiplex-node",
|
|
214
|
+
* target: "output-node",
|
|
215
|
+
* sourcePort: "image",
|
|
216
|
+
* targetPort: "primary"
|
|
217
|
+
* };
|
|
218
|
+
* ```
|
|
219
|
+
*/
|
|
220
|
+
export type FlowEdge = {
|
|
221
|
+
source: string;
|
|
222
|
+
target: string;
|
|
223
|
+
sourcePort?: string; // For multi-output nodes
|
|
224
|
+
targetPort?: string; // For multi-input nodes
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Function type for checking schema compatibility between nodes.
|
|
229
|
+
*
|
|
230
|
+
* @param from - Source node's output schema
|
|
231
|
+
* @param to - Target node's input schema
|
|
232
|
+
* @returns true if schemas are compatible
|
|
233
|
+
*
|
|
234
|
+
* @remarks
|
|
235
|
+
* Custom type checkers can implement more sophisticated compatibility rules
|
|
236
|
+
* than the default checker.
|
|
237
|
+
*
|
|
238
|
+
* @see {@link FlowTypeValidator} for the default implementation
|
|
239
|
+
*/
|
|
240
|
+
export type TypeCompatibilityChecker = (
|
|
241
|
+
from: z.ZodSchema<any>,
|
|
242
|
+
to: z.ZodSchema<any>,
|
|
243
|
+
) => boolean;
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Interface for validating node connections and schema compatibility.
|
|
247
|
+
*
|
|
248
|
+
* @remarks
|
|
249
|
+
* Validators ensure that connected nodes have compatible types,
|
|
250
|
+
* preventing runtime type errors in flow execution.
|
|
251
|
+
*
|
|
252
|
+
* @see {@link FlowTypeValidator} for the implementation
|
|
253
|
+
*/
|
|
254
|
+
export type NodeConnectionValidator = {
|
|
255
|
+
validateConnection: (
|
|
256
|
+
sourceNode: FlowNode<any, any>,
|
|
257
|
+
targetNode: FlowNode<any, any>,
|
|
258
|
+
edge: FlowEdge,
|
|
259
|
+
) => boolean;
|
|
260
|
+
getCompatibleTypes: (
|
|
261
|
+
sourceSchema: z.ZodSchema<any>,
|
|
262
|
+
targetSchema: z.ZodSchema<any>,
|
|
263
|
+
) => boolean;
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Configuration object for creating a new flow.
|
|
268
|
+
*
|
|
269
|
+
* FlowConfig defines all aspects of a flow including its nodes, connections,
|
|
270
|
+
* schemas, and optional features like event handlers and parallel execution.
|
|
271
|
+
*
|
|
272
|
+
* @template TFlowInputSchema - Zod schema for flow inputs
|
|
273
|
+
* @template TFlowOutputSchema - Zod schema for flow outputs
|
|
274
|
+
* @template TNodeError - Union of possible errors from node Effects
|
|
275
|
+
* @template TNodeRequirements - Union of requirements from node Effects
|
|
276
|
+
*
|
|
277
|
+
* @property flowId - Unique identifier for the flow
|
|
278
|
+
* @property name - Human-readable flow name
|
|
279
|
+
* @property nodes - Array of nodes (can be plain nodes or Effects resolving to nodes)
|
|
280
|
+
* @property edges - Array of edges connecting the nodes
|
|
281
|
+
* @property inputSchema - Zod schema for validating flow inputs
|
|
282
|
+
* @property outputSchema - Zod schema for validating flow outputs
|
|
283
|
+
* @property typeChecker - Optional custom type compatibility checker
|
|
284
|
+
* @property onEvent - Optional event handler for monitoring execution
|
|
285
|
+
* @property parallelExecution - Optional parallel execution configuration
|
|
286
|
+
*
|
|
287
|
+
* @remarks
|
|
288
|
+
* - Nodes can be provided as plain objects or Effect-wrapped for lazy initialization
|
|
289
|
+
* - Event handlers receive all flow and node events
|
|
290
|
+
* - Parallel execution is experimental and disabled by default
|
|
291
|
+
* - Type checker allows custom schema compatibility rules
|
|
292
|
+
*
|
|
293
|
+
* @example
|
|
294
|
+
* ```typescript
|
|
295
|
+
* const config: FlowConfig<
|
|
296
|
+
* z.ZodObject<{ file: z.ZodType<File> }>,
|
|
297
|
+
* z.ZodType<UploadFile>,
|
|
298
|
+
* never,
|
|
299
|
+
* never
|
|
300
|
+
* > = {
|
|
301
|
+
* flowId: "image-upload",
|
|
302
|
+
* name: "Image Upload Pipeline",
|
|
303
|
+
* nodes: [inputNode, resizeNode, optimizeNode, storageNode],
|
|
304
|
+
* edges: [
|
|
305
|
+
* { source: "input", target: "resize" },
|
|
306
|
+
* { source: "resize", target: "optimize" },
|
|
307
|
+
* { source: "optimize", target: "storage" }
|
|
308
|
+
* ],
|
|
309
|
+
* inputSchema: z.object({ file: z.instanceof(File) }),
|
|
310
|
+
* outputSchema: uploadFileSchema,
|
|
311
|
+
* onEvent: (event) => Effect.gen(function* () {
|
|
312
|
+
* yield* logEvent(event);
|
|
313
|
+
* return { eventId: event.jobId };
|
|
314
|
+
* })
|
|
315
|
+
* };
|
|
316
|
+
* ```
|
|
317
|
+
*
|
|
318
|
+
* @see {@link createFlowWithSchema} for creating flows from config
|
|
319
|
+
* @see {@link FlowNode} for node specifications
|
|
320
|
+
* @see {@link FlowEdge} for edge specifications
|
|
321
|
+
*/
|
|
322
|
+
export type FlowConfig<
|
|
323
|
+
TFlowInputSchema extends z.ZodSchema<any>,
|
|
324
|
+
TFlowOutputSchema extends z.ZodSchema<any>,
|
|
325
|
+
TNodeError = never,
|
|
326
|
+
TNodeRequirements = never,
|
|
327
|
+
> = {
|
|
328
|
+
flowId: string;
|
|
329
|
+
name: string;
|
|
330
|
+
nodes: Array<
|
|
331
|
+
| FlowNode<any, any, UploadistaError>
|
|
332
|
+
| Effect.Effect<
|
|
333
|
+
FlowNode<any, any, UploadistaError>,
|
|
334
|
+
TNodeError,
|
|
335
|
+
TNodeRequirements
|
|
336
|
+
>
|
|
337
|
+
>;
|
|
338
|
+
edges: FlowEdge[];
|
|
339
|
+
inputSchema: TFlowInputSchema;
|
|
340
|
+
outputSchema: TFlowOutputSchema;
|
|
341
|
+
typeChecker?: TypeCompatibilityChecker;
|
|
342
|
+
onEvent?: (
|
|
343
|
+
event: FlowEvent,
|
|
344
|
+
) => Effect.Effect<{ eventId: string | null }, UploadistaError>;
|
|
345
|
+
parallelExecution?: {
|
|
346
|
+
enabled?: boolean;
|
|
347
|
+
maxConcurrency?: number;
|
|
348
|
+
};
|
|
349
|
+
};
|
|
350
|
+
|
|
351
|
+
// Re-export existing types for compatibility
|
|
352
|
+
export { NodeType };
|
|
353
|
+
export type { FlowEvent, FlowEventFlowEnd, FlowEventFlowStart };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Flow execution argument schemas and types.
|
|
3
|
+
*
|
|
4
|
+
* Defines and validates the arguments passed when running a flow,
|
|
5
|
+
* ensuring inputs are properly structured before execution begins.
|
|
6
|
+
*
|
|
7
|
+
* @module flow/types/run-args
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { z } from "zod";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Zod schema for validating flow run arguments.
|
|
14
|
+
*
|
|
15
|
+
* @property inputs - Record mapping input node IDs to their input data
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* const args = {
|
|
20
|
+
* inputs: {
|
|
21
|
+
* "input-node-1": { file: myFile, metadata: { ... } },
|
|
22
|
+
* "input-node-2": { file: anotherFile }
|
|
23
|
+
* }
|
|
24
|
+
* };
|
|
25
|
+
*
|
|
26
|
+
* // Validate before running
|
|
27
|
+
* const validated = runArgsSchema.parse(args);
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export const runArgsSchema = z.object({
|
|
31
|
+
inputs: z.record(z.string(), z.any()),
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Type representing validated flow run arguments.
|
|
36
|
+
*
|
|
37
|
+
* This type is inferred from the runArgsSchema and ensures type safety
|
|
38
|
+
* when passing inputs to flow execution.
|
|
39
|
+
*/
|
|
40
|
+
export type RunArgs = z.infer<typeof runArgsSchema>;
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/** biome-ignore-all lint/suspicious/noExplicitAny: any is used to allow for dynamic types */
|
|
2
|
+
import type { z } from "zod";
|
|
3
|
+
|
|
4
|
+
import type {
|
|
5
|
+
FlowEdge,
|
|
6
|
+
FlowNode,
|
|
7
|
+
NodeConnectionValidator,
|
|
8
|
+
TypeCompatibilityChecker,
|
|
9
|
+
} from "./flow-types";
|
|
10
|
+
|
|
11
|
+
// Default type compatibility checker using Zod schemas
|
|
12
|
+
export const defaultTypeChecker: TypeCompatibilityChecker = (
|
|
13
|
+
fromSchema,
|
|
14
|
+
toSchema,
|
|
15
|
+
) => {
|
|
16
|
+
// Basic schema compatibility rules
|
|
17
|
+
if (fromSchema === toSchema) return true;
|
|
18
|
+
|
|
19
|
+
// Check if schemas are compatible by comparing their types
|
|
20
|
+
try {
|
|
21
|
+
// For now, assume schemas are compatible if they're both Zod schemas
|
|
22
|
+
// In a more sophisticated system, you'd check actual schema compatibility
|
|
23
|
+
if (
|
|
24
|
+
fromSchema &&
|
|
25
|
+
toSchema &&
|
|
26
|
+
typeof fromSchema === "object" &&
|
|
27
|
+
typeof toSchema === "object"
|
|
28
|
+
) {
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return false;
|
|
33
|
+
} catch {
|
|
34
|
+
// If schema comparison fails, assume compatible
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// Enhanced type validator with Zod schema support
|
|
40
|
+
export class FlowTypeValidator implements NodeConnectionValidator {
|
|
41
|
+
private typeChecker: TypeCompatibilityChecker;
|
|
42
|
+
|
|
43
|
+
constructor(typeChecker: TypeCompatibilityChecker = defaultTypeChecker) {
|
|
44
|
+
this.typeChecker = typeChecker;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
validateConnection(
|
|
48
|
+
sourceNode: FlowNode<any, any>,
|
|
49
|
+
targetNode: FlowNode<any, any>,
|
|
50
|
+
_edge: FlowEdge,
|
|
51
|
+
): boolean {
|
|
52
|
+
// Check if source node output schema is compatible with target node input schema
|
|
53
|
+
return this.getCompatibleTypes(
|
|
54
|
+
sourceNode.outputSchema,
|
|
55
|
+
targetNode.inputSchema,
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
getCompatibleTypes(
|
|
60
|
+
sourceSchema: z.ZodSchema<any>,
|
|
61
|
+
targetSchema: z.ZodSchema<any>,
|
|
62
|
+
): boolean {
|
|
63
|
+
return this.typeChecker(sourceSchema, targetSchema);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Validate entire flow for type compatibility
|
|
67
|
+
validateFlow(
|
|
68
|
+
nodes: FlowNode<any, any>[],
|
|
69
|
+
edges: FlowEdge[],
|
|
70
|
+
): {
|
|
71
|
+
isValid: boolean;
|
|
72
|
+
errors: string[];
|
|
73
|
+
} {
|
|
74
|
+
const errors: string[] = [];
|
|
75
|
+
const nodeMap = new Map(nodes.map((node) => [node.id, node]));
|
|
76
|
+
|
|
77
|
+
for (const edge of edges) {
|
|
78
|
+
const sourceNode = nodeMap.get(edge.source);
|
|
79
|
+
const targetNode = nodeMap.get(edge.target);
|
|
80
|
+
|
|
81
|
+
if (!sourceNode) {
|
|
82
|
+
errors.push(`Source node ${edge.source} not found`);
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (!targetNode) {
|
|
87
|
+
errors.push(`Target node ${edge.target} not found`);
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (!this.validateConnection(sourceNode, targetNode, edge)) {
|
|
92
|
+
errors.push(
|
|
93
|
+
`Schema mismatch: ${sourceNode.id} output schema incompatible with ${targetNode.id} input schema`,
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return {
|
|
99
|
+
isValid: errors.length === 0,
|
|
100
|
+
errors,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Get expected input schemas for a node based on its incoming edges
|
|
105
|
+
getExpectedInputSchemas(
|
|
106
|
+
nodeId: string,
|
|
107
|
+
nodes: FlowNode<any, any>[],
|
|
108
|
+
edges: FlowEdge[],
|
|
109
|
+
): Record<string, unknown> {
|
|
110
|
+
const nodeMap = new Map(nodes.map((node) => [node.id, node]));
|
|
111
|
+
const expectedSchemas: Record<string, unknown> = {};
|
|
112
|
+
|
|
113
|
+
for (const edge of edges) {
|
|
114
|
+
if (edge.target === nodeId) {
|
|
115
|
+
const sourceNode = nodeMap.get(edge.source);
|
|
116
|
+
if (sourceNode) {
|
|
117
|
+
const portKey = edge.sourcePort || edge.source;
|
|
118
|
+
expectedSchemas[portKey] = sourceNode.outputSchema;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return expectedSchemas;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Get actual output schemas for a node based on its outgoing edges
|
|
127
|
+
getActualOutputSchemas(
|
|
128
|
+
nodeId: string,
|
|
129
|
+
nodes: FlowNode<any, any>[],
|
|
130
|
+
edges: FlowEdge[],
|
|
131
|
+
): Record<string, unknown> {
|
|
132
|
+
const nodeMap = new Map(nodes.map((node) => [node.id, node]));
|
|
133
|
+
const actualSchemas: Record<string, unknown> = {};
|
|
134
|
+
|
|
135
|
+
for (const edge of edges) {
|
|
136
|
+
if (edge.source === nodeId) {
|
|
137
|
+
const targetNode = nodeMap.get(edge.target);
|
|
138
|
+
if (targetNode) {
|
|
139
|
+
const portKey = edge.targetPort || edge.target;
|
|
140
|
+
actualSchemas[portKey] = targetNode.inputSchema;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return actualSchemas;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Validate data against a schema
|
|
149
|
+
validateData(
|
|
150
|
+
data: unknown,
|
|
151
|
+
schema: unknown,
|
|
152
|
+
): { isValid: boolean; errors: string[] } {
|
|
153
|
+
try {
|
|
154
|
+
(schema as z.ZodSchema<any>).parse(data);
|
|
155
|
+
return { isValid: true, errors: [] };
|
|
156
|
+
} catch (error) {
|
|
157
|
+
if (error instanceof Error && "errors" in error) {
|
|
158
|
+
return {
|
|
159
|
+
isValid: false,
|
|
160
|
+
errors: (
|
|
161
|
+
error as { errors: Array<{ path: string[]; message: string }> }
|
|
162
|
+
).errors.map((err) => `${err.path.join(".")}: ${err.message}`),
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
return {
|
|
166
|
+
isValid: false,
|
|
167
|
+
errors: [error instanceof Error ? error.message : "Validation failed"],
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Utility functions for common type checks
|
|
174
|
+
export const typeUtils = {
|
|
175
|
+
// Check if a schema is assignable to another
|
|
176
|
+
isAssignable(
|
|
177
|
+
fromSchema: z.ZodSchema<any>,
|
|
178
|
+
toSchema: z.ZodSchema<any>,
|
|
179
|
+
): boolean {
|
|
180
|
+
return defaultTypeChecker(fromSchema, toSchema);
|
|
181
|
+
},
|
|
182
|
+
|
|
183
|
+
// Get the most specific common schema
|
|
184
|
+
getCommonSchema(
|
|
185
|
+
schema1: z.ZodSchema<any>,
|
|
186
|
+
schema2: z.ZodSchema<any>,
|
|
187
|
+
): z.ZodSchema<any> {
|
|
188
|
+
if (schema1 === schema2) return schema1;
|
|
189
|
+
|
|
190
|
+
// For now, return the more specific schema or schema1
|
|
191
|
+
// In a more sophisticated system, you'd compute the intersection
|
|
192
|
+
return schema1;
|
|
193
|
+
},
|
|
194
|
+
|
|
195
|
+
// Check if a value matches a schema
|
|
196
|
+
matchesSchema(value: unknown, schema: z.ZodSchema<any>): boolean {
|
|
197
|
+
try {
|
|
198
|
+
schema.parse(value);
|
|
199
|
+
return true;
|
|
200
|
+
} catch {
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { UploadFile } from "../../types";
|
|
2
|
+
|
|
3
|
+
type FileMetadata = UploadFile["metadata"];
|
|
4
|
+
|
|
5
|
+
export type ResolvedUploadMetadata = {
|
|
6
|
+
type: string;
|
|
7
|
+
fileName: string;
|
|
8
|
+
metadata: FileMetadata;
|
|
9
|
+
metadataJson: string | undefined;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export function resolveUploadMetadata(
|
|
13
|
+
metadata: FileMetadata,
|
|
14
|
+
): ResolvedUploadMetadata {
|
|
15
|
+
if (!metadata) {
|
|
16
|
+
return {
|
|
17
|
+
type: "",
|
|
18
|
+
fileName: "",
|
|
19
|
+
metadata: undefined,
|
|
20
|
+
metadataJson: undefined,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const normalized = { ...metadata };
|
|
25
|
+
const type = String(
|
|
26
|
+
normalized.type || normalized.mimeType || normalized["content-type"] || ""
|
|
27
|
+
);
|
|
28
|
+
if (type) {
|
|
29
|
+
normalized.type ||= type;
|
|
30
|
+
normalized.mimeType ||= type;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const fileName = String(
|
|
34
|
+
normalized.fileName || normalized.originalName || normalized.name || ""
|
|
35
|
+
);
|
|
36
|
+
if (fileName) {
|
|
37
|
+
normalized.fileName ||= fileName;
|
|
38
|
+
normalized.originalName ||= fileName;
|
|
39
|
+
normalized.name ||= fileName;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
type,
|
|
44
|
+
fileName,
|
|
45
|
+
metadata: normalized,
|
|
46
|
+
metadataJson: JSON.stringify(normalized),
|
|
47
|
+
};
|
|
48
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type Logger = {
|
|
2
|
+
log: (message: string) => void;
|
|
3
|
+
};
|
|
4
|
+
|
|
5
|
+
export function createLogger(enabled: boolean): Logger {
|
|
6
|
+
return {
|
|
7
|
+
log: (message: string) => {
|
|
8
|
+
if (enabled) {
|
|
9
|
+
// eslint-disable-next-line no-console
|
|
10
|
+
console.log(message);
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
};
|
|
14
|
+
}
|