@bluelibs/runner 1.3.0 → 1.5.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.
Files changed (48) hide show
  1. package/README.md +223 -82
  2. package/dist/defs.d.ts +41 -7
  3. package/dist/examples/express-mongo/index.d.ts +0 -0
  4. package/dist/examples/express-mongo/index.js +3 -0
  5. package/dist/examples/express-mongo/index.js.map +1 -0
  6. package/dist/globalEvents.js +1 -0
  7. package/dist/globalEvents.js.map +1 -1
  8. package/dist/models/DependencyProcessor.d.ts +7 -5
  9. package/dist/models/DependencyProcessor.js +46 -25
  10. package/dist/models/DependencyProcessor.js.map +1 -1
  11. package/dist/models/EventManager.d.ts +1 -1
  12. package/dist/models/EventManager.js +2 -2
  13. package/dist/models/EventManager.js.map +1 -1
  14. package/dist/models/Logger.d.ts +16 -11
  15. package/dist/models/Logger.js +29 -17
  16. package/dist/models/Logger.js.map +1 -1
  17. package/dist/models/ResourceInitializer.d.ts +3 -1
  18. package/dist/models/ResourceInitializer.js +10 -10
  19. package/dist/models/ResourceInitializer.js.map +1 -1
  20. package/dist/models/Store.d.ts +4 -1
  21. package/dist/models/Store.js +17 -3
  22. package/dist/models/Store.js.map +1 -1
  23. package/dist/models/TaskRunner.d.ts +3 -1
  24. package/dist/models/TaskRunner.js +13 -7
  25. package/dist/models/TaskRunner.js.map +1 -1
  26. package/dist/run.d.ts +0 -8
  27. package/dist/run.js +11 -8
  28. package/dist/run.js.map +1 -1
  29. package/package.json +3 -2
  30. package/src/__tests__/index.ts +1 -0
  31. package/src/__tests__/models/EventManager.test.ts +21 -21
  32. package/src/__tests__/models/Logger.test.ts +50 -5
  33. package/src/__tests__/models/ResourceInitializer.test.ts +61 -25
  34. package/src/__tests__/models/Store.test.ts +4 -2
  35. package/src/__tests__/models/TaskRunner.test.ts +5 -2
  36. package/src/__tests__/run.hooks.test.ts +0 -31
  37. package/src/__tests__/run.middleware.test.ts +26 -0
  38. package/src/__tests__/typesafety.test.ts +127 -0
  39. package/src/defs.ts +57 -15
  40. package/src/examples/express-mongo/index.ts +1 -0
  41. package/src/globalEvents.ts +1 -0
  42. package/src/models/DependencyProcessor.ts +103 -47
  43. package/src/models/EventManager.ts +4 -2
  44. package/src/models/Logger.ts +39 -19
  45. package/src/models/ResourceInitializer.ts +53 -27
  46. package/src/models/Store.ts +20 -3
  47. package/src/models/TaskRunner.ts +45 -18
  48. package/src/run.ts +19 -15
@@ -6,12 +6,13 @@ import {
6
6
  IHookDefinition,
7
7
  IEventDefinition,
8
8
  } from "../defs";
9
- import { ResourceStoreElementType, Store } from "./Store";
9
+ import { ResourceStoreElementType, Store, TaskStoreElementType } from "./Store";
10
10
  import * as utils from "../define";
11
11
  import { EventManager } from "./EventManager";
12
12
  import { ResourceInitializer } from "./ResourceInitializer";
13
13
  import { TaskRunner } from "./TaskRunner";
14
14
  import { Errors } from "../errors";
15
+ import { Logger } from "./Logger";
15
16
 
16
17
  /**
17
18
  * This class is responsible of setting up dependencies with their respective computedValues.
@@ -24,9 +25,14 @@ export class DependencyProcessor {
24
25
  constructor(
25
26
  protected readonly store: Store,
26
27
  protected readonly eventManager: EventManager,
27
- protected readonly taskRunner: TaskRunner
28
+ protected readonly taskRunner: TaskRunner,
29
+ protected readonly logger: Logger
28
30
  ) {
29
- this.resourceInitializer = new ResourceInitializer(store, eventManager);
31
+ this.resourceInitializer = new ResourceInitializer(
32
+ store,
33
+ eventManager,
34
+ logger
35
+ );
30
36
  }
31
37
 
32
38
  /**
@@ -35,35 +41,59 @@ export class DependencyProcessor {
35
41
  async computeAllDependencies() {
36
42
  for (const middleware of this.store.middlewares.values()) {
37
43
  const deps = middleware.middleware.dependencies as DependencyMapType;
38
- middleware.computedDependencies = await this.extractDependencies(deps);
44
+ middleware.computedDependencies = await this.extractDependencies(
45
+ deps,
46
+ middleware.middleware.id
47
+ );
39
48
  }
40
49
 
41
50
  for (const task of this.store.tasks.values()) {
42
- const deps = task.task.dependencies as DependencyMapType;
43
- task.computedDependencies = await this.extractDependencies(deps);
44
-
45
- let eventDefinition = task.task.on;
46
- if (eventDefinition) {
47
- if (this.store.events.get(eventDefinition.id) === undefined) {
48
- throw Errors.eventNotFound(eventDefinition.id);
49
- }
50
-
51
- this.eventManager.addListener(
52
- eventDefinition,
53
- async (receivedEvent) => {
54
- return this.taskRunner.run(
55
- task.task,
56
- receivedEvent,
57
- task.computedDependencies
58
- );
59
- }
60
- );
61
- }
51
+ await this.computeTaskDependencies(task);
62
52
  }
63
53
 
64
54
  for (const resource of this.store.resources.values()) {
65
55
  await this.processResourceDependencies(resource);
66
56
  }
57
+
58
+ // leftovers that were registered but not depended upon, except root
59
+ // they should still be initialized as they might extend other
60
+ await this.initializeUninitializedResources();
61
+ }
62
+
63
+ private async computeTaskDependencies(
64
+ task: TaskStoreElementType<any, any, any>
65
+ ) {
66
+ const deps = task.task.dependencies as DependencyMapType;
67
+ task.computedDependencies = await this.extractDependencies(
68
+ deps,
69
+ task.task.id
70
+ );
71
+
72
+ let eventDefinition = task.task.on;
73
+ if (eventDefinition) {
74
+ if (this.store.events.get(eventDefinition.id) === undefined) {
75
+ throw Errors.eventNotFound(eventDefinition.id);
76
+ }
77
+
78
+ this.eventManager.addListener(
79
+ eventDefinition,
80
+ async (receivedEvent) => {
81
+ this.logger.debug({
82
+ message: `Task ${task.task.id} listened to event: ${eventDefinition.id}`,
83
+ event: receivedEvent,
84
+ });
85
+
86
+ return this.taskRunner.run(
87
+ task.task,
88
+ receivedEvent,
89
+ task.computedDependencies
90
+ );
91
+ },
92
+ {
93
+ order: task.task.listenerOrder || 0,
94
+ }
95
+ );
96
+ }
67
97
  }
68
98
 
69
99
  // Most likely these are resources that no-one has dependencies towards
@@ -93,7 +123,10 @@ export class DependencyProcessor {
93
123
  resource: ResourceStoreElementType<any, any, {}>
94
124
  ) {
95
125
  const deps = resource.resource.dependencies as DependencyMapType;
96
- resource.computedDependencies = await this.extractDependencies(deps);
126
+ resource.computedDependencies = await this.extractDependencies(
127
+ deps,
128
+ resource.resource.id
129
+ );
97
130
  }
98
131
 
99
132
  public async initializeRoot() {
@@ -111,10 +144,8 @@ export class DependencyProcessor {
111
144
 
112
145
  /**
113
146
  * Processes all hooks, should run before emission of any event.
114
- * @returns
115
147
  */
116
148
  public attachHooks() {
117
- // iterate through resources and send them to processHooks
118
149
  for (const resource of this.store.resources.values()) {
119
150
  if (resource.resource.hooks) {
120
151
  this.attachHooksToResource(resource);
@@ -141,46 +172,59 @@ export class DependencyProcessor {
141
172
 
142
173
  for (const hook of hooks) {
143
174
  const event = hook.event;
175
+ const order = hook.order || 0;
144
176
  if (event === "*") {
145
- this.eventManager.addGlobalListener(async (receivedEvent) => {
146
- return hook.run(
147
- receivedEvent,
148
- resourceStoreElement.computedDependencies as DependencyValuesType<{}>
149
- );
150
- });
177
+ this.eventManager.addGlobalListener(
178
+ async (receivedEvent) => {
179
+ return hook.run(
180
+ receivedEvent,
181
+ resourceStoreElement.computedDependencies as DependencyValuesType<{}>
182
+ );
183
+ },
184
+ {
185
+ order,
186
+ }
187
+ );
151
188
  } else {
152
189
  if (this.store.events.has(event.id) === false) {
153
190
  throw Errors.eventNotFound(event.id);
154
191
  }
155
- this.eventManager.addListener(event, async (receivedEvent) => {
156
- return hook.run(
157
- receivedEvent,
158
- resourceStoreElement.computedDependencies as DependencyValuesType<{}>
159
- );
160
- });
192
+ this.eventManager.addListener(
193
+ event,
194
+ async (receivedEvent) => {
195
+ return hook.run(
196
+ receivedEvent,
197
+ resourceStoreElement.computedDependencies as DependencyValuesType<{}>
198
+ );
199
+ },
200
+ {
201
+ order,
202
+ }
203
+ );
161
204
  }
162
205
  }
163
206
  }
164
207
 
165
208
  async extractDependencies<T extends DependencyMapType>(
166
- map: T
209
+ map: T,
210
+ source: string
167
211
  ): Promise<DependencyValuesType<T>> {
168
212
  const object = {} as DependencyValuesType<T>;
169
213
 
170
214
  for (const key in map) {
171
- object[key] = await this.extractDependency(map[key]);
215
+ object[key] = await this.extractDependency(map[key], source);
172
216
  }
173
217
 
174
218
  return object;
175
219
  }
176
220
 
177
- async extractDependency(object) {
221
+ async extractDependency(object, source: string) {
178
222
  if (utils.isResource(object)) {
179
223
  return this.extractResourceDependency(object);
180
224
  } else if (utils.isTask(object)) {
181
225
  return this.extractTaskDependency(object);
182
226
  } else if (utils.isEvent(object)) {
183
- return this.extractEventDependency(object);
227
+ return this.extractEventDependency(object, source);
184
228
  } else {
185
229
  throw Errors.unknownItemType(object);
186
230
  }
@@ -191,9 +235,17 @@ export class DependencyProcessor {
191
235
  * @param object
192
236
  * @returns
193
237
  */
194
- extractEventDependency(object: IEventDefinition<Record<string, any>>) {
238
+ extractEventDependency(
239
+ object: IEventDefinition<Record<string, any>>,
240
+ source: string
241
+ ) {
195
242
  return async (input) => {
196
- return this.eventManager.emit(object, input);
243
+ // runs it in background.
244
+ this.logger.debug({
245
+ message: `Event ${object.id} was emitted from ${source}`,
246
+ });
247
+
248
+ return this.eventManager.emit(object, input, source);
197
249
  };
198
250
  }
199
251
 
@@ -210,7 +262,8 @@ export class DependencyProcessor {
210
262
  const dependencies = object.dependencies as DependencyMapType;
211
263
 
212
264
  storeTask.computedDependencies = await this.extractDependencies(
213
- dependencies
265
+ dependencies,
266
+ storeTask.task.id
214
267
  );
215
268
  }
216
269
 
@@ -242,7 +295,10 @@ export class DependencyProcessor {
242
295
  storeResource.value = await this.resourceInitializer.initializeResource(
243
296
  resource,
244
297
  config,
245
- await this.extractDependencies(resource.dependencies || {})
298
+ await this.extractDependencies(
299
+ resource.dependencies || {},
300
+ resource.id
301
+ )
246
302
  );
247
303
  }
248
304
  }
@@ -1,5 +1,6 @@
1
1
  import { EventHandlerType, IEvent, IEventDefinition } from "../defs";
2
2
  import { Errors } from "../errors";
3
+ import { Logger } from "./Logger";
3
4
 
4
5
  const HandlerOptionsDefaults = { order: 0 };
5
6
 
@@ -54,9 +55,9 @@ export class EventManager {
54
55
 
55
56
  async emit<TInput>(
56
57
  eventDefinition: IEventDefinition<TInput>,
57
- ...args: TInput extends void ? [] : [TInput]
58
+ data: TInput,
59
+ source: string
58
60
  ): Promise<void> {
59
- const data = args[0];
60
61
  const eventListeners = this.listeners.get(eventDefinition.id) || [];
61
62
  const allListeners = this.mergeSortedListeners(
62
63
  eventListeners,
@@ -67,6 +68,7 @@ export class EventManager {
67
68
  id: eventDefinition.id,
68
69
  data,
69
70
  timestamp: new Date(),
71
+ source,
70
72
  };
71
73
 
72
74
  for (const listener of allListeners) {
@@ -11,13 +11,13 @@ export type LogLevels =
11
11
 
12
12
  export interface ILog {
13
13
  level: string;
14
- context?: string;
14
+ source?: string;
15
15
  data: any;
16
16
  timestamp: Date;
17
17
  }
18
18
 
19
19
  export class Logger {
20
- public static defaultContext = "app";
20
+ printThreshold: LogLevels | null = null;
21
21
 
22
22
  public severity = {
23
23
  trace: 0,
@@ -28,25 +28,45 @@ export class Logger {
28
28
  critical: 5,
29
29
  };
30
30
 
31
- constructor(private eventManager: EventManager) {}
31
+ constructor(protected eventManager: EventManager) {}
32
32
 
33
33
  /**
34
34
  * @param level
35
35
  * @param message
36
36
  */
37
- public async log(level: LogLevels, data: any): Promise<void> {
37
+ public async log(
38
+ level: LogLevels,
39
+ data: any,
40
+ source?: string
41
+ ): Promise<void> {
38
42
  const log: ILog = {
39
43
  level,
40
44
  data,
45
+ source: source,
41
46
  timestamp: new Date(),
42
47
  };
43
48
 
44
- await this.eventManager.emit(globalEvents.log, log);
49
+ if (
50
+ this.printThreshold &&
51
+ this.severity[level] >= this.severity[this.printThreshold]
52
+ ) {
53
+ this.print(log);
54
+ }
55
+
56
+ await this.eventManager.emit(globalEvents.log, log, source || "unknown");
57
+ }
58
+
59
+ /**
60
+ * Will print logs after that, use `null` to disable autoprinting.
61
+ * @param level
62
+ */
63
+ public setPrintThreshold(level: LogLevels | null) {
64
+ this.printThreshold = level;
45
65
  }
46
66
 
47
- public async print(log: ILog) {
67
+ public print(log: ILog) {
48
68
  // Extract the relevant information from the log
49
- const { level, context, data, timestamp } = log;
69
+ const { level, source: context, data, timestamp } = log;
50
70
 
51
71
  // Format the timestamp to a more readable format
52
72
  const formattedTimestamp = timestamp.toISOString();
@@ -74,27 +94,27 @@ export class Logger {
74
94
  console.log(logMessage);
75
95
  }
76
96
 
77
- public async info(data: any) {
78
- await this.log("info", data);
97
+ public async info(data: any, source?: string) {
98
+ await this.log("info", data, source);
79
99
  }
80
100
 
81
- public async error(data: any) {
82
- await this.log("error", data);
101
+ public async error(data: any, source?: string) {
102
+ await this.log("error", data, source);
83
103
  }
84
104
 
85
- public async warn(data: any) {
86
- await this.log("warn", data);
105
+ public async warn(data: any, source?: string) {
106
+ await this.log("warn", data, source);
87
107
  }
88
108
 
89
- public async debug(data: any) {
90
- await this.log("debug", data);
109
+ public async debug(data: any, source?: string) {
110
+ await this.log("debug", data, source);
91
111
  }
92
112
 
93
- public async trace(data: any) {
94
- await this.log("trace", data);
113
+ public async trace(data: any, source?: string) {
114
+ await this.log("trace", data, source);
95
115
  }
96
116
 
97
- public async critical(data: any) {
98
- await this.log("critical", data);
117
+ public async critical(data: any, source?: string) {
118
+ await this.log("critical", data, source);
99
119
  }
100
120
  }
@@ -7,11 +7,13 @@ import {
7
7
  import { EventManager } from "./EventManager";
8
8
  import { globalEvents } from "../globalEvents";
9
9
  import { MiddlewareStoreElementType, Store } from "./Store";
10
+ import { Logger } from "./Logger";
10
11
 
11
12
  export class ResourceInitializer {
12
13
  constructor(
13
14
  protected readonly store: Store,
14
- protected readonly eventManager: EventManager
15
+ protected readonly eventManager: EventManager,
16
+ protected readonly logger: Logger
15
17
  ) {}
16
18
 
17
19
  /**
@@ -27,14 +29,20 @@ export class ResourceInitializer {
27
29
  config: TConfig,
28
30
  dependencies: DependencyValuesType<TDeps>
29
31
  ): Promise<TValue | undefined> {
30
- // begin by dispatching the event of creating it.
31
- // then ensure the hooks are called
32
- // then ensure the middleware are called
33
- await this.eventManager.emit(globalEvents.resources.beforeInit, {
34
- config,
35
- resource,
36
- });
37
- await this.eventManager.emit(resource.events.beforeInit, { config });
32
+ await this.eventManager.emit(
33
+ globalEvents.resources.beforeInit,
34
+ {
35
+ config,
36
+ resource,
37
+ },
38
+ resource.id
39
+ );
40
+
41
+ await this.eventManager.emit(
42
+ resource.events.beforeInit,
43
+ { config },
44
+ resource.id
45
+ );
38
46
 
39
47
  let error, value;
40
48
  try {
@@ -42,15 +50,25 @@ export class ResourceInitializer {
42
50
  value = await this.initWithMiddleware(resource, config, dependencies);
43
51
  }
44
52
 
45
- await this.eventManager.emit(resource.events.afterInit, {
46
- config,
47
- value,
48
- });
49
- await this.eventManager.emit(globalEvents.resources.afterInit, {
50
- config,
51
- resource,
52
- value,
53
- });
53
+ await this.eventManager.emit(
54
+ resource.events.afterInit,
55
+ {
56
+ config,
57
+ value,
58
+ },
59
+ resource.id
60
+ );
61
+ await this.eventManager.emit(
62
+ globalEvents.resources.afterInit,
63
+ {
64
+ config,
65
+ resource,
66
+ value,
67
+ },
68
+ resource.id
69
+ );
70
+
71
+ this.logger.debug(`Resource ${resource.id} initialized`);
54
72
 
55
73
  return value;
56
74
  } catch (e) {
@@ -59,15 +77,23 @@ export class ResourceInitializer {
59
77
  const suppress = () => (isSuppressed = true);
60
78
 
61
79
  // If you want to rewthrow the error, this should be done inside the onError event.
62
- await this.eventManager.emit(resource.events.onError, {
63
- error,
64
- suppress,
65
- });
66
- await this.eventManager.emit(globalEvents.resources.onError, {
67
- error,
68
- resource,
69
- suppress,
70
- });
80
+ await this.eventManager.emit(
81
+ resource.events.onError,
82
+ {
83
+ error,
84
+ suppress,
85
+ },
86
+ resource.id
87
+ );
88
+ await this.eventManager.emit(
89
+ globalEvents.resources.onError,
90
+ {
91
+ error,
92
+ resource,
93
+ suppress,
94
+ },
95
+ resource.id
96
+ );
71
97
 
72
98
  if (!isSuppressed) throw e;
73
99
  }
@@ -17,6 +17,7 @@ import { Errors } from "../errors";
17
17
  import { globalResources } from "../globalResources";
18
18
  import { EventManager } from "./EventManager";
19
19
  import { TaskRunner } from "./TaskRunner";
20
+ import { Logger } from "./Logger";
20
21
 
21
22
  export type ResourceStoreElementType<
22
23
  C = any,
@@ -67,7 +68,10 @@ export class Store {
67
68
  #isLocked = false;
68
69
  #isInitialized = false;
69
70
 
70
- constructor(protected readonly eventManager: EventManager) {}
71
+ constructor(
72
+ protected readonly eventManager: EventManager,
73
+ protected readonly logger: Logger
74
+ ) {}
71
75
 
72
76
  get isLocked() {
73
77
  return this.#isLocked;
@@ -378,12 +382,22 @@ export class Store {
378
382
  });
379
383
  }
380
384
 
385
+ private middlewareAsMap(middleware: IMiddlewareDefinition[]) {
386
+ return middleware.reduce((acc, item) => {
387
+ acc[item.id] = item;
388
+ return acc;
389
+ }, {} as Record<string, IMiddlewareDefinition>);
390
+ }
391
+
381
392
  getDependentNodes(): IDependentNode[] {
382
393
  const depenedants: IDependentNode[] = [];
383
394
  for (const task of this.tasks.values()) {
384
395
  depenedants.push({
385
396
  id: task.task.id,
386
- dependencies: task.task.dependencies,
397
+ dependencies: {
398
+ ...task.task.dependencies,
399
+ ...this.middlewareAsMap(task.task.middleware),
400
+ },
387
401
  });
388
402
  }
389
403
  for (const middleware of this.middlewares.values()) {
@@ -395,7 +409,10 @@ export class Store {
395
409
  for (const resource of this.resources.values()) {
396
410
  depenedants.push({
397
411
  id: resource.resource.id,
398
- dependencies: resource.resource.dependencies || {},
412
+ dependencies: {
413
+ ...resource.resource.dependencies,
414
+ ...this.middlewareAsMap(resource.resource.middleware),
415
+ },
399
416
  });
400
417
  }
401
418
 
@@ -7,6 +7,7 @@ import {
7
7
  Store,
8
8
  TaskStoreElementType,
9
9
  } from "./Store";
10
+ import { Logger } from "./Logger";
10
11
 
11
12
  export class TaskRunner {
12
13
  protected readonly runnerStore = new Map<
@@ -16,7 +17,8 @@ export class TaskRunner {
16
17
 
17
18
  constructor(
18
19
  protected readonly store: Store,
19
- protected readonly eventManager: EventManager
20
+ protected readonly eventManager: EventManager,
21
+ protected readonly logger: Logger
20
22
  ) {}
21
23
 
22
24
  /**
@@ -51,23 +53,35 @@ export class TaskRunner {
51
53
  // begin by dispatching the event of creating it.
52
54
  // then ensure the hooks are called
53
55
  // then ensure the middleware are called
54
- await this.eventManager.emit(task.events.beforeRun, { input });
55
- await this.eventManager.emit(globalEvents.tasks.beforeRun, {
56
- task,
57
- input,
58
- });
56
+ await this.eventManager.emit(task.events.beforeRun, { input }, task.id);
57
+ await this.eventManager.emit(
58
+ globalEvents.tasks.beforeRun,
59
+ {
60
+ task,
61
+ input,
62
+ },
63
+ task.id
64
+ );
59
65
 
60
66
  let error;
61
67
  try {
62
68
  // craft the next function starting from the first next function
63
69
  const output = await runner(input);
64
70
 
65
- await this.eventManager.emit(task.events.afterRun, { input, output });
66
- await this.eventManager.emit(globalEvents.tasks.afterRun, {
67
- task,
68
- input,
69
- output,
70
- });
71
+ await this.eventManager.emit(
72
+ task.events.afterRun,
73
+ { input, output },
74
+ task.id
75
+ );
76
+ await this.eventManager.emit(
77
+ globalEvents.tasks.afterRun,
78
+ {
79
+ task,
80
+ input,
81
+ output,
82
+ },
83
+ task.id
84
+ );
71
85
 
72
86
  return output;
73
87
  } catch (e) {
@@ -76,12 +90,20 @@ export class TaskRunner {
76
90
  error = e;
77
91
 
78
92
  // If you want to rewthrow the error, this should be done inside the onError event.
79
- await this.eventManager.emit(task.events.onError, { error, suppress });
80
- await this.eventManager.emit(globalEvents.tasks.onError, {
81
- task,
82
- error,
83
- suppress,
84
- });
93
+ await this.eventManager.emit(
94
+ task.events.onError,
95
+ { error, suppress },
96
+ task.id
97
+ );
98
+ await this.eventManager.emit(
99
+ globalEvents.tasks.onError,
100
+ {
101
+ task,
102
+ error,
103
+ suppress,
104
+ },
105
+ task.id
106
+ );
85
107
 
86
108
  if (!isSuppressed) throw e;
87
109
  }
@@ -104,6 +126,11 @@ export class TaskRunner {
104
126
  ) {
105
127
  // this is the final next()
106
128
  let next = async (input) => {
129
+ this.logger.debug({
130
+ message: `Running task ${task.id}`,
131
+ input,
132
+ });
133
+
107
134
  return task.run.call(null, input, taskDependencies as any);
108
135
  };
109
136