@bluelibs/runner 1.2.0 → 1.4.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 (54) hide show
  1. package/README.md +310 -178
  2. package/dist/define.d.ts +2 -2
  3. package/dist/define.js +12 -9
  4. package/dist/define.js.map +1 -1
  5. package/dist/defs.d.ts +45 -12
  6. package/dist/examples/express-mongo/index.d.ts +0 -0
  7. package/dist/examples/express-mongo/index.js +3 -0
  8. package/dist/examples/express-mongo/index.js.map +1 -0
  9. package/dist/globalEvents.d.ts +3 -1
  10. package/dist/globalEvents.js +1 -0
  11. package/dist/globalEvents.js.map +1 -1
  12. package/dist/index.d.ts +3 -1
  13. package/dist/models/DependencyProcessor.d.ts +4 -2
  14. package/dist/models/DependencyProcessor.js +45 -20
  15. package/dist/models/DependencyProcessor.js.map +1 -1
  16. package/dist/models/EventManager.d.ts +2 -1
  17. package/dist/models/EventManager.js +47 -21
  18. package/dist/models/EventManager.js.map +1 -1
  19. package/dist/models/Logger.d.ts +15 -10
  20. package/dist/models/Logger.js +27 -15
  21. package/dist/models/Logger.js.map +1 -1
  22. package/dist/models/ResourceInitializer.d.ts +4 -1
  23. package/dist/models/ResourceInitializer.js +39 -7
  24. package/dist/models/ResourceInitializer.js.map +1 -1
  25. package/dist/models/Store.d.ts +5 -1
  26. package/dist/models/Store.js +27 -3
  27. package/dist/models/Store.js.map +1 -1
  28. package/dist/models/TaskRunner.d.ts +3 -1
  29. package/dist/models/TaskRunner.js +13 -3
  30. package/dist/models/TaskRunner.js.map +1 -1
  31. package/dist/run.d.ts +0 -8
  32. package/dist/run.js +8 -6
  33. package/dist/run.js.map +1 -1
  34. package/package.json +1 -1
  35. package/src/__tests__/index.ts +2 -0
  36. package/src/__tests__/models/EventManager.test.ts +338 -67
  37. package/src/__tests__/models/Logger.test.ts +44 -1
  38. package/src/__tests__/models/ResourceInitializer.test.ts +6 -4
  39. package/src/__tests__/models/Store.test.ts +4 -2
  40. package/src/__tests__/models/TaskRunner.test.ts +9 -4
  41. package/src/__tests__/run.middleware.test.ts +249 -0
  42. package/src/__tests__/run.test.ts +112 -131
  43. package/src/__tests__/typesafety.test.ts +127 -0
  44. package/src/define.ts +15 -11
  45. package/src/defs.ts +63 -21
  46. package/src/examples/express-mongo/index.ts +1 -0
  47. package/src/globalEvents.ts +5 -2
  48. package/src/models/DependencyProcessor.ts +77 -33
  49. package/src/models/EventManager.ts +55 -25
  50. package/src/models/Logger.ts +36 -16
  51. package/src/models/ResourceInitializer.ts +54 -8
  52. package/src/models/Store.ts +34 -3
  53. package/src/models/TaskRunner.ts +13 -3
  54. package/src/run.ts +16 -13
@@ -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;
@@ -118,6 +122,8 @@ export class Store {
118
122
  this.computeRegistrationDeeply(root, config);
119
123
  this.resources.set(root.id, this.root);
120
124
 
125
+ this.runSanityChecks();
126
+
121
127
  for (const resource of this.resources.values()) {
122
128
  this.storeOverridesDeeply(resource.resource);
123
129
  }
@@ -125,6 +131,18 @@ export class Store {
125
131
  this.#isInitialized = true;
126
132
  }
127
133
 
134
+ private runSanityChecks() {
135
+ for (const task of this.tasks.values()) {
136
+ task.task.middleware.forEach((middleware) => {
137
+ if (!this.middlewares.has(middleware.id)) {
138
+ throw Errors.dependencyNotFound(
139
+ `Middleware ${middleware.id} in Task ${task.task.id}`
140
+ );
141
+ }
142
+ });
143
+ }
144
+ }
145
+
128
146
  /**
129
147
  * Beginning with the root, we perform registering to the container all the resources, tasks, middleware and events.
130
148
  * @param element
@@ -364,12 +382,22 @@ export class Store {
364
382
  });
365
383
  }
366
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
+
367
392
  getDependentNodes(): IDependentNode[] {
368
393
  const depenedants: IDependentNode[] = [];
369
394
  for (const task of this.tasks.values()) {
370
395
  depenedants.push({
371
396
  id: task.task.id,
372
- dependencies: task.task.dependencies,
397
+ dependencies: {
398
+ ...task.task.dependencies,
399
+ ...this.middlewareAsMap(task.task.middleware),
400
+ },
373
401
  });
374
402
  }
375
403
  for (const middleware of this.middlewares.values()) {
@@ -381,7 +409,10 @@ export class Store {
381
409
  for (const resource of this.resources.values()) {
382
410
  depenedants.push({
383
411
  id: resource.resource.id,
384
- dependencies: resource.resource.dependencies || {},
412
+ dependencies: {
413
+ ...resource.resource.dependencies,
414
+ ...this.middlewareAsMap(resource.resource.middleware),
415
+ },
385
416
  });
386
417
  }
387
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
  /**
@@ -71,16 +73,19 @@ export class TaskRunner {
71
73
 
72
74
  return output;
73
75
  } catch (e) {
76
+ let isSuppressed = false;
77
+ const suppress = () => (isSuppressed = true);
74
78
  error = e;
75
79
 
76
80
  // If you want to rewthrow the error, this should be done inside the onError event.
77
- await this.eventManager.emit(task.events.onError, { error });
81
+ await this.eventManager.emit(task.events.onError, { error, suppress });
78
82
  await this.eventManager.emit(globalEvents.tasks.onError, {
79
83
  task,
80
84
  error,
85
+ suppress,
81
86
  });
82
87
 
83
- throw e;
88
+ if (!isSuppressed) throw e;
84
89
  }
85
90
  }
86
91
 
@@ -101,6 +106,11 @@ export class TaskRunner {
101
106
  ) {
102
107
  // this is the final next()
103
108
  let next = async (input) => {
109
+ this.logger.debug({
110
+ message: `Running task ${task.id}`,
111
+ input,
112
+ });
113
+
104
114
  return task.run.call(null, input, taskDependencies as any);
105
115
  };
106
116
 
package/src/run.ts CHANGED
@@ -52,22 +52,24 @@ export type RunnerState = {
52
52
  middleware: Record<string, MiddlewareStoreElementType>;
53
53
  };
54
54
 
55
- export type RunnerType = {
56
- store: Store;
57
- eventManager: EventManager;
58
- taskRunner: TaskRunner;
59
- };
60
-
61
55
  export async function run<C, V>(
62
56
  resource: IResource<C, V>,
63
57
  config?: C
64
58
  ): Promise<V> {
65
59
  const eventManager = new EventManager();
66
- const store = new Store(eventManager);
67
- const taskRunner = new TaskRunner(store, eventManager);
68
- const processor = new DependencyProcessor(store, eventManager, taskRunner);
60
+
61
+ // ensure for logger, that it can be used only after: computeAllDependencies() has executed
69
62
  const logger = new Logger(eventManager);
70
63
 
64
+ const store = new Store(eventManager, logger);
65
+ const taskRunner = new TaskRunner(store, eventManager, logger);
66
+ const processor = new DependencyProcessor(
67
+ store,
68
+ eventManager,
69
+ taskRunner,
70
+ logger
71
+ );
72
+
71
73
  // In the registration phase we register deeply all the resources, tasks, middleware and events
72
74
  store.initializeStore(resource, config);
73
75
  store.storeGenericItem(globalResources.logger.with(logger));
@@ -80,24 +82,25 @@ export async function run<C, V>(
80
82
  throw Errors.circularDependencies(circularDependencies.cycles);
81
83
  }
82
84
 
85
+ // the overrides that were registered now will override the other registered resources
83
86
  await store.processOverrides();
84
87
 
85
- // a form of hooking, we store the events for all tasks
88
+ // a form of hooking, we create the events for all tasks and store them so they can be referenced
86
89
  await store.storeEventsForAllTasks();
87
90
  await processor.attachHooks();
88
91
  await processor.computeAllDependencies();
89
92
 
93
+ await logger.debug("All elements have been initalized..");
94
+
90
95
  // Now we can safely compute dependencies without being afraid of an infinite loop.
91
96
  // The hooking part is done here.
92
97
  await eventManager.emit(globalEvents.beforeInit);
93
98
 
94
- // leftovers that were registered but not depended upon, except root
95
- await processor.initializeUninitializedResources();
96
-
97
99
  // Now we can initialise the root resource
98
100
  await processor.initializeRoot();
99
101
 
100
102
  await eventManager.emit(globalEvents.afterInit);
103
+ await logger.debug("System initialized and operational.");
101
104
 
102
105
  // disallow manipulation or attaching more
103
106
  store.lock();