@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/dist/run.js CHANGED
@@ -31,7 +31,7 @@ async function run(resource, config) {
31
31
  await store.processOverrides();
32
32
  // a form of hooking, we create the events for all tasks and store them so they can be referenced
33
33
  await store.storeEventsForAllTasks();
34
- await processor.attachHooks();
34
+ await processor.attachListeners();
35
35
  await processor.computeAllDependencies();
36
36
  // After this stage, logger print policy could have been set.
37
37
  await logger.debug("All elements have been initalized..");
package/dist/run.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"run.js","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":";;AAsDA,kBAuDC;AA7GD,oDAAiD;AAUjD,sEAAmE;AACnE,wDAAqD;AACrD,iDAA8C;AAC9C,0CAAuC;AACvC,+EAA4E;AAC5E,qCAAkC;AAClC,uDAAoD;AACpD,4CAAyC;AAqClC,KAAK,UAAU,GAAG,CACvB,QAAyB,EACzB,MAAU;IAEV,MAAM,YAAY,GAAG,IAAI,2BAAY,EAAE,CAAC;IAExC,2FAA2F;IAC3F,MAAM,MAAM,GAAG,IAAI,eAAM,CAAC,YAAY,CAAC,CAAC;IAExC,MAAM,KAAK,GAAG,IAAI,aAAK,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IAC9C,MAAM,UAAU,GAAG,IAAI,uBAAU,CAAC,KAAK,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC;IAC/D,MAAM,SAAS,GAAG,IAAI,yCAAmB,CACvC,KAAK,EACL,YAAY,EACZ,UAAU,EACV,MAAM,CACP,CAAC;IAEF,+FAA+F;IAC/F,KAAK,CAAC,eAAe,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACxC,KAAK,CAAC,gBAAgB,CAAC,iCAAe,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IAC5D,KAAK,CAAC,gBAAgB,CAAC,iCAAe,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;IAEpE,kGAAkG;IAClG,MAAM,cAAc,GAAG,KAAK,CAAC,iBAAiB,EAAE,CAAC;IACjD,MAAM,oBAAoB,GAAG,IAAA,mDAAwB,EAAC,cAAc,CAAC,CAAC;IACtE,IAAI,oBAAoB,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3C,MAAM,eAAM,CAAC,oBAAoB,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC;IACjE,CAAC;IAED,sFAAsF;IACtF,MAAM,KAAK,CAAC,gBAAgB,EAAE,CAAC;IAE/B,iGAAiG;IACjG,MAAM,KAAK,CAAC,sBAAsB,EAAE,CAAC;IACrC,MAAM,SAAS,CAAC,WAAW,EAAE,CAAC;IAC9B,MAAM,SAAS,CAAC,sBAAsB,EAAE,CAAC;IAEzC,6DAA6D;IAC7D,MAAM,MAAM,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC;IAE1D,mFAAmF;IACnF,iCAAiC;IACjC,MAAM,YAAY,CAAC,IAAI,CAAC,2BAAY,CAAC,UAAU,EAAE,IAAI,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;IAEpE,0CAA0C;IAC1C,MAAM,SAAS,CAAC,cAAc,EAAE,CAAC;IAEjC,MAAM,YAAY,CAAC,IAAI,CAAC,2BAAY,CAAC,SAAS,EAAE,IAAI,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;IACnE,MAAM,MAAM,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC;IAE1D,0CAA0C;IAC1C,KAAK,CAAC,IAAI,EAAE,CAAC;IAEb,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;AAC1B,CAAC"}
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":";;AAsDA,kBAuDC;AA7GD,oDAAiD;AAUjD,sEAAmE;AACnE,wDAAqD;AACrD,iDAA8C;AAC9C,0CAAuC;AACvC,+EAA4E;AAC5E,qCAAkC;AAClC,uDAAoD;AACpD,4CAAyC;AAqClC,KAAK,UAAU,GAAG,CACvB,QAAyB,EACzB,MAAU;IAEV,MAAM,YAAY,GAAG,IAAI,2BAAY,EAAE,CAAC;IAExC,2FAA2F;IAC3F,MAAM,MAAM,GAAG,IAAI,eAAM,CAAC,YAAY,CAAC,CAAC;IAExC,MAAM,KAAK,GAAG,IAAI,aAAK,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IAC9C,MAAM,UAAU,GAAG,IAAI,uBAAU,CAAC,KAAK,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC;IAC/D,MAAM,SAAS,GAAG,IAAI,yCAAmB,CACvC,KAAK,EACL,YAAY,EACZ,UAAU,EACV,MAAM,CACP,CAAC;IAEF,+FAA+F;IAC/F,KAAK,CAAC,eAAe,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACxC,KAAK,CAAC,gBAAgB,CAAC,iCAAe,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IAC5D,KAAK,CAAC,gBAAgB,CAAC,iCAAe,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;IAEpE,kGAAkG;IAClG,MAAM,cAAc,GAAG,KAAK,CAAC,iBAAiB,EAAE,CAAC;IACjD,MAAM,oBAAoB,GAAG,IAAA,mDAAwB,EAAC,cAAc,CAAC,CAAC;IACtE,IAAI,oBAAoB,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3C,MAAM,eAAM,CAAC,oBAAoB,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC;IACjE,CAAC;IAED,sFAAsF;IACtF,MAAM,KAAK,CAAC,gBAAgB,EAAE,CAAC;IAE/B,iGAAiG;IACjG,MAAM,KAAK,CAAC,sBAAsB,EAAE,CAAC;IACrC,MAAM,SAAS,CAAC,eAAe,EAAE,CAAC;IAClC,MAAM,SAAS,CAAC,sBAAsB,EAAE,CAAC;IAEzC,6DAA6D;IAC7D,MAAM,MAAM,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC;IAE1D,mFAAmF;IACnF,iCAAiC;IACjC,MAAM,YAAY,CAAC,IAAI,CAAC,2BAAY,CAAC,UAAU,EAAE,IAAI,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;IAEpE,0CAA0C;IAC1C,MAAM,SAAS,CAAC,cAAc,EAAE,CAAC;IAEjC,MAAM,YAAY,CAAC,IAAI,CAAC,2BAAY,CAAC,SAAS,EAAE,IAAI,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;IACnE,MAAM,MAAM,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC;IAE1D,0CAA0C;IAC1C,KAAK,CAAC,IAAI,EAAE,CAAC;IAEb,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;AAC1B,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function getCallerFile(): string | undefined;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getCallerFile = getCallerFile;
4
+ function getCallerFile() {
5
+ const originalFunc = Error.prepareStackTrace;
6
+ try {
7
+ const err = new Error();
8
+ let callerfile;
9
+ let currentfile;
10
+ // Safeguard prepareStackTrace
11
+ Error.prepareStackTrace = (err, stack) => stack;
12
+ const stack = err.stack;
13
+ // Don't know how to test this.
14
+ // if (stack.length < 3) {
15
+ // // We need at least 3 frames: current function, its caller, and one above
16
+ // return undefined;
17
+ // }
18
+ // Remove the first frame (getCallerFile itself)
19
+ stack.shift();
20
+ // Remove the second frame (the direct caller of getCallerFile)
21
+ currentfile = stack.shift()?.getFileName();
22
+ // The third frame (the caller above the immediate one)
23
+ callerfile = stack.shift()?.getFileName();
24
+ return callerfile; // Return the file name of the caller above
25
+ }
26
+ finally {
27
+ Error.prepareStackTrace = originalFunc;
28
+ }
29
+ }
30
+ //# sourceMappingURL=getCallerFile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getCallerFile.js","sourceRoot":"","sources":["../../src/tools/getCallerFile.ts"],"names":[],"mappings":";;AAAA,sCAgCC;AAhCD,SAAgB,aAAa;IAC3B,MAAM,YAAY,GAAG,KAAK,CAAC,iBAAiB,CAAC;IAE7C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,KAAK,EAAE,CAAC;QACxB,IAAI,UAAU,CAAC;QACf,IAAI,WAAW,CAAC;QAEhB,8BAA8B;QAC9B,KAAK,CAAC,iBAAiB,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC;QAEhD,MAAM,KAAK,GAAG,GAAG,CAAC,KAAqC,CAAC;QAExD,+BAA+B;QAC/B,0BAA0B;QAC1B,8EAA8E;QAC9E,sBAAsB;QACtB,IAAI;QAEJ,gDAAgD;QAChD,KAAK,CAAC,KAAK,EAAE,CAAC;QAEd,+DAA+D;QAC/D,WAAW,GAAG,KAAK,CAAC,KAAK,EAAE,EAAE,WAAW,EAAE,CAAC;QAE3C,uDAAuD;QACvD,UAAU,GAAG,KAAK,CAAC,KAAK,EAAE,EAAE,WAAW,EAAE,CAAC;QAE1C,OAAO,UAAU,CAAC,CAAC,2CAA2C;IAChE,CAAC;YAAS,CAAC;QACT,KAAK,CAAC,iBAAiB,GAAG,YAAY,CAAC;IACzC,CAAC;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bluelibs/runner",
3
- "version": "1.5.4",
3
+ "version": "2.1.0",
4
4
  "description": "BlueLibs Runner",
5
5
  "main": "dist/index.js",
6
6
  "repository": {
@@ -78,16 +78,18 @@ describe("Benchmarks", () => {
78
78
  const testEvent = defineEvent<{ message: string }>({ id: "test.event" });
79
79
  const eventHandler = jest.fn();
80
80
 
81
+ const handlerTask = defineTask({
82
+ id: "handler.task",
83
+ on: testEvent,
84
+ run: async ({ data }) => {
85
+ eventHandler(data.message);
86
+ },
87
+ });
88
+
81
89
  const app = defineResource({
82
90
  id: "app",
83
- register: [testEvent],
91
+ register: [testEvent, handlerTask],
84
92
  dependencies: { testEvent },
85
- hooks: [
86
- {
87
- event: testEvent,
88
- run: eventHandler,
89
- },
90
- ],
91
93
  async init(_, { testEvent }) {
92
94
  await testEvent({ message: "Event emitted" });
93
95
  },
@@ -191,19 +191,6 @@ describe("Errors", () => {
191
191
  );
192
192
  });
193
193
 
194
- it("should throw an error if a hook tries to use a non-reigstered event", async () => {
195
- const hook = { event: { id: "non.existent.event" } as any, run: () => {} };
196
-
197
- const app = defineResource({
198
- id: "app",
199
- hooks: [hook],
200
- });
201
-
202
- await expect(run(app)).rejects.toThrow(
203
- Errors.eventNotFound("non.existent.event").message
204
- );
205
- });
206
-
207
194
  it("should throw an error when a task depends on a non-registered task", async () => {
208
195
  const offTheGrid = defineTask({
209
196
  id: "test.off.the.grid",
@@ -23,30 +23,55 @@ describe("Global Events", () => {
23
23
  },
24
24
  });
25
25
 
26
+ const taskBeforeInit = defineTask({
27
+ id: "task.beforeInit",
28
+ on: globalEvents.beforeInit,
29
+ run: globalBeforeInitHandler,
30
+ });
31
+
32
+ const taskAfterInit = defineTask({
33
+ id: "task.afterInit",
34
+ on: globalEvents.afterInit,
35
+ run: globalAfterInitHandler,
36
+ });
37
+
38
+ const taskBeforeRun = defineTask({
39
+ id: "task.beforeRun",
40
+ on: globalEvents.tasks.beforeRun,
41
+ run: globalTaskBeforeRunHandler,
42
+ });
43
+
44
+ const taskAfterRun = defineTask({
45
+ id: "task.afterRun",
46
+ on: globalEvents.tasks.afterRun,
47
+ run: globalTaskAfterRunHandler,
48
+ });
49
+
50
+ const resourceBeforeInit = defineTask({
51
+ id: "resource.beforeInit",
52
+ on: globalEvents.resources.beforeInit,
53
+ run: globalResourceBeforeInitHandler,
54
+ });
55
+
56
+ const resourceAfterInit = defineTask({
57
+ id: "resource.afterInit",
58
+ on: globalEvents.resources.afterInit,
59
+ run: globalResourceAfterInitHandler,
60
+ });
61
+
26
62
  const app = defineResource({
27
63
  id: "app",
28
- register: [testResource, testTask],
29
- dependencies: { testResource, testTask },
30
- hooks: [
31
- { event: globalEvents.beforeInit, run: globalBeforeInitHandler },
32
- { event: globalEvents.afterInit, run: globalAfterInitHandler },
33
- {
34
- event: globalEvents.tasks.beforeRun,
35
- run: globalTaskBeforeRunHandler,
36
- },
37
- {
38
- event: globalEvents.tasks.afterRun,
39
- run: globalTaskAfterRunHandler,
40
- },
41
- {
42
- event: globalEvents.resources.beforeInit,
43
- run: globalResourceBeforeInitHandler,
44
- },
45
- {
46
- event: globalEvents.resources.afterInit,
47
- run: globalResourceAfterInitHandler,
48
- },
64
+ register: [
65
+ testResource,
66
+ testTask,
67
+ taskBeforeInit,
68
+ taskAfterInit,
69
+ taskBeforeRun,
70
+ taskAfterRun,
71
+ resourceBeforeInit,
72
+ resourceAfterInit,
49
73
  ],
74
+ dependencies: { testResource, testTask },
50
75
  async init(_, { testResource, testTask }) {
51
76
  expect(testResource).toBe("Resource Value");
52
77
  const response = await testTask();
@@ -73,16 +98,16 @@ describe("Global Events", () => {
73
98
  },
74
99
  });
75
100
 
101
+ const onErrorHandler = defineTask({
102
+ id: "on.error.handler",
103
+ on: globalEvents.tasks.onError,
104
+ run: globalTaskOnErrorHandler,
105
+ });
106
+
76
107
  const app = defineResource({
77
108
  id: "app",
78
- register: [errorTask],
109
+ register: [errorTask, onErrorHandler],
79
110
  dependencies: { errorTask },
80
- hooks: [
81
- {
82
- event: globalEvents.tasks.onError,
83
- run: globalTaskOnErrorHandler,
84
- },
85
- ],
86
111
  async init(_, { errorTask }) {
87
112
  try {
88
113
  await errorTask();
@@ -5,9 +5,9 @@ import "./models/Store.test";
5
5
  import "./models/Logger.test";
6
6
 
7
7
  import "./tools/findCircularDependencies.test";
8
+ import "./tools/getCallerFile.test";
8
9
 
9
10
  import "./run.test";
10
- import "./run.hooks.test";
11
11
  import "./run.overrides.test";
12
12
  import "./run.middleware.test";
13
13
  import "./globalEvents.test";
@@ -22,6 +22,7 @@ describe("EventManager", () => {
22
22
  expect.objectContaining({
23
23
  id: "testEvent",
24
24
  data: "testData",
25
+ timestamp: expect.any(Date),
25
26
  })
26
27
  );
27
28
  });
@@ -72,15 +72,15 @@ describe("run", () => {
72
72
  },
73
73
  });
74
74
 
75
+ const handlerTask = defineTask({
76
+ id: "handler.task",
77
+ on: testEvent,
78
+ run: eventHandler,
79
+ });
80
+
75
81
  const app = defineResource({
76
82
  id: "app",
77
- register: [testEvent, testTask],
78
- hooks: [
79
- {
80
- event: testEvent,
81
- run: eventHandler,
82
- },
83
- ],
83
+ register: [testEvent, testTask, handlerTask],
84
84
  dependencies: { testTask },
85
85
  async init(_, { testTask }) {
86
86
  await testTask();
@@ -101,15 +101,28 @@ describe("run", () => {
101
101
  run: async () => "Task executed",
102
102
  });
103
103
 
104
+ const onBeforeRun = defineTask({
105
+ id: "on.before.run",
106
+ on: testTask.events.beforeRun,
107
+ run: beforeRunHandler,
108
+ });
109
+
110
+ const onAfterRun = defineTask({
111
+ id: "on.after.run",
112
+ on: testTask.events.afterRun,
113
+ run: afterRunHandler,
114
+ });
115
+
116
+ const onError = defineTask({
117
+ id: "on.error",
118
+ on: testTask.events.onError,
119
+ run: onErrorHandler,
120
+ });
121
+
104
122
  const app = defineResource({
105
123
  id: "app",
106
- register: [testTask],
124
+ register: [testTask, onBeforeRun, onAfterRun, onError],
107
125
  dependencies: { testTask },
108
- hooks: [
109
- { event: testTask.events.beforeRun, run: beforeRunHandler },
110
- { event: testTask.events.afterRun, run: afterRunHandler },
111
- { event: testTask.events.onError, run: onErrorHandler },
112
- ],
113
126
  async init(_, { testTask }) {
114
127
  await testTask();
115
128
  expect(beforeRunHandler).toHaveBeenCalled();
@@ -132,56 +145,23 @@ describe("run", () => {
132
145
  let value = false;
133
146
  const errorHook = jest.fn();
134
147
 
135
- const app = defineResource({
136
- id: "app",
137
- register: [testTask],
138
- dependencies: { testTask },
139
- hooks: [
140
- {
141
- event: testTask.events.onError,
142
- run: errorHook,
143
- },
144
- ],
145
- async init(_, { testTask }) {
146
- await testTask();
147
- },
148
- });
149
-
150
- await expect(run(app)).rejects.toThrow("Task failed");
151
- expect(errorHook).toHaveBeenCalled();
152
- });
153
-
154
- it("should allow suppression of an error", async () => {
155
- const supressMock = jest.fn();
156
- const testTask = defineTask({
157
- id: "test.task",
158
- run: async () => {
159
- throw new Error("Task failed");
160
- },
148
+ const handler = defineTask({
149
+ id: "handler",
150
+ on: testTask.events.onError,
151
+ run: errorHook,
161
152
  });
162
153
 
163
154
  const app = defineResource({
164
155
  id: "app",
165
- register: [testTask],
156
+ register: [testTask, handler],
166
157
  dependencies: { testTask },
167
- hooks: [
168
- {
169
- event: testTask.events.onError,
170
- run: async (event, deps) => {
171
- supressMock();
172
- event.data.suppress();
173
- },
174
- },
175
- ],
176
158
  async init(_, { testTask }) {
177
159
  await testTask();
178
-
179
- return "ok";
180
160
  },
181
161
  });
182
162
 
183
- await expect(run(app)).resolves.toBe("ok");
184
- expect(supressMock).toHaveBeenCalled();
163
+ await expect(run(app)).rejects.toThrow("Task failed");
164
+ expect(errorHook).toHaveBeenCalled();
185
165
  });
186
166
 
187
167
  it("should be able to register an task with middleware and execute it, ensuring the middleware is called in the correct order", async () => {
@@ -307,58 +287,86 @@ describe("run", () => {
307
287
 
308
288
  await expect(run(app)).rejects.toThrow(/Circular dependencies detected/);
309
289
  });
310
- });
311
290
 
312
- it("should be able to listen to an event through the 'on' property", async () => {
313
- const testEvent = defineEvent<{ message: string }>({ id: "test.event" });
314
- const eventHandler = jest.fn();
291
+ it("should be able to listen to an event through the 'on' property", async () => {
292
+ const testEvent = defineEvent<{ message: string }>({ id: "test.event" });
293
+ const eventHandler = jest.fn();
315
294
 
316
- const task = defineTask({
317
- id: "app",
318
- on: testEvent,
319
- async run(event) {
320
- eventHandler();
321
- },
322
- });
295
+ const task = defineTask({
296
+ id: "app",
297
+ on: testEvent,
298
+ async run(event) {
299
+ eventHandler();
300
+ },
301
+ });
323
302
 
324
- const app = defineResource({
325
- id: "app.resource",
326
- register: [testEvent, task],
327
- dependencies: { task, testEvent },
328
- async init(_, deps) {
329
- await deps.testEvent({ message: "Event emitted" });
330
- },
303
+ const app = defineResource({
304
+ id: "app.resource",
305
+ register: [testEvent, task],
306
+ dependencies: { task, testEvent },
307
+ async init(_, deps) {
308
+ await deps.testEvent({ message: "Event emitted" });
309
+ },
310
+ });
311
+
312
+ await run(app);
313
+ expect(eventHandler).toHaveBeenCalled();
331
314
  });
332
315
 
333
- await run(app);
334
- expect(eventHandler).toHaveBeenCalled();
335
- });
316
+ it("should avoid infinite recursion by omitting task emissions recursively", async () => {
317
+ const testEvent = defineEvent<{ message: string }>({ id: "test.event" });
318
+ const eventHandler = jest.fn();
336
319
 
337
- it("should be able to listen to global events", async () => {
338
- const testEvent = defineEvent<{ message: string }>({ id: "test.event" });
339
- const eventHandler = jest.fn();
320
+ const task = defineTask({
321
+ id: "app",
322
+ on: testEvent,
323
+ dependencies: { testEvent },
324
+ async run(event, { testEvent }) {
325
+ eventHandler();
326
+ await testEvent({ message: "Event emitted" });
327
+ },
328
+ });
340
329
 
341
- const resource = defineResource({
342
- id: "app",
343
- hooks: [
344
- {
345
- event: "*",
346
- run: eventHandler,
330
+ const app = defineResource({
331
+ id: "app.resource",
332
+ register: [testEvent, task],
333
+ dependencies: { task, testEvent },
334
+ async init(_, deps) {
335
+ await deps.testEvent({ message: "Event emitted" });
347
336
  },
348
- ],
349
- });
337
+ });
350
338
 
351
- const app = defineResource({
352
- id: "app.resource",
353
- register: [testEvent, resource],
354
- dependencies: { resource, testEvent },
355
- async init(_, deps) {
356
- await deps.testEvent({ message: "Event emitted" });
357
- },
339
+ await run(app);
340
+ expect(eventHandler).toHaveBeenCalled();
358
341
  });
359
342
 
360
- await run(app);
361
- expect(eventHandler).toHaveBeenCalled();
343
+ it("should be able to listen to global events", async () => {
344
+ const testEvent = defineEvent<{ message: string }>({ id: "test.event" });
345
+ const eventHandler = jest.fn();
346
+ let isReady = false;
347
+
348
+ const task = defineTask({
349
+ id: "app",
350
+ on: "*",
351
+ async run(event) {
352
+ event.data;
353
+ isReady && eventHandler();
354
+ },
355
+ });
356
+
357
+ const app = defineResource({
358
+ id: "app.resource",
359
+ register: [testEvent, task],
360
+ dependencies: { task, testEvent },
361
+ async init(_, deps) {
362
+ isReady = true;
363
+ await deps.testEvent({ message: "Event emitted" });
364
+ },
365
+ });
366
+
367
+ await run(app);
368
+ expect(eventHandler).toHaveBeenCalled();
369
+ });
362
370
  });
363
371
 
364
372
  // Resources
@@ -462,8 +470,8 @@ describe("run", () => {
462
470
 
463
471
  it("should allow suppression of an error", async () => {
464
472
  const supressMock = jest.fn();
465
- const testResource = defineResource({
466
- id: "test.resource",
473
+ const erroringResource = defineResource({
474
+ id: "error.resource",
467
475
  init: async () => {
468
476
  // we do this so it doesn't become a never.
469
477
  if (true === true) {
@@ -471,29 +479,52 @@ describe("run", () => {
471
479
  }
472
480
  },
473
481
  });
482
+ const erroringTask = defineTask({
483
+ id: "error.task",
484
+ run: async (event) => {
485
+ if (true === true) {
486
+ throw new Error("Run failed");
487
+ }
488
+ },
489
+ });
490
+
491
+ const resourceErrorHandler = defineTask({
492
+ id: "resourcehandler",
493
+ on: erroringResource.events.onError,
494
+ run: async (event) => {
495
+ supressMock();
496
+ event.data.suppress();
497
+ },
498
+ });
499
+
500
+ const taskErrorHandler = defineTask({
501
+ id: "taskhandler",
502
+ on: erroringTask.events.onError,
503
+ run: async (event) => {
504
+ supressMock();
505
+ event.data.suppress();
506
+ },
507
+ });
474
508
 
475
509
  const app = defineResource({
476
510
  id: "app",
477
- register: [testResource],
478
- dependencies: { testResource },
479
- hooks: [
480
- {
481
- event: testResource.events.onError,
482
- run: async (event, deps) => {
483
- supressMock();
484
- event.data.suppress();
485
- },
486
- },
511
+ register: [
512
+ erroringResource,
513
+ erroringTask,
514
+ resourceErrorHandler,
515
+ taskErrorHandler,
487
516
  ],
488
- async init(_, { testResource }) {
489
- expect(testResource).toBeUndefined();
517
+ dependencies: { erroringResource, erroringTask },
518
+ async init(_, { erroringResource, erroringTask }) {
519
+ expect(erroringResource).toBeUndefined();
520
+ expect(await erroringTask()).toBeUndefined();
490
521
 
491
522
  return "ok";
492
523
  },
493
524
  });
494
525
 
495
526
  await expect(run(app)).resolves.toBe("ok");
496
- expect(supressMock).toHaveBeenCalled();
527
+ expect(supressMock).toHaveBeenCalledTimes(2);
497
528
  });
498
529
  });
499
530
 
@@ -0,0 +1,51 @@
1
+ import {
2
+ defineTask,
3
+ defineResource,
4
+ defineMiddleware,
5
+ defineEvent,
6
+ } from "../../define";
7
+ import { symbols } from "../../defs";
8
+ import { getCallerFile } from "../../tools/getCallerFile";
9
+
10
+ describe("getCallerFile", () => {
11
+ it("should return the file name of the caller", () => {
12
+ function testFunction() {
13
+ return getCallerFile();
14
+ }
15
+
16
+ const callerFile = testFunction();
17
+
18
+ expect(callerFile).toBeDefined();
19
+ expect(callerFile).toContain("getCallerFile.test"); // we don't use .ts because for coverage it gets compiled to js
20
+ });
21
+
22
+ it("Should work with tasks, resources, middleware and events", () => {
23
+ const task = defineTask({
24
+ id: "task",
25
+ run: async () => {},
26
+ });
27
+ const resource = defineResource({
28
+ id: "resource",
29
+ init: async () => {},
30
+ });
31
+
32
+ const middleware = defineMiddleware({
33
+ id: "middleware",
34
+ run: async () => {},
35
+ });
36
+
37
+ const event = defineEvent({
38
+ id: "event",
39
+ });
40
+
41
+ expect(task[symbols.filePath]).toBeDefined();
42
+ expect(resource[symbols.filePath]).toBeDefined();
43
+ expect(middleware[symbols.filePath]).toBeDefined();
44
+ expect(event[symbols.filePath]).toBeDefined();
45
+
46
+ expect(task[symbols.filePath]).toContain("getCallerFile.test");
47
+ expect(resource[symbols.filePath]).toContain("getCallerFile.test");
48
+ expect(middleware[symbols.filePath]).toContain("getCallerFile.test");
49
+ expect(event[symbols.filePath]).toContain("getCallerFile.test");
50
+ });
51
+ });
@@ -51,6 +51,10 @@ describe("typesafety", () => {
51
51
  id: "dummy.resource",
52
52
  init: async () => "Resource Value",
53
53
  });
54
+ const dummyResourceOptionalConfig = defineResource({
55
+ id: "dummy.resource",
56
+ init: async (config?: string) => "Resource Value",
57
+ });
54
58
 
55
59
  const testResource = defineResource({
56
60
  id: "test.resource",
@@ -91,6 +95,9 @@ describe("typesafety", () => {
91
95
  dummyResource.with({ ok: 123 }),
92
96
  // @ts-expect-error
93
97
  dummyResource.with(),
98
+
99
+ // should work
100
+ dummyResourceOptionalConfig.with("hello"),
94
101
  ],
95
102
  });
96
103
 
@@ -105,24 +112,18 @@ describe("typesafety", () => {
105
112
  run: async () => "Task executed",
106
113
  });
107
114
 
108
- const testResource = defineResource({
115
+ const testResource = defineTask({
109
116
  id: "test.resource",
110
117
  dependencies: { task },
111
- init: async () => "Resource Value",
112
- hooks: [
113
- {
114
- event: hookEvent,
115
- run: (event, deps) => {
116
- // @ts-expect-error
117
- event.data.x;
118
-
119
- event.data.message;
120
- deps.task;
121
- // @ts-expect-error
122
- deps.task2;
123
- },
124
- },
125
- ],
118
+ on: hookEvent,
119
+ run: async (_, deps) => {
120
+ _.data.message;
121
+ // @ts-expect-error
122
+ _.data.messagex;
123
+ deps.task();
124
+ // @ts-expect-error
125
+ deps.task2;
126
+ },
126
127
  });
127
128
 
128
129
  expect(true).toBe(true);