@hpcc-js/dataflow 9.6.9 → 9.6.11

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/src/utils/pipe.ts CHANGED
@@ -1,233 +1,233 @@
1
- import { IterableActivity, ScalarActivity, Source, isSource } from "../activities/activity.ts";
2
-
3
- // =============================================================================
4
- // Constants and Base Types
5
- // =============================================================================
6
-
7
- const GeneratorFunction = (function* () { }).constructor;
8
-
9
- type AnyIterableActivity = IterableActivity<any, any>;
10
- type AnyScalarActivity = ScalarActivity<any, any>;
11
- type AnyActivity = AnyIterableActivity | AnyScalarActivity;
12
-
13
- // =============================================================================
14
- // Type Utilities for Activity Analysis
15
- // =============================================================================
16
-
17
- type ActivityIn<A extends AnyActivity> = Parameters<A>[0] extends Source<infer Input> ? Input : never;
18
- type ActivityOut<A extends AnyActivity> = ReturnType<A> extends IterableIterator<infer Output> ? Output : ReturnType<A>;
19
- type ActivityIsScalar<A extends AnyActivity> = ReturnType<A> extends IterableIterator<any> ? false : true;
20
-
21
- type FirstActivity<Activities extends readonly [AnyActivity, ...AnyActivity[]]> = Activities[0];
22
-
23
- // =============================================================================
24
- // Type Resolution for Activity Chains (Without Source)
25
- // =============================================================================
26
-
27
- /**
28
- * Recursively resolves the output type of a chain of activities starting from an iterable activity.
29
- * Validates that each activity's input type matches the previous activity's output type.
30
- */
31
-
32
- // Handle a scalar (non-iterable) activity in the chain
33
- type ResolveScalarActivity<CurrentOut, InitialIn, Next extends AnyActivity, Rest extends readonly AnyActivity[]> =
34
- CurrentOut extends ActivityIn<Next>
35
- ? Rest extends []
36
- ? { kind: "scalar"; in: InitialIn; out: ActivityOut<Next> }
37
- : { kind: "error" } // Scalar activities must be terminal
38
- : { kind: "error" }; // Type mismatch
39
-
40
- // Handle an iterable activity in the chain
41
- type ResolveIterableActivity<CurrentOut, InitialIn, Next extends AnyActivity, Rest extends readonly AnyActivity[]> =
42
- CurrentOut extends ActivityIn<Next>
43
- ? ResolveIterableTail<ActivityOut<Next>, InitialIn, Rest>
44
- : { kind: "error" }; // Type mismatch
45
-
46
- // Process the next activity in the chain
47
- type ResolveNextActivity<CurrentOut, InitialIn, Next extends AnyActivity, Rest extends readonly AnyActivity[]> =
48
- ActivityIsScalar<Next> extends true
49
- ? ResolveScalarActivity<CurrentOut, InitialIn, Next, Rest>
50
- : ResolveIterableActivity<CurrentOut, InitialIn, Next, Rest>;
51
-
52
- // Check if we've reached the end of the activity chain
53
- type ResolveIterableTail<CurrentOut, InitialIn, Tail extends readonly AnyActivity[]> =
54
- Tail extends []
55
- ? { kind: "iterable"; in: InitialIn; out: CurrentOut }
56
- : Tail extends readonly [infer Next extends AnyActivity, ...infer Rest extends readonly AnyActivity[]]
57
- ? ResolveNextActivity<CurrentOut, InitialIn, Next, Rest>
58
- : { kind: "error" };
59
-
60
- /**
61
- * Resolves the complete type signature for a chain of activities without a source.
62
- * Determines the input, output, and whether the final result is scalar or iterable.
63
- */
64
-
65
- // Handle when the first activity is scalar (must be the only activity)
66
- type ResolveFirstScalarActivity<First extends AnyActivity, Rest extends readonly AnyActivity[]> =
67
- Rest extends []
68
- ? { kind: "scalar"; in: ActivityIn<First>; out: ActivityOut<First> }
69
- : { kind: "error" }; // Scalar activities cannot be followed by others
70
-
71
- // Handle when the first activity is iterable
72
- type ResolveFirstIterableActivity<First extends AnyActivity, Rest extends readonly AnyActivity[]> =
73
- Rest extends []
74
- ? { kind: "iterable"; in: ActivityIn<First>; out: ActivityOut<First> }
75
- : ResolveIterableTail<ActivityOut<First>, ActivityIn<First>, Rest>;
76
-
77
- // Determine how to handle the first activity based on whether it's scalar or iterable
78
- type ResolveFirstActivity<First extends AnyActivity, Rest extends readonly AnyActivity[]> =
79
- ActivityIsScalar<First> extends true
80
- ? ResolveFirstScalarActivity<First, Rest>
81
- : ResolveFirstIterableActivity<First, Rest>;
82
-
83
- type ResolveActivities<Activities extends readonly [AnyActivity, ...AnyActivity[]]> =
84
- Activities extends readonly [infer First extends AnyActivity, ...infer Rest extends readonly AnyActivity[]]
85
- ? ResolveFirstActivity<First, Rest>
86
- : { kind: "error" };
87
-
88
- /**
89
- * Return type for pipe when called without a source - returns a reusable activity function.
90
- */
91
- type PipeWithoutSourceReturn<Activities extends readonly [AnyActivity, ...AnyActivity[]]> =
92
- ResolveActivities<Activities> extends infer Result
93
- ? Result extends { kind: "iterable"; in: infer In; out: infer Out }
94
- ? IterableActivity<In & ActivityIn<FirstActivity<Activities>>, Out>
95
- : Result extends { kind: "scalar"; in: infer In; out: infer Out }
96
- ? ScalarActivity<In & ActivityIn<FirstActivity<Activities>>, Out>
97
- : never
98
- : never;
99
-
100
- // =============================================================================
101
- // Type Resolution for Activity Chains (With Source)
102
- // =============================================================================
103
-
104
- /**
105
- * Resolves the output type when a source is provided as the first argument to pipe.
106
- * Validates that the source type is compatible with the first activity's input.
107
- */
108
-
109
- // Extract the final result kind from ResolveIterableTail
110
- type ExtractFinalResultKind<Result> =
111
- Result extends { kind: "iterable"; out: infer Out }
112
- ? { kind: "iterable"; out: Out }
113
- : Result extends { kind: "scalar"; out: infer Out }
114
- ? { kind: "scalar"; out: Out }
115
- : { kind: "error" };
116
-
117
- // Handle when the first activity after source is scalar
118
- type ResolveSourceWithScalarActivity<TSource, First extends AnyActivity, Rest extends readonly AnyActivity[]> =
119
- TSource extends ActivityIn<First>
120
- ? Rest extends []
121
- ? { kind: "scalar"; out: ActivityOut<First> }
122
- : { kind: "error" } // Scalar activities must be terminal
123
- : { kind: "error" }; // Type mismatch
124
-
125
- // Handle when the first activity after source is iterable
126
- type ResolveSourceWithIterableActivity<TSource, First extends AnyActivity, Rest extends readonly AnyActivity[]> =
127
- TSource extends ActivityIn<First>
128
- ? Rest extends []
129
- ? { kind: "iterable"; out: ActivityOut<First> }
130
- : ExtractFinalResultKind<ResolveIterableTail<ActivityOut<First>, ActivityIn<First>, Rest>>
131
- : { kind: "error" }; // Type mismatch
132
-
133
- // Determine how to handle the source with the first activity
134
- type ResolveSourceWithFirstActivity<TSource, First extends AnyActivity, Rest extends readonly AnyActivity[]> =
135
- ActivityIsScalar<First> extends true
136
- ? ResolveSourceWithScalarActivity<TSource, First, Rest>
137
- : ResolveSourceWithIterableActivity<TSource, First, Rest>;
138
-
139
- type ResolveSourceActivities<TSource, Activities extends readonly AnyActivity[]> =
140
- Activities extends []
141
- ? { kind: "source"; out: TSource }
142
- : Activities extends readonly [infer First extends AnyActivity, ...infer Rest extends readonly AnyActivity[]]
143
- ? ResolveSourceWithFirstActivity<TSource, First, Rest>
144
- : { kind: "error" };
145
-
146
- /**
147
- * Return type for pipe when called with a source - executes immediately and returns the result.
148
- */
149
- type PipeWithSourceReturn<TSource, Activities extends readonly AnyActivity[]> =
150
- ResolveSourceActivities<TSource, Activities> extends infer Result
151
- ? Result extends { kind: "iterable"; out: infer Out }
152
- ? IterableIterator<Out>
153
- : Result extends { kind: "scalar"; out: infer Out }
154
- ? Out
155
- : Result extends { kind: "source"; out: infer Out }
156
- ? Source<Out>
157
- : never
158
- : never;
159
-
160
- // =============================================================================
161
- // Runtime Implementation
162
- // =============================================================================
163
-
164
- /**
165
- * Internal helper that chains activities together at runtime.
166
- * Returns a function that accepts a source and applies all activities in sequence.
167
- * Handles both generator (iterable) and scalar activities appropriately.
168
- */
169
- function chainGen(...activities: AnyActivity[]) {
170
- if (activities.length === 0) {
171
- return <T>(source: Source<T>) => source;
172
- }
173
-
174
- const isGenerator = activities[activities.length - 1] instanceof GeneratorFunction;
175
- const len = activities.length;
176
-
177
- if (isGenerator) {
178
- return function* (source: Source<unknown>) {
179
- let tail: unknown = source;
180
- for (let i = 0; i < len; i++) {
181
- tail = activities[i](tail as Source<unknown>);
182
- }
183
- yield* tail as IterableIterator<unknown>;
184
- };
185
- }
186
-
187
- return (source: Source<unknown>) => {
188
- let tail: unknown = source;
189
- for (let i = 0; i < len; i++) {
190
- tail = activities[i](tail as Source<unknown>);
191
- }
192
- return tail;
193
- };
194
- }
195
-
196
- // =============================================================================
197
- // Public API
198
- // =============================================================================
199
-
200
- /**
201
- * Pipes activities together to create a data processing pipeline.
202
- *
203
- * Two usage modes:
204
- * 1. Without source: pipe(activity1, activity2, ...) - returns a reusable activity function
205
- * 2. With source: pipe(source, activity1, activity2, ...) - executes immediately and returns result
206
- *
207
- * Activities are chained left-to-right, with type checking ensuring output of each activity
208
- * matches the input of the next.
209
- */
210
- export function pipe<const Activities extends readonly [AnyActivity, ...AnyActivity[]]>(...activities: Activities): PipeWithoutSourceReturn<Activities>;
211
- export function pipe<TSource, const Activities extends readonly AnyActivity[]>(source: Source<TSource>, ...activities: Activities): PipeWithSourceReturn<TSource, Activities>;
212
- export function pipe(...args: any[]): any {
213
- if (args.length === 0) {
214
- throw new TypeError("pipe requires at least one argument");
215
- }
216
-
217
- // Handle source-based invocation
218
- if (isSource(args[0])) {
219
- return args.length === 1 ? args[0] : chainGen(...args.slice(1))(args[0]);
220
- }
221
-
222
- // Handle activity-based invocation
223
- return chainGen(...args);
224
- }
225
-
226
- // =============================================================================
227
- // Backward Compatibility
228
- // =============================================================================
229
-
230
- /**
231
- * @deprecated Use pipe instead. Maintained for backward compatibility.
232
- */
233
- export const chain = pipe;
1
+ import { IterableActivity, ScalarActivity, Source, isSource } from "../activities/activity.ts";
2
+
3
+ // =============================================================================
4
+ // Constants and Base Types
5
+ // =============================================================================
6
+
7
+ const GeneratorFunction = (function* () { }).constructor;
8
+
9
+ type AnyIterableActivity = IterableActivity<any, any>;
10
+ type AnyScalarActivity = ScalarActivity<any, any>;
11
+ type AnyActivity = AnyIterableActivity | AnyScalarActivity;
12
+
13
+ // =============================================================================
14
+ // Type Utilities for Activity Analysis
15
+ // =============================================================================
16
+
17
+ type ActivityIn<A extends AnyActivity> = Parameters<A>[0] extends Source<infer Input> ? Input : never;
18
+ type ActivityOut<A extends AnyActivity> = ReturnType<A> extends IterableIterator<infer Output> ? Output : ReturnType<A>;
19
+ type ActivityIsScalar<A extends AnyActivity> = ReturnType<A> extends IterableIterator<any> ? false : true;
20
+
21
+ type FirstActivity<Activities extends readonly [AnyActivity, ...AnyActivity[]]> = Activities[0];
22
+
23
+ // =============================================================================
24
+ // Type Resolution for Activity Chains (Without Source)
25
+ // =============================================================================
26
+
27
+ /**
28
+ * Recursively resolves the output type of a chain of activities starting from an iterable activity.
29
+ * Validates that each activity's input type matches the previous activity's output type.
30
+ */
31
+
32
+ // Handle a scalar (non-iterable) activity in the chain
33
+ type ResolveScalarActivity<CurrentOut, InitialIn, Next extends AnyActivity, Rest extends readonly AnyActivity[]> =
34
+ CurrentOut extends ActivityIn<Next>
35
+ ? Rest extends []
36
+ ? { kind: "scalar"; in: InitialIn; out: ActivityOut<Next> }
37
+ : { kind: "error" } // Scalar activities must be terminal
38
+ : { kind: "error" }; // Type mismatch
39
+
40
+ // Handle an iterable activity in the chain
41
+ type ResolveIterableActivity<CurrentOut, InitialIn, Next extends AnyActivity, Rest extends readonly AnyActivity[]> =
42
+ CurrentOut extends ActivityIn<Next>
43
+ ? ResolveIterableTail<ActivityOut<Next>, InitialIn, Rest>
44
+ : { kind: "error" }; // Type mismatch
45
+
46
+ // Process the next activity in the chain
47
+ type ResolveNextActivity<CurrentOut, InitialIn, Next extends AnyActivity, Rest extends readonly AnyActivity[]> =
48
+ ActivityIsScalar<Next> extends true
49
+ ? ResolveScalarActivity<CurrentOut, InitialIn, Next, Rest>
50
+ : ResolveIterableActivity<CurrentOut, InitialIn, Next, Rest>;
51
+
52
+ // Check if we've reached the end of the activity chain
53
+ type ResolveIterableTail<CurrentOut, InitialIn, Tail extends readonly AnyActivity[]> =
54
+ Tail extends []
55
+ ? { kind: "iterable"; in: InitialIn; out: CurrentOut }
56
+ : Tail extends readonly [infer Next extends AnyActivity, ...infer Rest extends readonly AnyActivity[]]
57
+ ? ResolveNextActivity<CurrentOut, InitialIn, Next, Rest>
58
+ : { kind: "error" };
59
+
60
+ /**
61
+ * Resolves the complete type signature for a chain of activities without a source.
62
+ * Determines the input, output, and whether the final result is scalar or iterable.
63
+ */
64
+
65
+ // Handle when the first activity is scalar (must be the only activity)
66
+ type ResolveFirstScalarActivity<First extends AnyActivity, Rest extends readonly AnyActivity[]> =
67
+ Rest extends []
68
+ ? { kind: "scalar"; in: ActivityIn<First>; out: ActivityOut<First> }
69
+ : { kind: "error" }; // Scalar activities cannot be followed by others
70
+
71
+ // Handle when the first activity is iterable
72
+ type ResolveFirstIterableActivity<First extends AnyActivity, Rest extends readonly AnyActivity[]> =
73
+ Rest extends []
74
+ ? { kind: "iterable"; in: ActivityIn<First>; out: ActivityOut<First> }
75
+ : ResolveIterableTail<ActivityOut<First>, ActivityIn<First>, Rest>;
76
+
77
+ // Determine how to handle the first activity based on whether it's scalar or iterable
78
+ type ResolveFirstActivity<First extends AnyActivity, Rest extends readonly AnyActivity[]> =
79
+ ActivityIsScalar<First> extends true
80
+ ? ResolveFirstScalarActivity<First, Rest>
81
+ : ResolveFirstIterableActivity<First, Rest>;
82
+
83
+ type ResolveActivities<Activities extends readonly [AnyActivity, ...AnyActivity[]]> =
84
+ Activities extends readonly [infer First extends AnyActivity, ...infer Rest extends readonly AnyActivity[]]
85
+ ? ResolveFirstActivity<First, Rest>
86
+ : { kind: "error" };
87
+
88
+ /**
89
+ * Return type for pipe when called without a source - returns a reusable activity function.
90
+ */
91
+ type PipeWithoutSourceReturn<Activities extends readonly [AnyActivity, ...AnyActivity[]]> =
92
+ ResolveActivities<Activities> extends infer Result
93
+ ? Result extends { kind: "iterable"; in: infer In; out: infer Out }
94
+ ? IterableActivity<In & ActivityIn<FirstActivity<Activities>>, Out>
95
+ : Result extends { kind: "scalar"; in: infer In; out: infer Out }
96
+ ? ScalarActivity<In & ActivityIn<FirstActivity<Activities>>, Out>
97
+ : never
98
+ : never;
99
+
100
+ // =============================================================================
101
+ // Type Resolution for Activity Chains (With Source)
102
+ // =============================================================================
103
+
104
+ /**
105
+ * Resolves the output type when a source is provided as the first argument to pipe.
106
+ * Validates that the source type is compatible with the first activity's input.
107
+ */
108
+
109
+ // Extract the final result kind from ResolveIterableTail
110
+ type ExtractFinalResultKind<Result> =
111
+ Result extends { kind: "iterable"; out: infer Out }
112
+ ? { kind: "iterable"; out: Out }
113
+ : Result extends { kind: "scalar"; out: infer Out }
114
+ ? { kind: "scalar"; out: Out }
115
+ : { kind: "error" };
116
+
117
+ // Handle when the first activity after source is scalar
118
+ type ResolveSourceWithScalarActivity<TSource, First extends AnyActivity, Rest extends readonly AnyActivity[]> =
119
+ TSource extends ActivityIn<First>
120
+ ? Rest extends []
121
+ ? { kind: "scalar"; out: ActivityOut<First> }
122
+ : { kind: "error" } // Scalar activities must be terminal
123
+ : { kind: "error" }; // Type mismatch
124
+
125
+ // Handle when the first activity after source is iterable
126
+ type ResolveSourceWithIterableActivity<TSource, First extends AnyActivity, Rest extends readonly AnyActivity[]> =
127
+ TSource extends ActivityIn<First>
128
+ ? Rest extends []
129
+ ? { kind: "iterable"; out: ActivityOut<First> }
130
+ : ExtractFinalResultKind<ResolveIterableTail<ActivityOut<First>, ActivityIn<First>, Rest>>
131
+ : { kind: "error" }; // Type mismatch
132
+
133
+ // Determine how to handle the source with the first activity
134
+ type ResolveSourceWithFirstActivity<TSource, First extends AnyActivity, Rest extends readonly AnyActivity[]> =
135
+ ActivityIsScalar<First> extends true
136
+ ? ResolveSourceWithScalarActivity<TSource, First, Rest>
137
+ : ResolveSourceWithIterableActivity<TSource, First, Rest>;
138
+
139
+ type ResolveSourceActivities<TSource, Activities extends readonly AnyActivity[]> =
140
+ Activities extends []
141
+ ? { kind: "source"; out: TSource }
142
+ : Activities extends readonly [infer First extends AnyActivity, ...infer Rest extends readonly AnyActivity[]]
143
+ ? ResolveSourceWithFirstActivity<TSource, First, Rest>
144
+ : { kind: "error" };
145
+
146
+ /**
147
+ * Return type for pipe when called with a source - executes immediately and returns the result.
148
+ */
149
+ type PipeWithSourceReturn<TSource, Activities extends readonly AnyActivity[]> =
150
+ ResolveSourceActivities<TSource, Activities> extends infer Result
151
+ ? Result extends { kind: "iterable"; out: infer Out }
152
+ ? IterableIterator<Out>
153
+ : Result extends { kind: "scalar"; out: infer Out }
154
+ ? Out
155
+ : Result extends { kind: "source"; out: infer Out }
156
+ ? Source<Out>
157
+ : never
158
+ : never;
159
+
160
+ // =============================================================================
161
+ // Runtime Implementation
162
+ // =============================================================================
163
+
164
+ /**
165
+ * Internal helper that chains activities together at runtime.
166
+ * Returns a function that accepts a source and applies all activities in sequence.
167
+ * Handles both generator (iterable) and scalar activities appropriately.
168
+ */
169
+ function chainGen(...activities: AnyActivity[]) {
170
+ if (activities.length === 0) {
171
+ return <T>(source: Source<T>) => source;
172
+ }
173
+
174
+ const isGenerator = activities[activities.length - 1] instanceof GeneratorFunction;
175
+ const len = activities.length;
176
+
177
+ if (isGenerator) {
178
+ return function* (source: Source<unknown>) {
179
+ let tail: unknown = source;
180
+ for (let i = 0; i < len; i++) {
181
+ tail = activities[i](tail as Source<unknown>);
182
+ }
183
+ yield* tail as IterableIterator<unknown>;
184
+ };
185
+ }
186
+
187
+ return (source: Source<unknown>) => {
188
+ let tail: unknown = source;
189
+ for (let i = 0; i < len; i++) {
190
+ tail = activities[i](tail as Source<unknown>);
191
+ }
192
+ return tail;
193
+ };
194
+ }
195
+
196
+ // =============================================================================
197
+ // Public API
198
+ // =============================================================================
199
+
200
+ /**
201
+ * Pipes activities together to create a data processing pipeline.
202
+ *
203
+ * Two usage modes:
204
+ * 1. Without source: pipe(activity1, activity2, ...) - returns a reusable activity function
205
+ * 2. With source: pipe(source, activity1, activity2, ...) - executes immediately and returns result
206
+ *
207
+ * Activities are chained left-to-right, with type checking ensuring output of each activity
208
+ * matches the input of the next.
209
+ */
210
+ export function pipe<const Activities extends readonly [AnyActivity, ...AnyActivity[]]>(...activities: Activities): PipeWithoutSourceReturn<Activities>;
211
+ export function pipe<TSource, const Activities extends readonly AnyActivity[]>(source: Source<TSource>, ...activities: Activities): PipeWithSourceReturn<TSource, Activities>;
212
+ export function pipe(...args: any[]): any {
213
+ if (args.length === 0) {
214
+ throw new TypeError("pipe requires at least one argument");
215
+ }
216
+
217
+ // Handle source-based invocation
218
+ if (isSource(args[0])) {
219
+ return args.length === 1 ? args[0] : chainGen(...args.slice(1))(args[0]);
220
+ }
221
+
222
+ // Handle activity-based invocation
223
+ return chainGen(...args);
224
+ }
225
+
226
+ // =============================================================================
227
+ // Backward Compatibility
228
+ // =============================================================================
229
+
230
+ /**
231
+ * @deprecated Use pipe instead. Maintained for backward compatibility.
232
+ */
233
+ export const chain = pipe;