@uploadista/server 0.0.18-beta.16 → 0.0.18-beta.2
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 +0 -83
- package/dist/index.cjs +2 -2
- package/dist/index.d.cts +9 -794
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +9 -794
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +10 -10
- package/src/core/http-handlers/flow-http-handlers.ts +6 -61
- package/src/core/http-handlers/http-handlers.ts +0 -50
- package/src/core/http-handlers/upload-http-handlers.ts +3 -56
- package/src/core/routes.ts +0 -171
- package/src/core/server.ts +11 -71
- package/src/core/types.ts +0 -150
- package/src/index.ts +0 -2
- package/src/plugins-typing.ts +1 -1
- package/src/service.ts +3 -101
- package/docs/HEALTH_CHECKS.md +0 -256
- package/src/core/health-check-service.ts +0 -367
- package/src/core/http-handlers/dlq-http-handlers.ts +0 -219
- package/src/core/http-handlers/health-http-handlers.ts +0 -150
- package/src/permissions/errors.ts +0 -105
- package/src/permissions/index.ts +0 -9
- package/src/permissions/matcher.ts +0 -139
- package/src/permissions/types.ts +0 -151
- package/src/usage-hooks/index.ts +0 -8
- package/src/usage-hooks/service.ts +0 -162
- package/src/usage-hooks/types.ts +0 -221
- package/tests/core/health-check-service.test.ts +0 -570
- package/tests/core/http-handlers/health-handlers.test.ts +0 -351
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uploadista/server",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.18-beta.
|
|
4
|
+
"version": "0.0.18-beta.2",
|
|
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.18-beta.
|
|
24
|
-
"@uploadista/event-
|
|
25
|
-
"@uploadista/
|
|
26
|
-
"@uploadista/
|
|
23
|
+
"@uploadista/core": "0.0.18-beta.2",
|
|
24
|
+
"@uploadista/event-broadcaster-memory": "0.0.18-beta.2",
|
|
25
|
+
"@uploadista/event-emitter-websocket": "0.0.18-beta.2",
|
|
26
|
+
"@uploadista/observability": "0.0.18-beta.2"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"@cloudflare/workers-types": "4.
|
|
29
|
+
"@cloudflare/workers-types": "4.20251125.0",
|
|
30
30
|
"@effect/vitest": "0.27.0",
|
|
31
31
|
"@types/express": "^5.0.0",
|
|
32
32
|
"@types/node": "24.10.1",
|
|
33
|
-
"effect": "3.19.
|
|
33
|
+
"effect": "3.19.6",
|
|
34
34
|
"tsd": "0.33.0",
|
|
35
|
-
"tsdown": "0.16.
|
|
35
|
+
"tsdown": "0.16.6",
|
|
36
36
|
"typescript": "5.9.3",
|
|
37
|
-
"vitest": "4.0.
|
|
37
|
+
"vitest": "4.0.13",
|
|
38
38
|
"zod": "4.1.13",
|
|
39
|
-
"@uploadista/typescript-config": "0.0.18-beta.
|
|
39
|
+
"@uploadista/typescript-config": "0.0.18-beta.2"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
42
|
"effect": "^3.0.0",
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import { FlowServer } from "@uploadista/core/flow";
|
|
2
2
|
import { Effect } from "effect";
|
|
3
3
|
import { AuthCacheService } from "../../cache";
|
|
4
|
-
import { PERMISSIONS } from "../../permissions/types";
|
|
5
|
-
import { QuotaExceededError } from "../../permissions/errors";
|
|
6
4
|
import { AuthContextService } from "../../service";
|
|
7
|
-
import { UsageHookService } from "../../usage-hooks/service";
|
|
8
5
|
import type {
|
|
9
6
|
CancelFlowRequest,
|
|
10
7
|
CancelFlowResponse,
|
|
@@ -23,12 +20,10 @@ import type {
|
|
|
23
20
|
export const handleGetFlow = ({ flowId }: GetFlowRequest) => {
|
|
24
21
|
return Effect.gen(function* () {
|
|
25
22
|
const flowServer = yield* FlowServer;
|
|
23
|
+
// Access auth context if available
|
|
26
24
|
const authService = yield* AuthContextService;
|
|
27
25
|
const clientId = yield* authService.getClientId();
|
|
28
26
|
|
|
29
|
-
// Check permission for reading flow status
|
|
30
|
-
yield* authService.requirePermission(PERMISSIONS.FLOW.STATUS);
|
|
31
|
-
|
|
32
27
|
if (clientId) {
|
|
33
28
|
yield* Effect.logInfo(
|
|
34
29
|
`[Flow] Getting flow data: ${flowId}, client: ${clientId}`,
|
|
@@ -51,14 +46,11 @@ export const handleRunFlow = <TRequirements>({
|
|
|
51
46
|
}: RunFlowRequest) => {
|
|
52
47
|
return Effect.gen(function* () {
|
|
53
48
|
const flowServer = yield* FlowServer;
|
|
49
|
+
// Access auth context if available
|
|
54
50
|
const authService = yield* AuthContextService;
|
|
55
51
|
const authCache = yield* AuthCacheService;
|
|
56
|
-
const usageHookService = yield* UsageHookService;
|
|
57
52
|
const clientId = yield* authService.getClientId();
|
|
58
53
|
|
|
59
|
-
// Check permission for executing flows
|
|
60
|
-
yield* authService.requirePermission(PERMISSIONS.FLOW.EXECUTE);
|
|
61
|
-
|
|
62
54
|
if (clientId) {
|
|
63
55
|
yield* Effect.logInfo(
|
|
64
56
|
`[Flow] Executing flow: ${flowId}, storage: ${storageId}, client: ${clientId}`,
|
|
@@ -73,28 +65,7 @@ export const handleRunFlow = <TRequirements>({
|
|
|
73
65
|
);
|
|
74
66
|
}
|
|
75
67
|
|
|
76
|
-
// Execute onFlowStart hook for quota checking
|
|
77
|
-
if (clientId) {
|
|
78
|
-
const hookResult = yield* usageHookService.onFlowStart({
|
|
79
|
-
clientId,
|
|
80
|
-
operation: "flow",
|
|
81
|
-
metadata: {
|
|
82
|
-
flowId,
|
|
83
|
-
},
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
if (hookResult.action === "abort") {
|
|
87
|
-
return yield* Effect.fail(
|
|
88
|
-
new QuotaExceededError(
|
|
89
|
-
hookResult.reason,
|
|
90
|
-
hookResult.code ?? "SUBSCRIPTION_REQUIRED",
|
|
91
|
-
),
|
|
92
|
-
);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
68
|
// Run flow returns immediately with jobId
|
|
97
|
-
const startTime = Date.now();
|
|
98
69
|
yield* Effect.logInfo(`[Flow] Calling flowServer.runFlow...`);
|
|
99
70
|
const result = yield* flowServer
|
|
100
71
|
.runFlow<TRequirements>({
|
|
@@ -120,10 +91,6 @@ export const handleRunFlow = <TRequirements>({
|
|
|
120
91
|
|
|
121
92
|
yield* Effect.logInfo(`[Flow] Flow started with jobId: ${result.id}`);
|
|
122
93
|
|
|
123
|
-
// Note: onFlowComplete hook is called when the flow actually completes,
|
|
124
|
-
// which happens asynchronously. The hook should be invoked from the
|
|
125
|
-
// flow execution pipeline, not here where we just start the flow.
|
|
126
|
-
|
|
127
94
|
return {
|
|
128
95
|
status: 200,
|
|
129
96
|
body: result,
|
|
@@ -134,13 +101,11 @@ export const handleRunFlow = <TRequirements>({
|
|
|
134
101
|
export const handleJobStatus = ({ jobId }: GetJobStatusRequest) => {
|
|
135
102
|
return Effect.gen(function* () {
|
|
136
103
|
const flowServer = yield* FlowServer;
|
|
104
|
+
// Access auth context if available
|
|
137
105
|
const authService = yield* AuthContextService;
|
|
138
106
|
const authCache = yield* AuthCacheService;
|
|
139
107
|
const clientId = yield* authService.getClientId();
|
|
140
108
|
|
|
141
|
-
// Check permission for checking flow status
|
|
142
|
-
yield* authService.requirePermission(PERMISSIONS.FLOW.STATUS);
|
|
143
|
-
|
|
144
109
|
if (!jobId) {
|
|
145
110
|
throw new Error("No job id");
|
|
146
111
|
}
|
|
@@ -177,12 +142,10 @@ export const handleResumeFlow = <TRequirements>({
|
|
|
177
142
|
}: ResumeFlowRequest) => {
|
|
178
143
|
return Effect.gen(function* () {
|
|
179
144
|
const flowServer = yield* FlowServer;
|
|
145
|
+
// Try to get auth from current request or cached auth
|
|
180
146
|
const authService = yield* AuthContextService;
|
|
181
147
|
const authCache = yield* AuthCacheService;
|
|
182
148
|
|
|
183
|
-
// Check permission for executing flows (resume is part of execution)
|
|
184
|
-
yield* authService.requirePermission(PERMISSIONS.FLOW.EXECUTE);
|
|
185
|
-
|
|
186
149
|
// Try current auth first, fallback to cached auth
|
|
187
150
|
let clientId = yield* authService.getClientId();
|
|
188
151
|
if (!clientId) {
|
|
@@ -223,16 +186,13 @@ export const handleResumeFlow = <TRequirements>({
|
|
|
223
186
|
} as ResumeFlowResponse;
|
|
224
187
|
});
|
|
225
188
|
};
|
|
226
|
-
|
|
227
189
|
export const handlePauseFlow = ({ jobId }: PauseFlowRequest) => {
|
|
228
190
|
return Effect.gen(function* () {
|
|
229
191
|
const flowServer = yield* FlowServer;
|
|
192
|
+
// Try to get auth from current request or cached auth
|
|
230
193
|
const authService = yield* AuthContextService;
|
|
231
194
|
const authCache = yield* AuthCacheService;
|
|
232
195
|
|
|
233
|
-
// Check permission for cancelling flows (pause is related to cancel)
|
|
234
|
-
yield* authService.requirePermission(PERMISSIONS.FLOW.CANCEL);
|
|
235
|
-
|
|
236
196
|
// Try current auth first, fallback to cached auth
|
|
237
197
|
let clientId = yield* authService.getClientId();
|
|
238
198
|
if (!clientId) {
|
|
@@ -264,12 +224,9 @@ export const handlePauseFlow = ({ jobId }: PauseFlowRequest) => {
|
|
|
264
224
|
export const handleCancelFlow = ({ jobId }: CancelFlowRequest) => {
|
|
265
225
|
return Effect.gen(function* () {
|
|
266
226
|
const flowServer = yield* FlowServer;
|
|
227
|
+
// Try to get auth from current request or cached auth
|
|
267
228
|
const authService = yield* AuthContextService;
|
|
268
229
|
const authCache = yield* AuthCacheService;
|
|
269
|
-
const usageHookService = yield* UsageHookService;
|
|
270
|
-
|
|
271
|
-
// Check permission for cancelling flows
|
|
272
|
-
yield* authService.requirePermission(PERMISSIONS.FLOW.CANCEL);
|
|
273
230
|
|
|
274
231
|
if (!jobId) {
|
|
275
232
|
throw new Error("No job id");
|
|
@@ -296,18 +253,6 @@ export const handleCancelFlow = ({ jobId }: CancelFlowRequest) => {
|
|
|
296
253
|
yield* Effect.logInfo(
|
|
297
254
|
`[Flow] Flow cancelled, cleared auth cache: ${jobId}`,
|
|
298
255
|
);
|
|
299
|
-
|
|
300
|
-
// Execute onFlowComplete hook for cancelled flow
|
|
301
|
-
yield* Effect.forkDaemon(
|
|
302
|
-
usageHookService.onFlowComplete({
|
|
303
|
-
clientId,
|
|
304
|
-
operation: "flow",
|
|
305
|
-
metadata: {
|
|
306
|
-
jobId,
|
|
307
|
-
status: "cancelled",
|
|
308
|
-
},
|
|
309
|
-
}),
|
|
310
|
-
);
|
|
311
256
|
}
|
|
312
257
|
|
|
313
258
|
return {
|
|
@@ -1,16 +1,5 @@
|
|
|
1
|
-
import type { HealthCheckConfig } from "@uploadista/core/types";
|
|
2
1
|
import { Effect } from "effect";
|
|
3
2
|
import type { UploadistaRequest, UploadistaResponse } from "../routes";
|
|
4
|
-
import {
|
|
5
|
-
handleDlqCleanup,
|
|
6
|
-
handleDlqDelete,
|
|
7
|
-
handleDlqGet,
|
|
8
|
-
handleDlqList,
|
|
9
|
-
handleDlqResolve,
|
|
10
|
-
handleDlqRetry,
|
|
11
|
-
handleDlqRetryAll,
|
|
12
|
-
handleDlqStats,
|
|
13
|
-
} from "./dlq-http-handlers";
|
|
14
3
|
import {
|
|
15
4
|
handleCancelFlow,
|
|
16
5
|
handleGetFlow,
|
|
@@ -19,11 +8,6 @@ import {
|
|
|
19
8
|
handleResumeFlow,
|
|
20
9
|
handleRunFlow,
|
|
21
10
|
} from "./flow-http-handlers";
|
|
22
|
-
import {
|
|
23
|
-
handleHealthComponents,
|
|
24
|
-
handleHealthLiveness,
|
|
25
|
-
handleHealthReadiness,
|
|
26
|
-
} from "./health-http-handlers";
|
|
27
11
|
import {
|
|
28
12
|
handleCreateUpload,
|
|
29
13
|
handleGetCapabilities,
|
|
@@ -35,7 +19,6 @@ export type { UploadistaRequest, UploadistaResponse } from "../routes";
|
|
|
35
19
|
|
|
36
20
|
export const handleUploadistaRequest = <TRequirements>(
|
|
37
21
|
req: UploadistaRequest,
|
|
38
|
-
options?: { healthCheckConfig?: HealthCheckConfig },
|
|
39
22
|
) => {
|
|
40
23
|
return Effect.gen(function* () {
|
|
41
24
|
switch (req.type) {
|
|
@@ -61,39 +44,6 @@ export const handleUploadistaRequest = <TRequirements>(
|
|
|
61
44
|
return (yield* handlePauseFlow(req)) as UploadistaResponse;
|
|
62
45
|
case "cancel-flow":
|
|
63
46
|
return (yield* handleCancelFlow(req)) as UploadistaResponse;
|
|
64
|
-
// DLQ Admin routes
|
|
65
|
-
case "dlq-list":
|
|
66
|
-
return (yield* handleDlqList(req)) as UploadistaResponse;
|
|
67
|
-
case "dlq-get":
|
|
68
|
-
return (yield* handleDlqGet(req)) as UploadistaResponse;
|
|
69
|
-
case "dlq-retry":
|
|
70
|
-
return (yield* handleDlqRetry(req)) as UploadistaResponse;
|
|
71
|
-
case "dlq-retry-all":
|
|
72
|
-
return (yield* handleDlqRetryAll(req)) as UploadistaResponse;
|
|
73
|
-
case "dlq-delete":
|
|
74
|
-
return (yield* handleDlqDelete(req)) as UploadistaResponse;
|
|
75
|
-
case "dlq-resolve":
|
|
76
|
-
return (yield* handleDlqResolve(req)) as UploadistaResponse;
|
|
77
|
-
case "dlq-cleanup":
|
|
78
|
-
return (yield* handleDlqCleanup(req)) as UploadistaResponse;
|
|
79
|
-
case "dlq-stats":
|
|
80
|
-
return (yield* handleDlqStats(req)) as UploadistaResponse;
|
|
81
|
-
// Health check routes
|
|
82
|
-
case "health":
|
|
83
|
-
return (yield* handleHealthLiveness(
|
|
84
|
-
req,
|
|
85
|
-
options?.healthCheckConfig,
|
|
86
|
-
)) as UploadistaResponse;
|
|
87
|
-
case "health-ready":
|
|
88
|
-
return (yield* handleHealthReadiness(
|
|
89
|
-
req,
|
|
90
|
-
options?.healthCheckConfig,
|
|
91
|
-
)) as UploadistaResponse;
|
|
92
|
-
case "health-components":
|
|
93
|
-
return (yield* handleHealthComponents(
|
|
94
|
-
req,
|
|
95
|
-
options?.healthCheckConfig,
|
|
96
|
-
)) as UploadistaResponse;
|
|
97
47
|
case "not-found":
|
|
98
48
|
return {
|
|
99
49
|
status: 404,
|
|
@@ -5,10 +5,7 @@ import { MetricsService } from "@uploadista/observability";
|
|
|
5
5
|
import { Effect } from "effect";
|
|
6
6
|
import { AuthCacheService } from "../../cache";
|
|
7
7
|
import { ValidationError } from "../../error-types";
|
|
8
|
-
import { PERMISSIONS } from "../../permissions/types";
|
|
9
|
-
import { QuotaExceededError } from "../../permissions/errors";
|
|
10
8
|
import { AuthContextService } from "../../service";
|
|
11
|
-
import { UsageHookService } from "../../usage-hooks/service";
|
|
12
9
|
import type {
|
|
13
10
|
CreateUploadRequest,
|
|
14
11
|
CreateUploadResponse,
|
|
@@ -23,14 +20,11 @@ import type {
|
|
|
23
20
|
export const handleCreateUpload = (req: CreateUploadRequest) =>
|
|
24
21
|
Effect.gen(function* () {
|
|
25
22
|
const server = yield* UploadServer;
|
|
23
|
+
// Access auth context if available
|
|
26
24
|
const authService = yield* AuthContextService;
|
|
27
25
|
const authCache = yield* AuthCacheService;
|
|
28
|
-
const usageHookService = yield* UsageHookService;
|
|
29
26
|
const clientId = yield* authService.getClientId();
|
|
30
27
|
|
|
31
|
-
// Check permission for creating uploads
|
|
32
|
-
yield* authService.requirePermission(PERMISSIONS.UPLOAD.CREATE);
|
|
33
|
-
|
|
34
28
|
if (clientId) {
|
|
35
29
|
yield* Effect.logInfo(`[Upload] Creating upload for client: ${clientId}`);
|
|
36
30
|
}
|
|
@@ -57,28 +51,6 @@ export const handleCreateUpload = (req: CreateUploadRequest) =>
|
|
|
57
51
|
);
|
|
58
52
|
}
|
|
59
53
|
|
|
60
|
-
// Execute onUploadStart hook for quota checking
|
|
61
|
-
if (clientId) {
|
|
62
|
-
const hookResult = yield* usageHookService.onUploadStart({
|
|
63
|
-
clientId,
|
|
64
|
-
operation: "upload",
|
|
65
|
-
metadata: {
|
|
66
|
-
fileSize: parsedInputFile.data.size,
|
|
67
|
-
mimeType: parsedInputFile.data.type,
|
|
68
|
-
fileName: parsedInputFile.data.fileName,
|
|
69
|
-
},
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
if (hookResult.action === "abort") {
|
|
73
|
-
return yield* Effect.fail(
|
|
74
|
-
new QuotaExceededError(
|
|
75
|
-
hookResult.reason,
|
|
76
|
-
hookResult.code ?? "QUOTA_EXCEEDED",
|
|
77
|
-
),
|
|
78
|
-
);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
54
|
const fileCreated = yield* server.createUpload(
|
|
83
55
|
parsedInputFile.data,
|
|
84
56
|
clientId,
|
|
@@ -108,9 +80,6 @@ export const handleGetCapabilities = ({ storageId }: GetCapabilitiesRequest) =>
|
|
|
108
80
|
const authService = yield* AuthContextService;
|
|
109
81
|
const clientId = yield* authService.getClientId();
|
|
110
82
|
|
|
111
|
-
// Check permission for reading upload capabilities
|
|
112
|
-
yield* authService.requirePermission(PERMISSIONS.UPLOAD.READ);
|
|
113
|
-
|
|
114
83
|
const capabilities = yield* server.getCapabilities(storageId, clientId);
|
|
115
84
|
|
|
116
85
|
return {
|
|
@@ -126,11 +95,6 @@ export const handleGetCapabilities = ({ storageId }: GetCapabilitiesRequest) =>
|
|
|
126
95
|
export const handleGetUpload = ({ uploadId }: GetUploadRequest) =>
|
|
127
96
|
Effect.gen(function* () {
|
|
128
97
|
const server = yield* UploadServer;
|
|
129
|
-
const authService = yield* AuthContextService;
|
|
130
|
-
|
|
131
|
-
// Check permission for reading upload status
|
|
132
|
-
yield* authService.requirePermission(PERMISSIONS.UPLOAD.READ);
|
|
133
|
-
|
|
134
98
|
const fileResult = yield* server.getUpload(uploadId);
|
|
135
99
|
|
|
136
100
|
return {
|
|
@@ -142,16 +106,13 @@ export const handleGetUpload = ({ uploadId }: GetUploadRequest) =>
|
|
|
142
106
|
export const handleUploadChunk = (req: UploadChunkRequest) =>
|
|
143
107
|
Effect.gen(function* () {
|
|
144
108
|
const server = yield* UploadServer;
|
|
109
|
+
// Try to get auth from current request or cached auth
|
|
145
110
|
const authService = yield* AuthContextService;
|
|
146
111
|
const authCache = yield* AuthCacheService;
|
|
147
112
|
const metricsService = yield* MetricsService;
|
|
148
|
-
const usageHookService = yield* UsageHookService;
|
|
149
113
|
|
|
150
114
|
const { uploadId, data } = req;
|
|
151
115
|
|
|
152
|
-
// Check permission for creating uploads (chunks are part of creation)
|
|
153
|
-
yield* authService.requirePermission(PERMISSIONS.UPLOAD.CREATE);
|
|
154
|
-
|
|
155
116
|
// Try current auth first, fallback to cached auth
|
|
156
117
|
let clientId = yield* authService.getClientId();
|
|
157
118
|
let authMetadata = yield* authService.getMetadata();
|
|
@@ -167,7 +128,6 @@ export const handleUploadChunk = (req: UploadChunkRequest) =>
|
|
|
167
128
|
);
|
|
168
129
|
}
|
|
169
130
|
|
|
170
|
-
const startTime = Date.now();
|
|
171
131
|
const fileResult = yield* server.uploadChunk(uploadId, clientId, data);
|
|
172
132
|
|
|
173
133
|
// Clear cache and record metrics if upload is complete
|
|
@@ -180,6 +140,7 @@ export const handleUploadChunk = (req: UploadChunkRequest) =>
|
|
|
180
140
|
}
|
|
181
141
|
|
|
182
142
|
// Record upload metrics if we have organization ID
|
|
143
|
+
|
|
183
144
|
if (clientId && fileResult.size) {
|
|
184
145
|
yield* Effect.logInfo(
|
|
185
146
|
`[Upload] Recording metrics for org: ${clientId}, size: ${fileResult.size}`,
|
|
@@ -187,20 +148,6 @@ export const handleUploadChunk = (req: UploadChunkRequest) =>
|
|
|
187
148
|
yield* Effect.forkDaemon(
|
|
188
149
|
metricsService.recordUpload(clientId, fileResult.size, authMetadata),
|
|
189
150
|
);
|
|
190
|
-
|
|
191
|
-
// Execute onUploadComplete hook for usage tracking
|
|
192
|
-
const duration = Date.now() - startTime;
|
|
193
|
-
yield* Effect.forkDaemon(
|
|
194
|
-
usageHookService.onUploadComplete({
|
|
195
|
-
clientId,
|
|
196
|
-
operation: "upload",
|
|
197
|
-
metadata: {
|
|
198
|
-
uploadId,
|
|
199
|
-
fileSize: fileResult.size,
|
|
200
|
-
duration,
|
|
201
|
-
},
|
|
202
|
-
}),
|
|
203
|
-
);
|
|
204
151
|
} else {
|
|
205
152
|
yield* Effect.logWarning(
|
|
206
153
|
`[Upload] Cannot record metrics - missing organizationId or size`,
|
package/src/core/routes.ts
CHANGED
|
@@ -1,14 +1,7 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
DataStoreCapabilities,
|
|
3
|
-
DeadLetterCleanupOptions,
|
|
4
|
-
DeadLetterCleanupResult,
|
|
5
|
-
DeadLetterItem,
|
|
6
|
-
DeadLetterItemStatus,
|
|
7
|
-
DeadLetterListOptions,
|
|
8
|
-
DeadLetterQueueStats,
|
|
9
3
|
FlowData,
|
|
10
4
|
FlowJob,
|
|
11
|
-
HealthResponse as HealthResponseBody,
|
|
12
5
|
UploadFile,
|
|
13
6
|
} from "@uploadista/core";
|
|
14
7
|
import type { StandardResponse } from "../adapter/types";
|
|
@@ -24,20 +17,6 @@ export type UploadistaRouteType =
|
|
|
24
17
|
| "resume-flow"
|
|
25
18
|
| "pause-flow"
|
|
26
19
|
| "cancel-flow"
|
|
27
|
-
// DLQ Admin routes
|
|
28
|
-
| "dlq-list"
|
|
29
|
-
| "dlq-get"
|
|
30
|
-
| "dlq-retry"
|
|
31
|
-
| "dlq-retry-all"
|
|
32
|
-
| "dlq-delete"
|
|
33
|
-
| "dlq-resolve"
|
|
34
|
-
| "dlq-cleanup"
|
|
35
|
-
| "dlq-stats"
|
|
36
|
-
// Health check routes
|
|
37
|
-
| "health"
|
|
38
|
-
| "health-ready"
|
|
39
|
-
| "health-components"
|
|
40
|
-
// Error routes
|
|
41
20
|
| "not-found"
|
|
42
21
|
| "bad-request"
|
|
43
22
|
| "method-not-allowed"
|
|
@@ -175,128 +154,6 @@ export type CancelFlowResponse = UploadistaStandardResponse<
|
|
|
175
154
|
FlowJob
|
|
176
155
|
>;
|
|
177
156
|
|
|
178
|
-
// ============================================================================
|
|
179
|
-
// Dead Letter Queue Admin Routes
|
|
180
|
-
// ============================================================================
|
|
181
|
-
|
|
182
|
-
export type DlqListRequest = UploadistaRoute<"dlq-list"> & {
|
|
183
|
-
options?: DeadLetterListOptions;
|
|
184
|
-
};
|
|
185
|
-
export type DlqListResponse = UploadistaStandardResponse<
|
|
186
|
-
"dlq-list",
|
|
187
|
-
{ items: DeadLetterItem[]; total: number }
|
|
188
|
-
>;
|
|
189
|
-
|
|
190
|
-
export type DlqGetRequest = UploadistaRoute<"dlq-get"> & {
|
|
191
|
-
itemId: string;
|
|
192
|
-
};
|
|
193
|
-
export type DlqGetResponse = UploadistaStandardResponse<"dlq-get", DeadLetterItem>;
|
|
194
|
-
|
|
195
|
-
export type DlqRetryRequest = UploadistaRoute<"dlq-retry"> & {
|
|
196
|
-
itemId: string;
|
|
197
|
-
};
|
|
198
|
-
export type DlqRetryResponse = UploadistaStandardResponse<
|
|
199
|
-
"dlq-retry",
|
|
200
|
-
{ success: boolean; newJobId?: string }
|
|
201
|
-
>;
|
|
202
|
-
|
|
203
|
-
export type DlqRetryAllRequest = UploadistaRoute<"dlq-retry-all"> & {
|
|
204
|
-
options?: { status?: DeadLetterItemStatus; flowId?: string };
|
|
205
|
-
};
|
|
206
|
-
export type DlqRetryAllResponse = UploadistaStandardResponse<
|
|
207
|
-
"dlq-retry-all",
|
|
208
|
-
{ retried: number; succeeded: number; failed: number }
|
|
209
|
-
>;
|
|
210
|
-
|
|
211
|
-
export type DlqDeleteRequest = UploadistaRoute<"dlq-delete"> & {
|
|
212
|
-
itemId: string;
|
|
213
|
-
};
|
|
214
|
-
export type DlqDeleteResponse = UploadistaStandardResponse<
|
|
215
|
-
"dlq-delete",
|
|
216
|
-
{ success: boolean }
|
|
217
|
-
>;
|
|
218
|
-
|
|
219
|
-
export type DlqResolveRequest = UploadistaRoute<"dlq-resolve"> & {
|
|
220
|
-
itemId: string;
|
|
221
|
-
};
|
|
222
|
-
export type DlqResolveResponse = UploadistaStandardResponse<
|
|
223
|
-
"dlq-resolve",
|
|
224
|
-
DeadLetterItem
|
|
225
|
-
>;
|
|
226
|
-
|
|
227
|
-
export type DlqCleanupRequest = UploadistaRoute<"dlq-cleanup"> & {
|
|
228
|
-
options?: DeadLetterCleanupOptions;
|
|
229
|
-
};
|
|
230
|
-
export type DlqCleanupResponse = UploadistaStandardResponse<
|
|
231
|
-
"dlq-cleanup",
|
|
232
|
-
DeadLetterCleanupResult
|
|
233
|
-
>;
|
|
234
|
-
|
|
235
|
-
export type DlqStatsRequest = UploadistaRoute<"dlq-stats">;
|
|
236
|
-
export type DlqStatsResponse = UploadistaStandardResponse<
|
|
237
|
-
"dlq-stats",
|
|
238
|
-
DeadLetterQueueStats
|
|
239
|
-
>;
|
|
240
|
-
|
|
241
|
-
// ============================================================================
|
|
242
|
-
// Health Check Routes
|
|
243
|
-
// ============================================================================
|
|
244
|
-
|
|
245
|
-
/**
|
|
246
|
-
* Health check request base type with optional Accept header.
|
|
247
|
-
*/
|
|
248
|
-
type HealthCheckRequestBase = {
|
|
249
|
-
/** Accept header value for response format negotiation */
|
|
250
|
-
acceptHeader?: string | null;
|
|
251
|
-
};
|
|
252
|
-
|
|
253
|
-
/**
|
|
254
|
-
* Liveness health check request (GET /health or /healthz).
|
|
255
|
-
*/
|
|
256
|
-
export type HealthRequest = UploadistaRoute<"health"> & HealthCheckRequestBase;
|
|
257
|
-
|
|
258
|
-
/**
|
|
259
|
-
* Liveness health check response.
|
|
260
|
-
* Can return JSON or plain text based on Accept header.
|
|
261
|
-
*/
|
|
262
|
-
export type HealthResponse = UploadistaRoute<"health"> & {
|
|
263
|
-
status: 200;
|
|
264
|
-
headers: { "Content-Type": "application/json" | "text/plain" };
|
|
265
|
-
body: HealthResponseBody | string;
|
|
266
|
-
};
|
|
267
|
-
|
|
268
|
-
/**
|
|
269
|
-
* Readiness health check request (GET /ready or /readyz).
|
|
270
|
-
*/
|
|
271
|
-
export type HealthReadyRequest = UploadistaRoute<"health-ready"> &
|
|
272
|
-
HealthCheckRequestBase;
|
|
273
|
-
|
|
274
|
-
/**
|
|
275
|
-
* Readiness health check response.
|
|
276
|
-
* Returns 200 if healthy, 503 if unhealthy.
|
|
277
|
-
*/
|
|
278
|
-
export type HealthReadyResponse = UploadistaRoute<"health-ready"> & {
|
|
279
|
-
status: 200 | 503;
|
|
280
|
-
headers: { "Content-Type": "application/json" | "text/plain" };
|
|
281
|
-
body: HealthResponseBody | string;
|
|
282
|
-
};
|
|
283
|
-
|
|
284
|
-
/**
|
|
285
|
-
* Component details health check request (GET /health/components).
|
|
286
|
-
*/
|
|
287
|
-
export type HealthComponentsRequest = UploadistaRoute<"health-components"> &
|
|
288
|
-
HealthCheckRequestBase;
|
|
289
|
-
|
|
290
|
-
/**
|
|
291
|
-
* Component details health check response.
|
|
292
|
-
* Always returns 200 for debugging purposes.
|
|
293
|
-
*/
|
|
294
|
-
export type HealthComponentsResponse = UploadistaRoute<"health-components"> & {
|
|
295
|
-
status: 200;
|
|
296
|
-
headers: { "Content-Type": "application/json" | "text/plain" };
|
|
297
|
-
body: HealthResponseBody | string;
|
|
298
|
-
};
|
|
299
|
-
|
|
300
157
|
export type UploadistaRequest =
|
|
301
158
|
| CreateUploadRequest
|
|
302
159
|
| GetCapabilitiesRequest
|
|
@@ -308,20 +165,6 @@ export type UploadistaRequest =
|
|
|
308
165
|
| ResumeFlowRequest
|
|
309
166
|
| PauseFlowRequest
|
|
310
167
|
| CancelFlowRequest
|
|
311
|
-
// DLQ Admin requests
|
|
312
|
-
| DlqListRequest
|
|
313
|
-
| DlqGetRequest
|
|
314
|
-
| DlqRetryRequest
|
|
315
|
-
| DlqRetryAllRequest
|
|
316
|
-
| DlqDeleteRequest
|
|
317
|
-
| DlqResolveRequest
|
|
318
|
-
| DlqCleanupRequest
|
|
319
|
-
| DlqStatsRequest
|
|
320
|
-
// Health check requests
|
|
321
|
-
| HealthRequest
|
|
322
|
-
| HealthReadyRequest
|
|
323
|
-
| HealthComponentsRequest
|
|
324
|
-
// Error requests
|
|
325
168
|
| NotFoundRequest
|
|
326
169
|
| BadRequestRequest
|
|
327
170
|
| MethodNotAllowedRequest
|
|
@@ -338,20 +181,6 @@ export type UploadistaResponse =
|
|
|
338
181
|
| ResumeFlowResponse
|
|
339
182
|
| PauseFlowResponse
|
|
340
183
|
| CancelFlowResponse
|
|
341
|
-
// DLQ Admin responses
|
|
342
|
-
| DlqListResponse
|
|
343
|
-
| DlqGetResponse
|
|
344
|
-
| DlqRetryResponse
|
|
345
|
-
| DlqRetryAllResponse
|
|
346
|
-
| DlqDeleteResponse
|
|
347
|
-
| DlqResolveResponse
|
|
348
|
-
| DlqCleanupResponse
|
|
349
|
-
| DlqStatsResponse
|
|
350
|
-
// Health check responses
|
|
351
|
-
| HealthResponse
|
|
352
|
-
| HealthReadyResponse
|
|
353
|
-
| HealthComponentsResponse
|
|
354
|
-
// Error responses
|
|
355
184
|
| NotFoundResponse
|
|
356
185
|
| BadRequestResponse
|
|
357
186
|
| MethodNotAllowedResponse
|