@uploadista/server 0.0.7 → 0.0.9

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 +735 -12
  10. package/dist/index.d.cts.map +1 -1
  11. package/dist/index.d.mts +1343 -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 +10 -7
  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
@@ -0,0 +1,1343 @@
1
+ import { n as getAuthCredentials, t as AuthCredentialsResponse } from "./index--Lny6VJP.mjs";
2
+ import { Context, Effect, Layer } from "effect";
3
+ import { Flow, FlowProvider, FlowServerShape } from "@uploadista/core/flow";
4
+ import { BaseEventEmitterService, BaseKvStoreService, DataStoreConfig, EventBroadcasterService, UploadFileDataStore, UploadFileDataStores, UploadFileKVStore } from "@uploadista/core/types";
5
+ import { GenerateId } from "@uploadista/core/utils";
6
+ import { UploadServer, UploadServerShape } from "@uploadista/core/upload";
7
+ import { UploadistaError } from "@uploadista/core/errors";
8
+ import { DataStoreCapabilities, Flow as Flow$1, FlowData, FlowJob, FlowServer as FlowServer$1, UploadEvent, UploadFile, UploadServer as UploadServer$1, UploadistaError as UploadistaError$1 } from "@uploadista/core";
9
+ import z$1, { z } from "zod";
10
+
11
+ //#region src/core/routes.d.ts
12
+ 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";
13
+ type UploadistaRoute<T extends UploadistaRouteType> = {
14
+ type: T;
15
+ };
16
+ type UploadistaStandardResponse<T extends UploadistaRouteType, ResponseBody, Status extends number = 200> = UploadistaRoute<T> & {
17
+ status: Status;
18
+ headers: {
19
+ "Content-Type": "application/json";
20
+ };
21
+ body: ResponseBody;
22
+ };
23
+ type NotFoundRequest = UploadistaRoute<"not-found">;
24
+ type NotFoundResponse = UploadistaStandardResponse<"not-found", {
25
+ error: "Not found";
26
+ }, 404>;
27
+ type MethodNotAllowedRequest = UploadistaRoute<"method-not-allowed">;
28
+ type MethodNotAllowedResponse = UploadistaStandardResponse<"method-not-allowed", {
29
+ error: "Method not allowed";
30
+ }, 405>;
31
+ type BadRequestRequest = UploadistaRoute<"bad-request"> & {
32
+ message: string;
33
+ };
34
+ type BadRequestResponse = UploadistaStandardResponse<"bad-request", {
35
+ error: "Bad request";
36
+ message: string;
37
+ }, 400>;
38
+ type UnsupportedContentTypeRequest = UploadistaRoute<"unsupported-content-type">;
39
+ type UnsupportedContentTypeResponse = UploadistaStandardResponse<"unsupported-content-type", {
40
+ error: "Unsupported content type";
41
+ }, 415>;
42
+ type CreateUploadRequest = UploadistaRoute<"create-upload"> & {
43
+ data: unknown;
44
+ };
45
+ type CreateUploadResponse = UploadistaStandardResponse<"create-upload", UploadFile>;
46
+ type GetCapabilitiesRequest = UploadistaRoute<"get-capabilities"> & {
47
+ storageId: string;
48
+ };
49
+ type GetCapabilitiesResponse = UploadistaStandardResponse<"get-capabilities", {
50
+ storageId: string;
51
+ capabilities: DataStoreCapabilities;
52
+ timestamp: string;
53
+ }>;
54
+ type GetUploadRequest = UploadistaRoute<"get-upload"> & {
55
+ uploadId: string;
56
+ };
57
+ type GetUploadResponse = UploadistaStandardResponse<"get-upload", UploadFile>;
58
+ type UploadChunkRequest = UploadistaRoute<"upload-chunk"> & {
59
+ uploadId: string;
60
+ data: ReadableStream;
61
+ };
62
+ type UploadChunkResponse = UploadistaStandardResponse<"upload-chunk", UploadFile>;
63
+ type GetFlowRequest = UploadistaRoute<"get-flow"> & {
64
+ flowId: string;
65
+ };
66
+ type GetFlowResponse = UploadistaStandardResponse<"get-flow", FlowData>;
67
+ type RunFlowRequest = UploadistaRoute<"run-flow"> & {
68
+ flowId: string;
69
+ storageId: string;
70
+ inputs: Record<string, unknown>;
71
+ };
72
+ type RunFlowResponse = UploadistaStandardResponse<"run-flow", FlowJob>;
73
+ type GetJobStatusRequest = UploadistaRoute<"job-status"> & {
74
+ jobId: string;
75
+ };
76
+ type GetJobStatusResponse = UploadistaStandardResponse<"job-status", FlowJob>;
77
+ type ResumeFlowRequest = UploadistaRoute<"resume-flow"> & {
78
+ jobId: string;
79
+ nodeId: string;
80
+ newData: unknown;
81
+ };
82
+ type ResumeFlowResponse = UploadistaStandardResponse<"resume-flow", FlowJob>;
83
+ type PauseFlowRequest = UploadistaRoute<"pause-flow"> & {
84
+ jobId: string;
85
+ };
86
+ type PauseFlowResponse = UploadistaStandardResponse<"pause-flow", FlowJob>;
87
+ type CancelFlowRequest = UploadistaRoute<"cancel-flow"> & {
88
+ jobId: string;
89
+ };
90
+ type CancelFlowResponse = UploadistaStandardResponse<"cancel-flow", FlowJob>;
91
+ type UploadistaRequest = CreateUploadRequest | GetCapabilitiesRequest | GetUploadRequest | UploadChunkRequest | GetFlowRequest | RunFlowRequest | GetJobStatusRequest | ResumeFlowRequest | PauseFlowRequest | CancelFlowRequest | NotFoundRequest | BadRequestRequest | MethodNotAllowedRequest | UnsupportedContentTypeRequest;
92
+ type UploadistaResponse = CreateUploadResponse | GetCapabilitiesResponse | GetUploadResponse | UploadChunkResponse | GetFlowResponse | RunFlowResponse | GetJobStatusResponse | ResumeFlowResponse | PauseFlowResponse | CancelFlowResponse | NotFoundResponse | BadRequestResponse | MethodNotAllowedResponse | UnsupportedContentTypeResponse | StandardResponse;
93
+ //#endregion
94
+ //#region src/types.d.ts
95
+ /**
96
+ * Authentication context containing user identity and authorization metadata.
97
+ * This context is extracted from authentication middleware and made available
98
+ * throughout the upload and flow processing pipeline via Effect Layer.
99
+ */
100
+ type AuthContext = {
101
+ /**
102
+ * Unique identifier for the authenticated user.
103
+ * This is typically extracted from JWT claims (sub), session data, or API key metadata.
104
+ */
105
+ clientId: string;
106
+ /**
107
+ * Optional metadata for authorization and tracking purposes.
108
+ * Can include rate limits, quotas, permissions, or custom application data.
109
+ *
110
+ * @example
111
+ * ```typescript
112
+ * {
113
+ * permissions: ['upload:create', 'flow:execute'],
114
+ * rateLimit: { requests: 1000, period: 3600 },
115
+ * quota: { storage: 10737418240, used: 5368709120 }
116
+ * }
117
+ * ```
118
+ */
119
+ metadata?: Record<string, unknown>;
120
+ /**
121
+ * Optional list of permissions granted to the user.
122
+ * These can be used for fine-grained access control in the future.
123
+ */
124
+ permissions?: string[];
125
+ };
126
+ /**
127
+ * Result type for authentication middleware.
128
+ * - AuthContext: Successful authentication with user identity
129
+ * - null: Authentication failed or not authenticated
130
+ */
131
+ type AuthResult = AuthContext | null;
132
+ //#endregion
133
+ //#region src/adapter/types.d.ts
134
+ /**
135
+ * Standard request representation extracted from framework-specific request objects.
136
+ *
137
+ * This interface provides a framework-agnostic way to represent HTTP requests,
138
+ * allowing the core server logic to work uniformly across Hono, Express, Fastify,
139
+ * and other frameworks.
140
+ *
141
+ * @example
142
+ * ```typescript
143
+ * const standardRequest: StandardRequest = {
144
+ * method: "POST",
145
+ * url: new URL("https://example.com/uploadista/api/upload"),
146
+ * headers: { "content-type": "application/json" },
147
+ * body: { file: "data" }
148
+ * };
149
+ * ```
150
+ */
151
+ interface StandardRequest {
152
+ /**
153
+ * HTTP method (GET, POST, PATCH, etc.)
154
+ */
155
+ method: string;
156
+ /**
157
+ * Full URL of the request including protocol, host, path, and query parameters
158
+ */
159
+ url: URL;
160
+ /**
161
+ * Request headers as key-value pairs
162
+ */
163
+ headers: Record<string, string>;
164
+ /**
165
+ * Optional request body (parsed or raw)
166
+ */
167
+ body?: unknown;
168
+ }
169
+ /**
170
+ * Standard response representation to be sent by framework-specific adapters.
171
+ *
172
+ * The core server produces StandardResponse objects, which adapters then
173
+ * translate into framework-specific response formats.
174
+ *
175
+ * @example
176
+ * ```typescript
177
+ * const standardResponse: StandardResponse = {
178
+ * status: 200,
179
+ * headers: { "content-type": "application/json" },
180
+ * body: { uploadId: "abc123" }
181
+ * };
182
+ * ```
183
+ */
184
+ interface StandardResponse {
185
+ /**
186
+ * HTTP status code (200, 404, 500, etc.)
187
+ */
188
+ status: number;
189
+ /**
190
+ * Optional response headers as key-value pairs
191
+ */
192
+ headers?: Record<string, string>;
193
+ /**
194
+ * Optional response body (will be JSON-stringified if object)
195
+ */
196
+ body?: unknown;
197
+ }
198
+ /**
199
+ * WebSocket handler interface for framework-agnostic WebSocket management.
200
+ *
201
+ * This interface allows the core server to interact with WebSocket connections
202
+ * without needing to know about framework-specific WebSocket APIs.
203
+ *
204
+ * @example
205
+ * ```typescript
206
+ * const wsHandler: WebSocketHandler = {
207
+ * onMessage: (message) => console.log("Received:", message),
208
+ * onClose: () => console.log("Connection closed"),
209
+ * onError: (error) => console.error("WebSocket error:", error)
210
+ * };
211
+ * ```
212
+ */
213
+ interface WebSocketHandler {
214
+ /**
215
+ * Callback invoked when a message is received from the client
216
+ *
217
+ * @param message - The message string received
218
+ */
219
+ onMessage: (message: string) => void;
220
+ /**
221
+ * Callback invoked when the WebSocket connection is closed
222
+ */
223
+ onClose: () => void;
224
+ /**
225
+ * Callback invoked when a WebSocket error occurs
226
+ *
227
+ * @param error - The error that occurred
228
+ */
229
+ onError: (error: Error) => void;
230
+ }
231
+ /**
232
+ * ServerAdapter interface that framework adapters must implement.
233
+ *
234
+ * This interface defines the contract between the core server (framework-agnostic)
235
+ * and framework-specific adapters (Hono, Express, Fastify, etc.).
236
+ *
237
+ * Each adapter translates between framework-specific request/response types
238
+ * and the standard types used by the core server.
239
+ *
240
+ * @template TRequest - Framework-specific request type (e.g., Context for Hono, Request for Express)
241
+ * @template TResponse - Framework-specific response type (e.g., Context for Hono, Response for Express)
242
+ * @template TWebSocket - Framework-specific WebSocket type (optional, defaults to unknown)
243
+ *
244
+ * @example
245
+ * ```typescript
246
+ * // Hono adapter example
247
+ * const honoAdapter: ServerAdapter<Context, Context, WSEvents> = {
248
+ * extractRequest: (c) => Effect.succeed({
249
+ * method: c.req.raw.method,
250
+ * url: new URL(c.req.raw.url),
251
+ * headers: Object.fromEntries(c.req.raw.headers.entries()),
252
+ * body: c.req.raw.body
253
+ * }),
254
+ * sendResponse: (c, response) => Effect.sync(() =>
255
+ * new Response(JSON.stringify(response.body), {
256
+ * status: response.status,
257
+ * headers: response.headers
258
+ * })
259
+ * ),
260
+ * runAuthMiddleware: (c) => Effect.tryPromise(() => authMiddleware(c)),
261
+ * createWebSocketHandler: (ws) => ({ ... })
262
+ * };
263
+ * ```
264
+ */
265
+ interface ServerAdapter<TContext, TResponse, TWebSocketHandler = unknown> {
266
+ /**
267
+ * Extract standard request details from framework-specific request.
268
+ *
269
+ * This method converts the framework's native request object into a
270
+ * UploadistaRequest that the core server can process uniformly.
271
+ *
272
+ * @param req - Framework-specific request object
273
+ * @returns Effect that produces UploadistaRequest on success
274
+ */
275
+ extractRequest(req: TContext, {
276
+ baseUrl
277
+ }: {
278
+ baseUrl: string;
279
+ }): Effect.Effect<UploadistaRequest, never, never>;
280
+ /**
281
+ * Send standard response using framework-specific response object.
282
+ *
283
+ * This method converts a UploadistaResponse from the core server into
284
+ * the format required by the framework (e.g., Web API Response, Express res.json()).
285
+ *
286
+ * @param response - Standard response to send
287
+ * @returns Effect that completes when response is sent
288
+ */
289
+ sendResponse(response: UploadistaResponse, context: TContext): Effect.Effect<TResponse, never, never>;
290
+ /**
291
+ * Optional: Run framework-specific auth middleware.
292
+ *
293
+ * If provided, this method is called before each request is processed.
294
+ * It should execute the framework's authentication middleware and return
295
+ * an AuthResult (AuthContext on success, null on failure).
296
+ *
297
+ * If not provided, the adapter assumes no authentication is required.
298
+ *
299
+ * @param ctx - Framework-specific context object
300
+ * @param res - Framework-specific response object
301
+ * @returns Effect that produces AuthResult (AuthContext or null)
302
+ */
303
+ runAuthMiddleware?(ctx: TContext): Effect.Effect<AuthResult, never, never>;
304
+ /**
305
+ * Optional: Create WebSocket handler for real-time updates.
306
+ *
307
+ * Only needed if the framework supports WebSocket connections for
308
+ * real-time upload progress and flow status updates.
309
+ *
310
+ * @param ws - Framework-specific WebSocket object
311
+ * @param ctx - Framework-specific context object (for initial handshake)
312
+ * @param context - Server context with baseUrl, uploadServer, and flowServer
313
+ * @returns WebSocketHandler with callbacks for message, close, and error events
314
+ */
315
+ webSocketHandler(context: {
316
+ baseUrl: string;
317
+ }): Effect.Effect<TWebSocketHandler, never, UploadServer$1 | FlowServer$1>;
318
+ /**
319
+ * Optional: Extract waitUntil callback from the framework context.
320
+ *
321
+ * When provided, allows flows to execute beyond the HTTP response lifecycle.
322
+ * This function is called per-request to extract the waitUntil callback from
323
+ * the framework-specific context.
324
+ *
325
+ * @param ctx - Framework-specific context object
326
+ * @returns The waitUntil callback or undefined if not available
327
+ *
328
+ * @example
329
+ * ```typescript
330
+ * // Cloudflare Workers with Hono:
331
+ * extractWaitUntil: (c) => c.executionCtx.waitUntil.bind(c.executionCtx)
332
+ * ```
333
+ */
334
+ extractWaitUntil?: (ctx: TContext) => ((promise: Promise<unknown>) => void) | undefined;
335
+ }
336
+ //#endregion
337
+ //#region src/cache.d.ts
338
+ /**
339
+ * Configuration options for the auth cache.
340
+ */
341
+ type AuthCacheConfig = {
342
+ /**
343
+ * Maximum number of entries in the cache.
344
+ * When exceeded, oldest entries are removed (LRU eviction).
345
+ * @default 10000
346
+ */
347
+ maxSize?: number;
348
+ /**
349
+ * Time-to-live for cache entries in milliseconds.
350
+ * Entries older than this will be automatically evicted.
351
+ * @default 3600000 (1 hour)
352
+ */
353
+ ttl?: number;
354
+ };
355
+ declare const AuthCacheService_base: Context.TagClass<AuthCacheService, "AuthCacheService", {
356
+ /**
357
+ * Store an auth context for a job ID.
358
+ */
359
+ readonly set: (jobId: string, authContext: AuthContext) => Effect.Effect<void>;
360
+ /**
361
+ * Retrieve a cached auth context by job ID.
362
+ * Returns null if not found or expired.
363
+ */
364
+ readonly get: (jobId: string) => Effect.Effect<AuthContext | null>;
365
+ /**
366
+ * Delete a cached auth context by job ID.
367
+ */
368
+ readonly delete: (jobId: string) => Effect.Effect<void>;
369
+ /**
370
+ * Clear all cached auth contexts.
371
+ */
372
+ readonly clear: () => Effect.Effect<void>;
373
+ /**
374
+ * Get the current number of cached entries.
375
+ */
376
+ readonly size: () => Effect.Effect<number>;
377
+ }>;
378
+ /**
379
+ * Auth Cache Service
380
+ *
381
+ * Provides caching of authentication contexts for upload and flow jobs.
382
+ * This allows subsequent operations (chunk uploads, flow continuations)
383
+ * to reuse the auth context from the initial request without re-authenticating.
384
+ *
385
+ * @example
386
+ * ```typescript
387
+ * import { Effect } from "effect";
388
+ * import { AuthCacheService } from "@uploadista/server";
389
+ *
390
+ * const handler = Effect.gen(function* () {
391
+ * const authCache = yield* AuthCacheService;
392
+ * const authContext = { userId: "user-123" };
393
+ *
394
+ * // Cache auth for upload
395
+ * yield* authCache.set("upload-abc", authContext);
396
+ *
397
+ * // Retrieve cached auth later
398
+ * const cached = yield* authCache.get("upload-abc");
399
+ * console.log(cached?.userId); // "user-123"
400
+ *
401
+ * // Clear when done
402
+ * yield* authCache.delete("upload-abc");
403
+ * });
404
+ * ```
405
+ */
406
+ declare class AuthCacheService extends AuthCacheService_base {}
407
+ /**
408
+ * Creates an AuthCacheService Layer with in-memory storage.
409
+ *
410
+ * @param config - Optional configuration for cache behavior
411
+ * @returns Effect Layer providing AuthCacheService
412
+ */
413
+ declare const AuthCacheServiceLive: (config?: AuthCacheConfig) => Layer.Layer<AuthCacheService>;
414
+ /**
415
+ * No-op implementation of AuthCacheService.
416
+ * Does not cache anything - all operations are no-ops.
417
+ * Used when caching is disabled or not needed.
418
+ */
419
+ declare const NoAuthCacheServiceLive: Layer.Layer<AuthCacheService>;
420
+ //#endregion
421
+ //#region src/core/types.d.ts
422
+ /**
423
+ * Function type for retrieving flows based on flow ID and client ID.
424
+ *
425
+ * This function is called by the core server when a flow needs to be executed.
426
+ * It should return an Effect that resolves to the requested Flow or fails with
427
+ * an UploadistaError if the flow is not found or not authorized.
428
+ *
429
+ * @param flowId - The unique identifier of the flow to retrieve
430
+ * @param clientId - The authenticated client ID (null if not authenticated)
431
+ * @returns Effect that produces the Flow or fails with an error
432
+ *
433
+ * @example
434
+ * ```typescript
435
+ * const flows: FlowsFunction = (flowId, clientId) =>
436
+ * Effect.gen(function* () {
437
+ * if (flowId === "image-resize") {
438
+ * return imageResizeFlow;
439
+ * }
440
+ * return yield* Effect.fail(
441
+ * new UploadistaError({ code: "FLOW_NOT_FOUND", status: 404 })
442
+ * );
443
+ * });
444
+ * ```
445
+ */
446
+ type FlowsFunction = (flowId: string, clientId: string | null) => Effect.Effect<Flow<z.ZodSchema<unknown>, z.ZodSchema<unknown>, unknown>, UploadistaError$1, unknown>;
447
+ /**
448
+ * Configuration for creating the unified Uploadista server.
449
+ *
450
+ * This configuration is framework-agnostic and contains all the business logic
451
+ * configuration. Framework-specific details are provided via the `adapter` field.
452
+ *
453
+ * @template TRequest - Framework-specific request type
454
+ * @template TResponse - Framework-specific response type
455
+ * @template TWebSocket - Framework-specific WebSocket type (optional)
456
+ *
457
+ * @example
458
+ * ```typescript
459
+ * import { createUploadistaServer, honoAdapter } from "@uploadista/server";
460
+ *
461
+ * const config: UploadistaServerConfig<Context, Context, WSEvents> = {
462
+ * // Core business logic configuration
463
+ * flows: getFlowById,
464
+ * dataStore: { type: "s3", config: { bucket: "my-bucket" } },
465
+ * kvStore: redisKvStore,
466
+ * baseUrl: "/uploadista",
467
+ *
468
+ * // Framework-specific adapter
469
+ * adapter: honoAdapter({
470
+ * authMiddleware: async (c) => {
471
+ * // Hono-specific auth logic
472
+ * return { clientId: "user-123" };
473
+ * },
474
+ * }),
475
+ * };
476
+ *
477
+ * const server = await createUploadistaServer(config);
478
+ * ```
479
+ */
480
+ interface UploadistaServerConfig<TRequest, TResponse, TWebSocket = unknown> {
481
+ /**
482
+ * Function for retrieving flows by ID.
483
+ *
484
+ * This function is called when a flow execution is requested.
485
+ * It receives the flow ID and client ID (from auth context) and should
486
+ * return an Effect that resolves to the Flow definition.
487
+ *
488
+ * @example
489
+ * ```typescript
490
+ * flows: (flowId, clientId) => Effect.succeed(myFlows[flowId])
491
+ * ```
492
+ */
493
+ flows: FlowsFunction;
494
+ /**
495
+ * Data store configuration for file storage.
496
+ *
497
+ * Specifies where uploaded files should be stored (S3, Azure, GCS, filesystem).
498
+ * The core server creates the appropriate data store layer from this configuration.
499
+ *
500
+ * @example
501
+ * ```typescript
502
+ * dataStore: {
503
+ * type: "s3",
504
+ * config: {
505
+ * bucket: "my-uploads",
506
+ * region: "us-east-1"
507
+ * }
508
+ * }
509
+ * ```
510
+ */
511
+ dataStore: DataStoreConfig;
512
+ /**
513
+ * Key-value store layer for metadata storage.
514
+ *
515
+ * Used for storing upload metadata, flow job state, and other persistent data.
516
+ * Can be Redis, Cloudflare KV, in-memory, or any implementation of BaseKvStoreService.
517
+ *
518
+ * @example
519
+ * ```typescript
520
+ * import { redisKvStore } from "@uploadista/kv-store-redis";
521
+ *
522
+ * kvStore: redisKvStore({ url: "redis://localhost:6379" })
523
+ * ```
524
+ */
525
+ kvStore: Layer.Layer<BaseKvStoreService>;
526
+ /**
527
+ * Optional: Plugins to extend functionality.
528
+ *
529
+ * Plugins are Effect layers that add additional capabilities to the upload
530
+ * and flow servers. They are merged into the server layer composition.
531
+ *
532
+ * @example
533
+ * ```typescript
534
+ * plugins: [imageProcessingPlugin, virusScanPlugin]
535
+ * ```
536
+ */
537
+ plugins?: readonly Layer.Layer<any, never, never>[];
538
+ /**
539
+ * Optional: Event emitter layer for progress notifications.
540
+ *
541
+ * Used to emit upload progress, flow status updates, and other events.
542
+ * Defaults to in-memory event emitter if not provided.
543
+ *
544
+ * @example
545
+ * ```typescript
546
+ * import { webSocketEventEmitter } from "@uploadista/event-emitter-websocket";
547
+ *
548
+ * eventEmitter: webSocketEventEmitter()
549
+ * ```
550
+ */
551
+ eventEmitter?: Layer.Layer<BaseEventEmitterService>;
552
+ /**
553
+ * Optional: Event broadcaster layer for real-time updates.
554
+ *
555
+ * Used to broadcast events to multiple subscribers (e.g., WebSocket connections).
556
+ * Defaults to in-memory broadcaster if not provided.
557
+ *
558
+ * @example
559
+ * ```typescript
560
+ * import { memoryEventBroadcaster } from "@uploadista/event-broadcaster-memory";
561
+ *
562
+ * eventBroadcaster: memoryEventBroadcaster()
563
+ * ```
564
+ */
565
+ eventBroadcaster?: Layer.Layer<EventBroadcasterService>;
566
+ /**
567
+ * Optional: Base URL path for Uploadista endpoints.
568
+ *
569
+ * All Uploadista routes will be prefixed with `{baseUrl}/api/`.
570
+ * For example, with baseUrl="/uploadista", routes become:
571
+ * - POST /uploadista/api/upload
572
+ * - POST /uploadista/api/flow/{flowId}/{storageId}
573
+ *
574
+ * @default "" (no prefix, routes start with /api/)
575
+ */
576
+ baseUrl?: string;
577
+ /**
578
+ * Optional: Custom ID generator layer.
579
+ *
580
+ * Used for generating upload IDs, job IDs, and other unique identifiers.
581
+ * Defaults to built-in ID generator if not provided.
582
+ *
583
+ * @example
584
+ * ```typescript
585
+ * import { nanoidGenerator } from "@uploadista/utils";
586
+ *
587
+ * generateId: nanoidGenerator()
588
+ * ```
589
+ */
590
+ generateId?: Layer.Layer<GenerateId>;
591
+ /**
592
+ * Optional: Enable distributed tracing with OpenTelemetry.
593
+ *
594
+ * When true, Effect programs run with OpenTelemetry tracing enabled,
595
+ * allowing observability into upload and flow execution.
596
+ *
597
+ * @default false
598
+ */
599
+ withTracing?: boolean;
600
+ /**
601
+ * Optional: Metrics layer for observability.
602
+ *
603
+ * Used to collect metrics about upload/flow performance, errors, and usage.
604
+ * Defaults to NoOp metrics if not provided.
605
+ *
606
+ * @example
607
+ * ```typescript
608
+ * import { prometheusMetrics } from "@uploadista/observability";
609
+ *
610
+ * metricsLayer: prometheusMetrics()
611
+ * ```
612
+ */
613
+ metricsLayer?: Layer.Layer<any, never, never>;
614
+ /**
615
+ * Optional: Buffered data store layer for performance optimization.
616
+ *
617
+ * Provides in-memory buffering for frequently accessed data,
618
+ * reducing latency for chunk uploads and reads.
619
+ *
620
+ * @example
621
+ * ```typescript
622
+ * import { bufferedDataStore } from "@uploadista/core/data-store";
623
+ *
624
+ * bufferedDataStore: bufferedDataStore({ maxSize: 1024 * 1024 * 10 })
625
+ * ```
626
+ */
627
+ bufferedDataStore?: Layer.Layer<UploadFileDataStore, never, UploadFileKVStore>;
628
+ /**
629
+ * Framework-specific adapter.
630
+ *
631
+ * The adapter provides the bridge between framework-specific request/response
632
+ * types and the standard types used by the core server. Each framework
633
+ * (Hono, Express, Fastify) has its own adapter implementation.
634
+ *
635
+ * @example
636
+ * ```typescript
637
+ * import { honoAdapter } from "@uploadista/adapters-hono";
638
+ *
639
+ * adapter: honoAdapter({
640
+ * authMiddleware: async (c) => ({ clientId: "user-123" })
641
+ * })
642
+ * ```
643
+ */
644
+ adapter: ServerAdapter<TRequest, TResponse, TWebSocket>;
645
+ /**
646
+ * Optional: Configuration for auth context caching.
647
+ *
648
+ * Caching allows subsequent requests (chunk uploads, flow continuations) to
649
+ * reuse the auth context from the initial request without re-authenticating.
650
+ *
651
+ * @example
652
+ * ```typescript
653
+ * authCacheConfig: {
654
+ * maxSize: 10000,
655
+ * ttl: 3600000 // 1 hour
656
+ * }
657
+ * ```
658
+ */
659
+ authCacheConfig?: AuthCacheConfig;
660
+ }
661
+ /**
662
+ * Return type from createUploadistaServer.
663
+ *
664
+ * Contains the handler function and exposed server layers for framework-specific routing.
665
+ *
666
+ * @template TRequest - Framework-specific request type
667
+ * @template TResponse - Framework-specific response type
668
+ * @template TWebSocket - Framework-specific WebSocket type (optional)
669
+ */
670
+ interface UploadistaServer<TRequest, TResponse, TWebSocketHandler = unknown> {
671
+ /**
672
+ * Main request handler that processes HTTP requests through the adapter.
673
+ */
674
+ handler: (req: TRequest) => Promise<TResponse>;
675
+ /**
676
+ * Optional WebSocket handler if the adapter supports WebSocket connections.
677
+ */
678
+ websocketHandler: TWebSocketHandler;
679
+ /**
680
+ * Base URL path for Uploadista endpoints.
681
+ */
682
+ baseUrl: string;
683
+ /**
684
+ * Dispose function for graceful shutdown.
685
+ * Cleans up all resources associated with the managed runtime.
686
+ * Should be called when the server is shutting down.
687
+ */
688
+ dispose: () => Promise<void>;
689
+ }
690
+ //#endregion
691
+ //#region src/core/server.d.ts
692
+ /**
693
+ * Creates the unified Uploadista server with framework-specific adapter.
694
+ *
695
+ * This function composes all layers (upload server, flow server, auth, metrics)
696
+ * and returns a handler that works with any framework via the provided adapter.
697
+ *
698
+ * The core server handles:
699
+ * - Route parsing and matching
700
+ * - Auth middleware execution with timeout protection
701
+ * - Layer composition (upload/flow servers, auth cache, metrics)
702
+ * - Error handling and response formatting
703
+ * - Effect program execution with optional tracing
704
+ *
705
+ * @param config - Server configuration including adapter and business logic
706
+ * @returns Object with handler function, optional WebSocket handler, and base URL
707
+ *
708
+ * @example
709
+ * ```typescript
710
+ * import { createUploadistaServer, honoAdapter } from "@uploadista/server";
711
+ *
712
+ * const server = await createUploadistaServer({
713
+ * flows: getFlowById,
714
+ * dataStore: { type: "s3", config: { bucket: "uploads" } },
715
+ * kvStore: redisKvStore,
716
+ * adapter: honoAdapter({
717
+ * authMiddleware: async (c) => ({ clientId: "user-123" })
718
+ * })
719
+ * });
720
+ *
721
+ * // Use with Hono
722
+ * app.all("/uploadista/*", server.handler);
723
+ * ```
724
+ */
725
+ declare const createUploadistaServer: <TContext, TResponse, TWebSocketHandler = unknown>({
726
+ flows,
727
+ dataStore,
728
+ kvStore,
729
+ plugins,
730
+ eventEmitter,
731
+ eventBroadcaster,
732
+ withTracing,
733
+ baseUrl: configBaseUrl,
734
+ generateId,
735
+ metricsLayer,
736
+ bufferedDataStore,
737
+ adapter,
738
+ authCacheConfig
739
+ }: UploadistaServerConfig<TContext, TResponse, TWebSocketHandler>) => Promise<UploadistaServer<TContext, TResponse, TWebSocketHandler>>;
740
+ //#endregion
741
+ //#region src/core/websocket-routes.d.ts
742
+ /**
743
+ * Framework-agnostic WebSocket connection interface
744
+ * Adapters should wrap their native WebSocket implementations to match this interface
745
+ */
746
+ type WebSocketConnection = {
747
+ id: string;
748
+ send: (data: string) => void;
749
+ close: (code?: number, reason?: string) => void;
750
+ readyState: number;
751
+ };
752
+ /**
753
+ * WebSocket event types for real-time communication
754
+ */
755
+ type WebSocketEventType = "subscribe-upload" | "subscribe-flow" | "unsubscribe-upload" | "unsubscribe-flow" | "ping" | "connection" | "upload-event" | "flow-event" | "error" | "invalid-path" | "auth-failed";
756
+ /**
757
+ * Base WebSocket event structure
758
+ */
759
+ type WebSocketEvent<T extends WebSocketEventType> = {
760
+ type: T;
761
+ };
762
+ /**
763
+ * Incoming WebSocket messages (client -> server)
764
+ */
765
+ type SubscribeUploadEvent = WebSocketEvent<"subscribe-upload"> & {
766
+ uploadId: string;
767
+ };
768
+ type SubscribeFlowEvent = WebSocketEvent<"subscribe-flow"> & {
769
+ jobId: string;
770
+ };
771
+ type UnsubscribeUploadEvent = WebSocketEvent<"unsubscribe-upload"> & {
772
+ uploadId: string;
773
+ };
774
+ type UnsubscribeFlowEvent = WebSocketEvent<"unsubscribe-flow"> & {
775
+ jobId: string;
776
+ };
777
+ type PingEvent = WebSocketEvent<"ping">;
778
+ type WebSocketIncomingEvent = SubscribeUploadEvent | SubscribeFlowEvent | UnsubscribeUploadEvent | UnsubscribeFlowEvent | PingEvent;
779
+ /**
780
+ * Outgoing WebSocket messages (server -> client)
781
+ */
782
+ type ConnectionEvent = WebSocketEvent<"connection"> & {
783
+ message: string;
784
+ id?: string;
785
+ jobId?: string;
786
+ uploadId?: string;
787
+ timestamp: string;
788
+ };
789
+ type UploadEventMessage = WebSocketEvent<"upload-event"> & {
790
+ uploadId: string;
791
+ event: UploadEvent;
792
+ timestamp: string;
793
+ };
794
+ type FlowEventMessage = WebSocketEvent<"flow-event"> & {
795
+ jobId: string;
796
+ event: unknown;
797
+ timestamp: string;
798
+ };
799
+ type ErrorEvent = WebSocketEvent<"error"> & {
800
+ message: string;
801
+ code?: string;
802
+ };
803
+ type InvalidPathEvent = WebSocketEvent<"invalid-path"> & {
804
+ message: string;
805
+ expectedPrefix: string;
806
+ };
807
+ type AuthFailedEvent = WebSocketEvent<"auth-failed"> & {
808
+ message: string;
809
+ authMethod: "token" | "cookies";
810
+ };
811
+ type WebSocketOutgoingEvent = ConnectionEvent | UploadEventMessage | FlowEventMessage | ErrorEvent | InvalidPathEvent | AuthFailedEvent;
812
+ /**
813
+ * WebSocket connection request with routing information
814
+ * Extracted from the WebSocket URL and query parameters
815
+ */
816
+ type WebSocketConnectionRequest = {
817
+ /** Base URL prefix for WebSocket connections */
818
+ baseUrl: string;
819
+ /** Full pathname from the URL */
820
+ pathname: string;
821
+ /** Parsed route segments after baseUrl/ws/ */
822
+ routeSegments: string[];
823
+ /** Whether this is an upload route */
824
+ isUploadRoute: boolean;
825
+ /** Whether this is a flow route */
826
+ isFlowRoute: boolean;
827
+ /** Job ID (for flows) */
828
+ jobId?: string;
829
+ /** Upload ID (for uploads) */
830
+ uploadId?: string;
831
+ /** Event ID (jobId or uploadId) */
832
+ eventId?: string;
833
+ /** WebSocket connection instance */
834
+ connection: WebSocketConnection;
835
+ };
836
+ //#endregion
837
+ //#region src/core/websocket-handlers/websocket-handlers.d.ts
838
+ /**
839
+ * Handles WebSocket connection opening
840
+ * Subscribes to the appropriate events based on the connection request
841
+ */
842
+ declare const handleWebSocketOpen: (request: WebSocketConnectionRequest, uploadServer: UploadServerShape, flowServer: FlowServerShape) => Effect.Effect<void, never, unknown>;
843
+ /**
844
+ * Handles incoming WebSocket messages
845
+ * Currently supports ping/pong for connection keep-alive
846
+ */
847
+ declare const handleWebSocketMessage: (message: string, connection: WebSocketConnection) => Effect.Effect<void, never, never>;
848
+ /**
849
+ * Handles WebSocket connection closing
850
+ * Unsubscribes from all events and cleans up resources
851
+ */
852
+ declare const handleWebSocketClose: (request: WebSocketConnectionRequest, uploadServer: UploadServerShape, flowServer: FlowServerShape) => Effect.Effect<void, never, unknown>;
853
+ /**
854
+ * Handles WebSocket errors
855
+ */
856
+ declare const handleWebSocketError: (error: unknown, eventId?: string) => Effect.Effect<void, never, never>;
857
+ //#endregion
858
+ //#region src/error-types.d.ts
859
+ /**
860
+ * Base adapter error class for HTTP adapters.
861
+ * All adapter-specific errors should extend this class or one of its subclasses.
862
+ *
863
+ * @example
864
+ * ```typescript
865
+ * throw new AdapterError("Something went wrong", 500, "INTERNAL_ERROR");
866
+ * ```
867
+ */
868
+ declare class AdapterError extends Error {
869
+ readonly statusCode: number;
870
+ readonly errorCode: string;
871
+ constructor(message: string, statusCode?: number, errorCode?: string);
872
+ }
873
+ /**
874
+ * Validation error - indicates invalid request data or parameters.
875
+ * Returns HTTP 400 Bad Request status.
876
+ *
877
+ * @example
878
+ * ```typescript
879
+ * if (!isValidUploadId(id)) {
880
+ * throw new ValidationError("Invalid upload ID format");
881
+ * }
882
+ * ```
883
+ */
884
+ declare class ValidationError extends AdapterError {
885
+ constructor(message: string);
886
+ }
887
+ /**
888
+ * Not found error - indicates a requested resource does not exist.
889
+ * Returns HTTP 404 Not Found status.
890
+ *
891
+ * @example
892
+ * ```typescript
893
+ * if (!upload) {
894
+ * throw new NotFoundError("Upload");
895
+ * }
896
+ * ```
897
+ */
898
+ declare class NotFoundError extends AdapterError {
899
+ constructor(resource: string);
900
+ }
901
+ /**
902
+ * Bad request error - indicates a malformed request.
903
+ * Returns HTTP 400 Bad Request status.
904
+ * Similar to ValidationError but for request structure issues.
905
+ *
906
+ * @example
907
+ * ```typescript
908
+ * try {
909
+ * const data = JSON.parse(body);
910
+ * } catch {
911
+ * throw new BadRequestError("Invalid JSON body");
912
+ * }
913
+ * ```
914
+ */
915
+ declare class BadRequestError extends AdapterError {
916
+ constructor(message: string);
917
+ }
918
+ /**
919
+ * Creates a standardized error response object for AdapterError.
920
+ * Includes error message, error code, and ISO timestamp.
921
+ *
922
+ * @param error - The AdapterError to format
923
+ * @returns Standardized error response body
924
+ *
925
+ * @example
926
+ * ```typescript
927
+ * import { createErrorResponseBody } from "@uploadista/server";
928
+ *
929
+ * try {
930
+ * // ... operation
931
+ * } catch (err) {
932
+ * const errorResponse = createErrorResponseBody(err);
933
+ * res.status(err.statusCode).json(errorResponse);
934
+ * }
935
+ * ```
936
+ */
937
+ declare const createErrorResponseBody: (error: AdapterError) => {
938
+ error: string;
939
+ code: string;
940
+ timestamp: string;
941
+ };
942
+ /**
943
+ * Creates a standardized error response body from UploadistaError.
944
+ * Formats core library errors for HTTP responses with optional details.
945
+ *
946
+ * @param error - The UploadistaError to format
947
+ * @returns Standardized error response body with error, code, timestamp, and optional details
948
+ *
949
+ * @example
950
+ * ```typescript
951
+ * import { createUploadistaErrorResponseBody } from "@uploadista/server";
952
+ *
953
+ * try {
954
+ * const result = yield* uploadServer.handleUpload(input);
955
+ * } catch (err) {
956
+ * if (err instanceof UploadistaError) {
957
+ * const errorResponse = createUploadistaErrorResponseBody(err);
958
+ * res.status(400).json(errorResponse);
959
+ * }
960
+ * }
961
+ * ```
962
+ */
963
+ declare const createUploadistaErrorResponseBody: (error: UploadistaError) => {
964
+ error: string;
965
+ code: string;
966
+ timestamp: string;
967
+ details?: unknown;
968
+ };
969
+ /**
970
+ * Creates a generic error response body for unknown/unexpected errors.
971
+ * Used as a fallback when error type cannot be determined.
972
+ *
973
+ * @param message - Error message to include in response (defaults to "Internal server error")
974
+ * @returns Standardized error response body with generic INTERNAL_ERROR code
975
+ *
976
+ * @example
977
+ * ```typescript
978
+ * import { createGenericErrorResponseBody } from "@uploadista/server";
979
+ *
980
+ * try {
981
+ * // ... operation
982
+ * } catch (err) {
983
+ * const errorResponse = createGenericErrorResponseBody(
984
+ * err instanceof Error ? err.message : "Unknown error"
985
+ * );
986
+ * res.status(500).json(errorResponse);
987
+ * }
988
+ * ```
989
+ */
990
+ declare const createGenericErrorResponseBody: (message?: string) => {
991
+ error: string;
992
+ code: string;
993
+ timestamp: string;
994
+ };
995
+ //#endregion
996
+ //#region src/http-utils.d.ts
997
+ /**
998
+ * Shared HTTP utilities for server adapters
999
+ *
1000
+ * This module provides routing and error handling utilities used across
1001
+ * Hono, Express, and Fastify adapters for request parsing and response formatting.
1002
+ */
1003
+ /**
1004
+ * Parses URL segments from a pathname, filtering out empty segments.
1005
+ * Useful for extracting route components from request paths.
1006
+ *
1007
+ * @param pathname - The URL pathname (e.g., "/uploadista/api/upload/abc123")
1008
+ * @returns Array of non-empty path segments
1009
+ *
1010
+ * @example
1011
+ * ```typescript
1012
+ * const segments = parseUrlSegments("/uploadista/api/upload/abc123");
1013
+ * // => ["uploadista", "api", "upload", "abc123"]
1014
+ * ```
1015
+ */
1016
+ declare const parseUrlSegments: (pathname: string) => string[];
1017
+ /**
1018
+ * Extracts the last segment from a URL pathname.
1019
+ *
1020
+ * @param pathname - The URL pathname to parse
1021
+ * @returns The last non-empty segment, or undefined if none exists
1022
+ *
1023
+ * @example
1024
+ * ```typescript
1025
+ * const id = getLastSegment("/uploadista/api/upload/abc123");
1026
+ * // => "abc123"
1027
+ * ```
1028
+ */
1029
+ declare const getLastSegment: (pathname: string) => string | undefined;
1030
+ /**
1031
+ * Checks if a pathname includes a specific base path and API prefix.
1032
+ * Used to determine if a request should be handled by the Uploadista adapter.
1033
+ *
1034
+ * @param pathname - The request pathname
1035
+ * @param basePath - The base path configured for the adapter (e.g., "uploadista")
1036
+ * @returns true if the path includes `{basePath}/api/`
1037
+ *
1038
+ * @example
1039
+ * ```typescript
1040
+ * const isUploadistaPath = hasBasePath("/uploadista/api/upload", "uploadista");
1041
+ * // => true
1042
+ * ```
1043
+ */
1044
+ declare const hasBasePath: (pathname: string, basePath: string) => boolean;
1045
+ /**
1046
+ * Removes the base path prefix and returns clean route segments.
1047
+ * Transforms "/uploadista/api/upload/abc123" → ["upload", "abc123"]
1048
+ *
1049
+ * @param pathname - The full request pathname
1050
+ * @param basePath - The base path to remove (e.g., "uploadista")
1051
+ * @returns Array of route segments without base path prefix
1052
+ *
1053
+ * @example
1054
+ * ```typescript
1055
+ * const route = getRouteSegments("/uploadista/api/upload/abc123", "uploadista");
1056
+ * // => ["upload", "abc123"]
1057
+ * ```
1058
+ */
1059
+ declare const getRouteSegments: (pathname: string, basePath: string) => string[];
1060
+ /**
1061
+ * Standard error handler for flow and job operations.
1062
+ * Maps application errors to appropriate HTTP status codes and error formats.
1063
+ *
1064
+ * Supports errors with `code`, `message`, `status`, and `details` properties.
1065
+ * Maps error codes to HTTP status codes (e.g., NOT_FOUND → 404, VALIDATION_ERROR → 400).
1066
+ *
1067
+ * @param error - The error object to handle (can be any type)
1068
+ * @returns Standardized error response with status, code, message, and optional details
1069
+ *
1070
+ * @example
1071
+ * ```typescript
1072
+ * import { handleFlowError } from "@uploadista/server";
1073
+ *
1074
+ * const response = handleFlowError({
1075
+ * code: "FLOW_JOB_NOT_FOUND",
1076
+ * message: "Job not found",
1077
+ * });
1078
+ * // => { status: 404, code: "FLOW_JOB_NOT_FOUND", message: "Job not found" }
1079
+ * ```
1080
+ */
1081
+ declare const handleFlowError: (error: unknown) => {
1082
+ status: number;
1083
+ code: string;
1084
+ message: string;
1085
+ details?: unknown;
1086
+ };
1087
+ /**
1088
+ * Extracts job ID from URL segments for job status endpoint.
1089
+ * Expected URL format: `/uploadista/api/jobs/:jobId/status`
1090
+ *
1091
+ * @param urlSegments - Parsed URL segments (without base path)
1092
+ * @returns The job ID if found, or undefined
1093
+ *
1094
+ * @example
1095
+ * ```typescript
1096
+ * const jobId = extractJobIdFromStatus(["jobs", "job-123", "status"]);
1097
+ * // => "job-123"
1098
+ * ```
1099
+ */
1100
+ declare const extractJobIdFromStatus: (urlSegments: string[]) => string | undefined;
1101
+ /**
1102
+ * Extracts job ID and node ID from URL segments for resume flow endpoint.
1103
+ * Expected URL format: `/uploadista/api/jobs/:jobId/resume/:nodeId`
1104
+ *
1105
+ * @param urlSegments - Parsed URL segments (without base path)
1106
+ * @returns Object with extracted jobId and nodeId (either can be undefined if not found)
1107
+ *
1108
+ * @example
1109
+ * ```typescript
1110
+ * const { jobId, nodeId } = extractJobAndNodeId([
1111
+ * "jobs",
1112
+ * "job-123",
1113
+ * "resume",
1114
+ * "node-456",
1115
+ * ]);
1116
+ * // => { jobId: "job-123", nodeId: "node-456" }
1117
+ * ```
1118
+ */
1119
+ declare const extractJobAndNodeId: (urlSegments: string[]) => {
1120
+ jobId: string | undefined;
1121
+ nodeId: string | undefined;
1122
+ };
1123
+ /**
1124
+ * Extracts flow ID and storage ID from URL segments.
1125
+ * Expected URL format: `/uploadista/api/flow/:flowId/:storageId`
1126
+ *
1127
+ * Mutates the input array (removes last 2 elements).
1128
+ *
1129
+ * @param urlSegments - Parsed URL segments (will be mutated)
1130
+ * @returns Object with extracted flowId and storageId
1131
+ *
1132
+ * @example
1133
+ * ```typescript
1134
+ * const segments = ["flow", "flow-123", "storage-456"];
1135
+ * const { flowId, storageId } = extractFlowAndStorageId(segments);
1136
+ * // => { flowId: "flow-123", storageId: "storage-456" }
1137
+ * // segments is now ["flow"]
1138
+ * ```
1139
+ */
1140
+ declare const extractFlowAndStorageId: (urlSegments: string[]) => {
1141
+ flowId: string | undefined;
1142
+ storageId: string | undefined;
1143
+ };
1144
+ //#endregion
1145
+ //#region src/layer-utils.d.ts
1146
+ /**
1147
+ * Configuration for creating upload server layers.
1148
+ * Specifies all dependencies needed by the upload server Effect Layer.
1149
+ *
1150
+ * @property kvStore - Key-value store for upload metadata
1151
+ * @property eventEmitter - Event emitter for upload progress events
1152
+ * @property dataStore - File data storage implementation
1153
+ * @property bufferedDataStore - Optional buffered storage for performance optimization
1154
+ * @property generateId - Optional custom ID generator (uses default if omitted)
1155
+ *
1156
+ * @example
1157
+ * ```typescript
1158
+ * import { createUploadServerLayer } from "@uploadista/server";
1159
+ *
1160
+ * const uploadLayerConfig: UploadServerLayerConfig = {
1161
+ * kvStore: redisKvStore,
1162
+ * eventEmitter: webSocketEventEmitter,
1163
+ * dataStore: s3DataStore,
1164
+ * };
1165
+ * ```
1166
+ */
1167
+ interface UploadServerLayerConfig {
1168
+ kvStore: Layer.Layer<BaseKvStoreService>;
1169
+ eventEmitter: Layer.Layer<BaseEventEmitterService>;
1170
+ dataStore: Layer.Layer<UploadFileDataStores, never, UploadFileKVStore>;
1171
+ bufferedDataStore?: Layer.Layer<UploadFileDataStore, never, UploadFileKVStore>;
1172
+ generateId?: Layer.Layer<GenerateId>;
1173
+ }
1174
+ /**
1175
+ * Configuration for creating flow server layers.
1176
+ * Specifies all dependencies needed by the flow processing server.
1177
+ *
1178
+ * @property kvStore - Key-value store for flow job metadata
1179
+ * @property eventEmitter - Event emitter for flow progress events
1180
+ * @property flowProvider - Factory function for creating flows
1181
+ * @property uploadServer - Upload server layer (used by flows for uploads)
1182
+ *
1183
+ * @example
1184
+ * ```typescript
1185
+ * import { createFlowServerLayer } from "@uploadista/server";
1186
+ *
1187
+ * const flowLayerConfig: FlowServerLayerConfig = {
1188
+ * kvStore: redisKvStore,
1189
+ * eventEmitter: webSocketEventEmitter,
1190
+ * flowProvider: createFlowsEffect,
1191
+ * uploadServer: uploadServerLayer,
1192
+ * };
1193
+ * ```
1194
+ */
1195
+ interface FlowServerLayerConfig {
1196
+ kvStore: Layer.Layer<BaseKvStoreService>;
1197
+ eventEmitter: Layer.Layer<BaseEventEmitterService>;
1198
+ flowProvider: Layer.Layer<FlowProvider>;
1199
+ uploadServer: Layer.Layer<UploadServer>;
1200
+ }
1201
+ /**
1202
+ * Creates the upload server layer with all dependencies composed.
1203
+ * This layer handles file uploads with chunked transfer, resumption, and metadata tracking.
1204
+ *
1205
+ * The created layer includes:
1206
+ * - Upload KV store (metadata tracking)
1207
+ * - Data store (file storage)
1208
+ * - Event emitter (progress notifications)
1209
+ * - Optional buffered data store (performance optimization)
1210
+ * - Optional custom ID generator
1211
+ *
1212
+ * @param config - Upload server layer configuration
1213
+ * @returns Effect Layer providing UploadServer
1214
+ *
1215
+ * @example
1216
+ * ```typescript
1217
+ * import { createUploadServerLayer } from "@uploadista/server";
1218
+ * import { Layer } from "effect";
1219
+ *
1220
+ * const uploadServerLayer = createUploadServerLayer({
1221
+ * kvStore: redisKvStore,
1222
+ * eventEmitter: webSocketEventEmitter,
1223
+ * dataStore: s3DataStore,
1224
+ * });
1225
+ *
1226
+ * // Use in application
1227
+ * const app = Layer.provide(appLogic, uploadServerLayer);
1228
+ * ```
1229
+ */
1230
+ declare const createUploadServerLayer: ({
1231
+ kvStore,
1232
+ eventEmitter,
1233
+ dataStore,
1234
+ bufferedDataStore,
1235
+ generateId
1236
+ }: UploadServerLayerConfig) => Layer.Layer<unknown, unknown, any>;
1237
+ /**
1238
+ * Creates the flow server layer with all dependencies composed.
1239
+ * This layer handles file processing workflows with multi-stage pipelines.
1240
+ *
1241
+ * The created layer includes:
1242
+ * - Flow job KV store (job metadata and state)
1243
+ * - Event emitter (progress notifications)
1244
+ * - Flow provider (flow definitions)
1245
+ * - Upload server (for uploads within flows)
1246
+ *
1247
+ * @param config - Flow server layer configuration
1248
+ * @returns Effect Layer providing FlowServer
1249
+ *
1250
+ * @example
1251
+ * ```typescript
1252
+ * import { createFlowServerLayer } from "@uploadista/server";
1253
+ * import { Layer } from "effect";
1254
+ *
1255
+ * const flowServerLayer = createFlowServerLayer({
1256
+ * kvStore: redisKvStore,
1257
+ * eventEmitter: webSocketEventEmitter,
1258
+ * flowProvider: createFlowsEffect,
1259
+ * uploadServer: uploadServerLayer,
1260
+ * });
1261
+ *
1262
+ * // Use in application
1263
+ * const app = Layer.provide(appLogic, flowServerLayer);
1264
+ * ```
1265
+ */
1266
+ declare const createFlowServerLayer: ({
1267
+ kvStore,
1268
+ eventEmitter,
1269
+ flowProvider,
1270
+ uploadServer
1271
+ }: FlowServerLayerConfig) => Layer.Layer<unknown, unknown, any>;
1272
+ //#endregion
1273
+ //#region src/plugins-typing.d.ts
1274
+ type LayerSuccessUnion<Layers extends readonly Layer.Layer<any, never, never>[]> = Layers[number] extends Layer.Layer<infer Success, never, never> ? Success : never;
1275
+ 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;
1276
+ type FlowRequirementsOf<TFlows extends (flowId: string, clientId: string | null) => Effect.Effect<unknown, unknown, unknown>> = FlowSuccess<TFlows> extends Flow$1<z$1.ZodSchema<unknown>, z$1.ZodSchema<unknown>, infer R> ? Exclude<R, UploadServer$1> : never;
1277
+ type RequiredPluginsOf<TFlows extends (flowId: string, clientId: string | null) => Effect.Effect<unknown, unknown, unknown>> = Exclude<FlowRequirementsOf<TFlows>, UploadServer$1>;
1278
+ 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 : {
1279
+ __missingPlugins: Exclude<RequiredPluginsOf<TFlows>, LayerSuccessUnion<TPlugins>>;
1280
+ };
1281
+ //#endregion
1282
+ //#region src/service.d.ts
1283
+ declare const AuthContextService_base: Context.TagClass<AuthContextService, "AuthContextService", {
1284
+ /**
1285
+ * Get the current client ID from auth context.
1286
+ * Returns null if no authentication context is available.
1287
+ */
1288
+ readonly getClientId: () => Effect.Effect<string | null>;
1289
+ /**
1290
+ * Get the current auth metadata.
1291
+ * Returns empty object if no authentication context or no metadata.
1292
+ */
1293
+ readonly getMetadata: () => Effect.Effect<Record<string, unknown>>;
1294
+ /**
1295
+ * Check if the current client has a specific permission.
1296
+ * Returns false if no authentication context or permission not found.
1297
+ */
1298
+ readonly hasPermission: (permission: string) => Effect.Effect<boolean>;
1299
+ /**
1300
+ * Get the full authentication context if available.
1301
+ * Returns null if no authentication context is available.
1302
+ */
1303
+ readonly getAuthContext: () => Effect.Effect<AuthContext | null>;
1304
+ }>;
1305
+ /**
1306
+ * Authentication Context Service
1307
+ *
1308
+ * Provides access to the current authentication context throughout
1309
+ * the upload and flow processing pipeline. The service is provided
1310
+ * via Effect Layer and can be accessed using Effect.service().
1311
+ *
1312
+ * @example
1313
+ * ```typescript
1314
+ * import { Effect } from "effect";
1315
+ * import { AuthContextService } from "@uploadista/server";
1316
+ *
1317
+ * const uploadHandler = Effect.gen(function* () {
1318
+ * const authService = yield* AuthContextService;
1319
+ * const clientId = yield* authService.getClientId();
1320
+ * if (clientId) {
1321
+ * console.log(`Processing upload for client: ${clientId}`);
1322
+ * }
1323
+ * });
1324
+ * ```
1325
+ */
1326
+ declare class AuthContextService extends AuthContextService_base {}
1327
+ /**
1328
+ * Creates an AuthContextService Layer from an AuthContext.
1329
+ * This is typically called by adapters after successful authentication.
1330
+ *
1331
+ * @param authContext - The authentication context from middleware
1332
+ * @returns Effect Layer providing AuthContextService
1333
+ */
1334
+ declare const AuthContextServiceLive: (authContext: AuthContext | null) => Layer.Layer<AuthContextService>;
1335
+ /**
1336
+ * No-auth implementation of AuthContextService.
1337
+ * Returns null/empty values for all operations.
1338
+ * Used when no authentication middleware is configured (backward compatibility).
1339
+ */
1340
+ declare const NoAuthContextServiceLive: Layer.Layer<AuthContextService>;
1341
+ //#endregion
1342
+ 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 };
1343
+ //# sourceMappingURL=index.d.mts.map