@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,316 @@
|
|
|
1
|
+
import { Context, Effect, Layer, type Stream } from "effect";
|
|
2
|
+
import { UploadistaError } from "../errors/uploadista-error";
|
|
3
|
+
import type { UploadFileKVStore } from "./kv-store";
|
|
4
|
+
import type { UploadFile } from "./upload-file";
|
|
5
|
+
/**
|
|
6
|
+
* Options for writing data to a DataStore.
|
|
7
|
+
*
|
|
8
|
+
* @property file_id - Unique identifier for the file being written
|
|
9
|
+
* @property stream - Stream of byte chunks to write to storage
|
|
10
|
+
* @property offset - Byte offset where writing should begin (for resumable uploads)
|
|
11
|
+
*/
|
|
12
|
+
export type DataStoreWriteOptions = {
|
|
13
|
+
file_id: string;
|
|
14
|
+
stream: Stream.Stream<Uint8Array, UploadistaError>;
|
|
15
|
+
offset: number;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Upload strategy type indicating how chunks are uploaded.
|
|
19
|
+
*
|
|
20
|
+
* - `single`: Upload file in a single request (traditional upload)
|
|
21
|
+
* - `parallel`: Upload file chunks in parallel (for large files)
|
|
22
|
+
*/
|
|
23
|
+
export type UploadStrategy = "single" | "parallel";
|
|
24
|
+
/**
|
|
25
|
+
* Capabilities and constraints of a DataStore implementation.
|
|
26
|
+
*
|
|
27
|
+
* This type describes what features a storage backend supports and what
|
|
28
|
+
* limitations it has. Use this to determine the optimal upload strategy
|
|
29
|
+
* and validate client requests.
|
|
30
|
+
*
|
|
31
|
+
* @property supportsParallelUploads - Can upload chunks in parallel (e.g., S3 multipart)
|
|
32
|
+
* @property supportsConcatenation - Can concatenate multiple uploads into one file
|
|
33
|
+
* @property supportsDeferredLength - Can start upload without knowing final size
|
|
34
|
+
* @property supportsResumableUploads - Can resume interrupted uploads from last offset
|
|
35
|
+
* @property supportsTransactionalUploads - Guarantees atomic upload success/failure
|
|
36
|
+
* @property maxConcurrentUploads - Maximum parallel upload parts (if parallel supported)
|
|
37
|
+
* @property minChunkSize - Minimum size in bytes for each chunk (except last)
|
|
38
|
+
* @property maxChunkSize - Maximum size in bytes for each chunk
|
|
39
|
+
* @property maxParts - Maximum number of parts in a multipart upload
|
|
40
|
+
* @property optimalChunkSize - Recommended chunk size for best performance
|
|
41
|
+
* @property requiresOrderedChunks - Must receive chunks in sequential order
|
|
42
|
+
* @property requiresMimeTypeValidation - Validates file MIME type matches declaration
|
|
43
|
+
* @property maxValidationSize - Maximum file size for MIME type validation
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```typescript
|
|
47
|
+
* const capabilities = dataStore.getCapabilities();
|
|
48
|
+
*
|
|
49
|
+
* if (capabilities.supportsParallelUploads && fileSize > 10_000_000) {
|
|
50
|
+
* // Use parallel upload for large files
|
|
51
|
+
* const chunkSize = capabilities.optimalChunkSize || 5_242_880; // 5MB default
|
|
52
|
+
* uploadInParallel(file, chunkSize);
|
|
53
|
+
* } else {
|
|
54
|
+
* // Use single upload
|
|
55
|
+
* uploadAsSingleChunk(file);
|
|
56
|
+
* }
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
export type DataStoreCapabilities = {
|
|
60
|
+
supportsParallelUploads: boolean;
|
|
61
|
+
supportsConcatenation: boolean;
|
|
62
|
+
supportsDeferredLength: boolean;
|
|
63
|
+
supportsResumableUploads: boolean;
|
|
64
|
+
supportsTransactionalUploads: boolean;
|
|
65
|
+
maxConcurrentUploads?: number;
|
|
66
|
+
minChunkSize?: number;
|
|
67
|
+
maxChunkSize?: number;
|
|
68
|
+
maxParts?: number;
|
|
69
|
+
optimalChunkSize?: number;
|
|
70
|
+
requiresOrderedChunks: boolean;
|
|
71
|
+
requiresMimeTypeValidation?: boolean;
|
|
72
|
+
maxValidationSize?: number;
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* Core interface for all storage backend implementations.
|
|
76
|
+
*
|
|
77
|
+
* DataStore abstracts file storage operations across different backends
|
|
78
|
+
* (S3, Azure Blob, GCS, local filesystem, etc.). All storage adapters
|
|
79
|
+
* must implement this interface.
|
|
80
|
+
*
|
|
81
|
+
* @template TData - The data type stored (typically UploadFile)
|
|
82
|
+
*
|
|
83
|
+
* @property bucket - Optional storage bucket or container name
|
|
84
|
+
* @property path - Optional base path prefix for all stored files
|
|
85
|
+
* @property create - Creates a new file record in storage
|
|
86
|
+
* @property remove - Deletes a file from storage
|
|
87
|
+
* @property read - Reads complete file contents as bytes
|
|
88
|
+
* @property write - Writes data stream to storage at specified offset
|
|
89
|
+
* @property deleteExpired - Optional cleanup of expired files
|
|
90
|
+
* @property getCapabilities - Returns storage backend capabilities
|
|
91
|
+
* @property validateUploadStrategy - Validates if strategy is supported
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```typescript
|
|
95
|
+
* // Implement a custom DataStore
|
|
96
|
+
* const myDataStore: DataStore<UploadFile> = {
|
|
97
|
+
* bucket: "my-uploads",
|
|
98
|
+
* path: "files/",
|
|
99
|
+
*
|
|
100
|
+
* create: (file) => Effect.gen(function* () {
|
|
101
|
+
* // Store file metadata
|
|
102
|
+
* yield* saveMetadata(file);
|
|
103
|
+
* return file;
|
|
104
|
+
* }),
|
|
105
|
+
*
|
|
106
|
+
* write: ({ file_id, stream, offset }, { onProgress }) => Effect.gen(function* () {
|
|
107
|
+
* // Write chunks to storage
|
|
108
|
+
* let bytesWritten = offset;
|
|
109
|
+
* yield* Stream.runForEach(stream, (chunk) => Effect.sync(() => {
|
|
110
|
+
* writeChunk(file_id, chunk, bytesWritten);
|
|
111
|
+
* bytesWritten += chunk.byteLength;
|
|
112
|
+
* onProgress?.(chunk.byteLength);
|
|
113
|
+
* }));
|
|
114
|
+
* return bytesWritten;
|
|
115
|
+
* }),
|
|
116
|
+
*
|
|
117
|
+
* read: (file_id) => Effect.gen(function* () {
|
|
118
|
+
* // Read complete file
|
|
119
|
+
* const data = yield* readFromStorage(file_id);
|
|
120
|
+
* return data;
|
|
121
|
+
* }),
|
|
122
|
+
*
|
|
123
|
+
* remove: (file_id) => Effect.gen(function* () {
|
|
124
|
+
* yield* deleteFromStorage(file_id);
|
|
125
|
+
* }),
|
|
126
|
+
*
|
|
127
|
+
* getCapabilities: () => ({
|
|
128
|
+
* supportsParallelUploads: true,
|
|
129
|
+
* supportsConcatenation: false,
|
|
130
|
+
* supportsDeferredLength: true,
|
|
131
|
+
* supportsResumableUploads: true,
|
|
132
|
+
* supportsTransactionalUploads: false,
|
|
133
|
+
* maxConcurrentUploads: 10,
|
|
134
|
+
* optimalChunkSize: 5_242_880, // 5MB
|
|
135
|
+
* requiresOrderedChunks: false,
|
|
136
|
+
* }),
|
|
137
|
+
*
|
|
138
|
+
* validateUploadStrategy: (strategy) =>
|
|
139
|
+
* Effect.succeed(strategy === "parallel" || strategy === "single"),
|
|
140
|
+
* };
|
|
141
|
+
* ```
|
|
142
|
+
*/
|
|
143
|
+
export type DataStore<TData = unknown> = {
|
|
144
|
+
readonly bucket?: string;
|
|
145
|
+
readonly path?: string;
|
|
146
|
+
readonly create: (file: TData) => Effect.Effect<TData, UploadistaError>;
|
|
147
|
+
readonly remove: (file_id: string) => Effect.Effect<void, UploadistaError>;
|
|
148
|
+
readonly read: (file_id: string) => Effect.Effect<Uint8Array, UploadistaError>;
|
|
149
|
+
readonly write: (options: DataStoreWriteOptions, dependencies: {
|
|
150
|
+
onProgress?: (chunkSize: number) => void;
|
|
151
|
+
}) => Effect.Effect<number, UploadistaError>;
|
|
152
|
+
readonly deleteExpired?: Effect.Effect<number, UploadistaError>;
|
|
153
|
+
readonly getCapabilities: () => DataStoreCapabilities;
|
|
154
|
+
readonly validateUploadStrategy: (strategy: UploadStrategy) => Effect.Effect<boolean, never>;
|
|
155
|
+
};
|
|
156
|
+
declare const UploadFileDataStore_base: Context.TagClass<UploadFileDataStore, "UploadFileDataStore", DataStore<UploadFile>>;
|
|
157
|
+
/**
|
|
158
|
+
* Effect-TS context tag for UploadFile DataStore.
|
|
159
|
+
*
|
|
160
|
+
* Use this tag to access the primary DataStore in an Effect context.
|
|
161
|
+
* This is the standard storage backend for uploaded files.
|
|
162
|
+
*
|
|
163
|
+
* @example
|
|
164
|
+
* ```typescript
|
|
165
|
+
* const uploadEffect = Effect.gen(function* () {
|
|
166
|
+
* const dataStore = yield* UploadFileDataStore;
|
|
167
|
+
* const file = yield* dataStore.create(uploadFile);
|
|
168
|
+
* return file;
|
|
169
|
+
* });
|
|
170
|
+
* ```
|
|
171
|
+
*/
|
|
172
|
+
export declare class UploadFileDataStore extends UploadFileDataStore_base {
|
|
173
|
+
}
|
|
174
|
+
declare const BufferedUploadFileDataStore_base: Context.TagClass<BufferedUploadFileDataStore, "BufferedUploadFileDataStore", DataStore<UploadFile>>;
|
|
175
|
+
/**
|
|
176
|
+
* Effect-TS context tag for buffered/temporary DataStore.
|
|
177
|
+
*
|
|
178
|
+
* This is an optional storage backend used for temporary or intermediate files
|
|
179
|
+
* during flow processing. Not all implementations provide a buffered store.
|
|
180
|
+
*
|
|
181
|
+
* @example
|
|
182
|
+
* ```typescript
|
|
183
|
+
* const processEffect = Effect.gen(function* () {
|
|
184
|
+
* const bufferedStore = yield* BufferedUploadFileDataStore;
|
|
185
|
+
* // Store intermediate processing results
|
|
186
|
+
* const tempFile = yield* bufferedStore.create(intermediateFile);
|
|
187
|
+
* return tempFile;
|
|
188
|
+
* });
|
|
189
|
+
* ```
|
|
190
|
+
*/
|
|
191
|
+
export declare class BufferedUploadFileDataStore extends BufferedUploadFileDataStore_base {
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Service interface for managing multiple DataStore instances.
|
|
195
|
+
*
|
|
196
|
+
* This allows routing files to different storage backends based on
|
|
197
|
+
* storageId (e.g., different S3 buckets, Azure containers, or storage tiers).
|
|
198
|
+
*
|
|
199
|
+
* @property getDataStore - Retrieves the appropriate DataStore for a given storage ID
|
|
200
|
+
* @property bufferedDataStore - Optional temporary storage for intermediate files
|
|
201
|
+
*/
|
|
202
|
+
export type UploadFileDataStoresShape = {
|
|
203
|
+
getDataStore: (storageId: string, clientId: string | null) => Effect.Effect<DataStore<UploadFile>, UploadistaError>;
|
|
204
|
+
bufferedDataStore: Effect.Effect<DataStore<UploadFile> | undefined, UploadistaError>;
|
|
205
|
+
};
|
|
206
|
+
declare const UploadFileDataStores_base: Context.TagClass<UploadFileDataStores, "UploadFileDataStores", UploadFileDataStoresShape>;
|
|
207
|
+
/**
|
|
208
|
+
* Effect-TS context tag for the DataStore routing service.
|
|
209
|
+
*
|
|
210
|
+
* Provides access to multiple DataStore instances with routing logic.
|
|
211
|
+
*
|
|
212
|
+
* @example
|
|
213
|
+
* ```typescript
|
|
214
|
+
* const uploadEffect = Effect.gen(function* () {
|
|
215
|
+
* const dataStores = yield* UploadFileDataStores;
|
|
216
|
+
* // Route to specific storage based on storageId
|
|
217
|
+
* const dataStore = yield* dataStores.getDataStore("s3-production", clientId);
|
|
218
|
+
* const file = yield* dataStore.create(uploadFile);
|
|
219
|
+
* return file;
|
|
220
|
+
* });
|
|
221
|
+
* ```
|
|
222
|
+
*/
|
|
223
|
+
export declare class UploadFileDataStores extends UploadFileDataStores_base {
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Simplified DataStore configuration for easy setup.
|
|
227
|
+
*
|
|
228
|
+
* This type allows flexible configuration:
|
|
229
|
+
* - Single DataStore instance
|
|
230
|
+
* - Multiple named stores with routing
|
|
231
|
+
* - Effect that resolves to a DataStore
|
|
232
|
+
* - Pre-built Effect Layer
|
|
233
|
+
*
|
|
234
|
+
* @example
|
|
235
|
+
* ```typescript
|
|
236
|
+
* // Single store
|
|
237
|
+
* const config: DataStoreConfig = s3DataStore;
|
|
238
|
+
*
|
|
239
|
+
* // Multiple stores with routing
|
|
240
|
+
* const config: DataStoreConfig = {
|
|
241
|
+
* stores: {
|
|
242
|
+
* "s3-prod": s3ProdStore,
|
|
243
|
+
* "s3-dev": s3DevStore,
|
|
244
|
+
* "local": localFileStore,
|
|
245
|
+
* },
|
|
246
|
+
* default: "s3-prod"
|
|
247
|
+
* };
|
|
248
|
+
*
|
|
249
|
+
* // Effect that creates a store
|
|
250
|
+
* const config: DataStoreConfig = Effect.gen(function* () {
|
|
251
|
+
* const kvStore = yield* UploadFileKVStore;
|
|
252
|
+
* return createS3Store(kvStore);
|
|
253
|
+
* });
|
|
254
|
+
*
|
|
255
|
+
* // Pre-built Layer
|
|
256
|
+
* const config: DataStoreConfig = Layer.succeed(UploadFileDataStores, {...});
|
|
257
|
+
* ```
|
|
258
|
+
*/
|
|
259
|
+
export type DataStoreConfig = DataStore<UploadFile> | Effect.Effect<DataStore<UploadFile>, never, UploadFileKVStore> | {
|
|
260
|
+
stores: Record<string, DataStore<UploadFile> | Effect.Effect<DataStore<UploadFile>, never, UploadFileKVStore>>;
|
|
261
|
+
default?: string;
|
|
262
|
+
} | Layer.Layer<UploadFileDataStores, never, UploadFileKVStore>;
|
|
263
|
+
/**
|
|
264
|
+
* Type guard to check if a value is a DataStore instance.
|
|
265
|
+
*
|
|
266
|
+
* @param config - The value to check
|
|
267
|
+
* @returns True if the value is a DataStore
|
|
268
|
+
*
|
|
269
|
+
* @example
|
|
270
|
+
* ```typescript
|
|
271
|
+
* if (isDataStore(config)) {
|
|
272
|
+
* const capabilities = config.getCapabilities();
|
|
273
|
+
* }
|
|
274
|
+
* ```
|
|
275
|
+
*/
|
|
276
|
+
export declare const isDataStore: (config: DataStoreConfig) => config is DataStore<UploadFile>;
|
|
277
|
+
/**
|
|
278
|
+
* Creates an Effect Layer from simplified DataStoreConfig.
|
|
279
|
+
*
|
|
280
|
+
* This function converts any DataStoreConfig format into a proper Effect Layer
|
|
281
|
+
* that can be provided to the UploadFileDataStores context tag.
|
|
282
|
+
*
|
|
283
|
+
* It handles:
|
|
284
|
+
* - Single DataStore: Wraps in a Layer that always returns that store
|
|
285
|
+
* - Multiple stores: Creates routing logic with optional default
|
|
286
|
+
* - Effect<DataStore>: Executes the Effect and wraps the result
|
|
287
|
+
* - Layer: Returns as-is
|
|
288
|
+
*
|
|
289
|
+
* @param config - The DataStore configuration
|
|
290
|
+
* @returns A Layer that provides UploadFileDataStores service
|
|
291
|
+
*
|
|
292
|
+
* @example
|
|
293
|
+
* ```typescript
|
|
294
|
+
* // Create from single store
|
|
295
|
+
* const layer = await createDataStoreLayer(s3DataStore);
|
|
296
|
+
*
|
|
297
|
+
* // Create from multiple stores
|
|
298
|
+
* const layer = await createDataStoreLayer({
|
|
299
|
+
* stores: {
|
|
300
|
+
* "production": s3Store,
|
|
301
|
+
* "development": localStore,
|
|
302
|
+
* },
|
|
303
|
+
* default: "development"
|
|
304
|
+
* });
|
|
305
|
+
*
|
|
306
|
+
* // Use the layer
|
|
307
|
+
* const program = Effect.gen(function* () {
|
|
308
|
+
* const stores = yield* UploadFileDataStores;
|
|
309
|
+
* const store = yield* stores.getDataStore("production", null);
|
|
310
|
+
* return store;
|
|
311
|
+
* }).pipe(Effect.provide(layer));
|
|
312
|
+
* ```
|
|
313
|
+
*/
|
|
314
|
+
export declare const createDataStoreLayer: (config: DataStoreConfig) => Promise<Layer.Layer<UploadFileDataStores, never, UploadFileKVStore>>;
|
|
315
|
+
export {};
|
|
316
|
+
//# sourceMappingURL=data-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-store.d.ts","sourceRoot":"","sources":["../../src/types/data-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { Context, Effect, Layer } from "effect";
|
|
2
|
+
import { UploadistaError } from "../errors/uploadista-error";
|
|
3
|
+
/**
|
|
4
|
+
* Effect-TS context tag for UploadFile DataStore.
|
|
5
|
+
*
|
|
6
|
+
* Use this tag to access the primary DataStore in an Effect context.
|
|
7
|
+
* This is the standard storage backend for uploaded files.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* const uploadEffect = Effect.gen(function* () {
|
|
12
|
+
* const dataStore = yield* UploadFileDataStore;
|
|
13
|
+
* const file = yield* dataStore.create(uploadFile);
|
|
14
|
+
* return file;
|
|
15
|
+
* });
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export class UploadFileDataStore extends Context.Tag("UploadFileDataStore")() {
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Effect-TS context tag for buffered/temporary DataStore.
|
|
22
|
+
*
|
|
23
|
+
* This is an optional storage backend used for temporary or intermediate files
|
|
24
|
+
* during flow processing. Not all implementations provide a buffered store.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* const processEffect = Effect.gen(function* () {
|
|
29
|
+
* const bufferedStore = yield* BufferedUploadFileDataStore;
|
|
30
|
+
* // Store intermediate processing results
|
|
31
|
+
* const tempFile = yield* bufferedStore.create(intermediateFile);
|
|
32
|
+
* return tempFile;
|
|
33
|
+
* });
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export class BufferedUploadFileDataStore extends Context.Tag("BufferedUploadFileDataStore")() {
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Effect-TS context tag for the DataStore routing service.
|
|
40
|
+
*
|
|
41
|
+
* Provides access to multiple DataStore instances with routing logic.
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```typescript
|
|
45
|
+
* const uploadEffect = Effect.gen(function* () {
|
|
46
|
+
* const dataStores = yield* UploadFileDataStores;
|
|
47
|
+
* // Route to specific storage based on storageId
|
|
48
|
+
* const dataStore = yield* dataStores.getDataStore("s3-production", clientId);
|
|
49
|
+
* const file = yield* dataStore.create(uploadFile);
|
|
50
|
+
* return file;
|
|
51
|
+
* });
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export class UploadFileDataStores extends Context.Tag("UploadFileDataStores")() {
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Type guard to check if a value is a DataStore instance.
|
|
58
|
+
*
|
|
59
|
+
* @param config - The value to check
|
|
60
|
+
* @returns True if the value is a DataStore
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```typescript
|
|
64
|
+
* if (isDataStore(config)) {
|
|
65
|
+
* const capabilities = config.getCapabilities();
|
|
66
|
+
* }
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
export const isDataStore = (config) => {
|
|
70
|
+
return "create" in config && "write" in config;
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* Creates an Effect Layer from simplified DataStoreConfig.
|
|
74
|
+
*
|
|
75
|
+
* This function converts any DataStoreConfig format into a proper Effect Layer
|
|
76
|
+
* that can be provided to the UploadFileDataStores context tag.
|
|
77
|
+
*
|
|
78
|
+
* It handles:
|
|
79
|
+
* - Single DataStore: Wraps in a Layer that always returns that store
|
|
80
|
+
* - Multiple stores: Creates routing logic with optional default
|
|
81
|
+
* - Effect<DataStore>: Executes the Effect and wraps the result
|
|
82
|
+
* - Layer: Returns as-is
|
|
83
|
+
*
|
|
84
|
+
* @param config - The DataStore configuration
|
|
85
|
+
* @returns A Layer that provides UploadFileDataStores service
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```typescript
|
|
89
|
+
* // Create from single store
|
|
90
|
+
* const layer = await createDataStoreLayer(s3DataStore);
|
|
91
|
+
*
|
|
92
|
+
* // Create from multiple stores
|
|
93
|
+
* const layer = await createDataStoreLayer({
|
|
94
|
+
* stores: {
|
|
95
|
+
* "production": s3Store,
|
|
96
|
+
* "development": localStore,
|
|
97
|
+
* },
|
|
98
|
+
* default: "development"
|
|
99
|
+
* });
|
|
100
|
+
*
|
|
101
|
+
* // Use the layer
|
|
102
|
+
* const program = Effect.gen(function* () {
|
|
103
|
+
* const stores = yield* UploadFileDataStores;
|
|
104
|
+
* const store = yield* stores.getDataStore("production", null);
|
|
105
|
+
* return store;
|
|
106
|
+
* }).pipe(Effect.provide(layer));
|
|
107
|
+
* ```
|
|
108
|
+
*/
|
|
109
|
+
export const createDataStoreLayer = async (config) => {
|
|
110
|
+
// Already a Layer, return as-is
|
|
111
|
+
if (Layer.isLayer(config)) {
|
|
112
|
+
return config;
|
|
113
|
+
}
|
|
114
|
+
// Check if it's an Effect
|
|
115
|
+
if (Effect.isEffect(config)) {
|
|
116
|
+
return Layer.effect(UploadFileDataStores, Effect.gen(function* () {
|
|
117
|
+
const dataStore = config;
|
|
118
|
+
const resolvedStore = yield* dataStore;
|
|
119
|
+
return {
|
|
120
|
+
getDataStore: (_storageId) => Effect.succeed(resolvedStore),
|
|
121
|
+
bufferedDataStore: Effect.succeed(undefined),
|
|
122
|
+
};
|
|
123
|
+
}));
|
|
124
|
+
}
|
|
125
|
+
// Single store (most common case)
|
|
126
|
+
if (isDataStore(config)) {
|
|
127
|
+
const store = config;
|
|
128
|
+
return Layer.succeed(UploadFileDataStores, {
|
|
129
|
+
getDataStore: (_storageId) => Effect.succeed(store),
|
|
130
|
+
bufferedDataStore: Effect.succeed(undefined),
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
// Multiple stores with routing
|
|
134
|
+
const multiConfig = config;
|
|
135
|
+
const defaultKey = multiConfig.default || Object.keys(multiConfig.stores)[0];
|
|
136
|
+
// Resolve any Effects in the stores
|
|
137
|
+
const resolvedStores = {};
|
|
138
|
+
for (const [key, storeOrEffect] of Object.entries(multiConfig.stores)) {
|
|
139
|
+
if ("pipe" in storeOrEffect && !("create" in storeOrEffect)) {
|
|
140
|
+
resolvedStores[key] = await Effect.runPromise(storeOrEffect);
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
resolvedStores[key] = storeOrEffect;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return Layer.succeed(UploadFileDataStores, {
|
|
147
|
+
getDataStore: (storageId) => {
|
|
148
|
+
const store = resolvedStores[storageId] ||
|
|
149
|
+
(defaultKey ? resolvedStores[defaultKey] : undefined);
|
|
150
|
+
if (store) {
|
|
151
|
+
return Effect.succeed(store);
|
|
152
|
+
}
|
|
153
|
+
return Effect.fail(UploadistaError.fromCode("FILE_NOT_FOUND"));
|
|
154
|
+
},
|
|
155
|
+
bufferedDataStore: Effect.succeed(undefined),
|
|
156
|
+
});
|
|
157
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Context, type Effect } from "effect";
|
|
2
|
+
import type { UploadistaError } from "../errors";
|
|
3
|
+
/**
|
|
4
|
+
* Event broadcaster interface for pub/sub messaging across distributed instances.
|
|
5
|
+
* Used by WebSocketManager to broadcast upload events to all connected instances.
|
|
6
|
+
*/
|
|
7
|
+
export interface EventBroadcaster {
|
|
8
|
+
/**
|
|
9
|
+
* Publish a message to a channel
|
|
10
|
+
*/
|
|
11
|
+
readonly publish: (channel: string, message: string) => Effect.Effect<void, UploadistaError>;
|
|
12
|
+
/**
|
|
13
|
+
* Subscribe to messages on a channel
|
|
14
|
+
*/
|
|
15
|
+
readonly subscribe: (channel: string, handler: (message: string) => void) => Effect.Effect<void, UploadistaError>;
|
|
16
|
+
/**
|
|
17
|
+
* Unsubscribe from a channel (optional - not all implementations may support)
|
|
18
|
+
*/
|
|
19
|
+
readonly unsubscribe?: (channel: string) => Effect.Effect<void, UploadistaError>;
|
|
20
|
+
}
|
|
21
|
+
declare const EventBroadcasterService_base: Context.TagClass<EventBroadcasterService, "EventBroadcaster", EventBroadcaster>;
|
|
22
|
+
/**
|
|
23
|
+
* Context tag for EventBroadcaster service
|
|
24
|
+
*/
|
|
25
|
+
export declare class EventBroadcasterService extends EventBroadcasterService_base {
|
|
26
|
+
}
|
|
27
|
+
export {};
|
|
28
|
+
//# sourceMappingURL=event-broadcaster.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-broadcaster.d.ts","sourceRoot":"","sources":["../../src/types/event-broadcaster.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEjD;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,CAChB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,KACZ,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;IAE1C;;OAEG;IACH,QAAQ,CAAC,SAAS,EAAE,CAClB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,KAC/B,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;IAE1C;;OAEG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,CACrB,OAAO,EAAE,MAAM,KACZ,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;CAC3C;;AAED;;GAEG;AACH,qBAAa,uBAAwB,SAAQ,4BAG1C;CAAG"}
|