@bluelibs/runner 3.0.0 → 3.1.1

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 (70) hide show
  1. package/README.md +272 -12
  2. package/dist/define.d.ts +3 -3
  3. package/dist/define.js +39 -14
  4. package/dist/define.js.map +1 -1
  5. package/dist/defs.d.ts +60 -45
  6. package/dist/defs.js +3 -1
  7. package/dist/defs.js.map +1 -1
  8. package/dist/errors.d.ts +5 -5
  9. package/dist/errors.js +6 -5
  10. package/dist/errors.js.map +1 -1
  11. package/dist/globals/globalEvents.d.ts +11 -11
  12. package/dist/globals/globalMiddleware.d.ts +1 -1
  13. package/dist/globals/globalResources.d.ts +3 -3
  14. package/dist/globals/middleware/cache.middleware.d.ts +2 -2
  15. package/dist/globals/middleware/cache.middleware.js.map +1 -1
  16. package/dist/globals/resources/queue.resource.d.ts +2 -2
  17. package/dist/globals/resources/queue.resource.js.map +1 -1
  18. package/dist/index.d.ts +13 -13
  19. package/dist/models/DependencyProcessor.d.ts +4 -4
  20. package/dist/models/DependencyProcessor.js +2 -2
  21. package/dist/models/DependencyProcessor.js.map +1 -1
  22. package/dist/models/EventManager.d.ts +5 -5
  23. package/dist/models/EventManager.js.map +1 -1
  24. package/dist/models/Logger.d.ts +1 -1
  25. package/dist/models/Logger.js +29 -27
  26. package/dist/models/Logger.js.map +1 -1
  27. package/dist/models/OverrideManager.d.ts +2 -2
  28. package/dist/models/OverrideManager.js.map +1 -1
  29. package/dist/models/ResourceInitializer.js +3 -1
  30. package/dist/models/ResourceInitializer.js.map +1 -1
  31. package/dist/models/Store.d.ts +8 -8
  32. package/dist/models/Store.js.map +1 -1
  33. package/dist/models/StoreConstants.d.ts +2 -2
  34. package/dist/models/StoreRegistry.d.ts +8 -8
  35. package/dist/models/StoreRegistry.js +1 -1
  36. package/dist/models/StoreRegistry.js.map +1 -1
  37. package/dist/models/StoreValidator.d.ts +2 -2
  38. package/dist/models/StoreValidator.js +1 -1
  39. package/dist/models/StoreValidator.js.map +1 -1
  40. package/dist/models/TaskRunner.d.ts +1 -1
  41. package/dist/tools/getCallerFile.d.ts +9 -1
  42. package/dist/tools/getCallerFile.js +41 -0
  43. package/dist/tools/getCallerFile.js.map +1 -1
  44. package/package.json +1 -1
  45. package/src/__tests__/models/EventManager.test.ts +48 -46
  46. package/src/__tests__/recursion/README.md +3 -0
  47. package/src/__tests__/recursion/a.resource.ts +25 -0
  48. package/src/__tests__/recursion/b.resource.ts +33 -0
  49. package/src/__tests__/recursion/c.resource.ts +18 -0
  50. package/src/__tests__/run.anonymous.test.ts +679 -0
  51. package/src/__tests__/run.dynamic-register-and-dependencies.test.ts +1185 -0
  52. package/src/__tests__/run.middleware.test.ts +146 -0
  53. package/src/__tests__/run.test.ts +1 -1
  54. package/src/__tests__/tools/getCallerFile.test.ts +117 -2
  55. package/src/__tests__/typesafety.test.ts +17 -2
  56. package/src/define.ts +47 -22
  57. package/src/defs.ts +77 -90
  58. package/src/errors.ts +13 -10
  59. package/src/globals/middleware/cache.middleware.ts +1 -1
  60. package/src/globals/resources/queue.resource.ts +1 -1
  61. package/src/models/DependencyProcessor.ts +7 -10
  62. package/src/models/EventManager.ts +25 -14
  63. package/src/models/Logger.ts +51 -39
  64. package/src/models/OverrideManager.ts +3 -3
  65. package/src/models/ResourceInitializer.ts +3 -1
  66. package/src/models/Store.ts +2 -2
  67. package/src/models/StoreRegistry.ts +28 -17
  68. package/src/models/StoreValidator.ts +13 -8
  69. package/src/models/TaskRunner.ts +1 -1
  70. package/src/tools/getCallerFile.ts +54 -2
@@ -1,10 +1,10 @@
1
- import { IEvent, IEventDefinition, symbolEvent } from "../../defs";
1
+ import { IEvent, IEventEmission, symbolEvent } from "../../defs";
2
2
  import { Errors } from "../../errors";
3
3
  import { EventManager } from "../../models/EventManager";
4
4
 
5
5
  describe("EventManager", () => {
6
6
  let eventManager: EventManager;
7
- let eventDefinition: IEventDefinition<string>;
7
+ let eventDefinition: IEvent<string>;
8
8
 
9
9
  beforeEach(() => {
10
10
  eventManager = new EventManager();
@@ -69,7 +69,7 @@ describe("EventManager", () => {
69
69
 
70
70
  it("should apply filters correctly", async () => {
71
71
  const handler = jest.fn();
72
- const filter = (event: IEvent<string>) => event.data === "allowed";
72
+ const filter = (event: IEventEmission<string>) => event.data === "allowed";
73
73
 
74
74
  eventManager.addListener(eventDefinition, handler, { filter });
75
75
 
@@ -97,6 +97,7 @@ describe("EventManager", () => {
97
97
  expect.objectContaining({
98
98
  id: "testEvent",
99
99
  data: "testData",
100
+ timestamp: expect.any(Date),
100
101
  })
101
102
  );
102
103
  });
@@ -161,11 +162,11 @@ describe("EventManager", () => {
161
162
  });
162
163
 
163
164
  it("should handle multiple events", async () => {
164
- const eventDef1: IEventDefinition<string> = {
165
+ const eventDef1: IEvent<string> = {
165
166
  id: "event1",
166
167
  [symbolEvent]: true,
167
168
  };
168
- const eventDef2: IEventDefinition<string> = {
169
+ const eventDef2: IEvent<string> = {
169
170
  id: "event2",
170
171
  [symbolEvent]: true,
171
172
  };
@@ -184,6 +185,7 @@ describe("EventManager", () => {
184
185
  expect.objectContaining({
185
186
  id: "event1",
186
187
  data: "data1",
188
+ timestamp: expect.any(Date),
187
189
  })
188
190
  );
189
191
 
@@ -210,11 +212,11 @@ describe("EventManager", () => {
210
212
  });
211
213
 
212
214
  it("should handle listeners added to multiple events", async () => {
213
- const eventDef1: IEventDefinition<string> = {
215
+ const eventDef1: IEvent<string> = {
214
216
  id: "event1",
215
217
  [symbolEvent]: true,
216
218
  };
217
- const eventDef2: IEventDefinition<string> = {
219
+ const eventDef2: IEvent<string> = {
218
220
  id: "event2",
219
221
  [symbolEvent]: true,
220
222
  };
@@ -244,11 +246,11 @@ describe("EventManager", () => {
244
246
  });
245
247
 
246
248
  it("should not affect other events when emitting one", async () => {
247
- const eventDef1: IEventDefinition<string> = {
249
+ const eventDef1: IEvent<string> = {
248
250
  id: "event1",
249
251
  [symbolEvent]: true,
250
252
  };
251
- const eventDef2: IEventDefinition<string> = {
253
+ const eventDef2: IEvent<string> = {
252
254
  id: "event2",
253
255
  [symbolEvent]: true,
254
256
  };
@@ -367,7 +369,7 @@ describe("EventManager", () => {
367
369
 
368
370
  it("should handle filters in global listeners", async () => {
369
371
  const handler = jest.fn();
370
- const filter = (event: IEvent<string>) => event.data === "allowed";
372
+ const filter = (event: IEventEmission<string>) => event.data === "allowed";
371
373
 
372
374
  eventManager.addGlobalListener(handler, { filter });
373
375
 
@@ -387,7 +389,7 @@ describe("EventManager", () => {
387
389
  it("should handle listeners with no data", async () => {
388
390
  const handler = jest.fn();
389
391
 
390
- const voidEventDefinition: IEventDefinition<void> = {
392
+ const voidEventDefinition: IEvent<void> = {
391
393
  id: "voidEvent",
392
394
  [symbolEvent]: true,
393
395
  };
@@ -401,6 +403,7 @@ describe("EventManager", () => {
401
403
  expect.objectContaining({
402
404
  id: "voidEvent",
403
405
  data: undefined,
406
+ timestamp: expect.any(Date),
404
407
  })
405
408
  );
406
409
  });
@@ -409,15 +412,15 @@ describe("EventManager", () => {
409
412
  it("should cache merged listeners for repeated emits", async () => {
410
413
  const handler1 = jest.fn();
411
414
  const handler2 = jest.fn();
412
-
415
+
413
416
  eventManager.addListener(eventDefinition, handler1, { order: 1 });
414
417
  eventManager.addGlobalListener(handler2, { order: 2 });
415
-
418
+
416
419
  // First emit should build cache
417
420
  await eventManager.emit(eventDefinition, "test1", "source");
418
421
  // Second emit should use cache
419
422
  await eventManager.emit(eventDefinition, "test2", "source");
420
-
423
+
421
424
  expect(handler1).toHaveBeenCalledTimes(2);
422
425
  expect(handler2).toHaveBeenCalledTimes(2);
423
426
  });
@@ -426,55 +429,55 @@ describe("EventManager", () => {
426
429
  const handler1 = jest.fn();
427
430
  const handler2 = jest.fn();
428
431
  const handler3 = jest.fn();
429
-
432
+
430
433
  eventManager.addListener(eventDefinition, handler1, { order: 2 });
431
434
  await eventManager.emit(eventDefinition, "test1", "source");
432
-
435
+
433
436
  // Add new listener - should invalidate cache for this event
434
437
  eventManager.addListener(eventDefinition, handler2, { order: 1 });
435
438
  eventManager.addGlobalListener(handler3, { order: 3 });
436
-
439
+
437
440
  await eventManager.emit(eventDefinition, "test2", "source");
438
-
441
+
439
442
  expect(handler1).toHaveBeenCalledTimes(2);
440
443
  expect(handler2).toHaveBeenCalledTimes(1);
441
444
  expect(handler3).toHaveBeenCalledTimes(1);
442
445
  });
443
446
 
444
447
  it("should invalidate all caches when adding global listeners", async () => {
445
- const event1: IEventDefinition<string> = { id: "event1", [symbolEvent]: true };
446
- const event2: IEventDefinition<string> = { id: "event2", [symbolEvent]: true };
447
-
448
+ const event1: IEvent<string> = { id: "event1", [symbolEvent]: true };
449
+ const event2: IEvent<string> = { id: "event2", [symbolEvent]: true };
450
+
448
451
  const handler1 = jest.fn();
449
452
  const handler2 = jest.fn();
450
453
  const globalHandler = jest.fn();
451
-
454
+
452
455
  eventManager.addListener(event1, handler1);
453
456
  eventManager.addListener(event2, handler2);
454
-
457
+
455
458
  // Emit to build caches
456
459
  await eventManager.emit(event1, "test1", "source");
457
460
  await eventManager.emit(event2, "test2", "source");
458
-
461
+
459
462
  // Add global listener - should invalidate all caches
460
463
  eventManager.addGlobalListener(globalHandler);
461
-
464
+
462
465
  // Emit again - global handler should be called
463
466
  await eventManager.emit(event1, "test3", "source");
464
467
  await eventManager.emit(event2, "test4", "source");
465
-
468
+
466
469
  expect(globalHandler).toHaveBeenCalledTimes(2);
467
470
  });
468
471
 
469
472
  it("should optimize for empty listener scenarios", async () => {
470
- const emptyEventDef: IEventDefinition<string> = {
473
+ const emptyEventDef: IEvent<string> = {
471
474
  id: "emptyEvent",
472
475
  [symbolEvent]: true,
473
476
  };
474
-
477
+
475
478
  // Should return immediately without creating event object
476
479
  await eventManager.emit(emptyEventDef, "test", "source");
477
-
480
+
478
481
  // No errors should occur
479
482
  expect(true).toBe(true);
480
483
  });
@@ -483,17 +486,17 @@ describe("EventManager", () => {
483
486
  const handler = jest.fn();
484
487
  eventManager.addListener(eventDefinition, handler);
485
488
  eventManager.addGlobalListener(jest.fn());
486
-
489
+
487
490
  const emitCount = 1000;
488
491
  const startTime = Date.now();
489
-
492
+
490
493
  for (let i = 0; i < emitCount; i++) {
491
494
  await eventManager.emit(eventDefinition, `test${i}`, "source");
492
495
  }
493
-
496
+
494
497
  const endTime = Date.now();
495
498
  const duration = endTime - startTime;
496
-
499
+
497
500
  expect(handler).toHaveBeenCalledTimes(emitCount);
498
501
  // Should complete reasonably fast (adjust threshold as needed)
499
502
  expect(duration).toBeLessThan(5000); // 5 seconds max for 1000 emissions
@@ -501,7 +504,7 @@ describe("EventManager", () => {
501
504
 
502
505
  it("should efficiently handle mixed event and global listeners", async () => {
503
506
  const results: string[] = [];
504
-
507
+
505
508
  // Add many listeners with different orders
506
509
  for (let i = 0; i < 10; i++) {
507
510
  eventManager.addListener(
@@ -509,14 +512,13 @@ describe("EventManager", () => {
509
512
  () => results.push(`event${i}`),
510
513
  { order: i * 2 }
511
514
  );
512
- eventManager.addGlobalListener(
513
- () => results.push(`global${i}`),
514
- { order: i * 2 + 1 }
515
- );
515
+ eventManager.addGlobalListener(() => results.push(`global${i}`), {
516
+ order: i * 2 + 1,
517
+ });
516
518
  }
517
-
519
+
518
520
  await eventManager.emit(eventDefinition, "test", "source");
519
-
521
+
520
522
  // Should maintain correct order and call all listeners
521
523
  expect(results).toHaveLength(20);
522
524
  expect(results[0]).toBe("event0");
@@ -526,23 +528,23 @@ describe("EventManager", () => {
526
528
  });
527
529
 
528
530
  it("should reuse cached results across different event types", async () => {
529
- const event1: IEventDefinition<string> = { id: "event1", [symbolEvent]: true };
530
- const event2: IEventDefinition<string> = { id: "event2", [symbolEvent]: true };
531
-
531
+ const event1: IEvent<string> = { id: "event1", [symbolEvent]: true };
532
+ const event2: IEvent<string> = { id: "event2", [symbolEvent]: true };
533
+
532
534
  const handler1 = jest.fn();
533
535
  const handler2 = jest.fn();
534
536
  const globalHandler = jest.fn();
535
-
537
+
536
538
  eventManager.addListener(event1, handler1);
537
539
  eventManager.addListener(event2, handler2);
538
540
  eventManager.addGlobalListener(globalHandler);
539
-
541
+
540
542
  // Multiple emits should use cached merged listeners
541
543
  await eventManager.emit(event1, "test1", "source");
542
544
  await eventManager.emit(event2, "test2", "source");
543
545
  await eventManager.emit(event1, "test3", "source");
544
546
  await eventManager.emit(event2, "test4", "source");
545
-
547
+
546
548
  expect(handler1).toHaveBeenCalledTimes(2);
547
549
  expect(handler2).toHaveBeenCalledTimes(2);
548
550
  expect(globalHandler).toHaveBeenCalledTimes(4);
@@ -0,0 +1,3 @@
1
+ This is a test, tsc build will fail if the code is not correct.
2
+
3
+ These files are not ran they are just used to test the tsc build.
@@ -0,0 +1,25 @@
1
+ import { defineResource, defineTask } from "../../define";
2
+ import { bResource } from "./b.resource";
3
+
4
+ export const aResource = defineResource({
5
+ id: "a.resource",
6
+ dependencies: {
7
+ b: bResource,
8
+ },
9
+ async init(_, { b }) {
10
+ const result: string = b;
11
+ // @ts-expect-error
12
+ const result2: number = b;
13
+ return `A depends on ${b}`;
14
+ },
15
+ });
16
+
17
+ export const aTask = defineTask({
18
+ id: "a.task",
19
+ dependencies: {
20
+ a: aResource,
21
+ },
22
+ async run(_, { a }) {
23
+ return `Task A executed with dependency: ${a}`;
24
+ },
25
+ });
@@ -0,0 +1,33 @@
1
+ import { defineResource } from "../../define";
2
+ import { cResource } from "./c.resource";
3
+
4
+ export const bResource = defineResource({
5
+ id: "b.resource",
6
+ dependencies: {
7
+ c: cResource,
8
+ },
9
+ async init(_, { c }) {
10
+ const result: string = c;
11
+ // @ts-expect-error
12
+ const result2: number = c;
13
+ return `B depends on ${c}`;
14
+ },
15
+ });
16
+ export const b1Resource = defineResource({
17
+ id: "b.resource",
18
+ dependencies: {
19
+ c: cResource,
20
+ },
21
+ async init(_, { c }) {
22
+ return 123;
23
+ },
24
+ });
25
+ export const b2Resource = defineResource({
26
+ id: "b.resource",
27
+ dependencies: {
28
+ c: cResource,
29
+ },
30
+ async init(_, { c }) {
31
+ return true;
32
+ },
33
+ });
@@ -0,0 +1,18 @@
1
+ import { defineResource } from "../../define";
2
+ import { IResource } from "../../defs";
3
+ import { aResource, aTask } from "./a.resource";
4
+ import { b1Resource, b2Resource } from "./b.resource";
5
+
6
+ const value = Math.random() > 0.5 ? b1Resource : b2Resource;
7
+
8
+ export const cResource = defineResource({
9
+ id: "c.resource",
10
+ dependencies: {
11
+ aTask,
12
+ customResource: value,
13
+ },
14
+ async init(_, { aTask, customResource }) {
15
+ const result: string = await aTask(); // Still benefits of autocompletion
16
+ return `C depends on ${result}`;
17
+ },
18
+ }) as IResource<void, string>; // This is the key change.