@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.
- package/README.md +272 -12
- package/dist/define.d.ts +3 -3
- package/dist/define.js +39 -14
- package/dist/define.js.map +1 -1
- package/dist/defs.d.ts +60 -45
- package/dist/defs.js +3 -1
- package/dist/defs.js.map +1 -1
- package/dist/errors.d.ts +5 -5
- package/dist/errors.js +6 -5
- package/dist/errors.js.map +1 -1
- package/dist/globals/globalEvents.d.ts +11 -11
- package/dist/globals/globalMiddleware.d.ts +1 -1
- package/dist/globals/globalResources.d.ts +3 -3
- package/dist/globals/middleware/cache.middleware.d.ts +2 -2
- package/dist/globals/middleware/cache.middleware.js.map +1 -1
- package/dist/globals/resources/queue.resource.d.ts +2 -2
- package/dist/globals/resources/queue.resource.js.map +1 -1
- package/dist/index.d.ts +13 -13
- package/dist/models/DependencyProcessor.d.ts +4 -4
- package/dist/models/DependencyProcessor.js +2 -2
- package/dist/models/DependencyProcessor.js.map +1 -1
- package/dist/models/EventManager.d.ts +5 -5
- package/dist/models/EventManager.js.map +1 -1
- package/dist/models/Logger.d.ts +1 -1
- package/dist/models/Logger.js +29 -27
- package/dist/models/Logger.js.map +1 -1
- package/dist/models/OverrideManager.d.ts +2 -2
- package/dist/models/OverrideManager.js.map +1 -1
- package/dist/models/ResourceInitializer.js +3 -1
- package/dist/models/ResourceInitializer.js.map +1 -1
- package/dist/models/Store.d.ts +8 -8
- package/dist/models/Store.js.map +1 -1
- package/dist/models/StoreConstants.d.ts +2 -2
- package/dist/models/StoreRegistry.d.ts +8 -8
- package/dist/models/StoreRegistry.js +1 -1
- package/dist/models/StoreRegistry.js.map +1 -1
- package/dist/models/StoreValidator.d.ts +2 -2
- package/dist/models/StoreValidator.js +1 -1
- package/dist/models/StoreValidator.js.map +1 -1
- package/dist/models/TaskRunner.d.ts +1 -1
- package/dist/tools/getCallerFile.d.ts +9 -1
- package/dist/tools/getCallerFile.js +41 -0
- package/dist/tools/getCallerFile.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/models/EventManager.test.ts +48 -46
- package/src/__tests__/recursion/README.md +3 -0
- package/src/__tests__/recursion/a.resource.ts +25 -0
- package/src/__tests__/recursion/b.resource.ts +33 -0
- package/src/__tests__/recursion/c.resource.ts +18 -0
- package/src/__tests__/run.anonymous.test.ts +679 -0
- package/src/__tests__/run.dynamic-register-and-dependencies.test.ts +1185 -0
- package/src/__tests__/run.middleware.test.ts +146 -0
- package/src/__tests__/run.test.ts +1 -1
- package/src/__tests__/tools/getCallerFile.test.ts +117 -2
- package/src/__tests__/typesafety.test.ts +17 -2
- package/src/define.ts +47 -22
- package/src/defs.ts +77 -90
- package/src/errors.ts +13 -10
- package/src/globals/middleware/cache.middleware.ts +1 -1
- package/src/globals/resources/queue.resource.ts +1 -1
- package/src/models/DependencyProcessor.ts +7 -10
- package/src/models/EventManager.ts +25 -14
- package/src/models/Logger.ts +51 -39
- package/src/models/OverrideManager.ts +3 -3
- package/src/models/ResourceInitializer.ts +3 -1
- package/src/models/Store.ts +2 -2
- package/src/models/StoreRegistry.ts +28 -17
- package/src/models/StoreValidator.ts +13 -8
- package/src/models/TaskRunner.ts +1 -1
- package/src/tools/getCallerFile.ts +54 -2
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { IEvent,
|
|
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:
|
|
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:
|
|
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:
|
|
165
|
+
const eventDef1: IEvent<string> = {
|
|
165
166
|
id: "event1",
|
|
166
167
|
[symbolEvent]: true,
|
|
167
168
|
};
|
|
168
|
-
const eventDef2:
|
|
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:
|
|
215
|
+
const eventDef1: IEvent<string> = {
|
|
214
216
|
id: "event1",
|
|
215
217
|
[symbolEvent]: true,
|
|
216
218
|
};
|
|
217
|
-
const eventDef2:
|
|
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:
|
|
249
|
+
const eventDef1: IEvent<string> = {
|
|
248
250
|
id: "event1",
|
|
249
251
|
[symbolEvent]: true,
|
|
250
252
|
};
|
|
251
|
-
const eventDef2:
|
|
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:
|
|
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:
|
|
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:
|
|
446
|
-
const event2:
|
|
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:
|
|
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
|
-
|
|
514
|
-
|
|
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:
|
|
530
|
-
const event2:
|
|
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,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.
|