@uploadista/server 0.0.20-beta.7 → 0.0.20-beta.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/README.md +226 -375
- package/dist/index.cjs +2 -2
- package/dist/index.d.cts +31 -31
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +31 -31
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +12 -12
- package/src/adapter/types.ts +3 -3
- package/src/core/http-handlers/flow-http-handlers.ts +13 -13
- package/src/core/http-handlers/upload-http-handlers.ts +16 -9
- package/src/core/plugin-types.ts +2 -2
- package/src/core/server.ts +6 -6
- package/src/core/websocket-handlers/flow-websocket-handlers.ts +5 -5
- package/src/core/websocket-handlers/upload-websocket-handlers.ts +5 -5
- package/src/core/websocket-handlers/websocket-handlers.ts +10 -10
- package/src/error-types.ts +1 -1
- package/src/layer-utils.ts +24 -24
- package/src/plugins-typing.ts +4 -4
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uploadista/server",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.20-beta.
|
|
4
|
+
"version": "0.0.20-beta.9",
|
|
5
5
|
"description": "Core Server package for Uploadista",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "Uploadista",
|
|
@@ -20,23 +20,23 @@
|
|
|
20
20
|
}
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@uploadista/core": "0.0.20-beta.
|
|
24
|
-
"@uploadista/
|
|
25
|
-
"@uploadista/event-
|
|
26
|
-
"@uploadista/
|
|
23
|
+
"@uploadista/core": "0.0.20-beta.9",
|
|
24
|
+
"@uploadista/observability": "0.0.20-beta.9",
|
|
25
|
+
"@uploadista/event-broadcaster-memory": "0.0.20-beta.9",
|
|
26
|
+
"@uploadista/event-emitter-websocket": "0.0.20-beta.9"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"@cloudflare/workers-types": "4.
|
|
29
|
+
"@cloudflare/workers-types": "4.20251213.0",
|
|
30
30
|
"@effect/vitest": "0.27.0",
|
|
31
31
|
"@types/express": "^5.0.0",
|
|
32
|
-
"@types/node": "24.10.
|
|
33
|
-
"effect": "3.19.
|
|
32
|
+
"@types/node": "24.10.4",
|
|
33
|
+
"effect": "3.19.12",
|
|
34
34
|
"tsd": "0.33.0",
|
|
35
|
-
"tsdown": "0.
|
|
35
|
+
"tsdown": "0.18.0",
|
|
36
36
|
"typescript": "5.9.3",
|
|
37
37
|
"vitest": "4.0.15",
|
|
38
|
-
"zod": "4.
|
|
39
|
-
"@uploadista/typescript-config": "0.0.20-beta.
|
|
38
|
+
"zod": "4.2.0",
|
|
39
|
+
"@uploadista/typescript-config": "0.0.20-beta.9"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
42
|
"effect": "^3.0.0",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"zod": "^4.0.0"
|
|
46
46
|
},
|
|
47
47
|
"scripts": {
|
|
48
|
-
"build": "tsdown",
|
|
48
|
+
"build": "tsc --noEmit && tsdown",
|
|
49
49
|
"format": "biome format --write ./src",
|
|
50
50
|
"lint": "biome lint --write ./src",
|
|
51
51
|
"check": "biome check --write ./src",
|
package/src/adapter/types.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { FlowEngine, UploadEngine } from "@uploadista/core";
|
|
2
2
|
import type { Effect } from "effect";
|
|
3
3
|
import type { UploadistaRequest, UploadistaResponse } from "../core/routes";
|
|
4
4
|
import type { AuthResult } from "../types";
|
|
@@ -200,12 +200,12 @@ export interface ServerAdapter<
|
|
|
200
200
|
*
|
|
201
201
|
* @param ws - Framework-specific WebSocket object
|
|
202
202
|
* @param ctx - Framework-specific context object (for initial handshake)
|
|
203
|
-
* @param context - Server context with baseUrl,
|
|
203
|
+
* @param context - Server context with baseUrl, uploadEngine, and flowServer
|
|
204
204
|
* @returns WebSocketHandler with callbacks for message, close, and error events
|
|
205
205
|
*/
|
|
206
206
|
webSocketHandler(context: {
|
|
207
207
|
baseUrl: string;
|
|
208
|
-
}): Effect.Effect<TWebSocketHandler, never,
|
|
208
|
+
}): Effect.Effect<TWebSocketHandler, never, UploadEngine | FlowEngine>;
|
|
209
209
|
|
|
210
210
|
/**
|
|
211
211
|
* Optional: Extract waitUntil callback from the framework context.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { FlowEngine } from "@uploadista/core/flow";
|
|
2
2
|
import { Effect } from "effect";
|
|
3
3
|
import { AuthCacheService } from "../../cache";
|
|
4
4
|
import { QuotaExceededError } from "../../permissions/errors";
|
|
@@ -22,7 +22,7 @@ import type {
|
|
|
22
22
|
|
|
23
23
|
export const handleGetFlow = ({ flowId }: GetFlowRequest) => {
|
|
24
24
|
return Effect.gen(function* () {
|
|
25
|
-
const
|
|
25
|
+
const flowEngine = yield* FlowEngine;
|
|
26
26
|
const authService = yield* AuthContextService;
|
|
27
27
|
const clientId = yield* authService.getClientId();
|
|
28
28
|
|
|
@@ -35,7 +35,7 @@ export const handleGetFlow = ({ flowId }: GetFlowRequest) => {
|
|
|
35
35
|
);
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
const flowData = yield*
|
|
38
|
+
const flowData = yield* flowEngine.getFlowData(flowId, clientId);
|
|
39
39
|
|
|
40
40
|
return {
|
|
41
41
|
status: 200,
|
|
@@ -50,7 +50,7 @@ export const handleRunFlow = <TRequirements>({
|
|
|
50
50
|
inputs,
|
|
51
51
|
}: RunFlowRequest) => {
|
|
52
52
|
return Effect.gen(function* () {
|
|
53
|
-
const
|
|
53
|
+
const flowEngine = yield* FlowEngine;
|
|
54
54
|
const authService = yield* AuthContextService;
|
|
55
55
|
const authCache = yield* AuthCacheService;
|
|
56
56
|
const usageHookService = yield* UsageHookService;
|
|
@@ -96,7 +96,7 @@ export const handleRunFlow = <TRequirements>({
|
|
|
96
96
|
// Run flow returns immediately with jobId
|
|
97
97
|
const startTime = Date.now();
|
|
98
98
|
yield* Effect.logInfo(`[Flow] Calling flowServer.runFlow...`);
|
|
99
|
-
const result = yield*
|
|
99
|
+
const result = yield* flowEngine
|
|
100
100
|
.runFlow<TRequirements>({
|
|
101
101
|
flowId,
|
|
102
102
|
storageId,
|
|
@@ -133,7 +133,7 @@ export const handleRunFlow = <TRequirements>({
|
|
|
133
133
|
|
|
134
134
|
export const handleJobStatus = ({ jobId }: GetJobStatusRequest) => {
|
|
135
135
|
return Effect.gen(function* () {
|
|
136
|
-
const
|
|
136
|
+
const flowEngine = yield* FlowEngine;
|
|
137
137
|
const authService = yield* AuthContextService;
|
|
138
138
|
const authCache = yield* AuthCacheService;
|
|
139
139
|
const clientId = yield* authService.getClientId();
|
|
@@ -151,7 +151,7 @@ export const handleJobStatus = ({ jobId }: GetJobStatusRequest) => {
|
|
|
151
151
|
);
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
-
const result = yield*
|
|
154
|
+
const result = yield* flowEngine.getJobStatus(jobId);
|
|
155
155
|
|
|
156
156
|
// Clear cache if flow is completed or failed
|
|
157
157
|
if (result.status === "completed" || result.status === "failed") {
|
|
@@ -176,7 +176,7 @@ export const handleResumeFlow = <TRequirements>({
|
|
|
176
176
|
newData,
|
|
177
177
|
}: ResumeFlowRequest) => {
|
|
178
178
|
return Effect.gen(function* () {
|
|
179
|
-
const
|
|
179
|
+
const flowEngine = yield* FlowEngine;
|
|
180
180
|
const authService = yield* AuthContextService;
|
|
181
181
|
const authCache = yield* AuthCacheService;
|
|
182
182
|
|
|
@@ -200,7 +200,7 @@ export const handleResumeFlow = <TRequirements>({
|
|
|
200
200
|
throw new Error("Missing newData");
|
|
201
201
|
}
|
|
202
202
|
|
|
203
|
-
const result = yield*
|
|
203
|
+
const result = yield* flowEngine.resumeFlow<TRequirements>({
|
|
204
204
|
jobId,
|
|
205
205
|
nodeId,
|
|
206
206
|
newData,
|
|
@@ -226,7 +226,7 @@ export const handleResumeFlow = <TRequirements>({
|
|
|
226
226
|
|
|
227
227
|
export const handlePauseFlow = ({ jobId }: PauseFlowRequest) => {
|
|
228
228
|
return Effect.gen(function* () {
|
|
229
|
-
const
|
|
229
|
+
const flowEngine = yield* FlowEngine;
|
|
230
230
|
const authService = yield* AuthContextService;
|
|
231
231
|
const authCache = yield* AuthCacheService;
|
|
232
232
|
|
|
@@ -246,7 +246,7 @@ export const handlePauseFlow = ({ jobId }: PauseFlowRequest) => {
|
|
|
246
246
|
);
|
|
247
247
|
}
|
|
248
248
|
|
|
249
|
-
const result = yield*
|
|
249
|
+
const result = yield* flowEngine.pauseFlow(jobId, clientId);
|
|
250
250
|
|
|
251
251
|
if (clientId) {
|
|
252
252
|
yield* Effect.logInfo(
|
|
@@ -263,7 +263,7 @@ export const handlePauseFlow = ({ jobId }: PauseFlowRequest) => {
|
|
|
263
263
|
|
|
264
264
|
export const handleCancelFlow = ({ jobId }: CancelFlowRequest) => {
|
|
265
265
|
return Effect.gen(function* () {
|
|
266
|
-
const
|
|
266
|
+
const flowEngine = yield* FlowEngine;
|
|
267
267
|
const authService = yield* AuthContextService;
|
|
268
268
|
const authCache = yield* AuthCacheService;
|
|
269
269
|
const usageHookService = yield* UsageHookService;
|
|
@@ -288,7 +288,7 @@ export const handleCancelFlow = ({ jobId }: CancelFlowRequest) => {
|
|
|
288
288
|
);
|
|
289
289
|
}
|
|
290
290
|
|
|
291
|
-
const result = yield*
|
|
291
|
+
const result = yield* flowEngine.cancelFlow(jobId, clientId);
|
|
292
292
|
|
|
293
293
|
// Clear cache since flow is cancelled
|
|
294
294
|
yield* authCache.delete(jobId);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { inputFileSchema } from "@uploadista/core/types";
|
|
2
|
-
import {
|
|
2
|
+
import { UploadEngine } from "@uploadista/core/upload";
|
|
3
3
|
import { isSupportedAlgorithm } from "@uploadista/core/utils";
|
|
4
4
|
import { MetricsService } from "@uploadista/observability";
|
|
5
5
|
import { Effect } from "effect";
|
|
@@ -22,7 +22,7 @@ import type {
|
|
|
22
22
|
|
|
23
23
|
export const handleCreateUpload = (req: CreateUploadRequest) =>
|
|
24
24
|
Effect.gen(function* () {
|
|
25
|
-
const
|
|
25
|
+
const uploadEngine = yield* UploadEngine;
|
|
26
26
|
const authService = yield* AuthContextService;
|
|
27
27
|
const authCache = yield* AuthCacheService;
|
|
28
28
|
const usageHookService = yield* UsageHookService;
|
|
@@ -79,7 +79,7 @@ export const handleCreateUpload = (req: CreateUploadRequest) =>
|
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
const fileCreated = yield*
|
|
82
|
+
const fileCreated = yield* uploadEngine.createUpload(
|
|
83
83
|
parsedInputFile.data,
|
|
84
84
|
clientId,
|
|
85
85
|
);
|
|
@@ -104,14 +104,17 @@ export const handleCreateUpload = (req: CreateUploadRequest) =>
|
|
|
104
104
|
|
|
105
105
|
export const handleGetCapabilities = ({ storageId }: GetCapabilitiesRequest) =>
|
|
106
106
|
Effect.gen(function* () {
|
|
107
|
-
const
|
|
107
|
+
const uploadEngine = yield* UploadEngine;
|
|
108
108
|
const authService = yield* AuthContextService;
|
|
109
109
|
const clientId = yield* authService.getClientId();
|
|
110
110
|
|
|
111
111
|
// Check permission for reading upload capabilities
|
|
112
112
|
yield* authService.requirePermission(PERMISSIONS.UPLOAD.READ);
|
|
113
113
|
|
|
114
|
-
const capabilities = yield*
|
|
114
|
+
const capabilities = yield* uploadEngine.getCapabilities(
|
|
115
|
+
storageId,
|
|
116
|
+
clientId,
|
|
117
|
+
);
|
|
115
118
|
|
|
116
119
|
return {
|
|
117
120
|
status: 200,
|
|
@@ -125,13 +128,13 @@ export const handleGetCapabilities = ({ storageId }: GetCapabilitiesRequest) =>
|
|
|
125
128
|
|
|
126
129
|
export const handleGetUpload = ({ uploadId }: GetUploadRequest) =>
|
|
127
130
|
Effect.gen(function* () {
|
|
128
|
-
const
|
|
131
|
+
const uploadEngine = yield* UploadEngine;
|
|
129
132
|
const authService = yield* AuthContextService;
|
|
130
133
|
|
|
131
134
|
// Check permission for reading upload status
|
|
132
135
|
yield* authService.requirePermission(PERMISSIONS.UPLOAD.READ);
|
|
133
136
|
|
|
134
|
-
const fileResult = yield*
|
|
137
|
+
const fileResult = yield* uploadEngine.getUpload(uploadId);
|
|
135
138
|
|
|
136
139
|
return {
|
|
137
140
|
status: 200,
|
|
@@ -141,7 +144,7 @@ export const handleGetUpload = ({ uploadId }: GetUploadRequest) =>
|
|
|
141
144
|
|
|
142
145
|
export const handleUploadChunk = (req: UploadChunkRequest) =>
|
|
143
146
|
Effect.gen(function* () {
|
|
144
|
-
const
|
|
147
|
+
const uploadEngine = yield* UploadEngine;
|
|
145
148
|
const authService = yield* AuthContextService;
|
|
146
149
|
const authCache = yield* AuthCacheService;
|
|
147
150
|
const metricsService = yield* MetricsService;
|
|
@@ -168,7 +171,11 @@ export const handleUploadChunk = (req: UploadChunkRequest) =>
|
|
|
168
171
|
}
|
|
169
172
|
|
|
170
173
|
const startTime = Date.now();
|
|
171
|
-
const fileResult = yield*
|
|
174
|
+
const fileResult = yield* uploadEngine.uploadChunk(
|
|
175
|
+
uploadId,
|
|
176
|
+
clientId,
|
|
177
|
+
data,
|
|
178
|
+
);
|
|
172
179
|
|
|
173
180
|
// Clear cache and record metrics if upload is complete
|
|
174
181
|
if (fileResult.size && fileResult.offset >= fileResult.size) {
|
package/src/core/plugin-types.ts
CHANGED
|
@@ -166,7 +166,7 @@ export type TypeSafePluginConfig<
|
|
|
166
166
|
* Extracts plugin requirements from a flow function type.
|
|
167
167
|
*
|
|
168
168
|
* This navigates through the flow function signature to extract the requirements
|
|
169
|
-
* from the Flow type it returns, excluding
|
|
169
|
+
* from the Flow type it returns, excluding UploadEngine (provided by runtime).
|
|
170
170
|
*
|
|
171
171
|
* @template TFlowFn - The flow function type to extract requirements from
|
|
172
172
|
*
|
|
@@ -191,7 +191,7 @@ export type ExtractFlowPluginRequirements<
|
|
|
191
191
|
ReturnType<TFlowFn> extends Effect.Effect<infer TFlow, any, any>
|
|
192
192
|
? // biome-ignore lint/suspicious/noExplicitAny: Conditional type inference requires any for input and output schema parameters
|
|
193
193
|
TFlow extends Flow<any, any, infer TRequirements>
|
|
194
|
-
? Exclude<TRequirements, never> // Exclude
|
|
194
|
+
? Exclude<TRequirements, never> // Exclude UploadEngine is handled by FlowPluginRequirements in core
|
|
195
195
|
: never
|
|
196
196
|
: never;
|
|
197
197
|
|
package/src/core/server.ts
CHANGED
|
@@ -21,7 +21,7 @@ import type { z } from "zod";
|
|
|
21
21
|
import type { StandardResponse } from "../adapter";
|
|
22
22
|
import { AuthCacheServiceLive } from "../cache";
|
|
23
23
|
import { handleFlowError } from "../http-utils";
|
|
24
|
-
import {
|
|
24
|
+
import { createFlowEngineLayer, createUploadEngineLayer } from "../layer-utils";
|
|
25
25
|
import { AuthContextServiceLive } from "../service";
|
|
26
26
|
import type { AuthContext } from "../types";
|
|
27
27
|
import { UsageHookServiceLive } from "../usage-hooks/service";
|
|
@@ -252,7 +252,7 @@ export const createUploadistaServer = async <
|
|
|
252
252
|
> = await createDataStoreLayer(dataStore);
|
|
253
253
|
|
|
254
254
|
// Create upload server layer
|
|
255
|
-
const
|
|
255
|
+
const uploadEngineLayer = createUploadEngineLayer({
|
|
256
256
|
kvStore,
|
|
257
257
|
eventEmitter: finalEventEmitter,
|
|
258
258
|
dataStore: dataStoreLayer,
|
|
@@ -261,11 +261,11 @@ export const createUploadistaServer = async <
|
|
|
261
261
|
});
|
|
262
262
|
|
|
263
263
|
// Create flow server layer
|
|
264
|
-
const
|
|
264
|
+
const flowEngineLayer = createFlowEngineLayer({
|
|
265
265
|
kvStore,
|
|
266
266
|
eventEmitter: finalEventEmitter,
|
|
267
267
|
flowProvider: flowProviderLayer,
|
|
268
|
-
|
|
268
|
+
uploadEngine: uploadEngineLayer,
|
|
269
269
|
});
|
|
270
270
|
|
|
271
271
|
// Create auth cache layer (always present, even if auth is not enabled)
|
|
@@ -299,8 +299,8 @@ export const createUploadistaServer = async <
|
|
|
299
299
|
* with user-provided plugin layers.
|
|
300
300
|
*/
|
|
301
301
|
const serverLayerRaw = Layer.mergeAll(
|
|
302
|
-
|
|
303
|
-
|
|
302
|
+
uploadEngineLayer,
|
|
303
|
+
flowEngineLayer,
|
|
304
304
|
effectiveMetricsLayer,
|
|
305
305
|
authCacheLayer,
|
|
306
306
|
usageHookLayer,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { FlowEngineShape } from "@uploadista/core/flow";
|
|
2
2
|
import { Effect } from "effect";
|
|
3
3
|
import type { WebSocketConnection } from "../websocket-routes";
|
|
4
4
|
|
|
@@ -7,7 +7,7 @@ import type { WebSocketConnection } from "../websocket-routes";
|
|
|
7
7
|
* Subscribes the WebSocket connection to receive real-time flow execution events
|
|
8
8
|
*/
|
|
9
9
|
export const handleSubscribeToFlowEvents = (
|
|
10
|
-
|
|
10
|
+
flowEngine: FlowEngineShape,
|
|
11
11
|
jobId: string | undefined,
|
|
12
12
|
connection: WebSocketConnection,
|
|
13
13
|
) => {
|
|
@@ -25,7 +25,7 @@ export const handleSubscribeToFlowEvents = (
|
|
|
25
25
|
return;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
yield*
|
|
28
|
+
yield* flowEngine.subscribeToFlowEvents(jobId, connection);
|
|
29
29
|
});
|
|
30
30
|
};
|
|
31
31
|
|
|
@@ -34,7 +34,7 @@ export const handleSubscribeToFlowEvents = (
|
|
|
34
34
|
* Removes the WebSocket connection from receiving flow events
|
|
35
35
|
*/
|
|
36
36
|
export const handleUnsubscribeFromFlowEvents = (
|
|
37
|
-
|
|
37
|
+
flowEngine: FlowEngineShape,
|
|
38
38
|
jobId: string | undefined,
|
|
39
39
|
) => {
|
|
40
40
|
return Effect.gen(function* () {
|
|
@@ -42,6 +42,6 @@ export const handleUnsubscribeFromFlowEvents = (
|
|
|
42
42
|
return;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
yield*
|
|
45
|
+
yield* flowEngine.unsubscribeFromFlowEvents(jobId);
|
|
46
46
|
});
|
|
47
47
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { UploadEngineShape } from "@uploadista/core/upload";
|
|
2
2
|
import { Effect } from "effect";
|
|
3
3
|
import type { WebSocketConnection } from "../websocket-routes";
|
|
4
4
|
|
|
@@ -7,7 +7,7 @@ import type { WebSocketConnection } from "../websocket-routes";
|
|
|
7
7
|
* Subscribes the WebSocket connection to receive real-time upload progress events
|
|
8
8
|
*/
|
|
9
9
|
export const handleSubscribeToUploadEvents = (
|
|
10
|
-
|
|
10
|
+
uploadEngine: UploadEngineShape,
|
|
11
11
|
uploadId: string | undefined,
|
|
12
12
|
connection: WebSocketConnection,
|
|
13
13
|
) => {
|
|
@@ -25,7 +25,7 @@ export const handleSubscribeToUploadEvents = (
|
|
|
25
25
|
return;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
yield*
|
|
28
|
+
yield* uploadEngine.subscribeToUploadEvents(uploadId, connection);
|
|
29
29
|
});
|
|
30
30
|
};
|
|
31
31
|
|
|
@@ -34,7 +34,7 @@ export const handleSubscribeToUploadEvents = (
|
|
|
34
34
|
* Removes the WebSocket connection from receiving upload events
|
|
35
35
|
*/
|
|
36
36
|
export const handleUnsubscribeFromUploadEvents = (
|
|
37
|
-
|
|
37
|
+
uploadEngine: UploadEngineShape,
|
|
38
38
|
uploadId: string | undefined,
|
|
39
39
|
) => {
|
|
40
40
|
return Effect.gen(function* () {
|
|
@@ -42,6 +42,6 @@ export const handleUnsubscribeFromUploadEvents = (
|
|
|
42
42
|
return;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
yield*
|
|
45
|
+
yield* uploadEngine.unsubscribeFromUploadEvents(uploadId);
|
|
46
46
|
});
|
|
47
47
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { UploadistaError } from "@uploadista/core/errors";
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
2
|
+
import type { FlowEngineShape } from "@uploadista/core/flow";
|
|
3
|
+
import type { UploadEngineShape } from "@uploadista/core/upload";
|
|
4
4
|
import { Effect } from "effect";
|
|
5
5
|
import type {
|
|
6
6
|
WebSocketConnection,
|
|
@@ -26,8 +26,8 @@ export type {
|
|
|
26
26
|
*/
|
|
27
27
|
export const handleWebSocketOpen = (
|
|
28
28
|
request: WebSocketConnectionRequest,
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
uploadEngine: UploadEngineShape,
|
|
30
|
+
flowEngine: FlowEngineShape,
|
|
31
31
|
) => {
|
|
32
32
|
const { connection, isFlowRoute, isUploadRoute, jobId, uploadId, eventId } =
|
|
33
33
|
request;
|
|
@@ -35,12 +35,12 @@ export const handleWebSocketOpen = (
|
|
|
35
35
|
return Effect.gen(function* () {
|
|
36
36
|
// Subscribe to flow events if this is a flow route
|
|
37
37
|
if (isFlowRoute) {
|
|
38
|
-
yield* handleSubscribeToFlowEvents(
|
|
38
|
+
yield* handleSubscribeToFlowEvents(flowEngine, jobId, connection);
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
// Subscribe to upload events if this is an upload route
|
|
42
42
|
if (isUploadRoute) {
|
|
43
|
-
yield* handleSubscribeToUploadEvents(
|
|
43
|
+
yield* handleSubscribeToUploadEvents(uploadEngine, uploadId, connection);
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
// Send connection confirmation
|
|
@@ -114,20 +114,20 @@ export const handleWebSocketMessage = (
|
|
|
114
114
|
*/
|
|
115
115
|
export const handleWebSocketClose = (
|
|
116
116
|
request: WebSocketConnectionRequest,
|
|
117
|
-
|
|
118
|
-
|
|
117
|
+
uploadEngine: UploadEngineShape,
|
|
118
|
+
flowEngine: FlowEngineShape,
|
|
119
119
|
) => {
|
|
120
120
|
const { isFlowRoute, isUploadRoute, jobId, uploadId } = request;
|
|
121
121
|
|
|
122
122
|
return Effect.gen(function* () {
|
|
123
123
|
// Unsubscribe from flow events if this was a flow route
|
|
124
124
|
if (isFlowRoute) {
|
|
125
|
-
yield* handleUnsubscribeFromFlowEvents(
|
|
125
|
+
yield* handleUnsubscribeFromFlowEvents(flowEngine, jobId);
|
|
126
126
|
}
|
|
127
127
|
|
|
128
128
|
// Unsubscribe from upload events if this was an upload route
|
|
129
129
|
if (isUploadRoute) {
|
|
130
|
-
yield* handleUnsubscribeFromUploadEvents(
|
|
130
|
+
yield* handleUnsubscribeFromUploadEvents(uploadEngine, uploadId);
|
|
131
131
|
}
|
|
132
132
|
}).pipe(
|
|
133
133
|
Effect.catchAll((error) =>
|
package/src/error-types.ts
CHANGED
|
@@ -114,7 +114,7 @@ export const createErrorResponseBody = (error: AdapterError) => ({
|
|
|
114
114
|
* import { createUploadistaErrorResponseBody } from "@uploadista/server";
|
|
115
115
|
*
|
|
116
116
|
* try {
|
|
117
|
-
* const result = yield*
|
|
117
|
+
* const result = yield* uploadEngine.handleUpload(input);
|
|
118
118
|
* } catch (err) {
|
|
119
119
|
* if (err instanceof UploadistaError) {
|
|
120
120
|
* const errorResponse = createUploadistaErrorResponseBody(err);
|
package/src/layer-utils.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { FlowProvider } from "@uploadista/core/flow";
|
|
2
|
-
import {
|
|
2
|
+
import { flowEngine } from "@uploadista/core/flow";
|
|
3
3
|
import {
|
|
4
4
|
type BaseEventEmitterService,
|
|
5
5
|
type BaseKvStoreService,
|
|
@@ -11,13 +11,13 @@ import {
|
|
|
11
11
|
uploadEventEmitter,
|
|
12
12
|
uploadFileKvStore,
|
|
13
13
|
} from "@uploadista/core/types";
|
|
14
|
-
import { type
|
|
14
|
+
import { type UploadEngine, uploadEngine } from "@uploadista/core/upload";
|
|
15
15
|
import type { GenerateId } from "@uploadista/core/utils";
|
|
16
16
|
import { Layer } from "effect";
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
|
-
* Configuration for creating upload
|
|
20
|
-
* Specifies all dependencies needed by the upload
|
|
19
|
+
* Configuration for creating upload engine layers.
|
|
20
|
+
* Specifies all dependencies needed by the upload engine Effect Layer.
|
|
21
21
|
*
|
|
22
22
|
* @property kvStore - Key-value store for upload metadata
|
|
23
23
|
* @property eventEmitter - Event emitter for upload progress events
|
|
@@ -27,16 +27,16 @@ import { Layer } from "effect";
|
|
|
27
27
|
*
|
|
28
28
|
* @example
|
|
29
29
|
* ```typescript
|
|
30
|
-
* import {
|
|
30
|
+
* import { createUploadEngineLayer } from "@uploadista/server";
|
|
31
31
|
*
|
|
32
|
-
* const uploadLayerConfig:
|
|
32
|
+
* const uploadLayerConfig: UploadEngineLayerConfig = {
|
|
33
33
|
* kvStore: redisKvStore,
|
|
34
34
|
* eventEmitter: webSocketEventEmitter,
|
|
35
35
|
* dataStore: s3DataStore,
|
|
36
36
|
* };
|
|
37
37
|
* ```
|
|
38
38
|
*/
|
|
39
|
-
export interface
|
|
39
|
+
export interface UploadEngineLayerConfig {
|
|
40
40
|
kvStore: Layer.Layer<BaseKvStoreService>;
|
|
41
41
|
eventEmitter: Layer.Layer<BaseEventEmitterService>;
|
|
42
42
|
dataStore: Layer.Layer<UploadFileDataStores, never, UploadFileKVStore>;
|
|
@@ -55,7 +55,7 @@ export interface UploadServerLayerConfig {
|
|
|
55
55
|
* @property kvStore - Key-value store for flow job metadata
|
|
56
56
|
* @property eventEmitter - Event emitter for flow progress events
|
|
57
57
|
* @property flowProvider - Factory function for creating flows
|
|
58
|
-
* @property
|
|
58
|
+
* @property uploadEngine - Upload engine layer (used by flows for uploads)
|
|
59
59
|
*
|
|
60
60
|
* @example
|
|
61
61
|
* ```typescript
|
|
@@ -65,7 +65,7 @@ export interface UploadServerLayerConfig {
|
|
|
65
65
|
* kvStore: redisKvStore,
|
|
66
66
|
* eventEmitter: webSocketEventEmitter,
|
|
67
67
|
* flowProvider: createFlowsEffect,
|
|
68
|
-
*
|
|
68
|
+
* uploadEngine: uploadEngineLayer,
|
|
69
69
|
* };
|
|
70
70
|
* ```
|
|
71
71
|
*/
|
|
@@ -73,7 +73,7 @@ export interface FlowServerLayerConfig {
|
|
|
73
73
|
kvStore: Layer.Layer<BaseKvStoreService>;
|
|
74
74
|
eventEmitter: Layer.Layer<BaseEventEmitterService>;
|
|
75
75
|
flowProvider: Layer.Layer<FlowProvider>;
|
|
76
|
-
|
|
76
|
+
uploadEngine: Layer.Layer<UploadEngine>;
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
/**
|
|
@@ -88,30 +88,30 @@ export interface FlowServerLayerConfig {
|
|
|
88
88
|
* - Optional custom ID generator
|
|
89
89
|
*
|
|
90
90
|
* @param config - Upload server layer configuration
|
|
91
|
-
* @returns Effect Layer providing
|
|
91
|
+
* @returns Effect Layer providing UploadEngine
|
|
92
92
|
*
|
|
93
93
|
* @example
|
|
94
94
|
* ```typescript
|
|
95
|
-
* import {
|
|
95
|
+
* import { createUploadEngineLayer } from "@uploadista/server";
|
|
96
96
|
* import { Layer } from "effect";
|
|
97
97
|
*
|
|
98
|
-
* const
|
|
98
|
+
* const uploadEngineLayer = createUploadEngineLayer({
|
|
99
99
|
* kvStore: redisKvStore,
|
|
100
100
|
* eventEmitter: webSocketEventEmitter,
|
|
101
101
|
* dataStore: s3DataStore,
|
|
102
102
|
* });
|
|
103
103
|
*
|
|
104
104
|
* // Use in application
|
|
105
|
-
* const app = Layer.provide(appLogic,
|
|
105
|
+
* const app = Layer.provide(appLogic, uploadEngineLayer);
|
|
106
106
|
* ```
|
|
107
107
|
*/
|
|
108
|
-
export const
|
|
108
|
+
export const createUploadEngineLayer = ({
|
|
109
109
|
kvStore,
|
|
110
110
|
eventEmitter,
|
|
111
111
|
dataStore,
|
|
112
112
|
bufferedDataStore,
|
|
113
113
|
generateId,
|
|
114
|
-
}:
|
|
114
|
+
}: UploadEngineLayerConfig) => {
|
|
115
115
|
// Set up upload server dependencies
|
|
116
116
|
const uploadFileKVStoreLayer = Layer.provide(uploadFileKvStore, kvStore);
|
|
117
117
|
const uploadDataStoreLayer = Layer.provide(dataStore, uploadFileKVStoreLayer);
|
|
@@ -123,7 +123,7 @@ export const createUploadServerLayer = ({
|
|
|
123
123
|
eventEmitter,
|
|
124
124
|
);
|
|
125
125
|
|
|
126
|
-
const
|
|
126
|
+
const uploadEngineLayers = Layer.mergeAll(
|
|
127
127
|
uploadDataStoreLayer,
|
|
128
128
|
uploadFileKVStoreLayer,
|
|
129
129
|
uploadEventEmitterLayer,
|
|
@@ -131,7 +131,7 @@ export const createUploadServerLayer = ({
|
|
|
131
131
|
uploadBufferedDataStoreLayer,
|
|
132
132
|
);
|
|
133
133
|
|
|
134
|
-
return Layer.provide(
|
|
134
|
+
return Layer.provide(uploadEngine, uploadEngineLayers);
|
|
135
135
|
};
|
|
136
136
|
|
|
137
137
|
/**
|
|
@@ -156,29 +156,29 @@ export const createUploadServerLayer = ({
|
|
|
156
156
|
* kvStore: redisKvStore,
|
|
157
157
|
* eventEmitter: webSocketEventEmitter,
|
|
158
158
|
* flowProvider: createFlowsEffect,
|
|
159
|
-
*
|
|
159
|
+
* uploadEngine: uploadEngineLayer,
|
|
160
160
|
* });
|
|
161
161
|
*
|
|
162
162
|
* // Use in application
|
|
163
163
|
* const app = Layer.provide(appLogic, flowServerLayer);
|
|
164
164
|
* ```
|
|
165
165
|
*/
|
|
166
|
-
export const
|
|
166
|
+
export const createFlowEngineLayer = ({
|
|
167
167
|
kvStore,
|
|
168
168
|
eventEmitter,
|
|
169
169
|
flowProvider,
|
|
170
|
-
|
|
170
|
+
uploadEngine,
|
|
171
171
|
}: FlowServerLayerConfig) => {
|
|
172
172
|
// Set up flow server dependencies
|
|
173
173
|
const flowJobKVStoreLayer = Layer.provide(flowJobKvStore, kvStore);
|
|
174
174
|
const flowEventEmitterLayer = Layer.provide(flowEventEmitter, eventEmitter);
|
|
175
175
|
|
|
176
|
-
const
|
|
176
|
+
const flowEngineLayers = Layer.mergeAll(
|
|
177
177
|
flowProvider,
|
|
178
178
|
flowEventEmitterLayer,
|
|
179
179
|
flowJobKVStoreLayer,
|
|
180
|
-
|
|
180
|
+
uploadEngine,
|
|
181
181
|
);
|
|
182
182
|
|
|
183
|
-
return Layer.provide(
|
|
183
|
+
return Layer.provide(flowEngine, flowEngineLayers);
|
|
184
184
|
};
|
package/src/plugins-typing.ts
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* @module plugins-typing
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import type { Flow,
|
|
17
|
+
import type { Flow, UploadEngine } from "@uploadista/core";
|
|
18
18
|
import type { ExtractLayerServices } from "@uploadista/core/flow";
|
|
19
19
|
import type { Effect, Layer } from "effect";
|
|
20
20
|
import type z from "zod";
|
|
@@ -58,7 +58,7 @@ export type FlowSuccess<
|
|
|
58
58
|
/**
|
|
59
59
|
* @deprecated Use `ExtractFlowPluginRequirements` from `@uploadista/server/core/plugin-types` instead.
|
|
60
60
|
*
|
|
61
|
-
* Extracts plugin requirements from a flow function, excluding
|
|
61
|
+
* Extracts plugin requirements from a flow function, excluding UploadEngine.
|
|
62
62
|
*
|
|
63
63
|
* @example Migration
|
|
64
64
|
* ```typescript
|
|
@@ -82,7 +82,7 @@ export type FlowRequirementsOf<
|
|
|
82
82
|
z.ZodSchema<unknown>,
|
|
83
83
|
infer R
|
|
84
84
|
>
|
|
85
|
-
? Exclude<R,
|
|
85
|
+
? Exclude<R, UploadEngine>
|
|
86
86
|
: never;
|
|
87
87
|
|
|
88
88
|
/**
|
|
@@ -106,7 +106,7 @@ export type RequiredPluginsOf<
|
|
|
106
106
|
flowId: string,
|
|
107
107
|
clientId: string | null,
|
|
108
108
|
) => Effect.Effect<unknown, unknown, unknown>,
|
|
109
|
-
> = Exclude<FlowRequirementsOf<TFlows>,
|
|
109
|
+
> = Exclude<FlowRequirementsOf<TFlows>, UploadEngine>;
|
|
110
110
|
|
|
111
111
|
/**
|
|
112
112
|
* @deprecated Use `ValidatePlugins` from `@uploadista/server/core/plugin-types` instead.
|