gingersnap 0.22.0
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/_virtual/_tslib.cjs +102 -0
- package/_virtual/_tslib.mjs +93 -0
- package/data/AtomicValue.d.ts +15 -0
- package/data/bus.cjs +179 -0
- package/data/bus.d.ts +72 -0
- package/data/bus.mjs +177 -0
- package/data/decoders/index.d.ts +4 -0
- package/data/decoders/json.cjs +12 -0
- package/data/decoders/json.d.ts +7 -0
- package/data/decoders/json.mjs +10 -0
- package/data/decoders/msgpack.cjs +14 -0
- package/data/decoders/msgpack.d.ts +7 -0
- package/data/decoders/msgpack.mjs +12 -0
- package/data/decoders/protobuf.d.ts +13 -0
- package/data/decoders/string.cjs +12 -0
- package/data/decoders/string.d.ts +7 -0
- package/data/decoders/string.mjs +10 -0
- package/data/decoders/type.d.ts +7 -0
- package/data/decoders.cjs +11 -0
- package/data/decoders.mjs +3 -0
- package/data/model/credentials.cjs +114 -0
- package/data/model/credentials.d.ts +61 -0
- package/data/model/credentials.mjs +109 -0
- package/data/model/extra.cjs +88 -0
- package/data/model/extra.d.ts +5 -0
- package/data/model/extra.mjs +66 -0
- package/data/model/index.d.ts +6 -0
- package/data/model/model.cjs +541 -0
- package/data/model/model.d.ts +207 -0
- package/data/model/model.mjs +518 -0
- package/data/model/plugin.cjs +96 -0
- package/data/model/plugin.d.ts +38 -0
- package/data/model/plugin.mjs +72 -0
- package/data/model/property.cjs +310 -0
- package/data/model/property.d.ts +83 -0
- package/data/model/property.mjs +278 -0
- package/data/model/types.cjs +32 -0
- package/data/model/types.d.ts +28 -0
- package/data/model/types.mjs +32 -0
- package/data/model.cjs +43 -0
- package/data/model.mjs +6 -0
- package/data/signal.cjs +47 -0
- package/data/signal.d.ts +17 -0
- package/data/signal.mjs +45 -0
- package/data/store/index.d.ts +4 -0
- package/data/store/json.cjs +58 -0
- package/data/store/json.d.ts +18 -0
- package/data/store/json.mjs +56 -0
- package/data/store/manager.cjs +206 -0
- package/data/store/manager.d.ts +44 -0
- package/data/store/manager.mjs +203 -0
- package/data/store/web.cjs +92 -0
- package/data/store/web.d.ts +25 -0
- package/data/store/web.mjs +89 -0
- package/data/value.cjs +66 -0
- package/data/value.mjs +64 -0
- package/data-structures/array/CyclicalList.cjs +57 -0
- package/data-structures/array/CyclicalList.d.ts +12 -0
- package/data-structures/array/CyclicalList.mjs +55 -0
- package/data-structures/array/Pair.cjs +30 -0
- package/data-structures/array/Pair.d.ts +17 -0
- package/data-structures/array/Pair.mjs +27 -0
- package/data-structures/array/Stack.cjs +96 -0
- package/data-structures/array/Stack.d.ts +41 -0
- package/data-structures/array/Stack.mjs +94 -0
- package/data-structures/array/Triple.cjs +34 -0
- package/data-structures/array/Triple.d.ts +19 -0
- package/data-structures/array/Triple.mjs +31 -0
- package/data-structures/array/Tuple.d.ts +8 -0
- package/data-structures/array/index.d.ts +5 -0
- package/data-structures/array.cjs +15 -0
- package/data-structures/array.mjs +4 -0
- package/data-structures/object/BufferQueue.cjs +98 -0
- package/data-structures/object/BufferQueue.d.ts +21 -0
- package/data-structures/object/BufferQueue.mjs +77 -0
- package/data-structures/object/CyclicalObject.cjs +155 -0
- package/data-structures/object/CyclicalObject.d.ts +74 -0
- package/data-structures/object/CyclicalObject.mjs +134 -0
- package/data-structures/object/Queue.cjs +178 -0
- package/data-structures/object/Queue.d.ts +31 -0
- package/data-structures/object/Queue.mjs +176 -0
- package/data-structures/object/SimpleQueue.cjs +53 -0
- package/data-structures/object/SimpleQueue.d.ts +13 -0
- package/data-structures/object/SimpleQueue.mjs +51 -0
- package/data-structures/object/TimeableObject.cjs +73 -0
- package/data-structures/object/TimeableObject.d.ts +30 -0
- package/data-structures/object/TimeableObject.mjs +71 -0
- package/data-structures/object/WaitableObject.cjs +61 -0
- package/data-structures/object/WaitableObject.d.ts +29 -0
- package/data-structures/object/WaitableObject.mjs +59 -0
- package/data-structures/object/WatchableObject.cjs +251 -0
- package/data-structures/object/WatchableObject.d.ts +88 -0
- package/data-structures/object/WatchableObject.mjs +230 -0
- package/data-structures/object/index.d.ts +7 -0
- package/data-structures/object.cjs +23 -0
- package/data-structures/object.mjs +7 -0
- package/errors/AbortError.cjs +9 -0
- package/errors/AbortError.d.ts +5 -0
- package/errors/AbortError.mjs +7 -0
- package/errors/CallExecutionError.cjs +13 -0
- package/errors/CallExecutionError.d.ts +7 -0
- package/errors/CallExecutionError.mjs +11 -0
- package/errors/FutureCancelled.cjs +11 -0
- package/errors/FutureCancelled.d.ts +6 -0
- package/errors/FutureCancelled.mjs +9 -0
- package/errors/FutureError.cjs +11 -0
- package/errors/FutureError.d.ts +6 -0
- package/errors/FutureError.mjs +9 -0
- package/errors/IllegalArgumentsError.cjs +13 -0
- package/errors/IllegalArgumentsError.d.ts +7 -0
- package/errors/IllegalArgumentsError.mjs +11 -0
- package/errors/IllegalOperationError.cjs +6 -0
- package/errors/IllegalOperationError.d.ts +2 -0
- package/errors/IllegalOperationError.mjs +4 -0
- package/errors/InvalidType.cjs +6 -0
- package/errors/InvalidType.d.ts +2 -0
- package/errors/InvalidType.mjs +4 -0
- package/errors/InvalidValue.cjs +11 -0
- package/errors/InvalidValue.d.ts +4 -0
- package/errors/InvalidValue.mjs +9 -0
- package/errors/MissingArgumentsError.cjs +13 -0
- package/errors/MissingArgumentsError.d.ts +7 -0
- package/errors/MissingArgumentsError.mjs +11 -0
- package/errors/NetworkError.cjs +13 -0
- package/errors/NetworkError.d.ts +8 -0
- package/errors/NetworkError.mjs +11 -0
- package/errors/NoSuchElement.cjs +6 -0
- package/errors/NoSuchElement.d.ts +2 -0
- package/errors/NoSuchElement.mjs +4 -0
- package/errors/NotImplemented.cjs +9 -0
- package/errors/NotImplemented.d.ts +5 -0
- package/errors/NotImplemented.mjs +7 -0
- package/errors/ParsingError.cjs +10 -0
- package/errors/ParsingError.d.ts +5 -0
- package/errors/ParsingError.mjs +8 -0
- package/errors/QueueEmptyError.cjs +6 -0
- package/errors/QueueEmptyError.d.ts +2 -0
- package/errors/QueueEmptyError.mjs +4 -0
- package/errors/QueueFullError.cjs +6 -0
- package/errors/QueueFullError.d.ts +2 -0
- package/errors/QueueFullError.mjs +4 -0
- package/errors/StackEmptyError.cjs +6 -0
- package/errors/StackEmptyError.d.ts +2 -0
- package/errors/StackEmptyError.mjs +4 -0
- package/errors/StackFullError.cjs +6 -0
- package/errors/StackFullError.d.ts +2 -0
- package/errors/StackFullError.mjs +4 -0
- package/errors/StreamEnded.cjs +6 -0
- package/errors/StreamEnded.d.ts +2 -0
- package/errors/StreamEnded.mjs +4 -0
- package/errors/TimeoutError.cjs +11 -0
- package/errors/TimeoutError.d.ts +6 -0
- package/errors/TimeoutError.mjs +9 -0
- package/errors/ValueDestroyedError.cjs +6 -0
- package/errors/ValueDestroyedError.d.ts +2 -0
- package/errors/ValueDestroyedError.mjs +4 -0
- package/errors/VerificationError.cjs +9 -0
- package/errors/VerificationError.d.ts +5 -0
- package/errors/VerificationError.mjs +7 -0
- package/errors/index.d.ts +18 -0
- package/errors.cjs +41 -0
- package/errors.mjs +18 -0
- package/files.cjs +201 -0
- package/files.d.ts +31 -0
- package/files.mjs +180 -0
- package/functools/index.d.ts +31 -0
- package/functools.cjs +371 -0
- package/functools.mjs +334 -0
- package/future/future.cjs +570 -0
- package/future/future.d.ts +208 -0
- package/future/future.mjs +548 -0
- package/future/group.cjs +180 -0
- package/future/group.d.ts +82 -0
- package/future/group.mjs +159 -0
- package/future/index.d.ts +3 -0
- package/future/result.cjs +19 -0
- package/future/result.d.ts +18 -0
- package/future/result.mjs +17 -0
- package/future.cjs +11 -0
- package/future.mjs +3 -0
- package/managers/context.d.ts +8 -0
- package/managers/index.d.ts +1 -0
- package/managers.cjs +2 -0
- package/managers.mjs +1 -0
- package/mocks.cjs +301 -0
- package/mocks.d.ts +125 -0
- package/mocks.mjs +293 -0
- package/networking/EventSourceService.cjs +104 -0
- package/networking/EventSourceService.d.ts +11 -0
- package/networking/EventSourceService.mjs +83 -0
- package/networking/NetworkService.cjs +394 -0
- package/networking/NetworkService.d.ts +97 -0
- package/networking/NetworkService.mjs +373 -0
- package/networking/SocketService.cjs +218 -0
- package/networking/SocketService.d.ts +23 -0
- package/networking/SocketService.mjs +197 -0
- package/networking/decorators/index.d.ts +4 -0
- package/networking/decorators/options.cjs +289 -0
- package/networking/decorators/options.d.ts +148 -0
- package/networking/decorators/options.mjs +242 -0
- package/networking/decorators/requests.cjs +80 -0
- package/networking/decorators/requests.d.ts +34 -0
- package/networking/decorators/requests.mjs +52 -0
- package/networking/decorators/socket.cjs +81 -0
- package/networking/decorators/socket.d.ts +13 -0
- package/networking/decorators/socket.mjs +51 -0
- package/networking/http.cjs +69 -0
- package/networking/http.d.ts +66 -0
- package/networking/http.mjs +69 -0
- package/networking/index.d.ts +39 -0
- package/networking/request.cjs +18 -0
- package/networking/request.d.ts +9 -0
- package/networking/request.mjs +16 -0
- package/networking/types.cjs +37 -0
- package/networking/types.d.ts +132 -0
- package/networking/types.mjs +35 -0
- package/networking.cjs +91 -0
- package/networking.mjs +33 -0
- package/package.json +1 -0
- package/reflection/injector.cjs +43 -0
- package/reflection/injector.d.ts +3 -0
- package/reflection/injector.mjs +40 -0
- package/socket.cjs +239 -0
- package/socket.d.ts +65 -0
- package/socket.mjs +237 -0
- package/store.cjs +12 -0
- package/store.mjs +3 -0
- package/stream/call.cjs +157 -0
- package/stream/call.d.ts +66 -0
- package/stream/call.mjs +154 -0
- package/stream/collector.cjs +217 -0
- package/stream/collector.d.ts +14 -0
- package/stream/collector.mjs +215 -0
- package/stream/index.d.ts +257 -0
- package/stream/observable.cjs +110 -0
- package/stream/observable.d.ts +65 -0
- package/stream/observable.mjs +106 -0
- package/stream/state.cjs +10 -0
- package/stream/state.d.ts +5 -0
- package/stream/state.mjs +8 -0
- package/stream.cjs +1153 -0
- package/stream.mjs +1132 -0
- package/synchronize.cjs +106 -0
- package/synchronize.d.ts +54 -0
- package/synchronize.mjs +103 -0
- package/typing/types.d.ts +24 -0
- package/typing.cjs +2 -0
- package/typing.mjs +1 -0
- package/utils/parser.cjs +37 -0
- package/utils/parser.d.ts +7 -0
- package/utils/parser.mjs +16 -0
package/stream.mjs
ADDED
|
@@ -0,0 +1,1132 @@
|
|
|
1
|
+
import { __awaiter, __asyncValues } from './_virtual/_tslib.mjs';
|
|
2
|
+
import { CallExecutionError } from './errors/CallExecutionError.mjs';
|
|
3
|
+
import { FutureCancelled } from './errors/FutureCancelled.mjs';
|
|
4
|
+
import { FutureError } from './errors/FutureError.mjs';
|
|
5
|
+
import { StreamEnded } from './errors/StreamEnded.mjs';
|
|
6
|
+
import * as R from 'ramda';
|
|
7
|
+
import { Future } from './future/future.mjs';
|
|
8
|
+
import { FutureResult } from './future/result.mjs';
|
|
9
|
+
import { Lock } from './synchronize.mjs';
|
|
10
|
+
import { ExecutorState } from './stream/state.mjs';
|
|
11
|
+
import { TimeableObject } from './data-structures/object/TimeableObject.mjs';
|
|
12
|
+
import { IllegalOperationError } from './errors/IllegalOperationError.mjs';
|
|
13
|
+
import './data-structures/object/WatchableObject.mjs';
|
|
14
|
+
import 'uuid';
|
|
15
|
+
import { Queue } from './data-structures/object/Queue.mjs';
|
|
16
|
+
import { AtomicValue } from './data/value.mjs';
|
|
17
|
+
|
|
18
|
+
var ActionType;
|
|
19
|
+
(function (ActionType) {
|
|
20
|
+
ActionType[ActionType["TRANSFORM"] = 0] = "TRANSFORM";
|
|
21
|
+
ActionType[ActionType["FILTER"] = 1] = "FILTER";
|
|
22
|
+
ActionType[ActionType["LIMIT"] = 2] = "LIMIT";
|
|
23
|
+
ActionType[ActionType["UNPACK"] = 3] = "UNPACK";
|
|
24
|
+
ActionType[ActionType["PACK"] = 4] = "PACK";
|
|
25
|
+
ActionType[ActionType["CATCH"] = 5] = "CATCH";
|
|
26
|
+
})(ActionType || (ActionType = {}));
|
|
27
|
+
var State;
|
|
28
|
+
(function (State) {
|
|
29
|
+
State[State["MATCHED"] = 0] = "MATCHED";
|
|
30
|
+
State[State["CONTINUE"] = 1] = "CONTINUE";
|
|
31
|
+
State[State["DONE"] = 2] = "DONE";
|
|
32
|
+
})(State || (State = {}));
|
|
33
|
+
/**
|
|
34
|
+
* Handles a continuous supply of data that can be transformed and manipulated using a chain of actions
|
|
35
|
+
*/
|
|
36
|
+
class Stream {
|
|
37
|
+
constructor(executor) {
|
|
38
|
+
this.executor = executor;
|
|
39
|
+
this.controller = new AbortController();
|
|
40
|
+
this.executed = false;
|
|
41
|
+
this.done = false;
|
|
42
|
+
this.canRunExecutor = true;
|
|
43
|
+
this.actions = [];
|
|
44
|
+
this.backlog = [];
|
|
45
|
+
this.cancelHooks = new Set();
|
|
46
|
+
this.completionHooks = new Set();
|
|
47
|
+
this.completionHookInvoked = false;
|
|
48
|
+
this.runLock = new Lock();
|
|
49
|
+
this.concurrencyLimit = 0;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Used to provide setup logic that should only be invoked once, when stream
|
|
53
|
+
* is starting. This setup logic must provide the actual data required, which
|
|
54
|
+
* can come from a Stream or Future
|
|
55
|
+
* @param supplier
|
|
56
|
+
*/
|
|
57
|
+
static seed(supplier) {
|
|
58
|
+
return new Future((resolve, reject, signal) => {
|
|
59
|
+
resolve(supplier());
|
|
60
|
+
}).stream;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Streams the next available result from a list of futures, until all future completes. If any future fails, then the
|
|
64
|
+
* stream will throw an error
|
|
65
|
+
* @param futures
|
|
66
|
+
*/
|
|
67
|
+
static asCompleted(futures) {
|
|
68
|
+
const registerSignal = R.once((signal) => {
|
|
69
|
+
futures.forEach((future) => {
|
|
70
|
+
future.registerSignal(signal);
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
const launchFutures = R.once((futures) => {
|
|
74
|
+
const result = new Set();
|
|
75
|
+
for (let i = 0; i < futures.length; i++) {
|
|
76
|
+
const future = futures[i].clone();
|
|
77
|
+
result.add(future.thenApply((v) => [v.value, future], false));
|
|
78
|
+
}
|
|
79
|
+
return result;
|
|
80
|
+
});
|
|
81
|
+
return new Stream((signal) => __awaiter(this, void 0, void 0, function* () {
|
|
82
|
+
registerSignal(signal);
|
|
83
|
+
const promises = launchFutures(futures);
|
|
84
|
+
if (promises.size > 0) {
|
|
85
|
+
const result = yield Promise.race(promises);
|
|
86
|
+
const [value, future] = result;
|
|
87
|
+
promises.delete(future);
|
|
88
|
+
return value;
|
|
89
|
+
}
|
|
90
|
+
return new ExecutorState(true);
|
|
91
|
+
}));
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Stream the next available result from the list of streams. If any stream fails, then this merged stream also fails.
|
|
95
|
+
* @param streams
|
|
96
|
+
*/
|
|
97
|
+
static merge(streams) {
|
|
98
|
+
const register = R.once((signal) => {
|
|
99
|
+
signal.onabort = () => streams.forEach((stream) => stream.cancel());
|
|
100
|
+
});
|
|
101
|
+
const buildFuture = (stream, index) => stream.future
|
|
102
|
+
.thenApply((v) => [v.value, index])
|
|
103
|
+
.catch((error) => {
|
|
104
|
+
if (error instanceof StreamEnded) {
|
|
105
|
+
return [undefined, index];
|
|
106
|
+
}
|
|
107
|
+
throw error;
|
|
108
|
+
});
|
|
109
|
+
let streamCount = streams.length;
|
|
110
|
+
const futures = streams.map((stream, index) => buildFuture(stream, index));
|
|
111
|
+
return new Stream((signal) => __awaiter(this, void 0, void 0, function* () {
|
|
112
|
+
register(signal);
|
|
113
|
+
while (streamCount > 0) {
|
|
114
|
+
const [value, index] = yield Future.firstCompleted(futures);
|
|
115
|
+
if (value === undefined) {
|
|
116
|
+
futures[index] = new Future(() => { });
|
|
117
|
+
streamCount--;
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
futures[index] = buildFuture(streams[index], index);
|
|
121
|
+
return value;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return new ExecutorState(true);
|
|
125
|
+
}));
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Aggregates the results from multiple streams
|
|
129
|
+
* @param streams
|
|
130
|
+
*/
|
|
131
|
+
static zip(streams) {
|
|
132
|
+
const register = R.once((signal) => (signal.onabort = () => streams.forEach((stream) => stream.cancel())));
|
|
133
|
+
return new Stream((signal) => __awaiter(this, void 0, void 0, function* () {
|
|
134
|
+
register(signal);
|
|
135
|
+
try {
|
|
136
|
+
return yield Future.collect(streams.map((stream) => stream.future));
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
if (error instanceof StreamEnded) {
|
|
140
|
+
return new ExecutorState(true);
|
|
141
|
+
}
|
|
142
|
+
throw error;
|
|
143
|
+
}
|
|
144
|
+
}));
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Converts the provided value to a stream
|
|
148
|
+
* @param value
|
|
149
|
+
*/
|
|
150
|
+
static of(value) {
|
|
151
|
+
if (value[Symbol.iterator]) {
|
|
152
|
+
const iterator = value[Symbol.iterator]();
|
|
153
|
+
return new Stream((signal) => {
|
|
154
|
+
if (!signal.aborted) {
|
|
155
|
+
const { value, done } = iterator.next();
|
|
156
|
+
return new ExecutorState(done, value);
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
else if (value instanceof Future) {
|
|
161
|
+
let completed = false;
|
|
162
|
+
return new Stream((signal) => __awaiter(this, void 0, void 0, function* () {
|
|
163
|
+
if (completed) {
|
|
164
|
+
return new ExecutorState(true);
|
|
165
|
+
}
|
|
166
|
+
value.registerSignal(signal);
|
|
167
|
+
completed = true;
|
|
168
|
+
return new ExecutorState(false, yield value);
|
|
169
|
+
}));
|
|
170
|
+
}
|
|
171
|
+
const getIterator = value instanceof Function
|
|
172
|
+
? R.once((v) => value(v))
|
|
173
|
+
: R.once((v) => value[Symbol.asyncIterator]());
|
|
174
|
+
return new Stream((signal) => __awaiter(this, void 0, void 0, function* () {
|
|
175
|
+
if (!signal.aborted) {
|
|
176
|
+
const iterator = getIterator(signal);
|
|
177
|
+
const { value, done } = yield iterator.next();
|
|
178
|
+
return new ExecutorState(done, value);
|
|
179
|
+
}
|
|
180
|
+
}));
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Stream that never gives a result
|
|
184
|
+
*/
|
|
185
|
+
static forever() {
|
|
186
|
+
return new Stream(() => { });
|
|
187
|
+
}
|
|
188
|
+
get isParallel() {
|
|
189
|
+
return this.concurrencyLimit && this.sourceStream;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Gets a future of the next value on the stream, if any.
|
|
193
|
+
*/
|
|
194
|
+
get future() {
|
|
195
|
+
return Future.of((resolve, reject, signal) => {
|
|
196
|
+
if (!signal.aborted) {
|
|
197
|
+
signal.onabort = () => this.cancel();
|
|
198
|
+
this.next()
|
|
199
|
+
.then((v) => {
|
|
200
|
+
if (v.done && v.value === undefined) {
|
|
201
|
+
reject(new StreamEnded());
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
resolve(v.value);
|
|
205
|
+
}
|
|
206
|
+
})
|
|
207
|
+
.catch(reject);
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
get readableStream() {
|
|
212
|
+
const iterator = this[Symbol.asyncIterator]();
|
|
213
|
+
return new ReadableStream({
|
|
214
|
+
pull(controller) {
|
|
215
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
216
|
+
const { value, done } = yield iterator.next();
|
|
217
|
+
if (done) {
|
|
218
|
+
controller.close();
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
controller.enqueue(value);
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
},
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Cancel the stream on the given signal
|
|
229
|
+
* @param signal
|
|
230
|
+
*/
|
|
231
|
+
cancelOnSignal(signal) {
|
|
232
|
+
signal.addEventListener("abort", () => this.cancel());
|
|
233
|
+
return this;
|
|
234
|
+
}
|
|
235
|
+
parallel(concurrentlyLimit = 3) {
|
|
236
|
+
if (concurrentlyLimit < 1) {
|
|
237
|
+
throw new IllegalOperationError("Cannot start parallel stream less than 2");
|
|
238
|
+
}
|
|
239
|
+
const newStream = new Stream(() => { });
|
|
240
|
+
newStream.concurrencyLimit = concurrentlyLimit;
|
|
241
|
+
newStream.sourceStream = this;
|
|
242
|
+
newStream.executed = this.executed;
|
|
243
|
+
newStream.done = this.done;
|
|
244
|
+
newStream.cancelHooks = new Set(this.cancelHooks);
|
|
245
|
+
newStream.completionHooks = new Set(this.completionHooks);
|
|
246
|
+
newStream.completionHookInvoked = this.completionHookInvoked;
|
|
247
|
+
return newStream;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Transforms each data on the stream using the callback provided
|
|
251
|
+
* @param callback
|
|
252
|
+
*/
|
|
253
|
+
map(callback) {
|
|
254
|
+
this.actions.push({ type: ActionType.TRANSFORM, functor: callback });
|
|
255
|
+
return this;
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Filters data on the stream using the callback provided
|
|
259
|
+
* @param callback
|
|
260
|
+
*/
|
|
261
|
+
filter(callback) {
|
|
262
|
+
this.actions.push({
|
|
263
|
+
type: ActionType.FILTER,
|
|
264
|
+
functor: (v) => __awaiter(this, void 0, void 0, function* () {
|
|
265
|
+
if (v instanceof FutureResult)
|
|
266
|
+
v = v.value;
|
|
267
|
+
let result = callback(v);
|
|
268
|
+
if (result instanceof Promise || result instanceof Future)
|
|
269
|
+
result = yield result;
|
|
270
|
+
if (result)
|
|
271
|
+
return v;
|
|
272
|
+
return null;
|
|
273
|
+
}),
|
|
274
|
+
});
|
|
275
|
+
return this;
|
|
276
|
+
}
|
|
277
|
+
reduce(initialData, functor, exhaustive = true) {
|
|
278
|
+
let previousData = initialData;
|
|
279
|
+
if (exhaustive) {
|
|
280
|
+
this.actions.push({
|
|
281
|
+
type: ActionType.PACK,
|
|
282
|
+
functor: (v) => {
|
|
283
|
+
if (v === null || v === undefined) {
|
|
284
|
+
return { done: true, value: previousData };
|
|
285
|
+
}
|
|
286
|
+
previousData = functor(v, previousData);
|
|
287
|
+
return { done: false };
|
|
288
|
+
},
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
else {
|
|
292
|
+
this.actions.push({
|
|
293
|
+
type: ActionType.TRANSFORM,
|
|
294
|
+
functor: (v) => {
|
|
295
|
+
previousData = functor(v, previousData);
|
|
296
|
+
return previousData;
|
|
297
|
+
},
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
return this;
|
|
301
|
+
}
|
|
302
|
+
reduceWhile(predicate, initialData, functor, exhaustive = true) {
|
|
303
|
+
let previousData = initialData;
|
|
304
|
+
if (exhaustive) {
|
|
305
|
+
this.actions.push({
|
|
306
|
+
type: ActionType.PACK,
|
|
307
|
+
functor: (v) => {
|
|
308
|
+
if (v === null || v === undefined || predicate(v)) {
|
|
309
|
+
return { done: true, value: previousData };
|
|
310
|
+
}
|
|
311
|
+
previousData = functor(v, previousData);
|
|
312
|
+
return { done: false };
|
|
313
|
+
},
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
else {
|
|
317
|
+
this.actions.push({
|
|
318
|
+
type: ActionType.LIMIT,
|
|
319
|
+
functor: (v) => {
|
|
320
|
+
if (predicate(v)) {
|
|
321
|
+
previousData = functor(v, previousData);
|
|
322
|
+
return { done: false, value: previousData };
|
|
323
|
+
}
|
|
324
|
+
return { done: true };
|
|
325
|
+
},
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
return this;
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Retrieves the first value from the stream as a new stream. Important Note: the original stream cannot be executed
|
|
332
|
+
* before head() is invoked, otherwise the stream returned by head() will throw an error, as the first value was
|
|
333
|
+
* already consumed elsewhere
|
|
334
|
+
*/
|
|
335
|
+
head() {
|
|
336
|
+
return new Stream(() => __awaiter(this, void 0, void 0, function* () {
|
|
337
|
+
return new ExecutorState(true, yield this.execute());
|
|
338
|
+
}));
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Returns a new stream that exhausts the original stream, yielding the last value received before the original
|
|
342
|
+
* stream ended
|
|
343
|
+
*/
|
|
344
|
+
tail() {
|
|
345
|
+
let lastRecord = null;
|
|
346
|
+
return new Stream(() => __awaiter(this, void 0, void 0, function* () {
|
|
347
|
+
var _a, e_1, _b, _c;
|
|
348
|
+
try {
|
|
349
|
+
for (var _d = true, _e = __asyncValues(this), _f; _f = yield _e.next(), _a = _f.done, !_a;) {
|
|
350
|
+
_c = _f.value;
|
|
351
|
+
_d = false;
|
|
352
|
+
try {
|
|
353
|
+
const value = _c;
|
|
354
|
+
lastRecord = value;
|
|
355
|
+
}
|
|
356
|
+
finally {
|
|
357
|
+
_d = true;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
362
|
+
finally {
|
|
363
|
+
try {
|
|
364
|
+
if (!_d && !_a && (_b = _e.return)) yield _b.call(_e);
|
|
365
|
+
}
|
|
366
|
+
finally { if (e_1) throw e_1.error; }
|
|
367
|
+
}
|
|
368
|
+
return new ExecutorState(true, lastRecord);
|
|
369
|
+
}));
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* group data on the stream into separate slices
|
|
373
|
+
* E.g. Stream yielding 1,2,3,4,5,6 with chunk of 2 => [1,2], [3,4], [5,6]
|
|
374
|
+
* @param value chunk size or function that indicates when to split
|
|
375
|
+
* @param keepSplitCriteria if value provided was a function, this parameter is used to determine if the data used
|
|
376
|
+
* for the split criteria should be added to the chunk, if false then the data will be added to the next chunk
|
|
377
|
+
*/
|
|
378
|
+
chunk(value, keepSplitCriteria = false) {
|
|
379
|
+
if (typeof value === "number" && value < 1)
|
|
380
|
+
throw new Error("Invalid chunk size");
|
|
381
|
+
let chunkedResults = [];
|
|
382
|
+
if (typeof value === "number") {
|
|
383
|
+
this.actions.push({
|
|
384
|
+
type: ActionType.PACK,
|
|
385
|
+
functor: (v) => {
|
|
386
|
+
if (v === undefined || v === null) {
|
|
387
|
+
return { done: true, value: chunkedResults.length > 0 ? chunkedResults : undefined };
|
|
388
|
+
}
|
|
389
|
+
chunkedResults.push(v);
|
|
390
|
+
if (chunkedResults.length >= value) {
|
|
391
|
+
const data = chunkedResults;
|
|
392
|
+
chunkedResults = [];
|
|
393
|
+
return { done: true, value: data };
|
|
394
|
+
}
|
|
395
|
+
return { done: false };
|
|
396
|
+
},
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
else {
|
|
400
|
+
this.actions.push({
|
|
401
|
+
type: ActionType.TRANSFORM,
|
|
402
|
+
functor: (v) => {
|
|
403
|
+
if (value(v)) {
|
|
404
|
+
if (keepSplitCriteria)
|
|
405
|
+
chunkedResults.push(v);
|
|
406
|
+
const data = chunkedResults;
|
|
407
|
+
chunkedResults = [];
|
|
408
|
+
return { done: true, value: data };
|
|
409
|
+
}
|
|
410
|
+
chunkedResults.push(v);
|
|
411
|
+
return { done: false };
|
|
412
|
+
},
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
return this;
|
|
416
|
+
}
|
|
417
|
+
/**
|
|
418
|
+
* Clones the stream
|
|
419
|
+
* @param withSignals should the abort signals of the original stream trigger the cloned stream cancellation
|
|
420
|
+
*/
|
|
421
|
+
clone(withSignals) {
|
|
422
|
+
const newStream = new Stream(this.executor);
|
|
423
|
+
newStream.concurrencyLimit = this.concurrencyLimit;
|
|
424
|
+
newStream.sourceStream = this.sourceStream;
|
|
425
|
+
newStream.actions = [...this.actions];
|
|
426
|
+
newStream.executed = this.executed;
|
|
427
|
+
newStream.done = this.done;
|
|
428
|
+
newStream.backlog = [...this.backlog];
|
|
429
|
+
newStream.cancelHooks = new Set(this.cancelHooks);
|
|
430
|
+
newStream.completionHooks = new Set(this.completionHooks);
|
|
431
|
+
newStream.completionHookInvoked = this.completionHookInvoked;
|
|
432
|
+
if (withSignals) {
|
|
433
|
+
newStream.controller = this.controller;
|
|
434
|
+
}
|
|
435
|
+
return newStream;
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Register hook that is only ever called if stream was cancelled
|
|
439
|
+
* @param hook
|
|
440
|
+
*/
|
|
441
|
+
onCancellation(hook) {
|
|
442
|
+
this.cancelHooks.add(hook);
|
|
443
|
+
return this;
|
|
444
|
+
}
|
|
445
|
+
removeCancelHook(hook) {
|
|
446
|
+
this.cancelHooks.delete(hook);
|
|
447
|
+
return this;
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* Register hook that is called once the stream completes, cancelled or fails
|
|
451
|
+
* @param hook
|
|
452
|
+
*/
|
|
453
|
+
onCompletion(hook) {
|
|
454
|
+
this.completionHooks.add(hook);
|
|
455
|
+
return this;
|
|
456
|
+
}
|
|
457
|
+
removeCompletionHook(hook) {
|
|
458
|
+
this.completionHooks.delete(hook);
|
|
459
|
+
return this;
|
|
460
|
+
}
|
|
461
|
+
/**
|
|
462
|
+
* Cancels the stream
|
|
463
|
+
* @param reason
|
|
464
|
+
*/
|
|
465
|
+
cancel(reason) {
|
|
466
|
+
this.controller.abort(reason);
|
|
467
|
+
this.invokeCompletionHooks();
|
|
468
|
+
this.cancelHooks.forEach((handler) => {
|
|
469
|
+
void new Promise((resolve, reject) => {
|
|
470
|
+
try {
|
|
471
|
+
handler();
|
|
472
|
+
resolve(null);
|
|
473
|
+
}
|
|
474
|
+
catch (e) {
|
|
475
|
+
reject(e);
|
|
476
|
+
}
|
|
477
|
+
});
|
|
478
|
+
});
|
|
479
|
+
}
|
|
480
|
+
/**
|
|
481
|
+
* Limits the number of times the stream can yield a value
|
|
482
|
+
* @param count
|
|
483
|
+
*/
|
|
484
|
+
take(count) {
|
|
485
|
+
let index = 0;
|
|
486
|
+
this.actions.push({
|
|
487
|
+
type: ActionType.LIMIT,
|
|
488
|
+
functor: (value) => {
|
|
489
|
+
if (++index < count) {
|
|
490
|
+
return { value, done: false };
|
|
491
|
+
}
|
|
492
|
+
return { done: true, value };
|
|
493
|
+
},
|
|
494
|
+
});
|
|
495
|
+
return this;
|
|
496
|
+
}
|
|
497
|
+
/**
|
|
498
|
+
* Process stream data while predicate is true
|
|
499
|
+
* @param predicate
|
|
500
|
+
*/
|
|
501
|
+
takeWhile(predicate) {
|
|
502
|
+
this.actions.push({
|
|
503
|
+
type: ActionType.LIMIT,
|
|
504
|
+
functor: (value) => {
|
|
505
|
+
if (predicate(value)) {
|
|
506
|
+
return { value, done: false };
|
|
507
|
+
}
|
|
508
|
+
return { done: true };
|
|
509
|
+
},
|
|
510
|
+
});
|
|
511
|
+
return this;
|
|
512
|
+
}
|
|
513
|
+
/**
|
|
514
|
+
* Drop stream data until predicate is no longer true
|
|
515
|
+
* @param predicate
|
|
516
|
+
*/
|
|
517
|
+
skipWhile(predicate) {
|
|
518
|
+
let startFound = false;
|
|
519
|
+
this.actions.push({
|
|
520
|
+
type: ActionType.FILTER,
|
|
521
|
+
functor: (value) => {
|
|
522
|
+
if (!startFound && predicate(value)) {
|
|
523
|
+
return null;
|
|
524
|
+
}
|
|
525
|
+
startFound = true;
|
|
526
|
+
return value;
|
|
527
|
+
},
|
|
528
|
+
});
|
|
529
|
+
return this;
|
|
530
|
+
}
|
|
531
|
+
/**
|
|
532
|
+
* Removes duplicates from the stream based on the key extractor functor provided
|
|
533
|
+
* @param uniqKeyExtractor
|
|
534
|
+
* @param expiryPeriod
|
|
535
|
+
*/
|
|
536
|
+
dropRepeats(uniqKeyExtractor, expiryPeriod = undefined) {
|
|
537
|
+
const cache = new TimeableObject(undefined, expiryPeriod);
|
|
538
|
+
this.actions.push({
|
|
539
|
+
type: ActionType.FILTER,
|
|
540
|
+
functor: (v) => __awaiter(this, void 0, void 0, function* () {
|
|
541
|
+
const guid = uniqKeyExtractor(v);
|
|
542
|
+
if (!cache.has(guid)) {
|
|
543
|
+
cache.set(guid, 1);
|
|
544
|
+
return v;
|
|
545
|
+
}
|
|
546
|
+
return null;
|
|
547
|
+
}),
|
|
548
|
+
});
|
|
549
|
+
return this;
|
|
550
|
+
}
|
|
551
|
+
/**
|
|
552
|
+
* Allows the stream to yield only 1 value
|
|
553
|
+
*/
|
|
554
|
+
once() {
|
|
555
|
+
return this.take(1);
|
|
556
|
+
}
|
|
557
|
+
/**
|
|
558
|
+
* Skips the first X records on the stream
|
|
559
|
+
* @param count
|
|
560
|
+
*/
|
|
561
|
+
skip(count) {
|
|
562
|
+
let index = 1;
|
|
563
|
+
this.actions.push({
|
|
564
|
+
type: ActionType.FILTER,
|
|
565
|
+
functor: (value) => {
|
|
566
|
+
if (index && index++ <= count)
|
|
567
|
+
return null;
|
|
568
|
+
index = 0;
|
|
569
|
+
return value;
|
|
570
|
+
},
|
|
571
|
+
});
|
|
572
|
+
return this;
|
|
573
|
+
}
|
|
574
|
+
/**
|
|
575
|
+
* Applies rate limiting to the speed at which the data is made available on the stream
|
|
576
|
+
* @param period
|
|
577
|
+
*/
|
|
578
|
+
throttleBy(period) {
|
|
579
|
+
let future;
|
|
580
|
+
this.actions.push({
|
|
581
|
+
type: ActionType.TRANSFORM,
|
|
582
|
+
functor: (value) => {
|
|
583
|
+
if (!future) {
|
|
584
|
+
future = Future.sleep(period)
|
|
585
|
+
.thenApply(() => (future = undefined))
|
|
586
|
+
.schedule();
|
|
587
|
+
return value;
|
|
588
|
+
}
|
|
589
|
+
return null;
|
|
590
|
+
},
|
|
591
|
+
});
|
|
592
|
+
return this;
|
|
593
|
+
}
|
|
594
|
+
/**
|
|
595
|
+
* Flattens any nested structure from the data arriving on the stream
|
|
596
|
+
*/
|
|
597
|
+
flatten() {
|
|
598
|
+
this.actions.push({
|
|
599
|
+
type: ActionType.UNPACK,
|
|
600
|
+
functor: (value) => {
|
|
601
|
+
if (value instanceof Array || Array.isArray(value) || value instanceof Set)
|
|
602
|
+
return R.flatten(value);
|
|
603
|
+
return [value];
|
|
604
|
+
},
|
|
605
|
+
});
|
|
606
|
+
return this;
|
|
607
|
+
}
|
|
608
|
+
/**
|
|
609
|
+
* Runs the stream in the background, collecting and buffering the results for the next chain in the stream. This
|
|
610
|
+
* allows the stream to run concurrently without waiting on single emitted values sequentially
|
|
611
|
+
* @param maxSize
|
|
612
|
+
*/
|
|
613
|
+
buffer(maxSize) {
|
|
614
|
+
return Stream.seed(() => {
|
|
615
|
+
const queue = new Queue(maxSize);
|
|
616
|
+
this.forEach((record) => queue.awaitEnqueue(record)).finally(() => {
|
|
617
|
+
queue
|
|
618
|
+
.awaitEmpty()
|
|
619
|
+
.thenApply(() => queue.close())
|
|
620
|
+
.schedule();
|
|
621
|
+
});
|
|
622
|
+
return queue.streamEntries.catch((error) => {
|
|
623
|
+
throw error;
|
|
624
|
+
});
|
|
625
|
+
});
|
|
626
|
+
}
|
|
627
|
+
/**
|
|
628
|
+
* Process stream values in the background, thereby yielding the latest value if the collector of the stream is too
|
|
629
|
+
* slow (i.e. values that are not read by collector before new value flows in the stream, will be dropped)
|
|
630
|
+
*/
|
|
631
|
+
conflate() {
|
|
632
|
+
return Stream.seed(() => {
|
|
633
|
+
const value = new AtomicValue();
|
|
634
|
+
this.forEach((record) => value.set(record))
|
|
635
|
+
.finally(() => value.destroy())
|
|
636
|
+
.schedule();
|
|
637
|
+
return value.stream;
|
|
638
|
+
});
|
|
639
|
+
}
|
|
640
|
+
/**
|
|
641
|
+
* If the stream receives an error, handle that error with the given callback. If callback doesn't throw an error,
|
|
642
|
+
* then the stream will recover and resume with the result provided by the callback
|
|
643
|
+
* @param callback
|
|
644
|
+
*/
|
|
645
|
+
catch(callback) {
|
|
646
|
+
this.actions.push({
|
|
647
|
+
type: ActionType.CATCH,
|
|
648
|
+
functor: callback,
|
|
649
|
+
});
|
|
650
|
+
return this;
|
|
651
|
+
}
|
|
652
|
+
/**
|
|
653
|
+
* Consumes the entire stream and store the data in an array. Future is immediately executed
|
|
654
|
+
*/
|
|
655
|
+
collect(collector) {
|
|
656
|
+
return collector(this.isParallel ? this.join() : this).schedule();
|
|
657
|
+
}
|
|
658
|
+
/**
|
|
659
|
+
* Continuously exhaust the stream until the stream ends or the limit is reached. No result will be provided at
|
|
660
|
+
* the end. Future is immediately executed
|
|
661
|
+
* @param limit
|
|
662
|
+
*/
|
|
663
|
+
consume(limit = Number.POSITIVE_INFINITY) {
|
|
664
|
+
return new Future((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
|
|
665
|
+
var _a, e_2, _b, _c, _d, e_3, _e, _f;
|
|
666
|
+
var _g;
|
|
667
|
+
try {
|
|
668
|
+
if (limit !== Number.POSITIVE_INFINITY && limit !== Number.NEGATIVE_INFINITY) {
|
|
669
|
+
if (limit === 0)
|
|
670
|
+
return;
|
|
671
|
+
let index = 0;
|
|
672
|
+
try {
|
|
673
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
674
|
+
for (var _h = true, _j = __asyncValues(this), _k; _k = yield _j.next(), _a = _k.done, !_a;) {
|
|
675
|
+
_c = _k.value;
|
|
676
|
+
_h = false;
|
|
677
|
+
try {
|
|
678
|
+
const _ = _c;
|
|
679
|
+
if (++index >= limit)
|
|
680
|
+
break;
|
|
681
|
+
}
|
|
682
|
+
finally {
|
|
683
|
+
_h = true;
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
688
|
+
finally {
|
|
689
|
+
try {
|
|
690
|
+
if (!_h && !_a && (_b = _j.return)) yield _b.call(_j);
|
|
691
|
+
}
|
|
692
|
+
finally { if (e_2) throw e_2.error; }
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
else {
|
|
696
|
+
try {
|
|
697
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars,no-empty
|
|
698
|
+
for (var _l = true, _m = __asyncValues(this), _o; _o = yield _m.next(), _d = _o.done, !_d;) {
|
|
699
|
+
_f = _o.value;
|
|
700
|
+
_l = false;
|
|
701
|
+
try {
|
|
702
|
+
const _ = _f;
|
|
703
|
+
}
|
|
704
|
+
finally {
|
|
705
|
+
_l = true;
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
|
710
|
+
finally {
|
|
711
|
+
try {
|
|
712
|
+
if (!_l && !_d && (_e = _m.return)) yield _e.call(_m);
|
|
713
|
+
}
|
|
714
|
+
finally { if (e_3) throw e_3.error; }
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
resolve();
|
|
718
|
+
}
|
|
719
|
+
catch (error) {
|
|
720
|
+
reject(error instanceof FutureError ? error : new FutureError((_g = error === null || error === void 0 ? void 0 : error.message) !== null && _g !== void 0 ? _g : "Unknown"));
|
|
721
|
+
}
|
|
722
|
+
})).schedule();
|
|
723
|
+
}
|
|
724
|
+
/**
|
|
725
|
+
* Iterates over the stream of values, used as a collector. Future is immediately executed
|
|
726
|
+
* @param callback
|
|
727
|
+
*/
|
|
728
|
+
forEach(callback) {
|
|
729
|
+
return new Future((resolve, reject, signal) => __awaiter(this, void 0, void 0, function* () {
|
|
730
|
+
var _a;
|
|
731
|
+
try {
|
|
732
|
+
yield this.map((value) => callback(value))
|
|
733
|
+
.consume()
|
|
734
|
+
.registerSignal(signal);
|
|
735
|
+
resolve();
|
|
736
|
+
}
|
|
737
|
+
catch (error) {
|
|
738
|
+
reject(error instanceof FutureError ? error : new FutureError((_a = error === null || error === void 0 ? void 0 : error.message) !== null && _a !== void 0 ? _a : "Unknown"));
|
|
739
|
+
}
|
|
740
|
+
})).schedule();
|
|
741
|
+
}
|
|
742
|
+
/**
|
|
743
|
+
* Runs the stream only once. After this call, the stream is closed. Future is immediately executed
|
|
744
|
+
*/
|
|
745
|
+
execute() {
|
|
746
|
+
return this.runLock
|
|
747
|
+
.with(({ signal }) => __awaiter(this, void 0, void 0, function* () {
|
|
748
|
+
if (this.executed)
|
|
749
|
+
throw new CallExecutionError("Cannot rerun a one time stream");
|
|
750
|
+
while (true) {
|
|
751
|
+
const { state, value } = yield (this.sourceStream && this.concurrencyLimit
|
|
752
|
+
? this.forwardExecute().registerSignal(signal)
|
|
753
|
+
: this.__execute__().registerSignal(signal));
|
|
754
|
+
if (state !== State.CONTINUE) {
|
|
755
|
+
this.done = true;
|
|
756
|
+
this.invokeCompletionHooks();
|
|
757
|
+
return value;
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
}))
|
|
761
|
+
.schedule();
|
|
762
|
+
}
|
|
763
|
+
join() {
|
|
764
|
+
if (!this.concurrencyLimit || !this.sourceStream) {
|
|
765
|
+
throw new IllegalOperationError("Join can only be called on a parallel stream");
|
|
766
|
+
}
|
|
767
|
+
return Stream.of(this.internalIterator()).flatten();
|
|
768
|
+
}
|
|
769
|
+
[Symbol.asyncIterator]() {
|
|
770
|
+
return this.isParallel ? this.join() : this;
|
|
771
|
+
}
|
|
772
|
+
next(...args) {
|
|
773
|
+
if (this.concurrencyLimit || this.sourceStream) {
|
|
774
|
+
throw new IllegalOperationError("Iterator cannot be called on a parallel stream.Please join first");
|
|
775
|
+
}
|
|
776
|
+
return this.internalNext().run();
|
|
777
|
+
}
|
|
778
|
+
return(value) {
|
|
779
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
780
|
+
if (this.concurrencyLimit || this.sourceStream) {
|
|
781
|
+
throw new IllegalOperationError("Iterator cannot be called on a parallel stream.Please join first");
|
|
782
|
+
}
|
|
783
|
+
return { done: true, value: yield this.execute().run() };
|
|
784
|
+
});
|
|
785
|
+
}
|
|
786
|
+
throw(e) {
|
|
787
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
788
|
+
return {
|
|
789
|
+
done: true,
|
|
790
|
+
value: undefined,
|
|
791
|
+
};
|
|
792
|
+
});
|
|
793
|
+
}
|
|
794
|
+
__execute__(preProcessor = R.identity) {
|
|
795
|
+
return Future.of((resolve, __, signal) => __awaiter(this, void 0, void 0, function* () {
|
|
796
|
+
this.executed = true;
|
|
797
|
+
let i = 0;
|
|
798
|
+
let traversableActions = this.actions;
|
|
799
|
+
let data;
|
|
800
|
+
try {
|
|
801
|
+
const { index: actionStream, data: actionData } = yield this.checkBacklog(signal);
|
|
802
|
+
if (actionStream >= 0) {
|
|
803
|
+
i = actionStream;
|
|
804
|
+
data = actionData;
|
|
805
|
+
}
|
|
806
|
+
else if (this.canRunExecutor) {
|
|
807
|
+
do {
|
|
808
|
+
data = this.executor(this.controller.signal);
|
|
809
|
+
do {
|
|
810
|
+
if (data instanceof ExecutorState) {
|
|
811
|
+
this.canRunExecutor = !data.done;
|
|
812
|
+
data = data.value;
|
|
813
|
+
if (!this.canRunExecutor && (data === null || data === undefined)) {
|
|
814
|
+
[data, traversableActions] = yield this.findAndExecuteMostRecentPacker(signal);
|
|
815
|
+
if (data === undefined) {
|
|
816
|
+
return resolve({ state: State.DONE });
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
if (data instanceof Promise)
|
|
821
|
+
data = yield data;
|
|
822
|
+
if (data instanceof Future)
|
|
823
|
+
data = yield data.registerSignal(signal);
|
|
824
|
+
if (data instanceof FutureResult)
|
|
825
|
+
data = data.value;
|
|
826
|
+
if (data instanceof Stream) {
|
|
827
|
+
this.backlog.push({ actionStream: 0, records: data });
|
|
828
|
+
return resolve({ state: State.CONTINUE });
|
|
829
|
+
}
|
|
830
|
+
} while (data instanceof ExecutorState);
|
|
831
|
+
} while (data === undefined && this.canRunExecutor);
|
|
832
|
+
}
|
|
833
|
+
else {
|
|
834
|
+
[data, traversableActions] = yield this.findAndExecuteMostRecentPacker(signal);
|
|
835
|
+
if (data === undefined) {
|
|
836
|
+
return resolve({ state: State.DONE });
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
catch (e) {
|
|
841
|
+
const [value, index] = yield this.processError(e, i, traversableActions, signal);
|
|
842
|
+
i = index + 1;
|
|
843
|
+
if (value === undefined || value === null)
|
|
844
|
+
return resolve({ state: State.CONTINUE });
|
|
845
|
+
data = value;
|
|
846
|
+
}
|
|
847
|
+
resolve(yield this.processor(i, traversableActions, data, preProcessor, signal));
|
|
848
|
+
}), this.controller.signal);
|
|
849
|
+
}
|
|
850
|
+
processor(index, traversableActions, record, preProcessor = R.identity, signal) {
|
|
851
|
+
return Future.of((resolve, reject, signal) => __awaiter(this, void 0, void 0, function* () {
|
|
852
|
+
let data = record;
|
|
853
|
+
for (let i = index; i < traversableActions.length; i++) {
|
|
854
|
+
try {
|
|
855
|
+
const { type, functor } = traversableActions[i];
|
|
856
|
+
switch (type) {
|
|
857
|
+
case ActionType.FILTER: {
|
|
858
|
+
const preResult = yield this.yieldTrueResult(preProcessor(data), signal);
|
|
859
|
+
const result = yield this.yieldTrueResult(functor(preResult instanceof Promise ? yield preResult : preResult), signal);
|
|
860
|
+
if (result === null || result === undefined) {
|
|
861
|
+
return resolve({ state: State.CONTINUE });
|
|
862
|
+
}
|
|
863
|
+
data = result;
|
|
864
|
+
break;
|
|
865
|
+
}
|
|
866
|
+
case ActionType.TRANSFORM: {
|
|
867
|
+
const preResult = yield this.yieldTrueResult(preProcessor(data), signal);
|
|
868
|
+
const result = yield this.yieldTrueResult(functor(preResult instanceof Promise ? yield preResult : preResult), signal);
|
|
869
|
+
if (result instanceof Stream) {
|
|
870
|
+
this.backlog = [{ actionStream: i + 1, records: result }, ...this.backlog];
|
|
871
|
+
return resolve({ state: State.CONTINUE });
|
|
872
|
+
}
|
|
873
|
+
data = result;
|
|
874
|
+
break;
|
|
875
|
+
}
|
|
876
|
+
case ActionType.PACK: {
|
|
877
|
+
const preResult = yield this.yieldTrueResult(preProcessor(data), signal);
|
|
878
|
+
const result = (yield this.yieldTrueResult(functor(preResult instanceof Promise ? yield preResult : preResult), signal));
|
|
879
|
+
if (!result.done) {
|
|
880
|
+
return resolve({ state: State.CONTINUE });
|
|
881
|
+
}
|
|
882
|
+
data = result.value;
|
|
883
|
+
break;
|
|
884
|
+
}
|
|
885
|
+
case ActionType.LIMIT: {
|
|
886
|
+
const preResult = yield this.yieldTrueResult(preProcessor(data), signal);
|
|
887
|
+
const result = (yield this.yieldTrueResult(functor(preResult instanceof Promise ? yield preResult : preResult), signal));
|
|
888
|
+
if (result.done) {
|
|
889
|
+
this.canRunExecutor = false;
|
|
890
|
+
this.backlog = [];
|
|
891
|
+
this.actions = traversableActions.splice(i + 1);
|
|
892
|
+
traversableActions = this.actions;
|
|
893
|
+
i = -1;
|
|
894
|
+
}
|
|
895
|
+
data = result.value;
|
|
896
|
+
break;
|
|
897
|
+
}
|
|
898
|
+
case ActionType.UNPACK: {
|
|
899
|
+
const preResult = yield this.yieldTrueResult(preProcessor(data), signal);
|
|
900
|
+
const result = (yield this.yieldTrueResult(functor(preResult instanceof Promise ? yield preResult : preResult), signal));
|
|
901
|
+
if (result.length === 0) {
|
|
902
|
+
return resolve({ state: State.CONTINUE });
|
|
903
|
+
}
|
|
904
|
+
else if (result.length === 1) {
|
|
905
|
+
data = result[0];
|
|
906
|
+
}
|
|
907
|
+
else {
|
|
908
|
+
const value = result.shift();
|
|
909
|
+
this.backlog = [{ actionStream: i + 1, records: result }, ...this.backlog];
|
|
910
|
+
data = value;
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
catch (error) {
|
|
916
|
+
const [value, index] = yield this.processError(error, i, traversableActions, signal);
|
|
917
|
+
i = index;
|
|
918
|
+
if (value !== undefined && value !== null)
|
|
919
|
+
data = value;
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
return resolve({ state: State.MATCHED, value: data });
|
|
923
|
+
}), signal);
|
|
924
|
+
}
|
|
925
|
+
internalIterator() {
|
|
926
|
+
const iterator = {
|
|
927
|
+
next: () => this.internalNext().run(),
|
|
928
|
+
return: this.return.bind(this),
|
|
929
|
+
throw: this.throw,
|
|
930
|
+
[Symbol.asyncIterator]() {
|
|
931
|
+
return iterator;
|
|
932
|
+
},
|
|
933
|
+
};
|
|
934
|
+
return iterator;
|
|
935
|
+
}
|
|
936
|
+
checkBacklog(signal) {
|
|
937
|
+
return Future.of((resolve, __, signal) => __awaiter(this, void 0, void 0, function* () {
|
|
938
|
+
if (this.backlog.length === 0)
|
|
939
|
+
return resolve({ index: -1 });
|
|
940
|
+
const { actionStream, records } = this.backlog[0];
|
|
941
|
+
const index = actionStream;
|
|
942
|
+
if (records instanceof Stream) {
|
|
943
|
+
const hook = () => records.cancel();
|
|
944
|
+
this.onCancellation(hook);
|
|
945
|
+
try {
|
|
946
|
+
const { value: data, done } = yield records[Symbol.asyncIterator]().next();
|
|
947
|
+
if (done) {
|
|
948
|
+
this.backlog.shift();
|
|
949
|
+
return resolve(yield this.checkBacklog(signal));
|
|
950
|
+
}
|
|
951
|
+
return resolve({ index, data });
|
|
952
|
+
}
|
|
953
|
+
finally {
|
|
954
|
+
this.removeCancelHook(hook);
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
else {
|
|
958
|
+
const data = records.shift();
|
|
959
|
+
if (records.length === 0) {
|
|
960
|
+
this.backlog.shift();
|
|
961
|
+
}
|
|
962
|
+
return resolve({ index, data });
|
|
963
|
+
}
|
|
964
|
+
}), signal);
|
|
965
|
+
}
|
|
966
|
+
internalNext() {
|
|
967
|
+
return this.runLock.with(({ signal }) => __awaiter(this, void 0, void 0, function* () {
|
|
968
|
+
try {
|
|
969
|
+
while (!this.done) {
|
|
970
|
+
const { state, value } = yield (this.sourceStream && this.concurrencyLimit
|
|
971
|
+
? this.forwardExecute()
|
|
972
|
+
: this.__execute__());
|
|
973
|
+
if (state === State.MATCHED && value !== undefined)
|
|
974
|
+
return { done: false, value };
|
|
975
|
+
if (state === State.DONE) {
|
|
976
|
+
this.done = true;
|
|
977
|
+
if (value !== undefined)
|
|
978
|
+
return { done: false, value };
|
|
979
|
+
}
|
|
980
|
+
if (this.controller.signal.aborted) {
|
|
981
|
+
this.done = true;
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
this.invokeCompletionHooks();
|
|
985
|
+
return { done: true, value: undefined };
|
|
986
|
+
}
|
|
987
|
+
catch (error) {
|
|
988
|
+
this.invokeCompletionHooks();
|
|
989
|
+
if (error instanceof StreamEnded || error instanceof FutureCancelled)
|
|
990
|
+
return { done: true, value: null };
|
|
991
|
+
throw error;
|
|
992
|
+
}
|
|
993
|
+
}));
|
|
994
|
+
}
|
|
995
|
+
invokeCompletionHooks() {
|
|
996
|
+
if (this.completionHookInvoked) {
|
|
997
|
+
return;
|
|
998
|
+
}
|
|
999
|
+
this.completionHookInvoked = true;
|
|
1000
|
+
this.completionHooks.forEach((handler) => {
|
|
1001
|
+
void new Promise((resolve, reject) => {
|
|
1002
|
+
try {
|
|
1003
|
+
handler();
|
|
1004
|
+
resolve(null);
|
|
1005
|
+
}
|
|
1006
|
+
catch (e) {
|
|
1007
|
+
reject(e);
|
|
1008
|
+
}
|
|
1009
|
+
});
|
|
1010
|
+
});
|
|
1011
|
+
this.backlog.forEach(({ records }) => {
|
|
1012
|
+
if (records instanceof Stream) {
|
|
1013
|
+
records.cancel();
|
|
1014
|
+
}
|
|
1015
|
+
});
|
|
1016
|
+
}
|
|
1017
|
+
processError(error, i, actions, signal) {
|
|
1018
|
+
return Future.of((resolve, reject, signal) => __awaiter(this, void 0, void 0, function* () {
|
|
1019
|
+
let errorMessage;
|
|
1020
|
+
if (actions.length === 0)
|
|
1021
|
+
throw error;
|
|
1022
|
+
else if (!(error instanceof Error))
|
|
1023
|
+
errorMessage = new Error(error);
|
|
1024
|
+
else
|
|
1025
|
+
errorMessage = error;
|
|
1026
|
+
const catchAction = actions.splice(i).find((v, index) => {
|
|
1027
|
+
if (v.type === ActionType.CATCH) {
|
|
1028
|
+
i = index;
|
|
1029
|
+
return true;
|
|
1030
|
+
}
|
|
1031
|
+
return false;
|
|
1032
|
+
});
|
|
1033
|
+
if (!catchAction)
|
|
1034
|
+
throw error;
|
|
1035
|
+
try {
|
|
1036
|
+
const value = catchAction.functor(errorMessage);
|
|
1037
|
+
return resolve([yield this.yieldTrueResult(value, signal), i]);
|
|
1038
|
+
}
|
|
1039
|
+
catch (e) {
|
|
1040
|
+
return resolve(yield this.processError(e, i, actions, signal));
|
|
1041
|
+
}
|
|
1042
|
+
}), signal);
|
|
1043
|
+
}
|
|
1044
|
+
findAndExecuteMostRecentPacker(signal) {
|
|
1045
|
+
return Future.of((resolve, __, signal) => __awaiter(this, void 0, void 0, function* () {
|
|
1046
|
+
const index = this.actions.findIndex((action) => action.type === ActionType.PACK);
|
|
1047
|
+
if (index >= 0) {
|
|
1048
|
+
const functor = this.actions[index].functor;
|
|
1049
|
+
const result = (yield this.yieldTrueResult(functor(undefined), signal));
|
|
1050
|
+
if (result.done) {
|
|
1051
|
+
return resolve([result.value, this.actions.slice(index + 1)]);
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
return resolve([undefined, []]);
|
|
1055
|
+
}), signal);
|
|
1056
|
+
}
|
|
1057
|
+
yieldTrueResult(value, signal) {
|
|
1058
|
+
return Future.of((resolve, reject, signal) => __awaiter(this, void 0, void 0, function* () {
|
|
1059
|
+
if (value instanceof Future)
|
|
1060
|
+
value = yield value.registerSignal(signal);
|
|
1061
|
+
if (value instanceof FutureResult)
|
|
1062
|
+
value = value.value;
|
|
1063
|
+
if (value instanceof Promise)
|
|
1064
|
+
value = yield value;
|
|
1065
|
+
resolve(value);
|
|
1066
|
+
}), signal);
|
|
1067
|
+
}
|
|
1068
|
+
forwardExecute(preProcessor = R.identity) {
|
|
1069
|
+
return Future.of((resolve, reject, signal) => __awaiter(this, void 0, void 0, function* () {
|
|
1070
|
+
var _a, e_4, _b, _c;
|
|
1071
|
+
let pending = [];
|
|
1072
|
+
try {
|
|
1073
|
+
for (var _d = true, _e = __asyncValues(this.sourceStream.internalIterator()), _f; _f = yield _e.next(), _a = _f.done, !_a;) {
|
|
1074
|
+
_c = _f.value;
|
|
1075
|
+
_d = false;
|
|
1076
|
+
try {
|
|
1077
|
+
const data = _c;
|
|
1078
|
+
pending.push(this.processor(0, this.actions, data, preProcessor, signal));
|
|
1079
|
+
if (pending.length === this.concurrencyLimit) {
|
|
1080
|
+
const result = yield this.collectResult(pending, signal);
|
|
1081
|
+
if (result.state === State.CONTINUE) {
|
|
1082
|
+
pending = [];
|
|
1083
|
+
}
|
|
1084
|
+
else {
|
|
1085
|
+
return resolve(result);
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
1089
|
+
finally {
|
|
1090
|
+
_d = true;
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
catch (e_4_1) { e_4 = { error: e_4_1 }; }
|
|
1095
|
+
finally {
|
|
1096
|
+
try {
|
|
1097
|
+
if (!_d && !_a && (_b = _e.return)) yield _b.call(_e);
|
|
1098
|
+
}
|
|
1099
|
+
finally { if (e_4) throw e_4.error; }
|
|
1100
|
+
}
|
|
1101
|
+
const { state, value } = yield this.collectResult(pending, signal);
|
|
1102
|
+
if (state === State.CONTINUE) {
|
|
1103
|
+
return resolve({ state: State.DONE });
|
|
1104
|
+
}
|
|
1105
|
+
return resolve({ state: State.DONE, value });
|
|
1106
|
+
}));
|
|
1107
|
+
}
|
|
1108
|
+
collectResult(pending, signal) {
|
|
1109
|
+
return Future.of((resolve, reject, signal) => __awaiter(this, void 0, void 0, function* () {
|
|
1110
|
+
let doneFound = false;
|
|
1111
|
+
const results = (yield Future.collect(pending).registerSignal(signal)).filter((v) => {
|
|
1112
|
+
if (v.state === State.DONE) {
|
|
1113
|
+
doneFound = true;
|
|
1114
|
+
return true;
|
|
1115
|
+
}
|
|
1116
|
+
else if (v.state === State.MATCHED) {
|
|
1117
|
+
return true;
|
|
1118
|
+
}
|
|
1119
|
+
return false;
|
|
1120
|
+
});
|
|
1121
|
+
if (doneFound) {
|
|
1122
|
+
return resolve({ state: State.DONE, value: results.map((v) => v.value) });
|
|
1123
|
+
}
|
|
1124
|
+
else if (results.length) {
|
|
1125
|
+
return resolve({ state: State.MATCHED, value: results.map((v) => v.value) });
|
|
1126
|
+
}
|
|
1127
|
+
return resolve({ state: State.CONTINUE });
|
|
1128
|
+
}), signal);
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
export { State, Stream };
|