@uploadista/server 0.0.3
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/.turbo/turbo-build.log +5 -0
- package/.turbo/turbo-check.log +34 -0
- package/LICENSE +21 -0
- package/README.md +503 -0
- package/dist/auth/cache.d.ts +87 -0
- package/dist/auth/cache.d.ts.map +1 -0
- package/dist/auth/cache.js +121 -0
- package/dist/auth/cache.test.d.ts +2 -0
- package/dist/auth/cache.test.d.ts.map +1 -0
- package/dist/auth/cache.test.js +209 -0
- package/dist/auth/get-auth-credentials.d.ts +73 -0
- package/dist/auth/get-auth-credentials.d.ts.map +1 -0
- package/dist/auth/get-auth-credentials.js +55 -0
- package/dist/auth/index.d.ts +2 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +1 -0
- package/dist/auth/jwt/index.d.ts +38 -0
- package/dist/auth/jwt/index.d.ts.map +1 -0
- package/dist/auth/jwt/index.js +36 -0
- package/dist/auth/jwt/types.d.ts +77 -0
- package/dist/auth/jwt/types.d.ts.map +1 -0
- package/dist/auth/jwt/types.js +1 -0
- package/dist/auth/jwt/validate.d.ts +58 -0
- package/dist/auth/jwt/validate.d.ts.map +1 -0
- package/dist/auth/jwt/validate.js +226 -0
- package/dist/auth/jwt/validate.test.d.ts +2 -0
- package/dist/auth/jwt/validate.test.d.ts.map +1 -0
- package/dist/auth/jwt/validate.test.js +492 -0
- package/dist/auth/service.d.ts +63 -0
- package/dist/auth/service.d.ts.map +1 -0
- package/dist/auth/service.js +43 -0
- package/dist/auth/service.test.d.ts +2 -0
- package/dist/auth/service.test.d.ts.map +1 -0
- package/dist/auth/service.test.js +195 -0
- package/dist/auth/types.d.ts +38 -0
- package/dist/auth/types.d.ts.map +1 -0
- package/dist/auth/types.js +1 -0
- package/dist/cache.d.ts +87 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +121 -0
- package/dist/cache.test.d.ts +2 -0
- package/dist/cache.test.d.ts.map +1 -0
- package/dist/cache.test.js +209 -0
- package/dist/cloudflare-config.d.ts +72 -0
- package/dist/cloudflare-config.d.ts.map +1 -0
- package/dist/cloudflare-config.js +67 -0
- package/dist/error-types.d.ts +138 -0
- package/dist/error-types.d.ts.map +1 -0
- package/dist/error-types.js +155 -0
- package/dist/hono-adapter.d.ts +48 -0
- package/dist/hono-adapter.d.ts.map +1 -0
- package/dist/hono-adapter.js +58 -0
- package/dist/http-utils.d.ts +148 -0
- package/dist/http-utils.d.ts.map +1 -0
- package/dist/http-utils.js +233 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/layer-utils.d.ts +121 -0
- package/dist/layer-utils.d.ts.map +1 -0
- package/dist/layer-utils.js +80 -0
- package/dist/metrics/service.d.ts +26 -0
- package/dist/metrics/service.d.ts.map +1 -0
- package/dist/metrics/service.js +20 -0
- package/dist/plugins-typing.d.ts +11 -0
- package/dist/plugins-typing.d.ts.map +1 -0
- package/dist/plugins-typing.js +1 -0
- package/dist/service.d.ts +63 -0
- package/dist/service.d.ts.map +1 -0
- package/dist/service.js +43 -0
- package/dist/service.test.d.ts +2 -0
- package/dist/service.test.d.ts.map +1 -0
- package/dist/service.test.js +195 -0
- package/dist/types.d.ts +38 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +1 -0
- package/package.json +47 -0
- package/src/auth/get-auth-credentials.ts +97 -0
- package/src/auth/index.ts +1 -0
- package/src/cache.test.ts +306 -0
- package/src/cache.ts +204 -0
- package/src/error-types.ts +172 -0
- package/src/http-utils.ts +264 -0
- package/src/index.ts +8 -0
- package/src/layer-utils.ts +184 -0
- package/src/plugins-typing.ts +57 -0
- package/src/service.test.ts +275 -0
- package/src/service.ts +78 -0
- package/src/types.ts +40 -0
- package/tsconfig.json +13 -0
- package/tsconfig.tsbuildinfo +1 -0
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared HTTP utilities for server adapters
|
|
3
|
+
*
|
|
4
|
+
* This module provides routing and error handling utilities used across
|
|
5
|
+
* Hono, Express, and Fastify adapters for request parsing and response formatting.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Parses URL segments from a pathname, filtering out empty segments.
|
|
9
|
+
* Useful for extracting route components from request paths.
|
|
10
|
+
*
|
|
11
|
+
* @param pathname - The URL pathname (e.g., "/uploadista/api/upload/abc123")
|
|
12
|
+
* @returns Array of non-empty path segments
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* const segments = parseUrlSegments("/uploadista/api/upload/abc123");
|
|
17
|
+
* // => ["uploadista", "api", "upload", "abc123"]
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export declare const parseUrlSegments: (pathname: string) => string[];
|
|
21
|
+
/**
|
|
22
|
+
* Extracts the last segment from a URL pathname.
|
|
23
|
+
*
|
|
24
|
+
* @param pathname - The URL pathname to parse
|
|
25
|
+
* @returns The last non-empty segment, or undefined if none exists
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* const id = getLastSegment("/uploadista/api/upload/abc123");
|
|
30
|
+
* // => "abc123"
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export declare const getLastSegment: (pathname: string) => string | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* Checks if a pathname includes a specific base path and API prefix.
|
|
36
|
+
* Used to determine if a request should be handled by the Uploadista adapter.
|
|
37
|
+
*
|
|
38
|
+
* @param pathname - The request pathname
|
|
39
|
+
* @param basePath - The base path configured for the adapter (e.g., "uploadista")
|
|
40
|
+
* @returns true if the path includes `{basePath}/api/`
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```typescript
|
|
44
|
+
* const isUploadistaPath = hasBasePath("/uploadista/api/upload", "uploadista");
|
|
45
|
+
* // => true
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export declare const hasBasePath: (pathname: string, basePath: string) => boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Removes the base path prefix and returns clean route segments.
|
|
51
|
+
* Transforms "/uploadista/api/upload/abc123" → ["upload", "abc123"]
|
|
52
|
+
*
|
|
53
|
+
* @param pathname - The full request pathname
|
|
54
|
+
* @param basePath - The base path to remove (e.g., "uploadista")
|
|
55
|
+
* @returns Array of route segments without base path prefix
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```typescript
|
|
59
|
+
* const route = getRouteSegments("/uploadista/api/upload/abc123", "uploadista");
|
|
60
|
+
* // => ["upload", "abc123"]
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export declare const getRouteSegments: (pathname: string, basePath: string) => string[];
|
|
64
|
+
/**
|
|
65
|
+
* Standard error handler for flow and job operations.
|
|
66
|
+
* Maps application errors to appropriate HTTP status codes and error formats.
|
|
67
|
+
*
|
|
68
|
+
* Supports errors with `code`, `message`, `status`, and `details` properties.
|
|
69
|
+
* Maps error codes to HTTP status codes (e.g., NOT_FOUND → 404, VALIDATION_ERROR → 400).
|
|
70
|
+
*
|
|
71
|
+
* @param error - The error object to handle (can be any type)
|
|
72
|
+
* @returns Standardized error response with status, code, message, and optional details
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```typescript
|
|
76
|
+
* import { handleFlowError } from "@uploadista/server";
|
|
77
|
+
*
|
|
78
|
+
* const response = handleFlowError({
|
|
79
|
+
* code: "FLOW_JOB_NOT_FOUND",
|
|
80
|
+
* message: "Job not found",
|
|
81
|
+
* });
|
|
82
|
+
* // => { status: 404, code: "FLOW_JOB_NOT_FOUND", message: "Job not found" }
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
export declare const handleFlowError: (error: unknown) => {
|
|
86
|
+
status: number;
|
|
87
|
+
code: string;
|
|
88
|
+
message: string;
|
|
89
|
+
details?: unknown;
|
|
90
|
+
};
|
|
91
|
+
/**
|
|
92
|
+
* Extracts job ID from URL segments for job status endpoint.
|
|
93
|
+
* Expected URL format: `/uploadista/api/jobs/:jobId/status`
|
|
94
|
+
*
|
|
95
|
+
* @param urlSegments - Parsed URL segments (without base path)
|
|
96
|
+
* @returns The job ID if found, or undefined
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* ```typescript
|
|
100
|
+
* const jobId = extractJobIdFromStatus(["jobs", "job-123", "status"]);
|
|
101
|
+
* // => "job-123"
|
|
102
|
+
* ```
|
|
103
|
+
*/
|
|
104
|
+
export declare const extractJobIdFromStatus: (urlSegments: string[]) => string | undefined;
|
|
105
|
+
/**
|
|
106
|
+
* Extracts job ID and node ID from URL segments for continue flow endpoint.
|
|
107
|
+
* Expected URL format: `/uploadista/api/jobs/:jobId/continue/:nodeId`
|
|
108
|
+
*
|
|
109
|
+
* @param urlSegments - Parsed URL segments (without base path)
|
|
110
|
+
* @returns Object with extracted jobId and nodeId (either can be undefined if not found)
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* ```typescript
|
|
114
|
+
* const { jobId, nodeId } = extractJobAndNodeId([
|
|
115
|
+
* "jobs",
|
|
116
|
+
* "job-123",
|
|
117
|
+
* "continue",
|
|
118
|
+
* "node-456",
|
|
119
|
+
* ]);
|
|
120
|
+
* // => { jobId: "job-123", nodeId: "node-456" }
|
|
121
|
+
* ```
|
|
122
|
+
*/
|
|
123
|
+
export declare const extractJobAndNodeId: (urlSegments: string[]) => {
|
|
124
|
+
jobId: string | undefined;
|
|
125
|
+
nodeId: string | undefined;
|
|
126
|
+
};
|
|
127
|
+
/**
|
|
128
|
+
* Extracts flow ID and storage ID from URL segments.
|
|
129
|
+
* Expected URL format: `/uploadista/api/flow/:flowId/:storageId`
|
|
130
|
+
*
|
|
131
|
+
* Mutates the input array (removes last 2 elements).
|
|
132
|
+
*
|
|
133
|
+
* @param urlSegments - Parsed URL segments (will be mutated)
|
|
134
|
+
* @returns Object with extracted flowId and storageId
|
|
135
|
+
*
|
|
136
|
+
* @example
|
|
137
|
+
* ```typescript
|
|
138
|
+
* const segments = ["flow", "flow-123", "storage-456"];
|
|
139
|
+
* const { flowId, storageId } = extractFlowAndStorageId(segments);
|
|
140
|
+
* // => { flowId: "flow-123", storageId: "storage-456" }
|
|
141
|
+
* // segments is now ["flow"]
|
|
142
|
+
* ```
|
|
143
|
+
*/
|
|
144
|
+
export declare const extractFlowAndStorageId: (urlSegments: string[]) => {
|
|
145
|
+
flowId: string | undefined;
|
|
146
|
+
storageId: string | undefined;
|
|
147
|
+
};
|
|
148
|
+
//# sourceMappingURL=http-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-utils.d.ts","sourceRoot":"","sources":["../src/http-utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,gBAAgB,GAAI,UAAU,MAAM,KAAG,MAAM,EAEzD,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,cAAc,GAAI,UAAU,MAAM,KAAG,MAAM,GAAG,SAG1D,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,WAAW,GAAI,UAAU,MAAM,EAAE,UAAU,MAAM,KAAG,OAEhE,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,gBAAgB,GAC3B,UAAU,MAAM,EAChB,UAAU,MAAM,KACf,MAAM,EAER,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,eAAe,GAC1B,OAAO,OAAO,KACb;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAwFpE,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,sBAAsB,GACjC,aAAa,MAAM,EAAE,KACpB,MAAM,GAAG,SAEX,CAAC;AAEF;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,mBAAmB,GAC9B,aAAa,MAAM,EAAE,KACpB;IAAE,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAA;CAKzD,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,uBAAuB,GAClC,aAAa,MAAM,EAAE,KACpB;IAAE,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;CAK7D,CAAC"}
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared HTTP utilities for server adapters
|
|
3
|
+
*
|
|
4
|
+
* This module provides routing and error handling utilities used across
|
|
5
|
+
* Hono, Express, and Fastify adapters for request parsing and response formatting.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Parses URL segments from a pathname, filtering out empty segments.
|
|
9
|
+
* Useful for extracting route components from request paths.
|
|
10
|
+
*
|
|
11
|
+
* @param pathname - The URL pathname (e.g., "/uploadista/api/upload/abc123")
|
|
12
|
+
* @returns Array of non-empty path segments
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* const segments = parseUrlSegments("/uploadista/api/upload/abc123");
|
|
17
|
+
* // => ["uploadista", "api", "upload", "abc123"]
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export const parseUrlSegments = (pathname) => {
|
|
21
|
+
return pathname.split("/").filter(Boolean);
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Extracts the last segment from a URL pathname.
|
|
25
|
+
*
|
|
26
|
+
* @param pathname - The URL pathname to parse
|
|
27
|
+
* @returns The last non-empty segment, or undefined if none exists
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```typescript
|
|
31
|
+
* const id = getLastSegment("/uploadista/api/upload/abc123");
|
|
32
|
+
* // => "abc123"
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export const getLastSegment = (pathname) => {
|
|
36
|
+
const segments = parseUrlSegments(pathname);
|
|
37
|
+
return segments[segments.length - 1];
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Checks if a pathname includes a specific base path and API prefix.
|
|
41
|
+
* Used to determine if a request should be handled by the Uploadista adapter.
|
|
42
|
+
*
|
|
43
|
+
* @param pathname - The request pathname
|
|
44
|
+
* @param basePath - The base path configured for the adapter (e.g., "uploadista")
|
|
45
|
+
* @returns true if the path includes `{basePath}/api/`
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```typescript
|
|
49
|
+
* const isUploadistaPath = hasBasePath("/uploadista/api/upload", "uploadista");
|
|
50
|
+
* // => true
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
export const hasBasePath = (pathname, basePath) => {
|
|
54
|
+
return pathname.includes(`${basePath}/api/`);
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* Removes the base path prefix and returns clean route segments.
|
|
58
|
+
* Transforms "/uploadista/api/upload/abc123" → ["upload", "abc123"]
|
|
59
|
+
*
|
|
60
|
+
* @param pathname - The full request pathname
|
|
61
|
+
* @param basePath - The base path to remove (e.g., "uploadista")
|
|
62
|
+
* @returns Array of route segments without base path prefix
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```typescript
|
|
66
|
+
* const route = getRouteSegments("/uploadista/api/upload/abc123", "uploadista");
|
|
67
|
+
* // => ["upload", "abc123"]
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
export const getRouteSegments = (pathname, basePath) => {
|
|
71
|
+
return pathname.replace(`${basePath}/api/`, "").split("/").filter(Boolean);
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* Standard error handler for flow and job operations.
|
|
75
|
+
* Maps application errors to appropriate HTTP status codes and error formats.
|
|
76
|
+
*
|
|
77
|
+
* Supports errors with `code`, `message`, `status`, and `details` properties.
|
|
78
|
+
* Maps error codes to HTTP status codes (e.g., NOT_FOUND → 404, VALIDATION_ERROR → 400).
|
|
79
|
+
*
|
|
80
|
+
* @param error - The error object to handle (can be any type)
|
|
81
|
+
* @returns Standardized error response with status, code, message, and optional details
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```typescript
|
|
85
|
+
* import { handleFlowError } from "@uploadista/server";
|
|
86
|
+
*
|
|
87
|
+
* const response = handleFlowError({
|
|
88
|
+
* code: "FLOW_JOB_NOT_FOUND",
|
|
89
|
+
* message: "Job not found",
|
|
90
|
+
* });
|
|
91
|
+
* // => { status: 404, code: "FLOW_JOB_NOT_FOUND", message: "Job not found" }
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
export const handleFlowError = (error) => {
|
|
95
|
+
let status = 500;
|
|
96
|
+
let code = "UNKNOWN_ERROR";
|
|
97
|
+
let message = "Internal server error";
|
|
98
|
+
let details;
|
|
99
|
+
if (typeof error === "object" && error !== null) {
|
|
100
|
+
const errorObj = error;
|
|
101
|
+
// Extract error code
|
|
102
|
+
if ("code" in errorObj && typeof errorObj.code === "string") {
|
|
103
|
+
code = errorObj.code;
|
|
104
|
+
}
|
|
105
|
+
// Extract message
|
|
106
|
+
if ("message" in errorObj && typeof errorObj.message === "string") {
|
|
107
|
+
message = errorObj.message;
|
|
108
|
+
}
|
|
109
|
+
else if ("body" in errorObj && typeof errorObj.body === "string") {
|
|
110
|
+
// Support UploadistaError's body property
|
|
111
|
+
message = errorObj.body;
|
|
112
|
+
}
|
|
113
|
+
// Extract details if present
|
|
114
|
+
if ("details" in errorObj) {
|
|
115
|
+
details = errorObj.details;
|
|
116
|
+
}
|
|
117
|
+
// Map error codes to HTTP status codes
|
|
118
|
+
if ("status" in errorObj && typeof errorObj.status === "number") {
|
|
119
|
+
status = errorObj.status;
|
|
120
|
+
}
|
|
121
|
+
else if ("code" in errorObj) {
|
|
122
|
+
// Fallback: derive status from common error codes
|
|
123
|
+
switch (errorObj.code) {
|
|
124
|
+
case "FILE_NOT_FOUND":
|
|
125
|
+
case "FLOW_JOB_NOT_FOUND":
|
|
126
|
+
case "UPLOAD_ID_NOT_FOUND":
|
|
127
|
+
status = 404;
|
|
128
|
+
break;
|
|
129
|
+
case "FLOW_JOB_ERROR":
|
|
130
|
+
case "VALIDATION_ERROR":
|
|
131
|
+
case "INVALID_METADATA":
|
|
132
|
+
case "INVALID_LENGTH":
|
|
133
|
+
case "ABORTED":
|
|
134
|
+
case "INVALID_TERMINATION":
|
|
135
|
+
status = 400;
|
|
136
|
+
break;
|
|
137
|
+
case "INVALID_OFFSET":
|
|
138
|
+
status = 409;
|
|
139
|
+
break;
|
|
140
|
+
case "ERR_SIZE_EXCEEDED":
|
|
141
|
+
case "ERR_MAX_SIZE_EXCEEDED":
|
|
142
|
+
status = 413;
|
|
143
|
+
break;
|
|
144
|
+
case "FILE_NO_LONGER_EXISTS":
|
|
145
|
+
status = 410;
|
|
146
|
+
break;
|
|
147
|
+
case "MISSING_OFFSET":
|
|
148
|
+
case "INVALID_CONTENT_TYPE":
|
|
149
|
+
status = 403;
|
|
150
|
+
break;
|
|
151
|
+
default:
|
|
152
|
+
status = 500;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
// Special handling for specific error messages
|
|
156
|
+
if ("message" in errorObj && errorObj.message === "Invalid JSON body") {
|
|
157
|
+
status = 400;
|
|
158
|
+
code = "VALIDATION_ERROR";
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
const result = {
|
|
162
|
+
status,
|
|
163
|
+
code,
|
|
164
|
+
message,
|
|
165
|
+
};
|
|
166
|
+
if (details !== undefined) {
|
|
167
|
+
result.details = details;
|
|
168
|
+
}
|
|
169
|
+
return result;
|
|
170
|
+
};
|
|
171
|
+
/**
|
|
172
|
+
* Extracts job ID from URL segments for job status endpoint.
|
|
173
|
+
* Expected URL format: `/uploadista/api/jobs/:jobId/status`
|
|
174
|
+
*
|
|
175
|
+
* @param urlSegments - Parsed URL segments (without base path)
|
|
176
|
+
* @returns The job ID if found, or undefined
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* ```typescript
|
|
180
|
+
* const jobId = extractJobIdFromStatus(["jobs", "job-123", "status"]);
|
|
181
|
+
* // => "job-123"
|
|
182
|
+
* ```
|
|
183
|
+
*/
|
|
184
|
+
export const extractJobIdFromStatus = (urlSegments) => {
|
|
185
|
+
return urlSegments[urlSegments.length - 2];
|
|
186
|
+
};
|
|
187
|
+
/**
|
|
188
|
+
* Extracts job ID and node ID from URL segments for continue flow endpoint.
|
|
189
|
+
* Expected URL format: `/uploadista/api/jobs/:jobId/continue/:nodeId`
|
|
190
|
+
*
|
|
191
|
+
* @param urlSegments - Parsed URL segments (without base path)
|
|
192
|
+
* @returns Object with extracted jobId and nodeId (either can be undefined if not found)
|
|
193
|
+
*
|
|
194
|
+
* @example
|
|
195
|
+
* ```typescript
|
|
196
|
+
* const { jobId, nodeId } = extractJobAndNodeId([
|
|
197
|
+
* "jobs",
|
|
198
|
+
* "job-123",
|
|
199
|
+
* "continue",
|
|
200
|
+
* "node-456",
|
|
201
|
+
* ]);
|
|
202
|
+
* // => { jobId: "job-123", nodeId: "node-456" }
|
|
203
|
+
* ```
|
|
204
|
+
*/
|
|
205
|
+
export const extractJobAndNodeId = (urlSegments) => {
|
|
206
|
+
return {
|
|
207
|
+
jobId: urlSegments[urlSegments.length - 3],
|
|
208
|
+
nodeId: urlSegments[urlSegments.length - 1],
|
|
209
|
+
};
|
|
210
|
+
};
|
|
211
|
+
/**
|
|
212
|
+
* Extracts flow ID and storage ID from URL segments.
|
|
213
|
+
* Expected URL format: `/uploadista/api/flow/:flowId/:storageId`
|
|
214
|
+
*
|
|
215
|
+
* Mutates the input array (removes last 2 elements).
|
|
216
|
+
*
|
|
217
|
+
* @param urlSegments - Parsed URL segments (will be mutated)
|
|
218
|
+
* @returns Object with extracted flowId and storageId
|
|
219
|
+
*
|
|
220
|
+
* @example
|
|
221
|
+
* ```typescript
|
|
222
|
+
* const segments = ["flow", "flow-123", "storage-456"];
|
|
223
|
+
* const { flowId, storageId } = extractFlowAndStorageId(segments);
|
|
224
|
+
* // => { flowId: "flow-123", storageId: "storage-456" }
|
|
225
|
+
* // segments is now ["flow"]
|
|
226
|
+
* ```
|
|
227
|
+
*/
|
|
228
|
+
export const extractFlowAndStorageId = (urlSegments) => {
|
|
229
|
+
return {
|
|
230
|
+
storageId: urlSegments.pop(),
|
|
231
|
+
flowId: urlSegments.pop(),
|
|
232
|
+
};
|
|
233
|
+
};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from "./auth";
|
|
2
|
+
export * from "./cache";
|
|
3
|
+
export * from "./error-types";
|
|
4
|
+
export * from "./http-utils";
|
|
5
|
+
export * from "./layer-utils";
|
|
6
|
+
export * from "./plugins-typing";
|
|
7
|
+
export * from "./service";
|
|
8
|
+
export * from "./types";
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC;AACvB,cAAc,SAAS,CAAC;AACxB,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import type { FlowProvider } from "@uploadista/core/flow";
|
|
2
|
+
import { type BaseEventEmitterService, type BaseKvStoreService, type UploadFileDataStore, type UploadFileDataStores, type UploadFileKVStore } from "@uploadista/core/types";
|
|
3
|
+
import { type UploadServer } from "@uploadista/core/upload";
|
|
4
|
+
import type { GenerateId } from "@uploadista/core/utils";
|
|
5
|
+
import { Layer } from "effect";
|
|
6
|
+
/**
|
|
7
|
+
* Configuration for creating upload server layers.
|
|
8
|
+
* Specifies all dependencies needed by the upload server Effect Layer.
|
|
9
|
+
*
|
|
10
|
+
* @property kvStore - Key-value store for upload metadata
|
|
11
|
+
* @property eventEmitter - Event emitter for upload progress events
|
|
12
|
+
* @property dataStore - File data storage implementation
|
|
13
|
+
* @property bufferedDataStore - Optional buffered storage for performance optimization
|
|
14
|
+
* @property generateId - Optional custom ID generator (uses default if omitted)
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* import { createUploadServerLayer } from "@uploadista/server";
|
|
19
|
+
*
|
|
20
|
+
* const uploadLayerConfig: UploadServerLayerConfig = {
|
|
21
|
+
* kvStore: redisKvStore,
|
|
22
|
+
* eventEmitter: webSocketEventEmitter,
|
|
23
|
+
* dataStore: s3DataStore,
|
|
24
|
+
* };
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export interface UploadServerLayerConfig {
|
|
28
|
+
kvStore: Layer.Layer<BaseKvStoreService>;
|
|
29
|
+
eventEmitter: Layer.Layer<BaseEventEmitterService>;
|
|
30
|
+
dataStore: Layer.Layer<UploadFileDataStores, never, UploadFileKVStore>;
|
|
31
|
+
bufferedDataStore?: Layer.Layer<UploadFileDataStore, never, UploadFileKVStore>;
|
|
32
|
+
generateId?: Layer.Layer<GenerateId>;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Configuration for creating flow server layers.
|
|
36
|
+
* Specifies all dependencies needed by the flow processing server.
|
|
37
|
+
*
|
|
38
|
+
* @property kvStore - Key-value store for flow job metadata
|
|
39
|
+
* @property eventEmitter - Event emitter for flow progress events
|
|
40
|
+
* @property flowProvider - Factory function for creating flows
|
|
41
|
+
* @property uploadServer - Upload server layer (used by flows for uploads)
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```typescript
|
|
45
|
+
* import { createFlowServerLayer } from "@uploadista/server";
|
|
46
|
+
*
|
|
47
|
+
* const flowLayerConfig: FlowServerLayerConfig = {
|
|
48
|
+
* kvStore: redisKvStore,
|
|
49
|
+
* eventEmitter: webSocketEventEmitter,
|
|
50
|
+
* flowProvider: createFlowsEffect,
|
|
51
|
+
* uploadServer: uploadServerLayer,
|
|
52
|
+
* };
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export interface FlowServerLayerConfig {
|
|
56
|
+
kvStore: Layer.Layer<BaseKvStoreService>;
|
|
57
|
+
eventEmitter: Layer.Layer<BaseEventEmitterService>;
|
|
58
|
+
flowProvider: Layer.Layer<FlowProvider>;
|
|
59
|
+
uploadServer: Layer.Layer<UploadServer>;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Creates the upload server layer with all dependencies composed.
|
|
63
|
+
* This layer handles file uploads with chunked transfer, resumption, and metadata tracking.
|
|
64
|
+
*
|
|
65
|
+
* The created layer includes:
|
|
66
|
+
* - Upload KV store (metadata tracking)
|
|
67
|
+
* - Data store (file storage)
|
|
68
|
+
* - Event emitter (progress notifications)
|
|
69
|
+
* - Optional buffered data store (performance optimization)
|
|
70
|
+
* - Optional custom ID generator
|
|
71
|
+
*
|
|
72
|
+
* @param config - Upload server layer configuration
|
|
73
|
+
* @returns Effect Layer providing UploadServer
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* ```typescript
|
|
77
|
+
* import { createUploadServerLayer } from "@uploadista/server";
|
|
78
|
+
* import { Layer } from "effect";
|
|
79
|
+
*
|
|
80
|
+
* const uploadServerLayer = createUploadServerLayer({
|
|
81
|
+
* kvStore: redisKvStore,
|
|
82
|
+
* eventEmitter: webSocketEventEmitter,
|
|
83
|
+
* dataStore: s3DataStore,
|
|
84
|
+
* });
|
|
85
|
+
*
|
|
86
|
+
* // Use in application
|
|
87
|
+
* const app = Layer.provide(appLogic, uploadServerLayer);
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
export declare const createUploadServerLayer: ({ kvStore, eventEmitter, dataStore, bufferedDataStore, generateId, }: UploadServerLayerConfig) => Layer.Layer<UploadServer, never, never>;
|
|
91
|
+
/**
|
|
92
|
+
* Creates the flow server layer with all dependencies composed.
|
|
93
|
+
* This layer handles file processing workflows with multi-stage pipelines.
|
|
94
|
+
*
|
|
95
|
+
* The created layer includes:
|
|
96
|
+
* - Flow job KV store (job metadata and state)
|
|
97
|
+
* - Event emitter (progress notifications)
|
|
98
|
+
* - Flow provider (flow definitions)
|
|
99
|
+
* - Upload server (for uploads within flows)
|
|
100
|
+
*
|
|
101
|
+
* @param config - Flow server layer configuration
|
|
102
|
+
* @returns Effect Layer providing FlowServer
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* ```typescript
|
|
106
|
+
* import { createFlowServerLayer } from "@uploadista/server";
|
|
107
|
+
* import { Layer } from "effect";
|
|
108
|
+
*
|
|
109
|
+
* const flowServerLayer = createFlowServerLayer({
|
|
110
|
+
* kvStore: redisKvStore,
|
|
111
|
+
* eventEmitter: webSocketEventEmitter,
|
|
112
|
+
* flowProvider: createFlowsEffect,
|
|
113
|
+
* uploadServer: uploadServerLayer,
|
|
114
|
+
* });
|
|
115
|
+
*
|
|
116
|
+
* // Use in application
|
|
117
|
+
* const app = Layer.provide(appLogic, flowServerLayer);
|
|
118
|
+
* ```
|
|
119
|
+
*/
|
|
120
|
+
export declare const createFlowServerLayer: ({ kvStore, eventEmitter, flowProvider, uploadServer, }: FlowServerLayerConfig) => Layer.Layer<import("@uploadista/core").FlowServer, never, never>;
|
|
121
|
+
//# sourceMappingURL=layer-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layer-utils.d.ts","sourceRoot":"","sources":["../src/layer-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAE1D,OAAO,EACL,KAAK,uBAAuB,EAC5B,KAAK,kBAAkB,EAGvB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EAGvB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,KAAK,YAAY,EAAgB,MAAM,yBAAyB,CAAC;AAC1E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAE/B;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;IACzC,YAAY,EAAE,KAAK,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;IACnD,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,oBAAoB,EAAE,KAAK,EAAE,iBAAiB,CAAC,CAAC;IACvE,iBAAiB,CAAC,EAAE,KAAK,CAAC,KAAK,CAC7B,mBAAmB,EACnB,KAAK,EACL,iBAAiB,CAClB,CAAC;IACF,UAAU,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;CACtC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;IACzC,YAAY,EAAE,KAAK,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;IACnD,YAAY,EAAE,KAAK,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IACxC,YAAY,EAAE,KAAK,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;CACzC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,uBAAuB,GAAI,sEAMrC,uBAAuB,4CAqBzB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,qBAAqB,GAAI,wDAKnC,qBAAqB,qEAavB,CAAC"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { flowServer } from "@uploadista/core/flow";
|
|
2
|
+
import { flowEventEmitter, flowJobKvStore, uploadEventEmitter, uploadFileKvStore, } from "@uploadista/core/types";
|
|
3
|
+
import { uploadServer } from "@uploadista/core/upload";
|
|
4
|
+
import { Layer } from "effect";
|
|
5
|
+
/**
|
|
6
|
+
* Creates the upload server layer with all dependencies composed.
|
|
7
|
+
* This layer handles file uploads with chunked transfer, resumption, and metadata tracking.
|
|
8
|
+
*
|
|
9
|
+
* The created layer includes:
|
|
10
|
+
* - Upload KV store (metadata tracking)
|
|
11
|
+
* - Data store (file storage)
|
|
12
|
+
* - Event emitter (progress notifications)
|
|
13
|
+
* - Optional buffered data store (performance optimization)
|
|
14
|
+
* - Optional custom ID generator
|
|
15
|
+
*
|
|
16
|
+
* @param config - Upload server layer configuration
|
|
17
|
+
* @returns Effect Layer providing UploadServer
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* import { createUploadServerLayer } from "@uploadista/server";
|
|
22
|
+
* import { Layer } from "effect";
|
|
23
|
+
*
|
|
24
|
+
* const uploadServerLayer = createUploadServerLayer({
|
|
25
|
+
* kvStore: redisKvStore,
|
|
26
|
+
* eventEmitter: webSocketEventEmitter,
|
|
27
|
+
* dataStore: s3DataStore,
|
|
28
|
+
* });
|
|
29
|
+
*
|
|
30
|
+
* // Use in application
|
|
31
|
+
* const app = Layer.provide(appLogic, uploadServerLayer);
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export const createUploadServerLayer = ({ kvStore, eventEmitter, dataStore, bufferedDataStore, generateId, }) => {
|
|
35
|
+
// Set up upload server dependencies
|
|
36
|
+
const uploadFileKVStoreLayer = Layer.provide(uploadFileKvStore, kvStore);
|
|
37
|
+
const uploadDataStoreLayer = Layer.provide(dataStore, uploadFileKVStoreLayer);
|
|
38
|
+
const uploadBufferedDataStoreLayer = bufferedDataStore
|
|
39
|
+
? Layer.provide(bufferedDataStore, uploadFileKVStoreLayer)
|
|
40
|
+
: Layer.empty;
|
|
41
|
+
const uploadEventEmitterLayer = Layer.provide(uploadEventEmitter, eventEmitter);
|
|
42
|
+
const uploadServerLayers = Layer.mergeAll(uploadDataStoreLayer, uploadFileKVStoreLayer, uploadEventEmitterLayer, ...(generateId ? [generateId] : []), uploadBufferedDataStoreLayer);
|
|
43
|
+
return Layer.provide(uploadServer, uploadServerLayers);
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Creates the flow server layer with all dependencies composed.
|
|
47
|
+
* This layer handles file processing workflows with multi-stage pipelines.
|
|
48
|
+
*
|
|
49
|
+
* The created layer includes:
|
|
50
|
+
* - Flow job KV store (job metadata and state)
|
|
51
|
+
* - Event emitter (progress notifications)
|
|
52
|
+
* - Flow provider (flow definitions)
|
|
53
|
+
* - Upload server (for uploads within flows)
|
|
54
|
+
*
|
|
55
|
+
* @param config - Flow server layer configuration
|
|
56
|
+
* @returns Effect Layer providing FlowServer
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```typescript
|
|
60
|
+
* import { createFlowServerLayer } from "@uploadista/server";
|
|
61
|
+
* import { Layer } from "effect";
|
|
62
|
+
*
|
|
63
|
+
* const flowServerLayer = createFlowServerLayer({
|
|
64
|
+
* kvStore: redisKvStore,
|
|
65
|
+
* eventEmitter: webSocketEventEmitter,
|
|
66
|
+
* flowProvider: createFlowsEffect,
|
|
67
|
+
* uploadServer: uploadServerLayer,
|
|
68
|
+
* });
|
|
69
|
+
*
|
|
70
|
+
* // Use in application
|
|
71
|
+
* const app = Layer.provide(appLogic, flowServerLayer);
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
export const createFlowServerLayer = ({ kvStore, eventEmitter, flowProvider, uploadServer, }) => {
|
|
75
|
+
// Set up flow server dependencies
|
|
76
|
+
const flowJobKVStoreLayer = Layer.provide(flowJobKvStore, kvStore);
|
|
77
|
+
const flowEventEmitterLayer = Layer.provide(flowEventEmitter, eventEmitter);
|
|
78
|
+
const flowServerLayers = Layer.mergeAll(flowProvider, flowEventEmitterLayer, flowJobKVStoreLayer, uploadServer);
|
|
79
|
+
return Layer.provide(flowServer, flowServerLayers);
|
|
80
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Database } from "@uploadista/orm";
|
|
2
|
+
import { Context, Effect, Layer } from "effect";
|
|
3
|
+
declare const MetricsService_base: Context.TagClass<MetricsService, "MetricsService", {
|
|
4
|
+
/**
|
|
5
|
+
* Record upload metrics for an organization
|
|
6
|
+
*/
|
|
7
|
+
readonly recordUpload: (organizationId: string, bytes: number) => Effect.Effect<void, never>;
|
|
8
|
+
}>;
|
|
9
|
+
/**
|
|
10
|
+
* Metrics Recording Service
|
|
11
|
+
*
|
|
12
|
+
* Provides access to metrics recording functionality throughout
|
|
13
|
+
* the upload and flow processing pipeline. The service is provided
|
|
14
|
+
* via Effect Layer and can be accessed using Effect.service().
|
|
15
|
+
*/
|
|
16
|
+
export declare class MetricsService extends MetricsService_base {
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Creates a MetricsService Layer from a Database.
|
|
20
|
+
*
|
|
21
|
+
* @param db - The database instance
|
|
22
|
+
* @returns Effect Layer providing MetricsService
|
|
23
|
+
*/
|
|
24
|
+
export declare const MetricsServiceLive: (db: Database) => Layer.Layer<MetricsService>;
|
|
25
|
+
export {};
|
|
26
|
+
//# sourceMappingURL=service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/metrics/service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAEhD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;;IAY5C;;OAEG;2BACoB,CACrB,cAAc,EAAE,MAAM,EACtB,KAAK,EAAE,MAAM,KACV,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC;;AAhBnC;;;;;;GAMG;AACH,qBAAa,cAAe,SAAQ,mBAWjC;CAAG;AAEN;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,GAAI,IAAI,QAAQ,KAAG,KAAK,CAAC,KAAK,CAAC,cAAc,CAMxE,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { recordUploadMetrics } from "@uploadista/server-metrics";
|
|
2
|
+
import { Context, Effect, Layer } from "effect";
|
|
3
|
+
/**
|
|
4
|
+
* Metrics Recording Service
|
|
5
|
+
*
|
|
6
|
+
* Provides access to metrics recording functionality throughout
|
|
7
|
+
* the upload and flow processing pipeline. The service is provided
|
|
8
|
+
* via Effect Layer and can be accessed using Effect.service().
|
|
9
|
+
*/
|
|
10
|
+
export class MetricsService extends Context.Tag("MetricsService")() {
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Creates a MetricsService Layer from a Database.
|
|
14
|
+
*
|
|
15
|
+
* @param db - The database instance
|
|
16
|
+
* @returns Effect Layer providing MetricsService
|
|
17
|
+
*/
|
|
18
|
+
export const MetricsServiceLive = (db) => Layer.succeed(MetricsService, {
|
|
19
|
+
recordUpload: (organizationId, bytes) => recordUploadMetrics(db, organizationId, bytes).pipe(Effect.catchAll(() => Effect.void)),
|
|
20
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Flow, UploadServer } from "@uploadista/core";
|
|
2
|
+
import type { Effect, Layer } from "effect";
|
|
3
|
+
import type z from "zod";
|
|
4
|
+
export type LayerSuccessUnion<Layers extends readonly Layer.Layer<any, never, never>[]> = Layers[number] extends Layer.Layer<infer Success, never, never> ? Success : never;
|
|
5
|
+
export 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;
|
|
6
|
+
export type FlowRequirementsOf<TFlows extends (flowId: string, clientId: string | null) => Effect.Effect<unknown, unknown, unknown>> = FlowSuccess<TFlows> extends Flow<z.ZodSchema<unknown>, z.ZodSchema<unknown>, infer R> ? Exclude<R, UploadServer> : never;
|
|
7
|
+
export type RequiredPluginsOf<TFlows extends (flowId: string, clientId: string | null) => Effect.Effect<unknown, unknown, unknown>> = Exclude<FlowRequirementsOf<TFlows>, UploadServer>;
|
|
8
|
+
export 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 : {
|
|
9
|
+
__missingPlugins: Exclude<RequiredPluginsOf<TFlows>, LayerSuccessUnion<TPlugins>>;
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=plugins-typing.d.ts.map
|