@uploadista/server 0.2.0 → 1.0.0-beta.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/dist/index.cjs +2 -2
- package/dist/index.d.cts +35 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +35 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +8 -8
- package/src/core/server.ts +31 -1
- package/src/core/types.ts +32 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uploadista/server",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.2
|
|
4
|
+
"version": "1.0.0-beta.2",
|
|
5
5
|
"description": "Core Server package for Uploadista",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "Uploadista",
|
|
@@ -20,23 +20,23 @@
|
|
|
20
20
|
}
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@uploadista/core": "0.2
|
|
24
|
-
"@uploadista/
|
|
25
|
-
"@uploadista/
|
|
26
|
-
"@uploadista/event-emitter-websocket": "0.2
|
|
23
|
+
"@uploadista/core": "1.0.0-beta.2",
|
|
24
|
+
"@uploadista/observability": "1.0.0-beta.2",
|
|
25
|
+
"@uploadista/event-broadcaster-memory": "1.0.0-beta.2",
|
|
26
|
+
"@uploadista/event-emitter-websocket": "1.0.0-beta.2"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"@cloudflare/workers-types": "4.
|
|
29
|
+
"@cloudflare/workers-types": "4.20260227.0",
|
|
30
30
|
"@effect/vitest": "0.27.0",
|
|
31
31
|
"@types/express": "^5.0.0",
|
|
32
32
|
"@types/node": "24.10.9",
|
|
33
|
-
"effect": "3.19.
|
|
33
|
+
"effect": "3.19.19",
|
|
34
34
|
"tsd": "0.33.0",
|
|
35
35
|
"tsdown": "0.20.3",
|
|
36
36
|
"typescript": "5.9.3",
|
|
37
37
|
"vitest": "4.0.18",
|
|
38
38
|
"zod": "4.3.6",
|
|
39
|
-
"@uploadista/typescript-config": "0.2
|
|
39
|
+
"@uploadista/typescript-config": "1.0.0-beta.2"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
42
|
"effect": "^3.0.0",
|
package/src/core/server.ts
CHANGED
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
type Flow,
|
|
5
5
|
FlowLifecycleHook,
|
|
6
6
|
FlowProvider,
|
|
7
|
+
FlowQueueService,
|
|
7
8
|
FlowWaitUntil,
|
|
8
9
|
kvCircuitBreakerStoreLayer,
|
|
9
10
|
} from "@uploadista/core/flow";
|
|
@@ -203,6 +204,7 @@ export const createUploadistaServer = async <
|
|
|
203
204
|
authCacheConfig,
|
|
204
205
|
circuitBreaker = true,
|
|
205
206
|
deadLetterQueue = false,
|
|
207
|
+
flowQueue,
|
|
206
208
|
healthCheck,
|
|
207
209
|
usageHooks,
|
|
208
210
|
}: UploadistaServerConfig<
|
|
@@ -289,6 +291,30 @@ export const createUploadistaServer = async <
|
|
|
289
291
|
)
|
|
290
292
|
: null;
|
|
291
293
|
|
|
294
|
+
// Create flow queue layer if enabled.
|
|
295
|
+
// FlowQueueService requires FlowEngine (to dispatch jobs) and optionally
|
|
296
|
+
// DeadLetterQueueService (for the DLQ retry loop — resolved via optional).
|
|
297
|
+
const flowQueueLayer = flowQueue
|
|
298
|
+
? (() => {
|
|
299
|
+
const queueConfig =
|
|
300
|
+
flowQueue === true ? {} : (flowQueue.config ?? {});
|
|
301
|
+
const queueStore =
|
|
302
|
+
flowQueue === true ? undefined : flowQueue.store;
|
|
303
|
+
// When a custom store is provided (e.g. RedisFlowQueueStore), use it directly.
|
|
304
|
+
// Otherwise back the queue with the application's kvStore — same backend already
|
|
305
|
+
// used by uploads, flows, and the DLQ, no extra Redis client needed.
|
|
306
|
+
const base = queueStore
|
|
307
|
+
? FlowQueueService.make(queueConfig, queueStore).pipe(
|
|
308
|
+
Layer.provide(flowEngineLayer),
|
|
309
|
+
)
|
|
310
|
+
: FlowQueueService.fromBaseKvStore(queueConfig).pipe(
|
|
311
|
+
Layer.provide(flowEngineLayer),
|
|
312
|
+
Layer.provide(kvStore),
|
|
313
|
+
);
|
|
314
|
+
return base;
|
|
315
|
+
})()
|
|
316
|
+
: null;
|
|
317
|
+
|
|
292
318
|
// Create usage hook layer (defaults to no-op if not configured)
|
|
293
319
|
const usageHookLayer = UsageHookServiceLive(usageHooks);
|
|
294
320
|
|
|
@@ -330,6 +356,7 @@ export const createUploadistaServer = async <
|
|
|
330
356
|
...plugins,
|
|
331
357
|
...(circuitBreakerStoreLayer ? [circuitBreakerStoreLayer] : []),
|
|
332
358
|
...(dlqLayer ? [dlqLayer] : []),
|
|
359
|
+
...(flowQueueLayer ? [flowQueueLayer] : []),
|
|
333
360
|
);
|
|
334
361
|
|
|
335
362
|
/**
|
|
@@ -564,9 +591,12 @@ export const createUploadistaServer = async <
|
|
|
564
591
|
const withCircuitBreakerContext = circuitBreakerStoreLayer
|
|
565
592
|
? Layer.merge(baseRequestContextLayer, circuitBreakerStoreLayer)
|
|
566
593
|
: baseRequestContextLayer;
|
|
567
|
-
const
|
|
594
|
+
const withDlqContext = dlqLayer
|
|
568
595
|
? Layer.merge(withCircuitBreakerContext, dlqLayer)
|
|
569
596
|
: withCircuitBreakerContext;
|
|
597
|
+
const requestContextLayer = flowQueueLayer
|
|
598
|
+
? Layer.merge(withDlqContext, flowQueueLayer)
|
|
599
|
+
: withDlqContext;
|
|
570
600
|
|
|
571
601
|
// Check for baseUrl/api/ prefix
|
|
572
602
|
if (uploadistaRequest.type === "not-found") {
|
package/src/core/types.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { PluginLayer, UploadistaError } from "@uploadista/core";
|
|
2
2
|
import type { Flow } from "@uploadista/core/flow";
|
|
3
|
+
import type { FlowQueueConfig, FlowQueueStore } from "@uploadista/core/flow";
|
|
3
4
|
import type {
|
|
4
5
|
BaseEventEmitterService,
|
|
5
6
|
BaseKvStoreService,
|
|
@@ -412,6 +413,37 @@ export interface UploadistaServerConfig<
|
|
|
412
413
|
*/
|
|
413
414
|
healthCheck?: HealthCheckConfig;
|
|
414
415
|
|
|
416
|
+
/**
|
|
417
|
+
* Optional: Flow queue for bounded concurrent flow execution.
|
|
418
|
+
*
|
|
419
|
+
* When enabled, `FlowEngine.runFlow()` delegates to the queue instead of
|
|
420
|
+
* forking immediately. The queue dispatches flows up to `maxConcurrency`
|
|
421
|
+
* simultaneously, buffering the rest as `"pending"`.
|
|
422
|
+
*
|
|
423
|
+
* Set to `true` to use the default in-memory store (state lost on restart).
|
|
424
|
+
* Provide a `store` to use a persistent backend such as `RedisFlowQueueStore`.
|
|
425
|
+
*
|
|
426
|
+
* When both `flowQueue` and `deadLetterQueue` are enabled, the queue
|
|
427
|
+
* automatically retries DLQ items on a configurable interval.
|
|
428
|
+
*
|
|
429
|
+
* @default undefined (disabled — fire-and-forget behavior preserved)
|
|
430
|
+
*
|
|
431
|
+
* @example
|
|
432
|
+
* ```typescript
|
|
433
|
+
* // Simple in-memory queue
|
|
434
|
+
* flowQueue: true
|
|
435
|
+
*
|
|
436
|
+
* // Persistent Redis-backed queue with custom concurrency
|
|
437
|
+
* import { RedisFlowQueueStore } from "@uploadista/queue-store-redis";
|
|
438
|
+
*
|
|
439
|
+
* flowQueue: {
|
|
440
|
+
* store: new RedisFlowQueueStore({ redis }),
|
|
441
|
+
* config: { maxConcurrency: 8, dlqRetryIntervalMs: 60_000 },
|
|
442
|
+
* }
|
|
443
|
+
* ```
|
|
444
|
+
*/
|
|
445
|
+
flowQueue?: boolean | { config?: FlowQueueConfig; store?: FlowQueueStore };
|
|
446
|
+
|
|
415
447
|
/**
|
|
416
448
|
* Optional: Usage hooks for tracking and billing integration.
|
|
417
449
|
*
|