@bluelibs/runner 1.5.4 → 2.1.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 (63) hide show
  1. package/README.md +299 -156
  2. package/dist/define.d.ts +1 -1
  3. package/dist/define.js +6 -1
  4. package/dist/define.js.map +1 -1
  5. package/dist/defs.d.ts +14 -8
  6. package/dist/defs.js +3 -1
  7. package/dist/defs.js.map +1 -1
  8. package/dist/globalEvents.js +45 -0
  9. package/dist/globalEvents.js.map +1 -1
  10. package/dist/globalResources.js +19 -0
  11. package/dist/globalResources.js.map +1 -1
  12. package/dist/models/DependencyProcessor.d.ts +1 -7
  13. package/dist/models/DependencyProcessor.js +31 -54
  14. package/dist/models/DependencyProcessor.js.map +1 -1
  15. package/dist/models/EventManager.d.ts +4 -0
  16. package/dist/models/EventManager.js.map +1 -1
  17. package/dist/models/ResourceInitializer.js +4 -2
  18. package/dist/models/ResourceInitializer.js.map +1 -1
  19. package/dist/models/Store.d.ts +2 -2
  20. package/dist/models/Store.js.map +1 -1
  21. package/dist/models/TaskRunner.js +28 -16
  22. package/dist/models/TaskRunner.js.map +1 -1
  23. package/dist/run.js +1 -1
  24. package/dist/run.js.map +1 -1
  25. package/dist/tools/getCallerFile.d.ts +1 -0
  26. package/dist/tools/getCallerFile.js +30 -0
  27. package/dist/tools/getCallerFile.js.map +1 -0
  28. package/package.json +1 -1
  29. package/src/__tests__/benchmark/benchmark.test.ts +9 -7
  30. package/src/__tests__/errors.test.ts +0 -13
  31. package/src/__tests__/globalEvents.test.ts +53 -28
  32. package/src/__tests__/index.ts +1 -1
  33. package/src/__tests__/models/EventManager.test.ts +1 -0
  34. package/src/__tests__/run.test.ts +140 -109
  35. package/src/__tests__/tools/getCallerFile.test.ts +51 -0
  36. package/src/__tests__/typesafety.test.ts +17 -16
  37. package/src/define.ts +10 -4
  38. package/src/defs.ts +38 -22
  39. package/src/globalEvents.ts +53 -0
  40. package/src/globalResources.ts +23 -0
  41. package/src/models/DependencyProcessor.ts +45 -80
  42. package/src/models/EventManager.ts +4 -0
  43. package/src/models/ResourceInitializer.ts +4 -2
  44. package/src/models/Store.ts +3 -2
  45. package/src/models/TaskRunner.ts +51 -28
  46. package/src/run.ts +1 -1
  47. package/src/tools/getCallerFile.ts +33 -0
  48. package/dist/DependencyProcessor.d.ts +0 -49
  49. package/dist/DependencyProcessor.js +0 -178
  50. package/dist/DependencyProcessor.js.map +0 -1
  51. package/dist/EventManager.d.ts +0 -17
  52. package/dist/EventManager.js +0 -73
  53. package/dist/EventManager.js.map +0 -1
  54. package/dist/ResourceInitializer.d.ts +0 -13
  55. package/dist/ResourceInitializer.js +0 -54
  56. package/dist/ResourceInitializer.js.map +0 -1
  57. package/dist/Store.d.ts +0 -90
  58. package/dist/Store.js +0 -291
  59. package/dist/Store.js.map +0 -1
  60. package/dist/TaskRunner.d.ts +0 -25
  61. package/dist/TaskRunner.js +0 -96
  62. package/dist/TaskRunner.js.map +0 -1
  63. package/src/__tests__/run.hooks.test.ts +0 -110
package/src/define.ts CHANGED
@@ -16,17 +16,21 @@ import {
16
16
  symbolEvent,
17
17
  } from "./defs";
18
18
  import { Errors } from "./errors";
19
+ import { getCallerFile } from "./tools/getCallerFile";
20
+
21
+ // Helper function to get the caller file
19
22
 
20
23
  export function defineTask<
21
24
  Input = undefined,
22
25
  Output extends Promise<any> = any,
23
26
  Deps extends DependencyMapType = any,
24
- Test = any
27
+ TOn extends "*" | IEventDefinition | undefined = undefined
25
28
  >(
26
- taskConfig: ITaskDefinition<Input, Output, Deps, Test>
27
- ): ITask<Input, Output, Deps, Test> {
29
+ taskConfig: ITaskDefinition<Input, Output, Deps, TOn>
30
+ ): ITask<Input, Output, Deps, TOn> {
28
31
  return {
29
32
  [symbols.task]: true,
33
+ [symbols.filePath]: getCallerFile(),
30
34
  id: taskConfig.id,
31
35
  dependencies: taskConfig.dependencies || ({} as Deps),
32
36
  middleware: taskConfig.middleware || [],
@@ -58,9 +62,9 @@ export function defineResource<
58
62
  ): IResource<TConfig, TValue, TDeps> {
59
63
  return {
60
64
  [symbols.resource]: true,
65
+ [symbols.filePath]: getCallerFile(),
61
66
  id: constConfig.id,
62
67
  dependencies: constConfig.dependencies,
63
- hooks: constConfig.hooks || [],
64
68
  dispose: constConfig.dispose,
65
69
  register: constConfig.register || [],
66
70
  overrides: constConfig.overrides || [],
@@ -94,6 +98,7 @@ export function defineEvent<TPayload = any>(
94
98
  config: IEventDefinitionConfig<TPayload>
95
99
  ): IEventDefinition<TPayload> {
96
100
  return {
101
+ [symbols.filePath]: getCallerFile(),
97
102
  [symbolEvent]: true,
98
103
  ...config,
99
104
  };
@@ -103,6 +108,7 @@ export function defineMiddleware<TDeps extends DependencyMapType = {}>(
103
108
  config: IMiddlewareDefinition<TDeps>
104
109
  ): IMiddleware<TDeps> {
105
110
  const object = {
111
+ [symbols.filePath]: getCallerFile(),
106
112
  [symbols.middleware]: true,
107
113
  ...config,
108
114
  dependencies: config.dependencies || ({} as TDeps),
package/src/defs.ts CHANGED
@@ -9,6 +9,8 @@ export const symbolMiddlewareGlobal: unique symbol = Symbol(
9
9
  "runner.middlewareGlobal"
10
10
  );
11
11
 
12
+ export const symbolFilePath: unique symbol = Symbol("runner.filePath");
13
+
12
14
  export const symbols = {
13
15
  task: symbolTask,
14
16
  resource: symbolResource,
@@ -16,6 +18,7 @@ export const symbols = {
16
18
  event: symbolEvent,
17
19
  middleware: symbolMiddleware,
18
20
  middlewareGlobal: symbolMiddlewareGlobal,
21
+ filePath: symbolFilePath,
19
22
  };
20
23
 
21
24
  export interface IMeta {
@@ -32,7 +35,7 @@ export interface IMiddlewareMeta extends IMeta {}
32
35
  // DependencyMap types
33
36
  export type DependencyMapType = Record<
34
37
  string,
35
- ITask<any, any, any> | IResource<any, any, any> | IEventDefinition<any>
38
+ ITask<any, any, any, any> | IResource<any, any, any> | IEventDefinition<any>
36
39
  >;
37
40
 
38
41
  // Helper Types for Extracting Generics
@@ -61,19 +64,39 @@ export type DependencyValuesType<T extends DependencyMapType> = {
61
64
  [K in keyof T]: DependencyValueType<T[K]>;
62
65
  };
63
66
 
67
+ type Optional<T> = {
68
+ [K in keyof T]?: T[K];
69
+ };
70
+
71
+ // Utility type to check if a type is void
72
+ type IsVoid<T> = [T] extends [void] ? true : false;
73
+
74
+ // Utility type to check if a type is optional (can be undefined)
75
+ type IsOptional<T> = undefined extends T ? true : false;
76
+
77
+ // IReso
78
+
79
+ // Conditional type to allow `void`, optional, or any type
80
+ type OptionalOrVoidOrAnything<T> = IsVoid<T> extends true
81
+ ? void
82
+ : IsOptional<T> extends true
83
+ ? Optional<T>
84
+ : T;
85
+
64
86
  // RegisterableItems Type with Conditional Inclusion
65
- export type RegisterableItems =
87
+ export type RegisterableItems<T = any> =
66
88
  | IResourceWithConfig<any>
67
89
  | IResource<void, any, any>
68
- | ITaskDefinition
69
- | IMiddlewareDefinition
70
- | IEventDefinition;
90
+ | IResource<OptionalOrVoidOrAnything<T>, any, any>
91
+ | ITaskDefinition<any, any, any, any>
92
+ | IMiddlewareDefinition<any>
93
+ | IEventDefinition<any>;
71
94
 
72
95
  export interface ITaskDefinition<
73
96
  TInput = any,
74
97
  TOutput extends Promise<any> = any,
75
98
  TDependencies extends DependencyMapType = {},
76
- TEventDefinitionInput = null
99
+ TOn extends "*" | IEventDefinition<any> | undefined = undefined // Adding a generic to track 'on' type
77
100
  > {
78
101
  id: string;
79
102
  dependencies?: TDependencies | (() => TDependencies);
@@ -81,7 +104,7 @@ export interface ITaskDefinition<
81
104
  /**
82
105
  * Listen to events in a simple way
83
106
  */
84
- on?: IEventDefinition<TEventDefinitionInput>;
107
+ on?: TOn;
85
108
  /**
86
109
  * This makes sense only when `on` is specified to provide the order of the execution.
87
110
  * The event with the lowest order will be executed first.
@@ -89,7 +112,12 @@ export interface ITaskDefinition<
89
112
  listenerOrder?: number;
90
113
  meta?: ITaskMeta;
91
114
  run: (
92
- input: TEventDefinitionInput extends null ? TInput : TEventDefinitionInput,
115
+ input: TOn extends undefined ? TInput : IEvent<ExtractEventParams<TOn>>,
116
+ // input: TOn extends "*"
117
+ // ? IEvent<any>
118
+ // : TEventDefinitionInput extends null | void
119
+ // ? TInput
120
+ // : IEvent<TEventDefinitionInput>,
93
121
  dependencies: DependencyValuesType<TDependencies>
94
122
  ) => TOutput;
95
123
  }
@@ -127,13 +155,8 @@ export interface ITask<
127
155
  TInput = any,
128
156
  TOutput extends Promise<any> = any,
129
157
  TDependencies extends DependencyMapType = {},
130
- TEventDefinitionInput = null
131
- > extends ITaskDefinition<
132
- TInput,
133
- TOutput,
134
- TDependencies,
135
- TEventDefinitionInput
136
- > {
158
+ TOn extends "*" | IEventDefinition<any> | undefined = undefined
159
+ > extends ITaskDefinition<TInput, TOutput, TDependencies, TOn> {
137
160
  dependencies: TDependencies | (() => TDependencies);
138
161
  computedDependencies?: DependencyValuesType<TDependencies>;
139
162
  middleware: IMiddlewareDefinition[];
@@ -156,9 +179,6 @@ export interface IResourceDefinition<
156
179
  > {
157
180
  id: string;
158
181
  dependencies?: TDependencies | ((config: TConfig) => TDependencies);
159
- hooks?:
160
- | IHookDefinition<TDependencies, THooks>[]
161
- | ((config: TConfig) => IHookDefinition<TDependencies, THooks>[]);
162
182
  register?:
163
183
  | Array<RegisterableItems>
164
184
  | ((config: TConfig) => Array<RegisterableItems>);
@@ -201,10 +221,6 @@ export interface IResource<
201
221
  afterInit: IEventDefinition<AfterInitEventPayload<TConfig, TValue>>;
202
222
  onError: IEventDefinition<OnErrorEventPayload>;
203
223
  };
204
- hooks:
205
- | IHookDefinition<TDependencies>[]
206
- | ((config: TConfig) => IHookDefinition<TDependencies>[]);
207
-
208
224
  overrides: Array<IResource | ITask | IMiddleware | IResourceWithConfig>;
209
225
  middleware: IMiddlewareDefinition[];
210
226
  }
@@ -5,12 +5,29 @@ import { ILog } from "./models/Logger";
5
5
  export const globalEvents = {
6
6
  beforeInit: defineEvent({
7
7
  id: "global.beforeInit",
8
+ meta: {
9
+ title: "Before Initialization",
10
+ description:
11
+ "Triggered before any resource or system-wide initialization occurs.",
12
+ tags: ["system"],
13
+ },
8
14
  }),
9
15
  afterInit: defineEvent({
10
16
  id: "global.afterInit",
17
+ meta: {
18
+ title: "After Initialization",
19
+ description:
20
+ "Fired after the system or resource initialization is completed.",
21
+ tags: ["system"],
22
+ },
11
23
  }),
12
24
  log: defineEvent<ILog>({
13
25
  id: "global.log",
26
+ meta: {
27
+ title: "Log Event",
28
+ description: "Used to log events and messages across the system.",
29
+ tags: ["system"],
30
+ },
14
31
  }),
15
32
  tasks: {
16
33
  beforeRun: defineEvent<{
@@ -18,6 +35,12 @@ export const globalEvents = {
18
35
  input: any;
19
36
  }>({
20
37
  id: "global.tasks.beforeRun",
38
+ meta: {
39
+ title: "Before Task Execution",
40
+ description:
41
+ "Triggered before a task starts running, providing access to the input data.",
42
+ tags: ["system"],
43
+ },
21
44
  }),
22
45
  afterRun: defineEvent<{
23
46
  task: ITask<any, any, any>;
@@ -25,6 +48,12 @@ export const globalEvents = {
25
48
  output: any;
26
49
  }>({
27
50
  id: "global.tasks.afterRun",
51
+ meta: {
52
+ title: "After Task Execution",
53
+ description:
54
+ "Fired after a task has completed, providing both the input and output data.",
55
+ tags: ["system"],
56
+ },
28
57
  }),
29
58
  onError: defineEvent<{
30
59
  error: any;
@@ -32,6 +61,12 @@ export const globalEvents = {
32
61
  task: ITask<any, any, any>;
33
62
  }>({
34
63
  id: "global.tasks.onError",
64
+ meta: {
65
+ title: "Task Error",
66
+ description:
67
+ "Triggered when an error occurs during task execution. Allows error suppression.",
68
+ tags: ["system"],
69
+ },
35
70
  }),
36
71
  },
37
72
  resources: {
@@ -40,6 +75,12 @@ export const globalEvents = {
40
75
  config: any;
41
76
  }>({
42
77
  id: "global.resources.beforeInit",
78
+ meta: {
79
+ title: "Before Resource Initialization",
80
+ description:
81
+ "Fired before a resource is initialized, with access to the configuration.",
82
+ tags: ["system"],
83
+ },
43
84
  }),
44
85
  afterInit: defineEvent<{
45
86
  resource: IResource<any, any, any>;
@@ -47,6 +88,12 @@ export const globalEvents = {
47
88
  value: any;
48
89
  }>({
49
90
  id: "global.resources.afterInit",
91
+ meta: {
92
+ title: "After Resource Initialization",
93
+ description:
94
+ "Fired after a resource has been initialized, providing the final value.",
95
+ tags: ["system"],
96
+ },
50
97
  }),
51
98
  onError: defineEvent<{
52
99
  error: Error;
@@ -54,6 +101,12 @@ export const globalEvents = {
54
101
  resource: IResource<any, any, any>;
55
102
  }>({
56
103
  id: "global.resources.onError",
104
+ meta: {
105
+ title: "Resource Error",
106
+ description:
107
+ "Triggered when an error occurs during resource initialization. Allows error suppression.",
108
+ tags: ["system"],
109
+ },
57
110
  }),
58
111
  },
59
112
  };
@@ -7,6 +7,12 @@ import { TaskRunner } from "./models/TaskRunner";
7
7
  const store = defineResource({
8
8
  id: "global.store",
9
9
  init: async (store: Store) => store,
10
+ meta: {
11
+ title: "Store",
12
+ description:
13
+ "A global store that can be used to store and retrieve tasks, resources, events and middleware",
14
+ tags: ["internal"],
15
+ },
10
16
  });
11
17
 
12
18
  export const globalResources = {
@@ -14,13 +20,30 @@ export const globalResources = {
14
20
  eventManager: defineResource({
15
21
  id: "global.eventManager",
16
22
  init: async (em: EventManager) => em,
23
+ meta: {
24
+ title: "Event Manager",
25
+ description:
26
+ "Manages all events and event listeners. This is meant to be used internally for most use-cases.",
27
+ tags: ["internal"],
28
+ },
17
29
  }),
18
30
  taskRunner: defineResource({
19
31
  id: "global.taskRunner",
20
32
  init: async (runner: TaskRunner) => runner,
33
+ meta: {
34
+ title: "Task Runner",
35
+ description:
36
+ "Manages the execution of tasks and task dependencies. This is meant to be used internally for most use-cases.",
37
+ tags: ["internal"],
38
+ },
21
39
  }),
22
40
  logger: defineResource({
23
41
  id: "global.logger",
24
42
  init: async (logger: Logger) => logger,
43
+ meta: {
44
+ title: "Logger",
45
+ description:
46
+ "Logs all events and errors. This is meant to be used internally for most use-cases. Emits a global.log event for each log.",
47
+ },
25
48
  }),
26
49
  };
@@ -5,6 +5,7 @@ import {
5
5
  IResource,
6
6
  IHookDefinition,
7
7
  IEventDefinition,
8
+ IEvent,
8
9
  } from "../defs";
9
10
  import { ResourceStoreElementType, Store, TaskStoreElementType } from "./Store";
10
11
  import * as utils from "../define";
@@ -68,32 +69,6 @@ export class DependencyProcessor {
68
69
  deps,
69
70
  task.task.id
70
71
  );
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
- }
97
72
  }
98
73
 
99
74
  // Most likely these are resources that no-one has dependencies towards
@@ -145,62 +120,49 @@ export class DependencyProcessor {
145
120
  /**
146
121
  * Processes all hooks, should run before emission of any event.
147
122
  */
148
- public attachHooks() {
149
- for (const resource of this.store.resources.values()) {
150
- if (resource.resource.hooks) {
151
- this.attachHooksToResource(resource);
152
- }
153
- }
154
- }
123
+ public attachListeners() {
124
+ for (const task of this.store.tasks.values()) {
125
+ if (task.task.on) {
126
+ let eventDefinition = task.task.on;
127
+
128
+ const handler = async (receivedEvent: IEvent<any>) => {
129
+ if (receivedEvent.source === task.task.id) {
130
+ // we don't want to trigger the same task that emitted the event
131
+ // process.exit(0);
132
+ return;
133
+ }
155
134
 
156
- /**
157
- * Processes the hooks for resources
158
- * @param hooks
159
- * @param deps
160
- */
161
- public attachHooksToResource(
162
- resourceStoreElement: ResourceStoreElementType<any, any, {}>
163
- ) {
164
- let hooks = resourceStoreElement.resource.hooks;
165
- if (typeof hooks === "function") {
166
- hooks = hooks(resourceStoreElement.config);
167
- }
135
+ this.logger.debug(
136
+ {
137
+ message:
138
+ eventDefinition === "*"
139
+ ? `Task ${task.task.id} being triggered by all events`
140
+ : `Task ${task.task.id} being triggered by event: ${eventDefinition.id}`,
168
141
 
169
- if (hooks.length === 0) {
170
- return;
171
- }
142
+ event: receivedEvent,
143
+ },
144
+ task.task.id
145
+ );
146
+
147
+ return this.taskRunner.run(
148
+ task.task,
149
+ receivedEvent,
150
+ task.computedDependencies
151
+ );
152
+ };
172
153
 
173
- for (const hook of hooks) {
174
- const event = hook.event;
175
- const order = hook.order || 0;
176
- if (event === "*") {
177
- this.eventManager.addGlobalListener(
178
- async (receivedEvent) => {
179
- return hook.run(
180
- receivedEvent,
181
- resourceStoreElement.computedDependencies as DependencyValuesType<{}>
182
- );
183
- },
184
- {
185
- order,
154
+ if (eventDefinition === "*") {
155
+ this.eventManager.addGlobalListener(handler, {
156
+ order: task.task.listenerOrder || 0,
157
+ });
158
+ } else {
159
+ if (this.store.events.get(eventDefinition.id) === undefined) {
160
+ throw Errors.eventNotFound(eventDefinition.id);
186
161
  }
187
- );
188
- } else {
189
- if (this.store.events.has(event.id) === false) {
190
- throw Errors.eventNotFound(event.id);
162
+ this.eventManager.addListener(eventDefinition, handler, {
163
+ order: task.task.listenerOrder || 0,
164
+ });
191
165
  }
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
- );
204
166
  }
205
167
  }
206
168
  }
@@ -241,9 +203,12 @@ export class DependencyProcessor {
241
203
  ) {
242
204
  return async (input) => {
243
205
  // runs it in background.
244
- this.logger.debug({
245
- message: `Event ${object.id} was emitted from ${source}`,
246
- });
206
+ this.logger.debug(
207
+ {
208
+ message: `Event ${object.id} was emitted from ${source}`,
209
+ },
210
+ source
211
+ );
247
212
 
248
213
  return this.eventManager.emit(object, input, source);
249
214
  };
@@ -13,6 +13,10 @@ interface IListenerStorage {
13
13
  export interface IEventHandlerOptions<T = any> {
14
14
  order?: number;
15
15
  filter?: (event: IEvent<T>) => boolean;
16
+ /**
17
+ * Represents the listener ID. Use this to avoid a listener calling himself.
18
+ */
19
+ id?: string;
16
20
  }
17
21
 
18
22
  export class EventManager {
@@ -68,13 +68,15 @@ export class ResourceInitializer {
68
68
  resource.id
69
69
  );
70
70
 
71
- this.logger.debug(`Resource ${resource.id} initialized`);
71
+ this.logger.debug(`Resource ${resource.id} initialized`, resource.id);
72
72
 
73
73
  return value;
74
74
  } catch (e) {
75
75
  error = e;
76
76
  let isSuppressed = false;
77
- const suppress = () => (isSuppressed = true);
77
+ function suppress() {
78
+ isSuppressed = true;
79
+ }
78
80
 
79
81
  // If you want to rewthrow the error, this should be done inside the onError event.
80
82
  await this.eventManager.emit(
@@ -34,9 +34,10 @@ export type ResourceStoreElementType<
34
34
  export type TaskStoreElementType<
35
35
  Input = any,
36
36
  Output extends Promise<any> = any,
37
- D extends DependencyMapType = any
37
+ D extends DependencyMapType = any,
38
+ TOn extends "*" | IEventDefinition | undefined = any
38
39
  > = {
39
- task: ITask<Input, Output, D>;
40
+ task: ITask<Input, Output, D, TOn>;
40
41
  computedDependencies: DependencyValuesType<D>;
41
42
  isInitialized: boolean;
42
43
  };
@@ -50,43 +50,63 @@ export class TaskRunner {
50
50
  this.runnerStore.set(task.id, runner);
51
51
  }
52
52
 
53
- // begin by dispatching the event of creating it.
54
- // then ensure the hooks are called
55
- // then ensure the middleware are called
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
- );
53
+ const isGlobalEventListener = task.on === "*";
65
54
 
66
- let error;
67
- try {
68
- // craft the next function starting from the first next function
69
- const output = await runner(input);
55
+ if (!isGlobalEventListener) {
56
+ await this.eventManager.emit(task.events.beforeRun, { input }, task.id);
57
+ }
70
58
 
59
+ if (
60
+ !isGlobalEventListener &&
61
+ task.on !== globalEvents.tasks.beforeRun &&
62
+ task.on !== globalEvents.tasks.afterRun
63
+ ) {
71
64
  await this.eventManager.emit(
72
- task.events.afterRun,
73
- { input, output },
74
- task.id
75
- );
76
- await this.eventManager.emit(
77
- globalEvents.tasks.afterRun,
65
+ globalEvents.tasks.beforeRun,
78
66
  {
79
67
  task,
80
68
  input,
81
- output,
82
69
  },
83
70
  task.id
84
71
  );
72
+ }
73
+
74
+ let error;
75
+ try {
76
+ // craft the next function starting from the first next function
77
+ const output = await runner(input);
78
+
79
+ if (!isGlobalEventListener) {
80
+ await this.eventManager.emit(
81
+ task.events.afterRun,
82
+ { input, output },
83
+ task.id
84
+ );
85
+ }
86
+
87
+ if (
88
+ !isGlobalEventListener &&
89
+ task.on !== globalEvents.tasks.beforeRun &&
90
+ task.on !== globalEvents.tasks.afterRun
91
+ ) {
92
+ await this.eventManager.emit(
93
+ globalEvents.tasks.afterRun,
94
+ {
95
+ task,
96
+ input,
97
+ output,
98
+ },
99
+ task.id
100
+ );
101
+ }
85
102
 
86
103
  return output;
87
104
  } catch (e) {
88
105
  let isSuppressed = false;
89
- const suppress = () => (isSuppressed = true);
106
+ function suppress() {
107
+ isSuppressed = true;
108
+ }
109
+
90
110
  error = e;
91
111
 
92
112
  // If you want to rewthrow the error, this should be done inside the onError event.
@@ -126,10 +146,13 @@ export class TaskRunner {
126
146
  ) {
127
147
  // this is the final next()
128
148
  let next = async (input) => {
129
- this.logger.debug({
130
- message: `Running task ${task.id}`,
131
- input,
132
- });
149
+ this.logger.debug(
150
+ {
151
+ message: `Running task ${task.id}`,
152
+ input,
153
+ },
154
+ task.id
155
+ );
133
156
 
134
157
  return task.run.call(null, input, taskDependencies as any);
135
158
  };
package/src/run.ts CHANGED
@@ -87,7 +87,7 @@ export async function run<C, V>(
87
87
 
88
88
  // a form of hooking, we create the events for all tasks and store them so they can be referenced
89
89
  await store.storeEventsForAllTasks();
90
- await processor.attachHooks();
90
+ await processor.attachListeners();
91
91
  await processor.computeAllDependencies();
92
92
 
93
93
  // After this stage, logger print policy could have been set.
@@ -0,0 +1,33 @@
1
+ export function getCallerFile(): string | undefined {
2
+ const originalFunc = Error.prepareStackTrace;
3
+
4
+ try {
5
+ const err = new Error();
6
+ let callerfile;
7
+ let currentfile;
8
+
9
+ // Safeguard prepareStackTrace
10
+ Error.prepareStackTrace = (err, stack) => stack;
11
+
12
+ const stack = err.stack as unknown as NodeJS.CallSite[];
13
+
14
+ // Don't know how to test this.
15
+ // if (stack.length < 3) {
16
+ // // We need at least 3 frames: current function, its caller, and one above
17
+ // return undefined;
18
+ // }
19
+
20
+ // Remove the first frame (getCallerFile itself)
21
+ stack.shift();
22
+
23
+ // Remove the second frame (the direct caller of getCallerFile)
24
+ currentfile = stack.shift()?.getFileName();
25
+
26
+ // The third frame (the caller above the immediate one)
27
+ callerfile = stack.shift()?.getFileName();
28
+
29
+ return callerfile; // Return the file name of the caller above
30
+ } finally {
31
+ Error.prepareStackTrace = originalFunc;
32
+ }
33
+ }