@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,221 @@
|
|
|
1
|
+
import { Context, Effect, Layer } from "effect";
|
|
2
|
+
import type { UploadistaError } from "../errors";
|
|
3
|
+
import type { DataStore, DataStoreCapabilities, EventEmitter, InputFile, KvStore, Middleware, UploadEvent, UploadFile, WebSocketConnection } from "../types";
|
|
4
|
+
import { UploadEventEmitter, UploadFileDataStores, UploadFileKVStore } from "../types";
|
|
5
|
+
import { GenerateId, type GenerateIdShape } from "../utils/generate-id";
|
|
6
|
+
/**
|
|
7
|
+
* Legacy configuration options for UploadServer.
|
|
8
|
+
*
|
|
9
|
+
* @deprecated Use Effect Layers instead of this configuration object.
|
|
10
|
+
* This type is kept for backward compatibility.
|
|
11
|
+
*
|
|
12
|
+
* @property dataStore - DataStore instance or factory function
|
|
13
|
+
* @property kvStore - KV store for upload metadata
|
|
14
|
+
* @property eventEmitter - Event emitter for upload progress
|
|
15
|
+
* @property generateId - Optional ID generator (defaults to UUID)
|
|
16
|
+
* @property middlewares - Optional request middlewares
|
|
17
|
+
* @property withTracing - Enable Effect tracing for debugging
|
|
18
|
+
*/
|
|
19
|
+
export type UploadServerOptions = {
|
|
20
|
+
dataStore: ((storageId: string) => Promise<DataStore<UploadFile>>) | DataStore<UploadFile>;
|
|
21
|
+
kvStore: KvStore<UploadFile>;
|
|
22
|
+
eventEmitter: EventEmitter<UploadEvent>;
|
|
23
|
+
generateId?: GenerateIdShape;
|
|
24
|
+
middlewares?: Middleware[];
|
|
25
|
+
withTracing?: boolean;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* UploadServer service interface.
|
|
29
|
+
*
|
|
30
|
+
* This is the core upload handling service that provides all file upload operations.
|
|
31
|
+
* It manages upload lifecycle, resumable uploads, progress tracking, and storage integration.
|
|
32
|
+
*
|
|
33
|
+
* All operations return Effect types for composable, type-safe error handling.
|
|
34
|
+
*
|
|
35
|
+
* @property createUpload - Initiates a new upload and returns metadata
|
|
36
|
+
* @property uploadChunk - Uploads a chunk of data for an existing upload
|
|
37
|
+
* @property getCapabilities - Returns storage backend capabilities
|
|
38
|
+
* @property upload - Complete upload in one operation (create + upload data)
|
|
39
|
+
* @property uploadFromUrl - Uploads a file from a remote URL
|
|
40
|
+
* @property getUpload - Retrieves upload metadata by ID
|
|
41
|
+
* @property read - Reads the complete uploaded file data
|
|
42
|
+
* @property delete - Deletes an upload and its data
|
|
43
|
+
* @property subscribeToUploadEvents - Subscribes WebSocket to upload progress events
|
|
44
|
+
* @property unsubscribeFromUploadEvents - Unsubscribes from upload events
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```typescript
|
|
48
|
+
* // Basic upload flow
|
|
49
|
+
* const program = Effect.gen(function* () {
|
|
50
|
+
* const server = yield* UploadServer;
|
|
51
|
+
*
|
|
52
|
+
* // 1. Create upload
|
|
53
|
+
* const inputFile: InputFile = {
|
|
54
|
+
* storageId: "s3-production",
|
|
55
|
+
* size: 1024000,
|
|
56
|
+
* type: "image/jpeg",
|
|
57
|
+
* fileName: "photo.jpg"
|
|
58
|
+
* };
|
|
59
|
+
* const upload = yield* server.createUpload(inputFile, "client123");
|
|
60
|
+
*
|
|
61
|
+
* // 2. Upload chunks
|
|
62
|
+
* const chunk = new ReadableStream(...);
|
|
63
|
+
* const updated = yield* server.uploadChunk(upload.id, "client123", chunk);
|
|
64
|
+
*
|
|
65
|
+
* // 3. Read the uploaded file
|
|
66
|
+
* const data = yield* server.read(upload.id, "client123");
|
|
67
|
+
*
|
|
68
|
+
* return upload;
|
|
69
|
+
* });
|
|
70
|
+
*
|
|
71
|
+
* // Upload with WebSocket progress tracking
|
|
72
|
+
* const uploadWithProgress = Effect.gen(function* () {
|
|
73
|
+
* const server = yield* UploadServer;
|
|
74
|
+
*
|
|
75
|
+
* // Subscribe to progress events
|
|
76
|
+
* yield* server.subscribeToUploadEvents(uploadId, websocket);
|
|
77
|
+
*
|
|
78
|
+
* // Upload (events will be emitted automatically)
|
|
79
|
+
* const result = yield* server.upload(inputFile, clientId, stream);
|
|
80
|
+
*
|
|
81
|
+
* // Unsubscribe when done
|
|
82
|
+
* yield* server.unsubscribeFromUploadEvents(uploadId);
|
|
83
|
+
*
|
|
84
|
+
* return result;
|
|
85
|
+
* });
|
|
86
|
+
*
|
|
87
|
+
* // Upload from URL
|
|
88
|
+
* const urlUpload = Effect.gen(function* () {
|
|
89
|
+
* const server = yield* UploadServer;
|
|
90
|
+
*
|
|
91
|
+
* const inputFile: InputFile = {
|
|
92
|
+
* storageId: "s3-production",
|
|
93
|
+
* size: 0, // Unknown initially
|
|
94
|
+
* type: "image/png",
|
|
95
|
+
* fileName: "remote-image.png"
|
|
96
|
+
* };
|
|
97
|
+
*
|
|
98
|
+
* const upload = yield* server.uploadFromUrl(
|
|
99
|
+
* inputFile,
|
|
100
|
+
* "client123",
|
|
101
|
+
* "https://example.com/image.png"
|
|
102
|
+
* );
|
|
103
|
+
*
|
|
104
|
+
* return upload;
|
|
105
|
+
* });
|
|
106
|
+
* ```
|
|
107
|
+
*/
|
|
108
|
+
export type UploadServerShape = {
|
|
109
|
+
createUpload: (inputFile: InputFile, clientId: string | null) => Effect.Effect<UploadFile, UploadistaError>;
|
|
110
|
+
uploadChunk: (uploadId: string, clientId: string | null, chunk: ReadableStream) => Effect.Effect<UploadFile, UploadistaError>;
|
|
111
|
+
getCapabilities: (storageId: string, clientId: string | null) => Effect.Effect<DataStoreCapabilities, UploadistaError>;
|
|
112
|
+
upload: (file: InputFile, clientId: string | null, stream: ReadableStream) => Effect.Effect<UploadFile, UploadistaError>;
|
|
113
|
+
uploadFromUrl: (inputFile: InputFile, clientId: string | null, url: string) => Effect.Effect<UploadFile, UploadistaError>;
|
|
114
|
+
getUpload: (uploadId: string) => Effect.Effect<UploadFile, UploadistaError>;
|
|
115
|
+
read: (uploadId: string, clientId: string | null) => Effect.Effect<Uint8Array, UploadistaError>;
|
|
116
|
+
delete: (uploadId: string, clientId: string | null) => Effect.Effect<void, UploadistaError>;
|
|
117
|
+
subscribeToUploadEvents: (uploadId: string, connection: WebSocketConnection) => Effect.Effect<void, UploadistaError>;
|
|
118
|
+
unsubscribeFromUploadEvents: (uploadId: string) => Effect.Effect<void, UploadistaError>;
|
|
119
|
+
};
|
|
120
|
+
declare const UploadServer_base: Context.TagClass<UploadServer, "UploadServer", UploadServerShape>;
|
|
121
|
+
/**
|
|
122
|
+
* Effect-TS context tag for the UploadServer service.
|
|
123
|
+
*
|
|
124
|
+
* Use this tag to access the UploadServer in an Effect context.
|
|
125
|
+
* The server must be provided via a Layer or dependency injection.
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* ```typescript
|
|
129
|
+
* // Access UploadServer in an Effect
|
|
130
|
+
* const uploadEffect = Effect.gen(function* () {
|
|
131
|
+
* const server = yield* UploadServer;
|
|
132
|
+
* const upload = yield* server.createUpload(inputFile, clientId);
|
|
133
|
+
* return upload;
|
|
134
|
+
* });
|
|
135
|
+
*
|
|
136
|
+
* // Provide UploadServer layer
|
|
137
|
+
* const program = uploadEffect.pipe(
|
|
138
|
+
* Effect.provide(uploadServer),
|
|
139
|
+
* Effect.provide(uploadFileKvStore),
|
|
140
|
+
* Effect.provide(dataStoreLayer),
|
|
141
|
+
* Effect.provide(eventEmitterLayer)
|
|
142
|
+
* );
|
|
143
|
+
* ```
|
|
144
|
+
*/
|
|
145
|
+
export declare class UploadServer extends UploadServer_base {
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Creates the UploadServer implementation.
|
|
149
|
+
*
|
|
150
|
+
* This function constructs the UploadServer service by composing all required
|
|
151
|
+
* dependencies (KV store, data stores, event emitter, ID generator). It implements
|
|
152
|
+
* all upload operations defined in UploadServerShape.
|
|
153
|
+
*
|
|
154
|
+
* The server automatically handles:
|
|
155
|
+
* - Upload lifecycle management (create, resume, complete)
|
|
156
|
+
* - Progress tracking and event emission
|
|
157
|
+
* - Storage backend routing based on storageId
|
|
158
|
+
* - Error handling with proper UploadistaError types
|
|
159
|
+
*
|
|
160
|
+
* @returns An Effect that yields the UploadServerShape implementation
|
|
161
|
+
*
|
|
162
|
+
* @example
|
|
163
|
+
* ```typescript
|
|
164
|
+
* // Create a custom UploadServer layer
|
|
165
|
+
* const myUploadServer = Layer.effect(
|
|
166
|
+
* UploadServer,
|
|
167
|
+
* createUploadServer()
|
|
168
|
+
* );
|
|
169
|
+
*
|
|
170
|
+
* // Use in a program
|
|
171
|
+
* const program = Effect.gen(function* () {
|
|
172
|
+
* const server = yield* UploadServer;
|
|
173
|
+
* // Use server operations...
|
|
174
|
+
* }).pipe(Effect.provide(myUploadServer));
|
|
175
|
+
* ```
|
|
176
|
+
*/
|
|
177
|
+
export declare function createUploadServer(): Effect.Effect<{
|
|
178
|
+
upload: (inputFile: InputFile, clientId: string | null, stream: ReadableStream) => Effect.Effect<UploadFile, UploadistaError, never>;
|
|
179
|
+
uploadFromUrl: (inputFile: InputFile, clientId: string | null, url: string) => Effect.Effect<UploadFile, UploadistaError, never>;
|
|
180
|
+
createUpload: (inputFile: InputFile, clientId: string | null) => Effect.Effect<UploadFile, UploadistaError, never>;
|
|
181
|
+
uploadChunk: (uploadId: string, clientId: string | null, chunk: ReadableStream) => Effect.Effect<UploadFile, UploadistaError, never>;
|
|
182
|
+
getUpload: (uploadId: string) => Effect.Effect<UploadFile, UploadistaError, never>;
|
|
183
|
+
read: (uploadId: string, clientId: string | null) => Effect.Effect<Uint8Array<ArrayBufferLike>, UploadistaError, never>;
|
|
184
|
+
delete: (uploadId: string, clientId: string | null) => Effect.Effect<void, UploadistaError, never>;
|
|
185
|
+
getCapabilities: (storageId: string, clientId: string | null) => Effect.Effect<DataStoreCapabilities, UploadistaError, never>;
|
|
186
|
+
subscribeToUploadEvents: (uploadId: string, connection: WebSocketConnection) => Effect.Effect<void, UploadistaError, never>;
|
|
187
|
+
unsubscribeFromUploadEvents: (uploadId: string) => Effect.Effect<void, UploadistaError, never>;
|
|
188
|
+
}, never, UploadFileKVStore | UploadFileDataStores | UploadEventEmitter | GenerateId>;
|
|
189
|
+
/**
|
|
190
|
+
* Pre-built UploadServer Effect Layer.
|
|
191
|
+
*
|
|
192
|
+
* This layer provides a ready-to-use UploadServer implementation that can be
|
|
193
|
+
* composed with other layers to build a complete upload system.
|
|
194
|
+
*
|
|
195
|
+
* Required dependencies:
|
|
196
|
+
* - UploadFileKVStore: For storing upload metadata
|
|
197
|
+
* - UploadFileDataStores: For routing to storage backends
|
|
198
|
+
* - UploadEventEmitter: For progress events
|
|
199
|
+
* - GenerateId: For creating upload IDs
|
|
200
|
+
*
|
|
201
|
+
* @example
|
|
202
|
+
* ```typescript
|
|
203
|
+
* // Compose a complete upload system
|
|
204
|
+
* const fullUploadSystem = Layer.mergeAll(
|
|
205
|
+
* uploadServer,
|
|
206
|
+
* uploadFileKvStore,
|
|
207
|
+
* dataStoreLayer,
|
|
208
|
+
* uploadEventEmitter,
|
|
209
|
+
* generateIdLayer
|
|
210
|
+
* );
|
|
211
|
+
*
|
|
212
|
+
* // Use in application
|
|
213
|
+
* const app = Effect.gen(function* () {
|
|
214
|
+
* const server = yield* UploadServer;
|
|
215
|
+
* // Perform uploads...
|
|
216
|
+
* }).pipe(Effect.provide(fullUploadSystem));
|
|
217
|
+
* ```
|
|
218
|
+
*/
|
|
219
|
+
export declare const uploadServer: Layer.Layer<UploadServer, never, UploadFileKVStore | UploadFileDataStores | UploadEventEmitter | GenerateId>;
|
|
220
|
+
export {};
|
|
221
|
+
//# sourceMappingURL=upload-server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upload-server.d.ts","sourceRoot":"","sources":["../../src/upload/upload-server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { Context, Effect, Layer } from "effect";
|
|
2
|
+
import { UploadEventEmitter, UploadFileDataStores, UploadFileKVStore, } from "../types";
|
|
3
|
+
import { GenerateId } from "../utils/generate-id";
|
|
4
|
+
import { createUpload } from "./create-upload";
|
|
5
|
+
import { uploadChunk } from "./upload-chunk";
|
|
6
|
+
import { arrayBuffer, fetchFile } from "./upload-url";
|
|
7
|
+
/**
|
|
8
|
+
* Effect-TS context tag for the UploadServer service.
|
|
9
|
+
*
|
|
10
|
+
* Use this tag to access the UploadServer in an Effect context.
|
|
11
|
+
* The server must be provided via a Layer or dependency injection.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* // Access UploadServer in an Effect
|
|
16
|
+
* const uploadEffect = Effect.gen(function* () {
|
|
17
|
+
* const server = yield* UploadServer;
|
|
18
|
+
* const upload = yield* server.createUpload(inputFile, clientId);
|
|
19
|
+
* return upload;
|
|
20
|
+
* });
|
|
21
|
+
*
|
|
22
|
+
* // Provide UploadServer layer
|
|
23
|
+
* const program = uploadEffect.pipe(
|
|
24
|
+
* Effect.provide(uploadServer),
|
|
25
|
+
* Effect.provide(uploadFileKvStore),
|
|
26
|
+
* Effect.provide(dataStoreLayer),
|
|
27
|
+
* Effect.provide(eventEmitterLayer)
|
|
28
|
+
* );
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export class UploadServer extends Context.Tag("UploadServer")() {
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Creates the UploadServer implementation.
|
|
35
|
+
*
|
|
36
|
+
* This function constructs the UploadServer service by composing all required
|
|
37
|
+
* dependencies (KV store, data stores, event emitter, ID generator). It implements
|
|
38
|
+
* all upload operations defined in UploadServerShape.
|
|
39
|
+
*
|
|
40
|
+
* The server automatically handles:
|
|
41
|
+
* - Upload lifecycle management (create, resume, complete)
|
|
42
|
+
* - Progress tracking and event emission
|
|
43
|
+
* - Storage backend routing based on storageId
|
|
44
|
+
* - Error handling with proper UploadistaError types
|
|
45
|
+
*
|
|
46
|
+
* @returns An Effect that yields the UploadServerShape implementation
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```typescript
|
|
50
|
+
* // Create a custom UploadServer layer
|
|
51
|
+
* const myUploadServer = Layer.effect(
|
|
52
|
+
* UploadServer,
|
|
53
|
+
* createUploadServer()
|
|
54
|
+
* );
|
|
55
|
+
*
|
|
56
|
+
* // Use in a program
|
|
57
|
+
* const program = Effect.gen(function* () {
|
|
58
|
+
* const server = yield* UploadServer;
|
|
59
|
+
* // Use server operations...
|
|
60
|
+
* }).pipe(Effect.provide(myUploadServer));
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export function createUploadServer() {
|
|
64
|
+
return Effect.gen(function* () {
|
|
65
|
+
const kvStore = yield* UploadFileKVStore;
|
|
66
|
+
const eventEmitter = yield* UploadEventEmitter;
|
|
67
|
+
const generateId = yield* GenerateId;
|
|
68
|
+
const dataStoreService = yield* UploadFileDataStores;
|
|
69
|
+
return {
|
|
70
|
+
upload: (inputFile, clientId, stream) => Effect.gen(function* () {
|
|
71
|
+
const fileCreated = yield* createUpload(inputFile, clientId, {
|
|
72
|
+
dataStoreService,
|
|
73
|
+
kvStore,
|
|
74
|
+
eventEmitter,
|
|
75
|
+
generateId,
|
|
76
|
+
});
|
|
77
|
+
return yield* uploadChunk(fileCreated.id, clientId, stream, {
|
|
78
|
+
dataStoreService,
|
|
79
|
+
kvStore,
|
|
80
|
+
eventEmitter,
|
|
81
|
+
});
|
|
82
|
+
}),
|
|
83
|
+
uploadFromUrl: (inputFile, clientId, url) => Effect.gen(function* () {
|
|
84
|
+
const response = yield* fetchFile(url);
|
|
85
|
+
const buffer = yield* arrayBuffer(response);
|
|
86
|
+
// Create a readable stream from the buffer
|
|
87
|
+
const stream = new ReadableStream({
|
|
88
|
+
start(controller) {
|
|
89
|
+
controller.enqueue(new Uint8Array(buffer));
|
|
90
|
+
controller.close();
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
const fileCreated = yield* createUpload({ ...inputFile, size: buffer.byteLength }, clientId, {
|
|
94
|
+
dataStoreService,
|
|
95
|
+
kvStore,
|
|
96
|
+
eventEmitter,
|
|
97
|
+
generateId,
|
|
98
|
+
});
|
|
99
|
+
return yield* uploadChunk(fileCreated.id, clientId, stream, {
|
|
100
|
+
dataStoreService,
|
|
101
|
+
kvStore,
|
|
102
|
+
eventEmitter,
|
|
103
|
+
});
|
|
104
|
+
}),
|
|
105
|
+
createUpload: (inputFile, clientId) => Effect.gen(function* () {
|
|
106
|
+
const fileCreated = yield* createUpload(inputFile, clientId, {
|
|
107
|
+
dataStoreService,
|
|
108
|
+
kvStore,
|
|
109
|
+
eventEmitter,
|
|
110
|
+
generateId,
|
|
111
|
+
});
|
|
112
|
+
return fileCreated;
|
|
113
|
+
}),
|
|
114
|
+
uploadChunk: (uploadId, clientId, chunk) => Effect.gen(function* () {
|
|
115
|
+
const file = yield* uploadChunk(uploadId, clientId, chunk, {
|
|
116
|
+
dataStoreService,
|
|
117
|
+
kvStore,
|
|
118
|
+
eventEmitter,
|
|
119
|
+
});
|
|
120
|
+
return file;
|
|
121
|
+
}),
|
|
122
|
+
getUpload: (uploadId) => Effect.gen(function* () {
|
|
123
|
+
const file = yield* kvStore.get(uploadId);
|
|
124
|
+
return file;
|
|
125
|
+
}),
|
|
126
|
+
read: (uploadId, clientId) => Effect.gen(function* () {
|
|
127
|
+
const upload = yield* kvStore.get(uploadId);
|
|
128
|
+
const dataStore = yield* dataStoreService.getDataStore(upload.storage.id, clientId);
|
|
129
|
+
return yield* dataStore.read(uploadId);
|
|
130
|
+
}),
|
|
131
|
+
delete: (uploadId, clientId) => Effect.gen(function* () {
|
|
132
|
+
const upload = yield* kvStore.get(uploadId);
|
|
133
|
+
const dataStore = yield* dataStoreService.getDataStore(upload.storage.id, clientId);
|
|
134
|
+
yield* dataStore.remove(uploadId);
|
|
135
|
+
yield* kvStore.delete(uploadId);
|
|
136
|
+
return;
|
|
137
|
+
}),
|
|
138
|
+
getCapabilities: (storageId, clientId) => Effect.gen(function* () {
|
|
139
|
+
const dataStore = yield* dataStoreService.getDataStore(storageId, clientId);
|
|
140
|
+
return dataStore.getCapabilities();
|
|
141
|
+
}),
|
|
142
|
+
subscribeToUploadEvents: (uploadId, connection) => Effect.gen(function* () {
|
|
143
|
+
yield* eventEmitter.subscribe(uploadId, connection);
|
|
144
|
+
}),
|
|
145
|
+
unsubscribeFromUploadEvents: (uploadId) => Effect.gen(function* () {
|
|
146
|
+
yield* eventEmitter.unsubscribe(uploadId);
|
|
147
|
+
}),
|
|
148
|
+
};
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Pre-built UploadServer Effect Layer.
|
|
153
|
+
*
|
|
154
|
+
* This layer provides a ready-to-use UploadServer implementation that can be
|
|
155
|
+
* composed with other layers to build a complete upload system.
|
|
156
|
+
*
|
|
157
|
+
* Required dependencies:
|
|
158
|
+
* - UploadFileKVStore: For storing upload metadata
|
|
159
|
+
* - UploadFileDataStores: For routing to storage backends
|
|
160
|
+
* - UploadEventEmitter: For progress events
|
|
161
|
+
* - GenerateId: For creating upload IDs
|
|
162
|
+
*
|
|
163
|
+
* @example
|
|
164
|
+
* ```typescript
|
|
165
|
+
* // Compose a complete upload system
|
|
166
|
+
* const fullUploadSystem = Layer.mergeAll(
|
|
167
|
+
* uploadServer,
|
|
168
|
+
* uploadFileKvStore,
|
|
169
|
+
* dataStoreLayer,
|
|
170
|
+
* uploadEventEmitter,
|
|
171
|
+
* generateIdLayer
|
|
172
|
+
* );
|
|
173
|
+
*
|
|
174
|
+
* // Use in application
|
|
175
|
+
* const app = Effect.gen(function* () {
|
|
176
|
+
* const server = yield* UploadServer;
|
|
177
|
+
* // Perform uploads...
|
|
178
|
+
* }).pipe(Effect.provide(fullUploadSystem));
|
|
179
|
+
* ```
|
|
180
|
+
*/
|
|
181
|
+
export const uploadServer = Layer.effect(UploadServer, createUploadServer());
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import type { DataStoreCapabilities, UploadStrategy } from "../types";
|
|
2
|
+
/**
|
|
3
|
+
* Configuration options for upload strategy negotiation.
|
|
4
|
+
*
|
|
5
|
+
* @property fileSize - Size of the file to be uploaded in bytes
|
|
6
|
+
* @property preferredStrategy - Preferred upload strategy (single, parallel, resumable)
|
|
7
|
+
* @property preferredChunkSize - Preferred chunk size in bytes
|
|
8
|
+
* @property parallelUploads - Number of parallel upload connections
|
|
9
|
+
* @property minChunkSizeForParallel - Minimum file size to consider parallel uploads
|
|
10
|
+
*/
|
|
11
|
+
export type UploadStrategyOptions = {
|
|
12
|
+
fileSize: number;
|
|
13
|
+
preferredStrategy?: UploadStrategy;
|
|
14
|
+
preferredChunkSize?: number;
|
|
15
|
+
parallelUploads?: number;
|
|
16
|
+
minChunkSizeForParallel?: number;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Result of upload strategy negotiation.
|
|
20
|
+
*
|
|
21
|
+
* @property strategy - The negotiated upload strategy
|
|
22
|
+
* @property chunkSize - The negotiated chunk size in bytes
|
|
23
|
+
* @property parallelUploads - The negotiated number of parallel uploads
|
|
24
|
+
* @property reasoning - Array of reasoning strings explaining the decisions
|
|
25
|
+
* @property warnings - Array of warning messages about adjustments made
|
|
26
|
+
*/
|
|
27
|
+
export type NegotiatedStrategy = {
|
|
28
|
+
strategy: UploadStrategy;
|
|
29
|
+
chunkSize: number;
|
|
30
|
+
parallelUploads: number;
|
|
31
|
+
reasoning: string[];
|
|
32
|
+
warnings: string[];
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Negotiates the optimal upload strategy based on data store capabilities and file characteristics.
|
|
36
|
+
*
|
|
37
|
+
* This class analyzes data store capabilities, file size, and user preferences to determine
|
|
38
|
+
* the best upload strategy (single, parallel, resumable) and optimal parameters like chunk size
|
|
39
|
+
* and parallel connection count.
|
|
40
|
+
*
|
|
41
|
+
* The negotiator considers:
|
|
42
|
+
* - Data store capabilities (parallel uploads, resumable uploads, concatenation)
|
|
43
|
+
* - File size and chunk size constraints
|
|
44
|
+
* - User preferences and requirements
|
|
45
|
+
* - Performance optimization opportunities
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```typescript
|
|
49
|
+
* // Create negotiator for S3 data store
|
|
50
|
+
* const negotiator = new UploadStrategyNegotiator(
|
|
51
|
+
* s3Capabilities,
|
|
52
|
+
* (strategy) => s3Capabilities.supportsStrategy(strategy)
|
|
53
|
+
* );
|
|
54
|
+
*
|
|
55
|
+
* // Negotiate strategy for large file
|
|
56
|
+
* const result = negotiator.negotiateStrategy({
|
|
57
|
+
* fileSize: 100_000_000, // 100MB
|
|
58
|
+
* preferredStrategy: "parallel",
|
|
59
|
+
* preferredChunkSize: 5_000_000, // 5MB chunks
|
|
60
|
+
* parallelUploads: 4
|
|
61
|
+
* });
|
|
62
|
+
*
|
|
63
|
+
* console.log(result.strategy); // "parallel"
|
|
64
|
+
* console.log(result.chunkSize); // 5_000_000
|
|
65
|
+
* console.log(result.reasoning); // ["Using preferred strategy: parallel", ...]
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
export declare class UploadStrategyNegotiator {
|
|
69
|
+
private capabilities;
|
|
70
|
+
private validateUploadStrategy;
|
|
71
|
+
/**
|
|
72
|
+
* Creates a new upload strategy negotiator.
|
|
73
|
+
*
|
|
74
|
+
* @param capabilities - Data store capabilities and constraints
|
|
75
|
+
* @param validateUploadStrategy - Function to validate if a strategy is supported
|
|
76
|
+
*/
|
|
77
|
+
constructor(capabilities: DataStoreCapabilities, validateUploadStrategy: (strategy: UploadStrategy) => boolean);
|
|
78
|
+
/**
|
|
79
|
+
* Negotiates the optimal upload strategy based on options and data store capabilities.
|
|
80
|
+
*
|
|
81
|
+
* This method analyzes the provided options and data store capabilities to determine
|
|
82
|
+
* the best upload strategy, chunk size, and parallel upload settings. It considers
|
|
83
|
+
* user preferences, file size, and data store constraints to make optimal decisions.
|
|
84
|
+
*
|
|
85
|
+
* The negotiation process:
|
|
86
|
+
* 1. Validates preferred strategy against data store capabilities
|
|
87
|
+
* 2. Automatically selects strategy based on file size and capabilities
|
|
88
|
+
* 3. Adjusts chunk size to fit within data store constraints
|
|
89
|
+
* 4. Validates parallel upload settings
|
|
90
|
+
* 5. Ensures final strategy is supported by the data store
|
|
91
|
+
*
|
|
92
|
+
* @param options - Upload strategy options including file size and preferences
|
|
93
|
+
* @returns Negotiated strategy with reasoning and warnings
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```typescript
|
|
97
|
+
* const result = negotiator.negotiateStrategy({
|
|
98
|
+
* fileSize: 50_000_000, // 50MB
|
|
99
|
+
* preferredStrategy: "parallel",
|
|
100
|
+
* preferredChunkSize: 5_000_000, // 5MB
|
|
101
|
+
* parallelUploads: 3
|
|
102
|
+
* });
|
|
103
|
+
*
|
|
104
|
+
* console.log(result.strategy); // "parallel"
|
|
105
|
+
* console.log(result.chunkSize); // 5_000_000
|
|
106
|
+
* console.log(result.parallelUploads); // 3
|
|
107
|
+
* console.log(result.reasoning); // ["Using preferred strategy: parallel", ...]
|
|
108
|
+
* console.log(result.warnings); // [] (no warnings)
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
negotiateStrategy(options: UploadStrategyOptions): NegotiatedStrategy;
|
|
112
|
+
/**
|
|
113
|
+
* Gets the data store capabilities used by this negotiator.
|
|
114
|
+
*
|
|
115
|
+
* @returns The data store capabilities and constraints
|
|
116
|
+
*/
|
|
117
|
+
getDataStoreCapabilities(): DataStoreCapabilities;
|
|
118
|
+
/**
|
|
119
|
+
* Validates upload strategy configuration against data store capabilities.
|
|
120
|
+
*
|
|
121
|
+
* This method checks if the provided configuration is valid for the current
|
|
122
|
+
* data store capabilities without performing the actual negotiation. It's
|
|
123
|
+
* useful for pre-validation before attempting to negotiate a strategy.
|
|
124
|
+
*
|
|
125
|
+
* @param options - Upload strategy options to validate
|
|
126
|
+
* @returns Validation result with validity flag and error messages
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* ```typescript
|
|
130
|
+
* const validation = negotiator.validateConfiguration({
|
|
131
|
+
* fileSize: 10_000_000,
|
|
132
|
+
* preferredStrategy: "parallel",
|
|
133
|
+
* preferredChunkSize: 1_000_000,
|
|
134
|
+
* parallelUploads: 5
|
|
135
|
+
* });
|
|
136
|
+
*
|
|
137
|
+
* if (!validation.valid) {
|
|
138
|
+
* console.log("Configuration errors:", validation.errors);
|
|
139
|
+
* // Handle validation errors
|
|
140
|
+
* }
|
|
141
|
+
* ```
|
|
142
|
+
*/
|
|
143
|
+
validateConfiguration(options: UploadStrategyOptions): {
|
|
144
|
+
valid: boolean;
|
|
145
|
+
errors: string[];
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=upload-strategy-negotiator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upload-strategy-negotiator.d.ts","sourceRoot":"","sources":["../../src/upload/upload-strategy-negotiator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAEtE;;;;;;;;GAQG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,CAAC,EAAE,cAAc,CAAC;IACnC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,uBAAuB,CAAC,EAAE,MAAM,CAAC;CAClC,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,cAAc,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,qBAAa,wBAAwB;IAQjC,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,sBAAsB;IARhC;;;;;OAKG;gBAEO,YAAY,EAAE,qBAAqB,EACnC,sBAAsB,EAAE,CAAC,QAAQ,EAAE,cAAc,KAAK,OAAO;IAGvE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgCG;IACH,iBAAiB,CAAC,OAAO,EAAE,qBAAqB,GAAG,kBAAkB;IAqHrE;;;;OAIG;IACH,wBAAwB,IAAI,qBAAqB;IAIjD;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,qBAAqB,CAAC,OAAO,EAAE,qBAAqB,GAAG;QACrD,KAAK,EAAE,OAAO,CAAC;QACf,MAAM,EAAE,MAAM,EAAE,CAAC;KAClB;CA8CF"}
|