@navios/di 0.9.2 → 1.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 (174) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/README.md +28 -0
  3. package/coverage/block-navigation.js +1 -1
  4. package/coverage/clover.xml +1463 -3174
  5. package/coverage/coverage-final.json +56 -54
  6. package/coverage/index.html +179 -104
  7. package/coverage/sorter.js +21 -7
  8. package/coverage/src/{request-context-manager.mts.html → __tests__/gc/gc-test-utils.mts.html} +192 -231
  9. package/coverage/{lib → src/__tests__/gc}/index.html +25 -40
  10. package/coverage/src/container/abstract-container.mts.html +1066 -0
  11. package/coverage/src/container/container.mts.html +958 -0
  12. package/coverage/src/container/index.html +161 -0
  13. package/coverage/src/{testing → container}/index.mts.html +12 -9
  14. package/coverage/src/container/scoped-container.mts.html +907 -0
  15. package/coverage/src/decorators/factory.decorator.mts.html +68 -53
  16. package/coverage/src/decorators/index.html +34 -34
  17. package/coverage/src/decorators/index.mts.html +10 -10
  18. package/coverage/src/decorators/injectable.decorator.mts.html +144 -60
  19. package/coverage/src/enums/index.html +21 -21
  20. package/coverage/src/enums/index.mts.html +12 -12
  21. package/coverage/src/enums/injectable-scope.enum.mts.html +11 -8
  22. package/coverage/src/enums/injectable-type.enum.mts.html +10 -7
  23. package/coverage/src/errors/di-error.mts.html +380 -71
  24. package/coverage/src/errors/index.html +22 -127
  25. package/coverage/src/errors/index.mts.html +9 -33
  26. package/coverage/src/event-emitter.mts.html +35 -107
  27. package/coverage/src/index.html +14 -254
  28. package/coverage/src/index.mts.html +23 -50
  29. package/coverage/src/interfaces/container.interface.mts.html +370 -0
  30. package/coverage/src/interfaces/factory.interface.mts.html +12 -12
  31. package/coverage/src/interfaces/index.html +45 -30
  32. package/coverage/src/interfaces/index.mts.html +16 -13
  33. package/coverage/src/interfaces/on-service-destroy.interface.mts.html +1 -1
  34. package/coverage/src/interfaces/on-service-init.interface.mts.html +1 -1
  35. package/coverage/src/internal/context/async-local-storage.browser.mts.html +142 -0
  36. package/coverage/src/internal/context/async-local-storage.mts.html +292 -0
  37. package/coverage/src/{factory-context.mts.html → internal/context/async-local-storage.types.mts.html} +17 -17
  38. package/coverage/src/internal/context/factory-context.mts.html +142 -0
  39. package/coverage/src/internal/context/index.html +221 -0
  40. package/coverage/src/internal/context/index.mts.html +100 -0
  41. package/coverage/src/{service-locator-instance-holder.mts.html → internal/context/resolution-context.mts.html} +114 -78
  42. package/coverage/src/internal/context/service-initialization-context.mts.html +214 -0
  43. package/coverage/src/internal/context/sync-local-storage.mts.html +244 -0
  44. package/coverage/src/internal/core/index.html +206 -0
  45. package/coverage/src/internal/core/index.mts.html +103 -0
  46. package/coverage/src/internal/core/instance-resolver.mts.html +2533 -0
  47. package/coverage/src/{request-context-holder.mts.html → internal/core/name-resolver.mts.html} +245 -260
  48. package/coverage/src/{container.mts.html → internal/core/scope-tracker.mts.html} +352 -310
  49. package/coverage/src/{service-instantiator.mts.html → internal/core/service-initializer.mts.html} +254 -176
  50. package/coverage/src/internal/core/service-invalidator.mts.html +955 -0
  51. package/coverage/src/internal/core/token-resolver.mts.html +451 -0
  52. package/coverage/src/internal/holder/holder-storage.interface.mts.html +451 -0
  53. package/coverage/src/internal/holder/index.html +161 -0
  54. package/coverage/src/internal/holder/index.mts.html +94 -0
  55. package/coverage/src/internal/holder/instance-holder.mts.html +406 -0
  56. package/coverage/src/{service-locator.mts.html → internal/holder/unified-storage.mts.html} +376 -379
  57. package/coverage/{lib/testing → src/internal}/index.html +26 -11
  58. package/coverage/src/internal/index.mts.html +100 -0
  59. package/coverage/src/internal/lifecycle/circular-detector.mts.html +364 -0
  60. package/coverage/src/internal/lifecycle/index.html +146 -0
  61. package/coverage/src/internal/lifecycle/index.mts.html +91 -0
  62. package/coverage/src/{service-locator-event-bus.mts.html → internal/lifecycle/lifecycle-event-bus.mts.html} +104 -80
  63. package/coverage/src/internal/stub-factory-class.mts.html +133 -0
  64. package/coverage/src/symbols/index.html +14 -14
  65. package/coverage/src/symbols/index.mts.html +9 -9
  66. package/coverage/src/symbols/injectable-token.mts.html +9 -3
  67. package/coverage/src/testing/index.html +32 -32
  68. package/coverage/src/testing/test-container.mts.html +1576 -139
  69. package/coverage/src/testing/unit-test-container.mts.html +1888 -0
  70. package/coverage/src/token/index.html +146 -0
  71. package/coverage/{lib/testing/index.d.mts.html → src/token/index.mts.html} +11 -11
  72. package/coverage/src/{injection-token.mts.html → token/injection-token.mts.html} +225 -111
  73. package/coverage/src/{base-instance-holder-manager.mts.html → token/registry.mts.html} +188 -269
  74. package/coverage/src/{injector.mts.html → utils/default-injectors.mts.html} +31 -31
  75. package/coverage/src/utils/get-injectable-token.mts.html +19 -22
  76. package/coverage/src/utils/get-injectors.mts.html +684 -177
  77. package/coverage/src/utils/index.html +36 -36
  78. package/coverage/src/utils/index.mts.html +18 -12
  79. package/coverage/src/utils/types.mts.html +26 -11
  80. package/docs/examples/basic-usage.mts +1 -1
  81. package/docs/examples/factory-pattern.mts +3 -3
  82. package/docs/examples/request-scope-example.mts +1 -1
  83. package/docs/examples/service-lifecycle.mts +1 -1
  84. package/lib/browser/internal/core/instance-resolver.d.mts.map +1 -1
  85. package/lib/browser/internal/core/instance-resolver.mjs.map +1 -1
  86. package/lib/{container-D-0Ho3qL.d.cts → container-D3j3KuD9.d.mts} +5 -289
  87. package/lib/container-D3j3KuD9.d.mts.map +1 -0
  88. package/lib/{container-Bi0huFQX.mjs → container-qgHMgGNG.mjs} +3 -227
  89. package/lib/container-qgHMgGNG.mjs.map +1 -0
  90. package/lib/{container-CNiqesCL.d.mts → container-r1KP4F-n.d.cts} +5 -289
  91. package/lib/container-r1KP4F-n.d.cts.map +1 -0
  92. package/lib/{container-pmGNCZL_.cjs → container-ycYJgTq7.cjs} +41 -319
  93. package/lib/container-ycYJgTq7.cjs.map +1 -0
  94. package/lib/factory.decorator-D4mem6YQ.cjs +21 -0
  95. package/lib/factory.decorator-D4mem6YQ.cjs.map +1 -0
  96. package/lib/factory.decorator-_IPWcwQn.mjs +16 -0
  97. package/lib/factory.decorator-_IPWcwQn.mjs.map +1 -0
  98. package/lib/index.cjs +14 -24
  99. package/lib/index.cjs.map +1 -1
  100. package/lib/index.d.cts +3 -52
  101. package/lib/index.d.cts.map +1 -1
  102. package/lib/index.d.mts +3 -52
  103. package/lib/index.d.mts.map +1 -1
  104. package/lib/index.mjs +3 -13
  105. package/lib/index.mjs.map +1 -1
  106. package/lib/injectable.decorator-BNfWpjr_.d.cts +56 -0
  107. package/lib/injectable.decorator-BNfWpjr_.d.cts.map +1 -0
  108. package/lib/injectable.decorator-Bc05hRQU.d.mts +56 -0
  109. package/lib/injectable.decorator-Bc05hRQU.d.mts.map +1 -0
  110. package/lib/injectable.decorator-CyPrBzBN.mjs +227 -0
  111. package/lib/injectable.decorator-CyPrBzBN.mjs.map +1 -0
  112. package/lib/injectable.decorator-DbpiDrg-.cjs +281 -0
  113. package/lib/injectable.decorator-DbpiDrg-.cjs.map +1 -0
  114. package/lib/legacy-compat/index.cjs +114 -0
  115. package/lib/legacy-compat/index.cjs.map +1 -0
  116. package/lib/legacy-compat/index.d.cts +63 -0
  117. package/lib/legacy-compat/index.d.cts.map +1 -0
  118. package/lib/legacy-compat/index.d.mts +63 -0
  119. package/lib/legacy-compat/index.d.mts.map +1 -0
  120. package/lib/legacy-compat/index.mjs +111 -0
  121. package/lib/legacy-compat/index.mjs.map +1 -0
  122. package/lib/registry-DKbKWFvJ.d.cts +290 -0
  123. package/lib/registry-DKbKWFvJ.d.cts.map +1 -0
  124. package/lib/registry-n8JhJoxm.d.mts +290 -0
  125. package/lib/registry-n8JhJoxm.d.mts.map +1 -0
  126. package/lib/testing/index.cjs +23 -22
  127. package/lib/testing/index.cjs.map +1 -1
  128. package/lib/testing/index.d.cts +2 -1
  129. package/lib/testing/index.d.cts.map +1 -1
  130. package/lib/testing/index.d.mts +2 -1
  131. package/lib/testing/index.d.mts.map +1 -1
  132. package/lib/testing/index.mjs +2 -1
  133. package/lib/testing/index.mjs.map +1 -1
  134. package/package.json +11 -1
  135. package/project.json +8 -0
  136. package/src/__tests__/gc/basic-container.spec.mts +358 -0
  137. package/src/__tests__/gc/circular-dependencies.spec.mts +501 -0
  138. package/src/__tests__/gc/gc-test-utils.mts +136 -0
  139. package/src/__tests__/gc/memory-pressure.spec.mts +542 -0
  140. package/src/__tests__/gc/scoped-container.spec.mts +444 -0
  141. package/src/__tests__/gc/transient-services.spec.mts +326 -0
  142. package/src/__tests__/scope-upgrade.spec.mts +0 -18
  143. package/src/internal/core/instance-resolver.mts +0 -1
  144. package/src/legacy-compat/context-compat.mts +95 -0
  145. package/src/legacy-compat/factory.decorator.mts +37 -0
  146. package/src/legacy-compat/index.mts +16 -0
  147. package/src/legacy-compat/injectable.decorator.mts +41 -0
  148. package/tsdown.config.mts +1 -1
  149. package/vitest.config.mts +3 -7
  150. package/coverage/docs/examples/basic-usage.mts.html +0 -376
  151. package/coverage/docs/examples/factory-pattern.mts.html +0 -1039
  152. package/coverage/docs/examples/index.html +0 -176
  153. package/coverage/docs/examples/injection-tokens.mts.html +0 -760
  154. package/coverage/docs/examples/request-scope-example.mts.html +0 -847
  155. package/coverage/docs/examples/service-lifecycle.mts.html +0 -1162
  156. package/coverage/lib/_tsup-dts-rollup.d.mts.html +0 -3445
  157. package/coverage/lib/index.d.mts.html +0 -313
  158. package/coverage/src/errors/errors.enum.mts.html +0 -118
  159. package/coverage/src/errors/factory-not-found.mts.html +0 -118
  160. package/coverage/src/errors/factory-token-not-resolved.mts.html +0 -118
  161. package/coverage/src/errors/instance-destroying.mts.html +0 -118
  162. package/coverage/src/errors/instance-expired.mts.html +0 -118
  163. package/coverage/src/errors/instance-not-found.mts.html +0 -118
  164. package/coverage/src/errors/unknown-error.mts.html +0 -118
  165. package/coverage/src/instance-resolver.mts.html +0 -1762
  166. package/coverage/src/registry.mts.html +0 -247
  167. package/coverage/src/service-invalidator.mts.html +0 -1372
  168. package/coverage/src/service-locator-manager.mts.html +0 -340
  169. package/coverage/src/token-processor.mts.html +0 -607
  170. package/coverage/src/utils/defer.mts.html +0 -118
  171. package/lib/container-Bi0huFQX.mjs.map +0 -1
  172. package/lib/container-CNiqesCL.d.mts.map +0 -1
  173. package/lib/container-D-0Ho3qL.d.cts.map +0 -1
  174. package/lib/container-pmGNCZL_.cjs.map +0 -1
@@ -3,15 +3,15 @@
3
3
  <html lang="en">
4
4
 
5
5
  <head>
6
- <title>Code coverage report for src/request-context-manager.mts</title>
6
+ <title>Code coverage report for src/__tests__/gc/gc-test-utils.mts</title>
7
7
  <meta charset="utf-8" />
8
- <link rel="stylesheet" href="../prettify.css" />
9
- <link rel="stylesheet" href="../base.css" />
10
- <link rel="shortcut icon" type="image/x-icon" href="../favicon.png" />
8
+ <link rel="stylesheet" href="../../../prettify.css" />
9
+ <link rel="stylesheet" href="../../../base.css" />
10
+ <link rel="shortcut icon" type="image/x-icon" href="../../../favicon.png" />
11
11
  <meta name="viewport" content="width=device-width, initial-scale=1" />
12
12
  <style type='text/css'>
13
13
  .coverage-summary .sorter {
14
- background-image: url(../sort-arrow-sprite.png);
14
+ background-image: url(../../../sort-arrow-sprite.png);
15
15
  }
16
16
  </style>
17
17
  </head>
@@ -19,34 +19,34 @@
19
19
  <body>
20
20
  <div class='wrapper'>
21
21
  <div class='pad1'>
22
- <h1><a href="../index.html">All files</a> / <a href="index.html">src</a> request-context-manager.mts</h1>
22
+ <h1><a href="../../../index.html">All files</a> / <a href="index.html">src/__tests__/gc</a> gc-test-utils.mts</h1>
23
23
  <div class='clearfix'>
24
24
 
25
25
  <div class='fl pad1y space-right2'>
26
- <span class="strong">80.64% </span>
26
+ <span class="strong">3.33% </span>
27
27
  <span class="quiet">Statements</span>
28
- <span class='fraction'>75/93</span>
28
+ <span class='fraction'>1/30</span>
29
29
  </div>
30
30
 
31
31
 
32
32
  <div class='fl pad1y space-right2'>
33
- <span class="strong">83.33% </span>
33
+ <span class="strong">0% </span>
34
34
  <span class="quiet">Branches</span>
35
- <span class='fraction'>20/24</span>
35
+ <span class='fraction'>0/11</span>
36
36
  </div>
37
37
 
38
38
 
39
39
  <div class='fl pad1y space-right2'>
40
- <span class="strong">100% </span>
40
+ <span class="strong">0% </span>
41
41
  <span class="quiet">Functions</span>
42
- <span class='fraction'>8/8</span>
42
+ <span class='fraction'>0/12</span>
43
43
  </div>
44
44
 
45
45
 
46
46
  <div class='fl pad1y space-right2'>
47
- <span class="strong">80.64% </span>
47
+ <span class="strong">3.7% </span>
48
48
  <span class="quiet">Lines</span>
49
- <span class='fraction'>75/93</span>
49
+ <span class='fraction'>1/27</span>
50
50
  </div>
51
51
 
52
52
 
@@ -61,7 +61,7 @@
61
61
  </div>
62
62
  </template>
63
63
  </div>
64
- <div class='status-line high'></div>
64
+ <div class='status-line low'></div>
65
65
  <pre><table class="coverage">
66
66
  <tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
67
67
  <a name='L2'></a><a href='#L2'>2</a>
@@ -199,315 +199,276 @@
199
199
  <a name='L134'></a><a href='#L134'>134</a>
200
200
  <a name='L135'></a><a href='#L135'>135</a>
201
201
  <a name='L136'></a><a href='#L136'>136</a>
202
- <a name='L137'></a><a href='#L137'>137</a>
203
- <a name='L138'></a><a href='#L138'>138</a>
204
- <a name='L139'></a><a href='#L139'>139</a>
205
- <a name='L140'></a><a href='#L140'>140</a>
206
- <a name='L141'></a><a href='#L141'>141</a>
207
- <a name='L142'></a><a href='#L142'>142</a>
208
- <a name='L143'></a><a href='#L143'>143</a>
209
- <a name='L144'></a><a href='#L144'>144</a>
210
- <a name='L145'></a><a href='#L145'>145</a>
211
- <a name='L146'></a><a href='#L146'>146</a>
212
- <a name='L147'></a><a href='#L147'>147</a>
213
- <a name='L148'></a><a href='#L148'>148</a>
214
- <a name='L149'></a><a href='#L149'>149</a>
215
- <a name='L150'></a><a href='#L150'>150</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
202
+ <a name='L137'></a><a href='#L137'>137</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
216
203
  <span class="cline-any cline-neutral">&nbsp;</span>
217
- <span class="cline-any cline-yes">1x</span>
218
204
  <span class="cline-any cline-neutral">&nbsp;</span>
219
205
  <span class="cline-any cline-neutral">&nbsp;</span>
220
206
  <span class="cline-any cline-neutral">&nbsp;</span>
221
207
  <span class="cline-any cline-neutral">&nbsp;</span>
222
208
  <span class="cline-any cline-neutral">&nbsp;</span>
223
- <span class="cline-any cline-yes">1x</span>
224
- <span class="cline-any cline-yes">143x</span>
225
- <span class="cline-any cline-yes">143x</span>
226
209
  <span class="cline-any cline-neutral">&nbsp;</span>
227
- <span class="cline-any cline-yes">143x</span>
228
210
  <span class="cline-any cline-neutral">&nbsp;</span>
229
211
  <span class="cline-any cline-neutral">&nbsp;</span>
212
+ <span class="cline-any cline-yes">5x</span>
230
213
  <span class="cline-any cline-neutral">&nbsp;</span>
231
214
  <span class="cline-any cline-neutral">&nbsp;</span>
232
215
  <span class="cline-any cline-neutral">&nbsp;</span>
233
216
  <span class="cline-any cline-neutral">&nbsp;</span>
234
217
  <span class="cline-any cline-neutral">&nbsp;</span>
235
218
  <span class="cline-any cline-neutral">&nbsp;</span>
236
- <span class="cline-any cline-yes">143x</span>
237
- <span class="cline-any cline-yes">32x</span>
238
- <span class="cline-any cline-yes">32x</span>
239
- <span class="cline-any cline-yes">32x</span>
240
- <span class="cline-any cline-yes">32x</span>
241
- <span class="cline-any cline-yes">32x</span>
242
219
  <span class="cline-any cline-no">&nbsp;</span>
243
220
  <span class="cline-any cline-no">&nbsp;</span>
221
+ <span class="cline-any cline-neutral">&nbsp;</span>
222
+ <span class="cline-any cline-neutral">&nbsp;</span>
223
+ <span class="cline-any cline-neutral">&nbsp;</span>
224
+ <span class="cline-any cline-neutral">&nbsp;</span>
225
+ <span class="cline-any cline-neutral">&nbsp;</span>
226
+ <span class="cline-any cline-neutral">&nbsp;</span>
227
+ <span class="cline-any cline-neutral">&nbsp;</span>
244
228
  <span class="cline-any cline-no">&nbsp;</span>
229
+ <span class="cline-any cline-neutral">&nbsp;</span>
230
+ <span class="cline-any cline-neutral">&nbsp;</span>
231
+ <span class="cline-any cline-neutral">&nbsp;</span>
232
+ <span class="cline-any cline-neutral">&nbsp;</span>
233
+ <span class="cline-any cline-neutral">&nbsp;</span>
234
+ <span class="cline-any cline-neutral">&nbsp;</span>
245
235
  <span class="cline-any cline-no">&nbsp;</span>
246
236
  <span class="cline-any cline-neutral">&nbsp;</span>
247
- <span class="cline-any cline-yes">32x</span>
248
- <span class="cline-any cline-yes">32x</span>
249
- <span class="cline-any cline-yes">32x</span>
250
- <span class="cline-any cline-yes">32x</span>
251
- <span class="cline-any cline-yes">32x</span>
252
- <span class="cline-any cline-yes">32x</span>
253
- <span class="cline-any cline-yes">32x</span>
254
237
  <span class="cline-any cline-neutral">&nbsp;</span>
255
- <span class="cline-any cline-yes">32x</span>
256
- <span class="cline-any cline-yes">32x</span>
257
- <span class="cline-any cline-yes">32x</span>
258
- <span class="cline-any cline-yes">32x</span>
259
- <span class="cline-any cline-yes">32x</span>
260
238
  <span class="cline-any cline-neutral">&nbsp;</span>
261
239
  <span class="cline-any cline-neutral">&nbsp;</span>
262
240
  <span class="cline-any cline-neutral">&nbsp;</span>
263
241
  <span class="cline-any cline-neutral">&nbsp;</span>
264
242
  <span class="cline-any cline-neutral">&nbsp;</span>
265
- <span class="cline-any cline-yes">143x</span>
266
- <span class="cline-any cline-yes">26x</span>
267
- <span class="cline-any cline-yes">26x</span>
243
+ <span class="cline-any cline-neutral">&nbsp;</span>
244
+ <span class="cline-any cline-neutral">&nbsp;</span>
268
245
  <span class="cline-any cline-no">&nbsp;</span>
269
246
  <span class="cline-any cline-no">&nbsp;</span>
247
+ <span class="cline-any cline-neutral">&nbsp;</span>
270
248
  <span class="cline-any cline-no">&nbsp;</span>
249
+ <span class="cline-any cline-neutral">&nbsp;</span>
271
250
  <span class="cline-any cline-no">&nbsp;</span>
272
251
  <span class="cline-any cline-no">&nbsp;</span>
273
252
  <span class="cline-any cline-neutral">&nbsp;</span>
274
- <span class="cline-any cline-yes">26x</span>
275
- <span class="cline-any cline-yes">26x</span>
276
- <span class="cline-any cline-yes">26x</span>
253
+ <span class="cline-any cline-no">&nbsp;</span>
254
+ <span class="cline-any cline-neutral">&nbsp;</span>
255
+ <span class="cline-any cline-neutral">&nbsp;</span>
277
256
  <span class="cline-any cline-neutral">&nbsp;</span>
278
257
  <span class="cline-any cline-neutral">&nbsp;</span>
279
- <span class="cline-any cline-yes">26x</span>
280
- <span class="cline-any cline-yes">26x</span>
281
- <span class="cline-any cline-yes">21x</span>
282
- <span class="cline-any cline-yes">4x</span>
283
- <span class="cline-any cline-yes">4x</span>
284
- <span class="cline-any cline-yes">4x</span>
285
- <span class="cline-any cline-yes">4x</span>
286
- <span class="cline-any cline-yes">21x</span>
287
258
  <span class="cline-any cline-neutral">&nbsp;</span>
288
- <span class="cline-any cline-yes">26x</span>
289
259
  <span class="cline-any cline-neutral">&nbsp;</span>
290
260
  <span class="cline-any cline-neutral">&nbsp;</span>
291
- <span class="cline-any cline-yes">26x</span>
292
- <span class="cline-any cline-yes">26x</span>
293
261
  <span class="cline-any cline-neutral">&nbsp;</span>
294
262
  <span class="cline-any cline-neutral">&nbsp;</span>
295
- <span class="cline-any cline-yes">26x</span>
296
- <span class="cline-any cline-yes">24x</span>
297
- <span class="cline-any cline-yes">24x</span>
298
- <span class="cline-any cline-yes">24x</span>
299
263
  <span class="cline-any cline-neutral">&nbsp;</span>
300
- <span class="cline-any cline-yes">26x</span>
301
- <span class="cline-any cline-yes">26x</span>
302
- <span class="cline-any cline-yes">26x</span>
303
- <span class="cline-any cline-yes">26x</span>
264
+ <span class="cline-any cline-neutral">&nbsp;</span>
265
+ <span class="cline-any cline-neutral">&nbsp;</span>
266
+ <span class="cline-any cline-neutral">&nbsp;</span>
267
+ <span class="cline-any cline-no">&nbsp;</span>
268
+ <span class="cline-any cline-no">&nbsp;</span>
269
+ <span class="cline-any cline-neutral">&nbsp;</span>
270
+ <span class="cline-any cline-neutral">&nbsp;</span>
271
+ <span class="cline-any cline-neutral">&nbsp;</span>
272
+ <span class="cline-any cline-neutral">&nbsp;</span>
304
273
  <span class="cline-any cline-neutral">&nbsp;</span>
305
274
  <span class="cline-any cline-neutral">&nbsp;</span>
306
275
  <span class="cline-any cline-neutral">&nbsp;</span>
307
276
  <span class="cline-any cline-neutral">&nbsp;</span>
308
277
  <span class="cline-any cline-neutral">&nbsp;</span>
309
- <span class="cline-any cline-yes">143x</span>
310
- <span class="cline-any cline-yes">445x</span>
311
- <span class="cline-any cline-yes">445x</span>
312
278
  <span class="cline-any cline-neutral">&nbsp;</span>
313
279
  <span class="cline-any cline-neutral">&nbsp;</span>
314
280
  <span class="cline-any cline-neutral">&nbsp;</span>
315
281
  <span class="cline-any cline-neutral">&nbsp;</span>
316
282
  <span class="cline-any cline-neutral">&nbsp;</span>
317
- <span class="cline-any cline-yes">143x</span>
318
- <span class="cline-any cline-yes">3x</span>
319
- <span class="cline-any cline-yes">3x</span>
320
283
  <span class="cline-any cline-no">&nbsp;</span>
284
+ <span class="cline-any cline-neutral">&nbsp;</span>
321
285
  <span class="cline-any cline-no">&nbsp;</span>
322
286
  <span class="cline-any cline-no">&nbsp;</span>
287
+ <span class="cline-any cline-neutral">&nbsp;</span>
288
+ <span class="cline-any cline-no">&nbsp;</span>
323
289
  <span class="cline-any cline-no">&nbsp;</span>
324
- <span class="cline-any cline-yes">3x</span>
325
- <span class="cline-any cline-yes">3x</span>
326
290
  <span class="cline-any cline-neutral">&nbsp;</span>
327
291
  <span class="cline-any cline-neutral">&nbsp;</span>
292
+ <span class="cline-any cline-no">&nbsp;</span>
293
+ <span class="cline-any cline-neutral">&nbsp;</span>
294
+ <span class="cline-any cline-neutral">&nbsp;</span>
295
+ <span class="cline-any cline-no">&nbsp;</span>
296
+ <span class="cline-any cline-neutral">&nbsp;</span>
297
+ <span class="cline-any cline-neutral">&nbsp;</span>
298
+ <span class="cline-any cline-neutral">&nbsp;</span>
299
+ <span class="cline-any cline-neutral">&nbsp;</span>
300
+ <span class="cline-any cline-neutral">&nbsp;</span>
301
+ <span class="cline-any cline-neutral">&nbsp;</span>
302
+ <span class="cline-any cline-neutral">&nbsp;</span>
303
+ <span class="cline-any cline-no">&nbsp;</span>
328
304
  <span class="cline-any cline-neutral">&nbsp;</span>
329
305
  <span class="cline-any cline-neutral">&nbsp;</span>
330
306
  <span class="cline-any cline-neutral">&nbsp;</span>
331
- <span class="cline-any cline-yes">143x</span>
332
- <span class="cline-any cline-yes">41x</span>
333
- <span class="cline-any cline-yes">41x</span>
334
307
  <span class="cline-any cline-neutral">&nbsp;</span>
335
308
  <span class="cline-any cline-neutral">&nbsp;</span>
336
309
  <span class="cline-any cline-neutral">&nbsp;</span>
337
310
  <span class="cline-any cline-neutral">&nbsp;</span>
338
- <span class="cline-any cline-yes">143x</span>
339
- <span class="cline-any cline-yes">9x</span>
340
311
  <span class="cline-any cline-neutral">&nbsp;</span>
341
- <span class="cline-any cline-yes">9x</span>
342
- <span class="cline-any cline-yes">7x</span>
343
- <span class="cline-any cline-yes">7x</span>
344
- <span class="cline-any cline-yes">7x</span>
345
312
  <span class="cline-any cline-neutral">&nbsp;</span>
346
- <span class="cline-any cline-yes">2x</span>
347
- <span class="cline-any cline-yes">9x</span>
348
- <span class="cline-any cline-yes">9x</span>
349
313
  <span class="cline-any cline-neutral">&nbsp;</span>
350
314
  <span class="cline-any cline-neutral">&nbsp;</span>
351
- <span class="cline-any cline-yes">9x</span>
352
- <span class="cline-any cline-yes">2x</span>
353
- <span class="cline-any cline-yes">2x</span>
354
- <span class="cline-any cline-yes">2x</span>
355
315
  <span class="cline-any cline-no">&nbsp;</span>
316
+ <span class="cline-any cline-neutral">&nbsp;</span>
317
+ <span class="cline-any cline-neutral">&nbsp;</span>
318
+ <span class="cline-any cline-neutral">&nbsp;</span>
319
+ <span class="cline-any cline-neutral">&nbsp;</span>
320
+ <span class="cline-any cline-neutral">&nbsp;</span>
321
+ <span class="cline-any cline-neutral">&nbsp;</span>
322
+ <span class="cline-any cline-neutral">&nbsp;</span>
323
+ <span class="cline-any cline-neutral">&nbsp;</span>
324
+ <span class="cline-any cline-neutral">&nbsp;</span>
325
+ <span class="cline-any cline-neutral">&nbsp;</span>
326
+ <span class="cline-any cline-neutral">&nbsp;</span>
356
327
  <span class="cline-any cline-no">&nbsp;</span>
357
328
  <span class="cline-any cline-no">&nbsp;</span>
358
329
  <span class="cline-any cline-no">&nbsp;</span>
359
330
  <span class="cline-any cline-neutral">&nbsp;</span>
360
331
  <span class="cline-any cline-no">&nbsp;</span>
361
- <span class="cline-any cline-yes">2x</span>
362
- <span class="cline-any cline-yes">9x</span>
363
- <span class="cline-any cline-yes">143x</span>
364
- <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import type { RequestContextHolder } from './request-context-holder.mjs'
332
+ <span class="cline-any cline-no">&nbsp;</span>
333
+ <span class="cline-any cline-neutral">&nbsp;</span>
334
+ <span class="cline-any cline-neutral">&nbsp;</span>
335
+ <span class="cline-any cline-neutral">&nbsp;</span>
336
+ <span class="cline-any cline-neutral">&nbsp;</span>
337
+ <span class="cline-any cline-neutral">&nbsp;</span>
338
+ <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">/**
339
+ * Shared utilities for garbage collection tests
340
+ *
341
+ * These tests require Node.js to be started with --expose-gc flag
342
+ * to enable manual garbage collection triggering via global.gc()
343
+ */
365
344
  &nbsp;
366
- import { DefaultRequestContextHolder } from './request-context-holder.mjs'
345
+ /**
346
+ * Check if garbage collection is available
347
+ */
348
+ export const isGCAvailable = typeof global.gc === 'function'
367
349
  &nbsp;
368
350
  /**
369
- * RequestContextManager handles request context lifecycle management.
370
- * Extracted from ServiceLocator to improve separation of concerns.
351
+ * Force garbage collection if available
352
+ * Should be called after removing references to test objects
371
353
  */
372
- export class RequestContextManager {
373
- private readonly requestContexts = new Map&lt;string, RequestContextHolder&gt;()
374
- private currentRequestContext: RequestContextHolder | null = null
354
+ export function <span class="fstat-no" title="function not covered" >forceGC(): void {</span>
355
+ <span class="cstat-no" title="statement not covered" > if (isGCAvailable) {</span>
356
+ <span class="cstat-no" title="statement not covered" > global.gc!()</span>
357
+ }
358
+ }
375
359
  &nbsp;
376
- constructor(private readonly logger: Console | null = null) {}
360
+ /**
361
+ * Get current heap memory usage in bytes
362
+ */
363
+ export function <span class="fstat-no" title="function not covered" >getHeapUsed(): number {</span>
364
+ <span class="cstat-no" title="statement not covered" > return process.memoryUsage().heapUsed</span>
365
+ }
377
366
  &nbsp;
378
- /**
379
- * Begins a new request context with the given parameters.
380
- * @param requestId Unique identifier for this request
381
- * @param metadata Optional metadata for the request
382
- * @param priority Priority for resolution (higher = more priority)
383
- * @returns The created request context holder
384
- */
385
- beginRequest(
386
- requestId: string,
387
- metadata?: Record&lt;string, any&gt;,
388
- priority: number = 100,
389
- ): RequestContextHolder {
390
- if (this.requestContexts.has(requestId)) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
391
- <span class="cstat-no" title="statement not covered" > throw new Error(</span>
392
- <span class="cstat-no" title="statement not covered" > `[RequestContextManager] Request context ${requestId} already exists`,</span>
393
- <span class="cstat-no" title="statement not covered" > )</span>
394
- <span class="cstat-no" title="statement not covered" > }</span>
367
+ /**
368
+ * Get current heap memory usage in MB
369
+ */
370
+ export function <span class="fstat-no" title="function not covered" >getHeapUsedMB(): number {</span>
371
+ <span class="cstat-no" title="statement not covered" > return getHeapUsed() / 1024 / 1024</span>
372
+ }
395
373
  &nbsp;
396
- const contextHolder = new DefaultRequestContextHolder(
397
- requestId,
398
- priority,
399
- metadata,
400
- )
401
- this.requestContexts.set(requestId, contextHolder)
402
- this.currentRequestContext = contextHolder
374
+ /**
375
+ * Measure memory delta during a callback execution
376
+ * Forces GC before and after to get accurate measurements
377
+ */
378
+ export async function <span class="fstat-no" title="function not covered" >measureMemoryDelta(</span>
379
+ callback: () =&gt; Promise&lt;void&gt;
380
+ ): Promise&lt;{ before: number; after: number; delta: number }&gt; {
381
+ <span class="cstat-no" title="statement not covered" > forceGC()</span>
382
+ const before = <span class="cstat-no" title="statement not covered" >getHeapUsed()</span>
403
383
  &nbsp;
404
- this.logger?.log(
405
- `[RequestContextManager] Started request context: ${requestId}`,
406
- )
407
- return contextHolder
408
- }
384
+ <span class="cstat-no" title="statement not covered" > await callback()</span>
409
385
  &nbsp;
410
- /**
411
- * Ends a request context and cleans up all associated instances.
412
- * @param requestId The request ID to end
413
- */
414
- async endRequest(requestId: string): Promise&lt;void&gt; {
415
- const contextHolder = this.requestContexts.get(requestId)
416
- if (!contextHolder) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
417
- <span class="cstat-no" title="statement not covered" > this.logger?.warn(</span>
418
- <span class="cstat-no" title="statement not covered" > `[RequestContextManager] Request context ${requestId} not found`,</span>
419
- <span class="cstat-no" title="statement not covered" > )</span>
420
- <span class="cstat-no" title="statement not covered" > return</span>
421
- <span class="cstat-no" title="statement not covered" > }</span>
386
+ <span class="cstat-no" title="statement not covered" > forceGC()</span>
387
+ const after = <span class="cstat-no" title="statement not covered" >getHeapUsed()</span>
422
388
  &nbsp;
423
- this.logger?.log(
424
- `[RequestContextManager] Ending request context: ${requestId}`,
425
- )
389
+ <span class="cstat-no" title="statement not covered" > return {</span>
390
+ before,
391
+ after,
392
+ delta: after - before,
393
+ }
394
+ }
426
395
  &nbsp;
427
- // Clean up all request-scoped instances
428
- const cleanupPromises: Promise&lt;any&gt;[] = []
429
- for (const [, holder] of contextHolder.holders) {
430
- if (holder.destroyListeners.length &gt; 0) {
431
- cleanupPromises.push(
432
- Promise.all(holder.destroyListeners.map((listener) =&gt; listener())),
433
- )
434
- }
435
- }
396
+ /**
397
+ * Create a WeakRef tracker for an object
398
+ * Returns a function that checks if the object has been collected
399
+ */
400
+ export function <span class="fstat-no" title="function not covered" >createGCTracker&lt;T extends object&gt;(</span>
401
+ obj: T
402
+ ): () =&gt; { collected: boolean; ref: WeakRef&lt;T&gt; } {
403
+ const ref = <span class="cstat-no" title="statement not covered" >new WeakRef(obj)</span>
404
+ <span class="cstat-no" title="statement not covered" > return <span class="fstat-no" title="function not covered" >() =&gt; (<span class="cstat-no" title="statement not covered" >{</span></span></span>
405
+ collected: ref.deref() === undefined,
406
+ ref,
407
+ })
408
+ }
436
409
  &nbsp;
437
- await Promise.all(cleanupPromises)
410
+ /**
411
+ * Wait for an object to be garbage collected
412
+ * Returns true if collected within timeout, false otherwise
413
+ */
414
+ export async function <span class="fstat-no" title="function not covered" >waitForGC&lt;T extends object&gt;(</span>
415
+ ref: WeakRef&lt;T&gt;,
416
+ timeoutMs: number = <span class="branch-0 cbranch-no" title="branch not covered" >1000,</span>
417
+ intervalMs: number = <span class="branch-0 cbranch-no" title="branch not covered" >10</span>
418
+ ): Promise&lt;boolean&gt; {
419
+ const startTime = <span class="cstat-no" title="statement not covered" >Date.now()</span>
438
420
  &nbsp;
439
- // Clear the context
440
- contextHolder.clear()
441
- this.requestContexts.delete(requestId)
421
+ <span class="cstat-no" title="statement not covered" > while (Date.now() - startTime &lt; timeoutMs) {</span>
422
+ <span class="cstat-no" title="statement not covered" > forceGC()</span>
442
423
  &nbsp;
443
- // Reset current context if it was the one being ended
444
- if (this.currentRequestContext === contextHolder) {
445
- this.currentRequestContext =
446
- Array.from(this.requestContexts.values()).at(-1) ?? null
424
+ <span class="cstat-no" title="statement not covered" > if (ref.deref() === undefined) {</span>
425
+ <span class="cstat-no" title="statement not covered" > return true</span>
447
426
  }
448
427
  &nbsp;
449
- this.logger?.log(
450
- `[RequestContextManager] Request context ${requestId} ended`,
451
- )
452
- }
453
- &nbsp;
454
- /**
455
- * Gets the current request context.
456
- * @returns The current request context holder or null
457
- */
458
- getCurrentRequestContext(): RequestContextHolder | null {
459
- return this.currentRequestContext
428
+ <span class="cstat-no" title="statement not covered" > await new Promise(<span class="fstat-no" title="function not covered" >(r</span>esolve) =&gt; <span class="cstat-no" title="statement not covered" >setTimeout(resolve, intervalMs))</span></span>
460
429
  }
461
430
  &nbsp;
462
- /**
463
- * Sets the current request context.
464
- * @param requestId The request ID to set as current
465
- */
466
- setCurrentRequestContext(requestId: string): void {
467
- const contextHolder = this.requestContexts.get(requestId)
468
- if (!contextHolder) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
469
- <span class="cstat-no" title="statement not covered" > throw new Error(</span>
470
- <span class="cstat-no" title="statement not covered" > `[RequestContextManager] Request context ${requestId} not found`,</span>
471
- <span class="cstat-no" title="statement not covered" > )</span>
472
- <span class="cstat-no" title="statement not covered" > }</span>
473
- this.currentRequestContext = contextHolder
474
- }
431
+ <span class="cstat-no" title="statement not covered" > return false</span>
432
+ }
475
433
  &nbsp;
476
- /**
477
- * Gets all request contexts.
478
- * @returns Map of request contexts
479
- */
480
- getRequestContexts(): Map&lt;string, RequestContextHolder&gt; {
481
- return this.requestContexts
434
+ /**
435
+ * Create a large object to simulate memory pressure
436
+ * Size is in bytes (approximately)
437
+ */
438
+ export function <span class="fstat-no" title="function not covered" >createLargeObject(s</span>izeBytes: number): { data: Uint8Array } {
439
+ <span class="cstat-no" title="statement not covered" > return {</span>
440
+ data: new Uint8Array(sizeBytes),
482
441
  }
442
+ }
483
443
  &nbsp;
484
- /**
485
- * Clears all request contexts.
486
- */
487
- async clearAllRequestContexts(): Promise&lt;void&gt; {
488
- const requestIds = Array.from(this.requestContexts.keys())
444
+ /**
445
+ * Create multiple large objects to simulate batch allocations
446
+ */
447
+ export function <span class="fstat-no" title="function not covered" >createLargeObjects(</span>
448
+ count: number,
449
+ sizePerObject: number
450
+ ): Array&lt;{ data: Uint8Array }&gt; {
451
+ <span class="cstat-no" title="statement not covered" > return Array.from({ length: count }, <span class="fstat-no" title="function not covered" >() =&gt; <span class="cstat-no" title="statement not covered" >c</span>reateLargeObject(sizePerObject))</span></span>
452
+ }
489
453
  &nbsp;
490
- if (requestIds.length === 0) {
491
- this.logger?.log('[RequestContextManager] No request contexts to clear')
492
- return
493
- }
454
+ /**
455
+ * Memory threshold check - verifies memory is within expected bounds
456
+ * Useful for detecting memory leaks
457
+ */
458
+ export function <span class="fstat-no" title="function not covered" >assertMemoryWithinBounds(</span>
459
+ actualBytes: number,
460
+ expectedBytes: number,
461
+ tolerancePercent: number = <span class="branch-0 cbranch-no" title="branch not covered" >20</span>
462
+ ): void {
463
+ const tolerance = <span class="cstat-no" title="statement not covered" >expectedBytes * (tolerancePercent / 100)</span>
464
+ const lowerBound = <span class="cstat-no" title="statement not covered" >expectedBytes - tolerance</span>
465
+ const upperBound = <span class="cstat-no" title="statement not covered" >expectedBytes + tolerance</span>
494
466
  &nbsp;
495
- this.logger?.log(
496
- `[RequestContextManager] Clearing ${requestIds.length} request contexts: ${requestIds.join(', ')}`,
467
+ <span class="cstat-no" title="statement not covered" > if (actualBytes &lt; lowerBound || actualBytes &gt; upperBound) {</span>
468
+ <span class="cstat-no" title="statement not covered" > throw new Error(</span>
469
+ `Memory usage ${actualBytes} bytes is outside expected bounds ` +
470
+ `[${lowerBound}, ${upperBound}] (expected: ${expectedBytes} ±${tolerancePercent}%)`
497
471
  )
498
- &nbsp;
499
- // Clear request contexts sequentially to avoid race conditions
500
- for (const requestId of requestIds) {
501
- try {
502
- await this.endRequest(requestId)
503
- <span class="branch-0 cbranch-no" title="branch not covered" > } catch (error) {</span>
504
- <span class="cstat-no" title="statement not covered" > this.logger?.error(</span>
505
- <span class="cstat-no" title="statement not covered" > `[RequestContextManager] Error clearing request context ${requestId}:`,</span>
506
- <span class="cstat-no" title="statement not covered" > error,</span>
507
- <span class="cstat-no" title="statement not covered" > )</span>
508
- // Continue with other request contexts even if one fails
509
- <span class="cstat-no" title="statement not covered" > }</span>
510
- }
511
472
  }
512
473
  }
513
474
  &nbsp;</pre></td></tr></table></pre>
@@ -517,16 +478,16 @@ export class RequestContextManager {
517
478
  <div class='footer quiet pad2 space-top1 center small'>
518
479
  Code coverage generated by
519
480
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
520
- at 2025-09-21T17:47:07.632Z
481
+ at 2026-01-08T12:15:46.476Z
521
482
  </div>
522
- <script src="../prettify.js"></script>
483
+ <script src="../../../prettify.js"></script>
523
484
  <script>
524
485
  window.onload = function () {
525
486
  prettyPrint();
526
487
  };
527
488
  </script>
528
- <script src="../sorter.js"></script>
529
- <script src="../block-navigation.js"></script>
489
+ <script src="../../../sorter.js"></script>
490
+ <script src="../../../block-navigation.js"></script>
530
491
  </body>
531
492
  </html>
532
493