@bluelibs/runner 1.5.3 → 2.0.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.
- package/README.md +299 -156
- package/dist/define.d.ts +1 -1
- package/dist/define.js +0 -1
- package/dist/define.js.map +1 -1
- package/dist/defs.d.ts +12 -8
- package/dist/globalEvents.js +45 -0
- package/dist/globalEvents.js.map +1 -1
- package/dist/globalResources.js +14 -0
- package/dist/globalResources.js.map +1 -1
- package/dist/models/DependencyProcessor.d.ts +1 -7
- package/dist/models/DependencyProcessor.js +31 -54
- package/dist/models/DependencyProcessor.js.map +1 -1
- package/dist/models/EventManager.d.ts +4 -0
- package/dist/models/EventManager.js.map +1 -1
- package/dist/models/ResourceInitializer.js +4 -2
- package/dist/models/ResourceInitializer.js.map +1 -1
- package/dist/models/Store.d.ts +2 -2
- package/dist/models/Store.js +2 -0
- package/dist/models/Store.js.map +1 -1
- package/dist/models/TaskRunner.js +28 -16
- package/dist/models/TaskRunner.js.map +1 -1
- package/dist/run.js +1 -1
- package/dist/run.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/benchmark/benchmark.test.ts +9 -7
- package/src/__tests__/errors.test.ts +0 -13
- package/src/__tests__/globalEvents.test.ts +53 -28
- package/src/__tests__/index.ts +0 -1
- package/src/__tests__/models/EventManager.test.ts +1 -0
- package/src/__tests__/run.test.ts +140 -109
- package/src/__tests__/typesafety.test.ts +17 -16
- package/src/define.ts +3 -4
- package/src/defs.ts +35 -22
- package/src/globalEvents.ts +53 -0
- package/src/globalResources.ts +17 -0
- package/src/models/DependencyProcessor.ts +45 -80
- package/src/models/EventManager.ts +4 -0
- package/src/models/ResourceInitializer.ts +4 -2
- package/src/models/Store.ts +6 -2
- package/src/models/TaskRunner.ts +51 -28
- package/src/run.ts +1 -1
- package/dist/DependencyProcessor.d.ts +0 -49
- package/dist/DependencyProcessor.js +0 -178
- package/dist/DependencyProcessor.js.map +0 -1
- package/dist/EventManager.d.ts +0 -17
- package/dist/EventManager.js +0 -73
- package/dist/EventManager.js.map +0 -1
- package/dist/ResourceInitializer.d.ts +0 -13
- package/dist/ResourceInitializer.js +0 -54
- package/dist/ResourceInitializer.js.map +0 -1
- package/dist/Store.d.ts +0 -90
- package/dist/Store.js +0 -291
- package/dist/Store.js.map +0 -1
- package/dist/TaskRunner.d.ts +0 -25
- package/dist/TaskRunner.js +0 -96
- package/dist/TaskRunner.js.map +0 -1
- package/src/__tests__/run.hooks.test.ts +0 -110
package/README.md
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
<a href="https://github.com/bluelibs/runner/actions/workflows/ci.yml"><img src="https://github.com/bluelibs/runner/actions/workflows/ci.yml/badge.svg?branch=main" alt="Build Status" /></a>
|
|
5
5
|
<a href="https://coveralls.io/github/bluelibs/runner?branch=main"><img src="https://coveralls.io/repos/github/bluelibs/runner/badge.svg?branch=main" alt="Coverage Status" /></a>
|
|
6
6
|
<a href="https://bluelibs.github.io/runner/" target="_blank"><img src="https://img.shields.io/badge/read-typedocs-blue" alt="Docs" /></a>
|
|
7
|
+
<a href="https://github.com/bluelibs/runner" target="_blank"><img src="https://img.shields.io/badge/github-blue" alt="GitHub" /></a>
|
|
7
8
|
</p>
|
|
8
9
|
|
|
9
10
|
- [View the documentation page here](https://bluelibs.github.io/runner/).
|
|
@@ -244,7 +245,7 @@ const root = resource({
|
|
|
244
245
|
});
|
|
245
246
|
```
|
|
246
247
|
|
|
247
|
-
|
|
248
|
+
To listen to events you have to create a task.
|
|
248
249
|
|
|
249
250
|
### `task.on` property
|
|
250
251
|
|
|
@@ -277,9 +278,9 @@ const app = resource({
|
|
|
277
278
|
});
|
|
278
279
|
```
|
|
279
280
|
|
|
280
|
-
###
|
|
281
|
+
### wildcard events
|
|
281
282
|
|
|
282
|
-
|
|
283
|
+
You can listen to all events by using the wildcard `*`.
|
|
283
284
|
|
|
284
285
|
```ts
|
|
285
286
|
import { task, resource, run, event, global } from "@bluelibs/runner";
|
|
@@ -288,69 +289,24 @@ const afterRegisterEvent = event<{ userId: string }>({
|
|
|
288
289
|
id: "app.user.registered",
|
|
289
290
|
});
|
|
290
291
|
|
|
291
|
-
const
|
|
292
|
-
id: "app",
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
{
|
|
297
|
-
event: global.events.afterInit,
|
|
298
|
-
order: -1000, // event priority, the lower the number, the sooner it will run.
|
|
299
|
-
async run(event, deps) {
|
|
300
|
-
// both dependencies and event are properly infered through typescript
|
|
301
|
-
console.log("User has been registered!");
|
|
302
|
-
},
|
|
303
|
-
},
|
|
304
|
-
],
|
|
305
|
-
async init(_, deps) {
|
|
306
|
-
await deps.afterRegisterEvent({ userId: "XXX" });
|
|
292
|
+
const logAllEventsTask = task({
|
|
293
|
+
id: "app.tasks.logAllEvents",
|
|
294
|
+
on: "*",
|
|
295
|
+
run(event) {
|
|
296
|
+
console.log("Event detected", event.id, event.data);
|
|
307
297
|
},
|
|
308
298
|
});
|
|
309
|
-
```
|
|
310
|
-
|
|
311
|
-
#### wildcard events
|
|
312
|
-
|
|
313
|
-
You can listen to all events by using the wildcard `*`.
|
|
314
|
-
|
|
315
|
-
```ts
|
|
316
|
-
import { task, resource, run, event, global } from "@bluelibs/runner";
|
|
317
|
-
|
|
318
|
-
const afterRegisterEvent = event<{ userId: string }>({
|
|
319
|
-
id: "app.user.registered",
|
|
320
|
-
});
|
|
321
299
|
|
|
322
300
|
const root = resource({
|
|
323
301
|
id: "app",
|
|
324
|
-
register: [afterRegisterEvent],
|
|
302
|
+
register: [afterRegisterEvent, logAllEventsTask],
|
|
325
303
|
dependencies: {},
|
|
326
|
-
hooks: [
|
|
327
|
-
{
|
|
328
|
-
event: "*",
|
|
329
|
-
async run(event, deps) {
|
|
330
|
-
console.log(
|
|
331
|
-
"Generic event detected",
|
|
332
|
-
event.id,
|
|
333
|
-
event.data,
|
|
334
|
-
event.timestamp
|
|
335
|
-
);
|
|
336
|
-
},
|
|
337
|
-
},
|
|
338
|
-
],
|
|
339
304
|
async init(_, deps) {
|
|
340
305
|
deps.afterRegisterEvent({ userId: "XXX" });
|
|
341
306
|
},
|
|
342
307
|
});
|
|
343
308
|
```
|
|
344
309
|
|
|
345
|
-
When using hooks, inside resource() you benefit of autocompletion, in order to keep things clean, if your hooks become large and long consider switching to tasks and `on`. This is a more explicit way to listen to events, and your resource registers them.
|
|
346
|
-
|
|
347
|
-
The hooks from a `resource` are mostly used for configuration, and blending in the system.
|
|
348
|
-
|
|
349
|
-
### When to use either?
|
|
350
|
-
|
|
351
|
-
- `hooks` are for resources to extend each other, compose functionalities, they are mostly used for configuration and blending in the system.
|
|
352
|
-
- `on` is for when you want to perform a task when something happens, like send an email, begin processing something, etc.
|
|
353
|
-
|
|
354
310
|
## Middleware
|
|
355
311
|
|
|
356
312
|
Middleware intercepts the execution of tasks or the initialization of resources, providing a powerful means to enhance functionality. The order in which middleware is registered dictates its execution priority: the first middleware registered is the first to run, while the last middleware in the middleware array at the task level is the closest to the task itself, executing just before the task completes. (Imagine an onion if you will, with the task at the core.)
|
|
@@ -669,41 +625,237 @@ run();
|
|
|
669
625
|
|
|
670
626
|
## Global Events
|
|
671
627
|
|
|
672
|
-
|
|
628
|
+
You can listen to all events by using the wildcard `*`. However, keep in mind that to avoid infinite recursion, all the events coming from the same source will be ignored.
|
|
629
|
+
|
|
630
|
+
At the same time, if a task is listening to all events such as `beforeRun`, since it's a task, triggering `beforeRun` will lead to infinite recursion, this is why we ignore emitting the same event from the same source.
|
|
631
|
+
|
|
632
|
+
This guide outlines the key global events that can be used throughout your application to hook into resource and task lifecycle moments. These events help monitor initialization, execution, and errors, making your system more resilient and traceable.
|
|
633
|
+
|
|
634
|
+
### Overview
|
|
635
|
+
|
|
636
|
+
Global events are categorized into:
|
|
637
|
+
|
|
638
|
+
- **Initialization events**: Before and after a resource or task is initialized.
|
|
639
|
+
- **Execution events**: Before and after a task runs.
|
|
640
|
+
- **Error events**: Handling errors for both tasks and resources.
|
|
641
|
+
|
|
642
|
+
### Events in Tasks
|
|
643
|
+
|
|
644
|
+
#### `global.tasks.beforeRun`
|
|
645
|
+
|
|
646
|
+
This event is triggered just before a task is executed. It allows you to inspect or modify the input to the task.
|
|
647
|
+
|
|
648
|
+
##### Example:
|
|
649
|
+
|
|
650
|
+
```ts
|
|
651
|
+
task({
|
|
652
|
+
id: "logBeforeRun",
|
|
653
|
+
on: globalEvents.tasks.beforeRun, // Listening to the beforeRun event
|
|
654
|
+
run(event) {
|
|
655
|
+
console.log("Task is about to run with input:", event.data.input);
|
|
656
|
+
},
|
|
657
|
+
});
|
|
658
|
+
```
|
|
659
|
+
|
|
660
|
+
**Use Case**: You can use this event to log input data or modify it before the task execution.
|
|
661
|
+
|
|
662
|
+
#### `global.tasks.afterRun`
|
|
663
|
+
|
|
664
|
+
This event fires immediately after a task finishes. It provides access to both the task input and the result (output).
|
|
665
|
+
|
|
666
|
+
##### Example:
|
|
667
|
+
|
|
668
|
+
```ts
|
|
669
|
+
task({
|
|
670
|
+
id: "logAfterRun",
|
|
671
|
+
on: globalEvents.tasks.afterRun, // Listening to the afterRun event
|
|
672
|
+
run(event) {
|
|
673
|
+
console.log(
|
|
674
|
+
"Task completed. Input:",
|
|
675
|
+
event.data.input,
|
|
676
|
+
"Output:",
|
|
677
|
+
event.data.output
|
|
678
|
+
);
|
|
679
|
+
},
|
|
680
|
+
});
|
|
681
|
+
```
|
|
682
|
+
|
|
683
|
+
**Use Case**: Useful for logging or post-processing based on the task's output.
|
|
684
|
+
|
|
685
|
+
#### `global.tasks.onError`
|
|
686
|
+
|
|
687
|
+
If an error occurs during the execution of a task, this event is triggered. You can log or suppress the error.
|
|
688
|
+
|
|
689
|
+
##### Example:
|
|
690
|
+
|
|
691
|
+
```ts
|
|
692
|
+
task({
|
|
693
|
+
id: "handleTaskError",
|
|
694
|
+
on: globalEvents.tasks.onError, // Listening to the onError event
|
|
695
|
+
run(event) {
|
|
696
|
+
console.error("Error occurred:", event.data.error);
|
|
697
|
+
event.data.suppress(); // Optionally suppress the error to prevent propagation
|
|
698
|
+
},
|
|
699
|
+
});
|
|
700
|
+
```
|
|
701
|
+
|
|
702
|
+
**Use Case**: Error handling logic for specific tasks. For example, you may want to send alerts when a task fails.
|
|
703
|
+
|
|
704
|
+
### Events in Resources
|
|
705
|
+
|
|
706
|
+
#### `global.resources.beforeInit`
|
|
707
|
+
|
|
708
|
+
This event is triggered before a resource starts its initialization. It allows inspection or modification of the configuration before the resource is fully initialized.
|
|
709
|
+
|
|
710
|
+
##### Example:
|
|
711
|
+
|
|
712
|
+
```ts
|
|
713
|
+
task({
|
|
714
|
+
id: "logBeforeResourceInit",
|
|
715
|
+
on: globalEvents.resources.beforeInit, // Listening to beforeInit event for resources
|
|
716
|
+
run(event) {
|
|
717
|
+
console.log("Initializing resource with config:", event.data.config);
|
|
718
|
+
},
|
|
719
|
+
});
|
|
720
|
+
```
|
|
721
|
+
|
|
722
|
+
**Use Case**: Logging or validating the resource's configuration before initialization.
|
|
723
|
+
|
|
724
|
+
#### `global.resources.afterInit`
|
|
725
|
+
|
|
726
|
+
This event fires after a resource is initialized, giving access to the initialization result.
|
|
727
|
+
|
|
728
|
+
##### Example:
|
|
729
|
+
|
|
730
|
+
```ts
|
|
731
|
+
task({
|
|
732
|
+
id: "logAfterResourceInit",
|
|
733
|
+
on: globalEvents.resources.afterInit, // Listening to afterInit event
|
|
734
|
+
run(event) {
|
|
735
|
+
console.log("Resource initialized with value:", event.data.value);
|
|
736
|
+
},
|
|
737
|
+
});
|
|
738
|
+
```
|
|
739
|
+
|
|
740
|
+
**Use Case**: Post-processing or logging resource initialization details.
|
|
741
|
+
|
|
742
|
+
#### `global.resources.onError`
|
|
743
|
+
|
|
744
|
+
If an error occurs during resource initialization, this event is triggered. You can log or handle the error.
|
|
745
|
+
|
|
746
|
+
##### Example:
|
|
747
|
+
|
|
748
|
+
```ts
|
|
749
|
+
task({
|
|
750
|
+
id: "handleResourceError",
|
|
751
|
+
on: globalEvents.resources.onError, // Listening to resource onError event
|
|
752
|
+
run(event) {
|
|
753
|
+
console.error("Resource initialization error:", event.data.error);
|
|
754
|
+
event.data.suppress(); // Optionally suppress the error to prevent propagation
|
|
755
|
+
},
|
|
756
|
+
});
|
|
757
|
+
```
|
|
758
|
+
|
|
759
|
+
**Use Case**: Error handling for critical resources, allowing for fallback mechanisms or error logging.
|
|
760
|
+
|
|
761
|
+
#### Common Usage Pattern
|
|
762
|
+
|
|
763
|
+
To make use of these events, you will typically define tasks that respond to these global events. These tasks can then be registered in your main application resource to handle events for resources and tasks alike.
|
|
764
|
+
|
|
765
|
+
#### Example of registering event-handling tasks:
|
|
766
|
+
|
|
767
|
+
```ts
|
|
768
|
+
const app = resource({
|
|
769
|
+
id: "app",
|
|
770
|
+
register: [
|
|
771
|
+
logBeforeRun,
|
|
772
|
+
logAfterRun,
|
|
773
|
+
handleTaskError,
|
|
774
|
+
logBeforeResourceInit,
|
|
775
|
+
logAfterResourceInit,
|
|
776
|
+
handleResourceError,
|
|
777
|
+
],
|
|
778
|
+
});
|
|
779
|
+
|
|
780
|
+
run(app);
|
|
781
|
+
```
|
|
782
|
+
|
|
783
|
+
This structure helps you create a centralized and modular approach to manage events and handle tasks and resource lifecycles in your system.
|
|
784
|
+
|
|
785
|
+
### Available Global Events
|
|
786
|
+
|
|
787
|
+
Here’s a summary of all the global events you can listen to:
|
|
788
|
+
|
|
789
|
+
- `global.beforeInit`: Triggered before any resource is initialized.
|
|
790
|
+
- `global.afterInit`: Triggered after any resource is initialized.
|
|
791
|
+
- `global.log`: Used for logging across the system.
|
|
792
|
+
- **Task-specific events**:
|
|
793
|
+
- `global.tasks.beforeRun`: Fired before a task begins execution.
|
|
794
|
+
- `global.tasks.afterRun`: Fired after a task completes.
|
|
795
|
+
- `global.tasks.onError`: Fired if a task encounters an error.
|
|
796
|
+
- **Resource-specific events**:
|
|
797
|
+
- `global.resources.beforeInit`: Fired before a resource is initialized.
|
|
798
|
+
- `global.resources.afterInit`: Fired after a resource is initialized.
|
|
799
|
+
- `global.resources.onError`: Fired if an error occurs during resource initialization.
|
|
800
|
+
|
|
801
|
+
This modular event system helps in building more reactive and error-tolerant applications.
|
|
802
|
+
|
|
803
|
+
### Individual Task level
|
|
804
|
+
|
|
805
|
+
When creating tasks or resources we also create lifecycle events for them stored in `events` property.
|
|
673
806
|
|
|
674
807
|
```ts
|
|
675
808
|
import { task, run, event } from "@bluelibs/runner";
|
|
676
809
|
|
|
810
|
+
// Define the task
|
|
677
811
|
const helloWorld = task({
|
|
678
812
|
id: "app.helloWorld",
|
|
813
|
+
async run() {
|
|
814
|
+
// Task logic here
|
|
815
|
+
return "Hello World!";
|
|
816
|
+
},
|
|
817
|
+
});
|
|
818
|
+
|
|
819
|
+
// Define the tasks for beforeRun, afterRun, and onError using the `on` property
|
|
820
|
+
const beforeHelloWorldTask = task({
|
|
821
|
+
id: "app.helloWorld.beforeRun",
|
|
822
|
+
on: helloWorld.events.beforeRun, // Listening to beforeRun event
|
|
823
|
+
async run(event) {
|
|
824
|
+
const input = event.data.input; // Handle the input before task runs
|
|
825
|
+
console.log("Before run:", input);
|
|
826
|
+
},
|
|
827
|
+
});
|
|
828
|
+
|
|
829
|
+
const afterHelloWorldTask = task({
|
|
830
|
+
id: "app.helloWorld.afterRun",
|
|
831
|
+
on: helloWorld.events.afterRun, // Listening to afterRun event
|
|
832
|
+
async run(event) {
|
|
833
|
+
const output = event.data.output; // Handle the output after task runs
|
|
834
|
+
console.log("After run:", output);
|
|
835
|
+
},
|
|
836
|
+
});
|
|
837
|
+
|
|
838
|
+
const helloWorldErrorTask = task({
|
|
839
|
+
id: "app.helloWorld.onError",
|
|
840
|
+
on: helloWorld.events.onError, // Listening to onError event
|
|
841
|
+
async run(event) {
|
|
842
|
+
const error = event.data.error; // Handle errors during task execution
|
|
843
|
+
console.error("Error:", error);
|
|
844
|
+
},
|
|
679
845
|
});
|
|
680
846
|
|
|
681
|
-
//
|
|
847
|
+
// Register all tasks to the app
|
|
682
848
|
const app = resource({
|
|
683
849
|
id: "app",
|
|
684
|
-
register: [
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
event.data.input; // read the input
|
|
690
|
-
},
|
|
691
|
-
},
|
|
692
|
-
{
|
|
693
|
-
event: helloWorld.events.afterRun,
|
|
694
|
-
async run(event, deps) {
|
|
695
|
-
event.data.output; // you can read the input or output
|
|
696
|
-
},
|
|
697
|
-
},
|
|
698
|
-
{
|
|
699
|
-
event: helloWorld.events.onError,
|
|
700
|
-
async run(event, deps) {
|
|
701
|
-
event.data.error; // read the error that happened during execution
|
|
702
|
-
},
|
|
703
|
-
},
|
|
850
|
+
register: [
|
|
851
|
+
helloWorld,
|
|
852
|
+
beforeHelloWorldTask,
|
|
853
|
+
afterHelloWorldTask,
|
|
854
|
+
helloWorldErrorTask,
|
|
704
855
|
],
|
|
705
856
|
});
|
|
706
857
|
|
|
858
|
+
// Run the app
|
|
707
859
|
run(app);
|
|
708
860
|
```
|
|
709
861
|
|
|
@@ -712,42 +864,56 @@ run(app);
|
|
|
712
864
|
```ts
|
|
713
865
|
import { task, run, event } from "@bluelibs/runner";
|
|
714
866
|
|
|
715
|
-
|
|
716
|
-
pricePerSubscription: 9.99,
|
|
717
|
-
};
|
|
718
|
-
|
|
867
|
+
// Define the resource
|
|
719
868
|
const businessConfig = resource({
|
|
720
|
-
id: "app.
|
|
721
|
-
async init() {
|
|
722
|
-
|
|
869
|
+
id: "app.businessConfig",
|
|
870
|
+
async init(config) {
|
|
871
|
+
// Business logic to initialize config
|
|
872
|
+
return { value: "Business Configuration Loaded" };
|
|
873
|
+
},
|
|
874
|
+
});
|
|
875
|
+
|
|
876
|
+
// Define tasks for handling events beforeInit, afterInit, and onError
|
|
877
|
+
|
|
878
|
+
const beforeInitTask = task({
|
|
879
|
+
id: "app.businessConfig.beforeInit",
|
|
880
|
+
on: businessConfig.events.beforeInit, // Listening to beforeInit event
|
|
881
|
+
async run(event) {
|
|
882
|
+
const config = event.data.config; // Handle the config input before resource initialization
|
|
883
|
+
console.log("Before init:", config);
|
|
884
|
+
},
|
|
885
|
+
});
|
|
886
|
+
|
|
887
|
+
const afterInitTask = task({
|
|
888
|
+
id: "app.businessConfig.afterInit",
|
|
889
|
+
on: businessConfig.events.afterInit, // Listening to afterInit event
|
|
890
|
+
async run(event) {
|
|
891
|
+
const value = event.data.value; // Handle the return value after resource initialization
|
|
892
|
+
console.log("After init:", value);
|
|
893
|
+
},
|
|
894
|
+
});
|
|
895
|
+
|
|
896
|
+
const businessConfigErrorTask = task({
|
|
897
|
+
id: "app.businessConfig.onError",
|
|
898
|
+
on: businessConfig.events.onError, // Listening to onError event
|
|
899
|
+
async run(event) {
|
|
900
|
+
const error = event.data.error; // Handle errors during resource initialization
|
|
901
|
+
console.error("Error during initialization:", error);
|
|
723
902
|
},
|
|
724
903
|
});
|
|
725
904
|
|
|
905
|
+
// Register all tasks and the businessConfig resource to the app
|
|
726
906
|
const app = resource({
|
|
727
907
|
id: "app",
|
|
728
|
-
register: [
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
event.data.config; // read the input
|
|
734
|
-
},
|
|
735
|
-
},
|
|
736
|
-
{
|
|
737
|
-
event: businessConfig.events.afterInit,
|
|
738
|
-
async run(event, deps) {
|
|
739
|
-
event.data.value; // you can read the returned value of the resource
|
|
740
|
-
},
|
|
741
|
-
},
|
|
742
|
-
{
|
|
743
|
-
event: businessConfig.events.onError,
|
|
744
|
-
async run(event, deps) {
|
|
745
|
-
event.data.error; // read the error that happened during initialization
|
|
746
|
-
},
|
|
747
|
-
},
|
|
908
|
+
register: [
|
|
909
|
+
businessConfig,
|
|
910
|
+
beforeInitTask,
|
|
911
|
+
afterInitTask,
|
|
912
|
+
businessConfigErrorTask,
|
|
748
913
|
],
|
|
749
914
|
});
|
|
750
915
|
|
|
916
|
+
// Run the app
|
|
751
917
|
run(app);
|
|
752
918
|
```
|
|
753
919
|
|
|
@@ -843,7 +1009,7 @@ const app = resource({
|
|
|
843
1009
|
});
|
|
844
1010
|
```
|
|
845
1011
|
|
|
846
|
-
However, other resources might need to modify this dynamically as extensions. This is where
|
|
1012
|
+
However, other resources might need to modify this dynamically as extensions. This is where events become valuable.
|
|
847
1013
|
|
|
848
1014
|
```ts
|
|
849
1015
|
import { resource, run, event } from "@bluelibs/runner";
|
|
@@ -853,35 +1019,27 @@ type SecurityOptions = {
|
|
|
853
1019
|
};
|
|
854
1020
|
|
|
855
1021
|
const securityResource = resource({
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
1022
|
+
/* Same as above, but create a setHasher method */
|
|
1023
|
+
});
|
|
1024
|
+
const afterSecurityInitTask = task({
|
|
1025
|
+
id: "app.security.afterInit",
|
|
1026
|
+
on: securityResource.events.afterInit, // Listening to afterInit event
|
|
1027
|
+
async run(event, deps) {
|
|
1028
|
+
const { config, value } = event.data;
|
|
1029
|
+
const security = value;
|
|
1030
|
+
|
|
1031
|
+
// Custom hasher implementation
|
|
1032
|
+
security.setHasher((input) => {
|
|
1033
|
+
// Implement custom hashing logic here
|
|
1034
|
+
console.log("Hashing input:", input);
|
|
1035
|
+
});
|
|
865
1036
|
},
|
|
866
1037
|
});
|
|
867
1038
|
|
|
1039
|
+
// Register the security resource and the afterInit task in the app
|
|
868
1040
|
const app = resource({
|
|
869
1041
|
id: "app",
|
|
870
|
-
register: [securityResource],
|
|
871
|
-
hooks: [
|
|
872
|
-
{
|
|
873
|
-
// careful when you listen on such events and need dependencies, you might not have them computed yet due to how early these events happen in the system.
|
|
874
|
-
event: securityResource.events.afterInit,
|
|
875
|
-
async run(event, deps) {
|
|
876
|
-
const { config, value } = event.data;
|
|
877
|
-
const security = value;
|
|
878
|
-
|
|
879
|
-
security.setHasher((input) => {
|
|
880
|
-
// custom implementation here.
|
|
881
|
-
});
|
|
882
|
-
},
|
|
883
|
-
},
|
|
884
|
-
],
|
|
1042
|
+
register: [securityResource, afterSecurityInitTask],
|
|
885
1043
|
});
|
|
886
1044
|
```
|
|
887
1045
|
|
|
@@ -910,18 +1068,21 @@ const securityResource = resource({
|
|
|
910
1068
|
},
|
|
911
1069
|
});
|
|
912
1070
|
|
|
1071
|
+
// Define securityResource and securityConfigurationPhaseEvent as needed
|
|
1072
|
+
|
|
1073
|
+
const securityConfigTask = task({
|
|
1074
|
+
id: "app.security.config",
|
|
1075
|
+
on: securityConfigurationPhaseEvent, // Listening to securityConfigurationPhaseEvent
|
|
1076
|
+
async run(event, deps) {
|
|
1077
|
+
const { config } = event.data; // config is SecurityOptions
|
|
1078
|
+
config.setHasher(newHashFunction); // Apply the new hash function
|
|
1079
|
+
},
|
|
1080
|
+
});
|
|
1081
|
+
|
|
1082
|
+
// Register the security resource and configuration task in the app
|
|
913
1083
|
const app = resource({
|
|
914
1084
|
id: "app",
|
|
915
|
-
register: [securityResource],
|
|
916
|
-
hooks: [
|
|
917
|
-
{
|
|
918
|
-
event: securityConfigurationPhaseEvent,
|
|
919
|
-
async run(event, deps) {
|
|
920
|
-
const { config } = event.data; // config is SecurityOptions
|
|
921
|
-
config.setHasher(newHashFunction);
|
|
922
|
-
},
|
|
923
|
-
},
|
|
924
|
-
],
|
|
1085
|
+
register: [securityResource, securityConfigTask],
|
|
925
1086
|
});
|
|
926
1087
|
```
|
|
927
1088
|
|
|
@@ -1018,24 +1179,6 @@ const app = resource({
|
|
|
1018
1179
|
// Now your app will print all logs
|
|
1019
1180
|
```
|
|
1020
1181
|
|
|
1021
|
-
You can also achieve this using hooks:
|
|
1022
|
-
|
|
1023
|
-
```ts
|
|
1024
|
-
resource({
|
|
1025
|
-
id: "root",
|
|
1026
|
-
hooks: [
|
|
1027
|
-
{
|
|
1028
|
-
// after logger gets initialised as a resource, I'm going to set the print threshold
|
|
1029
|
-
event: logger.events.afterInit,
|
|
1030
|
-
async run(event) {
|
|
1031
|
-
const logger = event.data; // do not depend on the logger
|
|
1032
|
-
logger.setPrintThreshold("trace");
|
|
1033
|
-
},
|
|
1034
|
-
},
|
|
1035
|
-
],
|
|
1036
|
-
});
|
|
1037
|
-
```
|
|
1038
|
-
|
|
1039
1182
|
The logger’s log() function is asynchronous because it handles events. If you want to prevent your system from waiting for log operations to complete, simply omit the await when calling log(). This is useful if you have listeners that send logs to external log storage systems.
|
|
1040
1183
|
|
|
1041
1184
|
Additionally, there is a `global.events.log` event available. You can use this event both to emit log messages and to listen for all log activities.
|
package/dist/define.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ITask, ITaskDefinition, IResource, IResourceWithConfig, IResourceDefinition, IEventDefinition, IMiddlewareDefinition, DependencyMapType, IMiddleware, IEventDefinitionConfig } from "./defs";
|
|
2
|
-
export declare function defineTask<Input = undefined, Output extends Promise<any> = any, Deps extends DependencyMapType = any,
|
|
2
|
+
export declare function defineTask<Input = undefined, Output extends Promise<any> = any, Deps extends DependencyMapType = any, TOn extends "*" | IEventDefinition | undefined = undefined>(taskConfig: ITaskDefinition<Input, Output, Deps, TOn>): ITask<Input, Output, Deps, TOn>;
|
|
3
3
|
export declare function defineResource<TConfig = void, TValue = any, TDeps extends DependencyMapType = {}, THooks = any>(constConfig: IResourceDefinition<TConfig, TValue, TDeps, THooks>): IResource<TConfig, TValue, TDeps>;
|
|
4
4
|
export declare function defineEvent<TPayload = any>(config: IEventDefinitionConfig<TPayload>): IEventDefinition<TPayload>;
|
|
5
5
|
export declare function defineMiddleware<TDeps extends DependencyMapType = {}>(config: IMiddlewareDefinition<TDeps>): IMiddleware<TDeps>;
|
package/dist/define.js
CHANGED
|
@@ -39,7 +39,6 @@ function defineResource(constConfig) {
|
|
|
39
39
|
[defs_1.symbols.resource]: true,
|
|
40
40
|
id: constConfig.id,
|
|
41
41
|
dependencies: constConfig.dependencies,
|
|
42
|
-
hooks: constConfig.hooks || [],
|
|
43
42
|
dispose: constConfig.dispose,
|
|
44
43
|
register: constConfig.register || [],
|
|
45
44
|
overrides: constConfig.overrides || [],
|
package/dist/define.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"define.js","sourceRoot":"","sources":["../src/define.ts"],"names":[],"mappings":";;AAmBA,gCA6BC;AAED,
|
|
1
|
+
{"version":3,"file":"define.js","sourceRoot":"","sources":["../src/define.ts"],"names":[],"mappings":"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"}
|
package/dist/defs.d.ts
CHANGED
|
@@ -25,7 +25,7 @@ export interface IEventMeta extends IMeta {
|
|
|
25
25
|
}
|
|
26
26
|
export interface IMiddlewareMeta extends IMeta {
|
|
27
27
|
}
|
|
28
|
-
export type DependencyMapType = Record<string, ITask<any, any, any> | IResource<any, any, any> | IEventDefinition<any>>;
|
|
28
|
+
export type DependencyMapType = Record<string, ITask<any, any, any, any> | IResource<any, any, any> | IEventDefinition<any>>;
|
|
29
29
|
type ExtractTaskInput<T> = T extends ITask<infer I, any, infer D> ? I : never;
|
|
30
30
|
type ExtractTaskOutput<T> = T extends ITask<any, infer O, infer D> ? O : never;
|
|
31
31
|
type ExtractResourceValue<T> = T extends IResource<any, infer V, infer D> ? V : never;
|
|
@@ -37,22 +37,28 @@ export type DependencyValueType<T> = T extends ITask<any, any, any> ? TaskDepend
|
|
|
37
37
|
export type DependencyValuesType<T extends DependencyMapType> = {
|
|
38
38
|
[K in keyof T]: DependencyValueType<T[K]>;
|
|
39
39
|
};
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
type Optional<T> = {
|
|
41
|
+
[K in keyof T]?: T[K];
|
|
42
|
+
};
|
|
43
|
+
type IsVoid<T> = [T] extends [void] ? true : false;
|
|
44
|
+
type IsOptional<T> = undefined extends T ? true : false;
|
|
45
|
+
type OptionalOrVoidOrAnything<T> = IsVoid<T> extends true ? void : IsOptional<T> extends true ? Optional<T> : T;
|
|
46
|
+
export type RegisterableItems<T = any> = IResourceWithConfig<any> | IResource<void, any, any> | IResource<OptionalOrVoidOrAnything<T>, any, any> | ITaskDefinition<any, any, any, any> | IMiddlewareDefinition<any> | IEventDefinition<any>;
|
|
47
|
+
export interface ITaskDefinition<TInput = any, TOutput extends Promise<any> = any, TDependencies extends DependencyMapType = {}, TOn extends "*" | IEventDefinition<any> | undefined = undefined> {
|
|
42
48
|
id: string;
|
|
43
49
|
dependencies?: TDependencies | (() => TDependencies);
|
|
44
50
|
middleware?: IMiddlewareDefinition[];
|
|
45
51
|
/**
|
|
46
52
|
* Listen to events in a simple way
|
|
47
53
|
*/
|
|
48
|
-
on?:
|
|
54
|
+
on?: TOn;
|
|
49
55
|
/**
|
|
50
56
|
* This makes sense only when `on` is specified to provide the order of the execution.
|
|
51
57
|
* The event with the lowest order will be executed first.
|
|
52
58
|
*/
|
|
53
59
|
listenerOrder?: number;
|
|
54
60
|
meta?: ITaskMeta;
|
|
55
|
-
run: (input:
|
|
61
|
+
run: (input: TOn extends undefined ? TInput : IEvent<ExtractEventParams<TOn>>, dependencies: DependencyValuesType<TDependencies>) => TOutput;
|
|
56
62
|
}
|
|
57
63
|
export type BeforeRunEventPayload<TInput> = {
|
|
58
64
|
input: TInput;
|
|
@@ -78,7 +84,7 @@ export type AfterInitEventPayload<TConfig, TValue> = {
|
|
|
78
84
|
/**
|
|
79
85
|
* This is the response after the definition has been prepared. TODO: better naming?
|
|
80
86
|
*/
|
|
81
|
-
export interface ITask<TInput = any, TOutput extends Promise<any> = any, TDependencies extends DependencyMapType = {},
|
|
87
|
+
export interface ITask<TInput = any, TOutput extends Promise<any> = any, TDependencies extends DependencyMapType = {}, TOn extends "*" | IEventDefinition<any> | undefined = undefined> extends ITaskDefinition<TInput, TOutput, TDependencies, TOn> {
|
|
82
88
|
dependencies: TDependencies | (() => TDependencies);
|
|
83
89
|
computedDependencies?: DependencyValuesType<TDependencies>;
|
|
84
90
|
middleware: IMiddlewareDefinition[];
|
|
@@ -94,7 +100,6 @@ export interface ITask<TInput = any, TOutput extends Promise<any> = any, TDepend
|
|
|
94
100
|
export interface IResourceDefinition<TConfig = any, TValue = unknown, TDependencies extends DependencyMapType = {}, THooks = any, TRegisterableItems = any> {
|
|
95
101
|
id: string;
|
|
96
102
|
dependencies?: TDependencies | ((config: TConfig) => TDependencies);
|
|
97
|
-
hooks?: IHookDefinition<TDependencies, THooks>[] | ((config: TConfig) => IHookDefinition<TDependencies, THooks>[]);
|
|
98
103
|
register?: Array<RegisterableItems> | ((config: TConfig) => Array<RegisterableItems>);
|
|
99
104
|
init?: (config: TConfig, dependencies: DependencyValuesType<TDependencies>) => Promise<TValue>;
|
|
100
105
|
/**
|
|
@@ -121,7 +126,6 @@ export interface IResource<TConfig = void, TValue = any, TDependencies extends D
|
|
|
121
126
|
afterInit: IEventDefinition<AfterInitEventPayload<TConfig, TValue>>;
|
|
122
127
|
onError: IEventDefinition<OnErrorEventPayload>;
|
|
123
128
|
};
|
|
124
|
-
hooks: IHookDefinition<TDependencies>[] | ((config: TConfig) => IHookDefinition<TDependencies>[]);
|
|
125
129
|
overrides: Array<IResource | ITask | IMiddleware | IResourceWithConfig>;
|
|
126
130
|
middleware: IMiddlewareDefinition[];
|
|
127
131
|
}
|