@uploadista/core 0.0.13 → 0.0.14
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/{checksum-CtOagryS.mjs → checksum-BaO9w1gC.mjs} +2 -2
- package/dist/{checksum-CtOagryS.mjs.map → checksum-BaO9w1gC.mjs.map} +1 -1
- package/dist/{checksum-jmKtZ9W8.cjs → checksum-DXCv7Avr.cjs} +1 -1
- package/dist/errors/index.cjs +1 -1
- package/dist/errors/index.d.cts +1 -1
- package/dist/errors/index.d.mts +1 -1
- package/dist/errors/index.mjs +1 -1
- package/dist/flow/index.cjs +1 -1
- package/dist/flow/index.d.cts +5 -5
- package/dist/flow/index.d.mts +5 -5
- package/dist/flow/index.mjs +1 -1
- package/dist/flow-DhuIQwjv.mjs +2 -0
- package/dist/flow-DhuIQwjv.mjs.map +1 -0
- package/dist/flow-s_AlC4r5.cjs +1 -0
- package/dist/{index-Bi9YYid8.d.mts → index-3jSHmGwH.d.mts} +2 -2
- package/dist/{index-Bi9YYid8.d.mts.map → index-3jSHmGwH.d.mts.map} +1 -1
- package/dist/{index-4VDJDcWM.d.cts → index-5K4oXy67.d.cts} +822 -169
- package/dist/index-5K4oXy67.d.cts.map +1 -0
- package/dist/{index-RgOX4psL.d.mts → index-BB1v4Ynz.d.mts} +822 -169
- package/dist/index-BB1v4Ynz.d.mts.map +1 -0
- package/dist/{index-Cbf1OPLp.d.mts → index-Bu5i-gcV.d.mts} +2 -2
- package/dist/index-Bu5i-gcV.d.mts.map +1 -0
- package/dist/{index-De4wQJwR.d.cts → index-CHGBYDtr.d.cts} +2 -2
- package/dist/{index-De4wQJwR.d.cts.map → index-CHGBYDtr.d.cts.map} +1 -1
- package/dist/{index-qZ90PVNl.d.cts → index-T6MZvUlM.d.cts} +2 -2
- package/dist/{index-Cbf1OPLp.d.mts.map → index-T6MZvUlM.d.cts.map} +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +5 -5
- package/dist/index.d.mts +5 -5
- package/dist/index.mjs +1 -1
- package/dist/{stream-limiter-D9rrsvAT.cjs → stream-limiter-BcTJAjs-.cjs} +1 -1
- package/dist/{stream-limiter-D9KSAaoY.mjs → stream-limiter-D1-sVS5i.mjs} +2 -2
- package/dist/{stream-limiter-D9KSAaoY.mjs.map → stream-limiter-D1-sVS5i.mjs.map} +1 -1
- package/dist/streams/index.cjs +1 -1
- package/dist/streams/index.d.cts +2 -2
- package/dist/streams/index.d.mts +2 -2
- package/dist/streams/index.mjs +1 -1
- package/dist/testing/index.cjs +1 -1
- package/dist/testing/index.d.cts +4 -4
- package/dist/testing/index.d.mts +4 -4
- package/dist/testing/index.mjs +1 -1
- package/dist/types/index.cjs +1 -1
- package/dist/types/index.d.cts +4 -4
- package/dist/types/index.d.mts +4 -4
- package/dist/types/index.mjs +1 -1
- package/dist/types-B-EckCWW.cjs +1 -0
- package/dist/types-CO-R4pFG.mjs +2 -0
- package/dist/types-CO-R4pFG.mjs.map +1 -0
- package/dist/upload/index.cjs +1 -1
- package/dist/upload/index.d.cts +4 -4
- package/dist/upload/index.d.mts +4 -4
- package/dist/upload/index.mjs +1 -1
- package/dist/{upload-D-eiOIVG.cjs → upload-BwXGQQ26.cjs} +1 -1
- package/dist/upload-C_Ew1NMF.mjs +2 -0
- package/dist/{upload-Yj5lrtZo.mjs.map → upload-C_Ew1NMF.mjs.map} +1 -1
- package/dist/{uploadista-error-B-n8Kfyh.cjs → uploadista-error-Blmj3lpk.cjs} +5 -1
- package/dist/{uploadista-error-DUWw6OqS.d.mts → uploadista-error-Cpn3uBLO.d.mts} +2 -2
- package/dist/uploadista-error-Cpn3uBLO.d.mts.map +1 -0
- package/dist/{uploadista-error-BQLhNZcY.d.cts → uploadista-error-DgdQnozn.d.cts} +2 -2
- package/dist/uploadista-error-DgdQnozn.d.cts.map +1 -0
- package/dist/{uploadista-error-Buscq-FR.mjs → uploadista-error-DhNBioWq.mjs} +5 -1
- package/dist/uploadista-error-DhNBioWq.mjs.map +1 -0
- package/dist/utils/index.cjs +1 -1
- package/dist/utils/index.d.cts +2 -2
- package/dist/utils/index.d.mts +2 -2
- package/dist/utils/index.mjs +1 -1
- package/dist/{utils-BWiu6lqv.mjs → utils-7gziergl.mjs} +2 -2
- package/dist/{utils-BWiu6lqv.mjs.map → utils-7gziergl.mjs.map} +1 -1
- package/dist/{utils-_StwBtxT.cjs → utils-C_STf6Wl.cjs} +1 -1
- package/package.json +3 -3
- package/src/errors/uploadista-error.ts +21 -1
- package/src/flow/event.ts +28 -4
- package/src/flow/flow-server.ts +43 -12
- package/src/flow/flow.ts +92 -13
- package/src/flow/index.ts +7 -0
- package/src/flow/node-types/index.ts +85 -0
- package/src/flow/node.ts +48 -6
- package/src/flow/nodes/input-node.ts +2 -0
- package/src/flow/nodes/storage-node.ts +2 -0
- package/src/flow/type-guards.ts +293 -0
- package/src/flow/type-registry.ts +345 -0
- package/src/flow/types/flow-job.ts +22 -6
- package/src/flow/types/flow-types.ts +152 -3
- package/tests/flow/type-system.test.ts +799 -0
- package/dist/flow-ChADffZ5.cjs +0 -1
- package/dist/flow-_J9-Dm_m.mjs +0 -2
- package/dist/flow-_J9-Dm_m.mjs.map +0 -1
- package/dist/index-4VDJDcWM.d.cts.map +0 -1
- package/dist/index-RgOX4psL.d.mts.map +0 -1
- package/dist/index-qZ90PVNl.d.cts.map +0 -1
- package/dist/types-BI_KmpTc.mjs +0 -2
- package/dist/types-BI_KmpTc.mjs.map +0 -1
- package/dist/types-f08UsX4E.cjs +0 -1
- package/dist/upload-Yj5lrtZo.mjs +0 -2
- package/dist/uploadista-error-BQLhNZcY.d.cts.map +0 -1
- package/dist/uploadista-error-Buscq-FR.mjs.map +0 -1
- package/dist/uploadista-error-DUWw6OqS.d.mts.map +0 -1
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
* @see {@link FlowServer} for job management operations
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
+
import type { TypedOutput } from "./flow-types";
|
|
13
|
+
|
|
12
14
|
// import type { FlowData } from "@/flow";
|
|
13
15
|
|
|
14
16
|
/**
|
|
@@ -33,16 +35,25 @@ export type FlowJobTaskStatus =
|
|
|
33
35
|
*
|
|
34
36
|
* @property nodeId - Unique identifier of the node this task represents
|
|
35
37
|
* @property status - Current execution status of the node
|
|
36
|
-
* @property result -
|
|
38
|
+
* @property result - Node execution result data (can be partial data if paused, or complete data if finished)
|
|
37
39
|
* @property error - Error message if the node failed
|
|
38
40
|
* @property retryCount - Number of retry attempts made before success or final failure
|
|
39
41
|
* @property createdAt - When the task was created
|
|
40
42
|
* @property updatedAt - When the task was last updated
|
|
43
|
+
*
|
|
44
|
+
* @remarks
|
|
45
|
+
* The result field can contain:
|
|
46
|
+
* - Partial/intermediate data when status is "paused" (unknown type)
|
|
47
|
+
* - Complete data when status is "completed" (could be TypedOutput for output nodes)
|
|
48
|
+
* - undefined when status is "pending", "running", "started", or "failed"
|
|
49
|
+
*
|
|
50
|
+
* For type-safe access to final outputs, use FlowJob.result instead, which contains
|
|
51
|
+
* the array of TypedOutput from all output nodes.
|
|
41
52
|
*/
|
|
42
53
|
export type FlowJobTask = {
|
|
43
54
|
nodeId: string;
|
|
44
55
|
status: FlowJobTaskStatus;
|
|
45
|
-
result?: unknown; //
|
|
56
|
+
result?: unknown; // Can be partial data (paused) or complete data (completed)
|
|
46
57
|
error?: string; // Error message from failed execution
|
|
47
58
|
retryCount?: number; // Number of retry attempts made
|
|
48
59
|
createdAt: Date;
|
|
@@ -65,7 +76,7 @@ export type FlowJobTask = {
|
|
|
65
76
|
* @property tasks - Array of node execution tasks
|
|
66
77
|
* @property error - Error message if the job failed
|
|
67
78
|
* @property endedAt - When the job completed or failed
|
|
68
|
-
* @property result -
|
|
79
|
+
* @property result - Array of typed outputs from all output nodes (only set when completed)
|
|
69
80
|
* @property pausedAt - Node ID where execution is paused (if applicable)
|
|
70
81
|
* @property executionState - State needed to resume a paused flow
|
|
71
82
|
* @property intermediateFiles - File IDs to cleanup after completion
|
|
@@ -75,6 +86,7 @@ export type FlowJobTask = {
|
|
|
75
86
|
* - Paused jobs store execution state and can be resumed with new data
|
|
76
87
|
* - Intermediate files from non-output nodes are automatically cleaned up
|
|
77
88
|
* - Tasks are updated as nodes progress through their lifecycle
|
|
89
|
+
* - The result field now contains an array of TypedOutput for all output nodes
|
|
78
90
|
*
|
|
79
91
|
* @example
|
|
80
92
|
* ```typescript
|
|
@@ -88,7 +100,11 @@ export type FlowJobTask = {
|
|
|
88
100
|
* // Poll for status
|
|
89
101
|
* const status = yield* flowServer.getJobStatus(job.id);
|
|
90
102
|
* if (status.status === "completed") {
|
|
91
|
-
*
|
|
103
|
+
* // Access typed outputs
|
|
104
|
+
* console.log("Outputs:", status.result);
|
|
105
|
+
* for (const output of status.result || []) {
|
|
106
|
+
* console.log(`${output.nodeId} (${output.nodeType}):`, output.data);
|
|
107
|
+
* }
|
|
92
108
|
* } else if (status.status === "paused") {
|
|
93
109
|
* // Resume with additional data
|
|
94
110
|
* yield* flowServer.resumeFlow({
|
|
@@ -110,8 +126,8 @@ export type FlowJob = {
|
|
|
110
126
|
tasks: FlowJobTask[];
|
|
111
127
|
error?: string;
|
|
112
128
|
endedAt?: Date;
|
|
113
|
-
//
|
|
114
|
-
result?:
|
|
129
|
+
// Array of typed outputs from all output nodes (only populated when completed)
|
|
130
|
+
result?: TypedOutput[];
|
|
115
131
|
// Paused execution state
|
|
116
132
|
pausedAt?: string; // nodeId where execution is paused
|
|
117
133
|
executionState?: {
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
import type { Effect } from "effect";
|
|
16
16
|
import type { z } from "zod";
|
|
17
17
|
import type { UploadistaError } from "../../errors";
|
|
18
|
+
import type { UploadFile } from "../../types/upload-file";
|
|
18
19
|
import type { FlowEvent, FlowEventFlowEnd, FlowEventFlowStart } from "../event";
|
|
19
20
|
import { NodeType } from "../node";
|
|
20
21
|
|
|
@@ -40,6 +41,139 @@ export type FlowNodeData = {
|
|
|
40
41
|
type: NodeType;
|
|
41
42
|
};
|
|
42
43
|
|
|
44
|
+
/**
|
|
45
|
+
* Built-in typed outputs with automatic TypeScript narrowing.
|
|
46
|
+
*
|
|
47
|
+
* These outputs use discriminated unions to enable automatic type narrowing
|
|
48
|
+
* in switch statements without requiring type guards.
|
|
49
|
+
*
|
|
50
|
+
* @remarks
|
|
51
|
+
* Built-in types automatically narrow when using switch statements:
|
|
52
|
+
* ```typescript
|
|
53
|
+
* switch (output.nodeType) {
|
|
54
|
+
* case 'storage-output-v1':
|
|
55
|
+
* output.data.url // ✅ TypeScript knows data is UploadFile
|
|
56
|
+
* break;
|
|
57
|
+
* }
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export type BuiltInTypedOutput =
|
|
61
|
+
| {
|
|
62
|
+
nodeType: "storage-output-v1";
|
|
63
|
+
data: UploadFile;
|
|
64
|
+
nodeId: string;
|
|
65
|
+
timestamp: string;
|
|
66
|
+
}
|
|
67
|
+
| {
|
|
68
|
+
nodeType: "streaming-input-v1";
|
|
69
|
+
data: UploadFile;
|
|
70
|
+
nodeId: string;
|
|
71
|
+
timestamp: string;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Custom typed output for user-defined node types.
|
|
76
|
+
*
|
|
77
|
+
* Custom outputs require type guards for type narrowing:
|
|
78
|
+
* ```typescript
|
|
79
|
+
* if (isThumbnailOutput(output)) {
|
|
80
|
+
* output.data.width // ✅ Type guard narrows data to ThumbnailOutput
|
|
81
|
+
* }
|
|
82
|
+
* ```
|
|
83
|
+
*
|
|
84
|
+
* @template T - The TypeScript type of the output data
|
|
85
|
+
*/
|
|
86
|
+
export type CustomTypedOutput<T = unknown> = {
|
|
87
|
+
nodeType?: string; // Custom type ID or undefined for untyped nodes
|
|
88
|
+
data: T;
|
|
89
|
+
nodeId: string;
|
|
90
|
+
timestamp: string;
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Typed output structure from a flow node.
|
|
95
|
+
*
|
|
96
|
+
* This is a discriminated union that provides automatic type narrowing for
|
|
97
|
+
* built-in types while maintaining extensibility for custom types.
|
|
98
|
+
*
|
|
99
|
+
* @template T - The TypeScript type of the output data (for custom outputs)
|
|
100
|
+
*
|
|
101
|
+
* @property nodeId - Node instance ID that produced this output
|
|
102
|
+
* @property nodeType - Type ID from the registry (e.g., "storage-output-v1")
|
|
103
|
+
* @property data - The actual output data from the node
|
|
104
|
+
* @property timestamp - ISO 8601 timestamp when the result was produced
|
|
105
|
+
*
|
|
106
|
+
* @remarks
|
|
107
|
+
* **Built-in types (automatic narrowing):**
|
|
108
|
+
* - `storage-output-v1` - Storage node output (UploadFile)
|
|
109
|
+
* - `streaming-input-v1` - Streaming input node (UploadFile)
|
|
110
|
+
*
|
|
111
|
+
* Use switch statements for automatic narrowing:
|
|
112
|
+
* ```typescript
|
|
113
|
+
* for (const output of state.flowOutputs) {
|
|
114
|
+
* switch (output.nodeType) {
|
|
115
|
+
* case 'storage-output-v1':
|
|
116
|
+
* // ✅ output.data is automatically UploadFile
|
|
117
|
+
* console.log(output.data.url);
|
|
118
|
+
* break;
|
|
119
|
+
* case 'streaming-input-v1':
|
|
120
|
+
* // ✅ output.data is automatically UploadFile
|
|
121
|
+
* console.log(output.data.size);
|
|
122
|
+
* break;
|
|
123
|
+
* }
|
|
124
|
+
* }
|
|
125
|
+
* ```
|
|
126
|
+
*
|
|
127
|
+
* **Custom types (require type guards):**
|
|
128
|
+
* ```typescript
|
|
129
|
+
* import { isThumbnailOutput } from './type-guards';
|
|
130
|
+
*
|
|
131
|
+
* if (isThumbnailOutput(output)) {
|
|
132
|
+
* // ✅ Type guard narrows output.data to ThumbnailOutput
|
|
133
|
+
* console.log(output.data.width);
|
|
134
|
+
* }
|
|
135
|
+
* ```
|
|
136
|
+
*
|
|
137
|
+
* **Untyped nodes (backward compatible):**
|
|
138
|
+
* ```typescript
|
|
139
|
+
* const untypedOutput: TypedOutput = {
|
|
140
|
+
* nodeId: "custom-node-1",
|
|
141
|
+
* data: { custom: "data" },
|
|
142
|
+
* timestamp: "2024-01-15T10:30:00Z"
|
|
143
|
+
* };
|
|
144
|
+
* ```
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* ```typescript
|
|
148
|
+
* // Storage output result (built-in, automatic narrowing)
|
|
149
|
+
* const output: TypedOutput = {
|
|
150
|
+
* nodeId: "storage-1",
|
|
151
|
+
* nodeType: "storage-output-v1",
|
|
152
|
+
* data: {
|
|
153
|
+
* id: "file-123",
|
|
154
|
+
* url: "https://cdn.example.com/file.jpg",
|
|
155
|
+
* size: 1024000,
|
|
156
|
+
* // ... rest of UploadFile
|
|
157
|
+
* },
|
|
158
|
+
* timestamp: "2024-01-15T10:30:00Z"
|
|
159
|
+
* };
|
|
160
|
+
*
|
|
161
|
+
* // Custom output (requires type guard)
|
|
162
|
+
* const thumbnailOutput: TypedOutput<ThumbnailOutput> = {
|
|
163
|
+
* nodeId: "thumbnail-1",
|
|
164
|
+
* nodeType: "thumbnail-output-v1",
|
|
165
|
+
* data: {
|
|
166
|
+
* url: "https://cdn.example.com/thumb.jpg",
|
|
167
|
+
* width: 200,
|
|
168
|
+
* height: 200,
|
|
169
|
+
* format: "webp",
|
|
170
|
+
* },
|
|
171
|
+
* timestamp: "2024-01-15T10:30:00Z"
|
|
172
|
+
* };
|
|
173
|
+
* ```
|
|
174
|
+
*/
|
|
175
|
+
export type TypedOutput<T = unknown> = BuiltInTypedOutput | CustomTypedOutput<T>;
|
|
176
|
+
|
|
43
177
|
/**
|
|
44
178
|
* Result of a node execution - either complete or waiting for more data.
|
|
45
179
|
*
|
|
@@ -50,10 +184,15 @@ export type FlowNodeData = {
|
|
|
50
184
|
* data (e.g., chunked uploads, external service responses). The flow can be
|
|
51
185
|
* resumed later with the missing data.
|
|
52
186
|
*
|
|
187
|
+
* Results now include optional type information (`nodeType` and `nodeId`) to
|
|
188
|
+
* enable type-safe result consumption. These fields are automatically added
|
|
189
|
+
* by the node execution wrapper when a node is created with a `nodeTypeId`.
|
|
190
|
+
*
|
|
53
191
|
* @example
|
|
54
192
|
* ```typescript
|
|
55
|
-
* // Node completes immediately
|
|
193
|
+
* // Node completes immediately with type information
|
|
56
194
|
* return completeNodeExecution({ processedData });
|
|
195
|
+
* // Result will be wrapped with: { type: "complete", data, nodeType, nodeId }
|
|
57
196
|
*
|
|
58
197
|
* // Node waits for more chunks
|
|
59
198
|
* if (needsMoreData) {
|
|
@@ -62,8 +201,18 @@ export type FlowNodeData = {
|
|
|
62
201
|
* ```
|
|
63
202
|
*/
|
|
64
203
|
export type NodeExecutionResult<TOutput> =
|
|
65
|
-
| {
|
|
66
|
-
|
|
204
|
+
| {
|
|
205
|
+
type: "complete";
|
|
206
|
+
data: TOutput;
|
|
207
|
+
nodeType?: string;
|
|
208
|
+
nodeId?: string;
|
|
209
|
+
}
|
|
210
|
+
| {
|
|
211
|
+
type: "waiting";
|
|
212
|
+
partialData?: unknown;
|
|
213
|
+
nodeType?: string;
|
|
214
|
+
nodeId?: string;
|
|
215
|
+
};
|
|
67
216
|
|
|
68
217
|
/**
|
|
69
218
|
* Helper function to create a complete node execution result.
|