@bluelibs/runner 3.4.2 → 4.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (375) hide show
  1. package/AI.md +621 -0
  2. package/README.md +1024 -577
  3. package/dist/context.d.ts +4 -8
  4. package/dist/context.js +5 -12
  5. package/dist/context.js.map +1 -1
  6. package/dist/define.d.ts +9 -113
  7. package/dist/define.js +29 -358
  8. package/dist/define.js.map +1 -1
  9. package/dist/definers/defineEvent.d.ts +2 -0
  10. package/dist/definers/defineEvent.js +23 -0
  11. package/dist/definers/defineEvent.js.map +1 -0
  12. package/dist/definers/defineHook.d.ts +6 -0
  13. package/dist/definers/defineHook.js +24 -0
  14. package/dist/definers/defineHook.js.map +1 -0
  15. package/dist/definers/defineOverride.d.ts +14 -0
  16. package/dist/definers/defineOverride.js +13 -0
  17. package/dist/definers/defineOverride.js.map +1 -0
  18. package/dist/definers/defineResource.d.ts +2 -0
  19. package/dist/definers/defineResource.js +69 -0
  20. package/dist/definers/defineResource.js.map +1 -0
  21. package/dist/definers/defineResourceMiddleware.d.ts +2 -0
  22. package/dist/definers/defineResourceMiddleware.js +42 -0
  23. package/dist/definers/defineResourceMiddleware.js.map +1 -0
  24. package/dist/definers/defineTag.d.ts +12 -0
  25. package/dist/definers/defineTag.js +106 -0
  26. package/dist/definers/defineTag.js.map +1 -0
  27. package/dist/definers/defineTask.d.ts +15 -0
  28. package/dist/definers/defineTask.js +42 -0
  29. package/dist/definers/defineTask.js.map +1 -0
  30. package/dist/definers/defineTaskMiddleware.d.ts +2 -0
  31. package/dist/definers/defineTaskMiddleware.js +42 -0
  32. package/dist/definers/defineTaskMiddleware.js.map +1 -0
  33. package/dist/definers/tools.d.ts +45 -0
  34. package/dist/definers/tools.js +75 -0
  35. package/dist/definers/tools.js.map +1 -0
  36. package/dist/defs.d.ts +16 -424
  37. package/dist/defs.js +26 -38
  38. package/dist/defs.js.map +1 -1
  39. package/dist/errors.d.ts +23 -8
  40. package/dist/errors.js +50 -10
  41. package/dist/errors.js.map +1 -1
  42. package/dist/globals/globalEvents.d.ts +15 -39
  43. package/dist/globals/globalEvents.js +20 -81
  44. package/dist/globals/globalEvents.js.map +1 -1
  45. package/dist/globals/globalMiddleware.d.ts +24 -17
  46. package/dist/globals/globalMiddleware.js +12 -4
  47. package/dist/globals/globalMiddleware.js.map +1 -1
  48. package/dist/globals/globalResources.d.ts +13 -28
  49. package/dist/globals/globalResources.js +15 -7
  50. package/dist/globals/globalResources.js.map +1 -1
  51. package/dist/globals/globalTags.d.ts +9 -0
  52. package/dist/globals/globalTags.js +23 -0
  53. package/dist/globals/globalTags.js.map +1 -0
  54. package/dist/globals/middleware/cache.middleware.d.ts +10 -17
  55. package/dist/globals/middleware/cache.middleware.js +4 -16
  56. package/dist/globals/middleware/cache.middleware.js.map +1 -1
  57. package/dist/globals/middleware/requireContext.middleware.d.ts +1 -1
  58. package/dist/globals/middleware/requireContext.middleware.js +5 -14
  59. package/dist/globals/middleware/requireContext.middleware.js.map +1 -1
  60. package/dist/globals/middleware/retry.middleware.d.ts +2 -1
  61. package/dist/globals/middleware/retry.middleware.js +32 -5
  62. package/dist/globals/middleware/retry.middleware.js.map +1 -1
  63. package/dist/globals/middleware/timeout.middleware.d.ts +2 -1
  64. package/dist/globals/middleware/timeout.middleware.js +31 -5
  65. package/dist/globals/middleware/timeout.middleware.js.map +1 -1
  66. package/dist/globals/resources/debug/debug.resource.d.ts +7 -0
  67. package/dist/globals/resources/debug/debug.resource.js +29 -0
  68. package/dist/globals/resources/debug/debug.resource.js.map +1 -0
  69. package/dist/globals/resources/debug/debug.tag.d.ts +2 -0
  70. package/dist/globals/resources/debug/debug.tag.js +12 -0
  71. package/dist/globals/resources/debug/debug.tag.js.map +1 -0
  72. package/dist/globals/resources/debug/debugConfig.resource.d.ts +22 -0
  73. package/dist/globals/resources/debug/debugConfig.resource.js +20 -0
  74. package/dist/globals/resources/debug/debugConfig.resource.js.map +1 -0
  75. package/dist/globals/resources/debug/executionTracker.middleware.d.ts +50 -0
  76. package/dist/globals/resources/debug/executionTracker.middleware.js +87 -0
  77. package/dist/globals/resources/debug/executionTracker.middleware.js.map +1 -0
  78. package/dist/globals/resources/debug/globalEvent.hook.d.ts +27 -0
  79. package/dist/globals/resources/debug/globalEvent.hook.js +38 -0
  80. package/dist/globals/resources/debug/globalEvent.hook.js.map +1 -0
  81. package/dist/globals/resources/debug/hook.hook.d.ts +25 -0
  82. package/dist/globals/resources/debug/hook.hook.js +42 -0
  83. package/dist/globals/resources/debug/hook.hook.js.map +1 -0
  84. package/dist/globals/resources/debug/index.d.ts +6 -0
  85. package/dist/{types → globals/resources/debug}/index.js +6 -11
  86. package/dist/globals/resources/debug/index.js.map +1 -0
  87. package/dist/globals/resources/debug/middleware.hook.d.ts +25 -0
  88. package/dist/globals/resources/debug/middleware.hook.js +71 -0
  89. package/dist/globals/resources/debug/middleware.hook.js.map +1 -0
  90. package/dist/globals/resources/debug/types.d.ts +25 -0
  91. package/dist/globals/resources/debug/types.js +65 -0
  92. package/dist/globals/resources/debug/types.js.map +1 -0
  93. package/dist/globals/resources/debug/utils.d.ts +2 -0
  94. package/dist/globals/resources/debug/utils.js +9 -0
  95. package/dist/globals/resources/debug/utils.js.map +1 -0
  96. package/dist/globals/resources/queue.resource.d.ts +3 -3
  97. package/dist/globals/resources/queue.resource.js.map +1 -1
  98. package/dist/globals/types.d.ts +1 -0
  99. package/dist/{task.types.js → globals/types.js} +2 -7
  100. package/dist/globals/types.js.map +1 -0
  101. package/dist/index.d.ts +58 -85
  102. package/dist/index.js +23 -10
  103. package/dist/index.js.map +1 -1
  104. package/dist/models/DependencyProcessor.d.ts +8 -6
  105. package/dist/models/DependencyProcessor.js +116 -33
  106. package/dist/models/DependencyProcessor.js.map +1 -1
  107. package/dist/models/EventManager.d.ts +127 -7
  108. package/dist/models/EventManager.js +251 -78
  109. package/dist/models/EventManager.js.map +1 -1
  110. package/dist/models/LogPrinter.d.ts +55 -0
  111. package/dist/models/LogPrinter.js +196 -0
  112. package/dist/models/LogPrinter.js.map +1 -0
  113. package/dist/models/Logger.d.ts +47 -27
  114. package/dist/models/Logger.js +133 -155
  115. package/dist/models/Logger.js.map +1 -1
  116. package/dist/models/MiddlewareManager.d.ts +86 -0
  117. package/dist/models/MiddlewareManager.js +409 -0
  118. package/dist/models/MiddlewareManager.js.map +1 -0
  119. package/dist/models/OverrideManager.d.ts +3 -3
  120. package/dist/models/OverrideManager.js +22 -7
  121. package/dist/models/OverrideManager.js.map +1 -1
  122. package/dist/models/ResourceInitializer.d.ts +4 -3
  123. package/dist/models/ResourceInitializer.js +12 -68
  124. package/dist/models/ResourceInitializer.js.map +1 -1
  125. package/dist/models/RunResult.d.ts +35 -0
  126. package/dist/models/RunResult.js +68 -0
  127. package/dist/models/RunResult.js.map +1 -0
  128. package/dist/models/Store.d.ts +30 -17
  129. package/dist/models/Store.js +87 -25
  130. package/dist/models/Store.js.map +1 -1
  131. package/dist/models/StoreRegistry.d.ts +34 -19
  132. package/dist/models/StoreRegistry.js +248 -100
  133. package/dist/models/StoreRegistry.js.map +1 -1
  134. package/dist/models/StoreValidator.d.ts +5 -7
  135. package/dist/models/StoreValidator.js +50 -17
  136. package/dist/models/StoreValidator.js.map +1 -1
  137. package/dist/models/TaskRunner.d.ts +3 -2
  138. package/dist/models/TaskRunner.js +6 -103
  139. package/dist/models/TaskRunner.js.map +1 -1
  140. package/dist/models/UnhandledError.d.ts +11 -0
  141. package/dist/models/UnhandledError.js +30 -0
  142. package/dist/models/UnhandledError.js.map +1 -0
  143. package/dist/models/index.d.ts +3 -0
  144. package/dist/models/index.js +3 -0
  145. package/dist/models/index.js.map +1 -1
  146. package/dist/{tools → models/utils}/findCircularDependencies.js +8 -16
  147. package/dist/models/utils/findCircularDependencies.js.map +1 -0
  148. package/dist/models/utils/safeStringify.d.ts +3 -0
  149. package/dist/models/utils/safeStringify.js +45 -0
  150. package/dist/models/utils/safeStringify.js.map +1 -0
  151. package/dist/processHooks.d.ts +2 -0
  152. package/dist/processHooks.js +70 -0
  153. package/dist/processHooks.js.map +1 -0
  154. package/dist/run.d.ts +14 -27
  155. package/dist/run.js +100 -36
  156. package/dist/run.js.map +1 -1
  157. package/dist/testing.d.ts +5 -4
  158. package/dist/testing.js +3 -2
  159. package/dist/testing.js.map +1 -1
  160. package/dist/tools/getCallerFile.d.ts +0 -8
  161. package/dist/tools/getCallerFile.js +0 -51
  162. package/dist/tools/getCallerFile.js.map +1 -1
  163. package/dist/types/contracts.d.ts +55 -0
  164. package/dist/types/contracts.js +4 -0
  165. package/dist/types/contracts.js.map +1 -0
  166. package/dist/types/event.d.ts +26 -7
  167. package/dist/types/event.js +1 -1
  168. package/dist/types/event.js.map +1 -1
  169. package/dist/types/hook.d.ts +21 -0
  170. package/dist/{models/StoreTypes.js → types/hook.js} +2 -1
  171. package/dist/types/hook.js.map +1 -0
  172. package/dist/types/meta.d.ts +6 -1
  173. package/dist/types/meta.js +4 -2
  174. package/dist/types/meta.js.map +1 -1
  175. package/dist/types/resource.d.ts +40 -52
  176. package/dist/types/resource.js +1 -0
  177. package/dist/types/resource.js.map +1 -1
  178. package/dist/types/resourceMiddleware.d.ts +47 -0
  179. package/dist/{middleware.types.js → types/resourceMiddleware.js} +1 -1
  180. package/dist/types/resourceMiddleware.js.map +1 -0
  181. package/dist/types/runner.d.ts +37 -0
  182. package/dist/types/{base.js → runner.js} +1 -1
  183. package/dist/types/runner.js.map +1 -0
  184. package/dist/types/storeTypes.d.ts +40 -0
  185. package/dist/types/{metadata.js → storeTypes.js} +1 -1
  186. package/dist/types/storeTypes.js.map +1 -0
  187. package/dist/types/symbols.d.ts +10 -21
  188. package/dist/types/symbols.js +17 -22
  189. package/dist/types/symbols.js.map +1 -1
  190. package/dist/types/tag.d.ts +46 -0
  191. package/dist/{resource.types.js → types/tag.js} +2 -1
  192. package/dist/types/tag.js.map +1 -0
  193. package/dist/types/task.d.ts +28 -52
  194. package/dist/types/task.js +1 -0
  195. package/dist/types/task.js.map +1 -1
  196. package/dist/types/taskMiddleware.d.ts +48 -0
  197. package/dist/{event.types.js → types/taskMiddleware.js} +1 -1
  198. package/dist/types/taskMiddleware.js.map +1 -0
  199. package/dist/types/utilities.d.ts +105 -6
  200. package/dist/types/utilities.js +16 -2
  201. package/dist/types/utilities.js.map +1 -1
  202. package/package.json +14 -5
  203. package/dist/cli/extract-docs.d.ts +0 -2
  204. package/dist/cli/extract-docs.js +0 -88
  205. package/dist/cli/extract-docs.js.map +0 -1
  206. package/dist/common.types.d.ts +0 -20
  207. package/dist/common.types.js +0 -4
  208. package/dist/common.types.js.map +0 -1
  209. package/dist/defs/core.d.ts +0 -144
  210. package/dist/defs/core.js +0 -6
  211. package/dist/defs/core.js.map +0 -1
  212. package/dist/defs/symbols.d.ts +0 -42
  213. package/dist/defs/symbols.js +0 -45
  214. package/dist/defs/symbols.js.map +0 -1
  215. package/dist/defs/tags.d.ts +0 -70
  216. package/dist/defs/tags.js +0 -6
  217. package/dist/defs/tags.js.map +0 -1
  218. package/dist/defs.returnTag.d.ts +0 -36
  219. package/dist/defs.returnTag.js +0 -4
  220. package/dist/defs.returnTag.js.map +0 -1
  221. package/dist/docs/introspect.d.ts +0 -7
  222. package/dist/docs/introspect.js +0 -199
  223. package/dist/docs/introspect.js.map +0 -1
  224. package/dist/docs/markdown.d.ts +0 -2
  225. package/dist/docs/markdown.js +0 -148
  226. package/dist/docs/markdown.js.map +0 -1
  227. package/dist/docs/model.d.ts +0 -62
  228. package/dist/docs/model.js +0 -33
  229. package/dist/docs/model.js.map +0 -1
  230. package/dist/event.types.d.ts +0 -18
  231. package/dist/event.types.js.map +0 -1
  232. package/dist/examples/express-mongo/index.d.ts +0 -0
  233. package/dist/examples/express-mongo/index.js +0 -3
  234. package/dist/examples/express-mongo/index.js.map +0 -1
  235. package/dist/examples/registrator-example.d.ts +0 -122
  236. package/dist/examples/registrator-example.js +0 -147
  237. package/dist/examples/registrator-example.js.map +0 -1
  238. package/dist/express/docsRouter.d.ts +0 -12
  239. package/dist/express/docsRouter.js +0 -54
  240. package/dist/express/docsRouter.js.map +0 -1
  241. package/dist/globalEvents.d.ts +0 -40
  242. package/dist/globalEvents.js +0 -94
  243. package/dist/globalEvents.js.map +0 -1
  244. package/dist/globalResources.d.ts +0 -10
  245. package/dist/globalResources.js +0 -43
  246. package/dist/globalResources.js.map +0 -1
  247. package/dist/middleware.types.d.ts +0 -40
  248. package/dist/middleware.types.js.map +0 -1
  249. package/dist/models/StoreConstants.d.ts +0 -14
  250. package/dist/models/StoreConstants.js +0 -19
  251. package/dist/models/StoreConstants.js.map +0 -1
  252. package/dist/models/StoreTypes.d.ts +0 -21
  253. package/dist/models/StoreTypes.js.map +0 -1
  254. package/dist/models/VarStore.d.ts +0 -17
  255. package/dist/models/VarStore.js +0 -60
  256. package/dist/models/VarStore.js.map +0 -1
  257. package/dist/resource.types.d.ts +0 -31
  258. package/dist/resource.types.js.map +0 -1
  259. package/dist/symbols.d.ts +0 -24
  260. package/dist/symbols.js +0 -29
  261. package/dist/symbols.js.map +0 -1
  262. package/dist/t1.d.ts +0 -1
  263. package/dist/t1.js +0 -13
  264. package/dist/t1.js.map +0 -1
  265. package/dist/task.types.d.ts +0 -55
  266. package/dist/task.types.js.map +0 -1
  267. package/dist/tools/findCircularDependencies.js.map +0 -1
  268. package/dist/tools/registratorId.d.ts +0 -4
  269. package/dist/tools/registratorId.js +0 -40
  270. package/dist/tools/registratorId.js.map +0 -1
  271. package/dist/tools/simpleHash.d.ts +0 -9
  272. package/dist/tools/simpleHash.js +0 -34
  273. package/dist/tools/simpleHash.js.map +0 -1
  274. package/dist/types/base-interfaces.d.ts +0 -18
  275. package/dist/types/base-interfaces.js +0 -6
  276. package/dist/types/base-interfaces.js.map +0 -1
  277. package/dist/types/base.d.ts +0 -13
  278. package/dist/types/base.js.map +0 -1
  279. package/dist/types/dependencies.d.ts +0 -51
  280. package/dist/types/dependencies.js +0 -3
  281. package/dist/types/dependencies.js.map +0 -1
  282. package/dist/types/dependency-core.d.ts +0 -14
  283. package/dist/types/dependency-core.js +0 -5
  284. package/dist/types/dependency-core.js.map +0 -1
  285. package/dist/types/events.d.ts +0 -52
  286. package/dist/types/events.js +0 -6
  287. package/dist/types/events.js.map +0 -1
  288. package/dist/types/hooks.d.ts +0 -16
  289. package/dist/types/hooks.js +0 -5
  290. package/dist/types/hooks.js.map +0 -1
  291. package/dist/types/index.d.ts +0 -8
  292. package/dist/types/index.js.map +0 -1
  293. package/dist/types/metadata.d.ts +0 -75
  294. package/dist/types/metadata.js.map +0 -1
  295. package/dist/types/middleware.d.ts +0 -63
  296. package/dist/types/middleware.js +0 -3
  297. package/dist/types/middleware.js.map +0 -1
  298. package/dist/types/registerable.d.ts +0 -10
  299. package/dist/types/registerable.js +0 -5
  300. package/dist/types/registerable.js.map +0 -1
  301. package/dist/types/resources.d.ts +0 -44
  302. package/dist/types/resources.js +0 -5
  303. package/dist/types/resources.js.map +0 -1
  304. package/dist/types/tasks.d.ts +0 -41
  305. package/dist/types/tasks.js +0 -5
  306. package/dist/types/tasks.js.map +0 -1
  307. package/src/__tests__/benchmark/benchmark.test.ts +0 -148
  308. package/src/__tests__/benchmark/task-benchmark.test.ts +0 -132
  309. package/src/__tests__/context.test.ts +0 -91
  310. package/src/__tests__/createTestResource.test.ts +0 -139
  311. package/src/__tests__/errors.test.ts +0 -341
  312. package/src/__tests__/globalEvents.test.ts +0 -542
  313. package/src/__tests__/globals/cache.middleware.test.ts +0 -772
  314. package/src/__tests__/globals/queue.resource.test.ts +0 -141
  315. package/src/__tests__/globals/requireContext.middleware.test.ts +0 -98
  316. package/src/__tests__/globals/retry.middleware.test.ts +0 -157
  317. package/src/__tests__/globals/timeout.middleware.test.ts +0 -88
  318. package/src/__tests__/index.helper.test.ts +0 -55
  319. package/src/__tests__/models/EventManager.test.ts +0 -585
  320. package/src/__tests__/models/Logger.test.ts +0 -519
  321. package/src/__tests__/models/Queue.test.ts +0 -189
  322. package/src/__tests__/models/ResourceInitializer.test.ts +0 -148
  323. package/src/__tests__/models/Semaphore.test.ts +0 -713
  324. package/src/__tests__/models/Store.test.ts +0 -227
  325. package/src/__tests__/models/TaskRunner.test.ts +0 -221
  326. package/src/__tests__/override.test.ts +0 -104
  327. package/src/__tests__/recursion/README.md +0 -3
  328. package/src/__tests__/recursion/a.resource.ts +0 -25
  329. package/src/__tests__/recursion/b.resource.ts +0 -33
  330. package/src/__tests__/recursion/c.resource.ts +0 -18
  331. package/src/__tests__/run.anonymous.test.ts +0 -706
  332. package/src/__tests__/run.dynamic-register-and-dependencies.test.ts +0 -1185
  333. package/src/__tests__/run.middleware.test.ts +0 -549
  334. package/src/__tests__/run.overrides.test.ts +0 -424
  335. package/src/__tests__/run.test.ts +0 -1040
  336. package/src/__tests__/setOutput.test.ts +0 -244
  337. package/src/__tests__/tags.test.ts +0 -396
  338. package/src/__tests__/tools/findCircularDependencies.test.ts +0 -217
  339. package/src/__tests__/tools/getCallerFile.test.ts +0 -179
  340. package/src/__tests__/typesafety.test.ts +0 -423
  341. package/src/__tests__/validation-edge-cases.test.ts +0 -111
  342. package/src/__tests__/validation-interface.test.ts +0 -428
  343. package/src/context.ts +0 -86
  344. package/src/define.ts +0 -480
  345. package/src/defs.returnTag.ts +0 -91
  346. package/src/defs.ts +0 -596
  347. package/src/errors.ts +0 -105
  348. package/src/globals/globalEvents.ts +0 -125
  349. package/src/globals/globalMiddleware.ts +0 -16
  350. package/src/globals/globalResources.ts +0 -53
  351. package/src/globals/middleware/cache.middleware.ts +0 -115
  352. package/src/globals/middleware/requireContext.middleware.ts +0 -36
  353. package/src/globals/middleware/retry.middleware.ts +0 -56
  354. package/src/globals/middleware/timeout.middleware.ts +0 -46
  355. package/src/globals/resources/queue.resource.ts +0 -34
  356. package/src/index.ts +0 -39
  357. package/src/models/DependencyProcessor.ts +0 -257
  358. package/src/models/EventManager.ts +0 -210
  359. package/src/models/Logger.ts +0 -282
  360. package/src/models/OverrideManager.ts +0 -79
  361. package/src/models/Queue.ts +0 -66
  362. package/src/models/ResourceInitializer.ts +0 -165
  363. package/src/models/Semaphore.ts +0 -208
  364. package/src/models/Store.ts +0 -193
  365. package/src/models/StoreConstants.ts +0 -18
  366. package/src/models/StoreRegistry.ts +0 -253
  367. package/src/models/StoreTypes.ts +0 -47
  368. package/src/models/StoreValidator.ts +0 -43
  369. package/src/models/TaskRunner.ts +0 -203
  370. package/src/models/index.ts +0 -8
  371. package/src/run.ts +0 -116
  372. package/src/testing.ts +0 -66
  373. package/src/tools/findCircularDependencies.ts +0 -69
  374. package/src/tools/getCallerFile.ts +0 -96
  375. /package/dist/{tools → models/utils}/findCircularDependencies.d.ts +0 -0
@@ -1,519 +0,0 @@
1
- import { Logger, ILog, LogLevels } from "../../models/Logger";
2
- import { EventManager } from "../../models/EventManager";
3
- import { globalEvents } from "../../globals/globalEvents";
4
-
5
- describe("Logger", () => {
6
- let logger: Logger;
7
- let mockEventManager: jest.Mocked<EventManager>;
8
- let originalEnv: any;
9
-
10
- beforeEach(() => {
11
- // Save original environment
12
- originalEnv = { ...process.env };
13
-
14
- // Clear environment variables that might affect tests
15
- delete process.env.RUNNER_DISABLE_LOGS;
16
- delete process.env.RUNNER_LOG_LEVEL;
17
-
18
- mockEventManager = new EventManager() as jest.Mocked<EventManager>;
19
- logger = new Logger(mockEventManager);
20
- });
21
-
22
- afterEach(() => {
23
- // Restore original environment
24
- process.env = originalEnv;
25
- });
26
-
27
- describe("log method", () => {
28
- it("should emit a log event with correct data", async () => {
29
- const testData = "Test log message";
30
- const testLevel = "info";
31
- mockEventManager.emit = jest.fn().mockResolvedValue(undefined);
32
- mockEventManager.hasListeners = jest.fn().mockReturnValue(true);
33
-
34
- logger.log(testLevel, testData);
35
-
36
- // Wait for setImmediate to execute
37
- await new Promise(setImmediate);
38
-
39
- expect(mockEventManager.emit).toHaveBeenCalledWith(
40
- globalEvents.log,
41
- expect.objectContaining({
42
- level: testLevel,
43
- message: testData,
44
- timestamp: expect.any(Date),
45
- }),
46
- "unknown"
47
- );
48
- });
49
-
50
- it("should handle different log levels", async () => {
51
- const levels: Array<LogLevels> = [
52
- "trace",
53
- "debug",
54
- "info",
55
- "warn",
56
- "error",
57
- "critical",
58
- ];
59
-
60
- mockEventManager.emit = jest.fn().mockResolvedValue(undefined);
61
- mockEventManager.hasListeners = jest.fn().mockReturnValue(true);
62
-
63
- for (const level of levels) {
64
- logger.log(level, `Test ${level} message`, { source: "testSource" });
65
- }
66
-
67
- // Wait for setImmediate to execute
68
- await new Promise(setImmediate);
69
-
70
- // Check all calls were made
71
- expect(mockEventManager.emit).toHaveBeenCalledTimes(levels.length);
72
- });
73
-
74
- it("should not emit events when there are no listeners", () => {
75
- mockEventManager.emit = jest.fn().mockResolvedValue(undefined);
76
- mockEventManager.hasListeners = jest.fn().mockReturnValue(false);
77
-
78
- logger.log("info", "Test message");
79
-
80
- // Should not emit events when no listeners
81
- expect(mockEventManager.emit).not.toHaveBeenCalled();
82
- });
83
- });
84
-
85
- describe("print method", () => {
86
- let consoleLogSpy: jest.SpyInstance;
87
-
88
- beforeEach(() => {
89
- consoleLogSpy = jest.spyOn(console, "log").mockImplementation();
90
- });
91
-
92
- afterEach(() => {
93
- consoleLogSpy.mockRestore();
94
- });
95
-
96
- it("should print log messages correctly", async () => {
97
- const testLog: ILog = {
98
- level: "info",
99
- source: "test",
100
- message: "Test log message",
101
- timestamp: new Date("2023-01-01T00:00:00Z"),
102
- };
103
-
104
- await logger.print(testLog);
105
-
106
- expect(consoleLogSpy).toHaveBeenCalledWith(
107
- expect.stringContaining("INFO")
108
- );
109
- });
110
-
111
- it("should handle Error objects in log data", () => {
112
- const testError = new Error("Test error");
113
- const testLog: ILog = {
114
- level: "error",
115
- message: "Operation failed",
116
- error: {
117
- name: testError.name,
118
- message: testError.message,
119
- stack: testError.stack,
120
- },
121
- timestamp: new Date("2023-01-01T00:00:00Z"),
122
- };
123
-
124
- logger.print(testLog);
125
-
126
- expect(consoleLogSpy).toHaveBeenCalledWith(
127
- expect.stringContaining("ERROR")
128
- );
129
- expect(consoleLogSpy).toHaveBeenCalledWith(
130
- expect.stringContaining("Error: Error")
131
- );
132
- expect(consoleLogSpy).toHaveBeenCalledWith(
133
- expect.stringContaining("Test error")
134
- );
135
- });
136
-
137
- it("should handle error objects without stack trace", () => {
138
- const testLog: ILog = {
139
- level: "error",
140
- message: "Operation failed",
141
- error: {
142
- name: "CustomError",
143
- message: "Something went wrong",
144
- },
145
- timestamp: new Date("2023-01-01T00:00:00Z"),
146
- };
147
-
148
- logger.print(testLog);
149
-
150
- expect(consoleLogSpy).toHaveBeenCalledWith(
151
- expect.stringContaining("ERROR")
152
- );
153
- expect(consoleLogSpy).toHaveBeenCalledWith(
154
- expect.stringContaining("Error: CustomError")
155
- );
156
- expect(consoleLogSpy).toHaveBeenCalledWith(
157
- expect.stringContaining("Something went wrong")
158
- );
159
- });
160
-
161
- it("should pretty-print structured data", () => {
162
- const testObject = { key: "value", nested: { foo: "bar" } };
163
- const testLog: ILog = {
164
- level: "debug",
165
- message: "Debug info",
166
- data: testObject,
167
- timestamp: new Date("2023-01-01T00:00:00Z"),
168
- };
169
-
170
- logger.print(testLog);
171
-
172
- expect(consoleLogSpy).toHaveBeenCalledWith(
173
- expect.stringContaining("DEBUG")
174
- );
175
- expect(consoleLogSpy).toHaveBeenCalledWith(
176
- expect.stringContaining('"key": "value"')
177
- );
178
- });
179
-
180
- it("should handle object message by stringifying it", () => {
181
- const objectMessage = { type: "user", action: "login" };
182
- const testLog: ILog = {
183
- level: "info",
184
- message: objectMessage as any,
185
- timestamp: new Date("2023-01-01T00:00:00Z"),
186
- };
187
-
188
- logger.print(testLog);
189
-
190
- expect(consoleLogSpy).toHaveBeenCalledWith(
191
- expect.stringContaining("INFO")
192
- );
193
- expect(consoleLogSpy).toHaveBeenCalledWith(
194
- expect.stringContaining(JSON.stringify(objectMessage, null, 2))
195
- );
196
- });
197
-
198
- it("should print context information when present", () => {
199
- const context = { userId: "123", requestId: "abc-def" };
200
- const testLog: ILog = {
201
- level: "warn",
202
- message: "Warning message",
203
- data: context,
204
- timestamp: new Date("2023-01-01T00:00:00Z"),
205
- };
206
-
207
- logger.print(testLog);
208
-
209
- expect(consoleLogSpy).toHaveBeenCalledWith(
210
- expect.stringContaining("WARN")
211
- );
212
- expect(consoleLogSpy).toHaveBeenCalledWith(
213
- expect.stringContaining('"userId": "123"')
214
- );
215
- });
216
-
217
- it("should print context from context field", () => {
218
- const context = { userId: "456", feature: "login", source: "auth" };
219
- const testLog: ILog = {
220
- level: "info",
221
- message: "User action",
222
- context: context,
223
- timestamp: new Date("2023-01-01T00:00:00Z"),
224
- };
225
-
226
- logger.print(testLog);
227
-
228
- expect(consoleLogSpy).toHaveBeenCalledWith(
229
- expect.stringContaining("INFO")
230
- );
231
- // Should show context but filter out 'source' since it's shown separately
232
- expect(consoleLogSpy).toHaveBeenCalledWith(
233
- expect.stringContaining("Context:")
234
- );
235
- expect(consoleLogSpy).toHaveBeenCalledWith(
236
- expect.stringContaining('"userId": "456"')
237
- );
238
- expect(consoleLogSpy).toHaveBeenCalledWith(
239
- expect.stringContaining('"feature": "login"')
240
- );
241
- });
242
-
243
- it("should handle empty context gracefully", () => {
244
- const testLog: ILog = {
245
- level: "debug",
246
- message: "Debug message",
247
- context: {},
248
- timestamp: new Date("2023-01-01T00:00:00Z"),
249
- };
250
-
251
- logger.print(testLog);
252
-
253
- expect(consoleLogSpy).toHaveBeenCalledWith(
254
- expect.stringContaining("DEBUG")
255
- );
256
- // Should not print context section for empty context
257
- expect(consoleLogSpy).not.toHaveBeenCalledWith(
258
- expect.stringContaining("Context:")
259
- );
260
- });
261
-
262
- it("should handle unknown log levels gracefully", () => {
263
- const testLog: ILog = {
264
- level: "unknown" as any,
265
- message: "Unknown level message",
266
- timestamp: new Date("2023-01-01T00:00:00Z"),
267
- };
268
-
269
- logger.print(testLog);
270
-
271
- expect(consoleLogSpy).toHaveBeenCalledWith(
272
- expect.stringContaining("UNKNOWN")
273
- );
274
- });
275
- });
276
-
277
- describe("log level methods", () => {
278
- const testLevels: Array<LogLevels> = [
279
- "trace",
280
- "debug",
281
- "info",
282
- "warn",
283
- "error",
284
- "critical",
285
- ];
286
-
287
- for (const level of testLevels) {
288
- it(`should call log method with ${level} level`, () => {
289
- const logSpy = jest.spyOn(logger, "log").mockImplementation();
290
-
291
- logger[level]("Test log message");
292
-
293
- expect(logSpy).toHaveBeenCalledWith(
294
- level,
295
- "Test log message",
296
- {} // the LogInfo parameter
297
- );
298
- });
299
- }
300
- });
301
-
302
- describe("with method", () => {
303
- it("should create a new logger with additional context", () => {
304
- const initialContext = { source: "initial" };
305
- const loggerWithContext = new Logger(mockEventManager, initialContext);
306
-
307
- const additionalContext = { userId: "123", feature: "auth" };
308
- const newLogger = loggerWithContext.with(additionalContext);
309
-
310
- expect(newLogger).toBeInstanceOf(Logger);
311
- expect(newLogger).not.toBe(loggerWithContext);
312
-
313
- // Test that the context is merged by checking the log call
314
- const logSpy = jest.spyOn(newLogger, "log").mockImplementation();
315
- newLogger.info("test message");
316
-
317
- expect(logSpy).toHaveBeenCalledWith("info", "test message", {});
318
- });
319
-
320
- it("should override context values when keys overlap", () => {
321
- const initialContext = { source: "initial", common: "old" };
322
- const loggerWithContext = new Logger(mockEventManager, initialContext);
323
-
324
- const newContext = { source: "override", newProp: "value" };
325
- const newLogger = loggerWithContext.with(newContext);
326
-
327
- // The new logger should have the overridden context
328
- expect(newLogger).toBeInstanceOf(Logger);
329
- });
330
-
331
- it("should use bound context in log calls", async () => {
332
- const boundContext = { source: "testSource", userId: "123" };
333
- const loggerWithContext = new Logger(mockEventManager, boundContext);
334
-
335
- mockEventManager.emit = jest.fn().mockResolvedValue(undefined);
336
- mockEventManager.hasListeners = jest.fn().mockReturnValue(true);
337
-
338
- loggerWithContext.log("info", "Test message");
339
-
340
- await new Promise(setImmediate);
341
-
342
- expect(mockEventManager.emit).toHaveBeenCalledWith(
343
- globalEvents.log,
344
- expect.objectContaining({
345
- source: "testSource",
346
- context: boundContext,
347
- }),
348
- "testSource"
349
- );
350
- });
351
- });
352
-
353
- describe("error handling", () => {
354
- it("should handle event emission errors gracefully", async () => {
355
- const consoleErrorSpy = jest.spyOn(console, "error").mockImplementation();
356
- const emitError = new Error("Event emission failed");
357
-
358
- mockEventManager.emit = jest.fn().mockRejectedValue(emitError);
359
- mockEventManager.hasListeners = jest.fn().mockReturnValue(true);
360
-
361
- logger.log("error", "Test error message");
362
-
363
- // Wait for setImmediate and promise rejection to be handled
364
- await new Promise(setImmediate);
365
- await new Promise((resolve) => setTimeout(resolve, 0));
366
-
367
- expect(consoleErrorSpy).toHaveBeenCalledWith(
368
- "Logger event emission failed:",
369
- emitError
370
- );
371
-
372
- consoleErrorSpy.mockRestore();
373
- });
374
-
375
- it("should extract error information from Error objects", async () => {
376
- mockEventManager.emit = jest.fn().mockResolvedValue(undefined);
377
- mockEventManager.hasListeners = jest.fn().mockReturnValue(true);
378
-
379
- const testError = new Error("Test error message");
380
- testError.name = "CustomError";
381
-
382
- logger.log("error", "Operation failed", { error: testError });
383
-
384
- // Wait for setImmediate to execute
385
- await new Promise(setImmediate);
386
-
387
- expect(mockEventManager.emit).toHaveBeenCalledWith(
388
- globalEvents.log,
389
- expect.objectContaining({
390
- level: "error",
391
- message: "Operation failed",
392
- error: {
393
- name: "CustomError",
394
- message: "Test error message",
395
- stack: expect.any(String),
396
- },
397
- timestamp: expect.any(Date),
398
- }),
399
- "unknown"
400
- );
401
- });
402
- });
403
-
404
- describe("default print threshold", () => {
405
- it("should default to 'info' level when no environment variables are set", () => {
406
- const logger = new Logger(mockEventManager);
407
- expect(logger.printThreshold).toBe("info");
408
- });
409
-
410
- it("should respect RUNNER_DISABLE_LOGS=true to disable logging", () => {
411
- process.env.RUNNER_DISABLE_LOGS = "true";
412
- const logger = new Logger(mockEventManager);
413
- expect(logger.printThreshold).toBeNull();
414
- });
415
-
416
- it("should respect RUNNER_DISABLE_LOGS=1 to disable logging", () => {
417
- process.env.RUNNER_DISABLE_LOGS = "1";
418
- const logger = new Logger(mockEventManager);
419
- expect(logger.printThreshold).toBeNull();
420
- });
421
-
422
- it("should respect RUNNER_LOG_LEVEL environment variable", () => {
423
- process.env.RUNNER_LOG_LEVEL = "error";
424
- const logger = new Logger(mockEventManager);
425
- expect(logger.printThreshold).toBe("error");
426
- });
427
-
428
- it("should ignore invalid RUNNER_LOG_LEVEL and use default", () => {
429
- process.env.RUNNER_LOG_LEVEL = "invalid_level";
430
- const logger = new Logger(mockEventManager);
431
- expect(logger.printThreshold).toBe("info");
432
- });
433
-
434
- it("should prioritize RUNNER_DISABLE_LOGS over RUNNER_LOG_LEVEL", () => {
435
- process.env.RUNNER_DISABLE_LOGS = "true";
436
- process.env.RUNNER_LOG_LEVEL = "debug";
437
- const logger = new Logger(mockEventManager);
438
- expect(logger.printThreshold).toBeNull();
439
- });
440
-
441
- it("should print info level logs by default", () => {
442
- const consoleLogSpy = jest.spyOn(console, "log").mockImplementation();
443
-
444
- const logger = new Logger(mockEventManager);
445
- logger.log("info", "This should be printed by default");
446
-
447
- expect(consoleLogSpy).toHaveBeenCalledWith(
448
- expect.stringContaining("This should be printed by default")
449
- );
450
-
451
- consoleLogSpy.mockRestore();
452
- });
453
-
454
- it("should not print debug level logs by default", () => {
455
- const consoleLogSpy = jest.spyOn(console, "log").mockImplementation();
456
-
457
- const logger = new Logger(mockEventManager);
458
- logger.log("debug", "This should not be printed by default");
459
-
460
- expect(consoleLogSpy).not.toHaveBeenCalledWith(
461
- expect.stringContaining("This should not be printed by default")
462
- );
463
-
464
- consoleLogSpy.mockRestore();
465
- });
466
- });
467
-
468
- it("should auto-print logs based on autoPrintLogsAfter option", () => {
469
- const autoPrintLevel: LogLevels = "warn";
470
- logger.setPrintThreshold(autoPrintLevel);
471
- const consoleLogSpy = jest.spyOn(console, "log").mockImplementation();
472
-
473
- const levels: Array<LogLevels> = [
474
- "trace",
475
- "debug",
476
- "info",
477
- "warn",
478
- "error",
479
- "critical",
480
- ];
481
-
482
- for (const level of levels) {
483
- logger.setPrintThreshold(level);
484
- logger.log(level, `Test ${level} message`);
485
-
486
- expect(consoleLogSpy).toHaveBeenCalledWith(
487
- expect.stringContaining(`Test ${level} message`)
488
- );
489
- }
490
-
491
- // ensure events with a higher level thatn auto print level are printed, and lower levels are not
492
- logger.setPrintThreshold("error");
493
- logger.log("info", "xx Test info message");
494
- logger.log("error", "xx Test error message");
495
-
496
- expect(consoleLogSpy).toHaveBeenCalledWith(
497
- expect.stringContaining("xx Test error message")
498
- );
499
-
500
- expect(consoleLogSpy).not.toHaveBeenCalledWith(
501
- expect.stringContaining("xx Test info message")
502
- );
503
-
504
- consoleLogSpy.mockRestore();
505
- });
506
-
507
- it("should disable auto-printing when setPrintThreshold is set to null", () => {
508
- const consoleLogSpy = jest.spyOn(console, "log").mockImplementation();
509
-
510
- // Set to null to disable auto-printing
511
- logger.setPrintThreshold(null);
512
-
513
- logger.log("error", "Should not be printed");
514
-
515
- expect(consoleLogSpy).not.toHaveBeenCalled();
516
-
517
- consoleLogSpy.mockRestore();
518
- });
519
- });
@@ -1,189 +0,0 @@
1
- // queue.test.ts
2
- import { Queue } from "../.."; // <-- adjust path if needed
3
-
4
- /* ------------------------------------------------------------------ */
5
- /* Helpers */
6
- /* ------------------------------------------------------------------ */
7
-
8
- /** Flush native micro‑tasks once (Promise jobs / process.nextTick). */
9
- const flushMicroTasks = () => Promise.resolve();
10
-
11
- /** Small delay helper for tests */
12
- const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
13
-
14
- /* ------------------------------------------------------------------ */
15
- /* Tests */
16
- /* ------------------------------------------------------------------ */
17
-
18
- describe("Queue", () => {
19
- it("runs tasks sequentially and returns their results in order", async () => {
20
- const q = new Queue();
21
-
22
- const started: number[] = [];
23
- const finished: number[] = [];
24
- let concurrent = 0;
25
- let maxConcurrent = 0;
26
-
27
- const taskFactory = (id: number) => async () => {
28
- started.push(id);
29
- concurrent++;
30
- maxConcurrent = Math.max(maxConcurrent, concurrent);
31
-
32
- // simulate async work with a real small delay
33
- await delay(1);
34
-
35
- finished.push(id);
36
- concurrent--;
37
- return id;
38
- };
39
-
40
- const p1 = q.run(taskFactory(1));
41
- const p2 = q.run(taskFactory(2));
42
- const p3 = q.run(taskFactory(3));
43
-
44
- const results = await Promise.all([p1, p2, p3]);
45
-
46
- expect(results).toEqual([1, 2, 3]);
47
- expect(started).toEqual([1, 2, 3]);
48
- expect(finished).toEqual([1, 2, 3]);
49
- expect(maxConcurrent).toBe(1); // never overlapped
50
- });
51
-
52
- it("detects dead‑lock when a queued task enqueues another task", async () => {
53
- const q = new Queue();
54
-
55
- const deadlock = () => q.run(async () => "nested"); // <-- illegal
56
-
57
- await expect(q.run(deadlock)).rejects.toThrow(/Dead‑lock/);
58
- });
59
-
60
- it("dispose() drains pending tasks and rejects new ones", async () => {
61
- const q = new Queue();
62
-
63
- const task = async () => {
64
- await delay(1);
65
- return "ok";
66
- };
67
-
68
- const p1 = q.run(task);
69
- const p2 = q.run(task);
70
-
71
- const disposeDone = q.dispose(); // default => { cancel: false }
72
-
73
- await expect(disposeDone).resolves.toBeUndefined();
74
- await expect(p1).resolves.toBe("ok");
75
- await expect(p2).resolves.toBe("ok");
76
-
77
- await expect(q.run(task)).rejects.toThrow(/disposed/);
78
- });
79
-
80
- it("dispose({ cancel: true }) aborts the running task", async () => {
81
- jest.useFakeTimers();
82
-
83
- const q = new Queue();
84
-
85
- /** Long‑running task that cooperates with AbortSignal. */
86
- const longTask = async (signal: AbortSignal) =>
87
- new Promise<void>((_res, rej) => {
88
- const tid = setTimeout(_res, 100); // never actually fires
89
- signal.addEventListener("abort", () => {
90
- clearTimeout(tid);
91
- rej(new Error("aborted"));
92
- });
93
- });
94
-
95
- const p = q.run(longTask);
96
-
97
- // Let the task start
98
- jest.advanceTimersByTime(0);
99
- await flushMicroTasks();
100
-
101
- const disposeDone = q.dispose({ cancel: true });
102
-
103
- await flushMicroTasks(); // allow rejection to propagate
104
-
105
- await expect(p).rejects.toThrow(/aborted/);
106
- await expect(disposeDone).resolves.toBeUndefined();
107
-
108
- jest.useRealTimers();
109
- });
110
-
111
- it("dispose() is idempotent - multiple calls should be safe", async () => {
112
- const q = new Queue();
113
-
114
- const task = async () => {
115
- await delay(1);
116
- return "ok";
117
- };
118
-
119
- const p = q.run(task);
120
-
121
- // First dispose call
122
- const dispose1 = q.dispose();
123
- // Second dispose call should return immediately (if (this.disposed) return;)
124
- const dispose2 = q.dispose();
125
- // Third dispose call should also return immediately
126
- const dispose3 = q.dispose();
127
-
128
- await expect(dispose1).resolves.toBeUndefined();
129
- await expect(dispose2).resolves.toBeUndefined();
130
- await expect(dispose3).resolves.toBeUndefined();
131
- await expect(p).resolves.toBe("ok");
132
-
133
- // Further dispose calls after everything is settled should also be safe
134
- const dispose4 = q.dispose();
135
- await expect(dispose4).resolves.toBeUndefined();
136
- });
137
-
138
- it("dispose() properly handles rejected tail promises", async () => {
139
- const q = new Queue();
140
-
141
- // Run a task first to establish the normal tail chain
142
- await q.run(async () => "setup");
143
-
144
- // Directly set the tail to a promise that will reject
145
- // This simulates an internal error scenario where the tail becomes rejected
146
- const rejectingPromise = Promise.reject(
147
- new Error("Simulated tail rejection")
148
- );
149
- (q as any).tail = rejectingPromise;
150
-
151
- // Spy on the rejecting promise to verify the catch is called
152
- const catchSpy = jest.spyOn(rejectingPromise, "catch");
153
-
154
- // The dispose method should handle this rejection with: await this.tail.catch(() => {})
155
- // This specifically tests the line: await this.tail.catch(() => {});
156
- await expect(q.dispose()).resolves.toBeUndefined();
157
-
158
- // Verify that the catch method was called (meaning the tail.catch() line was executed)
159
- expect(catchSpy).toHaveBeenCalledWith(expect.any(Function));
160
-
161
- // Verify the queue is properly disposed
162
- await expect(q.run(async () => "test")).rejects.toThrow(/disposed/);
163
- });
164
-
165
- it("should propagate task exceptions to the caller", async () => {
166
- const q = new Queue();
167
-
168
- // Test that exceptions are propagated, not swallowed
169
- const errorTask = async () => {
170
- await delay(1);
171
- throw new Error("Task exception");
172
- };
173
-
174
- const successTask = async () => {
175
- await delay(1);
176
- return "success";
177
- };
178
-
179
- // Exception should be catchable by the caller
180
- await expect(q.run(errorTask)).rejects.toThrow("Task exception");
181
-
182
- // Queue should still work for subsequent tasks
183
- await expect(q.run(successTask)).resolves.toBe("success");
184
-
185
- // Multiple exceptions should all be catchable
186
- await expect(q.run(errorTask)).rejects.toThrow("Task exception");
187
- await expect(q.run(errorTask)).rejects.toThrow("Task exception");
188
- });
189
- });