@bgord/bun 1.16.1 → 1.16.2

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 (239) hide show
  1. package/dist/antivirus-clamav.adapter.js +1 -1
  2. package/dist/antivirus-clamav.adapter.js.map +1 -1
  3. package/dist/antivirus-with-logger.adapter.d.ts +17 -0
  4. package/dist/antivirus-with-logger.adapter.d.ts.map +1 -0
  5. package/dist/antivirus-with-logger.adapter.js +35 -0
  6. package/dist/antivirus-with-logger.adapter.js.map +1 -0
  7. package/dist/antivirus-with-semaphore.adapter.d.ts +14 -0
  8. package/dist/antivirus-with-semaphore.adapter.d.ts.map +1 -0
  9. package/dist/antivirus-with-semaphore.adapter.js +10 -0
  10. package/dist/antivirus-with-semaphore.adapter.js.map +1 -0
  11. package/dist/csv-stringifier-noop.adapter.d.ts +5 -0
  12. package/dist/csv-stringifier-noop.adapter.d.ts.map +1 -0
  13. package/dist/csv-stringifier-noop.adapter.js +6 -0
  14. package/dist/csv-stringifier-noop.adapter.js.map +1 -0
  15. package/dist/environment-loader-encrypted.adapter.d.ts.map +1 -1
  16. package/dist/environment-loader-encrypted.adapter.js +0 -1
  17. package/dist/environment-loader-encrypted.adapter.js.map +1 -1
  18. package/dist/environment-loader-noop.adapter.d.ts.map +1 -1
  19. package/dist/environment-loader-noop.adapter.js +0 -1
  20. package/dist/environment-loader-noop.adapter.js.map +1 -1
  21. package/dist/environment-loader-process-safe.adapter.d.ts.map +1 -1
  22. package/dist/environment-loader-process-safe.adapter.js +0 -1
  23. package/dist/environment-loader-process-safe.adapter.js.map +1 -1
  24. package/dist/environment-loader-process.adapter.d.ts.map +1 -1
  25. package/dist/environment-loader-process.adapter.js +0 -1
  26. package/dist/environment-loader-process.adapter.js.map +1 -1
  27. package/dist/event-loop-lag.service.js +1 -1
  28. package/dist/event-loop-lag.service.js.map +1 -1
  29. package/dist/event-loop-utilization.service.d.ts.map +1 -1
  30. package/dist/event-loop-utilization.service.js +0 -2
  31. package/dist/event-loop-utilization.service.js.map +1 -1
  32. package/dist/event-store-with-logger.adapter.d.ts.map +1 -1
  33. package/dist/event-store-with-logger.adapter.js +0 -1
  34. package/dist/event-store-with-logger.adapter.js.map +1 -1
  35. package/dist/event-upcaster-chain.adapter.js +1 -1
  36. package/dist/event-upcaster-chain.adapter.js.map +1 -1
  37. package/dist/event-validator-registry.adapter.d.ts.map +1 -1
  38. package/dist/event-validator-registry.adapter.js +0 -1
  39. package/dist/event-validator-registry.adapter.js.map +1 -1
  40. package/dist/file-copier.adapter.d.ts.map +1 -1
  41. package/dist/file-copier.adapter.js +0 -2
  42. package/dist/file-copier.adapter.js.map +1 -1
  43. package/dist/file-writer-forgiving.adapter.d.ts +6 -0
  44. package/dist/file-writer-forgiving.adapter.d.ts.map +1 -0
  45. package/dist/file-writer-forgiving.adapter.js +10 -0
  46. package/dist/file-writer-forgiving.adapter.js.map +1 -0
  47. package/dist/graceful-shutdown.service.d.ts.map +1 -1
  48. package/dist/graceful-shutdown.service.js +1 -3
  49. package/dist/graceful-shutdown.service.js.map +1 -1
  50. package/dist/image-alpha-with-semaphore.adapter.d.ts +14 -0
  51. package/dist/image-alpha-with-semaphore.adapter.d.ts.map +1 -0
  52. package/dist/image-alpha-with-semaphore.adapter.js +10 -0
  53. package/dist/image-alpha-with-semaphore.adapter.js.map +1 -0
  54. package/dist/image-blur-with-semaphore.adapter.d.ts +14 -0
  55. package/dist/image-blur-with-semaphore.adapter.d.ts.map +1 -0
  56. package/dist/image-blur-with-semaphore.adapter.js +10 -0
  57. package/dist/image-blur-with-semaphore.adapter.js.map +1 -0
  58. package/dist/image-compressor-with-semaphore.adapter.d.ts +14 -0
  59. package/dist/image-compressor-with-semaphore.adapter.d.ts.map +1 -0
  60. package/dist/image-compressor-with-semaphore.adapter.js +10 -0
  61. package/dist/image-compressor-with-semaphore.adapter.js.map +1 -0
  62. package/dist/image-exif-clear-with-semaphore.adapter.d.ts +14 -0
  63. package/dist/image-exif-clear-with-semaphore.adapter.d.ts.map +1 -0
  64. package/dist/image-exif-clear-with-semaphore.adapter.js +10 -0
  65. package/dist/image-exif-clear-with-semaphore.adapter.js.map +1 -0
  66. package/dist/image-formatter-with-semaphore.adapter.d.ts +14 -0
  67. package/dist/image-formatter-with-semaphore.adapter.d.ts.map +1 -0
  68. package/dist/image-formatter-with-semaphore.adapter.js +10 -0
  69. package/dist/image-formatter-with-semaphore.adapter.js.map +1 -0
  70. package/dist/image-grayscale-with-semaphore.adapter.d.ts +14 -0
  71. package/dist/image-grayscale-with-semaphore.adapter.d.ts.map +1 -0
  72. package/dist/image-grayscale-with-semaphore.adapter.js +10 -0
  73. package/dist/image-grayscale-with-semaphore.adapter.js.map +1 -0
  74. package/dist/image-info-with-semaphore.adapter.d.ts +14 -0
  75. package/dist/image-info-with-semaphore.adapter.d.ts.map +1 -0
  76. package/dist/image-info-with-semaphore.adapter.js +10 -0
  77. package/dist/image-info-with-semaphore.adapter.js.map +1 -0
  78. package/dist/image-processor-with-semaphore.adapter.d.ts +14 -0
  79. package/dist/image-processor-with-semaphore.adapter.d.ts.map +1 -0
  80. package/dist/image-processor-with-semaphore.adapter.js +10 -0
  81. package/dist/image-processor-with-semaphore.adapter.js.map +1 -0
  82. package/dist/image-resizer-with-semaphore.adapter.d.ts +14 -0
  83. package/dist/image-resizer-with-semaphore.adapter.d.ts.map +1 -0
  84. package/dist/image-resizer-with-semaphore.adapter.js +10 -0
  85. package/dist/image-resizer-with-semaphore.adapter.js.map +1 -0
  86. package/dist/index.d.ts +15 -1
  87. package/dist/index.d.ts.map +1 -1
  88. package/dist/index.js +15 -1
  89. package/dist/index.js.map +1 -1
  90. package/dist/language-detector-header.strategy.d.ts.map +1 -1
  91. package/dist/language-detector-header.strategy.js +0 -2
  92. package/dist/language-detector-header.strategy.js.map +1 -1
  93. package/dist/logger.port.d.ts +1 -2
  94. package/dist/logger.port.d.ts.map +1 -1
  95. package/dist/logger.port.js.map +1 -1
  96. package/dist/prerequisite-verifier-dns.adapter.js +1 -1
  97. package/dist/prerequisite-verifier-dns.adapter.js.map +1 -1
  98. package/dist/prerequisite-verifier-with-retry.adapter.d.ts.map +1 -1
  99. package/dist/prerequisite-verifier-with-retry.adapter.js +0 -2
  100. package/dist/prerequisite-verifier-with-retry.adapter.js.map +1 -1
  101. package/dist/prerequisite-verifier.port.d.ts +2 -2
  102. package/dist/prerequisite-verifier.port.d.ts.map +1 -1
  103. package/dist/prerequisite-verifier.port.js +2 -2
  104. package/dist/prerequisite-verifier.port.js.map +1 -1
  105. package/dist/randomness-crypto.strategy.js +1 -1
  106. package/dist/randomness-crypto.strategy.js.map +1 -1
  107. package/dist/redactor-error-cause-depth-limit.strategy.d.ts.map +1 -1
  108. package/dist/redactor-error-cause-depth-limit.strategy.js +2 -6
  109. package/dist/redactor-error-cause-depth-limit.strategy.js.map +1 -1
  110. package/dist/redactor-error-stack-hide.strategy.d.ts.map +1 -1
  111. package/dist/redactor-error-stack-hide.strategy.js +3 -6
  112. package/dist/redactor-error-stack-hide.strategy.js.map +1 -1
  113. package/dist/redactor-mask.strategy.js +2 -2
  114. package/dist/redactor-mask.strategy.js.map +1 -1
  115. package/dist/redactor-metadata-compact-array.strategy.d.ts.map +1 -1
  116. package/dist/redactor-metadata-compact-array.strategy.js +2 -4
  117. package/dist/redactor-metadata-compact-array.strategy.js.map +1 -1
  118. package/dist/redactor-metadata-compact-object.strategy.d.ts.map +1 -1
  119. package/dist/redactor-metadata-compact-object.strategy.js +3 -5
  120. package/dist/redactor-metadata-compact-object.strategy.js.map +1 -1
  121. package/dist/remote-file-storage-noop.adapter.d.ts +4 -7
  122. package/dist/remote-file-storage-noop.adapter.d.ts.map +1 -1
  123. package/dist/remote-file-storage-noop.adapter.js +4 -26
  124. package/dist/remote-file-storage-noop.adapter.js.map +1 -1
  125. package/dist/remote-file-storage-with-logger.adapter.d.ts +21 -0
  126. package/dist/remote-file-storage-with-logger.adapter.d.ts.map +1 -0
  127. package/dist/remote-file-storage-with-logger.adapter.js +111 -0
  128. package/dist/remote-file-storage-with-logger.adapter.js.map +1 -0
  129. package/dist/retry.service.d.ts +0 -3
  130. package/dist/retry.service.d.ts.map +1 -1
  131. package/dist/retry.service.js +0 -3
  132. package/dist/retry.service.js.map +1 -1
  133. package/dist/semaphore.service.d.ts +10 -0
  134. package/dist/semaphore.service.d.ts.map +1 -0
  135. package/dist/semaphore.service.js +19 -0
  136. package/dist/semaphore.service.js.map +1 -0
  137. package/dist/setup-hono.service.d.ts.map +1 -1
  138. package/dist/setup-hono.service.js +1 -12
  139. package/dist/setup-hono.service.js.map +1 -1
  140. package/dist/shield-ip-whitelist.strategy.d.ts.map +1 -1
  141. package/dist/shield-ip-whitelist.strategy.js +0 -2
  142. package/dist/shield-ip-whitelist.strategy.js.map +1 -1
  143. package/dist/sse-registry.adapter.js +1 -1
  144. package/dist/sse-registry.adapter.js.map +1 -1
  145. package/dist/static-files-hono.service.d.ts.map +1 -1
  146. package/dist/static-files-hono.service.js +0 -2
  147. package/dist/static-files-hono.service.js.map +1 -1
  148. package/dist/translations-hono.handler.d.ts +1 -1
  149. package/dist/translations-hono.handler.d.ts.map +1 -1
  150. package/dist/translations-hono.handler.js.map +1 -1
  151. package/dist/woodchopper-diagnostics-collecting.strategy.js +2 -2
  152. package/dist/woodchopper-diagnostics-collecting.strategy.js.map +1 -1
  153. package/dist/woodchopper-diagnostics-console-error.strategy.js +2 -2
  154. package/dist/woodchopper-diagnostics-console-error.strategy.js.map +1 -1
  155. package/dist/woodchopper-dispatcher-async.strategy.d.ts.map +1 -1
  156. package/dist/woodchopper-dispatcher-async.strategy.js +0 -2
  157. package/dist/woodchopper-dispatcher-async.strategy.js.map +1 -1
  158. package/dist/woodchopper-sampling-correlation-id.strategy.js +1 -1
  159. package/dist/woodchopper-sampling-correlation-id.strategy.js.map +1 -1
  160. package/dist/woodchopper-sink-stderr.strategy.js +1 -1
  161. package/dist/woodchopper-sink-stderr.strategy.js.map +1 -1
  162. package/dist/woodchopper-sink-stdout-human.strategy.js +1 -1
  163. package/dist/woodchopper-sink-stdout-human.strategy.js.map +1 -1
  164. package/dist/woodchopper-sink-stdout.strategy.js +1 -1
  165. package/dist/woodchopper-sink-stdout.strategy.js.map +1 -1
  166. package/dist/woodchopper.d.ts.map +1 -1
  167. package/dist/woodchopper.js +1 -2
  168. package/dist/woodchopper.js.map +1 -1
  169. package/package.json +4 -3
  170. package/readme.md +15 -3
  171. package/src/antivirus-clamav.adapter.ts +1 -1
  172. package/src/antivirus-with-logger.adapter.ts +44 -0
  173. package/src/antivirus-with-semaphore.adapter.ts +13 -0
  174. package/src/csv-stringifier-noop.adapter.ts +7 -0
  175. package/src/environment-loader-encrypted.adapter.ts +0 -1
  176. package/src/environment-loader-noop.adapter.ts +0 -1
  177. package/src/environment-loader-process-safe.adapter.ts +0 -1
  178. package/src/environment-loader-process.adapter.ts +0 -1
  179. package/src/event-loop-lag.service.ts +1 -1
  180. package/src/event-loop-utilization.service.ts +0 -2
  181. package/src/event-store-with-logger.adapter.ts +0 -1
  182. package/src/event-upcaster-chain.adapter.ts +1 -1
  183. package/src/event-validator-registry.adapter.ts +0 -1
  184. package/src/file-copier.adapter.ts +0 -2
  185. package/src/file-writer-forgiving.adapter.ts +14 -0
  186. package/src/graceful-shutdown.service.ts +0 -2
  187. package/src/image-alpha-with-semaphore.adapter.ts +13 -0
  188. package/src/image-blur-with-semaphore.adapter.ts +13 -0
  189. package/src/image-compressor-with-semaphore.adapter.ts +13 -0
  190. package/src/image-exif-clear-with-semaphore.adapter.ts +13 -0
  191. package/src/image-formatter-with-semaphore.adapter.ts +13 -0
  192. package/src/image-grayscale-with-semaphore.adapter.ts +13 -0
  193. package/src/image-info-with-semaphore.adapter.ts +13 -0
  194. package/src/image-processor-with-semaphore.adapter.ts +13 -0
  195. package/src/image-resizer-with-semaphore.adapter.ts +13 -0
  196. package/src/index.ts +15 -1
  197. package/src/language-detector-header.strategy.ts +0 -2
  198. package/src/logger.port.ts +1 -2
  199. package/src/prerequisite-verifier-dns.adapter.ts +1 -1
  200. package/src/prerequisite-verifier-with-retry.adapter.ts +0 -2
  201. package/src/prerequisite-verifier.port.ts +3 -3
  202. package/src/randomness-crypto.strategy.ts +1 -1
  203. package/src/redactor-error-cause-depth-limit.strategy.ts +3 -7
  204. package/src/redactor-error-stack-hide.strategy.ts +4 -7
  205. package/src/redactor-mask.strategy.ts +2 -2
  206. package/src/redactor-metadata-compact-array.strategy.ts +2 -4
  207. package/src/redactor-metadata-compact-object.strategy.ts +3 -5
  208. package/src/remote-file-storage-noop.adapter.ts +5 -32
  209. package/src/remote-file-storage-with-logger.adapter.ts +140 -0
  210. package/src/retry.service.ts +0 -4
  211. package/src/semaphore.service.ts +26 -0
  212. package/src/setup-hono.service.ts +1 -12
  213. package/src/shield-ip-whitelist.strategy.ts +0 -2
  214. package/src/sse-registry.adapter.ts +1 -1
  215. package/src/static-files-hono.service.ts +0 -2
  216. package/src/translations-hono.handler.ts +1 -1
  217. package/src/woodchopper-diagnostics-collecting.strategy.ts +2 -2
  218. package/src/woodchopper-diagnostics-console-error.strategy.ts +2 -2
  219. package/src/woodchopper-dispatcher-async.strategy.ts +0 -2
  220. package/src/woodchopper-sampling-correlation-id.strategy.ts +1 -1
  221. package/src/woodchopper-sink-stderr.strategy.ts +1 -1
  222. package/src/woodchopper-sink-stdout-human.strategy.ts +1 -1
  223. package/src/woodchopper-sink-stdout.strategy.ts +1 -1
  224. package/src/woodchopper.ts +1 -2
  225. package/dist/deep-clone-with.d.ts +0 -4
  226. package/dist/deep-clone-with.d.ts.map +0 -1
  227. package/dist/deep-clone-with.js +0 -22
  228. package/dist/deep-clone-with.js.map +0 -1
  229. package/dist/error-normalizer.service.d.ts +0 -12
  230. package/dist/error-normalizer.service.d.ts.map +0 -1
  231. package/dist/error-normalizer.service.js +0 -24
  232. package/dist/error-normalizer.service.js.map +0 -1
  233. package/dist/is-plain-object.d.ts +0 -2
  234. package/dist/is-plain-object.d.ts.map +0 -1
  235. package/dist/is-plain-object.js +0 -7
  236. package/dist/is-plain-object.js.map +0 -1
  237. package/src/deep-clone-with.ts +0 -31
  238. package/src/error-normalizer.service.ts +0 -32
  239. package/src/is-plain-object.ts +0 -7
@@ -0,0 +1,13 @@
1
+ import type * as tools from "@bgord/tools";
2
+ import type { ImageFormatterPort, ImageFormatterStrategy } from "./image-formatter.port";
3
+ import type { Semaphore } from "./semaphore.service";
4
+
5
+ type Dependencies = { inner: ImageFormatterPort; semaphore: Semaphore };
6
+
7
+ export class ImageFormatterWithSemaphoreAdapter implements ImageFormatterPort {
8
+ constructor(private readonly deps: Dependencies) {}
9
+
10
+ async format(recipe: ImageFormatterStrategy): Promise<tools.FilePathRelative | tools.FilePathAbsolute> {
11
+ return this.deps.semaphore.run(() => this.deps.inner.format(recipe));
12
+ }
13
+ }
@@ -0,0 +1,13 @@
1
+ import type * as tools from "@bgord/tools";
2
+ import type { ImageGrayscalePort, ImageGrayscaleStrategy } from "./image-grayscale.port";
3
+ import type { Semaphore } from "./semaphore.service";
4
+
5
+ type Dependencies = { inner: ImageGrayscalePort; semaphore: Semaphore };
6
+
7
+ export class ImageGrayscaleWithSemaphoreAdapter implements ImageGrayscalePort {
8
+ constructor(private readonly deps: Dependencies) {}
9
+
10
+ async grayscale(recipe: ImageGrayscaleStrategy): Promise<tools.FilePathRelative | tools.FilePathAbsolute> {
11
+ return this.deps.semaphore.run(() => this.deps.inner.grayscale(recipe));
12
+ }
13
+ }
@@ -0,0 +1,13 @@
1
+ import type * as tools from "@bgord/tools";
2
+ import type { ImageInfoPort, ImageInfoType } from "./image-info.port";
3
+ import type { Semaphore } from "./semaphore.service";
4
+
5
+ type Dependencies = { inner: ImageInfoPort; semaphore: Semaphore };
6
+
7
+ export class ImageInfoWithSemaphoreAdapter implements ImageInfoPort {
8
+ constructor(private readonly deps: Dependencies) {}
9
+
10
+ async inspect(input: tools.FilePathRelative | tools.FilePathAbsolute): Promise<ImageInfoType> {
11
+ return this.deps.semaphore.run(() => this.deps.inner.inspect(input));
12
+ }
13
+ }
@@ -0,0 +1,13 @@
1
+ import type * as tools from "@bgord/tools";
2
+ import type { ImageProcessorPort, ImageProcessorStrategy } from "./image-processor.port";
3
+ import type { Semaphore } from "./semaphore.service";
4
+
5
+ type Dependencies = { inner: ImageProcessorPort; semaphore: Semaphore };
6
+
7
+ export class ImageProcessorWithSemaphoreAdapter implements ImageProcessorPort {
8
+ constructor(private readonly deps: Dependencies) {}
9
+
10
+ async process(recipe: ImageProcessorStrategy): Promise<tools.FilePathRelative | tools.FilePathAbsolute> {
11
+ return this.deps.semaphore.run(() => this.deps.inner.process(recipe));
12
+ }
13
+ }
@@ -0,0 +1,13 @@
1
+ import type * as tools from "@bgord/tools";
2
+ import type { ImageResizerPort, ImageResizerStrategy } from "./image-resizer.port";
3
+ import type { Semaphore } from "./semaphore.service";
4
+
5
+ type Dependencies = { inner: ImageResizerPort; semaphore: Semaphore };
6
+
7
+ export class ImageResizerWithSemaphoreAdapter implements ImageResizerPort {
8
+ constructor(private readonly deps: Dependencies) {}
9
+
10
+ async resize(recipe: ImageResizerStrategy): Promise<tools.FilePathRelative | tools.FilePathAbsolute> {
11
+ return this.deps.semaphore.run(() => this.deps.inner.resize(recipe));
12
+ }
13
+ }
package/src/index.ts CHANGED
@@ -24,6 +24,8 @@ export * from "./alert-message.vo";
24
24
  export * from "./antivirus.port";
25
25
  export * from "./antivirus-clamav.adapter";
26
26
  export * from "./antivirus-noop.adapter";
27
+ export * from "./antivirus-with-logger.adapter";
28
+ export * from "./antivirus-with-semaphore.adapter";
27
29
  export * from "./api-version.middleware";
28
30
  export * from "./api-version-hono.middleware";
29
31
  export * from "./auth-session-reader.port";
@@ -70,6 +72,7 @@ export * from "./crypto-key-provider-noop.adapter";
70
72
  export * from "./crypto-key-provider-with-cache.adapter";
71
73
  export * from "./csv-stringifier.adapter";
72
74
  export * from "./csv-stringifier.port";
75
+ export * from "./csv-stringifier-noop.adapter";
73
76
  export * from "./directory-ensurer.adapter";
74
77
  export * from "./directory-ensurer.port";
75
78
  export * from "./directory-ensurer-noop.adapter";
@@ -87,7 +90,6 @@ export * from "./environment-loader-encrypted.adapter";
87
90
  export * from "./environment-loader-noop.adapter";
88
91
  export * from "./environment-loader-process.adapter";
89
92
  export * from "./environment-loader-process-safe.adapter";
90
- export * from "./error-normalizer.service";
91
93
  export * from "./etag-extractor.middleware";
92
94
  export * from "./etag-extractor-hono.middleware";
93
95
  export * from "./event.types";
@@ -153,6 +155,7 @@ export * from "./file-uploader.middleware";
153
155
  export * from "./file-uploader-hono.middleware";
154
156
  export * from "./file-writer.adapter";
155
157
  export * from "./file-writer.port";
158
+ export * from "./file-writer-forgiving.adapter";
156
159
  export * from "./file-writer-noop.adapter";
157
160
  export * from "./fnv1a32.service";
158
161
  export * from "./graceful-shutdown.service";
@@ -183,30 +186,39 @@ export * from "./id-provider-deterministic.adapter";
183
186
  export * from "./image-alpha.port";
184
187
  export * from "./image-alpha-noop.adapter";
185
188
  export * from "./image-alpha-sharp.adapter";
189
+ export * from "./image-alpha-with-semaphore.adapter";
186
190
  export * from "./image-blur.port";
187
191
  export * from "./image-blur-noop.adapter";
188
192
  export * from "./image-blur-sharp.adapter";
193
+ export * from "./image-blur-with-semaphore.adapter";
189
194
  export * from "./image-compressor.port";
190
195
  export * from "./image-compressor-noop.adapter";
191
196
  export * from "./image-compressor-sharp.adapter";
197
+ export * from "./image-compressor-with-semaphore.adapter";
192
198
  export * from "./image-exif-clear.port";
193
199
  export * from "./image-exif-clear-noop.adapter";
194
200
  export * from "./image-exif-clear-sharp.adapter";
201
+ export * from "./image-exif-clear-with-semaphore.adapter";
195
202
  export * from "./image-formatter.port";
196
203
  export * from "./image-formatter-noop.adapter";
197
204
  export * from "./image-formatter-sharp.adapter";
205
+ export * from "./image-formatter-with-semaphore.adapter";
198
206
  export * from "./image-grayscale.port";
199
207
  export * from "./image-grayscale-noop.adapter";
200
208
  export * from "./image-grayscale-sharp.adapter";
209
+ export * from "./image-grayscale-with-semaphore.adapter";
201
210
  export * from "./image-info.port";
202
211
  export * from "./image-info-noop.adapter";
203
212
  export * from "./image-info-sharp.adapter";
213
+ export * from "./image-info-with-semaphore.adapter";
204
214
  export * from "./image-processor.port";
205
215
  export * from "./image-processor-noop.adapter";
206
216
  export * from "./image-processor-sharp.adapter";
217
+ export * from "./image-processor-with-semaphore.adapter";
207
218
  export * from "./image-resizer.port";
208
219
  export * from "./image-resizer-noop.adapter";
209
220
  export * from "./image-resizer-sharp.adapter";
221
+ export * from "./image-resizer-with-semaphore.adapter";
210
222
  export * from "./in-flight-requests-hono.middleware";
211
223
  export * from "./in-flight-requests-tracker.service";
212
224
  export * from "./instrumentation.service";
@@ -324,6 +336,7 @@ export * from "./redactor-noop.strategy";
324
336
  export * from "./remote-file-storage.port";
325
337
  export * from "./remote-file-storage-disk.adapter";
326
338
  export * from "./remote-file-storage-noop.adapter";
339
+ export * from "./remote-file-storage-with-logger.adapter";
327
340
  export * from "./request-context.port";
328
341
  export * from "./request-context-hono.adapter";
329
342
  export * from "./retry.service";
@@ -357,6 +370,7 @@ export * from "./security-rule-or.strategy";
357
370
  export * from "./security-rule-pass.strategy";
358
371
  export * from "./security-rule-user-agent.strategy";
359
372
  export * from "./security-rule-violation-threshold.strategy";
373
+ export * from "./semaphore.service";
360
374
  export * from "./setup-hono.service";
361
375
  export * from "./shield-api-key.strategy";
362
376
  export * from "./shield-api-key-hono.strategy";
@@ -12,11 +12,9 @@ export class LanguageDetectorHeaderStrategy<T extends tools.LanguageType>
12
12
  if (!header) return null;
13
13
 
14
14
  // Example Accept-Language header: en-US,en;q=0.9,pl;q=0.8
15
- // Stryker disable all
16
15
  const incoming = header
17
16
  .split(",")
18
17
  .map((language) => language.split(";")[0]?.trim().toLowerCase().split("-")[0]);
19
- // Stryker restore all
20
18
 
21
19
  return incoming.find((language) => languages.isSupported(language)) ?? null;
22
20
  }
@@ -1,6 +1,5 @@
1
1
  import type * as tools from "@bgord/tools";
2
2
  import type { CorrelationIdType } from "./correlation-id.vo";
3
- import type { NormalizedError } from "./error-normalizer.service";
4
3
  import type { NodeEnvironmentEnum } from "./node-env.vo";
5
4
 
6
5
  export type LoggerAppType = string;
@@ -50,7 +49,7 @@ export type LoggerEntryBare = Omit<
50
49
  AdapterInjectedFields
51
50
  >;
52
51
 
53
- export type LoggerEntryBareWithError = Omit<LoggerEntryBare, "error"> & { error: NormalizedError };
52
+ export type LoggerEntryBareWithError = Omit<LoggerEntryBare, "error"> & { error: tools.NormalizedError };
54
53
 
55
54
  export type LoggerEntry = LogCoreType | LogHttpType | LogWarnType | LogErrorType;
56
55
 
@@ -1,4 +1,4 @@
1
- import dns from "dns/promises";
1
+ import dns from "node:dns/promises";
2
2
  import {
3
3
  PrerequisiteVerification,
4
4
  type PrerequisiteVerificationResult,
@@ -21,9 +21,7 @@ export class PrerequisiteVerifierWithRetryAdapter implements PrerequisiteVerifie
21
21
  return await new Retry(this.deps).run<PrerequisiteVerificationResult>(async () => {
22
22
  const result = await this.config.inner.verify();
23
23
 
24
- // Stryker disable all
25
24
  if (result.outcome === PrerequisiteVerificationOutcome.failure) throw result.error?.message;
26
- // Stryker restore all
27
25
  return result;
28
26
  }, this.config.retry);
29
27
  } catch (error) {
@@ -1,4 +1,4 @@
1
- import { ErrorNormalizer, type NormalizedError } from "./error-normalizer.service";
1
+ import * as tools from "@bgord/tools";
2
2
 
3
3
  export enum PrerequisiteVerificationOutcome {
4
4
  success = "success",
@@ -9,7 +9,7 @@ export enum PrerequisiteVerificationOutcome {
9
9
  export type PrerequisiteVerificationSuccess = { outcome: PrerequisiteVerificationOutcome.success };
10
10
  export type PrerequisiteVerificationFailure = {
11
11
  outcome: PrerequisiteVerificationOutcome.failure;
12
- error?: NormalizedError;
12
+ error?: tools.NormalizedError;
13
13
  };
14
14
  export type PrerequisiteVerificationUndetermined = { outcome: PrerequisiteVerificationOutcome.undetermined };
15
15
  export type PrerequisiteVerificationResult =
@@ -23,7 +23,7 @@ export class PrerequisiteVerification {
23
23
  static failure(meta?: unknown): PrerequisiteVerificationFailure {
24
24
  return {
25
25
  outcome: PrerequisiteVerificationOutcome.failure,
26
- error: meta ? ErrorNormalizer.normalize(meta) : undefined,
26
+ error: meta ? tools.ErrorNormalizer.normalize(meta) : undefined,
27
27
  };
28
28
  }
29
29
 
@@ -4,6 +4,6 @@ export class RandomnessCryptoStrategy implements RandomnessStrategy {
4
4
  next(): number {
5
5
  const array = new Uint32Array(1);
6
6
  crypto.getRandomValues(array);
7
- return array[0]! / 0xffffffff;
7
+ return (array[0] ?? 0) / 0xffffffff;
8
8
  }
9
9
  }
@@ -1,20 +1,16 @@
1
1
  import * as tools from "@bgord/tools";
2
- import { ErrorNormalizer, type NormalizedError } from "./error-normalizer.service";
3
- import { isPlainObject } from "./is-plain-object";
4
2
  import type { RedactorStrategy } from "./redactor.strategy";
5
3
 
6
4
  export class RedactorErrorCauseDepthLimit implements RedactorStrategy {
7
5
  constructor(private readonly max: tools.IntegerNonNegativeType) {}
8
6
 
9
7
  redact<T>(input: T): T {
10
- // Stryker disable all
11
- if (!isPlainObject(input)) return input;
12
- // Stryker restore all
13
- if (!ErrorNormalizer.isNormalizedError(input["error"])) return input;
8
+ if (!tools.isPlainObject(input)) return input;
9
+ if (!tools.ErrorNormalizer.isNormalizedError(input["error"])) return input;
14
10
  return { ...input, error: this.limit(input["error"], tools.Int.nonNegative(0)) };
15
11
  }
16
12
 
17
- private limit(error: NormalizedError, depth: tools.IntegerNonNegativeType): NormalizedError {
13
+ private limit(error: tools.NormalizedError, depth: tools.IntegerNonNegativeType): tools.NormalizedError {
18
14
  if (!error.cause || depth >= this.max) return { ...error, cause: undefined };
19
15
  return { ...error, cause: this.limit(error.cause, tools.Int.nonNegative(depth + 1)) };
20
16
  }
@@ -1,17 +1,14 @@
1
- import { ErrorNormalizer, type NormalizedError } from "./error-normalizer.service";
2
- import { isPlainObject } from "./is-plain-object";
1
+ import * as tools from "@bgord/tools";
3
2
  import type { RedactorStrategy } from "./redactor.strategy";
4
3
 
5
4
  export class RedactorErrorStackHide implements RedactorStrategy {
6
5
  redact<T>(input: T): T {
7
- // Stryker disable all
8
- if (!isPlainObject(input)) return input;
9
- // Stryker restore all
10
- if (!ErrorNormalizer.isNormalizedError(input["error"])) return input;
6
+ if (!tools.isPlainObject(input)) return input;
7
+ if (!tools.ErrorNormalizer.isNormalizedError(input["error"])) return input;
11
8
  return { ...input, error: this.hide(input["error"]) };
12
9
  }
13
10
 
14
- private hide(error: NormalizedError): NormalizedError {
11
+ private hide(error: tools.NormalizedError): tools.NormalizedError {
15
12
  return {
16
13
  ...error,
17
14
  stack: undefined,
@@ -1,4 +1,4 @@
1
- import { deepCloneWith } from "./deep-clone-with";
1
+ import * as tools from "@bgord/tools";
2
2
  import type { RedactorStrategy } from "./redactor.strategy";
3
3
 
4
4
  export class RedactorMask implements RedactorStrategy {
@@ -28,7 +28,7 @@ export class RedactorMask implements RedactorStrategy {
28
28
  }
29
29
 
30
30
  redact<T>(input: T): T {
31
- return deepCloneWith(input, (_value, key) =>
31
+ return tools.deepCloneWith(input, (_value, key) =>
32
32
  typeof key === "string" && this.keys.has(key.toLowerCase()) ? "***" : undefined,
33
33
  );
34
34
  }
@@ -1,6 +1,4 @@
1
1
  import * as tools from "@bgord/tools";
2
- import { deepCloneWith } from "./deep-clone-with";
3
- import { isPlainObject } from "./is-plain-object";
4
2
  import type { RedactorStrategy } from "./redactor.strategy";
5
3
 
6
4
  type RedactorMetadataCompactArrayOptions = { maxItems?: tools.IntegerPositiveType };
@@ -15,11 +13,11 @@ export class RedactorMetadataCompactArray implements RedactorStrategy {
15
13
  }
16
14
 
17
15
  redact<T>(input: T): T {
18
- if (!isPlainObject(input)) return input;
16
+ if (!tools.isPlainObject(input)) return input;
19
17
 
20
18
  return {
21
19
  ...input,
22
- metadata: deepCloneWith(
20
+ metadata: tools.deepCloneWith(
23
21
  input["metadata"],
24
22
  (value) => {
25
23
  if (!Array.isArray(value)) return undefined;
@@ -1,6 +1,4 @@
1
1
  import * as tools from "@bgord/tools";
2
- import { deepCloneWith } from "./deep-clone-with";
3
- import { isPlainObject } from "./is-plain-object";
4
2
  import type { RedactorStrategy } from "./redactor.strategy";
5
3
 
6
4
  type RedactorMetadataCompactObjectOptions = { maxKeys?: tools.IntegerPositiveType };
@@ -15,14 +13,14 @@ export class RedactorMetadataCompactObject implements RedactorStrategy {
15
13
  }
16
14
 
17
15
  redact<T>(input: T): T {
18
- if (!isPlainObject(input)) return input;
16
+ if (!tools.isPlainObject(input)) return input;
19
17
 
20
18
  return {
21
19
  ...input,
22
- metadata: deepCloneWith(
20
+ metadata: tools.deepCloneWith(
23
21
  input["metadata"],
24
22
  (value) => {
25
- if (!isPlainObject(value) || Array.isArray(value)) return undefined;
23
+ if (!tools.isPlainObject(value) || Array.isArray(value)) return undefined;
26
24
 
27
25
  const keys = Object.keys(value).length;
28
26
 
@@ -1,7 +1,6 @@
1
1
  import * as tools from "@bgord/tools";
2
2
  import type { ClockPort } from "./clock.port";
3
3
  import { Hash } from "./hash.vo";
4
- import type { LoggerPort } from "./logger.port";
5
4
  import type {
6
5
  RemoteFileStoragePort,
7
6
  RemoteHeadResult,
@@ -9,25 +8,17 @@ import type {
9
8
  RemotePutFromPathResult,
10
9
  } from "./remote-file-storage.port";
11
10
 
12
- type Dependencies = { Logger: LoggerPort; Clock: ClockPort };
11
+ type Dependencies = { Clock: ClockPort };
13
12
 
14
13
  type RemoteFileStorageNoopConfig = { root: tools.DirectoryPathAbsoluteType };
15
14
 
16
15
  export class RemoteFileStorageNoopAdapter implements RemoteFileStoragePort {
17
- private readonly base = { component: "infra", operation: "RemoteFileStorageNoopAdapter" };
18
-
19
16
  constructor(
20
17
  private readonly config: RemoteFileStorageNoopConfig,
21
18
  private readonly deps: Dependencies,
22
19
  ) {}
23
20
 
24
- async putFromPath(input: RemotePutFromPathInput): Promise<RemotePutFromPathResult> {
25
- this.deps.Logger.info({
26
- message: "[NOOP] RemoteFileStorageNoopAdapter putFromPath",
27
- metadata: { input },
28
- ...this.base,
29
- });
30
-
21
+ async putFromPath(_input: RemotePutFromPathInput): Promise<RemotePutFromPathResult> {
31
22
  return {
32
23
  etag: Hash.fromString("0".repeat(64)),
33
24
  size: tools.Size.fromBytes(10),
@@ -36,33 +27,15 @@ export class RemoteFileStorageNoopAdapter implements RemoteFileStoragePort {
36
27
  };
37
28
  }
38
29
 
39
- async head(key: tools.ObjectKeyType): Promise<RemoteHeadResult> {
40
- this.deps.Logger.info({
41
- message: "[NOOP] RemoteFileStorageNoopAdapter head",
42
- metadata: { key },
43
- ...this.base,
44
- });
45
-
30
+ async head(_key: tools.ObjectKeyType): Promise<RemoteHeadResult> {
46
31
  return { exists: false };
47
32
  }
48
33
 
49
- async getStream(key: tools.ObjectKeyType): Promise<ReadableStream | null> {
50
- this.deps.Logger.info({
51
- message: "[NOOP] RemoteFileStorageNoopAdapter getStream",
52
- metadata: { key },
53
- ...this.base,
54
- });
55
-
34
+ async getStream(_key: tools.ObjectKeyType): Promise<ReadableStream | null> {
56
35
  return null;
57
36
  }
58
37
 
59
- async delete(key: tools.ObjectKeyType): Promise<void> {
60
- this.deps.Logger.info({
61
- message: "[NOOP] RemoteFileStorageNoopAdapter delete",
62
- metadata: { key },
63
- ...this.base,
64
- });
65
- }
38
+ async delete(_key: tools.ObjectKeyType): Promise<void> {}
66
39
 
67
40
  get root(): tools.DirectoryPathAbsoluteType {
68
41
  return this.config.root;
@@ -0,0 +1,140 @@
1
+ import type * as tools from "@bgord/tools";
2
+ import type { ClockPort } from "./clock.port";
3
+ import type { LoggerPort } from "./logger.port";
4
+ import type {
5
+ RemoteFileStoragePort,
6
+ RemoteHeadResult,
7
+ RemotePutFromPathInput,
8
+ RemotePutFromPathResult,
9
+ } from "./remote-file-storage.port";
10
+ import { Stopwatch } from "./stopwatch.service";
11
+
12
+ type Dependencies = { inner: RemoteFileStoragePort; Logger: LoggerPort; Clock: ClockPort };
13
+
14
+ export class RemoteFileStorageWithLoggerAdapter implements RemoteFileStoragePort {
15
+ private readonly base = { component: "infra", operation: "remote_file_storage" };
16
+
17
+ constructor(private readonly deps: Dependencies) {}
18
+
19
+ async putFromPath(input: RemotePutFromPathInput): Promise<RemotePutFromPathResult> {
20
+ const duration = new Stopwatch(this.deps);
21
+
22
+ try {
23
+ this.deps.Logger.info({
24
+ message: "Remote file storage put attempt",
25
+ metadata: { key: input.key },
26
+ ...this.base,
27
+ });
28
+
29
+ const result = await this.deps.inner.putFromPath(input);
30
+
31
+ this.deps.Logger.info({
32
+ message: "Remote file storage put success",
33
+ metadata: { key: input.key, size: result.size, duration: duration.stop() },
34
+ ...this.base,
35
+ });
36
+
37
+ return result;
38
+ } catch (error) {
39
+ this.deps.Logger.error({
40
+ message: "Remote file storage put error",
41
+ error,
42
+ metadata: duration.stop(),
43
+ ...this.base,
44
+ });
45
+
46
+ throw error;
47
+ }
48
+ }
49
+
50
+ async head(key: tools.ObjectKeyType): Promise<RemoteHeadResult> {
51
+ const duration = new Stopwatch(this.deps);
52
+
53
+ try {
54
+ this.deps.Logger.info({ message: "Remote file storage head attempt", metadata: { key }, ...this.base });
55
+
56
+ const result = await this.deps.inner.head(key);
57
+
58
+ this.deps.Logger.info({
59
+ message: "Remote file storage head success",
60
+ metadata: { key, exists: result.exists, duration: duration.stop() },
61
+ ...this.base,
62
+ });
63
+
64
+ return result;
65
+ } catch (error) {
66
+ this.deps.Logger.error({
67
+ message: "Remote file storage head error",
68
+ error,
69
+ metadata: duration.stop(),
70
+ ...this.base,
71
+ });
72
+
73
+ throw error;
74
+ }
75
+ }
76
+
77
+ async getStream(key: tools.ObjectKeyType): Promise<ReadableStream | null> {
78
+ const duration = new Stopwatch(this.deps);
79
+
80
+ try {
81
+ this.deps.Logger.info({
82
+ message: "Remote file storage get stream attempt",
83
+ metadata: { key },
84
+ ...this.base,
85
+ });
86
+
87
+ const result = await this.deps.inner.getStream(key);
88
+
89
+ this.deps.Logger.info({
90
+ message: "Remote file storage get stream success",
91
+ metadata: { key, duration: duration.stop() },
92
+ ...this.base,
93
+ });
94
+
95
+ return result;
96
+ } catch (error) {
97
+ this.deps.Logger.error({
98
+ message: "Remote file storage get stream error",
99
+ error,
100
+ metadata: duration.stop(),
101
+ ...this.base,
102
+ });
103
+
104
+ throw error;
105
+ }
106
+ }
107
+
108
+ async delete(key: tools.ObjectKeyType): Promise<void> {
109
+ const duration = new Stopwatch(this.deps);
110
+
111
+ try {
112
+ this.deps.Logger.info({
113
+ message: "Remote file storage delete attempt",
114
+ metadata: { key },
115
+ ...this.base,
116
+ });
117
+
118
+ await this.deps.inner.delete(key);
119
+
120
+ this.deps.Logger.info({
121
+ message: "Remote file storage delete success",
122
+ metadata: { key, duration: duration.stop() },
123
+ ...this.base,
124
+ });
125
+ } catch (error) {
126
+ this.deps.Logger.error({
127
+ message: "Remote file storage delete error",
128
+ error,
129
+ metadata: duration.stop(),
130
+ ...this.base,
131
+ });
132
+
133
+ throw error;
134
+ }
135
+ }
136
+
137
+ get root(): tools.DirectoryPathAbsoluteType {
138
+ return this.deps.inner.root;
139
+ }
140
+ }
@@ -2,8 +2,6 @@ import * as tools from "@bgord/tools";
2
2
  import type { RetryBackoffStrategy } from "./retry-backoff.strategy";
3
3
  import type { SleeperPort } from "./sleeper.port";
4
4
 
5
- export const RetryError = { InvalidMax: "retry.invalid.max" };
6
-
7
5
  type Dependencies = { Sleeper: SleeperPort };
8
6
 
9
7
  export type RetryConfig = {
@@ -16,8 +14,6 @@ export class Retry {
16
14
  constructor(private readonly deps: Dependencies) {}
17
15
 
18
16
  async run<T>(action: () => Promise<T>, config: RetryConfig): Promise<T> {
19
- if (config.max < 1) throw new Error(RetryError.InvalidMax);
20
-
21
17
  let lastError: unknown;
22
18
 
23
19
  for (let attempt = 1; attempt <= config.max; attempt++) {
@@ -0,0 +1,26 @@
1
+ import type * as tools from "@bgord/tools";
2
+
3
+ export type SemaphoreConfig = { limit: tools.IntegerPositiveType };
4
+
5
+ export class Semaphore {
6
+ private readonly slots: Array<Promise<void>>;
7
+
8
+ constructor(config: SemaphoreConfig) {
9
+ this.slots = Array.from({ length: config.limit }, () => Promise.resolve());
10
+ }
11
+
12
+ async run<T>(action: () => Promise<T>): Promise<T> {
13
+ const slot = this.slots.shift()!;
14
+ const { promise, resolve } = Promise.withResolvers<void>();
15
+
16
+ this.slots.push(promise);
17
+
18
+ await slot;
19
+
20
+ try {
21
+ return await action();
22
+ } finally {
23
+ resolve();
24
+ }
25
+ }
26
+ }
@@ -69,18 +69,7 @@ export class SetupHono {
69
69
  xFrameOptions: false,
70
70
  }),
71
71
  cors({
72
- // Stryker disable all
73
- origin: (origin, c) => {
74
- // server-to-server, curl, same-origin navigation
75
- if (!origin) return undefined;
76
-
77
- // same-origin fetch
78
- if (origin === new URL(c.req.url).origin) return origin;
79
-
80
- // deny cross-origin
81
- return null;
82
- },
83
- // Stryker restore all
72
+ origin: (origin, c) => (origin === new URL(c.req.url).origin ? origin : null),
84
73
  credentials: false,
85
74
  maxAge: tools.Duration.Minutes(10).seconds,
86
75
  ...config.cors,
@@ -12,9 +12,7 @@ export class ShieldIpWhitelistStrategy {
12
12
  evaluate(context: HasIdentityIp): boolean {
13
13
  const ip = v.safeParse(ClientIp, context.identity.ip());
14
14
 
15
- // Stryker disable all
16
15
  if (!ip.success) return false;
17
- // Stryker restore all
18
16
  return this.config.whitelist.includes(ip.output);
19
17
  }
20
18
  }
@@ -8,7 +8,7 @@ export class SseRegistryAdapter<Messages extends Message> implements SseRegistry
8
8
  register(identity: HashValueType, connection: SseSenderType<Messages>): void {
9
9
  if (!this.senders.has(identity)) this.senders.set(identity, new Set());
10
10
 
11
- this.senders.get(identity)!.add(connection);
11
+ this.senders.get(identity)?.add(connection);
12
12
  }
13
13
 
14
14
  unregister(identity: HashValueType, connection: SseSenderType<Messages>): void {
@@ -72,9 +72,7 @@ export class StaticFilesHono {
72
72
 
73
73
  const contentType = context.res.headers.get("Content-Type");
74
74
 
75
- // Stryker disable all
76
75
  if (contentType?.startsWith("text/html")) staticDocumentHeaders(context, noop);
77
- // Stryker restore all
78
76
  else staticAssetHeaders(context, noop);
79
77
  },
80
78
  etag(),