@uploadista/server 0.1.3 → 0.2.0
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/dist/auth/index.cjs +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.d.cts +9 -0
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +9 -0
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -9
- package/src/core/http-handlers/upload-http-handlers.ts +10 -1
- package/src/core/server.ts +24 -1
- package/src/usage-hooks/types.ts +9 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uploadista/server",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.2.0",
|
|
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.
|
|
24
|
-
"@uploadista/
|
|
25
|
-
"@uploadista/
|
|
26
|
-
"@uploadista/event-emitter-websocket": "0.
|
|
23
|
+
"@uploadista/core": "0.2.0",
|
|
24
|
+
"@uploadista/event-broadcaster-memory": "0.2.0",
|
|
25
|
+
"@uploadista/observability": "0.2.0",
|
|
26
|
+
"@uploadista/event-emitter-websocket": "0.2.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"@cloudflare/workers-types": "4.
|
|
29
|
+
"@cloudflare/workers-types": "4.20260213.0",
|
|
30
30
|
"@effect/vitest": "0.27.0",
|
|
31
31
|
"@types/express": "^5.0.0",
|
|
32
32
|
"@types/node": "24.10.9",
|
|
33
|
-
"effect": "3.19.
|
|
33
|
+
"effect": "3.19.17",
|
|
34
34
|
"tsd": "0.33.0",
|
|
35
|
-
"tsdown": "0.20.
|
|
35
|
+
"tsdown": "0.20.3",
|
|
36
36
|
"typescript": "5.9.3",
|
|
37
37
|
"vitest": "4.0.18",
|
|
38
38
|
"zod": "4.3.6",
|
|
39
|
-
"@uploadista/typescript-config": "0.
|
|
39
|
+
"@uploadista/typescript-config": "0.2.0"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
42
|
"effect": "^3.0.0",
|
|
@@ -195,7 +195,7 @@ export const handleUploadChunk = (req: UploadChunkRequest) =>
|
|
|
195
195
|
metricsService.recordUpload(clientId, fileResult.size, authMetadata),
|
|
196
196
|
);
|
|
197
197
|
|
|
198
|
-
// Execute onUploadComplete hook for usage tracking
|
|
198
|
+
// Execute onUploadComplete hook for usage tracking and billing
|
|
199
199
|
const duration = Date.now() - startTime;
|
|
200
200
|
yield* Effect.forkDaemon(
|
|
201
201
|
usageHookService.onUploadComplete({
|
|
@@ -205,6 +205,15 @@ export const handleUploadChunk = (req: UploadChunkRequest) =>
|
|
|
205
205
|
uploadId,
|
|
206
206
|
fileSize: fileResult.size,
|
|
207
207
|
duration,
|
|
208
|
+
storageId: fileResult.storage?.id,
|
|
209
|
+
url: fileResult.url,
|
|
210
|
+
fileName: fileResult.metadata?.fileName as string | undefined,
|
|
211
|
+
flowContext: fileResult.flow
|
|
212
|
+
? {
|
|
213
|
+
flowId: fileResult.flow.flowId,
|
|
214
|
+
jobId: fileResult.flow.jobId,
|
|
215
|
+
}
|
|
216
|
+
: undefined,
|
|
208
217
|
},
|
|
209
218
|
}),
|
|
210
219
|
);
|
package/src/core/server.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { PluginLayer, UploadistaError } from "@uploadista/core";
|
|
|
2
2
|
import {
|
|
3
3
|
deadLetterQueueService,
|
|
4
4
|
type Flow,
|
|
5
|
+
FlowLifecycleHook,
|
|
5
6
|
FlowProvider,
|
|
6
7
|
FlowWaitUntil,
|
|
7
8
|
kvCircuitBreakerStoreLayer,
|
|
@@ -24,7 +25,7 @@ import { handleFlowError } from "../http-utils";
|
|
|
24
25
|
import { createFlowEngineLayer, createUploadEngineLayer } from "../layer-utils";
|
|
25
26
|
import { AuthContextServiceLive } from "../service";
|
|
26
27
|
import type { AuthContext } from "../types";
|
|
27
|
-
import { UsageHookServiceLive } from "../usage-hooks/service";
|
|
28
|
+
import { UsageHookService, UsageHookServiceLive } from "../usage-hooks/service";
|
|
28
29
|
import { handleUploadistaRequest } from "./http-handlers/http-handlers";
|
|
29
30
|
import type { ExtractFlowPluginRequirements } from "./plugin-types";
|
|
30
31
|
import type { NotFoundResponse } from "./routes";
|
|
@@ -291,6 +292,27 @@ export const createUploadistaServer = async <
|
|
|
291
292
|
// Create usage hook layer (defaults to no-op if not configured)
|
|
292
293
|
const usageHookLayer = UsageHookServiceLive(usageHooks);
|
|
293
294
|
|
|
295
|
+
// Bridge UsageHookService.onFlowComplete to FlowLifecycleHook
|
|
296
|
+
// so the flow engine can call it reliably from the execution daemon
|
|
297
|
+
const flowLifecycleHookLayer = Layer.effect(
|
|
298
|
+
FlowLifecycleHook,
|
|
299
|
+
Effect.gen(function* () {
|
|
300
|
+
const usageHookService = yield* UsageHookService;
|
|
301
|
+
return {
|
|
302
|
+
onComplete: (ctx) =>
|
|
303
|
+
usageHookService.onFlowComplete({
|
|
304
|
+
clientId: ctx.clientId ?? "",
|
|
305
|
+
operation: "flow",
|
|
306
|
+
metadata: {
|
|
307
|
+
jobId: ctx.jobId,
|
|
308
|
+
flowId: ctx.flowId,
|
|
309
|
+
status: ctx.status === "completed" ? "success" : "failed",
|
|
310
|
+
},
|
|
311
|
+
}),
|
|
312
|
+
};
|
|
313
|
+
}),
|
|
314
|
+
).pipe(Layer.provide(usageHookLayer));
|
|
315
|
+
|
|
294
316
|
/**
|
|
295
317
|
* Merge all server layers including plugins.
|
|
296
318
|
*
|
|
@@ -304,6 +326,7 @@ export const createUploadistaServer = async <
|
|
|
304
326
|
effectiveMetricsLayer,
|
|
305
327
|
authCacheLayer,
|
|
306
328
|
usageHookLayer,
|
|
329
|
+
flowLifecycleHookLayer,
|
|
307
330
|
...plugins,
|
|
308
331
|
...(circuitBreakerStoreLayer ? [circuitBreakerStoreLayer] : []),
|
|
309
332
|
...(dlqLayer ? [dlqLayer] : []),
|
package/src/usage-hooks/types.ts
CHANGED
|
@@ -64,6 +64,15 @@ export interface UploadUsageMetadata extends BaseUsageMetadata {
|
|
|
64
64
|
uploadId?: string;
|
|
65
65
|
/** Duration of the upload in milliseconds */
|
|
66
66
|
duration?: number;
|
|
67
|
+
/** Storage configuration identifier (for database persistence) */
|
|
68
|
+
storageId?: string;
|
|
69
|
+
/** URL of the uploaded file (for database persistence) */
|
|
70
|
+
url?: string;
|
|
71
|
+
/** Flow context if this upload was initiated as part of a flow (for double-counting prevention) */
|
|
72
|
+
flowContext?: {
|
|
73
|
+
flowId: string;
|
|
74
|
+
jobId: string;
|
|
75
|
+
};
|
|
67
76
|
}
|
|
68
77
|
|
|
69
78
|
/**
|