@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.
- package/README.md +491 -74
- package/dist/define.d.ts +5 -5
- package/dist/define.js +22 -2
- package/dist/define.js.map +1 -1
- package/dist/defs.d.ts +55 -21
- package/dist/defs.js.map +1 -1
- package/dist/defs.returnTag.d.ts +36 -0
- package/dist/defs.returnTag.js +4 -0
- package/dist/defs.returnTag.js.map +1 -0
- package/dist/errors.d.ts +60 -10
- package/dist/errors.js +103 -12
- package/dist/errors.js.map +1 -1
- package/dist/globals/globalMiddleware.d.ts +4 -4
- package/dist/globals/globalResources.d.ts +28 -10
- package/dist/globals/middleware/cache.middleware.d.ts +9 -9
- package/dist/globals/resources/queue.resource.d.ts +5 -2
- package/dist/index.d.ts +33 -14
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/models/DependencyProcessor.js +4 -4
- package/dist/models/DependencyProcessor.js.map +1 -1
- package/dist/models/EventManager.js +10 -1
- package/dist/models/EventManager.js.map +1 -1
- package/dist/models/Logger.d.ts +8 -0
- package/dist/models/Logger.js +24 -0
- package/dist/models/Logger.js.map +1 -1
- package/dist/models/OverrideManager.js +1 -1
- package/dist/models/OverrideManager.js.map +1 -1
- package/dist/models/ResourceInitializer.d.ts +2 -2
- package/dist/models/ResourceInitializer.js.map +1 -1
- package/dist/models/Store.d.ts +5 -3
- package/dist/models/Store.js +7 -1
- package/dist/models/Store.js.map +1 -1
- package/dist/models/StoreConstants.d.ts +6 -3
- package/dist/models/StoreRegistry.d.ts +5 -3
- package/dist/models/StoreRegistry.js +17 -1
- package/dist/models/StoreRegistry.js.map +1 -1
- package/dist/models/StoreTypes.d.ts +1 -1
- package/dist/models/StoreValidator.js +5 -5
- package/dist/models/StoreValidator.js.map +1 -1
- package/dist/models/TaskRunner.js +10 -0
- package/dist/models/TaskRunner.js.map +1 -1
- package/dist/run.d.ts +3 -3
- package/dist/run.js +1 -1
- package/dist/run.js.map +1 -1
- package/dist/t1.d.ts +1 -0
- package/dist/t1.js +13 -0
- package/dist/t1.js.map +1 -0
- package/dist/testing.d.ts +1 -1
- package/package.json +2 -2
- package/src/__tests__/errors.test.ts +92 -11
- package/src/__tests__/models/EventManager.test.ts +0 -1
- package/src/__tests__/models/Logger.test.ts +82 -5
- package/src/__tests__/models/Store.test.ts +57 -0
- package/src/__tests__/recursion/c.resource.ts +1 -1
- package/src/__tests__/run.overrides.test.ts +3 -3
- package/src/__tests__/typesafety.test.ts +112 -9
- package/src/__tests__/validation-edge-cases.test.ts +111 -0
- package/src/__tests__/validation-interface.test.ts +428 -0
- package/src/define.ts +47 -15
- package/src/defs.returnTag.ts +91 -0
- package/src/defs.ts +84 -27
- package/src/errors.ts +95 -23
- package/src/index.ts +1 -0
- package/src/models/DependencyProcessor.ts +9 -5
- package/src/models/EventManager.ts +12 -3
- package/src/models/Logger.ts +28 -0
- package/src/models/OverrideManager.ts +2 -7
- package/src/models/ResourceInitializer.ts +8 -3
- package/src/models/Store.ts +12 -3
- package/src/models/StoreRegistry.ts +27 -2
- package/src/models/StoreTypes.ts +1 -1
- package/src/models/StoreValidator.ts +6 -6
- package/src/models/TaskRunner.ts +10 -1
- package/src/run.ts +8 -5
- package/src/testing.ts +1 -1
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
IEventDefinition,
|
|
5
5
|
IEventEmission,
|
|
6
6
|
} from "../defs";
|
|
7
|
-
import {
|
|
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
|
|
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
|
}
|
package/src/models/Logger.ts
CHANGED
|
@@ -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 {
|
|
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
|
|
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<
|
|
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>,
|
package/src/models/Store.ts
CHANGED
|
@@ -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 {
|
|
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
|
|
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 {
|
|
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
|
|
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
|
}
|
package/src/models/StoreTypes.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
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
|
|
19
|
+
throw new DuplicateRegistrationError("Task", id);
|
|
20
20
|
}
|
|
21
21
|
if (this.resources.has(id)) {
|
|
22
|
-
throw
|
|
22
|
+
throw new DuplicateRegistrationError("Resource", id);
|
|
23
23
|
}
|
|
24
24
|
if (this.events.has(id)) {
|
|
25
|
-
throw
|
|
25
|
+
throw new DuplicateRegistrationError("Event", id);
|
|
26
26
|
}
|
|
27
27
|
if (this.middlewares.has(id)) {
|
|
28
|
-
throw
|
|
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
|
|
36
|
+
throw new DependencyNotFoundError(
|
|
37
37
|
`Middleware ${middleware.id.toString()} in Task ${task.task.id.toString()}`
|
|
38
38
|
);
|
|
39
39
|
}
|
package/src/models/TaskRunner.ts
CHANGED
|
@@ -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 {
|
|
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<{
|
|
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
|
|
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],
|