@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,104 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* Zod schema for validating InputFile objects.
|
|
4
|
+
*
|
|
5
|
+
* This schema defines the structure and validation rules for file upload requests.
|
|
6
|
+
* Use this schema to parse and validate input data when creating new uploads.
|
|
7
|
+
*
|
|
8
|
+
* @see {@link InputFile} for the TypeScript type
|
|
9
|
+
*/
|
|
10
|
+
export declare const inputFileSchema: z.ZodObject<{
|
|
11
|
+
uploadLengthDeferred: z.ZodOptional<z.ZodBoolean>;
|
|
12
|
+
storageId: z.ZodString;
|
|
13
|
+
size: z.ZodNumber;
|
|
14
|
+
type: z.ZodString;
|
|
15
|
+
fileName: z.ZodOptional<z.ZodString>;
|
|
16
|
+
lastModified: z.ZodOptional<z.ZodNumber>;
|
|
17
|
+
metadata: z.ZodOptional<z.ZodString>;
|
|
18
|
+
checksum: z.ZodOptional<z.ZodString>;
|
|
19
|
+
checksumAlgorithm: z.ZodOptional<z.ZodString>;
|
|
20
|
+
flow: z.ZodOptional<z.ZodObject<{
|
|
21
|
+
flowId: z.ZodString;
|
|
22
|
+
nodeId: z.ZodString;
|
|
23
|
+
jobId: z.ZodString;
|
|
24
|
+
}, z.core.$strip>>;
|
|
25
|
+
}, z.core.$strip>;
|
|
26
|
+
/**
|
|
27
|
+
* Represents the input data for creating a new file upload.
|
|
28
|
+
*
|
|
29
|
+
* This type defines the information required to initiate an upload.
|
|
30
|
+
* It's used by clients to provide upload metadata before sending file data.
|
|
31
|
+
*
|
|
32
|
+
* @property storageId - Target storage backend identifier (e.g., "s3-production", "azure-blob")
|
|
33
|
+
* @property size - File size in bytes
|
|
34
|
+
* @property type - MIME type of the file (e.g., "image/jpeg", "application/pdf")
|
|
35
|
+
* @property uploadLengthDeferred - If true, file size is not known upfront (streaming upload)
|
|
36
|
+
* @property fileName - Original filename from the client
|
|
37
|
+
* @property lastModified - File's last modified timestamp in milliseconds since epoch
|
|
38
|
+
* @property metadata - Base64-encoded metadata string (as per tus protocol)
|
|
39
|
+
* @property checksum - Expected file checksum for validation
|
|
40
|
+
* @property checksumAlgorithm - Algorithm used for checksum (e.g., "md5", "sha256")
|
|
41
|
+
* @property flow - Optional flow processing configuration
|
|
42
|
+
* @property flow.flowId - ID of the flow to execute on this file
|
|
43
|
+
* @property flow.nodeId - Starting node ID in the flow
|
|
44
|
+
* @property flow.jobId - Flow job execution ID
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```typescript
|
|
48
|
+
* // Basic file upload
|
|
49
|
+
* const inputFile: InputFile = {
|
|
50
|
+
* storageId: "s3-production",
|
|
51
|
+
* size: 1024000,
|
|
52
|
+
* type: "image/jpeg",
|
|
53
|
+
* fileName: "photo.jpg",
|
|
54
|
+
* lastModified: Date.now()
|
|
55
|
+
* };
|
|
56
|
+
*
|
|
57
|
+
* // Upload with metadata (base64 encoded as per tus protocol)
|
|
58
|
+
* const metadata = btoa(JSON.stringify({
|
|
59
|
+
* userId: "user_123",
|
|
60
|
+
* albumId: "album_456"
|
|
61
|
+
* }));
|
|
62
|
+
* const inputWithMetadata: InputFile = {
|
|
63
|
+
* storageId: "s3-production",
|
|
64
|
+
* size: 2048000,
|
|
65
|
+
* type: "image/png",
|
|
66
|
+
* fileName: "screenshot.png",
|
|
67
|
+
* metadata
|
|
68
|
+
* };
|
|
69
|
+
*
|
|
70
|
+
* // Upload with checksum validation
|
|
71
|
+
* const inputWithChecksum: InputFile = {
|
|
72
|
+
* storageId: "s3-production",
|
|
73
|
+
* size: 512000,
|
|
74
|
+
* type: "application/pdf",
|
|
75
|
+
* fileName: "document.pdf",
|
|
76
|
+
* checksum: "5d41402abc4b2a76b9719d911017c592",
|
|
77
|
+
* checksumAlgorithm: "md5"
|
|
78
|
+
* };
|
|
79
|
+
*
|
|
80
|
+
* // Upload that triggers a flow
|
|
81
|
+
* const inputWithFlow: InputFile = {
|
|
82
|
+
* storageId: "s3-temp",
|
|
83
|
+
* size: 4096000,
|
|
84
|
+
* type: "image/jpeg",
|
|
85
|
+
* fileName: "large-image.jpg",
|
|
86
|
+
* flow: {
|
|
87
|
+
* flowId: "resize-and-optimize",
|
|
88
|
+
* nodeId: "input_1",
|
|
89
|
+
* jobId: "job_789"
|
|
90
|
+
* }
|
|
91
|
+
* };
|
|
92
|
+
*
|
|
93
|
+
* // Streaming upload (size unknown)
|
|
94
|
+
* const streamingInput: InputFile = {
|
|
95
|
+
* storageId: "s3-production",
|
|
96
|
+
* size: 0, // Will be updated as data arrives
|
|
97
|
+
* type: "video/mp4",
|
|
98
|
+
* uploadLengthDeferred: true,
|
|
99
|
+
* fileName: "live-stream.mp4"
|
|
100
|
+
* };
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
export type InputFile = z.infer<typeof inputFileSchema>;
|
|
104
|
+
//# sourceMappingURL=input-file.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input-file.d.ts","sourceRoot":"","sources":["../../src/types/input-file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;iBAiB1B,CAAC;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4EG;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* Zod schema for validating InputFile objects.
|
|
4
|
+
*
|
|
5
|
+
* This schema defines the structure and validation rules for file upload requests.
|
|
6
|
+
* Use this schema to parse and validate input data when creating new uploads.
|
|
7
|
+
*
|
|
8
|
+
* @see {@link InputFile} for the TypeScript type
|
|
9
|
+
*/
|
|
10
|
+
export const inputFileSchema = z.object({
|
|
11
|
+
uploadLengthDeferred: z.boolean().optional(),
|
|
12
|
+
storageId: z.string(),
|
|
13
|
+
size: z.number(),
|
|
14
|
+
type: z.string(),
|
|
15
|
+
fileName: z.string().optional(),
|
|
16
|
+
lastModified: z.number().optional(),
|
|
17
|
+
metadata: z.string().optional(),
|
|
18
|
+
checksum: z.string().optional(),
|
|
19
|
+
checksumAlgorithm: z.string().optional(),
|
|
20
|
+
flow: z
|
|
21
|
+
.object({
|
|
22
|
+
flowId: z.string(),
|
|
23
|
+
nodeId: z.string(),
|
|
24
|
+
jobId: z.string(),
|
|
25
|
+
})
|
|
26
|
+
.optional(),
|
|
27
|
+
});
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
import { Context, Effect, Layer } from "effect";
|
|
2
|
+
import { UploadistaError } from "../errors";
|
|
3
|
+
import type { FlowJob } from "../flow";
|
|
4
|
+
import type { UploadFile } from "./upload-file";
|
|
5
|
+
/**
|
|
6
|
+
* Base key-value store interface for raw string storage.
|
|
7
|
+
*
|
|
8
|
+
* This is the low-level interface that storage adapters implement.
|
|
9
|
+
* It stores raw string values without type safety or serialization.
|
|
10
|
+
*
|
|
11
|
+
* @property get - Retrieves a value by key, returns null if not found
|
|
12
|
+
* @property set - Stores a value with the given key
|
|
13
|
+
* @property delete - Removes a value by key
|
|
14
|
+
* @property list - Optional operation to list all keys with a given prefix
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* // Implement a BaseKvStore with Redis
|
|
19
|
+
* const redisKvStore: BaseKvStore = {
|
|
20
|
+
* get: (key) => Effect.tryPromise({
|
|
21
|
+
* try: () => redis.get(key),
|
|
22
|
+
* catch: (error) => UploadistaError.fromCode("UNKNOWN_ERROR", { cause: error })
|
|
23
|
+
* }),
|
|
24
|
+
*
|
|
25
|
+
* set: (key, value) => Effect.tryPromise({
|
|
26
|
+
* try: () => redis.set(key, value),
|
|
27
|
+
* catch: (error) => UploadistaError.fromCode("UNKNOWN_ERROR", { cause: error })
|
|
28
|
+
* }),
|
|
29
|
+
*
|
|
30
|
+
* delete: (key) => Effect.tryPromise({
|
|
31
|
+
* try: () => redis.del(key),
|
|
32
|
+
* catch: (error) => UploadistaError.fromCode("UNKNOWN_ERROR", { cause: error })
|
|
33
|
+
* }),
|
|
34
|
+
*
|
|
35
|
+
* list: (prefix) => Effect.tryPromise({
|
|
36
|
+
* try: () => redis.keys(`${prefix}*`),
|
|
37
|
+
* catch: (error) => UploadistaError.fromCode("UNKNOWN_ERROR", { cause: error })
|
|
38
|
+
* })
|
|
39
|
+
* };
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export interface BaseKvStore {
|
|
43
|
+
readonly get: (key: string) => Effect.Effect<string | null, UploadistaError>;
|
|
44
|
+
readonly set: (key: string, value: string) => Effect.Effect<void, UploadistaError>;
|
|
45
|
+
readonly delete: (key: string) => Effect.Effect<void, UploadistaError>;
|
|
46
|
+
readonly list?: (keyPrefix: string) => Effect.Effect<Array<string>, UploadistaError>;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Type-safe key-value store interface with automatic serialization.
|
|
50
|
+
*
|
|
51
|
+
* This wraps a BaseKvStore and handles JSON serialization/deserialization
|
|
52
|
+
* for a specific data type, providing type safety and eliminating the need
|
|
53
|
+
* for manual JSON.stringify/parse calls.
|
|
54
|
+
*
|
|
55
|
+
* @template TData - The type of data stored in this KV store
|
|
56
|
+
*
|
|
57
|
+
* @property get - Retrieves and deserializes a value, fails if not found
|
|
58
|
+
* @property set - Serializes and stores a value
|
|
59
|
+
* @property delete - Removes a value by key
|
|
60
|
+
* @property list - Optional operation to list all keys (without prefix)
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```typescript
|
|
64
|
+
* // Use a typed KV store
|
|
65
|
+
* const uploadStore: KvStore<UploadFile> = new TypedKvStore(
|
|
66
|
+
* baseStore,
|
|
67
|
+
* "uploads:",
|
|
68
|
+
* jsonSerializer.serialize,
|
|
69
|
+
* jsonSerializer.deserialize
|
|
70
|
+
* );
|
|
71
|
+
*
|
|
72
|
+
* // Store and retrieve typed data
|
|
73
|
+
* const program = Effect.gen(function* () {
|
|
74
|
+
* const file: UploadFile = {
|
|
75
|
+
* id: "file123",
|
|
76
|
+
* offset: 0,
|
|
77
|
+
* storage: { id: "s3", type: "s3" }
|
|
78
|
+
* };
|
|
79
|
+
*
|
|
80
|
+
* // Automatic serialization
|
|
81
|
+
* yield* uploadStore.set("file123", file);
|
|
82
|
+
*
|
|
83
|
+
* // Automatic deserialization with type safety
|
|
84
|
+
* const retrieved = yield* uploadStore.get("file123");
|
|
85
|
+
* console.log(retrieved.offset); // TypeScript knows this is a number
|
|
86
|
+
* });
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
export type KvStore<TData> = {
|
|
90
|
+
readonly get: (key: string) => Effect.Effect<TData, UploadistaError>;
|
|
91
|
+
readonly set: (key: string, value: TData) => Effect.Effect<void, UploadistaError>;
|
|
92
|
+
readonly delete: (key: string) => Effect.Effect<void, UploadistaError>;
|
|
93
|
+
readonly list?: () => Effect.Effect<Array<string>, UploadistaError>;
|
|
94
|
+
};
|
|
95
|
+
/**
|
|
96
|
+
* Typed wrapper class that adds serialization to a BaseKvStore.
|
|
97
|
+
*
|
|
98
|
+
* This class implements the KvStore interface by wrapping a BaseKvStore
|
|
99
|
+
* and handling serialization/deserialization for a specific type. It also
|
|
100
|
+
* adds a key prefix to isolate different data types in the same store.
|
|
101
|
+
*
|
|
102
|
+
* @template TData - The type of data to store
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* ```typescript
|
|
106
|
+
* // Create a typed store for UploadFile
|
|
107
|
+
* const uploadFileStore = new TypedKvStore<UploadFile>(
|
|
108
|
+
* baseKvStore,
|
|
109
|
+
* "uploadista:upload-file:", // All keys will be prefixed
|
|
110
|
+
* (data) => JSON.stringify(data),
|
|
111
|
+
* (str) => JSON.parse(str) as UploadFile
|
|
112
|
+
* );
|
|
113
|
+
*
|
|
114
|
+
* // Use the store
|
|
115
|
+
* const effect = Effect.gen(function* () {
|
|
116
|
+
* const file: UploadFile = { ... };
|
|
117
|
+
* yield* uploadFileStore.set("abc123", file);
|
|
118
|
+
* // Internally stores at key "uploadista:upload-file:abc123"
|
|
119
|
+
*
|
|
120
|
+
* const retrieved = yield* uploadFileStore.get("abc123");
|
|
121
|
+
* return retrieved;
|
|
122
|
+
* });
|
|
123
|
+
*
|
|
124
|
+
* // Custom serialization for binary data
|
|
125
|
+
* const binaryStore = new TypedKvStore<Uint8Array>(
|
|
126
|
+
* baseKvStore,
|
|
127
|
+
* "binary:",
|
|
128
|
+
* (data) => btoa(String.fromCharCode(...data)), // Base64 encode
|
|
129
|
+
* (str) => Uint8Array.from(atob(str), c => c.charCodeAt(0)) // Base64 decode
|
|
130
|
+
* );
|
|
131
|
+
* ```
|
|
132
|
+
*/
|
|
133
|
+
export declare class TypedKvStore<TData> implements KvStore<TData> {
|
|
134
|
+
private baseStore;
|
|
135
|
+
private keyPrefix;
|
|
136
|
+
private serialize;
|
|
137
|
+
private deserialize;
|
|
138
|
+
constructor(baseStore: BaseKvStore, keyPrefix: string, serialize: (data: TData) => string, deserialize: (str: string) => TData);
|
|
139
|
+
get: (key: string) => Effect.Effect<TData, UploadistaError>;
|
|
140
|
+
set: (key: string, value: TData) => Effect.Effect<void, UploadistaError>;
|
|
141
|
+
delete: (key: string) => Effect.Effect<void, UploadistaError>;
|
|
142
|
+
list: () => Effect.Effect<Array<string>, UploadistaError>;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Default JSON serialization helpers.
|
|
146
|
+
*
|
|
147
|
+
* These functions provide standard JSON serialization for use with TypedKvStore.
|
|
148
|
+
* They work with any JSON-serializable type.
|
|
149
|
+
*
|
|
150
|
+
* @example
|
|
151
|
+
* ```typescript
|
|
152
|
+
* const store = new TypedKvStore<MyType>(
|
|
153
|
+
* baseStore,
|
|
154
|
+
* "mydata:",
|
|
155
|
+
* jsonSerializer.serialize,
|
|
156
|
+
* jsonSerializer.deserialize
|
|
157
|
+
* );
|
|
158
|
+
* ```
|
|
159
|
+
*/
|
|
160
|
+
export declare const jsonSerializer: {
|
|
161
|
+
serialize: <T>(data: T) => string;
|
|
162
|
+
deserialize: <T>(str: string) => T;
|
|
163
|
+
};
|
|
164
|
+
declare const BaseKvStoreService_base: Context.TagClass<BaseKvStoreService, "BaseKvStore", BaseKvStore>;
|
|
165
|
+
/**
|
|
166
|
+
* Effect-TS context tag for the base untyped KV store.
|
|
167
|
+
*
|
|
168
|
+
* This is the low-level store that storage adapter implementations provide.
|
|
169
|
+
* Most application code should use typed stores like UploadFileKVStore instead.
|
|
170
|
+
*
|
|
171
|
+
* @example
|
|
172
|
+
* ```typescript
|
|
173
|
+
* // Provide a base store implementation
|
|
174
|
+
* const baseStoreLayer = Layer.succeed(BaseKvStoreService, redisKvStore);
|
|
175
|
+
*
|
|
176
|
+
* // Use in an Effect
|
|
177
|
+
* const effect = Effect.gen(function* () {
|
|
178
|
+
* const baseStore = yield* BaseKvStoreService;
|
|
179
|
+
* yield* baseStore.set("raw-key", "raw-value");
|
|
180
|
+
* });
|
|
181
|
+
* ```
|
|
182
|
+
*/
|
|
183
|
+
export declare class BaseKvStoreService extends BaseKvStoreService_base {
|
|
184
|
+
}
|
|
185
|
+
declare const UploadFileKVStore_base: Context.TagClass<UploadFileKVStore, "UploadFileKVStore", KvStore<UploadFile>>;
|
|
186
|
+
/**
|
|
187
|
+
* Effect-TS context tag for the UploadFile typed KV store.
|
|
188
|
+
*
|
|
189
|
+
* This provides type-safe storage for UploadFile metadata. It's the primary
|
|
190
|
+
* way to store and retrieve upload metadata in the system.
|
|
191
|
+
*
|
|
192
|
+
* @example
|
|
193
|
+
* ```typescript
|
|
194
|
+
* const uploadEffect = Effect.gen(function* () {
|
|
195
|
+
* const kvStore = yield* UploadFileKVStore;
|
|
196
|
+
*
|
|
197
|
+
* // Store upload metadata
|
|
198
|
+
* const file: UploadFile = {
|
|
199
|
+
* id: "upload123",
|
|
200
|
+
* offset: 0,
|
|
201
|
+
* storage: { id: "s3", type: "s3" }
|
|
202
|
+
* };
|
|
203
|
+
* yield* kvStore.set("upload123", file);
|
|
204
|
+
*
|
|
205
|
+
* // Retrieve with type safety
|
|
206
|
+
* const retrieved = yield* kvStore.get("upload123");
|
|
207
|
+
* return retrieved;
|
|
208
|
+
* });
|
|
209
|
+
* ```
|
|
210
|
+
*/
|
|
211
|
+
export declare class UploadFileKVStore extends UploadFileKVStore_base {
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Effect Layer that creates the UploadFileKVStore from a BaseKvStore.
|
|
215
|
+
*
|
|
216
|
+
* This layer automatically wires up JSON serialization for UploadFile objects
|
|
217
|
+
* with the "uploadista:upload-file:" key prefix.
|
|
218
|
+
*
|
|
219
|
+
* @example
|
|
220
|
+
* ```typescript
|
|
221
|
+
* const program = Effect.gen(function* () {
|
|
222
|
+
* const kvStore = yield* UploadFileKVStore;
|
|
223
|
+
* // Use the store...
|
|
224
|
+
* }).pipe(
|
|
225
|
+
* Effect.provide(uploadFileKvStore),
|
|
226
|
+
* Effect.provide(baseStoreLayer)
|
|
227
|
+
* );
|
|
228
|
+
* ```
|
|
229
|
+
*/
|
|
230
|
+
export declare const uploadFileKvStore: Layer.Layer<UploadFileKVStore, never, BaseKvStoreService>;
|
|
231
|
+
declare const FlowJobKVStore_base: Context.TagClass<FlowJobKVStore, "FlowJobKVStore", KvStore<FlowJob>>;
|
|
232
|
+
/**
|
|
233
|
+
* Effect-TS context tag for the FlowJob typed KV store.
|
|
234
|
+
*
|
|
235
|
+
* This provides type-safe storage for FlowJob metadata, tracking the
|
|
236
|
+
* execution state of flow processing jobs.
|
|
237
|
+
*
|
|
238
|
+
* @example
|
|
239
|
+
* ```typescript
|
|
240
|
+
* const flowEffect = Effect.gen(function* () {
|
|
241
|
+
* const jobStore = yield* FlowJobKVStore;
|
|
242
|
+
*
|
|
243
|
+
* // Store job state
|
|
244
|
+
* const job: FlowJob = {
|
|
245
|
+
* id: "job123",
|
|
246
|
+
* flowId: "flow_resize",
|
|
247
|
+
* status: "running",
|
|
248
|
+
* tasks: [],
|
|
249
|
+
* createdAt: new Date(),
|
|
250
|
+
* updatedAt: new Date()
|
|
251
|
+
* };
|
|
252
|
+
* yield* jobStore.set("job123", job);
|
|
253
|
+
*
|
|
254
|
+
* // Retrieve and check status
|
|
255
|
+
* const retrieved = yield* jobStore.get("job123");
|
|
256
|
+
* return retrieved.status;
|
|
257
|
+
* });
|
|
258
|
+
* ```
|
|
259
|
+
*/
|
|
260
|
+
export declare class FlowJobKVStore extends FlowJobKVStore_base {
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Effect Layer that creates the FlowJobKVStore from a BaseKvStore.
|
|
264
|
+
*
|
|
265
|
+
* This layer automatically wires up JSON serialization for FlowJob objects
|
|
266
|
+
* with the "uploadista:flow-job:" key prefix.
|
|
267
|
+
*
|
|
268
|
+
* @example
|
|
269
|
+
* ```typescript
|
|
270
|
+
* const program = Effect.gen(function* () {
|
|
271
|
+
* const jobStore = yield* FlowJobKVStore;
|
|
272
|
+
* // Use the store...
|
|
273
|
+
* }).pipe(
|
|
274
|
+
* Effect.provide(flowJobKvStore),
|
|
275
|
+
* Effect.provide(baseStoreLayer)
|
|
276
|
+
* );
|
|
277
|
+
* ```
|
|
278
|
+
*/
|
|
279
|
+
export declare const flowJobKvStore: Layer.Layer<FlowJobKVStore, never, BaseKvStoreService>;
|
|
280
|
+
export {};
|
|
281
|
+
//# sourceMappingURL=kv-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kv-store.d.ts","sourceRoot":"","sources":["../../src/types/kv-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import { Context, Effect, Layer } from "effect";
|
|
2
|
+
import { UploadistaError } from "../errors";
|
|
3
|
+
/**
|
|
4
|
+
* Typed wrapper class that adds serialization to a BaseKvStore.
|
|
5
|
+
*
|
|
6
|
+
* This class implements the KvStore interface by wrapping a BaseKvStore
|
|
7
|
+
* and handling serialization/deserialization for a specific type. It also
|
|
8
|
+
* adds a key prefix to isolate different data types in the same store.
|
|
9
|
+
*
|
|
10
|
+
* @template TData - The type of data to store
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* // Create a typed store for UploadFile
|
|
15
|
+
* const uploadFileStore = new TypedKvStore<UploadFile>(
|
|
16
|
+
* baseKvStore,
|
|
17
|
+
* "uploadista:upload-file:", // All keys will be prefixed
|
|
18
|
+
* (data) => JSON.stringify(data),
|
|
19
|
+
* (str) => JSON.parse(str) as UploadFile
|
|
20
|
+
* );
|
|
21
|
+
*
|
|
22
|
+
* // Use the store
|
|
23
|
+
* const effect = Effect.gen(function* () {
|
|
24
|
+
* const file: UploadFile = { ... };
|
|
25
|
+
* yield* uploadFileStore.set("abc123", file);
|
|
26
|
+
* // Internally stores at key "uploadista:upload-file:abc123"
|
|
27
|
+
*
|
|
28
|
+
* const retrieved = yield* uploadFileStore.get("abc123");
|
|
29
|
+
* return retrieved;
|
|
30
|
+
* });
|
|
31
|
+
*
|
|
32
|
+
* // Custom serialization for binary data
|
|
33
|
+
* const binaryStore = new TypedKvStore<Uint8Array>(
|
|
34
|
+
* baseKvStore,
|
|
35
|
+
* "binary:",
|
|
36
|
+
* (data) => btoa(String.fromCharCode(...data)), // Base64 encode
|
|
37
|
+
* (str) => Uint8Array.from(atob(str), c => c.charCodeAt(0)) // Base64 decode
|
|
38
|
+
* );
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export class TypedKvStore {
|
|
42
|
+
baseStore;
|
|
43
|
+
keyPrefix;
|
|
44
|
+
serialize;
|
|
45
|
+
deserialize;
|
|
46
|
+
constructor(baseStore, keyPrefix, serialize, deserialize) {
|
|
47
|
+
this.baseStore = baseStore;
|
|
48
|
+
this.keyPrefix = keyPrefix;
|
|
49
|
+
this.serialize = serialize;
|
|
50
|
+
this.deserialize = deserialize;
|
|
51
|
+
}
|
|
52
|
+
get = (key) => this.baseStore.get(this.keyPrefix + key).pipe(Effect.flatMap((value) => {
|
|
53
|
+
if (value === null) {
|
|
54
|
+
return Effect.fail(UploadistaError.fromCode("FILE_NOT_FOUND", {
|
|
55
|
+
cause: `Key "${key}" not found`,
|
|
56
|
+
}));
|
|
57
|
+
}
|
|
58
|
+
try {
|
|
59
|
+
return Effect.succeed(this.deserialize(value));
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
return Effect.fail(new UploadistaError({
|
|
63
|
+
code: "VALIDATION_ERROR",
|
|
64
|
+
status: 400,
|
|
65
|
+
body: `Failed to deserialize value for key "${key}"`,
|
|
66
|
+
cause: error,
|
|
67
|
+
}));
|
|
68
|
+
}
|
|
69
|
+
}));
|
|
70
|
+
set = (key, value) => {
|
|
71
|
+
try {
|
|
72
|
+
const serialized = this.serialize(value);
|
|
73
|
+
return this.baseStore.set(this.keyPrefix + key, serialized);
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
return Effect.fail(new UploadistaError({
|
|
77
|
+
code: "VALIDATION_ERROR",
|
|
78
|
+
status: 400,
|
|
79
|
+
body: `Failed to serialize value for key "${key}"`,
|
|
80
|
+
cause: error,
|
|
81
|
+
}));
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
delete = (key) => this.baseStore.delete(this.keyPrefix + key);
|
|
85
|
+
list = () => {
|
|
86
|
+
if (this.baseStore.list) {
|
|
87
|
+
return this.baseStore.list(this.keyPrefix);
|
|
88
|
+
}
|
|
89
|
+
return Effect.fail(new UploadistaError({
|
|
90
|
+
code: "UNKNOWN_ERROR",
|
|
91
|
+
status: 501,
|
|
92
|
+
body: "List operation not supported by this store",
|
|
93
|
+
}));
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Default JSON serialization helpers.
|
|
98
|
+
*
|
|
99
|
+
* These functions provide standard JSON serialization for use with TypedKvStore.
|
|
100
|
+
* They work with any JSON-serializable type.
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```typescript
|
|
104
|
+
* const store = new TypedKvStore<MyType>(
|
|
105
|
+
* baseStore,
|
|
106
|
+
* "mydata:",
|
|
107
|
+
* jsonSerializer.serialize,
|
|
108
|
+
* jsonSerializer.deserialize
|
|
109
|
+
* );
|
|
110
|
+
* ```
|
|
111
|
+
*/
|
|
112
|
+
export const jsonSerializer = {
|
|
113
|
+
serialize: (data) => JSON.stringify(data),
|
|
114
|
+
deserialize: (str) => JSON.parse(str),
|
|
115
|
+
};
|
|
116
|
+
/**
|
|
117
|
+
* Effect-TS context tag for the base untyped KV store.
|
|
118
|
+
*
|
|
119
|
+
* This is the low-level store that storage adapter implementations provide.
|
|
120
|
+
* Most application code should use typed stores like UploadFileKVStore instead.
|
|
121
|
+
*
|
|
122
|
+
* @example
|
|
123
|
+
* ```typescript
|
|
124
|
+
* // Provide a base store implementation
|
|
125
|
+
* const baseStoreLayer = Layer.succeed(BaseKvStoreService, redisKvStore);
|
|
126
|
+
*
|
|
127
|
+
* // Use in an Effect
|
|
128
|
+
* const effect = Effect.gen(function* () {
|
|
129
|
+
* const baseStore = yield* BaseKvStoreService;
|
|
130
|
+
* yield* baseStore.set("raw-key", "raw-value");
|
|
131
|
+
* });
|
|
132
|
+
* ```
|
|
133
|
+
*/
|
|
134
|
+
export class BaseKvStoreService extends Context.Tag("BaseKvStore")() {
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Effect-TS context tag for the UploadFile typed KV store.
|
|
138
|
+
*
|
|
139
|
+
* This provides type-safe storage for UploadFile metadata. It's the primary
|
|
140
|
+
* way to store and retrieve upload metadata in the system.
|
|
141
|
+
*
|
|
142
|
+
* @example
|
|
143
|
+
* ```typescript
|
|
144
|
+
* const uploadEffect = Effect.gen(function* () {
|
|
145
|
+
* const kvStore = yield* UploadFileKVStore;
|
|
146
|
+
*
|
|
147
|
+
* // Store upload metadata
|
|
148
|
+
* const file: UploadFile = {
|
|
149
|
+
* id: "upload123",
|
|
150
|
+
* offset: 0,
|
|
151
|
+
* storage: { id: "s3", type: "s3" }
|
|
152
|
+
* };
|
|
153
|
+
* yield* kvStore.set("upload123", file);
|
|
154
|
+
*
|
|
155
|
+
* // Retrieve with type safety
|
|
156
|
+
* const retrieved = yield* kvStore.get("upload123");
|
|
157
|
+
* return retrieved;
|
|
158
|
+
* });
|
|
159
|
+
* ```
|
|
160
|
+
*/
|
|
161
|
+
export class UploadFileKVStore extends Context.Tag("UploadFileKVStore")() {
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Effect Layer that creates the UploadFileKVStore from a BaseKvStore.
|
|
165
|
+
*
|
|
166
|
+
* This layer automatically wires up JSON serialization for UploadFile objects
|
|
167
|
+
* with the "uploadista:upload-file:" key prefix.
|
|
168
|
+
*
|
|
169
|
+
* @example
|
|
170
|
+
* ```typescript
|
|
171
|
+
* const program = Effect.gen(function* () {
|
|
172
|
+
* const kvStore = yield* UploadFileKVStore;
|
|
173
|
+
* // Use the store...
|
|
174
|
+
* }).pipe(
|
|
175
|
+
* Effect.provide(uploadFileKvStore),
|
|
176
|
+
* Effect.provide(baseStoreLayer)
|
|
177
|
+
* );
|
|
178
|
+
* ```
|
|
179
|
+
*/
|
|
180
|
+
export const uploadFileKvStore = Layer.effect(UploadFileKVStore, Effect.gen(function* () {
|
|
181
|
+
const baseStore = yield* BaseKvStoreService;
|
|
182
|
+
return new TypedKvStore(baseStore, "uploadista:upload-file:", jsonSerializer.serialize, jsonSerializer.deserialize);
|
|
183
|
+
}));
|
|
184
|
+
/**
|
|
185
|
+
* Effect-TS context tag for the FlowJob typed KV store.
|
|
186
|
+
*
|
|
187
|
+
* This provides type-safe storage for FlowJob metadata, tracking the
|
|
188
|
+
* execution state of flow processing jobs.
|
|
189
|
+
*
|
|
190
|
+
* @example
|
|
191
|
+
* ```typescript
|
|
192
|
+
* const flowEffect = Effect.gen(function* () {
|
|
193
|
+
* const jobStore = yield* FlowJobKVStore;
|
|
194
|
+
*
|
|
195
|
+
* // Store job state
|
|
196
|
+
* const job: FlowJob = {
|
|
197
|
+
* id: "job123",
|
|
198
|
+
* flowId: "flow_resize",
|
|
199
|
+
* status: "running",
|
|
200
|
+
* tasks: [],
|
|
201
|
+
* createdAt: new Date(),
|
|
202
|
+
* updatedAt: new Date()
|
|
203
|
+
* };
|
|
204
|
+
* yield* jobStore.set("job123", job);
|
|
205
|
+
*
|
|
206
|
+
* // Retrieve and check status
|
|
207
|
+
* const retrieved = yield* jobStore.get("job123");
|
|
208
|
+
* return retrieved.status;
|
|
209
|
+
* });
|
|
210
|
+
* ```
|
|
211
|
+
*/
|
|
212
|
+
export class FlowJobKVStore extends Context.Tag("FlowJobKVStore")() {
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Effect Layer that creates the FlowJobKVStore from a BaseKvStore.
|
|
216
|
+
*
|
|
217
|
+
* This layer automatically wires up JSON serialization for FlowJob objects
|
|
218
|
+
* with the "uploadista:flow-job:" key prefix.
|
|
219
|
+
*
|
|
220
|
+
* @example
|
|
221
|
+
* ```typescript
|
|
222
|
+
* const program = Effect.gen(function* () {
|
|
223
|
+
* const jobStore = yield* FlowJobKVStore;
|
|
224
|
+
* // Use the store...
|
|
225
|
+
* }).pipe(
|
|
226
|
+
* Effect.provide(flowJobKvStore),
|
|
227
|
+
* Effect.provide(baseStoreLayer)
|
|
228
|
+
* );
|
|
229
|
+
* ```
|
|
230
|
+
*/
|
|
231
|
+
export const flowJobKvStore = Layer.effect(FlowJobKVStore, Effect.gen(function* () {
|
|
232
|
+
const baseStore = yield* BaseKvStoreService;
|
|
233
|
+
return new TypedKvStore(baseStore, "uploadista:flow-job:", jsonSerializer.serialize, jsonSerializer.deserialize);
|
|
234
|
+
}));
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Context, Effect, Layer } from "effect";
|
|
2
|
+
import type { UploadistaError } from "../errors";
|
|
3
|
+
export type MiddlewareContext = {
|
|
4
|
+
request: Request;
|
|
5
|
+
uploadId?: string;
|
|
6
|
+
metadata?: Record<string, string>;
|
|
7
|
+
};
|
|
8
|
+
export type MiddlewareNext = () => Promise<Response>;
|
|
9
|
+
export type Middleware = (context: MiddlewareContext, next: MiddlewareNext) => Promise<Response>;
|
|
10
|
+
declare const MiddlewareService_base: Context.TagClass<MiddlewareService, "MiddlewareService", {
|
|
11
|
+
readonly execute: (middlewares: Middleware[], context: MiddlewareContext, handler: MiddlewareNext) => Effect.Effect<Response, UploadistaError>;
|
|
12
|
+
}>;
|
|
13
|
+
export declare class MiddlewareService extends MiddlewareService_base {
|
|
14
|
+
}
|
|
15
|
+
export declare const MiddlewareServiceLive: Layer.Layer<MiddlewareService, never, never>;
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=middleware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/types/middleware.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAChD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEjD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,CAAC;AAErD,MAAM,MAAM,UAAU,GAAG,CACvB,OAAO,EAAE,iBAAiB,EAC1B,IAAI,EAAE,cAAc,KACjB,OAAO,CAAC,QAAQ,CAAC,CAAC;;sBAMD,CAChB,WAAW,EAAE,UAAU,EAAE,EACzB,OAAO,EAAE,iBAAiB,EAC1B,OAAO,EAAE,cAAc,KACpB,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,eAAe,CAAC;;AAPjD,qBAAa,iBAAkB,SAAQ,sBASpC;CAAG;AAEN,eAAO,MAAM,qBAAqB,8CAyBjC,CAAC"}
|