@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.
Files changed (204) hide show
  1. package/README.md +1315 -942
  2. package/dist/common.types.d.ts +20 -0
  3. package/dist/common.types.js +4 -0
  4. package/dist/common.types.js.map +1 -0
  5. package/dist/context.d.ts +34 -0
  6. package/dist/context.js +58 -0
  7. package/dist/context.js.map +1 -0
  8. package/dist/define.d.ts +22 -3
  9. package/dist/define.js +52 -8
  10. package/dist/define.js.map +1 -1
  11. package/dist/defs.d.ts +52 -31
  12. package/dist/defs.js +10 -2
  13. package/dist/defs.js.map +1 -1
  14. package/dist/errors.js +1 -1
  15. package/dist/errors.js.map +1 -1
  16. package/dist/event.types.d.ts +18 -0
  17. package/dist/event.types.js +4 -0
  18. package/dist/event.types.js.map +1 -0
  19. package/dist/examples/registrator-example.d.ts +122 -0
  20. package/dist/examples/registrator-example.js +147 -0
  21. package/dist/examples/registrator-example.js.map +1 -0
  22. package/dist/globals/globalEvents.d.ts +41 -0
  23. package/dist/globals/globalEvents.js +94 -0
  24. package/dist/globals/globalEvents.js.map +1 -0
  25. package/dist/globals/globalMiddleware.d.ts +23 -0
  26. package/dist/globals/globalMiddleware.js +15 -0
  27. package/dist/globals/globalMiddleware.js.map +1 -0
  28. package/dist/globals/globalResources.d.ts +27 -0
  29. package/dist/globals/globalResources.js +47 -0
  30. package/dist/globals/globalResources.js.map +1 -0
  31. package/dist/globals/middleware/cache.middleware.d.ts +34 -0
  32. package/dist/globals/middleware/cache.middleware.js +85 -0
  33. package/dist/globals/middleware/cache.middleware.js.map +1 -0
  34. package/dist/globals/middleware/requireContext.middleware.d.ts +6 -0
  35. package/dist/globals/middleware/requireContext.middleware.js +25 -0
  36. package/dist/globals/middleware/requireContext.middleware.js.map +1 -0
  37. package/dist/globals/middleware/retry.middleware.d.ts +20 -0
  38. package/dist/globals/middleware/retry.middleware.js +34 -0
  39. package/dist/globals/middleware/retry.middleware.js.map +1 -0
  40. package/dist/globals/resources/queue.resource.d.ts +7 -0
  41. package/dist/globals/resources/queue.resource.js +31 -0
  42. package/dist/globals/resources/queue.resource.js.map +1 -0
  43. package/dist/index.d.ts +45 -9
  44. package/dist/index.js +14 -9
  45. package/dist/index.js.map +1 -1
  46. package/dist/middleware.types.d.ts +40 -0
  47. package/dist/middleware.types.js +4 -0
  48. package/dist/middleware.types.js.map +1 -0
  49. package/dist/models/DependencyProcessor.d.ts +2 -1
  50. package/dist/models/DependencyProcessor.js +11 -13
  51. package/dist/models/DependencyProcessor.js.map +1 -1
  52. package/dist/models/EventManager.d.ts +5 -0
  53. package/dist/models/EventManager.js +44 -2
  54. package/dist/models/EventManager.js.map +1 -1
  55. package/dist/models/Logger.d.ts +30 -12
  56. package/dist/models/Logger.js +130 -42
  57. package/dist/models/Logger.js.map +1 -1
  58. package/dist/models/OverrideManager.d.ts +13 -0
  59. package/dist/models/OverrideManager.js +70 -0
  60. package/dist/models/OverrideManager.js.map +1 -0
  61. package/dist/models/Queue.d.ts +25 -0
  62. package/dist/models/Queue.js +54 -0
  63. package/dist/models/Queue.js.map +1 -0
  64. package/dist/models/ResourceInitializer.d.ts +5 -2
  65. package/dist/models/ResourceInitializer.js +20 -14
  66. package/dist/models/ResourceInitializer.js.map +1 -1
  67. package/dist/models/Semaphore.d.ts +61 -0
  68. package/dist/models/Semaphore.js +166 -0
  69. package/dist/models/Semaphore.js.map +1 -0
  70. package/dist/models/Store.d.ts +17 -72
  71. package/dist/models/Store.js +71 -269
  72. package/dist/models/Store.js.map +1 -1
  73. package/dist/models/StoreConstants.d.ts +11 -0
  74. package/dist/models/StoreConstants.js +18 -0
  75. package/dist/models/StoreConstants.js.map +1 -0
  76. package/dist/models/StoreRegistry.d.ts +25 -0
  77. package/dist/models/StoreRegistry.js +171 -0
  78. package/dist/models/StoreRegistry.js.map +1 -0
  79. package/dist/models/StoreTypes.d.ts +21 -0
  80. package/dist/models/StoreTypes.js +3 -0
  81. package/dist/models/StoreTypes.js.map +1 -0
  82. package/dist/models/StoreValidator.d.ts +10 -0
  83. package/dist/models/StoreValidator.js +41 -0
  84. package/dist/models/StoreValidator.js.map +1 -0
  85. package/dist/models/TaskRunner.js +39 -24
  86. package/dist/models/TaskRunner.js.map +1 -1
  87. package/dist/models/VarStore.d.ts +17 -0
  88. package/dist/models/VarStore.js +60 -0
  89. package/dist/models/VarStore.js.map +1 -0
  90. package/dist/models/index.d.ts +3 -0
  91. package/dist/models/index.js +3 -0
  92. package/dist/models/index.js.map +1 -1
  93. package/dist/resource.types.d.ts +31 -0
  94. package/dist/resource.types.js +3 -0
  95. package/dist/resource.types.js.map +1 -0
  96. package/dist/run.d.ts +4 -1
  97. package/dist/run.js +6 -3
  98. package/dist/run.js.map +1 -1
  99. package/dist/symbols.d.ts +24 -0
  100. package/dist/symbols.js +29 -0
  101. package/dist/symbols.js.map +1 -0
  102. package/dist/task.types.d.ts +55 -0
  103. package/dist/task.types.js +23 -0
  104. package/dist/task.types.js.map +1 -0
  105. package/dist/tools/registratorId.d.ts +4 -0
  106. package/dist/tools/registratorId.js +40 -0
  107. package/dist/tools/registratorId.js.map +1 -0
  108. package/dist/tools/simpleHash.d.ts +9 -0
  109. package/dist/tools/simpleHash.js +34 -0
  110. package/dist/tools/simpleHash.js.map +1 -0
  111. package/dist/types/base-interfaces.d.ts +18 -0
  112. package/dist/types/base-interfaces.js +6 -0
  113. package/dist/types/base-interfaces.js.map +1 -0
  114. package/dist/types/base.d.ts +13 -0
  115. package/dist/types/base.js +3 -0
  116. package/dist/types/base.js.map +1 -0
  117. package/dist/types/dependencies.d.ts +22 -0
  118. package/dist/types/dependencies.js +3 -0
  119. package/dist/types/dependencies.js.map +1 -0
  120. package/dist/types/dependency-core.d.ts +14 -0
  121. package/dist/types/dependency-core.js +5 -0
  122. package/dist/types/dependency-core.js.map +1 -0
  123. package/dist/types/events.d.ts +52 -0
  124. package/dist/types/events.js +6 -0
  125. package/dist/types/events.js.map +1 -0
  126. package/dist/types/hooks.d.ts +16 -0
  127. package/dist/types/hooks.js +5 -0
  128. package/dist/types/hooks.js.map +1 -0
  129. package/dist/types/index.d.ts +14 -0
  130. package/dist/types/index.js +27 -0
  131. package/dist/types/index.js.map +1 -0
  132. package/dist/types/meta.d.ts +13 -0
  133. package/dist/types/meta.js +5 -0
  134. package/dist/types/meta.js.map +1 -0
  135. package/dist/types/middleware.d.ts +38 -0
  136. package/dist/types/middleware.js +6 -0
  137. package/dist/types/middleware.js.map +1 -0
  138. package/dist/types/registerable.d.ts +10 -0
  139. package/dist/types/registerable.js +5 -0
  140. package/dist/types/registerable.js.map +1 -0
  141. package/dist/types/resources.d.ts +44 -0
  142. package/dist/types/resources.js +5 -0
  143. package/dist/types/resources.js.map +1 -0
  144. package/dist/types/symbols.d.ts +24 -0
  145. package/dist/types/symbols.js +30 -0
  146. package/dist/types/symbols.js.map +1 -0
  147. package/dist/types/tasks.d.ts +41 -0
  148. package/dist/types/tasks.js +5 -0
  149. package/dist/types/tasks.js.map +1 -0
  150. package/dist/types/utilities.d.ts +7 -0
  151. package/dist/types/utilities.js +5 -0
  152. package/dist/types/utilities.js.map +1 -0
  153. package/package.json +10 -6
  154. package/src/__tests__/benchmark/benchmark.test.ts +1 -1
  155. package/src/__tests__/context.test.ts +91 -0
  156. package/src/__tests__/errors.test.ts +8 -5
  157. package/src/__tests__/globalEvents.test.ts +1 -1
  158. package/src/__tests__/globals/cache.middleware.test.ts +772 -0
  159. package/src/__tests__/globals/queue.resource.test.ts +141 -0
  160. package/src/__tests__/globals/requireContext.middleware.test.ts +98 -0
  161. package/src/__tests__/globals/retry.middleware.test.ts +157 -0
  162. package/src/__tests__/index.helper.test.ts +55 -0
  163. package/src/__tests__/models/EventManager.test.ts +144 -0
  164. package/src/__tests__/models/Logger.test.ts +291 -34
  165. package/src/__tests__/models/Queue.test.ts +189 -0
  166. package/src/__tests__/models/ResourceInitializer.test.ts +8 -6
  167. package/src/__tests__/models/Semaphore.test.ts +713 -0
  168. package/src/__tests__/models/Store.test.ts +40 -0
  169. package/src/__tests__/models/TaskRunner.test.ts +86 -5
  170. package/src/__tests__/run.middleware.test.ts +166 -12
  171. package/src/__tests__/run.overrides.test.ts +13 -10
  172. package/src/__tests__/run.test.ts +363 -12
  173. package/src/__tests__/setOutput.test.ts +244 -0
  174. package/src/__tests__/tools/getCallerFile.test.ts +9 -9
  175. package/src/__tests__/typesafety.test.ts +54 -39
  176. package/src/context.ts +86 -0
  177. package/src/define.ts +84 -14
  178. package/src/defs.ts +91 -41
  179. package/src/errors.ts +3 -1
  180. package/src/{globalEvents.ts → globals/globalEvents.ts} +13 -12
  181. package/src/globals/globalMiddleware.ts +14 -0
  182. package/src/{globalResources.ts → globals/globalResources.ts} +14 -10
  183. package/src/globals/middleware/cache.middleware.ts +115 -0
  184. package/src/globals/middleware/requireContext.middleware.ts +36 -0
  185. package/src/globals/middleware/retry.middleware.ts +56 -0
  186. package/src/globals/resources/queue.resource.ts +34 -0
  187. package/src/index.ts +9 -5
  188. package/src/models/DependencyProcessor.ts +36 -40
  189. package/src/models/EventManager.ts +45 -5
  190. package/src/models/Logger.ts +170 -48
  191. package/src/models/OverrideManager.ts +84 -0
  192. package/src/models/Queue.ts +66 -0
  193. package/src/models/ResourceInitializer.ts +38 -20
  194. package/src/models/Semaphore.ts +208 -0
  195. package/src/models/Store.ts +94 -342
  196. package/src/models/StoreConstants.ts +17 -0
  197. package/src/models/StoreRegistry.ts +217 -0
  198. package/src/models/StoreTypes.ts +46 -0
  199. package/src/models/StoreValidator.ts +38 -0
  200. package/src/models/TaskRunner.ts +53 -40
  201. package/src/models/index.ts +3 -0
  202. package/src/run.ts +7 -4
  203. package/src/__tests__/index.ts +0 -15
  204. package/src/examples/express-mongo/index.ts +0 -1
@@ -1,4 +1,9 @@
1
- import { defineEvent, defineTask, defineResource } from "../define";
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
- THooks = any
73
+ TPrivate = any
71
74
  >(
72
- constConfig: IResourceDefinition<TConfig, TValue, TDeps, THooks>
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 || (async (...args: any[]) => undefined as TValue),
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 function defineMiddleware<TDeps extends DependencyMapType = {}>(
129
- config: IMiddlewareDefinition<TDeps>
130
- ): IMiddleware<TDeps> {
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
- ...config,
135
- dependencies: config.dependencies || ({} as TDeps),
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
- global() {
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.middlewareGlobal]: true,
144
- global() {
145
- throw Errors.middlewareAlreadyGlobal(config.id);
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
- middlewareGlobal: symbolMiddlewareGlobal,
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
- // | IResource<void, any, any>
90
- | IResource<OptionalOrVoidOrAnything<T>, any, any>
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?: IMiddlewareDefinition[];
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: IMiddlewareDefinition[];
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
- ) => Promise<TValue>;
232
+ dependencies: DependencyValuesType<TDependencies>,
233
+ context: TContext
234
+ ) => Promise<void>;
210
235
  meta?: IResourceMeta;
211
236
  overrides?: Array<IResource | ITask | IMiddleware | IResourceWithConfig>;
212
- middleware?: IMiddlewareDefinition[];
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
- > extends IResourceDefinition<TConfig, TValue, TDependencies> {
220
- init: (
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: IMiddlewareDefinition[];
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<TDependencies extends DependencyMapType = any>
298
- extends IMiddlewareDefinition<TDependencies> {
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
- global(): IMiddleware<TDependencies>;
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
- taskDefinition?: ITask;
312
- resourceDefinition?: IResource;
313
- config?: any;
314
- input?: any;
315
- next: (taskInputOrResourceConfig?: any) => Promise<any>;
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("Cannot call global on a global middleware: " + id),
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.`),