@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
@@ -0,0 +1,208 @@
1
+ interface WaitingOperation {
2
+ resolve: () => void;
3
+ reject: (error: Error) => void;
4
+ timeout?: NodeJS.Timeout;
5
+ abortController?: AbortController;
6
+ }
7
+
8
+ /**
9
+ * A semaphore that limits the number of concurrent operations.
10
+ * Used to prevent connection pool exhaustion by limiting concurrent
11
+ * database operations to the pool size.
12
+ */
13
+ export class Semaphore {
14
+ private permits: number;
15
+ private readonly waitingQueue: Array<WaitingOperation> = [];
16
+ private disposed = false;
17
+ private readonly maxPermits: number;
18
+
19
+ constructor(maxPermits: number) {
20
+ if (maxPermits <= 0) {
21
+ throw new Error("maxPermits must be greater than 0");
22
+ }
23
+ this.permits = maxPermits;
24
+ this.maxPermits = maxPermits;
25
+ }
26
+
27
+ /**
28
+ * Acquire a permit. If no permits are available, waits until one becomes available.
29
+ */
30
+ async acquire(options?: {
31
+ timeout?: number;
32
+ signal?: AbortSignal;
33
+ }): Promise<void> {
34
+ if (this.disposed) {
35
+ throw new Error("Semaphore has been disposed");
36
+ }
37
+
38
+ if (options?.signal?.aborted) {
39
+ throw new Error("Operation was aborted");
40
+ }
41
+
42
+ if (this.permits > 0) {
43
+ this.permits--;
44
+ return;
45
+ }
46
+
47
+ // No permits available, wait in queue
48
+ return new Promise<void>((resolve, reject) => {
49
+ const operation: WaitingOperation = { resolve, reject };
50
+
51
+ // Set up timeout if provided
52
+ if (options?.timeout && options.timeout > 0) {
53
+ operation.timeout = setTimeout(() => {
54
+ this.removeFromQueue(operation);
55
+ reject(
56
+ new Error(`Semaphore acquire timeout after ${options.timeout}ms`)
57
+ );
58
+ }, options.timeout);
59
+ }
60
+
61
+ // Set up abort signal if provided
62
+ if (options?.signal) {
63
+ const abortHandler = () => {
64
+ this.removeFromQueue(operation);
65
+ reject(new Error("Operation was aborted"));
66
+ };
67
+ options.signal.addEventListener("abort", abortHandler, { once: true });
68
+
69
+ // Clean up the abort listener when operation completes
70
+ const originalResolve = operation.resolve;
71
+ const originalReject = operation.reject;
72
+
73
+ operation.resolve = () => {
74
+ options.signal!.removeEventListener("abort", abortHandler);
75
+ originalResolve();
76
+ };
77
+
78
+ operation.reject = (error: Error) => {
79
+ options.signal!.removeEventListener("abort", abortHandler);
80
+ originalReject(error);
81
+ };
82
+ }
83
+
84
+ this.waitingQueue.push(operation);
85
+ });
86
+ }
87
+
88
+ /**
89
+ * Release a permit, allowing waiting operations to proceed.
90
+ */
91
+ release(): void {
92
+ if (this.disposed) {
93
+ return;
94
+ }
95
+
96
+ if (this.waitingQueue.length > 0) {
97
+ // Give permit directly to next waiting operation
98
+ const nextOperation = this.waitingQueue.shift()!;
99
+
100
+ // Clear timeout if it exists
101
+ if (nextOperation.timeout) {
102
+ clearTimeout(nextOperation.timeout);
103
+ }
104
+
105
+ nextOperation.resolve();
106
+ } else {
107
+ // No one waiting, increment available permits (but don't exceed max)
108
+ this.permits = Math.min(this.permits + 1, this.maxPermits);
109
+ }
110
+ }
111
+
112
+ private removeFromQueue(operation: WaitingOperation): void {
113
+ const index = this.waitingQueue.indexOf(operation);
114
+ if (index !== -1) {
115
+ this.waitingQueue.splice(index, 1);
116
+
117
+ // Clear timeout if it exists
118
+ if (operation.timeout) {
119
+ clearTimeout(operation.timeout);
120
+ }
121
+ }
122
+ }
123
+
124
+ /**
125
+ * Execute a function with a permit, automatically releasing it afterwards.
126
+ */
127
+ async withPermit<T>(
128
+ fn: () => Promise<T>,
129
+ options?: { timeout?: number; signal?: AbortSignal }
130
+ ): Promise<T> {
131
+ await this.acquire(options);
132
+ try {
133
+ return await fn();
134
+ } finally {
135
+ this.release();
136
+ }
137
+ }
138
+
139
+ /**
140
+ * Dispose the semaphore, rejecting all waiting operations and preventing new ones.
141
+ */
142
+ dispose(): void {
143
+ if (this.disposed) {
144
+ return;
145
+ }
146
+
147
+ this.disposed = true;
148
+
149
+ // Reject all waiting operations
150
+ while (this.waitingQueue.length > 0) {
151
+ const operation = this.waitingQueue.shift()!;
152
+
153
+ // Clear timeout if it exists
154
+ if (operation.timeout) {
155
+ clearTimeout(operation.timeout);
156
+ }
157
+
158
+ operation.reject(new Error("Semaphore has been disposed"));
159
+ }
160
+ }
161
+
162
+ /**
163
+ * Get current number of available permits (for debugging)
164
+ */
165
+ getAvailablePermits(): number {
166
+ return this.permits;
167
+ }
168
+
169
+ /**
170
+ * Get current number of waiting operations (for debugging)
171
+ */
172
+ getWaitingCount(): number {
173
+ return this.waitingQueue.length;
174
+ }
175
+
176
+ /**
177
+ * Get maximum number of permits
178
+ */
179
+ getMaxPermits(): number {
180
+ return this.maxPermits;
181
+ }
182
+
183
+ /**
184
+ * Check if the semaphore has been disposed
185
+ */
186
+ isDisposed(): boolean {
187
+ return this.disposed;
188
+ }
189
+
190
+ /**
191
+ * Get metrics about the current state of the semaphore
192
+ */
193
+ getMetrics(): {
194
+ availablePermits: number;
195
+ waitingCount: number;
196
+ maxPermits: number;
197
+ utilization: number;
198
+ disposed: boolean;
199
+ } {
200
+ return {
201
+ availablePermits: this.permits,
202
+ waitingCount: this.waitingQueue.length,
203
+ maxPermits: this.maxPermits,
204
+ utilization: (this.maxPermits - this.permits) / this.maxPermits,
205
+ disposed: this.disposed,
206
+ };
207
+ }
208
+ }