@uploadista/server 0.0.8 → 0.0.10

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.
Files changed (37) hide show
  1. package/CHANGELOG.md +69 -0
  2. package/dist/auth/index.d.mts +2 -0
  3. package/dist/auth/index.mjs +1 -0
  4. package/dist/{auth-C77S4vQd.js → auth-BqArZeGK.mjs} +1 -1
  5. package/dist/auth-BqArZeGK.mjs.map +1 -0
  6. package/dist/{index-CvDNB1lJ.d.ts → index--Lny6VJP.d.mts} +1 -1
  7. package/dist/index--Lny6VJP.d.mts.map +1 -0
  8. package/dist/index.cjs +1 -1
  9. package/dist/index.d.cts +734 -10
  10. package/dist/index.d.cts.map +1 -1
  11. package/dist/index.d.mts +1344 -0
  12. package/dist/index.d.mts.map +1 -0
  13. package/dist/index.mjs +2 -0
  14. package/dist/index.mjs.map +1 -0
  15. package/package.json +18 -13
  16. package/src/adapter/index.ts +10 -0
  17. package/src/adapter/types.ts +229 -0
  18. package/src/core/http-handlers/flow-http-handlers.ts +245 -0
  19. package/src/core/http-handlers/http-handlers.ts +72 -0
  20. package/src/core/http-handlers/upload-http-handlers.ts +168 -0
  21. package/src/core/index.ts +12 -0
  22. package/src/core/routes.ts +188 -0
  23. package/src/core/server.ts +327 -0
  24. package/src/core/types.ts +322 -0
  25. package/src/core/websocket-handlers/flow-websocket-handlers.ts +47 -0
  26. package/src/core/websocket-handlers/upload-websocket-handlers.ts +47 -0
  27. package/src/core/websocket-handlers/websocket-handlers.ts +151 -0
  28. package/src/core/websocket-routes.ts +136 -0
  29. package/src/index.ts +2 -0
  30. package/dist/auth/index.d.ts +0 -2
  31. package/dist/auth/index.js +0 -1
  32. package/dist/auth-C77S4vQd.js.map +0 -1
  33. package/dist/index-CvDNB1lJ.d.ts.map +0 -1
  34. package/dist/index.d.ts +0 -620
  35. package/dist/index.d.ts.map +0 -1
  36. package/dist/index.js +0 -2
  37. package/dist/index.js.map +0 -1
package/dist/index.d.cts CHANGED
@@ -1,14 +1,97 @@
1
1
  import { n as getAuthCredentials, t as AuthCredentialsResponse } from "./index-50KlDIjc.cjs";
2
- import { Context, Effect, Layer } from "effect";
3
- import { UploadistaError } from "@uploadista/core/errors";
4
2
  import * as _uploadista_core0 from "@uploadista/core";
5
- import { Flow, UploadServer } from "@uploadista/core";
6
- import { FlowProvider } from "@uploadista/core/flow";
7
- import { BaseEventEmitterService, BaseKvStoreService, UploadFileDataStore, UploadFileDataStores, UploadFileKVStore } from "@uploadista/core/types";
8
- import { UploadServer as UploadServer$1 } from "@uploadista/core/upload";
3
+ import { DataStoreCapabilities, Flow, FlowData, FlowJob, FlowServer, UploadEvent, UploadFile, UploadServer, UploadistaError } from "@uploadista/core";
4
+ import { Context, Effect, Layer } from "effect";
5
+ import { Flow as Flow$1, FlowProvider, FlowServerShape } from "@uploadista/core/flow";
6
+ import { BaseEventEmitterService, BaseKvStoreService, DataStoreConfig, EventBroadcasterService, UploadFileDataStore, UploadFileDataStores, UploadFileKVStore } from "@uploadista/core/types";
9
7
  import { GenerateId } from "@uploadista/core/utils";
10
- import z from "zod";
8
+ import z$1, { z } from "zod";
9
+ import { UploadServer as UploadServer$1, UploadServerShape } from "@uploadista/core/upload";
10
+ import { UploadistaError as UploadistaError$1 } from "@uploadista/core/errors";
11
11
 
12
+ //#region src/core/routes.d.ts
13
+ type UploadistaRouteType = "create-upload" | "get-capabilities" | "get-upload" | "upload-chunk" | "get-flow" | "run-flow" | "job-status" | "resume-flow" | "pause-flow" | "cancel-flow" | "not-found" | "bad-request" | "method-not-allowed" | "unsupported-content-type";
14
+ type UploadistaRoute<T extends UploadistaRouteType> = {
15
+ type: T;
16
+ };
17
+ type UploadistaStandardResponse<T extends UploadistaRouteType, ResponseBody, Status extends number = 200> = UploadistaRoute<T> & {
18
+ status: Status;
19
+ headers: {
20
+ "Content-Type": "application/json";
21
+ };
22
+ body: ResponseBody;
23
+ };
24
+ type NotFoundRequest = UploadistaRoute<"not-found">;
25
+ type NotFoundResponse = UploadistaStandardResponse<"not-found", {
26
+ error: "Not found";
27
+ }, 404>;
28
+ type MethodNotAllowedRequest = UploadistaRoute<"method-not-allowed">;
29
+ type MethodNotAllowedResponse = UploadistaStandardResponse<"method-not-allowed", {
30
+ error: "Method not allowed";
31
+ }, 405>;
32
+ type BadRequestRequest = UploadistaRoute<"bad-request"> & {
33
+ message: string;
34
+ };
35
+ type BadRequestResponse = UploadistaStandardResponse<"bad-request", {
36
+ error: "Bad request";
37
+ message: string;
38
+ }, 400>;
39
+ type UnsupportedContentTypeRequest = UploadistaRoute<"unsupported-content-type">;
40
+ type UnsupportedContentTypeResponse = UploadistaStandardResponse<"unsupported-content-type", {
41
+ error: "Unsupported content type";
42
+ }, 415>;
43
+ type CreateUploadRequest = UploadistaRoute<"create-upload"> & {
44
+ data: unknown;
45
+ };
46
+ type CreateUploadResponse = UploadistaStandardResponse<"create-upload", UploadFile>;
47
+ type GetCapabilitiesRequest = UploadistaRoute<"get-capabilities"> & {
48
+ storageId: string;
49
+ };
50
+ type GetCapabilitiesResponse = UploadistaStandardResponse<"get-capabilities", {
51
+ storageId: string;
52
+ capabilities: DataStoreCapabilities;
53
+ timestamp: string;
54
+ }>;
55
+ type GetUploadRequest = UploadistaRoute<"get-upload"> & {
56
+ uploadId: string;
57
+ };
58
+ type GetUploadResponse = UploadistaStandardResponse<"get-upload", UploadFile>;
59
+ type UploadChunkRequest = UploadistaRoute<"upload-chunk"> & {
60
+ uploadId: string;
61
+ data: ReadableStream;
62
+ };
63
+ type UploadChunkResponse = UploadistaStandardResponse<"upload-chunk", UploadFile>;
64
+ type GetFlowRequest = UploadistaRoute<"get-flow"> & {
65
+ flowId: string;
66
+ };
67
+ type GetFlowResponse = UploadistaStandardResponse<"get-flow", FlowData>;
68
+ type RunFlowRequest = UploadistaRoute<"run-flow"> & {
69
+ flowId: string;
70
+ storageId: string;
71
+ inputs: Record<string, unknown>;
72
+ };
73
+ type RunFlowResponse = UploadistaStandardResponse<"run-flow", FlowJob>;
74
+ type GetJobStatusRequest = UploadistaRoute<"job-status"> & {
75
+ jobId: string;
76
+ };
77
+ type GetJobStatusResponse = UploadistaStandardResponse<"job-status", FlowJob>;
78
+ type ResumeFlowRequest = UploadistaRoute<"resume-flow"> & {
79
+ jobId: string;
80
+ nodeId: string;
81
+ newData: unknown;
82
+ };
83
+ type ResumeFlowResponse = UploadistaStandardResponse<"resume-flow", FlowJob>;
84
+ type PauseFlowRequest = UploadistaRoute<"pause-flow"> & {
85
+ jobId: string;
86
+ };
87
+ type PauseFlowResponse = UploadistaStandardResponse<"pause-flow", FlowJob>;
88
+ type CancelFlowRequest = UploadistaRoute<"cancel-flow"> & {
89
+ jobId: string;
90
+ };
91
+ type CancelFlowResponse = UploadistaStandardResponse<"cancel-flow", FlowJob>;
92
+ type UploadistaRequest = CreateUploadRequest | GetCapabilitiesRequest | GetUploadRequest | UploadChunkRequest | GetFlowRequest | RunFlowRequest | GetJobStatusRequest | ResumeFlowRequest | PauseFlowRequest | CancelFlowRequest | NotFoundRequest | BadRequestRequest | MethodNotAllowedRequest | UnsupportedContentTypeRequest;
93
+ type UploadistaResponse = CreateUploadResponse | GetCapabilitiesResponse | GetUploadResponse | UploadChunkResponse | GetFlowResponse | RunFlowResponse | GetJobStatusResponse | ResumeFlowResponse | PauseFlowResponse | CancelFlowResponse | NotFoundResponse | BadRequestResponse | MethodNotAllowedResponse | UnsupportedContentTypeResponse | StandardResponse;
94
+ //#endregion
12
95
  //#region src/types.d.ts
13
96
  /**
14
97
  * Authentication context containing user identity and authorization metadata.
@@ -48,6 +131,210 @@ type AuthContext = {
48
131
  */
49
132
  type AuthResult = AuthContext | null;
50
133
  //#endregion
134
+ //#region src/adapter/types.d.ts
135
+ /**
136
+ * Standard request representation extracted from framework-specific request objects.
137
+ *
138
+ * This interface provides a framework-agnostic way to represent HTTP requests,
139
+ * allowing the core server logic to work uniformly across Hono, Express, Fastify,
140
+ * and other frameworks.
141
+ *
142
+ * @example
143
+ * ```typescript
144
+ * const standardRequest: StandardRequest = {
145
+ * method: "POST",
146
+ * url: new URL("https://example.com/uploadista/api/upload"),
147
+ * headers: { "content-type": "application/json" },
148
+ * body: { file: "data" }
149
+ * };
150
+ * ```
151
+ */
152
+ interface StandardRequest {
153
+ /**
154
+ * HTTP method (GET, POST, PATCH, etc.)
155
+ */
156
+ method: string;
157
+ /**
158
+ * Full URL of the request including protocol, host, path, and query parameters
159
+ */
160
+ url: URL;
161
+ /**
162
+ * Request headers as key-value pairs
163
+ */
164
+ headers: Record<string, string>;
165
+ /**
166
+ * Optional request body (parsed or raw)
167
+ */
168
+ body?: unknown;
169
+ }
170
+ /**
171
+ * Standard response representation to be sent by framework-specific adapters.
172
+ *
173
+ * The core server produces StandardResponse objects, which adapters then
174
+ * translate into framework-specific response formats.
175
+ *
176
+ * @example
177
+ * ```typescript
178
+ * const standardResponse: StandardResponse = {
179
+ * status: 200,
180
+ * headers: { "content-type": "application/json" },
181
+ * body: { uploadId: "abc123" }
182
+ * };
183
+ * ```
184
+ */
185
+ interface StandardResponse {
186
+ /**
187
+ * HTTP status code (200, 404, 500, etc.)
188
+ */
189
+ status: number;
190
+ /**
191
+ * Optional response headers as key-value pairs
192
+ */
193
+ headers?: Record<string, string>;
194
+ /**
195
+ * Optional response body (will be JSON-stringified if object)
196
+ */
197
+ body?: unknown;
198
+ }
199
+ /**
200
+ * WebSocket handler interface for framework-agnostic WebSocket management.
201
+ *
202
+ * This interface allows the core server to interact with WebSocket connections
203
+ * without needing to know about framework-specific WebSocket APIs.
204
+ *
205
+ * @example
206
+ * ```typescript
207
+ * const wsHandler: WebSocketHandler = {
208
+ * onMessage: (message) => console.log("Received:", message),
209
+ * onClose: () => console.log("Connection closed"),
210
+ * onError: (error) => console.error("WebSocket error:", error)
211
+ * };
212
+ * ```
213
+ */
214
+ interface WebSocketHandler {
215
+ /**
216
+ * Callback invoked when a message is received from the client
217
+ *
218
+ * @param message - The message string received
219
+ */
220
+ onMessage: (message: string) => void;
221
+ /**
222
+ * Callback invoked when the WebSocket connection is closed
223
+ */
224
+ onClose: () => void;
225
+ /**
226
+ * Callback invoked when a WebSocket error occurs
227
+ *
228
+ * @param error - The error that occurred
229
+ */
230
+ onError: (error: Error) => void;
231
+ }
232
+ /**
233
+ * ServerAdapter interface that framework adapters must implement.
234
+ *
235
+ * This interface defines the contract between the core server (framework-agnostic)
236
+ * and framework-specific adapters (Hono, Express, Fastify, etc.).
237
+ *
238
+ * Each adapter translates between framework-specific request/response types
239
+ * and the standard types used by the core server.
240
+ *
241
+ * @template TRequest - Framework-specific request type (e.g., Context for Hono, Request for Express)
242
+ * @template TResponse - Framework-specific response type (e.g., Context for Hono, Response for Express)
243
+ * @template TWebSocket - Framework-specific WebSocket type (optional, defaults to unknown)
244
+ *
245
+ * @example
246
+ * ```typescript
247
+ * // Hono adapter example
248
+ * const honoAdapter: ServerAdapter<Context, Context, WSEvents> = {
249
+ * extractRequest: (c) => Effect.succeed({
250
+ * method: c.req.raw.method,
251
+ * url: new URL(c.req.raw.url),
252
+ * headers: Object.fromEntries(c.req.raw.headers.entries()),
253
+ * body: c.req.raw.body
254
+ * }),
255
+ * sendResponse: (c, response) => Effect.sync(() =>
256
+ * new Response(JSON.stringify(response.body), {
257
+ * status: response.status,
258
+ * headers: response.headers
259
+ * })
260
+ * ),
261
+ * runAuthMiddleware: (c) => Effect.tryPromise(() => authMiddleware(c)),
262
+ * createWebSocketHandler: (ws) => ({ ... })
263
+ * };
264
+ * ```
265
+ */
266
+ interface ServerAdapter<TContext, TResponse, TWebSocketHandler = unknown> {
267
+ /**
268
+ * Extract standard request details from framework-specific request.
269
+ *
270
+ * This method converts the framework's native request object into a
271
+ * UploadistaRequest that the core server can process uniformly.
272
+ *
273
+ * @param req - Framework-specific request object
274
+ * @returns Effect that produces UploadistaRequest on success
275
+ */
276
+ extractRequest(req: TContext, {
277
+ baseUrl
278
+ }: {
279
+ baseUrl: string;
280
+ }): Effect.Effect<UploadistaRequest, never, never>;
281
+ /**
282
+ * Send standard response using framework-specific response object.
283
+ *
284
+ * This method converts a UploadistaResponse from the core server into
285
+ * the format required by the framework (e.g., Web API Response, Express res.json()).
286
+ *
287
+ * @param response - Standard response to send
288
+ * @returns Effect that completes when response is sent
289
+ */
290
+ sendResponse(response: UploadistaResponse, context: TContext): Effect.Effect<TResponse, never, never>;
291
+ /**
292
+ * Optional: Run framework-specific auth middleware.
293
+ *
294
+ * If provided, this method is called before each request is processed.
295
+ * It should execute the framework's authentication middleware and return
296
+ * an AuthResult (AuthContext on success, null on failure).
297
+ *
298
+ * If not provided, the adapter assumes no authentication is required.
299
+ *
300
+ * @param ctx - Framework-specific context object
301
+ * @param res - Framework-specific response object
302
+ * @returns Effect that produces AuthResult (AuthContext or null)
303
+ */
304
+ runAuthMiddleware?(ctx: TContext): Effect.Effect<AuthResult, never, never>;
305
+ /**
306
+ * Optional: Create WebSocket handler for real-time updates.
307
+ *
308
+ * Only needed if the framework supports WebSocket connections for
309
+ * real-time upload progress and flow status updates.
310
+ *
311
+ * @param ws - Framework-specific WebSocket object
312
+ * @param ctx - Framework-specific context object (for initial handshake)
313
+ * @param context - Server context with baseUrl, uploadServer, and flowServer
314
+ * @returns WebSocketHandler with callbacks for message, close, and error events
315
+ */
316
+ webSocketHandler(context: {
317
+ baseUrl: string;
318
+ }): Effect.Effect<TWebSocketHandler, never, UploadServer | FlowServer>;
319
+ /**
320
+ * Optional: Extract waitUntil callback from the framework context.
321
+ *
322
+ * When provided, allows flows to execute beyond the HTTP response lifecycle.
323
+ * This function is called per-request to extract the waitUntil callback from
324
+ * the framework-specific context.
325
+ *
326
+ * @param ctx - Framework-specific context object
327
+ * @returns The waitUntil callback or undefined if not available
328
+ *
329
+ * @example
330
+ * ```typescript
331
+ * // Cloudflare Workers with Hono:
332
+ * extractWaitUntil: (c) => c.executionCtx.waitUntil.bind(c.executionCtx)
333
+ * ```
334
+ */
335
+ extractWaitUntil?: (ctx: TContext) => ((promise: Promise<unknown>) => void) | undefined;
336
+ }
337
+ //#endregion
51
338
  //#region src/cache.d.ts
52
339
  /**
53
340
  * Configuration options for the auth cache.
@@ -132,6 +419,443 @@ declare const AuthCacheServiceLive: (config?: AuthCacheConfig) => Layer.Layer<Au
132
419
  */
133
420
  declare const NoAuthCacheServiceLive: Layer.Layer<AuthCacheService>;
134
421
  //#endregion
422
+ //#region src/core/types.d.ts
423
+ /**
424
+ * Function type for retrieving flows based on flow ID and client ID.
425
+ *
426
+ * This function is called by the core server when a flow needs to be executed.
427
+ * It should return an Effect that resolves to the requested Flow or fails with
428
+ * an UploadistaError if the flow is not found or not authorized.
429
+ *
430
+ * @param flowId - The unique identifier of the flow to retrieve
431
+ * @param clientId - The authenticated client ID (null if not authenticated)
432
+ * @returns Effect that produces the Flow or fails with an error
433
+ *
434
+ * @example
435
+ * ```typescript
436
+ * const flows: FlowsFunction = (flowId, clientId) =>
437
+ * Effect.gen(function* () {
438
+ * if (flowId === "image-resize") {
439
+ * return imageResizeFlow;
440
+ * }
441
+ * return yield* Effect.fail(
442
+ * new UploadistaError({ code: "FLOW_NOT_FOUND", status: 404 })
443
+ * );
444
+ * });
445
+ * ```
446
+ */
447
+ type FlowsFunction = (flowId: string, clientId: string | null) => Effect.Effect<Flow$1<z.ZodSchema<unknown>, z.ZodSchema<unknown>, unknown>, UploadistaError, unknown>;
448
+ /**
449
+ * Configuration for creating the unified Uploadista server.
450
+ *
451
+ * This configuration is framework-agnostic and contains all the business logic
452
+ * configuration. Framework-specific details are provided via the `adapter` field.
453
+ *
454
+ * @template TRequest - Framework-specific request type
455
+ * @template TResponse - Framework-specific response type
456
+ * @template TWebSocket - Framework-specific WebSocket type (optional)
457
+ *
458
+ * @example
459
+ * ```typescript
460
+ * import { createUploadistaServer, honoAdapter } from "@uploadista/server";
461
+ *
462
+ * const config: UploadistaServerConfig<Context, Context, WSEvents> = {
463
+ * // Core business logic configuration
464
+ * flows: getFlowById,
465
+ * dataStore: { type: "s3", config: { bucket: "my-bucket" } },
466
+ * kvStore: redisKvStore,
467
+ * baseUrl: "/uploadista",
468
+ *
469
+ * // Framework-specific adapter
470
+ * adapter: honoAdapter({
471
+ * authMiddleware: async (c) => {
472
+ * // Hono-specific auth logic
473
+ * return { clientId: "user-123" };
474
+ * },
475
+ * }),
476
+ * };
477
+ *
478
+ * const server = await createUploadistaServer(config);
479
+ * ```
480
+ */
481
+ interface UploadistaServerConfig<TRequest, TResponse, TWebSocket = unknown> {
482
+ /**
483
+ * Function for retrieving flows by ID.
484
+ *
485
+ * This function is called when a flow execution is requested.
486
+ * It receives the flow ID and client ID (from auth context) and should
487
+ * return an Effect that resolves to the Flow definition.
488
+ *
489
+ * @example
490
+ * ```typescript
491
+ * flows: (flowId, clientId) => Effect.succeed(myFlows[flowId])
492
+ * ```
493
+ */
494
+ flows: FlowsFunction;
495
+ /**
496
+ * Data store configuration for file storage.
497
+ *
498
+ * Specifies where uploaded files should be stored (S3, Azure, GCS, filesystem).
499
+ * The core server creates the appropriate data store layer from this configuration.
500
+ *
501
+ * @example
502
+ * ```typescript
503
+ * dataStore: {
504
+ * type: "s3",
505
+ * config: {
506
+ * bucket: "my-uploads",
507
+ * region: "us-east-1"
508
+ * }
509
+ * }
510
+ * ```
511
+ */
512
+ dataStore: DataStoreConfig;
513
+ /**
514
+ * Key-value store layer for metadata storage.
515
+ *
516
+ * Used for storing upload metadata, flow job state, and other persistent data.
517
+ * Can be Redis, Cloudflare KV, in-memory, or any implementation of BaseKvStoreService.
518
+ *
519
+ * @example
520
+ * ```typescript
521
+ * import { redisKvStore } from "@uploadista/kv-store-redis";
522
+ *
523
+ * kvStore: redisKvStore({ url: "redis://localhost:6379" })
524
+ * ```
525
+ */
526
+ kvStore: Layer.Layer<BaseKvStoreService>;
527
+ /**
528
+ * Optional: Plugins to extend functionality.
529
+ *
530
+ * Plugins are Effect layers that add additional capabilities to the upload
531
+ * and flow servers. They are merged into the server layer composition.
532
+ *
533
+ * @example
534
+ * ```typescript
535
+ * plugins: [imageProcessingPlugin, virusScanPlugin]
536
+ * ```
537
+ */
538
+ plugins?: readonly Layer.Layer<any, never, never>[];
539
+ /**
540
+ * Optional: Event emitter layer for progress notifications.
541
+ *
542
+ * Used to emit upload progress, flow status updates, and other events.
543
+ * Defaults to in-memory event emitter if not provided.
544
+ *
545
+ * @example
546
+ * ```typescript
547
+ * import { webSocketEventEmitter } from "@uploadista/event-emitter-websocket";
548
+ *
549
+ * eventEmitter: webSocketEventEmitter()
550
+ * ```
551
+ */
552
+ eventEmitter?: Layer.Layer<BaseEventEmitterService>;
553
+ /**
554
+ * Optional: Event broadcaster layer for real-time updates.
555
+ *
556
+ * Used to broadcast events to multiple subscribers (e.g., WebSocket connections).
557
+ * Defaults to in-memory broadcaster if not provided.
558
+ *
559
+ * @example
560
+ * ```typescript
561
+ * import { memoryEventBroadcaster } from "@uploadista/event-broadcaster-memory";
562
+ *
563
+ * eventBroadcaster: memoryEventBroadcaster()
564
+ * ```
565
+ */
566
+ eventBroadcaster?: Layer.Layer<EventBroadcasterService>;
567
+ /**
568
+ * Optional: Base URL path for Uploadista endpoints.
569
+ *
570
+ * All Uploadista routes will be prefixed with `{baseUrl}/api/`.
571
+ * For example, with baseUrl="/uploadista", routes become:
572
+ * - POST /uploadista/api/upload
573
+ * - POST /uploadista/api/flow/{flowId}/{storageId}
574
+ *
575
+ * @default "" (no prefix, routes start with /api/)
576
+ */
577
+ baseUrl?: string;
578
+ /**
579
+ * Optional: Custom ID generator layer.
580
+ *
581
+ * Used for generating upload IDs, job IDs, and other unique identifiers.
582
+ * Defaults to built-in ID generator if not provided.
583
+ *
584
+ * @example
585
+ * ```typescript
586
+ * import { nanoidGenerator } from "@uploadista/utils";
587
+ *
588
+ * generateId: nanoidGenerator()
589
+ * ```
590
+ */
591
+ generateId?: Layer.Layer<GenerateId>;
592
+ /**
593
+ * Optional: Enable distributed tracing with OpenTelemetry.
594
+ *
595
+ * When true, Effect programs run with OpenTelemetry tracing enabled,
596
+ * allowing observability into upload and flow execution.
597
+ *
598
+ * @default false
599
+ */
600
+ withTracing?: boolean;
601
+ /**
602
+ * Optional: Metrics layer for observability.
603
+ *
604
+ * Used to collect metrics about upload/flow performance, errors, and usage.
605
+ * Defaults to NoOp metrics if not provided.
606
+ *
607
+ * @example
608
+ * ```typescript
609
+ * import { prometheusMetrics } from "@uploadista/observability";
610
+ *
611
+ * metricsLayer: prometheusMetrics()
612
+ * ```
613
+ */
614
+ metricsLayer?: Layer.Layer<any, never, never>;
615
+ /**
616
+ * Optional: Buffered data store layer for performance optimization.
617
+ *
618
+ * Provides in-memory buffering for frequently accessed data,
619
+ * reducing latency for chunk uploads and reads.
620
+ *
621
+ * @example
622
+ * ```typescript
623
+ * import { bufferedDataStore } from "@uploadista/core/data-store";
624
+ *
625
+ * bufferedDataStore: bufferedDataStore({ maxSize: 1024 * 1024 * 10 })
626
+ * ```
627
+ */
628
+ bufferedDataStore?: Layer.Layer<UploadFileDataStore, never, UploadFileKVStore>;
629
+ /**
630
+ * Framework-specific adapter.
631
+ *
632
+ * The adapter provides the bridge between framework-specific request/response
633
+ * types and the standard types used by the core server. Each framework
634
+ * (Hono, Express, Fastify) has its own adapter implementation.
635
+ *
636
+ * @example
637
+ * ```typescript
638
+ * import { honoAdapter } from "@uploadista/adapters-hono";
639
+ *
640
+ * adapter: honoAdapter({
641
+ * authMiddleware: async (c) => ({ clientId: "user-123" })
642
+ * })
643
+ * ```
644
+ */
645
+ adapter: ServerAdapter<TRequest, TResponse, TWebSocket>;
646
+ /**
647
+ * Optional: Configuration for auth context caching.
648
+ *
649
+ * Caching allows subsequent requests (chunk uploads, flow continuations) to
650
+ * reuse the auth context from the initial request without re-authenticating.
651
+ *
652
+ * @example
653
+ * ```typescript
654
+ * authCacheConfig: {
655
+ * maxSize: 10000,
656
+ * ttl: 3600000 // 1 hour
657
+ * }
658
+ * ```
659
+ */
660
+ authCacheConfig?: AuthCacheConfig;
661
+ }
662
+ /**
663
+ * Return type from createUploadistaServer.
664
+ *
665
+ * Contains the handler function and exposed server layers for framework-specific routing.
666
+ *
667
+ * @template TRequest - Framework-specific request type
668
+ * @template TResponse - Framework-specific response type
669
+ * @template TWebSocket - Framework-specific WebSocket type (optional)
670
+ */
671
+ interface UploadistaServer<TRequest, TResponse, TWebSocketHandler = unknown> {
672
+ /**
673
+ * Main request handler that processes HTTP requests through the adapter.
674
+ */
675
+ handler: (req: TRequest) => Promise<TResponse>;
676
+ /**
677
+ * Optional WebSocket handler if the adapter supports WebSocket connections.
678
+ */
679
+ websocketHandler: TWebSocketHandler;
680
+ /**
681
+ * Base URL path for Uploadista endpoints.
682
+ */
683
+ baseUrl: string;
684
+ /**
685
+ * Dispose function for graceful shutdown.
686
+ * Cleans up all resources associated with the managed runtime.
687
+ * Should be called when the server is shutting down.
688
+ */
689
+ dispose: () => Promise<void>;
690
+ }
691
+ //#endregion
692
+ //#region src/core/server.d.ts
693
+ /**
694
+ * Creates the unified Uploadista server with framework-specific adapter.
695
+ *
696
+ * This function composes all layers (upload server, flow server, auth, metrics)
697
+ * and returns a handler that works with any framework via the provided adapter.
698
+ *
699
+ * The core server handles:
700
+ * - Route parsing and matching
701
+ * - Auth middleware execution with timeout protection
702
+ * - Layer composition (upload/flow servers, auth cache, metrics)
703
+ * - Error handling and response formatting
704
+ * - Effect program execution with optional tracing
705
+ *
706
+ * @param config - Server configuration including adapter and business logic
707
+ * @returns Object with handler function, optional WebSocket handler, and base URL
708
+ *
709
+ * @example
710
+ * ```typescript
711
+ * import { createUploadistaServer, honoAdapter } from "@uploadista/server";
712
+ *
713
+ * const server = await createUploadistaServer({
714
+ * flows: getFlowById,
715
+ * dataStore: { type: "s3", config: { bucket: "uploads" } },
716
+ * kvStore: redisKvStore,
717
+ * adapter: honoAdapter({
718
+ * authMiddleware: async (c) => ({ clientId: "user-123" })
719
+ * })
720
+ * });
721
+ *
722
+ * // Use with Hono
723
+ * app.all("/uploadista/*", server.handler);
724
+ * ```
725
+ */
726
+ declare const createUploadistaServer: <TContext, TResponse, TWebSocketHandler = unknown>({
727
+ flows,
728
+ dataStore,
729
+ kvStore,
730
+ plugins,
731
+ eventEmitter,
732
+ eventBroadcaster,
733
+ withTracing,
734
+ baseUrl: configBaseUrl,
735
+ generateId,
736
+ metricsLayer,
737
+ bufferedDataStore,
738
+ adapter,
739
+ authCacheConfig
740
+ }: UploadistaServerConfig<TContext, TResponse, TWebSocketHandler>) => Promise<UploadistaServer<TContext, TResponse, TWebSocketHandler>>;
741
+ //#endregion
742
+ //#region src/core/websocket-routes.d.ts
743
+ /**
744
+ * Framework-agnostic WebSocket connection interface
745
+ * Adapters should wrap their native WebSocket implementations to match this interface
746
+ */
747
+ type WebSocketConnection = {
748
+ id: string;
749
+ send: (data: string) => void;
750
+ close: (code?: number, reason?: string) => void;
751
+ readyState: number;
752
+ };
753
+ /**
754
+ * WebSocket event types for real-time communication
755
+ */
756
+ type WebSocketEventType = "subscribe-upload" | "subscribe-flow" | "unsubscribe-upload" | "unsubscribe-flow" | "ping" | "connection" | "upload-event" | "flow-event" | "error" | "invalid-path" | "auth-failed";
757
+ /**
758
+ * Base WebSocket event structure
759
+ */
760
+ type WebSocketEvent<T extends WebSocketEventType> = {
761
+ type: T;
762
+ };
763
+ /**
764
+ * Incoming WebSocket messages (client -> server)
765
+ */
766
+ type SubscribeUploadEvent = WebSocketEvent<"subscribe-upload"> & {
767
+ uploadId: string;
768
+ };
769
+ type SubscribeFlowEvent = WebSocketEvent<"subscribe-flow"> & {
770
+ jobId: string;
771
+ };
772
+ type UnsubscribeUploadEvent = WebSocketEvent<"unsubscribe-upload"> & {
773
+ uploadId: string;
774
+ };
775
+ type UnsubscribeFlowEvent = WebSocketEvent<"unsubscribe-flow"> & {
776
+ jobId: string;
777
+ };
778
+ type PingEvent = WebSocketEvent<"ping">;
779
+ type WebSocketIncomingEvent = SubscribeUploadEvent | SubscribeFlowEvent | UnsubscribeUploadEvent | UnsubscribeFlowEvent | PingEvent;
780
+ /**
781
+ * Outgoing WebSocket messages (server -> client)
782
+ */
783
+ type ConnectionEvent = WebSocketEvent<"connection"> & {
784
+ message: string;
785
+ id?: string;
786
+ jobId?: string;
787
+ uploadId?: string;
788
+ timestamp: string;
789
+ };
790
+ type UploadEventMessage = WebSocketEvent<"upload-event"> & {
791
+ uploadId: string;
792
+ event: UploadEvent;
793
+ timestamp: string;
794
+ };
795
+ type FlowEventMessage = WebSocketEvent<"flow-event"> & {
796
+ jobId: string;
797
+ event: unknown;
798
+ timestamp: string;
799
+ };
800
+ type ErrorEvent = WebSocketEvent<"error"> & {
801
+ message: string;
802
+ code?: string;
803
+ };
804
+ type InvalidPathEvent = WebSocketEvent<"invalid-path"> & {
805
+ message: string;
806
+ expectedPrefix: string;
807
+ };
808
+ type AuthFailedEvent = WebSocketEvent<"auth-failed"> & {
809
+ message: string;
810
+ authMethod: "token" | "cookies";
811
+ };
812
+ type WebSocketOutgoingEvent = ConnectionEvent | UploadEventMessage | FlowEventMessage | ErrorEvent | InvalidPathEvent | AuthFailedEvent;
813
+ /**
814
+ * WebSocket connection request with routing information
815
+ * Extracted from the WebSocket URL and query parameters
816
+ */
817
+ type WebSocketConnectionRequest = {
818
+ /** Base URL prefix for WebSocket connections */
819
+ baseUrl: string;
820
+ /** Full pathname from the URL */
821
+ pathname: string;
822
+ /** Parsed route segments after baseUrl/ws/ */
823
+ routeSegments: string[];
824
+ /** Whether this is an upload route */
825
+ isUploadRoute: boolean;
826
+ /** Whether this is a flow route */
827
+ isFlowRoute: boolean;
828
+ /** Job ID (for flows) */
829
+ jobId?: string;
830
+ /** Upload ID (for uploads) */
831
+ uploadId?: string;
832
+ /** Event ID (jobId or uploadId) */
833
+ eventId?: string;
834
+ /** WebSocket connection instance */
835
+ connection: WebSocketConnection;
836
+ };
837
+ //#endregion
838
+ //#region src/core/websocket-handlers/websocket-handlers.d.ts
839
+ /**
840
+ * Handles WebSocket connection opening
841
+ * Subscribes to the appropriate events based on the connection request
842
+ */
843
+ declare const handleWebSocketOpen: (request: WebSocketConnectionRequest, uploadServer: UploadServerShape, flowServer: FlowServerShape) => Effect.Effect<void, never, never>;
844
+ /**
845
+ * Handles incoming WebSocket messages
846
+ * Currently supports ping/pong for connection keep-alive
847
+ */
848
+ declare const handleWebSocketMessage: (message: string, connection: WebSocketConnection) => Effect.Effect<void, never, never>;
849
+ /**
850
+ * Handles WebSocket connection closing
851
+ * Unsubscribes from all events and cleans up resources
852
+ */
853
+ declare const handleWebSocketClose: (request: WebSocketConnectionRequest, uploadServer: UploadServerShape, flowServer: FlowServerShape) => Effect.Effect<void, never, never>;
854
+ /**
855
+ * Handles WebSocket errors
856
+ */
857
+ declare const handleWebSocketError: (error: unknown, eventId?: string) => Effect.Effect<void, never, never>;
858
+ //#endregion
135
859
  //#region src/error-types.d.ts
136
860
  /**
137
861
  * Base adapter error class for HTTP adapters.
@@ -237,7 +961,7 @@ declare const createErrorResponseBody: (error: AdapterError) => {
237
961
  * }
238
962
  * ```
239
963
  */
240
- declare const createUploadistaErrorResponseBody: (error: UploadistaError) => {
964
+ declare const createUploadistaErrorResponseBody: (error: UploadistaError$1) => {
241
965
  error: string;
242
966
  code: string;
243
967
  timestamp: string;
@@ -550,7 +1274,7 @@ declare const createFlowServerLayer: ({
550
1274
  //#region src/plugins-typing.d.ts
551
1275
  type LayerSuccessUnion<Layers extends readonly Layer.Layer<any, never, never>[]> = Layers[number] extends Layer.Layer<infer Success, never, never> ? Success : never;
552
1276
  type FlowSuccess<TFlows extends (flowId: string, clientId: string | null) => Effect.Effect<unknown, unknown, unknown>> = ReturnType<TFlows> extends Effect.Effect<infer Success, unknown, unknown> ? Success : never;
553
- type FlowRequirementsOf<TFlows extends (flowId: string, clientId: string | null) => Effect.Effect<unknown, unknown, unknown>> = FlowSuccess<TFlows> extends Flow<z.ZodSchema<unknown>, z.ZodSchema<unknown>, infer R> ? Exclude<R, UploadServer> : never;
1277
+ type FlowRequirementsOf<TFlows extends (flowId: string, clientId: string | null) => Effect.Effect<unknown, unknown, unknown>> = FlowSuccess<TFlows> extends Flow<z$1.ZodSchema<unknown>, z$1.ZodSchema<unknown>, infer R> ? Exclude<R, UploadServer> : never;
554
1278
  type RequiredPluginsOf<TFlows extends (flowId: string, clientId: string | null) => Effect.Effect<unknown, unknown, unknown>> = Exclude<FlowRequirementsOf<TFlows>, UploadServer>;
555
1279
  type PluginAssertion<TFlows extends (flowId: string, clientId: string | null) => Effect.Effect<unknown, unknown, unknown>, TPlugins extends readonly Layer.Layer<any, never, never>[]> = Exclude<RequiredPluginsOf<TFlows>, LayerSuccessUnion<TPlugins>> extends never ? unknown : {
556
1280
  __missingPlugins: Exclude<RequiredPluginsOf<TFlows>, LayerSuccessUnion<TPlugins>>;
@@ -616,5 +1340,5 @@ declare const AuthContextServiceLive: (authContext: AuthContext | null) => Layer
616
1340
  */
617
1341
  declare const NoAuthContextServiceLive: Layer.Layer<AuthContextService>;
618
1342
  //#endregion
619
- export { AdapterError, AuthCacheConfig, AuthCacheService, AuthCacheServiceLive, AuthContext, AuthContextService, AuthContextServiceLive, AuthCredentialsResponse, AuthResult, BadRequestError, FlowRequirementsOf, FlowServerLayerConfig, FlowSuccess, LayerSuccessUnion, NoAuthCacheServiceLive, NoAuthContextServiceLive, NotFoundError, PluginAssertion, RequiredPluginsOf, UploadServerLayerConfig, ValidationError, createErrorResponseBody, createFlowServerLayer, createGenericErrorResponseBody, createUploadServerLayer, createUploadistaErrorResponseBody, extractFlowAndStorageId, extractJobAndNodeId, extractJobIdFromStatus, getAuthCredentials, getLastSegment, getRouteSegments, handleFlowError, hasBasePath, parseUrlSegments };
1343
+ export { AdapterError, AuthCacheConfig, AuthCacheService, AuthCacheServiceLive, AuthContext, AuthContextService, AuthContextServiceLive, AuthCredentialsResponse, AuthFailedEvent, AuthResult, BadRequestError, BadRequestRequest, BadRequestResponse, CancelFlowRequest, CancelFlowResponse, ConnectionEvent, CreateUploadRequest, CreateUploadResponse, ErrorEvent, FlowEventMessage, FlowRequirementsOf, FlowServerLayerConfig, FlowSuccess, FlowsFunction, GetCapabilitiesRequest, GetCapabilitiesResponse, GetFlowRequest, GetFlowResponse, GetJobStatusRequest, GetJobStatusResponse, GetUploadRequest, GetUploadResponse, InvalidPathEvent, LayerSuccessUnion, MethodNotAllowedRequest, MethodNotAllowedResponse, NoAuthCacheServiceLive, NoAuthContextServiceLive, NotFoundError, NotFoundRequest, NotFoundResponse, PauseFlowRequest, PauseFlowResponse, PingEvent, PluginAssertion, RequiredPluginsOf, ResumeFlowRequest, ResumeFlowResponse, RunFlowRequest, RunFlowResponse, ServerAdapter, StandardRequest, StandardResponse, SubscribeFlowEvent, SubscribeUploadEvent, UnsubscribeFlowEvent, UnsubscribeUploadEvent, UnsupportedContentTypeRequest, UnsupportedContentTypeResponse, UploadChunkRequest, UploadChunkResponse, UploadEventMessage, UploadServerLayerConfig, UploadistaRequest, UploadistaResponse, UploadistaRoute, UploadistaRouteType, UploadistaServer, UploadistaServerConfig, UploadistaStandardResponse, ValidationError, type WebSocketConnection, type WebSocketConnectionRequest, WebSocketEvent, WebSocketEventType, WebSocketHandler, WebSocketIncomingEvent, WebSocketOutgoingEvent, createErrorResponseBody, createFlowServerLayer, createGenericErrorResponseBody, createUploadServerLayer, createUploadistaErrorResponseBody, createUploadistaServer, extractFlowAndStorageId, extractJobAndNodeId, extractJobIdFromStatus, getAuthCredentials, getLastSegment, getRouteSegments, handleFlowError, handleWebSocketClose, handleWebSocketError, handleWebSocketMessage, handleWebSocketOpen, hasBasePath, parseUrlSegments };
620
1344
  //# sourceMappingURL=index.d.cts.map