@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.
- package/CHANGELOG.md +69 -0
- package/dist/auth/index.d.mts +2 -0
- package/dist/auth/index.mjs +1 -0
- package/dist/{auth-C77S4vQd.js → auth-BqArZeGK.mjs} +1 -1
- package/dist/auth-BqArZeGK.mjs.map +1 -0
- package/dist/{index-CvDNB1lJ.d.ts → index--Lny6VJP.d.mts} +1 -1
- package/dist/index--Lny6VJP.d.mts.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +735 -12
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +1343 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +2 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +10 -7
- package/src/adapter/index.ts +10 -0
- package/src/adapter/types.ts +229 -0
- package/src/core/http-handlers/flow-http-handlers.ts +245 -0
- package/src/core/http-handlers/http-handlers.ts +72 -0
- package/src/core/http-handlers/upload-http-handlers.ts +168 -0
- package/src/core/index.ts +12 -0
- package/src/core/routes.ts +188 -0
- package/src/core/server.ts +327 -0
- package/src/core/types.ts +322 -0
- package/src/core/websocket-handlers/flow-websocket-handlers.ts +47 -0
- package/src/core/websocket-handlers/upload-websocket-handlers.ts +47 -0
- package/src/core/websocket-handlers/websocket-handlers.ts +151 -0
- package/src/core/websocket-routes.ts +136 -0
- package/src/index.ts +2 -0
- package/dist/auth/index.d.ts +0 -2
- package/dist/auth/index.js +0 -1
- package/dist/auth-C77S4vQd.js.map +0 -1
- package/dist/index-CvDNB1lJ.d.ts.map +0 -1
- package/dist/index.d.ts +0 -620
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -2
- package/dist/index.js.map +0 -1
package/dist/index.d.mts
ADDED
|
@@ -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
|