@uploadista/server 0.2.0 → 1.0.0-beta.3

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@uploadista/server",
3
3
  "type": "module",
4
- "version": "0.2.0",
4
+ "version": "1.0.0-beta.3",
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.0",
24
- "@uploadista/event-broadcaster-memory": "0.2.0",
25
- "@uploadista/observability": "0.2.0",
26
- "@uploadista/event-emitter-websocket": "0.2.0"
23
+ "@uploadista/core": "1.0.0-beta.3",
24
+ "@uploadista/observability": "1.0.0-beta.3",
25
+ "@uploadista/event-broadcaster-memory": "1.0.0-beta.3",
26
+ "@uploadista/event-emitter-websocket": "1.0.0-beta.3"
27
27
  },
28
28
  "devDependencies": {
29
- "@cloudflare/workers-types": "4.20260213.0",
29
+ "@cloudflare/workers-types": "4.20260301.1",
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.17",
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.0"
39
+ "@uploadista/typescript-config": "1.0.0-beta.3"
40
40
  },
41
41
  "peerDependencies": {
42
42
  "effect": "^3.0.0",
@@ -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 requestContextLayer = dlqLayer
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
  *