@bluelibs/runner 2.2.3 → 3.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 +1315 -942
- package/dist/common.types.d.ts +20 -0
- package/dist/common.types.js +4 -0
- package/dist/common.types.js.map +1 -0
- package/dist/context.d.ts +34 -0
- package/dist/context.js +58 -0
- package/dist/context.js.map +1 -0
- package/dist/define.d.ts +22 -3
- package/dist/define.js +52 -8
- package/dist/define.js.map +1 -1
- package/dist/defs.d.ts +52 -31
- package/dist/defs.js +10 -2
- package/dist/defs.js.map +1 -1
- package/dist/errors.js +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/event.types.d.ts +18 -0
- package/dist/event.types.js +4 -0
- package/dist/event.types.js.map +1 -0
- package/dist/examples/registrator-example.d.ts +122 -0
- package/dist/examples/registrator-example.js +147 -0
- package/dist/examples/registrator-example.js.map +1 -0
- package/dist/globals/globalEvents.d.ts +41 -0
- package/dist/globals/globalEvents.js +94 -0
- package/dist/globals/globalEvents.js.map +1 -0
- package/dist/globals/globalMiddleware.d.ts +23 -0
- package/dist/globals/globalMiddleware.js +15 -0
- package/dist/globals/globalMiddleware.js.map +1 -0
- package/dist/globals/globalResources.d.ts +27 -0
- package/dist/globals/globalResources.js +47 -0
- package/dist/globals/globalResources.js.map +1 -0
- package/dist/globals/middleware/cache.middleware.d.ts +34 -0
- package/dist/globals/middleware/cache.middleware.js +85 -0
- package/dist/globals/middleware/cache.middleware.js.map +1 -0
- package/dist/globals/middleware/requireContext.middleware.d.ts +6 -0
- package/dist/globals/middleware/requireContext.middleware.js +25 -0
- package/dist/globals/middleware/requireContext.middleware.js.map +1 -0
- package/dist/globals/middleware/retry.middleware.d.ts +20 -0
- package/dist/globals/middleware/retry.middleware.js +34 -0
- package/dist/globals/middleware/retry.middleware.js.map +1 -0
- package/dist/globals/resources/queue.resource.d.ts +7 -0
- package/dist/globals/resources/queue.resource.js +31 -0
- package/dist/globals/resources/queue.resource.js.map +1 -0
- package/dist/index.d.ts +45 -9
- package/dist/index.js +14 -9
- package/dist/index.js.map +1 -1
- package/dist/middleware.types.d.ts +40 -0
- package/dist/middleware.types.js +4 -0
- package/dist/middleware.types.js.map +1 -0
- package/dist/models/DependencyProcessor.d.ts +2 -1
- package/dist/models/DependencyProcessor.js +11 -13
- package/dist/models/DependencyProcessor.js.map +1 -1
- package/dist/models/EventManager.d.ts +5 -0
- package/dist/models/EventManager.js +44 -2
- package/dist/models/EventManager.js.map +1 -1
- package/dist/models/Logger.d.ts +30 -12
- package/dist/models/Logger.js +130 -42
- package/dist/models/Logger.js.map +1 -1
- package/dist/models/OverrideManager.d.ts +13 -0
- package/dist/models/OverrideManager.js +70 -0
- package/dist/models/OverrideManager.js.map +1 -0
- package/dist/models/Queue.d.ts +25 -0
- package/dist/models/Queue.js +54 -0
- package/dist/models/Queue.js.map +1 -0
- package/dist/models/ResourceInitializer.d.ts +5 -2
- package/dist/models/ResourceInitializer.js +20 -14
- package/dist/models/ResourceInitializer.js.map +1 -1
- package/dist/models/Semaphore.d.ts +61 -0
- package/dist/models/Semaphore.js +166 -0
- package/dist/models/Semaphore.js.map +1 -0
- package/dist/models/Store.d.ts +17 -72
- package/dist/models/Store.js +71 -269
- package/dist/models/Store.js.map +1 -1
- package/dist/models/StoreConstants.d.ts +11 -0
- package/dist/models/StoreConstants.js +18 -0
- package/dist/models/StoreConstants.js.map +1 -0
- package/dist/models/StoreRegistry.d.ts +25 -0
- package/dist/models/StoreRegistry.js +171 -0
- package/dist/models/StoreRegistry.js.map +1 -0
- package/dist/models/StoreTypes.d.ts +21 -0
- package/dist/models/StoreTypes.js +3 -0
- package/dist/models/StoreTypes.js.map +1 -0
- package/dist/models/StoreValidator.d.ts +10 -0
- package/dist/models/StoreValidator.js +41 -0
- package/dist/models/StoreValidator.js.map +1 -0
- package/dist/models/TaskRunner.js +39 -24
- package/dist/models/TaskRunner.js.map +1 -1
- package/dist/models/VarStore.d.ts +17 -0
- package/dist/models/VarStore.js +60 -0
- package/dist/models/VarStore.js.map +1 -0
- package/dist/models/index.d.ts +3 -0
- package/dist/models/index.js +3 -0
- package/dist/models/index.js.map +1 -1
- package/dist/resource.types.d.ts +31 -0
- package/dist/resource.types.js +3 -0
- package/dist/resource.types.js.map +1 -0
- package/dist/run.d.ts +4 -1
- package/dist/run.js +6 -3
- package/dist/run.js.map +1 -1
- package/dist/symbols.d.ts +24 -0
- package/dist/symbols.js +29 -0
- package/dist/symbols.js.map +1 -0
- package/dist/task.types.d.ts +55 -0
- package/dist/task.types.js +23 -0
- package/dist/task.types.js.map +1 -0
- package/dist/tools/registratorId.d.ts +4 -0
- package/dist/tools/registratorId.js +40 -0
- package/dist/tools/registratorId.js.map +1 -0
- package/dist/tools/simpleHash.d.ts +9 -0
- package/dist/tools/simpleHash.js +34 -0
- package/dist/tools/simpleHash.js.map +1 -0
- package/dist/types/base-interfaces.d.ts +18 -0
- package/dist/types/base-interfaces.js +6 -0
- package/dist/types/base-interfaces.js.map +1 -0
- package/dist/types/base.d.ts +13 -0
- package/dist/types/base.js +3 -0
- package/dist/types/base.js.map +1 -0
- package/dist/types/dependencies.d.ts +22 -0
- package/dist/types/dependencies.js +3 -0
- package/dist/types/dependencies.js.map +1 -0
- package/dist/types/dependency-core.d.ts +14 -0
- package/dist/types/dependency-core.js +5 -0
- package/dist/types/dependency-core.js.map +1 -0
- package/dist/types/events.d.ts +52 -0
- package/dist/types/events.js +6 -0
- package/dist/types/events.js.map +1 -0
- package/dist/types/hooks.d.ts +16 -0
- package/dist/types/hooks.js +5 -0
- package/dist/types/hooks.js.map +1 -0
- package/dist/types/index.d.ts +14 -0
- package/dist/types/index.js +27 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/meta.d.ts +13 -0
- package/dist/types/meta.js +5 -0
- package/dist/types/meta.js.map +1 -0
- package/dist/types/middleware.d.ts +38 -0
- package/dist/types/middleware.js +6 -0
- package/dist/types/middleware.js.map +1 -0
- package/dist/types/registerable.d.ts +10 -0
- package/dist/types/registerable.js +5 -0
- package/dist/types/registerable.js.map +1 -0
- package/dist/types/resources.d.ts +44 -0
- package/dist/types/resources.js +5 -0
- package/dist/types/resources.js.map +1 -0
- package/dist/types/symbols.d.ts +24 -0
- package/dist/types/symbols.js +30 -0
- package/dist/types/symbols.js.map +1 -0
- package/dist/types/tasks.d.ts +41 -0
- package/dist/types/tasks.js +5 -0
- package/dist/types/tasks.js.map +1 -0
- package/dist/types/utilities.d.ts +7 -0
- package/dist/types/utilities.js +5 -0
- package/dist/types/utilities.js.map +1 -0
- package/package.json +10 -6
- package/src/__tests__/benchmark/benchmark.test.ts +1 -1
- package/src/__tests__/context.test.ts +91 -0
- package/src/__tests__/errors.test.ts +8 -5
- package/src/__tests__/globalEvents.test.ts +1 -1
- package/src/__tests__/globals/cache.middleware.test.ts +772 -0
- package/src/__tests__/globals/queue.resource.test.ts +141 -0
- package/src/__tests__/globals/requireContext.middleware.test.ts +98 -0
- package/src/__tests__/globals/retry.middleware.test.ts +157 -0
- package/src/__tests__/index.helper.test.ts +55 -0
- package/src/__tests__/models/EventManager.test.ts +144 -0
- package/src/__tests__/models/Logger.test.ts +291 -34
- package/src/__tests__/models/Queue.test.ts +189 -0
- package/src/__tests__/models/ResourceInitializer.test.ts +8 -6
- package/src/__tests__/models/Semaphore.test.ts +713 -0
- package/src/__tests__/models/Store.test.ts +40 -0
- package/src/__tests__/models/TaskRunner.test.ts +86 -5
- package/src/__tests__/run.middleware.test.ts +166 -12
- package/src/__tests__/run.overrides.test.ts +13 -10
- package/src/__tests__/run.test.ts +363 -12
- package/src/__tests__/setOutput.test.ts +244 -0
- package/src/__tests__/tools/getCallerFile.test.ts +9 -9
- package/src/__tests__/typesafety.test.ts +54 -39
- package/src/context.ts +86 -0
- package/src/define.ts +84 -14
- package/src/defs.ts +91 -41
- package/src/errors.ts +3 -1
- package/src/{globalEvents.ts → globals/globalEvents.ts} +13 -12
- package/src/globals/globalMiddleware.ts +14 -0
- package/src/{globalResources.ts → globals/globalResources.ts} +14 -10
- package/src/globals/middleware/cache.middleware.ts +115 -0
- package/src/globals/middleware/requireContext.middleware.ts +36 -0
- package/src/globals/middleware/retry.middleware.ts +56 -0
- package/src/globals/resources/queue.resource.ts +34 -0
- package/src/index.ts +9 -5
- package/src/models/DependencyProcessor.ts +36 -40
- package/src/models/EventManager.ts +45 -5
- package/src/models/Logger.ts +170 -48
- package/src/models/OverrideManager.ts +84 -0
- package/src/models/Queue.ts +66 -0
- package/src/models/ResourceInitializer.ts +38 -20
- package/src/models/Semaphore.ts +208 -0
- package/src/models/Store.ts +94 -342
- package/src/models/StoreConstants.ts +17 -0
- package/src/models/StoreRegistry.ts +217 -0
- package/src/models/StoreTypes.ts +46 -0
- package/src/models/StoreValidator.ts +38 -0
- package/src/models/TaskRunner.ts +53 -40
- package/src/models/index.ts +3 -0
- package/src/run.ts +7 -4
- package/src/__tests__/index.ts +0 -15
- package/src/examples/express-mongo/index.ts +0 -1
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
defineEvent,
|
|
3
|
+
defineTask,
|
|
4
|
+
defineResource,
|
|
5
|
+
defineMiddleware,
|
|
6
|
+
} from "../define";
|
|
2
7
|
import { RegisterableItems } from "../defs";
|
|
3
8
|
|
|
4
9
|
describe("typesafety", () => {
|
|
@@ -7,6 +12,35 @@ describe("typesafety", () => {
|
|
|
7
12
|
message: string;
|
|
8
13
|
};
|
|
9
14
|
|
|
15
|
+
const middleware = defineMiddleware({
|
|
16
|
+
id: "middleware",
|
|
17
|
+
run: async (input, deps) => {
|
|
18
|
+
return input;
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
type MiddlewareConfig = {
|
|
23
|
+
message: string;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
type MiddlewareOptionalConfig = {
|
|
27
|
+
message?: string;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const middlewareWithConfig = defineMiddleware({
|
|
31
|
+
id: "middleware.config",
|
|
32
|
+
run: async (input, deps, config: MiddlewareConfig) => {
|
|
33
|
+
return input;
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const middlewareWithOptionalConfig = defineMiddleware({
|
|
38
|
+
id: "middleware.optional.config",
|
|
39
|
+
run: async (input, deps, config: MiddlewareOptionalConfig) => {
|
|
40
|
+
return input;
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
|
|
10
44
|
const event = defineEvent<{ message: string }>({
|
|
11
45
|
id: "event",
|
|
12
46
|
});
|
|
@@ -58,6 +92,18 @@ describe("typesafety", () => {
|
|
|
58
92
|
|
|
59
93
|
const testResource = defineResource({
|
|
60
94
|
id: "test.resource",
|
|
95
|
+
middleware: [
|
|
96
|
+
middleware,
|
|
97
|
+
// @ts-expect-error
|
|
98
|
+
middlewareWithConfig,
|
|
99
|
+
middlewareWithConfig.with({ message: "Hello, World!" }),
|
|
100
|
+
// @ts-expect-error
|
|
101
|
+
middlewareWithConfig.with({ message: 123 }),
|
|
102
|
+
middlewareWithOptionalConfig,
|
|
103
|
+
middlewareWithOptionalConfig.with({ message: "Hello, World!" }),
|
|
104
|
+
// @ts-expect-error
|
|
105
|
+
middlewareWithOptionalConfig.with({ message: 123 }),
|
|
106
|
+
],
|
|
61
107
|
dependencies: { task, dummyResource, event },
|
|
62
108
|
init: async (_, deps) => {
|
|
63
109
|
const result = await deps.task({
|
|
@@ -82,6 +128,13 @@ describe("typesafety", () => {
|
|
|
82
128
|
deps.task2;
|
|
83
129
|
},
|
|
84
130
|
register: [
|
|
131
|
+
middleware,
|
|
132
|
+
middlewareWithConfig,
|
|
133
|
+
middlewareWithOptionalConfig,
|
|
134
|
+
middlewareWithOptionalConfig.with({ message: "Hello, World!" }),
|
|
135
|
+
middlewareWithConfig.with({ message: "Hello, World!" }),
|
|
136
|
+
// @ts-expect-error
|
|
137
|
+
middlewareWithConfig.with({ message: 123 }),
|
|
85
138
|
dummyResourceNoConfig,
|
|
86
139
|
// @ts-expect-error
|
|
87
140
|
dummyResourceNoConfig.with("hello"),
|
|
@@ -141,42 +194,4 @@ describe("typesafety", () => {
|
|
|
141
194
|
|
|
142
195
|
expect(true).toBe(true);
|
|
143
196
|
});
|
|
144
|
-
|
|
145
|
-
it("should work with resources that register other resources and don't infer an any to them", async () => {
|
|
146
|
-
const resourceBase = defineResource({
|
|
147
|
-
id: "task",
|
|
148
|
-
init: async (_, deps) => {
|
|
149
|
-
deps.resource;
|
|
150
|
-
return "";
|
|
151
|
-
},
|
|
152
|
-
dependencies: () => ({
|
|
153
|
-
resource,
|
|
154
|
-
}),
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
const resource = defineResource({
|
|
158
|
-
id: "resource",
|
|
159
|
-
register: [],
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
resource.register = [resourceBase];
|
|
163
|
-
|
|
164
|
-
// @ts-expect-error
|
|
165
|
-
resource.DOES_NOT_EXIST;
|
|
166
|
-
|
|
167
|
-
expect(true).toBe(true);
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
it("should work to unit test with void arguments?", async () => {
|
|
171
|
-
const resourceBase = defineResource({
|
|
172
|
-
id: "task",
|
|
173
|
-
init: async (_, deps) => {
|
|
174
|
-
return "";
|
|
175
|
-
},
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
if (resourceBase.init) {
|
|
179
|
-
resourceBase.init(undefined, {});
|
|
180
|
-
}
|
|
181
|
-
});
|
|
182
197
|
});
|
package/src/context.ts
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
2
|
+
import { defineMiddleware } from "./define";
|
|
3
|
+
import { IMiddleware, IMiddlewareConfigured } from "./defs";
|
|
4
|
+
import { requireContextMiddleware } from "./globals/middleware/requireContext.middleware";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Error thrown whenever a requested context is not available.
|
|
8
|
+
*/
|
|
9
|
+
export class ContextError extends Error {
|
|
10
|
+
constructor(message: string) {
|
|
11
|
+
super(message);
|
|
12
|
+
this.name = "ContextError";
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* The generic Context object returned by `createContext`.
|
|
18
|
+
*/
|
|
19
|
+
export interface Context<T> {
|
|
20
|
+
/** unique symbol used as key in the AsyncLocalStorage map */
|
|
21
|
+
readonly id: symbol;
|
|
22
|
+
/** Retrieve the current context value or throw */
|
|
23
|
+
use(): T;
|
|
24
|
+
/**
|
|
25
|
+
* Provide a value for this context during the lifetime of `fn()`
|
|
26
|
+
*/
|
|
27
|
+
provide<R>(value: T, fn: () => Promise<R> | R): Promise<R> | R;
|
|
28
|
+
/**
|
|
29
|
+
* Generates a middleware that guarantees the context exists (and optionally
|
|
30
|
+
* enforces that certain keys are present on the context object).
|
|
31
|
+
*/
|
|
32
|
+
require<K extends keyof T = never>(
|
|
33
|
+
keys?: K[]
|
|
34
|
+
): IMiddlewareConfigured<{ context: Context<T> }>;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// The internal storage maps Context identifiers (symbols) to their values
|
|
38
|
+
export const storage = new AsyncLocalStorage<Map<symbol, unknown>>();
|
|
39
|
+
|
|
40
|
+
/** Returns the currently active store or undefined. */
|
|
41
|
+
function getCurrentStore(): Map<symbol, unknown> | undefined {
|
|
42
|
+
return storage.getStore();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Create a new typed Context. The result contains helpers similar to React’s
|
|
47
|
+
* Context API but adapted for async usage in Runner.
|
|
48
|
+
*/
|
|
49
|
+
export function createContext<T>(name: string = "runner.context"): Context<T> {
|
|
50
|
+
const ctxId = Symbol(name);
|
|
51
|
+
|
|
52
|
+
function use(): T {
|
|
53
|
+
const store = getCurrentStore();
|
|
54
|
+
if (!store || !store.has(ctxId)) {
|
|
55
|
+
throw new ContextError(
|
|
56
|
+
`Context not available for symbol ${ctxId.toString()}`
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
return store.get(ctxId) as T;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function provide<R>(value: T, fn: () => Promise<R> | R): Promise<R> | R {
|
|
63
|
+
const currentStore = getCurrentStore();
|
|
64
|
+
const map = currentStore
|
|
65
|
+
? new Map(currentStore)
|
|
66
|
+
: new Map<symbol, unknown>();
|
|
67
|
+
map.set(ctxId, value);
|
|
68
|
+
|
|
69
|
+
return storage.run(map, fn as any);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Generates a middleware that guarantees the context exists (and optionally
|
|
74
|
+
* enforces that certain keys are present on the context object).
|
|
75
|
+
*/
|
|
76
|
+
function require(): IMiddlewareConfigured {
|
|
77
|
+
return requireContextMiddleware.with({ context: this as Context<T> });
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
id: ctxId,
|
|
82
|
+
use,
|
|
83
|
+
provide,
|
|
84
|
+
require,
|
|
85
|
+
};
|
|
86
|
+
}
|
package/src/define.ts
CHANGED
|
@@ -15,6 +15,8 @@ import {
|
|
|
15
15
|
IEvent,
|
|
16
16
|
IEventDefinitionConfig,
|
|
17
17
|
symbolEvent,
|
|
18
|
+
RegisterableItems,
|
|
19
|
+
symbolMiddlewareConfigured,
|
|
18
20
|
} from "./defs";
|
|
19
21
|
import { Errors } from "./errors";
|
|
20
22
|
import { getCallerFile } from "./tools/getCallerFile";
|
|
@@ -38,6 +40,7 @@ export function defineTask<
|
|
|
38
40
|
middleware: taskConfig.middleware || [],
|
|
39
41
|
run: taskConfig.run,
|
|
40
42
|
on: taskConfig.on,
|
|
43
|
+
listenerOrder: taskConfig.listenerOrder,
|
|
41
44
|
events: {
|
|
42
45
|
beforeRun: {
|
|
43
46
|
...defineEvent({
|
|
@@ -67,10 +70,10 @@ export function defineResource<
|
|
|
67
70
|
TConfig = void,
|
|
68
71
|
TValue = any,
|
|
69
72
|
TDeps extends DependencyMapType = {},
|
|
70
|
-
|
|
73
|
+
TPrivate = any
|
|
71
74
|
>(
|
|
72
|
-
constConfig: IResourceDefinition<TConfig, TValue, TDeps,
|
|
73
|
-
): IResource<TConfig, TValue, TDeps> {
|
|
75
|
+
constConfig: IResourceDefinition<TConfig, TValue, TDeps, TPrivate>
|
|
76
|
+
): IResource<TConfig, TValue, TDeps, TPrivate> {
|
|
74
77
|
const filePath = getCallerFile();
|
|
75
78
|
return {
|
|
76
79
|
[symbols.resource]: true,
|
|
@@ -80,7 +83,8 @@ export function defineResource<
|
|
|
80
83
|
dispose: constConfig.dispose,
|
|
81
84
|
register: constConfig.register || [],
|
|
82
85
|
overrides: constConfig.overrides || [],
|
|
83
|
-
init: constConfig.init
|
|
86
|
+
init: constConfig.init,
|
|
87
|
+
context: constConfig.context,
|
|
84
88
|
with: function (config: TConfig) {
|
|
85
89
|
return {
|
|
86
90
|
[symbols.resourceWithConfig]: true,
|
|
@@ -115,6 +119,44 @@ export function defineResource<
|
|
|
115
119
|
};
|
|
116
120
|
}
|
|
117
121
|
|
|
122
|
+
/**
|
|
123
|
+
* Creates an "index" resource which groups multiple registerable items under
|
|
124
|
+
* a single dependency. The resulting resource registers every item, depends
|
|
125
|
+
* on the same items, and returns the resolved dependency map so users can
|
|
126
|
+
* access them naturally: `deps.services.myTask()` or `deps.services.myResource`.
|
|
127
|
+
*/
|
|
128
|
+
export function defineIndex<
|
|
129
|
+
T extends Record<string, RegisterableItems>,
|
|
130
|
+
D extends {
|
|
131
|
+
[K in keyof T]: T[K] extends IResourceWithConfig<any, any, any>
|
|
132
|
+
? T[K]["resource"]
|
|
133
|
+
: T[K];
|
|
134
|
+
} & DependencyMapType
|
|
135
|
+
>(items: T): IResource<void, DependencyValuesType<D>, D> {
|
|
136
|
+
const dependencies = {} as D;
|
|
137
|
+
const register: RegisterableItems[] = [];
|
|
138
|
+
|
|
139
|
+
for (const key of Object.keys(items) as (keyof T)[]) {
|
|
140
|
+
const item = items[key];
|
|
141
|
+
register.push(item);
|
|
142
|
+
|
|
143
|
+
if (isResourceWithConfig(item)) {
|
|
144
|
+
(dependencies as any)[key] = item.resource;
|
|
145
|
+
} else {
|
|
146
|
+
(dependencies as any)[key] = item as any;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return defineResource({
|
|
151
|
+
id: `index.${Math.random().toString(36).slice(2)}`,
|
|
152
|
+
register,
|
|
153
|
+
dependencies,
|
|
154
|
+
async init(_, deps) {
|
|
155
|
+
return deps as any;
|
|
156
|
+
},
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
|
|
118
160
|
export function defineEvent<TPayload = any>(
|
|
119
161
|
config: IEventDefinitionConfig<TPayload>
|
|
120
162
|
): IEventDefinition<TPayload> {
|
|
@@ -125,24 +167,52 @@ export function defineEvent<TPayload = any>(
|
|
|
125
167
|
};
|
|
126
168
|
}
|
|
127
169
|
|
|
128
|
-
export
|
|
129
|
-
|
|
130
|
-
|
|
170
|
+
export type MiddlewareEverywhereOptions = {
|
|
171
|
+
/**
|
|
172
|
+
* Enable this for tasks. Default is true.
|
|
173
|
+
*/
|
|
174
|
+
tasks?: boolean;
|
|
175
|
+
/**
|
|
176
|
+
* Enable this for resources. Default is true.
|
|
177
|
+
*/
|
|
178
|
+
resources?: boolean;
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
export function defineMiddleware<
|
|
182
|
+
TConfig extends Record<string, any>,
|
|
183
|
+
TDependencies extends DependencyMapType
|
|
184
|
+
>(
|
|
185
|
+
middlewareDef: IMiddlewareDefinition<TConfig, TDependencies>
|
|
186
|
+
): IMiddleware<TConfig, TDependencies> {
|
|
131
187
|
const object = {
|
|
132
188
|
[symbols.filePath]: getCallerFile(),
|
|
133
189
|
[symbols.middleware]: true,
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
190
|
+
config: {} as TConfig,
|
|
191
|
+
...middlewareDef,
|
|
192
|
+
dependencies: middlewareDef.dependencies || ({} as TDependencies),
|
|
193
|
+
} as IMiddleware<TConfig, TDependencies>;
|
|
137
194
|
|
|
138
195
|
return {
|
|
139
196
|
...object,
|
|
140
|
-
|
|
197
|
+
with: (config: TConfig) => {
|
|
198
|
+
return {
|
|
199
|
+
...object,
|
|
200
|
+
[symbolMiddlewareConfigured]: true,
|
|
201
|
+
config: {
|
|
202
|
+
...object.config,
|
|
203
|
+
...config,
|
|
204
|
+
},
|
|
205
|
+
};
|
|
206
|
+
},
|
|
207
|
+
everywhere(options: MiddlewareEverywhereOptions = {}) {
|
|
208
|
+
const { tasks = true, resources = true } = options;
|
|
209
|
+
|
|
141
210
|
return {
|
|
142
211
|
...object,
|
|
143
|
-
[symbols.
|
|
144
|
-
|
|
145
|
-
|
|
212
|
+
[symbols.middlewareEverywhereTasks]: tasks,
|
|
213
|
+
[symbols.middlewareEverywhereResources]: resources,
|
|
214
|
+
everywhere() {
|
|
215
|
+
throw Errors.middlewareAlreadyGlobal(middlewareDef.id);
|
|
146
216
|
},
|
|
147
217
|
};
|
|
148
218
|
},
|
package/src/defs.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
export { ICacheInstance } from "./globals/middleware/cache.middleware";
|
|
2
|
+
|
|
1
3
|
export const symbolTask: unique symbol = Symbol("runner.task");
|
|
2
4
|
export const symbolResource: unique symbol = Symbol("runner.resource");
|
|
3
5
|
export const symbolResourceWithConfig: unique symbol = Symbol(
|
|
@@ -5,11 +7,22 @@ export const symbolResourceWithConfig: unique symbol = Symbol(
|
|
|
5
7
|
);
|
|
6
8
|
export const symbolEvent: unique symbol = Symbol("runner.event");
|
|
7
9
|
export const symbolMiddleware: unique symbol = Symbol("runner.middleware");
|
|
10
|
+
export const symbolMiddlewareConfigured: unique symbol = Symbol(
|
|
11
|
+
"runner.middlewareConfigured"
|
|
12
|
+
);
|
|
8
13
|
export const symbolMiddlewareGlobal: unique symbol = Symbol(
|
|
9
14
|
"runner.middlewareGlobal"
|
|
10
15
|
);
|
|
16
|
+
export const symbolMiddlewareEverywhereTasks: unique symbol = Symbol(
|
|
17
|
+
"runner.middlewareGlobalTasks"
|
|
18
|
+
);
|
|
19
|
+
export const symbolMiddlewareEverywhereResources: unique symbol = Symbol(
|
|
20
|
+
"runner.middlewareGlobalResources"
|
|
21
|
+
);
|
|
11
22
|
|
|
12
23
|
export const symbolFilePath: unique symbol = Symbol("runner.filePath");
|
|
24
|
+
export const symbolDispose: unique symbol = Symbol("runner.dispose");
|
|
25
|
+
export const symbolStore: unique symbol = Symbol("runner.store");
|
|
13
26
|
|
|
14
27
|
export const symbols = {
|
|
15
28
|
task: symbolTask,
|
|
@@ -17,8 +30,11 @@ export const symbols = {
|
|
|
17
30
|
resourceWithConfig: symbolResourceWithConfig,
|
|
18
31
|
event: symbolEvent,
|
|
19
32
|
middleware: symbolMiddleware,
|
|
20
|
-
|
|
33
|
+
middlewareEverywhereTasks: symbolMiddlewareEverywhereTasks,
|
|
34
|
+
middlewareEverywhereResources: symbolMiddlewareEverywhereResources,
|
|
21
35
|
filePath: symbolFilePath,
|
|
36
|
+
dispose: symbolDispose,
|
|
37
|
+
store: symbolStore,
|
|
22
38
|
};
|
|
23
39
|
|
|
24
40
|
export interface IMeta {
|
|
@@ -83,15 +99,22 @@ type OptionalOrVoidOrAnything<T> = IsVoid<T> extends true
|
|
|
83
99
|
? Optional<T>
|
|
84
100
|
: T;
|
|
85
101
|
|
|
102
|
+
type OnlyOptionalFields<T> = {} extends T ? true : false;
|
|
103
|
+
|
|
86
104
|
// RegisterableItems Type with Conditional Inclusion
|
|
87
105
|
export type RegisterableItems<T = any> =
|
|
88
106
|
| IResourceWithConfig<any>
|
|
89
|
-
|
|
90
|
-
| IResource<
|
|
107
|
+
| IResource<void, any, any, any> // For void configs
|
|
108
|
+
| IResource<{ [K in any]?: any }, any, any, any> // For optional config
|
|
91
109
|
| ITaskDefinition<any, any, any, any>
|
|
92
110
|
| IMiddlewareDefinition<any>
|
|
93
111
|
| IEventDefinition<any>;
|
|
94
112
|
|
|
113
|
+
export type MiddlewareAttachments =
|
|
114
|
+
| IMiddleware<void>
|
|
115
|
+
| IMiddleware<{ [K in any]?: any }>
|
|
116
|
+
| IMiddlewareConfigured<any>;
|
|
117
|
+
|
|
95
118
|
export interface ITaskDefinition<
|
|
96
119
|
TInput = any,
|
|
97
120
|
TOutput extends Promise<any> = any,
|
|
@@ -100,7 +123,7 @@ export interface ITaskDefinition<
|
|
|
100
123
|
> {
|
|
101
124
|
id: string;
|
|
102
125
|
dependencies?: TDependencies | (() => TDependencies);
|
|
103
|
-
middleware?:
|
|
126
|
+
middleware?: MiddlewareAttachments[];
|
|
104
127
|
/**
|
|
105
128
|
* Listen to events in a simple way
|
|
106
129
|
*/
|
|
@@ -115,11 +138,6 @@ export interface ITaskDefinition<
|
|
|
115
138
|
input: TOn extends undefined
|
|
116
139
|
? TInput
|
|
117
140
|
: IEvent<TOn extends "*" ? any : ExtractEventParams<TOn>>,
|
|
118
|
-
// input: TOn extends "*"
|
|
119
|
-
// ? IEvent<any>
|
|
120
|
-
// : TEventDefinitionInput extends null | void
|
|
121
|
-
// ? TInput
|
|
122
|
-
// : IEvent<TEventDefinitionInput>,
|
|
123
141
|
dependencies: DependencyValuesType<TDependencies>
|
|
124
142
|
) => TOutput;
|
|
125
143
|
}
|
|
@@ -130,7 +148,8 @@ export type BeforeRunEventPayload<TInput> = {
|
|
|
130
148
|
|
|
131
149
|
export type AfterRunEventPayload<TInput, TOutput> = {
|
|
132
150
|
input: TInput;
|
|
133
|
-
output: TOutput;
|
|
151
|
+
output: TOutput extends Promise<infer U> ? U : TOutput;
|
|
152
|
+
setOutput(newOutput: TOutput extends Promise<infer U> ? U : TOutput): void;
|
|
134
153
|
};
|
|
135
154
|
|
|
136
155
|
export type OnErrorEventPayload = {
|
|
@@ -161,7 +180,7 @@ export interface ITask<
|
|
|
161
180
|
> extends ITaskDefinition<TInput, TOutput, TDependencies, TOn> {
|
|
162
181
|
dependencies: TDependencies | (() => TDependencies);
|
|
163
182
|
computedDependencies?: DependencyValuesType<TDependencies>;
|
|
164
|
-
middleware:
|
|
183
|
+
middleware: MiddlewareAttachments[];
|
|
165
184
|
/**
|
|
166
185
|
* These events are automatically populated after the task has been defined.
|
|
167
186
|
*/
|
|
@@ -171,18 +190,20 @@ export interface ITask<
|
|
|
171
190
|
onError: IEventDefinition<OnErrorEventPayload>;
|
|
172
191
|
};
|
|
173
192
|
}
|
|
174
|
-
|
|
175
|
-
type IsExactlyUnknown<T> = unknown extends T
|
|
176
|
-
? T extends unknown
|
|
177
|
-
? true
|
|
178
|
-
: false
|
|
179
|
-
: false;
|
|
180
|
-
|
|
181
193
|
// Resource interfaces
|
|
194
|
+
// Conditional type to determine the value type based on whether init is present
|
|
195
|
+
type ResourceValueType<T> = T extends { init: any }
|
|
196
|
+
? T["init"] extends (...args: any[]) => Promise<infer R>
|
|
197
|
+
? R
|
|
198
|
+
: unknown
|
|
199
|
+
: undefined;
|
|
200
|
+
|
|
182
201
|
export interface IResourceDefinition<
|
|
183
202
|
TConfig = any,
|
|
184
203
|
TValue = unknown,
|
|
185
204
|
TDependencies extends DependencyMapType = {},
|
|
205
|
+
TContext = any,
|
|
206
|
+
THooks = any,
|
|
186
207
|
TRegisterableItems = any
|
|
187
208
|
> {
|
|
188
209
|
id: string;
|
|
@@ -191,36 +212,38 @@ export interface IResourceDefinition<
|
|
|
191
212
|
| Array<RegisterableItems>
|
|
192
213
|
| ((config: TConfig) => Array<RegisterableItems>);
|
|
193
214
|
init?: (
|
|
215
|
+
this: any,
|
|
194
216
|
config: TConfig,
|
|
195
|
-
dependencies: DependencyValuesType<TDependencies
|
|
217
|
+
dependencies: DependencyValuesType<TDependencies>,
|
|
218
|
+
context: TContext
|
|
196
219
|
) => Promise<TValue>;
|
|
197
220
|
/**
|
|
198
221
|
* Clean-up function for the resource. This is called when the resource is no longer needed.
|
|
199
222
|
*
|
|
200
|
-
* @param value The value of the resource
|
|
223
|
+
* @param value The value of the resource (undefined if no init method)
|
|
201
224
|
* @param config The configuration it received
|
|
202
225
|
* @param dependencies The dependencies it needed
|
|
203
|
-
* @returns
|
|
226
|
+
* @returns Promise<void>
|
|
204
227
|
*/
|
|
205
228
|
dispose?: (
|
|
229
|
+
this: any,
|
|
206
230
|
value: TValue,
|
|
207
231
|
config: TConfig,
|
|
208
|
-
dependencies: DependencyValuesType<TDependencies
|
|
209
|
-
|
|
232
|
+
dependencies: DependencyValuesType<TDependencies>,
|
|
233
|
+
context: TContext
|
|
234
|
+
) => Promise<void>;
|
|
210
235
|
meta?: IResourceMeta;
|
|
211
236
|
overrides?: Array<IResource | ITask | IMiddleware | IResourceWithConfig>;
|
|
212
|
-
middleware?:
|
|
237
|
+
middleware?: MiddlewareAttachments[];
|
|
238
|
+
context?: () => TContext;
|
|
213
239
|
}
|
|
214
240
|
|
|
215
241
|
export interface IResource<
|
|
216
242
|
TConfig = void,
|
|
217
243
|
TValue = any,
|
|
218
|
-
TDependencies extends DependencyMapType = any
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
config: TConfig,
|
|
222
|
-
dependencies: DependencyValuesType<TDependencies>
|
|
223
|
-
) => Promise<TValue>;
|
|
244
|
+
TDependencies extends DependencyMapType = any,
|
|
245
|
+
TContext = any
|
|
246
|
+
> extends IResourceDefinition<TConfig, TValue, TDependencies, TContext> {
|
|
224
247
|
with(config: TConfig): IResourceWithConfig<TConfig, TValue, TDependencies>;
|
|
225
248
|
register:
|
|
226
249
|
| Array<RegisterableItems>
|
|
@@ -234,7 +257,7 @@ export interface IResource<
|
|
|
234
257
|
onError: IEventDefinition<OnErrorEventPayload>;
|
|
235
258
|
};
|
|
236
259
|
overrides: Array<IResource | ITask | IMiddleware | IResourceWithConfig>;
|
|
237
|
-
middleware:
|
|
260
|
+
middleware: MiddlewareAttachments[];
|
|
238
261
|
}
|
|
239
262
|
|
|
240
263
|
export interface IResourceWithConfig<
|
|
@@ -283,21 +306,39 @@ export interface IEventDefinition<TPayload = void> {
|
|
|
283
306
|
}
|
|
284
307
|
|
|
285
308
|
export interface IMiddlewareDefinition<
|
|
309
|
+
TConfig = any,
|
|
286
310
|
TDependencies extends DependencyMapType = any
|
|
287
311
|
> {
|
|
288
312
|
id: string;
|
|
289
313
|
dependencies?: TDependencies | (() => TDependencies);
|
|
290
314
|
run: (
|
|
291
315
|
input: IMiddlewareExecutionInput,
|
|
292
|
-
dependencies: DependencyValuesType<TDependencies
|
|
316
|
+
dependencies: DependencyValuesType<TDependencies>,
|
|
317
|
+
config: TConfig
|
|
293
318
|
) => Promise<any>;
|
|
294
319
|
meta?: IMiddlewareMeta;
|
|
295
320
|
}
|
|
296
321
|
|
|
297
|
-
export interface IMiddleware<
|
|
298
|
-
|
|
322
|
+
export interface IMiddleware<
|
|
323
|
+
TConfig = any,
|
|
324
|
+
TDependencies extends DependencyMapType = any
|
|
325
|
+
> extends IMiddlewareDefinition<TConfig, TDependencies> {
|
|
326
|
+
[symbolMiddleware]: true;
|
|
327
|
+
[symbolMiddlewareConfigured]?: boolean;
|
|
328
|
+
[symbolMiddlewareEverywhereTasks]?: boolean;
|
|
329
|
+
[symbolMiddlewareEverywhereResources]?: boolean;
|
|
330
|
+
|
|
299
331
|
dependencies: TDependencies | (() => TDependencies);
|
|
300
|
-
|
|
332
|
+
everywhere(): IMiddleware<TConfig, TDependencies>;
|
|
333
|
+
config: TConfig;
|
|
334
|
+
with: (config: TConfig) => IMiddlewareConfigured<TConfig, TDependencies>;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
export interface IMiddlewareConfigured<
|
|
338
|
+
TConfig = any,
|
|
339
|
+
TDependencies extends DependencyMapType = any
|
|
340
|
+
> extends IMiddleware<TConfig, TDependencies> {
|
|
341
|
+
[symbolMiddlewareConfigured]: true;
|
|
301
342
|
}
|
|
302
343
|
|
|
303
344
|
export interface IMiddlewareDefinitionConfigured<
|
|
@@ -307,12 +348,21 @@ export interface IMiddlewareDefinitionConfigured<
|
|
|
307
348
|
config?: C;
|
|
308
349
|
}
|
|
309
350
|
|
|
310
|
-
export interface IMiddlewareExecutionInput
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
351
|
+
export interface IMiddlewareExecutionInput<
|
|
352
|
+
TTaskInput = any,
|
|
353
|
+
TResourceConfig = any
|
|
354
|
+
> {
|
|
355
|
+
task?: {
|
|
356
|
+
definition: ITask<TTaskInput>;
|
|
357
|
+
input: TTaskInput;
|
|
358
|
+
};
|
|
359
|
+
resource?: {
|
|
360
|
+
definition: IResource<TResourceConfig>;
|
|
361
|
+
config: TResourceConfig;
|
|
362
|
+
};
|
|
363
|
+
next: (
|
|
364
|
+
taskInputOrResourceConfig?: TTaskInput | TResourceConfig
|
|
365
|
+
) => Promise<any>;
|
|
316
366
|
}
|
|
317
367
|
|
|
318
368
|
export interface IHookDefinition<
|
package/src/errors.ts
CHANGED
|
@@ -18,7 +18,9 @@ export const Errors = {
|
|
|
18
18
|
new Error(`Event "${id}" not found. Did you forget to register it?`),
|
|
19
19
|
|
|
20
20
|
middlewareAlreadyGlobal: (id: string) =>
|
|
21
|
-
new Error(
|
|
21
|
+
new Error(
|
|
22
|
+
"Cannot call .everywhere() on an already global middleware: " + id
|
|
23
|
+
),
|
|
22
24
|
|
|
23
25
|
locked: (what: string) =>
|
|
24
26
|
new Error(`Cannot modify the ${what} when it is locked.`),
|