@bluelibs/runner 3.3.2 → 3.4.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 (76) hide show
  1. package/README.md +491 -74
  2. package/dist/define.d.ts +5 -5
  3. package/dist/define.js +22 -2
  4. package/dist/define.js.map +1 -1
  5. package/dist/defs.d.ts +55 -21
  6. package/dist/defs.js.map +1 -1
  7. package/dist/defs.returnTag.d.ts +36 -0
  8. package/dist/defs.returnTag.js +4 -0
  9. package/dist/defs.returnTag.js.map +1 -0
  10. package/dist/errors.d.ts +60 -10
  11. package/dist/errors.js +103 -12
  12. package/dist/errors.js.map +1 -1
  13. package/dist/globals/globalMiddleware.d.ts +4 -4
  14. package/dist/globals/globalResources.d.ts +28 -10
  15. package/dist/globals/middleware/cache.middleware.d.ts +9 -9
  16. package/dist/globals/resources/queue.resource.d.ts +5 -2
  17. package/dist/index.d.ts +33 -14
  18. package/dist/index.js +2 -1
  19. package/dist/index.js.map +1 -1
  20. package/dist/models/DependencyProcessor.js +4 -4
  21. package/dist/models/DependencyProcessor.js.map +1 -1
  22. package/dist/models/EventManager.js +10 -1
  23. package/dist/models/EventManager.js.map +1 -1
  24. package/dist/models/Logger.d.ts +8 -0
  25. package/dist/models/Logger.js +24 -0
  26. package/dist/models/Logger.js.map +1 -1
  27. package/dist/models/OverrideManager.js +1 -1
  28. package/dist/models/OverrideManager.js.map +1 -1
  29. package/dist/models/ResourceInitializer.d.ts +2 -2
  30. package/dist/models/ResourceInitializer.js.map +1 -1
  31. package/dist/models/Store.d.ts +5 -3
  32. package/dist/models/Store.js +7 -1
  33. package/dist/models/Store.js.map +1 -1
  34. package/dist/models/StoreConstants.d.ts +6 -3
  35. package/dist/models/StoreRegistry.d.ts +5 -3
  36. package/dist/models/StoreRegistry.js +17 -1
  37. package/dist/models/StoreRegistry.js.map +1 -1
  38. package/dist/models/StoreTypes.d.ts +1 -1
  39. package/dist/models/StoreValidator.js +5 -5
  40. package/dist/models/StoreValidator.js.map +1 -1
  41. package/dist/models/TaskRunner.js +10 -0
  42. package/dist/models/TaskRunner.js.map +1 -1
  43. package/dist/run.d.ts +3 -3
  44. package/dist/run.js +1 -1
  45. package/dist/run.js.map +1 -1
  46. package/dist/t1.d.ts +1 -0
  47. package/dist/t1.js +13 -0
  48. package/dist/t1.js.map +1 -0
  49. package/dist/testing.d.ts +1 -1
  50. package/package.json +2 -2
  51. package/src/__tests__/errors.test.ts +92 -11
  52. package/src/__tests__/models/EventManager.test.ts +0 -1
  53. package/src/__tests__/models/Logger.test.ts +82 -5
  54. package/src/__tests__/models/Store.test.ts +57 -0
  55. package/src/__tests__/recursion/c.resource.ts +1 -1
  56. package/src/__tests__/run.overrides.test.ts +3 -3
  57. package/src/__tests__/typesafety.test.ts +112 -9
  58. package/src/__tests__/validation-edge-cases.test.ts +111 -0
  59. package/src/__tests__/validation-interface.test.ts +428 -0
  60. package/src/define.ts +47 -15
  61. package/src/defs.returnTag.ts +91 -0
  62. package/src/defs.ts +84 -27
  63. package/src/errors.ts +95 -23
  64. package/src/index.ts +1 -0
  65. package/src/models/DependencyProcessor.ts +9 -5
  66. package/src/models/EventManager.ts +12 -3
  67. package/src/models/Logger.ts +28 -0
  68. package/src/models/OverrideManager.ts +2 -7
  69. package/src/models/ResourceInitializer.ts +8 -3
  70. package/src/models/Store.ts +12 -3
  71. package/src/models/StoreRegistry.ts +27 -2
  72. package/src/models/StoreTypes.ts +1 -1
  73. package/src/models/StoreValidator.ts +6 -6
  74. package/src/models/TaskRunner.ts +10 -1
  75. package/src/run.ts +8 -5
  76. package/src/testing.ts +1 -1
@@ -4,7 +4,7 @@ import {
4
4
  IEventDefinition,
5
5
  IEventEmission,
6
6
  } from "../defs";
7
- import { Errors } from "../errors";
7
+ import { LockedError, ValidationError } from "../errors";
8
8
  import { Logger } from "./Logger";
9
9
 
10
10
  const HandlerOptionsDefaults = { order: 0 };
@@ -42,7 +42,7 @@ export class EventManager {
42
42
 
43
43
  checkLock() {
44
44
  if (this.#isLocked) {
45
- throw Errors.locked("EventManager");
45
+ throw new LockedError("EventManager");
46
46
  }
47
47
  }
48
48
 
@@ -106,6 +106,15 @@ export class EventManager {
106
106
  data: TInput,
107
107
  source: string | symbol
108
108
  ): Promise<void> {
109
+ // Validate payload with schema if provided
110
+ if (eventDefinition.payloadSchema) {
111
+ try {
112
+ data = eventDefinition.payloadSchema.parse(data);
113
+ } catch (error) {
114
+ throw new ValidationError("Event payload", eventDefinition.id, error instanceof Error ? error : new Error(String(error)));
115
+ }
116
+ }
117
+
109
118
  const allListeners = this.getCachedMergedListeners(eventDefinition.id);
110
119
 
111
120
  if (allListeners.length === 0) {
@@ -130,7 +139,7 @@ export class EventManager {
130
139
  if (propagationStopped) {
131
140
  break;
132
141
  }
133
-
142
+
134
143
  if (!listener.filter || listener.filter(event)) {
135
144
  await listener.handler(event);
136
145
  }
@@ -48,6 +48,34 @@ export class Logger {
48
48
  boundContext: Record<string, any> = {}
49
49
  ) {
50
50
  this.boundContext = { ...boundContext };
51
+ this.printThreshold = this.getDefaultPrintThreshold();
52
+ }
53
+
54
+ /**
55
+ * Determines the default print threshold based on environment variables
56
+ */
57
+ private getDefaultPrintThreshold(): LogLevels | null {
58
+ // Check if logging is explicitly disabled
59
+ const disableLogs = process.env.RUNNER_DISABLE_LOGS;
60
+ if (disableLogs === "true" || disableLogs === "1") {
61
+ return null;
62
+ }
63
+
64
+ // Check for specific log level override
65
+ const logLevel = process.env.RUNNER_LOG_LEVEL;
66
+ if (logLevel && this.isValidLogLevel(logLevel)) {
67
+ return logLevel as LogLevels;
68
+ }
69
+
70
+ // Default to 'info' level for better developer experience
71
+ return "info";
72
+ }
73
+
74
+ /**
75
+ * Validates if a string is a valid log level
76
+ */
77
+ private isValidLogLevel(level: string): boolean {
78
+ return Object.keys(Logger.Severity).includes(level);
51
79
  }
52
80
 
53
81
  /**
@@ -6,12 +6,7 @@ import {
6
6
  RegisterableItems,
7
7
  } from "../defs";
8
8
  import * as utils from "../define";
9
- import { Errors } from "../errors";
10
- import {
11
- TaskStoreElementType,
12
- MiddlewareStoreElementType,
13
- ResourceStoreElementType,
14
- } from "./StoreTypes";
9
+ import { DependencyNotFoundError } from "../errors";
15
10
  import { StoreRegistry } from "./StoreRegistry";
16
11
 
17
12
  export class OverrideManager {
@@ -65,7 +60,7 @@ export class OverrideManager {
65
60
  ? override.resource.id
66
61
  : override.id;
67
62
 
68
- throw Errors.dependencyNotFound(id);
63
+ throw new DependencyNotFoundError(id);
69
64
  }
70
65
  }
71
66
 
@@ -23,7 +23,7 @@ export class ResourceInitializer {
23
23
  */
24
24
  public async initializeResource<
25
25
  TConfig = null,
26
- TValue = any,
26
+ TValue extends Promise<any> = Promise<any>,
27
27
  TDeps extends DependencyMapType = {},
28
28
  TContext = any
29
29
  >(
@@ -109,11 +109,16 @@ export class ResourceInitializer {
109
109
 
110
110
  if (!isSuppressed) throw e;
111
111
 
112
- return { value: undefined as TValue, context: {} as TContext };
112
+ return { value: undefined as unknown as TValue, context: {} as TContext };
113
113
  }
114
114
  }
115
115
 
116
- public async initWithMiddleware<C, V, D extends DependencyMapType, TContext>(
116
+ public async initWithMiddleware<
117
+ C,
118
+ V extends Promise<any>,
119
+ D extends DependencyMapType,
120
+ TContext
121
+ >(
117
122
  resource: IResource<C, V, D, TContext>,
118
123
  config: C,
119
124
  dependencies: DependencyValuesType<D>,
@@ -3,10 +3,11 @@ import {
3
3
  IResource,
4
4
  RegisterableItems,
5
5
  IMiddleware,
6
+ ITag,
6
7
  } from "../defs";
7
8
  import { IDependentNode } from "../tools/findCircularDependencies";
8
9
  import { globalEventsArray } from "../globals/globalEvents";
9
- import { Errors } from "../errors";
10
+ import { StoreAlreadyInitializedError } from "../errors";
10
11
  import { EventManager } from "./EventManager";
11
12
  import { Logger } from "./Logger";
12
13
  import { StoreRegistry } from "./StoreRegistry";
@@ -125,9 +126,9 @@ export class Store {
125
126
  this.registry.resources.set(root.id, this.root);
126
127
  }
127
128
 
128
- initializeStore(root: IResource<any>, config: any) {
129
+ initializeStore(root: IResource<any, any, any, any, any>, config: any) {
129
130
  if (this.#isInitialized) {
130
- throw Errors.storeAlreadyInitialized();
131
+ throw new StoreAlreadyInitializedError();
131
132
  }
132
133
 
133
134
  this.registerGlobalComponents();
@@ -178,6 +179,14 @@ export class Store {
178
179
  this.registry.storeEventsForAllTasks();
179
180
  }
180
181
 
182
+ public getTasksWithTag(tag: string | ITag) {
183
+ return this.registry.getTasksWithTag(tag);
184
+ }
185
+
186
+ public getResourcesWithTag(tag: string | ITag) {
187
+ return this.registry.getResourcesWithTag(tag);
188
+ }
189
+
181
190
  getDependentNodes(): IDependentNode[] {
182
191
  return this.registry.getDependentNodes();
183
192
  }
@@ -10,9 +10,10 @@ import {
10
10
  symbolMiddlewareEverywhereResources,
11
11
  symbolMiddlewareEverywhereTasks,
12
12
  IEvent,
13
+ ITag,
13
14
  } from "../defs";
14
15
  import * as utils from "../define";
15
- import { Errors } from "../errors";
16
+ import { UnknownItemTypeError } from "../errors";
16
17
  import {
17
18
  TaskStoreElementType,
18
19
  MiddlewareStoreElementType,
@@ -55,7 +56,7 @@ export class StoreRegistry {
55
56
  } else if (utils.isResourceWithConfig(item)) {
56
57
  this.storeResourceWithConfig<C>(item);
57
58
  } else {
58
- throw Errors.unknownItemType(item);
59
+ throw new UnknownItemTypeError(item);
59
60
  }
60
61
  }
61
62
 
@@ -225,4 +226,28 @@ export class StoreRegistry {
225
226
 
226
227
  return depenedants;
227
228
  }
229
+
230
+ getTasksWithTag(tag: string | ITag) {
231
+ if (typeof tag === "string") {
232
+ return Array.from(this.tasks.values()).filter((x) =>
233
+ x.task.meta?.tags?.includes(tag)
234
+ );
235
+ }
236
+
237
+ return Array.from(this.tasks.values())
238
+ .filter((x) => tag.extract(x.task.meta?.tags))
239
+ .map((x) => x.task);
240
+ }
241
+
242
+ getResourcesWithTag(tag: string | ITag) {
243
+ if (typeof tag === "string") {
244
+ return Array.from(this.resources.values()).filter((x) =>
245
+ x.resource.meta?.tags?.includes(tag)
246
+ );
247
+ }
248
+
249
+ return Array.from(this.resources.values())
250
+ .filter((x) => tag.extract(x.resource.meta?.tags))
251
+ .map((x) => x.resource);
252
+ }
228
253
  }
@@ -13,7 +13,7 @@ import {
13
13
 
14
14
  export type ResourceStoreElementType<
15
15
  C = any,
16
- V = any,
16
+ V extends Promise<any> = any,
17
17
  D extends DependencyMapType = {},
18
18
  TContext = any
19
19
  > = {
@@ -1,4 +1,4 @@
1
- import { Errors } from "../errors";
1
+ import { DependencyNotFoundError, DuplicateRegistrationError } from "../errors";
2
2
  import {
3
3
  TaskStoreElementType,
4
4
  MiddlewareStoreElementType,
@@ -16,16 +16,16 @@ export class StoreValidator {
16
16
 
17
17
  checkIfIDExists(id: string | symbol): void | never {
18
18
  if (this.tasks.has(id)) {
19
- throw Errors.duplicateRegistration("Task", id);
19
+ throw new DuplicateRegistrationError("Task", id);
20
20
  }
21
21
  if (this.resources.has(id)) {
22
- throw Errors.duplicateRegistration("Resource", id);
22
+ throw new DuplicateRegistrationError("Resource", id);
23
23
  }
24
24
  if (this.events.has(id)) {
25
- throw Errors.duplicateRegistration("Event", id);
25
+ throw new DuplicateRegistrationError("Event", id);
26
26
  }
27
27
  if (this.middlewares.has(id)) {
28
- throw Errors.duplicateRegistration("Middleware", id);
28
+ throw new DuplicateRegistrationError("Middleware", id);
29
29
  }
30
30
  }
31
31
 
@@ -33,7 +33,7 @@ export class StoreValidator {
33
33
  for (const task of this.tasks.values()) {
34
34
  task.task.middleware.forEach((middleware) => {
35
35
  if (!this.middlewares.has(middleware.id)) {
36
- throw Errors.dependencyNotFound(
36
+ throw new DependencyNotFoundError(
37
37
  `Middleware ${middleware.id.toString()} in Task ${task.task.id.toString()}`
38
38
  );
39
39
  }
@@ -1,10 +1,10 @@
1
1
  import { DependencyMapType, DependencyValuesType, ITask } from "../defs";
2
- import { Errors } from "../errors";
3
2
  import { EventManager } from "./EventManager";
4
3
  import { globalEvents } from "../globals/globalEvents";
5
4
  import { Store } from "./Store";
6
5
  import { MiddlewareStoreElementType } from "./StoreTypes";
7
6
  import { Logger } from "./Logger";
7
+ import { ValidationError } from "../errors";
8
8
 
9
9
  export class TaskRunner {
10
10
  protected readonly runnerStore = new Map<
@@ -150,6 +150,15 @@ export class TaskRunner {
150
150
 
151
151
  // this is the final next()
152
152
  let next = async (input: any) => {
153
+ // Validate input with schema if provided
154
+ if (task.inputSchema) {
155
+ try {
156
+ input = task.inputSchema.parse(input);
157
+ } catch (error) {
158
+ throw new ValidationError("Task input", task.id, error instanceof Error ? error : new Error(String(error)));
159
+ }
160
+ }
161
+
153
162
  return task.run.call(null, input, storeTask?.computedDependencies as any);
154
163
  };
155
164
 
package/src/run.ts CHANGED
@@ -13,13 +13,13 @@ import { EventManager } from "./models/EventManager";
13
13
  import { globalEvents } from "./globals/globalEvents";
14
14
  import { Store } from "./models/Store";
15
15
  import { findCircularDependencies } from "./tools/findCircularDependencies";
16
- import { Errors } from "./errors";
16
+ import { CircularDependenciesError } from "./errors";
17
17
  import { globalResources } from "./globals/globalResources";
18
18
  import { Logger } from "./models/Logger";
19
19
 
20
20
  export type ResourcesStoreElementType<
21
21
  C = any,
22
- V = any,
22
+ V extends Promise<any> = any,
23
23
  D extends DependencyMapType = {}
24
24
  > = {
25
25
  resource: IResourceDefinition<C, V, D>;
@@ -53,9 +53,12 @@ export type RunnerState = {
53
53
  };
54
54
 
55
55
  export async function run<C, V>(
56
- resource: IResource<C, V>,
56
+ resource: IResource<C, V extends Promise<any> ? V : Promise<any>>,
57
57
  config?: C
58
- ): Promise<{ value: V; dispose: () => Promise<void> }> {
58
+ ): Promise<{
59
+ value: V extends Promise<infer U> ? U : V;
60
+ dispose: () => Promise<void>;
61
+ }> {
59
62
  const eventManager = new EventManager();
60
63
 
61
64
  // ensure for logger, that it can be used only after: computeAllDependencies() has executed
@@ -79,7 +82,7 @@ export async function run<C, V>(
79
82
  const dependentNodes = store.getDependentNodes();
80
83
  const circularDependencies = findCircularDependencies(dependentNodes);
81
84
  if (circularDependencies.cycles.length > 0) {
82
- throw Errors.circularDependencies(circularDependencies.cycles);
85
+ throw new CircularDependenciesError(circularDependencies.cycles);
83
86
  }
84
87
 
85
88
  // the overrides that were registered now will override the other registered resources
package/src/testing.ts CHANGED
@@ -25,7 +25,7 @@ export function createTestResource(
25
25
  options?: {
26
26
  overrides?: Array<IResource | ITask | IMiddleware | IResourceWithConfig>;
27
27
  }
28
- ): IResource<void, ReturnType<typeof buildTestFacade>> {
28
+ ): IResource<void, Promise<ReturnType<typeof buildTestFacade>>> {
29
29
  return defineResource({
30
30
  id: `tests.createTestResource.${++testResourceCounter}`,
31
31
  register: [root],