@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.
Files changed (97) hide show
  1. package/dist/{checksum-CtOagryS.mjs → checksum-BaO9w1gC.mjs} +2 -2
  2. package/dist/{checksum-CtOagryS.mjs.map → checksum-BaO9w1gC.mjs.map} +1 -1
  3. package/dist/{checksum-jmKtZ9W8.cjs → checksum-DXCv7Avr.cjs} +1 -1
  4. package/dist/errors/index.cjs +1 -1
  5. package/dist/errors/index.d.cts +1 -1
  6. package/dist/errors/index.d.mts +1 -1
  7. package/dist/errors/index.mjs +1 -1
  8. package/dist/flow/index.cjs +1 -1
  9. package/dist/flow/index.d.cts +5 -5
  10. package/dist/flow/index.d.mts +5 -5
  11. package/dist/flow/index.mjs +1 -1
  12. package/dist/flow-DhuIQwjv.mjs +2 -0
  13. package/dist/flow-DhuIQwjv.mjs.map +1 -0
  14. package/dist/flow-s_AlC4r5.cjs +1 -0
  15. package/dist/{index-Bi9YYid8.d.mts → index-3jSHmGwH.d.mts} +2 -2
  16. package/dist/{index-Bi9YYid8.d.mts.map → index-3jSHmGwH.d.mts.map} +1 -1
  17. package/dist/{index-4VDJDcWM.d.cts → index-5K4oXy67.d.cts} +822 -169
  18. package/dist/index-5K4oXy67.d.cts.map +1 -0
  19. package/dist/{index-RgOX4psL.d.mts → index-BB1v4Ynz.d.mts} +822 -169
  20. package/dist/index-BB1v4Ynz.d.mts.map +1 -0
  21. package/dist/{index-Cbf1OPLp.d.mts → index-Bu5i-gcV.d.mts} +2 -2
  22. package/dist/index-Bu5i-gcV.d.mts.map +1 -0
  23. package/dist/{index-De4wQJwR.d.cts → index-CHGBYDtr.d.cts} +2 -2
  24. package/dist/{index-De4wQJwR.d.cts.map → index-CHGBYDtr.d.cts.map} +1 -1
  25. package/dist/{index-qZ90PVNl.d.cts → index-T6MZvUlM.d.cts} +2 -2
  26. package/dist/{index-Cbf1OPLp.d.mts.map → index-T6MZvUlM.d.cts.map} +1 -1
  27. package/dist/index.cjs +1 -1
  28. package/dist/index.d.cts +5 -5
  29. package/dist/index.d.mts +5 -5
  30. package/dist/index.mjs +1 -1
  31. package/dist/{stream-limiter-D9rrsvAT.cjs → stream-limiter-BcTJAjs-.cjs} +1 -1
  32. package/dist/{stream-limiter-D9KSAaoY.mjs → stream-limiter-D1-sVS5i.mjs} +2 -2
  33. package/dist/{stream-limiter-D9KSAaoY.mjs.map → stream-limiter-D1-sVS5i.mjs.map} +1 -1
  34. package/dist/streams/index.cjs +1 -1
  35. package/dist/streams/index.d.cts +2 -2
  36. package/dist/streams/index.d.mts +2 -2
  37. package/dist/streams/index.mjs +1 -1
  38. package/dist/testing/index.cjs +1 -1
  39. package/dist/testing/index.d.cts +4 -4
  40. package/dist/testing/index.d.mts +4 -4
  41. package/dist/testing/index.mjs +1 -1
  42. package/dist/types/index.cjs +1 -1
  43. package/dist/types/index.d.cts +4 -4
  44. package/dist/types/index.d.mts +4 -4
  45. package/dist/types/index.mjs +1 -1
  46. package/dist/types-B-EckCWW.cjs +1 -0
  47. package/dist/types-CO-R4pFG.mjs +2 -0
  48. package/dist/types-CO-R4pFG.mjs.map +1 -0
  49. package/dist/upload/index.cjs +1 -1
  50. package/dist/upload/index.d.cts +4 -4
  51. package/dist/upload/index.d.mts +4 -4
  52. package/dist/upload/index.mjs +1 -1
  53. package/dist/{upload-D-eiOIVG.cjs → upload-BwXGQQ26.cjs} +1 -1
  54. package/dist/upload-C_Ew1NMF.mjs +2 -0
  55. package/dist/{upload-Yj5lrtZo.mjs.map → upload-C_Ew1NMF.mjs.map} +1 -1
  56. package/dist/{uploadista-error-B-n8Kfyh.cjs → uploadista-error-Blmj3lpk.cjs} +5 -1
  57. package/dist/{uploadista-error-DUWw6OqS.d.mts → uploadista-error-Cpn3uBLO.d.mts} +2 -2
  58. package/dist/uploadista-error-Cpn3uBLO.d.mts.map +1 -0
  59. package/dist/{uploadista-error-BQLhNZcY.d.cts → uploadista-error-DgdQnozn.d.cts} +2 -2
  60. package/dist/uploadista-error-DgdQnozn.d.cts.map +1 -0
  61. package/dist/{uploadista-error-Buscq-FR.mjs → uploadista-error-DhNBioWq.mjs} +5 -1
  62. package/dist/uploadista-error-DhNBioWq.mjs.map +1 -0
  63. package/dist/utils/index.cjs +1 -1
  64. package/dist/utils/index.d.cts +2 -2
  65. package/dist/utils/index.d.mts +2 -2
  66. package/dist/utils/index.mjs +1 -1
  67. package/dist/{utils-BWiu6lqv.mjs → utils-7gziergl.mjs} +2 -2
  68. package/dist/{utils-BWiu6lqv.mjs.map → utils-7gziergl.mjs.map} +1 -1
  69. package/dist/{utils-_StwBtxT.cjs → utils-C_STf6Wl.cjs} +1 -1
  70. package/package.json +3 -3
  71. package/src/errors/uploadista-error.ts +21 -1
  72. package/src/flow/event.ts +28 -4
  73. package/src/flow/flow-server.ts +43 -12
  74. package/src/flow/flow.ts +92 -13
  75. package/src/flow/index.ts +7 -0
  76. package/src/flow/node-types/index.ts +85 -0
  77. package/src/flow/node.ts +48 -6
  78. package/src/flow/nodes/input-node.ts +2 -0
  79. package/src/flow/nodes/storage-node.ts +2 -0
  80. package/src/flow/type-guards.ts +293 -0
  81. package/src/flow/type-registry.ts +345 -0
  82. package/src/flow/types/flow-job.ts +22 -6
  83. package/src/flow/types/flow-types.ts +152 -3
  84. package/tests/flow/type-system.test.ts +799 -0
  85. package/dist/flow-ChADffZ5.cjs +0 -1
  86. package/dist/flow-_J9-Dm_m.mjs +0 -2
  87. package/dist/flow-_J9-Dm_m.mjs.map +0 -1
  88. package/dist/index-4VDJDcWM.d.cts.map +0 -1
  89. package/dist/index-RgOX4psL.d.mts.map +0 -1
  90. package/dist/index-qZ90PVNl.d.cts.map +0 -1
  91. package/dist/types-BI_KmpTc.mjs +0 -2
  92. package/dist/types-BI_KmpTc.mjs.map +0 -1
  93. package/dist/types-f08UsX4E.cjs +0 -1
  94. package/dist/upload-Yj5lrtZo.mjs +0 -2
  95. package/dist/uploadista-error-BQLhNZcY.d.cts.map +0 -1
  96. package/dist/uploadista-error-Buscq-FR.mjs.map +0 -1
  97. 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 - Output data from the node (if completed successfully)
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; // Node execution result
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 - Final output from the flow (only set when completed)
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
- * console.log("Final result:", status.result);
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
- // Final flow execution result (only populated when completed)
114
- result?: unknown;
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
- | { type: "complete"; data: TOutput }
66
- | { type: "waiting"; partialData?: unknown };
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.