@bluelibs/runner 1.0.0 → 1.2.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 +231 -12
- package/dist/DependencyProcessor.d.ts +2 -2
- package/dist/DependencyProcessor.js +3 -3
- package/dist/DependencyProcessor.js.map +1 -1
- package/dist/EventManager.d.ts +4 -0
- package/dist/EventManager.js +15 -0
- package/dist/EventManager.js.map +1 -1
- package/dist/Store.d.ts +30 -2
- package/dist/Store.js +134 -29
- package/dist/Store.js.map +1 -1
- package/dist/TaskRunner.d.ts +3 -0
- package/dist/TaskRunner.js +3 -0
- package/dist/TaskRunner.js.map +1 -1
- package/dist/define.js +2 -7
- package/dist/define.js.map +1 -1
- package/dist/defs.d.ts +15 -4
- package/dist/errors.d.ts +2 -0
- package/dist/errors.js +2 -0
- package/dist/errors.js.map +1 -1
- package/dist/globalEvents.d.ts +2 -0
- package/dist/globalEvents.js +3 -0
- package/dist/globalEvents.js.map +1 -1
- package/dist/globalResources.d.ts +8 -6
- package/dist/globalResources.js +9 -4
- package/dist/globalResources.js.map +1 -1
- package/dist/index.d.ts +8 -6
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/models/DependencyProcessor.d.ts +49 -0
- package/dist/models/DependencyProcessor.js +178 -0
- package/dist/models/DependencyProcessor.js.map +1 -0
- package/dist/models/EventManager.d.ts +17 -0
- package/dist/models/EventManager.js +73 -0
- package/dist/models/EventManager.js.map +1 -0
- package/dist/models/Logger.d.ts +33 -0
- package/dist/models/Logger.js +76 -0
- package/dist/models/Logger.js.map +1 -0
- package/dist/models/ResourceInitializer.d.ts +13 -0
- package/dist/models/ResourceInitializer.js +54 -0
- package/dist/models/ResourceInitializer.js.map +1 -0
- package/dist/models/Store.d.ts +90 -0
- package/dist/models/Store.js +302 -0
- package/dist/models/Store.js.map +1 -0
- package/dist/models/TaskRunner.d.ts +25 -0
- package/dist/models/TaskRunner.js +96 -0
- package/dist/models/TaskRunner.js.map +1 -0
- package/dist/models/index.d.ts +5 -0
- package/dist/models/index.js +22 -0
- package/dist/models/index.js.map +1 -0
- package/dist/run.d.ts +4 -4
- package/dist/run.js +14 -7
- package/dist/run.js.map +1 -1
- package/package.json +1 -2
- package/src/__tests__/index.ts +8 -4
- package/src/__tests__/{EventManager.test.ts → models/EventManager.test.ts} +20 -2
- package/src/__tests__/models/Logger.test.ts +140 -0
- package/src/__tests__/{ResourceInitializer.test.ts → models/ResourceInitializer.test.ts} +4 -4
- package/src/__tests__/models/Store.test.ts +128 -0
- package/src/__tests__/{TaskRunner.test.ts → models/TaskRunner.test.ts} +5 -5
- package/src/__tests__/run.overrides.test.ts +392 -0
- package/src/__tests__/run.test.ts +28 -1
- package/src/define.ts +4 -8
- package/src/defs.ts +20 -4
- package/src/errors.ts +6 -0
- package/src/globalEvents.ts +4 -0
- package/src/globalResources.ts +18 -11
- package/src/index.ts +3 -3
- package/src/{DependencyProcessor.ts → models/DependencyProcessor.ts} +6 -6
- package/src/{EventManager.ts → models/EventManager.ts} +21 -1
- package/src/models/Logger.ts +100 -0
- package/src/{ResourceInitializer.ts → models/ResourceInitializer.ts} +2 -2
- package/src/{Store.ts → models/Store.ts} +181 -41
- package/src/{TaskRunner.ts → models/TaskRunner.ts} +6 -3
- package/src/models/index.ts +5 -0
- package/src/run.ts +17 -9
- package/src/__tests__/Store.test.ts +0 -143
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
defineMiddleware,
|
|
6
6
|
} from "../define";
|
|
7
7
|
import { run } from "../run";
|
|
8
|
+
import { globalResources } from "../globalResources";
|
|
8
9
|
|
|
9
10
|
describe("run", () => {
|
|
10
11
|
// Tasks
|
|
@@ -603,7 +604,6 @@ describe("run", () => {
|
|
|
603
604
|
dependencies: () => ({ middle }),
|
|
604
605
|
register: () => [middle, testTask],
|
|
605
606
|
async init(_, { middle }) {
|
|
606
|
-
console.log(middle.toString());
|
|
607
607
|
expect(await middle()).toBe("middle");
|
|
608
608
|
},
|
|
609
609
|
});
|
|
@@ -611,4 +611,31 @@ describe("run", () => {
|
|
|
611
611
|
await run(app);
|
|
612
612
|
expect(mockFn).toHaveBeenCalled();
|
|
613
613
|
});
|
|
614
|
+
|
|
615
|
+
describe("disposal", () => {
|
|
616
|
+
it("should be able to dispose of a resource", async () => {
|
|
617
|
+
const disposeFn = jest.fn();
|
|
618
|
+
const testResource = defineResource({
|
|
619
|
+
id: "test.resource",
|
|
620
|
+
dispose: disposeFn,
|
|
621
|
+
init: async () => "Resource Value",
|
|
622
|
+
});
|
|
623
|
+
|
|
624
|
+
const app = defineResource({
|
|
625
|
+
id: "app",
|
|
626
|
+
register: [testResource],
|
|
627
|
+
dependencies: { testResource, store: globalResources.store },
|
|
628
|
+
async init(_, { testResource, store }) {
|
|
629
|
+
expect(testResource).toBe("Resource Value");
|
|
630
|
+
|
|
631
|
+
return {
|
|
632
|
+
dispose: () => store.dispose(),
|
|
633
|
+
};
|
|
634
|
+
},
|
|
635
|
+
});
|
|
636
|
+
|
|
637
|
+
const result = await run(app);
|
|
638
|
+
await result.dispose();
|
|
639
|
+
});
|
|
640
|
+
});
|
|
614
641
|
});
|
package/src/define.ts
CHANGED
|
@@ -10,6 +10,8 @@ import {
|
|
|
10
10
|
DependencyMapType,
|
|
11
11
|
DependencyValuesType,
|
|
12
12
|
IMiddleware,
|
|
13
|
+
IHookDefinition,
|
|
14
|
+
IEvent,
|
|
13
15
|
} from "./defs";
|
|
14
16
|
import { Errors } from "./errors";
|
|
15
17
|
|
|
@@ -21,14 +23,6 @@ export function defineTask<
|
|
|
21
23
|
>(
|
|
22
24
|
config: ITaskDefinition<Input, Output, Deps, Test>
|
|
23
25
|
): ITask<Input, Output, Deps, Test> {
|
|
24
|
-
const autorun: any = {};
|
|
25
|
-
// if (config.autorun) {
|
|
26
|
-
// if (config.autorun.on) {
|
|
27
|
-
// autorun.on = Array.isArray(config.autorun.on);
|
|
28
|
-
// autorun.schedule = config.autorun.schedule;
|
|
29
|
-
// }
|
|
30
|
-
// }
|
|
31
|
-
|
|
32
26
|
return {
|
|
33
27
|
[symbols.task]: true,
|
|
34
28
|
id: config.id,
|
|
@@ -63,7 +57,9 @@ export function defineResource<
|
|
|
63
57
|
id: constConfig.id,
|
|
64
58
|
dependencies: constConfig.dependencies,
|
|
65
59
|
hooks: constConfig.hooks || [],
|
|
60
|
+
dispose: constConfig.dispose,
|
|
66
61
|
register: constConfig.register || [],
|
|
62
|
+
overrides: constConfig.overrides || [],
|
|
67
63
|
init: constConfig.init,
|
|
68
64
|
with: function (config: TConfig) {
|
|
69
65
|
return {
|
package/src/defs.ts
CHANGED
|
@@ -21,7 +21,7 @@ export interface IMiddlewareMeta extends IMeta {}
|
|
|
21
21
|
// DependencyMap types
|
|
22
22
|
export type DependencyMapType = Record<
|
|
23
23
|
string,
|
|
24
|
-
ITask | IResource | IEventDefinition
|
|
24
|
+
ITask | IResource | IEventDefinition | IResourceWithConfig<any, any>
|
|
25
25
|
>;
|
|
26
26
|
|
|
27
27
|
export type DependencyValueType<T> = T extends ITask<
|
|
@@ -132,7 +132,21 @@ export interface IResourceDefinintion<
|
|
|
132
132
|
config: TConfig,
|
|
133
133
|
dependencies: DependencyValuesType<TDependencies>
|
|
134
134
|
) => Promise<TValue>;
|
|
135
|
+
/**
|
|
136
|
+
* Clean-up function for the resource. This is called when the resource is no longer needed.
|
|
137
|
+
*
|
|
138
|
+
* @param value The value of the resource
|
|
139
|
+
* @param config The configuration it received
|
|
140
|
+
* @param dependencies The dependencies it needed
|
|
141
|
+
* @returns
|
|
142
|
+
*/
|
|
143
|
+
dispose?: (
|
|
144
|
+
value: TValue,
|
|
145
|
+
config: TConfig,
|
|
146
|
+
dependencies: DependencyValuesType<TDependencies>
|
|
147
|
+
) => Promise<TValue>;
|
|
135
148
|
meta?: IResourceMeta;
|
|
149
|
+
overrides?: Array<IResource | ITask | IMiddleware | IResourceWithConfig>;
|
|
136
150
|
}
|
|
137
151
|
|
|
138
152
|
export interface IResource<
|
|
@@ -155,6 +169,8 @@ export interface IResource<
|
|
|
155
169
|
hooks:
|
|
156
170
|
| IHookDefinition<TDependencies>[]
|
|
157
171
|
| ((config: TConfig) => IHookDefinition<TDependencies>[]);
|
|
172
|
+
|
|
173
|
+
overrides: Array<IResource | ITask | IMiddleware | IResourceWithConfig>;
|
|
158
174
|
}
|
|
159
175
|
|
|
160
176
|
export interface IResourceWithConfig<
|
|
@@ -212,10 +228,10 @@ export interface IMiddlewareExecutionInput {
|
|
|
212
228
|
next: (input?: any) => Promise<any>;
|
|
213
229
|
}
|
|
214
230
|
|
|
215
|
-
export interface IHookDefinition<D extends DependencyMapType = {}> {
|
|
216
|
-
event: IEventDefinition
|
|
231
|
+
export interface IHookDefinition<D extends DependencyMapType = {}, T = any> {
|
|
232
|
+
event: IEventDefinition<T>;
|
|
217
233
|
run: (
|
|
218
|
-
event: IEvent
|
|
234
|
+
event: IEvent<T>,
|
|
219
235
|
dependencies: DependencyValuesType<D>
|
|
220
236
|
) => Promise<void> | void;
|
|
221
237
|
}
|
package/src/errors.ts
CHANGED
|
@@ -19,4 +19,10 @@ export const Errors = {
|
|
|
19
19
|
|
|
20
20
|
middlewareAlreadyGlobal: (id: string) =>
|
|
21
21
|
new Error("Cannot call global on a global middleware: " + id),
|
|
22
|
+
|
|
23
|
+
locked: (what: string) =>
|
|
24
|
+
new Error(`Cannot modify the ${what} when it is locked.`),
|
|
25
|
+
|
|
26
|
+
storeAlreadyInitialized: () =>
|
|
27
|
+
new Error("Store already initialized. Cannot reinitialize."),
|
|
22
28
|
};
|
package/src/globalEvents.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { defineEvent } from "./define";
|
|
2
2
|
import { ITask, IResource } from "./defs";
|
|
3
|
+
import { ILog } from "./models/Logger";
|
|
3
4
|
|
|
4
5
|
export const globalEvents = {
|
|
5
6
|
beforeInit: defineEvent({
|
|
@@ -8,6 +9,9 @@ export const globalEvents = {
|
|
|
8
9
|
afterInit: defineEvent({
|
|
9
10
|
id: "global.afterInit",
|
|
10
11
|
}),
|
|
12
|
+
log: defineEvent<ILog>({
|
|
13
|
+
id: "global.log",
|
|
14
|
+
}),
|
|
11
15
|
tasks: {
|
|
12
16
|
beforeRun: defineEvent<{
|
|
13
17
|
task: ITask<any, any, any>;
|
package/src/globalResources.ts
CHANGED
|
@@ -1,19 +1,26 @@
|
|
|
1
1
|
import { defineResource } from "./define";
|
|
2
|
-
import { EventManager } from "./EventManager";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
2
|
+
import { EventManager } from "./models/EventManager";
|
|
3
|
+
import { Logger } from "./models/Logger";
|
|
4
|
+
import { Store } from "./models/Store";
|
|
5
|
+
import { TaskRunner } from "./models/TaskRunner";
|
|
6
|
+
|
|
7
|
+
const store = defineResource({
|
|
8
|
+
id: "global.store",
|
|
9
|
+
init: async (store: Store) => store,
|
|
10
|
+
});
|
|
5
11
|
|
|
6
12
|
export const globalResources = {
|
|
7
|
-
store
|
|
8
|
-
|
|
9
|
-
init: async (store) => store,
|
|
10
|
-
}),
|
|
11
|
-
eventManager: defineResource<EventManager>({
|
|
13
|
+
store,
|
|
14
|
+
eventManager: defineResource({
|
|
12
15
|
id: "global.eventManager",
|
|
13
|
-
init: async (em) => em,
|
|
16
|
+
init: async (em: EventManager) => em,
|
|
14
17
|
}),
|
|
15
|
-
taskRunner: defineResource
|
|
18
|
+
taskRunner: defineResource({
|
|
16
19
|
id: "global.taskRunner",
|
|
17
|
-
init: async (runner) => runner,
|
|
20
|
+
init: async (runner: TaskRunner) => runner,
|
|
21
|
+
}),
|
|
22
|
+
logger: defineResource({
|
|
23
|
+
id: "global.logger",
|
|
24
|
+
init: async (logger: Logger) => logger,
|
|
18
25
|
}),
|
|
19
26
|
};
|
package/src/index.ts
CHANGED
|
@@ -23,6 +23,6 @@ export {
|
|
|
23
23
|
};
|
|
24
24
|
|
|
25
25
|
export * as definitions from "./defs";
|
|
26
|
-
export { Store } from "./Store";
|
|
27
|
-
export { EventManager } from "./EventManager";
|
|
28
|
-
export { TaskRunner } from "./TaskRunner";
|
|
26
|
+
export { Store } from "./models/Store";
|
|
27
|
+
export { EventManager } from "./models/EventManager";
|
|
28
|
+
export { TaskRunner } from "./models/TaskRunner";
|
|
@@ -5,13 +5,13 @@ import {
|
|
|
5
5
|
IResource,
|
|
6
6
|
IHookDefinition,
|
|
7
7
|
IEventDefinition,
|
|
8
|
-
} from "
|
|
8
|
+
} from "../defs";
|
|
9
9
|
import { ResourceStoreElementType, Store } from "./Store";
|
|
10
|
-
import * as utils from "
|
|
10
|
+
import * as utils from "../define";
|
|
11
11
|
import { EventManager } from "./EventManager";
|
|
12
12
|
import { ResourceInitializer } from "./ResourceInitializer";
|
|
13
13
|
import { TaskRunner } from "./TaskRunner";
|
|
14
|
-
import { Errors } from "
|
|
14
|
+
import { Errors } from "../errors";
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* This class is responsible of setting up dependencies with their respective computedValues.
|
|
@@ -113,11 +113,11 @@ export class DependencyProcessor {
|
|
|
113
113
|
* Processes all hooks, should run before emission of any event.
|
|
114
114
|
* @returns
|
|
115
115
|
*/
|
|
116
|
-
public
|
|
116
|
+
public attachHooks() {
|
|
117
117
|
// iterate through resources and send them to processHooks
|
|
118
118
|
for (const resource of this.store.resources.values()) {
|
|
119
119
|
if (resource.resource.hooks) {
|
|
120
|
-
this.
|
|
120
|
+
this.attachHooksToResource(resource);
|
|
121
121
|
}
|
|
122
122
|
}
|
|
123
123
|
}
|
|
@@ -127,7 +127,7 @@ export class DependencyProcessor {
|
|
|
127
127
|
* @param hooks
|
|
128
128
|
* @param deps
|
|
129
129
|
*/
|
|
130
|
-
public
|
|
130
|
+
public attachHooksToResource(
|
|
131
131
|
resourceStoreElement: ResourceStoreElementType<any, any, {}>
|
|
132
132
|
) {
|
|
133
133
|
let hooks = resourceStoreElement.resource.hooks;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { EventHandlerType, IEvent, IEventDefinition } from "
|
|
1
|
+
import { EventHandlerType, IEvent, IEventDefinition } from "../defs";
|
|
2
|
+
import { Errors } from "../errors";
|
|
2
3
|
|
|
3
4
|
const HandlerOptionsDefaults = { order: 0 };
|
|
4
5
|
|
|
@@ -16,6 +17,21 @@ export interface IEventHandlerOptions<T = any> {
|
|
|
16
17
|
export class EventManager {
|
|
17
18
|
private listeners: Map<string, IListenerStorage[]> = new Map();
|
|
18
19
|
private globalListeners: IListenerStorage[] = [];
|
|
20
|
+
#isLocked = false;
|
|
21
|
+
|
|
22
|
+
get isLocked() {
|
|
23
|
+
return this.#isLocked;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
lock() {
|
|
27
|
+
this.#isLocked = true;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
checkLock() {
|
|
31
|
+
if (this.#isLocked) {
|
|
32
|
+
throw Errors.locked("EventManager");
|
|
33
|
+
}
|
|
34
|
+
}
|
|
19
35
|
|
|
20
36
|
async emit<TInput>(
|
|
21
37
|
eventDefinition: IEventDefinition<TInput>,
|
|
@@ -46,6 +62,8 @@ export class EventManager {
|
|
|
46
62
|
handler: EventHandlerType<T>,
|
|
47
63
|
options: IEventHandlerOptions<T> = HandlerOptionsDefaults
|
|
48
64
|
): void {
|
|
65
|
+
this.checkLock();
|
|
66
|
+
|
|
49
67
|
if (Array.isArray(event)) {
|
|
50
68
|
event.forEach((id) => this.addListener(id, handler, options));
|
|
51
69
|
} else {
|
|
@@ -66,6 +84,8 @@ export class EventManager {
|
|
|
66
84
|
handler: EventHandlerType,
|
|
67
85
|
options: IEventHandlerOptions = HandlerOptionsDefaults
|
|
68
86
|
): void {
|
|
87
|
+
this.checkLock();
|
|
88
|
+
|
|
69
89
|
const newListener: IListenerStorage = {
|
|
70
90
|
handler,
|
|
71
91
|
order: options.order || 0,
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { globalEvents } from "../globalEvents";
|
|
2
|
+
import { EventManager } from "./EventManager";
|
|
3
|
+
|
|
4
|
+
export type LogLevels =
|
|
5
|
+
| "trace"
|
|
6
|
+
| "debug"
|
|
7
|
+
| "info"
|
|
8
|
+
| "warn"
|
|
9
|
+
| "error"
|
|
10
|
+
| "critical";
|
|
11
|
+
|
|
12
|
+
export interface ILog {
|
|
13
|
+
level: string;
|
|
14
|
+
context?: string;
|
|
15
|
+
data: any;
|
|
16
|
+
timestamp: Date;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export class Logger {
|
|
20
|
+
public static defaultContext = "app";
|
|
21
|
+
|
|
22
|
+
public severity = {
|
|
23
|
+
trace: 0,
|
|
24
|
+
debug: 1,
|
|
25
|
+
info: 2,
|
|
26
|
+
warn: 3,
|
|
27
|
+
error: 4,
|
|
28
|
+
critical: 5,
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
constructor(private eventManager: EventManager) {}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @param level
|
|
35
|
+
* @param message
|
|
36
|
+
*/
|
|
37
|
+
public async log(level: LogLevels, data: any): Promise<void> {
|
|
38
|
+
const log: ILog = {
|
|
39
|
+
level,
|
|
40
|
+
data,
|
|
41
|
+
timestamp: new Date(),
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
await this.eventManager.emit(globalEvents.log, log);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
public async print(log: ILog) {
|
|
48
|
+
// Extract the relevant information from the log
|
|
49
|
+
const { level, context, data, timestamp } = log;
|
|
50
|
+
|
|
51
|
+
// Format the timestamp to a more readable format
|
|
52
|
+
const formattedTimestamp = timestamp.toISOString();
|
|
53
|
+
|
|
54
|
+
// Format the log level for better visibility
|
|
55
|
+
const levelStr = `[${level.toUpperCase()}]`;
|
|
56
|
+
|
|
57
|
+
// Format the context, if provided
|
|
58
|
+
const contextStr = context ? `(${context})` : "";
|
|
59
|
+
|
|
60
|
+
// Handle different data types, especially if it's an error
|
|
61
|
+
let dataStr: string;
|
|
62
|
+
if (data instanceof Error) {
|
|
63
|
+
dataStr = `Error: ${data.name} - ${data.message}\nStack Trace:\n${data.stack}`;
|
|
64
|
+
} else if (typeof data === "object") {
|
|
65
|
+
dataStr = JSON.stringify(data, null, 2); // Pretty-print JSON objects
|
|
66
|
+
} else {
|
|
67
|
+
dataStr = String(data); // Convert any other type to string
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Construct the final log message
|
|
71
|
+
const logMessage = `${formattedTimestamp} ${levelStr} ${contextStr} - ${dataStr}`;
|
|
72
|
+
|
|
73
|
+
// Print the log message
|
|
74
|
+
console.log(logMessage);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
public async info(data: any) {
|
|
78
|
+
await this.log("info", data);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
public async error(data: any) {
|
|
82
|
+
await this.log("error", data);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
public async warn(data: any) {
|
|
86
|
+
await this.log("warn", data);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
public async debug(data: any) {
|
|
90
|
+
await this.log("debug", data);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
public async trace(data: any) {
|
|
94
|
+
await this.log("trace", data);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
public async critical(data: any) {
|
|
98
|
+
await this.log("critical", data);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -3,9 +3,9 @@ import {
|
|
|
3
3
|
DependencyValuesType,
|
|
4
4
|
ITask,
|
|
5
5
|
IResource,
|
|
6
|
-
} from "
|
|
6
|
+
} from "../defs";
|
|
7
7
|
import { EventManager } from "./EventManager";
|
|
8
|
-
import { globalEvents } from "
|
|
8
|
+
import { globalEvents } from "../globalEvents";
|
|
9
9
|
import { Store } from "./Store";
|
|
10
10
|
|
|
11
11
|
export class ResourceInitializer {
|