@bluelibs/runner 1.2.0 → 1.3.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 (37) hide show
  1. package/README.md +151 -134
  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 +15 -6
  6. package/dist/globalEvents.d.ts +3 -1
  7. package/dist/globalEvents.js.map +1 -1
  8. package/dist/index.d.ts +3 -1
  9. package/dist/models/DependencyProcessor.js +12 -5
  10. package/dist/models/DependencyProcessor.js.map +1 -1
  11. package/dist/models/EventManager.d.ts +2 -1
  12. package/dist/models/EventManager.js +47 -21
  13. package/dist/models/EventManager.js.map +1 -1
  14. package/dist/models/ResourceInitializer.d.ts +1 -0
  15. package/dist/models/ResourceInitializer.js +35 -3
  16. package/dist/models/ResourceInitializer.js.map +1 -1
  17. package/dist/models/Store.d.ts +1 -0
  18. package/dist/models/Store.js +10 -0
  19. package/dist/models/Store.js.map +1 -1
  20. package/dist/models/TaskRunner.js +6 -2
  21. package/dist/models/TaskRunner.js.map +1 -1
  22. package/package.json +1 -1
  23. package/src/__tests__/index.ts +1 -0
  24. package/src/__tests__/models/EventManager.test.ts +338 -67
  25. package/src/__tests__/models/ResourceInitializer.test.ts +1 -0
  26. package/src/__tests__/models/TaskRunner.test.ts +4 -2
  27. package/src/__tests__/run.hooks.test.ts +31 -0
  28. package/src/__tests__/run.middleware.test.ts +223 -0
  29. package/src/__tests__/run.test.ts +112 -131
  30. package/src/define.ts +15 -11
  31. package/src/defs.ts +17 -7
  32. package/src/globalEvents.ts +4 -2
  33. package/src/models/DependencyProcessor.ts +17 -8
  34. package/src/models/EventManager.ts +54 -25
  35. package/src/models/ResourceInitializer.ts +49 -4
  36. package/src/models/Store.ts +14 -0
  37. package/src/models/TaskRunner.ts +5 -2
package/README.md CHANGED
@@ -6,9 +6,9 @@
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
7
  </p>
8
8
 
9
- These are the building blocks to create amazing applications. It's a more functional approach to building small and large-scale applications.
9
+ BlueLibs Runner is a framework that provides a functional approach to building applications, whether small or large-scale. Its core concepts include Tasks, Resources, Events, and Middleware. Tasks represent the units of logic, while resources are singletons that provide shared services across the application. Events facilitate communication between different parts of the system, and middleware allows interception and modification of task execution. The framework emphasizes an async-first philosophy, ensuring that all operations are executed asynchronously for smoother application flow.
10
10
 
11
- These are the building blocks:
11
+ ## Building Blocks
12
12
 
13
13
  - **Tasks**: Core units of logic that encapsulate specific tasks. They can depend on resources, other tasks, and event emitters.
14
14
  - **Resources**: Singleton objects providing shared functionality. They can be constants, services, functions. They can depend on other resources, tasks, and event emitters.
@@ -89,7 +89,7 @@ Resources are more like services, they are singletons, they are meant to be used
89
89
 
90
90
  ### Resource dispose()
91
91
 
92
- Resources can have a `dispose()` method that can be used to clean up resources. This is useful for cleaning up resources like closing database connections, etc. You typically want to use this when you have opened pending connections or you need to do some cleanup or a graceful shutdown.
92
+ Resources can have a `dispose()` method that can be used for cleanups. This is useful for cleaning up resources like closing database connections, etc. You typically want to use this when you have opened pending connections or you need to do some cleanup or a graceful shutdown.
93
93
 
94
94
  ```ts
95
95
  import { task, run, resource } from "@bluelibs/runner";
@@ -99,13 +99,14 @@ const dbResource = resource({
99
99
  const db = await connectToDatabase();
100
100
  return db;
101
101
  },
102
+ // the value returned from init() will be passed to dispose()
102
103
  async dispose(db, config, deps) {
103
104
  return db.close();
104
105
  },
105
106
  });
106
107
  ```
107
108
 
108
- If you want to call dispose, you have to do it through the global store.
109
+ If you want to call dispose, you have to do it through the global resource called `store`, as everything is encapsulated.
109
110
 
110
111
  ```ts
111
112
  import { task, run, resource, globals } from "@bluelibs/runner";
@@ -117,6 +118,7 @@ const app = resource({
117
118
  store: globals.resources.store,
118
119
  },
119
120
  async init(_, deps) {
121
+ // We use the fact that we can reuse the value we got from here
120
122
  return {
121
123
  dispose: async () => deps.store.dispose(),
122
124
  };
@@ -128,15 +130,43 @@ const value = await run(app);
128
130
  await value.dispose();
129
131
  ```
130
132
 
131
- ## Encapsulation
133
+ ### Resource with()
132
134
 
133
- We want to make sure that our tasks are not dependent on the outside world. This is why we have the `dependencies` object.
135
+ Resources can be configured with a configuration object. This is useful when you want to pass in configuration to them. For example, you're building a library and you're initialising a mailer service, you can pass in the SMTP credentials as a configuration.
134
136
 
135
- You cannot call on an task outside from dependencies. And not only that, it has to be explicitly registered to the container.
137
+ ```ts
138
+ import { task, run, resource } from "@bluelibs/runner";
139
+
140
+ type Config = { smtpUrl: string; defaultFrom: string };
141
+ const emailerResource = resource({
142
+ async init(config: Config) {
143
+ // run config checks
144
+ return {
145
+ sendEmail: async (to: string, subject: string, body: string) => {
146
+ // send *email*
147
+ },
148
+ };
149
+ },
150
+ });
151
+
152
+ const app = resource({
153
+ id: "app",
154
+ register: [
155
+ // proper autocompletion is present
156
+ emailerResource.with({ smtpUrl: "smtp://localhost", defaultFrom: "" }),
157
+ ],
158
+ });
159
+ ```
160
+
161
+ If by any chance your main `app` has configs then they will be passed via the second argument of `run`, like this:
162
+
163
+ ```ts
164
+ run(app, config);
165
+ ```
136
166
 
137
167
  ## Dependencies
138
168
 
139
- You can depend on `tasks`, `resources`, `events` and `middleware`.
169
+ You can depend on `tasks`, `resources`, `events` and (indirectly) on `middleware`.
140
170
 
141
171
  ```ts
142
172
  import { task, resource, run, event } from "@bluelibs/runner";
@@ -150,7 +180,7 @@ const helloWorld = task({
150
180
 
151
181
  const app = resource({
152
182
  id: "app",
153
- register: [helloWorld],
183
+ register: [helloWorld, logMiddleware],
154
184
  dependencies: {
155
185
  helloWorld,
156
186
  },
@@ -211,14 +241,14 @@ const helloTask = task({
211
241
  },
212
242
  });
213
243
 
214
- const root = resource({
244
+ const app = resource({
215
245
  id: "app",
216
246
  register: [afterRegisterEvent, helloTask],
217
247
  dependencies: {
218
248
  afterRegisterEvent,
219
249
  },
220
250
  async init(_, deps) {
221
- deps.afterRegisterEvent({ userId: "XXX" });
251
+ await deps.afterRegisterEvent({ userId: "XXX" });
222
252
  },
223
253
  });
224
254
  ```
@@ -242,6 +272,7 @@ const root = resource({
242
272
  {
243
273
  event: global.events.afterInit,
244
274
  async run(event, deps) {
275
+ // both dependencies and event are properly infered through typescript
245
276
  console.log("User has been registered!");
246
277
  },
247
278
  },
@@ -252,16 +283,55 @@ const root = resource({
252
283
  });
253
284
  ```
254
285
 
286
+ ### hooks wildcard
287
+
288
+ You can listen to all events by using the wildcard `*`.
289
+
290
+ ```ts
291
+ import { task, resource, run, event, global } from "@bluelibs/runner";
292
+
293
+ const afterRegisterEvent = event<{ userId: string }>({
294
+ id: "app.user.registered",
295
+ });
296
+
297
+ const root = resource({
298
+ id: "app",
299
+ register: [afterRegisterEvent],
300
+ dependencies: {},
301
+ hooks: [
302
+ {
303
+ event: "*",
304
+ async run(event, deps) {
305
+ console.log(
306
+ "Generic event detected",
307
+ event.id,
308
+ event.data,
309
+ event.timestamp
310
+ );
311
+ },
312
+ },
313
+ ],
314
+ async init(_, deps) {
315
+ deps.afterRegisterEvent({ userId: "XXX" });
316
+ },
317
+ });
318
+ ```
319
+
255
320
  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.
256
321
 
257
322
  The hooks from a `resource` are mostly used for configuration, and blending in the system.
258
323
 
324
+ ### When to use either?
325
+
326
+ - `hooks` are for resources to extend each other, compose functionalities, they are mostly used for configuration and blending in the system.
327
+ - `on` is for when you want to perform a task when something happens.
328
+
259
329
  ## Middleware
260
330
 
261
- Middleware is a way to intercept the execution of tasks. It's a powerful way to add additional functionality to your tasks. First middleware that gets registered is the first that runs, the last middleware that runs is 'closest' to the task, most likely the last element inside `middleware` array at task level.
331
+ Middleware is a way to intercept the execution of tasks or initialization of resources. It's a powerful way to add additional functionality. First middleware that gets registered is the first that runs, giving it a form of priority, the last middleware that runs is 'closest' to the task, most likely the last element inside `middleware` array at task level.
262
332
 
263
333
  ```ts
264
- import { task, run, event } from "@bluelibs/runner";
334
+ import { task, resource, run, event } from "@bluelibs/runner";
265
335
 
266
336
  const logMiddleware = middleware({
267
337
  id: "app.middleware.log",
@@ -269,11 +339,18 @@ const logMiddleware = middleware({
269
339
  // inject tasks, resources, eventCallers here.
270
340
  },
271
341
  async run(data, deps) {
272
- const { taskDefinition, next, input } = data;
273
-
274
- console.log("Before task", taskDefinition.id);
275
- const result = await next(input); // pass the input to the next middleware or task
276
- console.log("After task", taskDefinition.id);
342
+ const { taskDefinition, resourceDefinition, config, next, input } = data;
343
+
344
+ // The middleware can be for a task or a resource, depending on which you get the right elements.
345
+ if (taskDefinition) {
346
+ console.log("Before task", taskDefinition.id);
347
+ const result = await next(input); // pass the input to the next middleware or task
348
+ console.log("After task", taskDefinition.id);
349
+ } else {
350
+ console.log("Before resource", resourceDefinition.id);
351
+ const result = await next(config); // pass the input to the next middleware or task
352
+ console.log("After resource", resourceDefinition.id);
353
+ }
277
354
 
278
355
  return result;
279
356
  },
@@ -288,34 +365,14 @@ const helloTask = task({
288
365
  });
289
366
  ```
290
367
 
291
- You can use middleware creators (function that returns) for configurable middlewares such as:
292
-
293
- ```ts
294
- import { middleware } from "@bluelibs/runner";
295
-
296
- function createLogMiddleware(config) {
297
- return middleware({
298
- // your config-based middleware here.
299
- });
300
- }
301
- ```
302
-
303
- However, if you want to register a middleware for all tasks, here's how you can do it:
368
+ However, if you want to register a middleware for all tasks and resources, here's how you can do it:
304
369
 
305
370
  ```ts
306
371
  import { run, resource } from "@bluelibs/runner";
307
372
 
308
373
  const logMiddleware = middleware({
309
374
  id: "app.middleware.log",
310
- async run(data, deps) {
311
- const { taskDefinition, next, input } = data;
312
-
313
- console.log("Before task", task.id);
314
- const result = await next(input);
315
- console.log("After task", task.id);
316
-
317
- return result;
318
- },
375
+ // ... rest
319
376
  });
320
377
 
321
378
  const root = resource({
@@ -326,20 +383,9 @@ const root = resource({
326
383
 
327
384
  The middleware can only be registered once. This means that if you register a middleware as global, you cannot specify it as a task middleware.
328
385
 
329
- ### Middleware for resources
330
-
331
- Unfortunately, middleware for resources is not supported at the moment. The main reason for this is simplicity and the fact that resources are not meant to be executed, but rather to be initialized.
332
-
333
- You have access to the global events if you want to hook into the initialisation system.
334
-
335
- ### When to use either?
336
-
337
- - `hooks` are for resources to extend each other, compose functionalities, they are mostly used for configuration and blending in the system.
338
- - `on` is for when you want to perform a task when something happens.
339
-
340
386
  ## Errors
341
387
 
342
- If an error is thrown in a task, the error will be propagated up.
388
+ If an error is thrown in a task, the error will be propagated up to the top runner.
343
389
 
344
390
  ```ts
345
391
  import { task, run, event } from "@bluelibs/runner";
@@ -362,7 +408,9 @@ const app = resource({
362
408
  },
363
409
  });
364
410
 
365
- run(app);
411
+ run(app).catch((err) => {
412
+ console.error(err);
413
+ });
366
414
  ```
367
415
 
368
416
  You can listen to errors via events:
@@ -371,8 +419,11 @@ You can listen to errors via events:
371
419
  const helloWorld = task({
372
420
  id: "app.onError",
373
421
  on: helloWorld.events.onError,
374
- run({ error, input }, deps) {
422
+ run({ error, input, suppress }, deps) {
375
423
  // this will be called when an error happens
424
+
425
+ // if you handled the error, and you don't want it propagated to the top, supress the propagation.
426
+ suppress();
376
427
  },
377
428
  });
378
429
  ```
@@ -397,7 +448,7 @@ const helloWorld = task({
397
448
  });
398
449
  ```
399
450
 
400
- This is particularly helpful to use in conjunction with global middlewares, or global events, etc.
451
+ This is particularly helpful to use in conjunction with global middlewares, or global events, they can read some meta tag definition and act accordingly.
401
452
 
402
453
  The interfaces look like this:
403
454
 
@@ -495,7 +546,7 @@ Now you can freely use any of the tasks, resources, events, and middlewares from
495
546
 
496
547
  This approach is very powerful when you have multiple packages and you want to compose them together.
497
548
 
498
- ## Real world usage.
549
+ ## Real world examples
499
550
 
500
551
  Typically you have an express server (to handle HTTP requests), a database, and a bunch of services. You can define all of these in a single file and run them.
501
552
 
@@ -570,47 +621,7 @@ const app = resource({
570
621
  run();
571
622
  ```
572
623
 
573
- ### Resources can receive configs
574
-
575
- Resources are super configurable.
576
-
577
- ```ts
578
- import { resource, run } from "@bluelibs/runner";
579
-
580
- type EmailerOptions = {
581
- smtpUrl: string;
582
- defaultFrom: string;
583
- };
584
-
585
- const emailerResource = resource({
586
- id: "app.config",
587
- async init(config: EmailerOptions) {
588
- return {
589
- sendEmail: async (to: string, subject: string, body: string) => {
590
- // send *email*
591
- },
592
- };
593
- // or return some service that sends email
594
- },
595
- });
596
-
597
- const app = resource({
598
- id: "app",
599
- register: [
600
- // You can pass the config here
601
- emailerResource.with({
602
- smtpUrl: "smtp://localhost",
603
- defaultFrom: "",
604
- }),
605
- // Leaving it simply emailerResource is similar to passing an empty object.
606
- // We leave this for simplicity in some cases but we recommend using .with() for clarity.
607
- ],
608
- });
609
-
610
- run(app);
611
- ```
612
-
613
- ## Useful events
624
+ ## Global Events
614
625
 
615
626
  ### Task level
616
627
 
@@ -650,15 +661,19 @@ const app = resource({
650
661
  run(app);
651
662
  ```
652
663
 
653
- ## Resource level
664
+ ### Business Config
654
665
 
655
666
  ```ts
656
667
  import { task, run, event } from "@bluelibs/runner";
657
668
 
669
+ const businessData = {
670
+ pricePerSubscription: 9.99,
671
+ };
672
+
658
673
  const businessConfig = resource({
659
674
  id: "app.config",
660
675
  async init() {
661
- return businessData;
676
+ return businessData; // if you use it as a const you will have full typesafety
662
677
  },
663
678
  });
664
679
 
@@ -690,10 +705,12 @@ const app = resource({
690
705
  run(app);
691
706
  ```
692
707
 
693
- ## Moving further
708
+ ### Moving further
694
709
 
695
710
  This is just a "language" of developing applications. It simplifies dependency injection to the barebones, it forces you to think more functional and use classes less.
696
711
 
712
+ This doesn't mean you shouldn't use classes, just not for hooking things up together.
713
+
697
714
  You can add many services or external things into the runner ecosystem with things like:
698
715
 
699
716
  ```ts
@@ -743,7 +760,7 @@ const app = resource({
743
760
  run(app);
744
761
  ```
745
762
 
746
- ## Inter-communication between resources
763
+ ### Inter-communication between resources
747
764
 
748
765
  By stating dependencies you often don't care about the initialisation order, but sometimes you really do, for example, let's imagine a security service that allows you to inject a custom hashing function let's say to shift from md5 to sha256.
749
766
 
@@ -829,6 +846,39 @@ const app = resource({
829
846
  });
830
847
  ```
831
848
 
849
+ ## Overrides
850
+
851
+ Previously, we explored how we can extend functionality through events. However, sometimes you want to override a resource with a new one or simply swap out a task or a middleware that you import from another package and they don't offer the ability.
852
+
853
+ ```ts
854
+ import { resource, run, event } from "@bluelibs/runner";
855
+
856
+ // This example is for resources but override works for tasks, events, and middleware as well.
857
+ const securityResource = resource({
858
+ id: "app.security",
859
+ async init() {
860
+ // returns a security service
861
+ },
862
+ });
863
+
864
+ const override = resource({
865
+ ...securityResource,
866
+ init: async () => {
867
+ // a new and custom service
868
+ },
869
+ });
870
+
871
+ const app = resource({
872
+ id: "app",
873
+ register: [securityResource], // this resource might be registered by any element in the dependency tree.
874
+ overrides: [override],
875
+ });
876
+ ```
877
+
878
+ Now the `securityResource` will be overriden by the new one and whenever it's used it will use the new one.
879
+
880
+ Overrides can only happen once and only if the overriden resource is registered. If two resources try to override the same resource, an error will be thrown.
881
+
832
882
  ## Logging
833
883
 
834
884
  We expose through globals a logger that you can use to log things.
@@ -891,39 +941,6 @@ You can in theory do it in `hooks` as well, but as specified `hooks` are mostly
891
941
 
892
942
  The logger's `log()` function is async as it works with events. If you don't want your system hanging on logs, simply omit the `await`
893
943
 
894
- ## Overrides
895
-
896
- Previously, we explored how we can extend functionality through events. However, sometimes you want to override a resource with a new one or simply swap out a task or a middleware that you import from another package and they don't offer the ability.
897
-
898
- ```ts
899
- import { resource, run, event } from "@bluelibs/runner";
900
-
901
- // This example is for resources but override works for tasks, events, and middleware as well.
902
- const securityResource = resource({
903
- id: "app.security",
904
- async init() {
905
- // returns a security service
906
- },
907
- });
908
-
909
- const override = resource({
910
- ...securityResource,
911
- init: async () => {
912
- // a new and custom service
913
- },
914
- });
915
-
916
- const app = resource({
917
- id: "app",
918
- register: [securityResource], // this resource might be registered by any element in the dependency tree.
919
- overrides: [override],
920
- });
921
- ```
922
-
923
- Now the `securityResource` will be overriden by the new one and whenever it's used it will use the new one.
924
-
925
- Overrides can only happen once and only if the overriden resource is registered. If two resources try to override the same resource, an error will be thrown.
926
-
927
944
  ## Testing
928
945
 
929
946
  ### Unit Testing
package/dist/define.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { ITask, ITaskDefinition, IResource, IResourceWithConfig, IResourceDefinintion, IEventDefinition, IMiddlewareDefinition, DependencyMapType, IMiddleware } from "./defs";
2
- export declare function defineTask<Input = undefined, Output extends Promise<any> = any, Deps extends DependencyMapType = any, Test = any>(config: ITaskDefinition<Input, Output, Deps, Test>): ITask<Input, Output, Deps, Test>;
3
- export declare function defineResource<TConfig = void, TValue = any, TDeps extends DependencyMapType = {}>(constConfig: IResourceDefinintion<TConfig, TValue, TDeps>): IResource<TConfig, TValue, TDeps>;
2
+ export declare function defineTask<Input = undefined, Output extends Promise<any> = any, Deps extends DependencyMapType = any, Test = any>(taskConfig: ITaskDefinition<Input, Output, Deps, Test>): ITask<Input, Output, Deps, Test>;
3
+ export declare function defineResource<TConfig = void, TValue = any, TDeps extends DependencyMapType = {}, THooks = any>(constConfig: IResourceDefinintion<TConfig, TValue, TDeps, THooks>): IResource<TConfig, TValue, TDeps>;
4
4
  export declare function defineEvent<TPayload = any>(config: IEventDefinition<TPayload>): IEventDefinition<TPayload>;
5
5
  export declare function defineMiddleware<TDeps extends DependencyMapType = {}>(config: IMiddlewareDefinition<TDeps>): IMiddleware<TDeps>;
6
6
  export declare function isTask(definition: any): definition is ITask;
package/dist/define.js CHANGED
@@ -11,25 +11,26 @@ exports.isEvent = isEvent;
11
11
  exports.isMiddleware = isMiddleware;
12
12
  const defs_1 = require("./defs");
13
13
  const errors_1 = require("./errors");
14
- function defineTask(config) {
14
+ function defineTask(taskConfig) {
15
15
  return {
16
16
  [defs_1.symbols.task]: true,
17
- id: config.id,
18
- dependencies: config.dependencies || {},
19
- middleware: config.middleware || [],
20
- run: config.run,
21
- on: config.on,
17
+ id: taskConfig.id,
18
+ dependencies: taskConfig.dependencies || {},
19
+ middleware: taskConfig.middleware || [],
20
+ run: taskConfig.run,
21
+ on: taskConfig.on,
22
22
  events: {
23
23
  beforeRun: defineEvent({
24
- id: `${config.id}.beforeRun`,
24
+ id: `${taskConfig.id}.beforeRun`,
25
25
  }),
26
26
  afterRun: defineEvent({
27
- id: `${config.id}.afterRun`,
27
+ id: `${taskConfig.id}.afterRun`,
28
28
  }),
29
29
  onError: defineEvent({
30
- id: `${config.id}.onError`,
30
+ id: `${taskConfig.id}.onError`,
31
31
  }),
32
32
  },
33
+ meta: taskConfig.meta || {},
33
34
  // autorun,
34
35
  };
35
36
  }
@@ -61,6 +62,8 @@ function defineResource(constConfig) {
61
62
  id: `${constConfig.id}.onError`,
62
63
  }),
63
64
  },
65
+ meta: constConfig.meta || {},
66
+ middleware: constConfig.middleware || [],
64
67
  };
65
68
  }
66
69
  function defineEvent(config) {
@@ -1 +1 @@
1
- {"version":3,"file":"define.js","sourceRoot":"","sources":["../src/define.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"define.js","sourceRoot":"","sources":["../src/define.ts"],"names":[],"mappings":";;AAiBA,gCA6BC;AAED,wCAuCC;AAED,kCAOC;AAED,4CAqBC;AAED,wBAEC;AAED,gCAEC;AAED,oDAIC;AAED,0BAEC;AAED,oCAEC;AA7ID,iCAcgB;AAChB,qCAAkC;AAElC,SAAgB,UAAU,CAMxB,UAAsD;IAEtD,OAAO;QACL,CAAC,cAAO,CAAC,IAAI,CAAC,EAAE,IAAI;QACpB,EAAE,EAAE,UAAU,CAAC,EAAE;QACjB,YAAY,EAAE,UAAU,CAAC,YAAY,IAAK,EAAW;QACrD,UAAU,EAAE,UAAU,CAAC,UAAU,IAAI,EAAE;QACvC,GAAG,EAAE,UAAU,CAAC,GAAG;QACnB,EAAE,EAAE,UAAU,CAAC,EAAE;QACjB,MAAM,EAAE;YACN,SAAS,EAAE,WAAW,CAAC;gBACrB,EAAE,EAAE,GAAG,UAAU,CAAC,EAAE,YAAY;aACjC,CAAC;YACF,QAAQ,EAAE,WAAW,CAAC;gBACpB,EAAE,EAAE,GAAG,UAAU,CAAC,EAAE,WAAW;aAChC,CAAC;YACF,OAAO,EAAE,WAAW,CAAC;gBACnB,EAAE,EAAE,GAAG,UAAU,CAAC,EAAE,UAAU;aAC/B,CAAC;SACH;QACD,IAAI,EAAE,UAAU,CAAC,IAAI,IAAI,EAAE;QAC3B,WAAW;KACZ,CAAC;AACJ,CAAC;AAED,SAAgB,cAAc,CAM5B,WAAiE;IAEjE,OAAO;QACL,CAAC,cAAO,CAAC,QAAQ,CAAC,EAAE,IAAI;QACxB,EAAE,EAAE,WAAW,CAAC,EAAE;QAClB,YAAY,EAAE,WAAW,CAAC,YAAY;QACtC,KAAK,EAAE,WAAW,CAAC,KAAK,IAAI,EAAE;QAC9B,OAAO,EAAE,WAAW,CAAC,OAAO;QAC5B,QAAQ,EAAE,WAAW,CAAC,QAAQ,IAAI,EAAE;QACpC,SAAS,EAAE,WAAW,CAAC,SAAS,IAAI,EAAE;QACtC,IAAI,EAAE,WAAW,CAAC,IAAI;QACtB,IAAI,EAAE,UAAU,MAAe;YAC7B,OAAO;gBACL,CAAC,cAAO,CAAC,kBAAkB,CAAC,EAAE,IAAI;gBAClC,QAAQ,EAAE,IAAI;gBACd,MAAM;aACP,CAAC;QACJ,CAAC;QAED,MAAM,EAAE;YACN,UAAU,EAAE,WAAW,CAAC;gBACtB,EAAE,EAAE,GAAG,WAAW,CAAC,EAAE,aAAa;aACnC,CAAC;YACF,SAAS,EAAE,WAAW,CAAC;gBACrB,EAAE,EAAE,GAAG,WAAW,CAAC,EAAE,YAAY;aAClC,CAAC;YACF,OAAO,EAAE,WAAW,CAAC;gBACnB,EAAE,EAAE,GAAG,WAAW,CAAC,EAAE,UAAU;aAChC,CAAC;SACH;QACD,IAAI,EAAE,WAAW,CAAC,IAAI,IAAI,EAAE;QAC5B,UAAU,EAAE,WAAW,CAAC,UAAU,IAAI,EAAE;KACzC,CAAC;AACJ,CAAC;AAED,SAAgB,WAAW,CACzB,MAAkC;IAElC,OAAO;QACL,CAAC,cAAO,CAAC,KAAK,CAAC,EAAE,IAAI;QACrB,GAAG,MAAM;KACV,CAAC;AACJ,CAAC;AAED,SAAgB,gBAAgB,CAC9B,MAAoC;IAEpC,MAAM,MAAM,GAAG;QACb,CAAC,cAAO,CAAC,UAAU,CAAC,EAAE,IAAI;QAC1B,GAAG,MAAM;QACT,YAAY,EAAE,MAAM,CAAC,YAAY,IAAK,EAAY;KACnD,CAAC;IAEF,OAAO;QACL,GAAG,MAAM;QACT,MAAM;YACJ,OAAO;gBACL,GAAG,MAAM;gBACT,CAAC,cAAO,CAAC,gBAAgB,CAAC,EAAE,IAAI;gBAChC,MAAM;oBACJ,MAAM,eAAM,CAAC,uBAAuB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gBAClD,CAAC;aACF,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC;AAED,SAAgB,MAAM,CAAC,UAAe;IACpC,OAAO,UAAU,IAAI,UAAU,CAAC,cAAO,CAAC,IAAI,CAAC,CAAC;AAChD,CAAC;AAED,SAAgB,UAAU,CAAC,UAAe;IACxC,OAAO,UAAU,IAAI,UAAU,CAAC,cAAO,CAAC,QAAQ,CAAC,CAAC;AACpD,CAAC;AAED,SAAgB,oBAAoB,CAClC,UAAe;IAEf,OAAO,UAAU,IAAI,UAAU,CAAC,cAAO,CAAC,kBAAkB,CAAC,CAAC;AAC9D,CAAC;AAED,SAAgB,OAAO,CAAC,UAAe;IACrC,OAAO,UAAU,IAAI,UAAU,CAAC,cAAO,CAAC,KAAK,CAAC,CAAC;AACjD,CAAC;AAED,SAAgB,YAAY,CAAC,UAAe;IAC1C,OAAO,UAAU,IAAI,UAAU,CAAC,cAAO,CAAC,UAAU,CAAC,CAAC;AACtD,CAAC"}
package/dist/defs.d.ts CHANGED
@@ -9,7 +9,7 @@ export declare const symbols: {
9
9
  export interface IMeta {
10
10
  title?: string;
11
11
  description?: string;
12
- tags: string[];
12
+ tags?: string[];
13
13
  }
14
14
  export interface ITaskMeta extends IMeta {
15
15
  }
@@ -44,6 +44,10 @@ export type AfterRunEventPayload<TInput, TOutput> = {
44
44
  };
45
45
  export type OnErrorEventPayload = {
46
46
  error: any;
47
+ /**
48
+ * This function can be called to suppress the error from being thrown.
49
+ */
50
+ suppress(): void;
47
51
  };
48
52
  export type BeforeInitEventPayload<TConfig> = {
49
53
  config: TConfig;
@@ -68,10 +72,10 @@ export interface ITask<TInput = any, TOutput extends Promise<any> = any, TDepend
68
72
  onError: IEventDefinition<OnErrorEventPayload>;
69
73
  };
70
74
  }
71
- export interface IResourceDefinintion<TConfig = void, TValue = unknown, TDependencies extends DependencyMapType = {}> {
75
+ export interface IResourceDefinintion<TConfig = void, TValue = unknown, TDependencies extends DependencyMapType = {}, THooks = any> {
72
76
  id: string;
73
77
  dependencies?: TDependencies | ((config: TConfig) => TDependencies);
74
- hooks?: IHookDefinition<TDependencies>[] | ((config: TConfig) => IHookDefinition<TDependencies>[]);
78
+ hooks?: IHookDefinition<TDependencies, THooks>[] | ((config: TConfig) => IHookDefinition<TDependencies, THooks>[]);
75
79
  register?: Array<RegisterableItems> | ((config: TConfig) => Array<RegisterableItems>);
76
80
  init?: (config: TConfig, dependencies: DependencyValuesType<TDependencies>) => Promise<TValue>;
77
81
  /**
@@ -85,6 +89,7 @@ export interface IResourceDefinintion<TConfig = void, TValue = unknown, TDepende
85
89
  dispose?: (value: TValue, config: TConfig, dependencies: DependencyValuesType<TDependencies>) => Promise<TValue>;
86
90
  meta?: IResourceMeta;
87
91
  overrides?: Array<IResource | ITask | IMiddleware | IResourceWithConfig>;
92
+ middleware?: IMiddlewareDefinition[];
88
93
  }
89
94
  export interface IResource<TConfig = void, TValue = any, TDependencies extends DependencyMapType = any> extends IResourceDefinintion<TConfig, TValue, TDependencies> {
90
95
  with(config: TConfig): IResourceWithConfig<TConfig, TValue, TDependencies>;
@@ -99,6 +104,7 @@ export interface IResource<TConfig = void, TValue = any, TDependencies extends D
99
104
  };
100
105
  hooks: IHookDefinition<TDependencies>[] | ((config: TConfig) => IHookDefinition<TDependencies>[]);
101
106
  overrides: Array<IResource | ITask | IMiddleware | IResourceWithConfig>;
107
+ middleware: IMiddlewareDefinition[];
102
108
  }
103
109
  export interface IResourceWithConfig<TConfig = any, TValue = any, TDependencies extends DependencyMapType = any> {
104
110
  resource: IResource<TConfig, TValue, TDependencies>;
@@ -107,6 +113,7 @@ export interface IResourceWithConfig<TConfig = any, TValue = any, TDependencies
107
113
  export interface IEvent<TPayload = any> {
108
114
  id: string;
109
115
  data: TPayload;
116
+ timestamp: Date;
110
117
  }
111
118
  export type EventHandlerType<T = any> = (event: IEvent<T>) => any | Promise<any>;
112
119
  export interface IEventDefinition<TPayload = void> {
@@ -129,10 +136,12 @@ export interface IMiddlewareDefinitionConfigured<C extends Record<string, any> =
129
136
  }
130
137
  export interface IMiddlewareExecutionInput {
131
138
  taskDefinition?: ITask;
132
- input: any;
133
- next: (input?: any) => Promise<any>;
139
+ resourceDefinition?: IResource;
140
+ config?: any;
141
+ input?: any;
142
+ next: (taskInputOrResourceConfig?: any) => Promise<any>;
134
143
  }
135
144
  export interface IHookDefinition<D extends DependencyMapType = {}, T = any> {
136
- event: IEventDefinition<T>;
145
+ event: "*" | IEventDefinition<T>;
137
146
  run: (event: IEvent<T>, dependencies: DependencyValuesType<D>) => Promise<void> | void;
138
147
  }
@@ -15,7 +15,8 @@ export declare const globalEvents: {
15
15
  output: any;
16
16
  }>;
17
17
  onError: import("./defs").IEventDefinition<{
18
- error: Error;
18
+ error: any;
19
+ suppress: () => void;
19
20
  task: ITask<any, any, any>;
20
21
  }>;
21
22
  };
@@ -31,6 +32,7 @@ export declare const globalEvents: {
31
32
  }>;
32
33
  onError: import("./defs").IEventDefinition<{
33
34
  error: Error;
35
+ suppress: () => void;
34
36
  resource: IResource<any, any, any>;
35
37
  }>;
36
38
  };
@@ -1 +1 @@
1
- {"version":3,"file":"globalEvents.js","sourceRoot":"","sources":["../src/globalEvents.ts"],"names":[],"mappings":";;;AAAA,qCAAuC;AAI1B,QAAA,YAAY,GAAG;IAC1B,UAAU,EAAE,IAAA,oBAAW,EAAC;QACtB,EAAE,EAAE,mBAAmB;KACxB,CAAC;IACF,SAAS,EAAE,IAAA,oBAAW,EAAC;QACrB,EAAE,EAAE,kBAAkB;KACvB,CAAC;IACF,GAAG,EAAE,IAAA,oBAAW,EAAO;QACrB,EAAE,EAAE,YAAY;KACjB,CAAC;IACF,KAAK,EAAE;QACL,SAAS,EAAE,IAAA,oBAAW,EAGnB;YACD,EAAE,EAAE,wBAAwB;SAC7B,CAAC;QACF,QAAQ,EAAE,IAAA,oBAAW,EAIlB;YACD,EAAE,EAAE,uBAAuB;SAC5B,CAAC;QACF,OAAO,EAAE,IAAA,oBAAW,EAGjB;YACD,EAAE,EAAE,sBAAsB;SAC3B,CAAC;KACH;IACD,SAAS,EAAE;QACT,UAAU,EAAE,IAAA,oBAAW,EAGpB;YACD,EAAE,EAAE,6BAA6B;SAClC,CAAC;QACF,SAAS,EAAE,IAAA,oBAAW,EAInB;YACD,EAAE,EAAE,4BAA4B;SACjC,CAAC;QACF,OAAO,EAAE,IAAA,oBAAW,EAGjB;YACD,EAAE,EAAE,0BAA0B;SAC/B,CAAC;KACH;CACF,CAAC;AAEW,QAAA,iBAAiB,GAAG;IAC/B,oBAAY,CAAC,UAAU;IACvB,oBAAY,CAAC,SAAS;IACtB,oBAAY,CAAC,KAAK,CAAC,SAAS;IAC5B,oBAAY,CAAC,KAAK,CAAC,QAAQ;IAC3B,oBAAY,CAAC,KAAK,CAAC,OAAO;IAC1B,oBAAY,CAAC,SAAS,CAAC,UAAU;IACjC,oBAAY,CAAC,SAAS,CAAC,SAAS;IAChC,oBAAY,CAAC,SAAS,CAAC,OAAO;CAC/B,CAAC"}
1
+ {"version":3,"file":"globalEvents.js","sourceRoot":"","sources":["../src/globalEvents.ts"],"names":[],"mappings":";;;AAAA,qCAAuC;AAI1B,QAAA,YAAY,GAAG;IAC1B,UAAU,EAAE,IAAA,oBAAW,EAAC;QACtB,EAAE,EAAE,mBAAmB;KACxB,CAAC;IACF,SAAS,EAAE,IAAA,oBAAW,EAAC;QACrB,EAAE,EAAE,kBAAkB;KACvB,CAAC;IACF,GAAG,EAAE,IAAA,oBAAW,EAAO;QACrB,EAAE,EAAE,YAAY;KACjB,CAAC;IACF,KAAK,EAAE;QACL,SAAS,EAAE,IAAA,oBAAW,EAGnB;YACD,EAAE,EAAE,wBAAwB;SAC7B,CAAC;QACF,QAAQ,EAAE,IAAA,oBAAW,EAIlB;YACD,EAAE,EAAE,uBAAuB;SAC5B,CAAC;QACF,OAAO,EAAE,IAAA,oBAAW,EAIjB;YACD,EAAE,EAAE,sBAAsB;SAC3B,CAAC;KACH;IACD,SAAS,EAAE;QACT,UAAU,EAAE,IAAA,oBAAW,EAGpB;YACD,EAAE,EAAE,6BAA6B;SAClC,CAAC;QACF,SAAS,EAAE,IAAA,oBAAW,EAInB;YACD,EAAE,EAAE,4BAA4B;SACjC,CAAC;QACF,OAAO,EAAE,IAAA,oBAAW,EAIjB;YACD,EAAE,EAAE,0BAA0B;SAC/B,CAAC;KACH;CACF,CAAC;AAEW,QAAA,iBAAiB,GAAG;IAC/B,oBAAY,CAAC,UAAU;IACvB,oBAAY,CAAC,SAAS;IACtB,oBAAY,CAAC,KAAK,CAAC,SAAS;IAC5B,oBAAY,CAAC,KAAK,CAAC,QAAQ;IAC3B,oBAAY,CAAC,KAAK,CAAC,OAAO;IAC1B,oBAAY,CAAC,SAAS,CAAC,UAAU;IACjC,oBAAY,CAAC,SAAS,CAAC,SAAS;IAChC,oBAAY,CAAC,SAAS,CAAC,OAAO;CAC/B,CAAC"}
package/dist/index.d.ts CHANGED
@@ -16,7 +16,8 @@ declare const globals: {
16
16
  output: any;
17
17
  }>;
18
18
  onError: import("./defs").IEventDefinition<{
19
- error: Error;
19
+ error: any;
20
+ suppress: () => void;
20
21
  task: import("./defs").ITask<any, any, any>;
21
22
  }>;
22
23
  };
@@ -32,6 +33,7 @@ declare const globals: {
32
33
  }>;
33
34
  onError: import("./defs").IEventDefinition<{
34
35
  error: Error;
36
+ suppress: () => void;
35
37
  resource: import("./defs").IResource<any, any, any>;
36
38
  }>;
37
39
  };