@bgord/bun 1.15.3 → 1.15.5

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 (218) hide show
  1. package/dist/alert-channel-collecting.adapter.d.ts +8 -0
  2. package/dist/alert-channel-collecting.adapter.d.ts.map +1 -0
  3. package/dist/alert-channel-collecting.adapter.js +10 -0
  4. package/dist/alert-channel-collecting.adapter.js.map +1 -0
  5. package/dist/alert-channel-composite.adapter.d.ts +13 -0
  6. package/dist/alert-channel-composite.adapter.d.ts.map +1 -0
  7. package/dist/alert-channel-composite.adapter.js +22 -0
  8. package/dist/alert-channel-composite.adapter.js.map +1 -0
  9. package/dist/alert-channel-mailer.adapter.d.ts +18 -0
  10. package/dist/alert-channel-mailer.adapter.d.ts.map +1 -0
  11. package/dist/alert-channel-mailer.adapter.js +15 -0
  12. package/dist/alert-channel-mailer.adapter.js.map +1 -0
  13. package/dist/alert-channel-noop.adapter.d.ts +7 -0
  14. package/dist/alert-channel-noop.adapter.d.ts.map +1 -0
  15. package/dist/alert-channel-noop.adapter.js +7 -0
  16. package/dist/alert-channel-noop.adapter.js.map +1 -0
  17. package/dist/alert-channel-sms.adapter.d.ts +18 -0
  18. package/dist/alert-channel-sms.adapter.d.ts.map +1 -0
  19. package/dist/alert-channel-sms.adapter.js +15 -0
  20. package/dist/alert-channel-sms.adapter.js.map +1 -0
  21. package/dist/alert-channel-with-logger.adapter.d.ts +17 -0
  22. package/dist/alert-channel-with-logger.adapter.d.ts.map +1 -0
  23. package/dist/alert-channel-with-logger.adapter.js +33 -0
  24. package/dist/alert-channel-with-logger.adapter.js.map +1 -0
  25. package/dist/alert-channel-with-retry.adapter.d.ts +19 -0
  26. package/dist/alert-channel-with-retry.adapter.d.ts.map +1 -0
  27. package/dist/alert-channel-with-retry.adapter.js +16 -0
  28. package/dist/alert-channel-with-retry.adapter.js.map +1 -0
  29. package/dist/alert-channel-with-timeout.adapter.d.ts +19 -0
  30. package/dist/alert-channel-with-timeout.adapter.d.ts.map +1 -0
  31. package/dist/alert-channel-with-timeout.adapter.js +15 -0
  32. package/dist/alert-channel-with-timeout.adapter.js.map +1 -0
  33. package/dist/alert-channel.builder.d.ts +14 -0
  34. package/dist/alert-channel.builder.d.ts.map +1 -0
  35. package/dist/alert-channel.builder.js +28 -0
  36. package/dist/alert-channel.builder.js.map +1 -0
  37. package/dist/alert-channel.port.d.ts +6 -0
  38. package/dist/alert-channel.port.d.ts.map +1 -0
  39. package/dist/alert-channel.port.js +2 -0
  40. package/dist/alert-channel.port.js.map +1 -0
  41. package/dist/alert-message.vo.d.ts +10 -0
  42. package/dist/alert-message.vo.d.ts.map +1 -0
  43. package/dist/alert-message.vo.js +12 -0
  44. package/dist/alert-message.vo.js.map +1 -0
  45. package/dist/cache-repository-redis.adapter.d.ts +13 -0
  46. package/dist/cache-repository-redis.adapter.d.ts.map +1 -0
  47. package/dist/cache-repository-redis.adapter.js +27 -0
  48. package/dist/cache-repository-redis.adapter.js.map +1 -0
  49. package/dist/healthcheck-hono.handler.d.ts +3 -2
  50. package/dist/healthcheck-hono.handler.d.ts.map +1 -1
  51. package/dist/healthcheck-hono.handler.js +1 -2
  52. package/dist/healthcheck-hono.handler.js.map +1 -1
  53. package/dist/healthcheck.handler.d.ts +12 -1
  54. package/dist/healthcheck.handler.d.ts.map +1 -1
  55. package/dist/healthcheck.handler.js +20 -2
  56. package/dist/healthcheck.handler.js.map +1 -1
  57. package/dist/image-grayscale-noop.adapter.d.ts +6 -0
  58. package/dist/image-grayscale-noop.adapter.d.ts.map +1 -0
  59. package/dist/image-grayscale-noop.adapter.js +6 -0
  60. package/dist/image-grayscale-noop.adapter.js.map +1 -0
  61. package/dist/image-grayscale-sharp.adapter.d.ts +19 -0
  62. package/dist/image-grayscale-sharp.adapter.d.ts.map +1 -0
  63. package/dist/image-grayscale-sharp.adapter.js +28 -0
  64. package/dist/image-grayscale-sharp.adapter.js.map +1 -0
  65. package/dist/image-grayscale.port.d.ts +15 -0
  66. package/dist/image-grayscale.port.d.ts.map +1 -0
  67. package/dist/image-grayscale.port.js +2 -0
  68. package/dist/image-grayscale.port.js.map +1 -0
  69. package/dist/index.d.ts +37 -3
  70. package/dist/index.d.ts.map +1 -1
  71. package/dist/index.js +37 -3
  72. package/dist/index.js.map +1 -1
  73. package/dist/liveness-hono.handler.d.ts +8 -0
  74. package/dist/liveness-hono.handler.d.ts.map +1 -0
  75. package/dist/liveness-hono.handler.js +10 -0
  76. package/dist/liveness-hono.handler.js.map +1 -0
  77. package/dist/liveness.handler.d.ts +6 -0
  78. package/dist/liveness.handler.d.ts.map +1 -0
  79. package/dist/liveness.handler.js +6 -0
  80. package/dist/liveness.handler.js.map +1 -0
  81. package/dist/mailer-collecting.adapter.d.ts +8 -0
  82. package/dist/mailer-collecting.adapter.d.ts.map +1 -0
  83. package/dist/mailer-collecting.adapter.js +10 -0
  84. package/dist/mailer-collecting.adapter.js.map +1 -0
  85. package/dist/prerequisite-verifier-sms.adapter.d.ts +13 -0
  86. package/dist/prerequisite-verifier-sms.adapter.d.ts.map +1 -0
  87. package/dist/prerequisite-verifier-sms.adapter.js +20 -0
  88. package/dist/prerequisite-verifier-sms.adapter.js.map +1 -0
  89. package/dist/randomness-crypto.strategy.d.ts +5 -0
  90. package/dist/randomness-crypto.strategy.d.ts.map +1 -0
  91. package/dist/randomness-crypto.strategy.js +8 -0
  92. package/dist/randomness-crypto.strategy.js.map +1 -0
  93. package/dist/randomness-math.strategy.d.ts +5 -0
  94. package/dist/randomness-math.strategy.d.ts.map +1 -0
  95. package/dist/randomness-math.strategy.js +6 -0
  96. package/dist/randomness-math.strategy.js.map +1 -0
  97. package/dist/randomness-noop.strategy.d.ts +7 -0
  98. package/dist/randomness-noop.strategy.d.ts.map +1 -0
  99. package/dist/randomness-noop.strategy.js +10 -0
  100. package/dist/randomness-noop.strategy.js.map +1 -0
  101. package/dist/randomness.strategy.d.ts +4 -0
  102. package/dist/randomness.strategy.d.ts.map +1 -0
  103. package/dist/randomness.strategy.js +2 -0
  104. package/dist/randomness.strategy.js.map +1 -0
  105. package/dist/readiness-hono.handler.d.ts +26 -0
  106. package/dist/readiness-hono.handler.d.ts.map +1 -0
  107. package/dist/readiness-hono.handler.js +17 -0
  108. package/dist/readiness-hono.handler.js.map +1 -0
  109. package/dist/readiness.handler.d.ts +19 -0
  110. package/dist/readiness.handler.d.ts.map +1 -0
  111. package/dist/readiness.handler.js +19 -0
  112. package/dist/readiness.handler.js.map +1 -0
  113. package/dist/retry-backoff-jitter.strategy.d.ts +10 -0
  114. package/dist/retry-backoff-jitter.strategy.d.ts.map +1 -0
  115. package/dist/retry-backoff-jitter.strategy.js +14 -0
  116. package/dist/retry-backoff-jitter.strategy.js.map +1 -0
  117. package/dist/shield-ip-blacklist-hono.strategy.d.ts +11 -0
  118. package/dist/shield-ip-blacklist-hono.strategy.d.ts.map +1 -0
  119. package/dist/shield-ip-blacklist-hono.strategy.js +21 -0
  120. package/dist/shield-ip-blacklist-hono.strategy.js.map +1 -0
  121. package/dist/shield-ip-blacklist.strategy.d.ts +14 -0
  122. package/dist/shield-ip-blacklist.strategy.d.ts.map +1 -0
  123. package/dist/shield-ip-blacklist.strategy.js +16 -0
  124. package/dist/shield-ip-blacklist.strategy.js.map +1 -0
  125. package/dist/shield-ip-whitelist-hono.strategy.d.ts +11 -0
  126. package/dist/shield-ip-whitelist-hono.strategy.d.ts.map +1 -0
  127. package/dist/shield-ip-whitelist-hono.strategy.js +21 -0
  128. package/dist/shield-ip-whitelist-hono.strategy.js.map +1 -0
  129. package/dist/shield-ip-whitelist.strategy.d.ts +14 -0
  130. package/dist/shield-ip-whitelist.strategy.d.ts.map +1 -0
  131. package/dist/shield-ip-whitelist.strategy.js +16 -0
  132. package/dist/shield-ip-whitelist.strategy.js.map +1 -0
  133. package/dist/sms-collecting.adapter.d.ts +8 -0
  134. package/dist/sms-collecting.adapter.d.ts.map +1 -0
  135. package/dist/sms-collecting.adapter.js +10 -0
  136. package/dist/sms-collecting.adapter.js.map +1 -0
  137. package/dist/sms-noop.adapter.d.ts +7 -0
  138. package/dist/sms-noop.adapter.d.ts.map +1 -0
  139. package/dist/sms-noop.adapter.js +7 -0
  140. package/dist/sms-noop.adapter.js.map +1 -0
  141. package/dist/sms-with-logger.adapter.d.ts +17 -0
  142. package/dist/sms-with-logger.adapter.d.ts.map +1 -0
  143. package/dist/sms-with-logger.adapter.js +28 -0
  144. package/dist/sms-with-logger.adapter.js.map +1 -0
  145. package/dist/sms-with-retry.adapter.d.ts +19 -0
  146. package/dist/sms-with-retry.adapter.d.ts.map +1 -0
  147. package/dist/sms-with-retry.adapter.js +16 -0
  148. package/dist/sms-with-retry.adapter.js.map +1 -0
  149. package/dist/sms-with-timeout.adapter.d.ts +18 -0
  150. package/dist/sms-with-timeout.adapter.d.ts.map +1 -0
  151. package/dist/sms-with-timeout.adapter.js +15 -0
  152. package/dist/sms-with-timeout.adapter.js.map +1 -0
  153. package/dist/sms.builder.d.ts +14 -0
  154. package/dist/sms.builder.d.ts.map +1 -0
  155. package/dist/sms.builder.js +28 -0
  156. package/dist/sms.builder.js.map +1 -0
  157. package/dist/sms.port.d.ts +6 -0
  158. package/dist/sms.port.d.ts.map +1 -0
  159. package/dist/sms.port.js +2 -0
  160. package/dist/sms.port.js.map +1 -0
  161. package/dist/tsconfig.tsbuildinfo +1 -1
  162. package/package.json +11 -11
  163. package/readme.md +37 -3
  164. package/src/alert-channel-collecting.adapter.ts +14 -0
  165. package/src/alert-channel-composite.adapter.ts +24 -0
  166. package/src/alert-channel-mailer.adapter.ts +22 -0
  167. package/src/alert-channel-noop.adapter.ts +10 -0
  168. package/src/alert-channel-sms.adapter.ts +22 -0
  169. package/src/alert-channel-with-logger.adapter.ts +46 -0
  170. package/src/alert-channel-with-retry.adapter.ts +22 -0
  171. package/src/alert-channel-with-timeout.adapter.ts +25 -0
  172. package/src/alert-channel.builder.ts +48 -0
  173. package/src/alert-channel.port.ts +7 -0
  174. package/src/alert-message.vo.ts +10 -0
  175. package/src/cache-repository-redis.adapter.ts +31 -0
  176. package/src/healthcheck-hono.handler.ts +1 -2
  177. package/src/healthcheck.handler.ts +28 -3
  178. package/src/image-grayscale-noop.adapter.ts +8 -0
  179. package/src/image-grayscale-sharp.adapter.ts +45 -0
  180. package/src/image-grayscale.port.ts +16 -0
  181. package/src/index.ts +37 -3
  182. package/src/liveness-hono.handler.ts +13 -0
  183. package/src/liveness.handler.ts +5 -0
  184. package/src/mailer-collecting.adapter.ts +14 -0
  185. package/src/prerequisite-verifier-sms.adapter.ts +26 -0
  186. package/src/randomness-crypto.strategy.ts +9 -0
  187. package/src/randomness-math.strategy.ts +7 -0
  188. package/src/randomness-noop.strategy.ts +9 -0
  189. package/src/randomness.strategy.ts +3 -0
  190. package/src/readiness-hono.handler.ts +22 -0
  191. package/src/readiness.handler.ts +33 -0
  192. package/src/retry-backoff-jitter.strategy.ts +15 -0
  193. package/src/shield-ip-blacklist-hono.strategy.ts +30 -0
  194. package/src/shield-ip-blacklist.strategy.ts +18 -0
  195. package/src/shield-ip-whitelist-hono.strategy.ts +30 -0
  196. package/src/shield-ip-whitelist.strategy.ts +18 -0
  197. package/src/sms-collecting.adapter.ts +14 -0
  198. package/src/sms-noop.adapter.ts +10 -0
  199. package/src/sms-with-logger.adapter.ts +37 -0
  200. package/src/sms-with-retry.adapter.ts +22 -0
  201. package/src/sms-with-timeout.adapter.ts +21 -0
  202. package/src/sms.builder.ts +39 -0
  203. package/src/sms.port.ts +6 -0
  204. package/dist/ping-hono.handler.d.ts +0 -6
  205. package/dist/ping-hono.handler.d.ts.map +0 -1
  206. package/dist/ping-hono.handler.js +0 -13
  207. package/dist/ping-hono.handler.js.map +0 -1
  208. package/dist/ping.handler.d.ts +0 -4
  209. package/dist/ping.handler.d.ts.map +0 -1
  210. package/dist/ping.handler.js +0 -6
  211. package/dist/ping.handler.js.map +0 -1
  212. package/dist/retry-backoff-fibonacci.strategy.d.ts +0 -9
  213. package/dist/retry-backoff-fibonacci.strategy.d.ts.map +0 -1
  214. package/dist/retry-backoff-fibonacci.strategy.js +0 -19
  215. package/dist/retry-backoff-fibonacci.strategy.js.map +0 -1
  216. package/src/ping-hono.handler.ts +0 -17
  217. package/src/ping.handler.ts +0 -5
  218. package/src/retry-backoff-fibonacci.strategy.ts +0 -17
package/src/index.ts CHANGED
@@ -10,6 +10,17 @@ export * from "./ab-variant.vo";
10
10
  export * from "./ab-variant-selector.service";
11
11
  export * from "./ab-variant-weight.vo";
12
12
  export * from "./ab-variants.vo";
13
+ export * from "./alert-channel.builder";
14
+ export * from "./alert-channel.port";
15
+ export * from "./alert-channel-collecting.adapter";
16
+ export * from "./alert-channel-composite.adapter";
17
+ export * from "./alert-channel-mailer.adapter";
18
+ export * from "./alert-channel-noop.adapter";
19
+ export * from "./alert-channel-sms.adapter";
20
+ export * from "./alert-channel-with-logger.adapter";
21
+ export * from "./alert-channel-with-retry.adapter";
22
+ export * from "./alert-channel-with-timeout.adapter";
23
+ export * from "./alert-message.vo";
13
24
  export * from "./antivirus.port";
14
25
  export * from "./antivirus-clamav.adapter";
15
26
  export * from "./antivirus-noop.adapter";
@@ -32,6 +43,7 @@ export * from "./cache-file.service";
32
43
  export * from "./cache-repository.port";
33
44
  export * from "./cache-repository-node-cache.adapter";
34
45
  export * from "./cache-repository-noop.adapter";
46
+ export * from "./cache-repository-redis.adapter";
35
47
  export * from "./cache-resolver.strategy";
36
48
  export * from "./cache-resolver-simple.strategy";
37
49
  export * from "./cache-response.middleware";
@@ -182,6 +194,9 @@ export * from "./image-exif-clear-sharp.adapter";
182
194
  export * from "./image-formatter.port";
183
195
  export * from "./image-formatter-noop.adapter";
184
196
  export * from "./image-formatter-sharp.adapter";
197
+ export * from "./image-grayscale.port";
198
+ export * from "./image-grayscale-noop.adapter";
199
+ export * from "./image-grayscale-sharp.adapter";
185
200
  export * from "./image-info.port";
186
201
  export * from "./image-info-noop.adapter";
187
202
  export * from "./image-info-sharp.adapter";
@@ -208,6 +223,8 @@ export * from "./language-detector-header.strategy";
208
223
  export * from "./language-detector-hono.middleware";
209
224
  export * from "./language-detector-query.strategy";
210
225
  export * from "./languages.vo";
226
+ export * from "./liveness.handler";
227
+ export * from "./liveness-hono.handler";
211
228
  export * from "./logger.port";
212
229
  export * from "./logger-collecting.adapter";
213
230
  export * from "./logger-noop.adapter";
@@ -216,6 +233,7 @@ export * from "./logger-stats-provider-noop.adapter";
216
233
  export * from "./mailer.builder";
217
234
  export * from "./mailer.builder";
218
235
  export * from "./mailer.port";
236
+ export * from "./mailer-collecting.adapter";
219
237
  export * from "./mailer-content-html.vo";
220
238
  export * from "./mailer-noop.adapter";
221
239
  export * from "./mailer-resend.adapter";
@@ -253,8 +271,6 @@ export * from "./nonce-value.vo";
253
271
  export * from "./pdf-generator.port";
254
272
  export * from "./pdf-generator-noop.adapter";
255
273
  export * from "./pdf-generator-with-logger.adapter";
256
- export * from "./ping.handler";
257
- export * from "./ping-hono.handler";
258
274
  export * from "./port.vo";
259
275
  export * from "./prerequisite.vo";
260
276
  export * from "./prerequisite-runner-startup.service";
@@ -277,11 +293,18 @@ export * from "./prerequisite-verifier-port.adapter";
277
293
  export * from "./prerequisite-verifier-ram.adapter";
278
294
  export * from "./prerequisite-verifier-running-user.adapter";
279
295
  export * from "./prerequisite-verifier-self.adapter";
296
+ export * from "./prerequisite-verifier-sms.adapter";
280
297
  export * from "./prerequisite-verifier-space.adapter";
281
298
  export * from "./prerequisite-verifier-sqlite.adapter";
282
299
  export * from "./prerequisite-verifier-ssl-certificate-expiry.adapter";
283
300
  export * from "./prerequisite-verifier-timezone-utc.adapter";
284
301
  export * from "./prerequisite-verifier-translations.adapter";
302
+ export * from "./randomness.strategy";
303
+ export * from "./randomness-crypto.strategy";
304
+ export * from "./randomness-math.strategy";
305
+ export * from "./randomness-noop.strategy";
306
+ export * from "./readiness.handler";
307
+ export * from "./readiness-hono.handler";
285
308
  export * from "./recaptcha-secret-key.vo";
286
309
  export * from "./recaptcha-site-key.vo";
287
310
  export * from "./redactor.strategy";
@@ -300,7 +323,7 @@ export * from "./request-context-hono.adapter";
300
323
  export * from "./retry.service";
301
324
  export * from "./retry-backoff.strategy";
302
325
  export * from "./retry-backoff-exponential.strategy";
303
- export * from "./retry-backoff-fibonacci.strategy";
326
+ export * from "./retry-backoff-jitter.strategy";
304
327
  export * from "./retry-backoff-linear.strategy";
305
328
  export * from "./retry-backoff-noop.strategy";
306
329
  export * from "./sealer.port";
@@ -342,6 +365,10 @@ export * from "./shield-csrf-hono.strategy";
342
365
  export * from "./shield-hcaptcha.strategy";
343
366
  export * from "./shield-hcaptcha-hono.strategy";
344
367
  export * from "./shield-hcaptcha-hono-local.strategy";
368
+ export * from "./shield-ip-blacklist.strategy";
369
+ export * from "./shield-ip-blacklist-hono.strategy";
370
+ export * from "./shield-ip-whitelist.strategy";
371
+ export * from "./shield-ip-whitelist-hono.strategy";
345
372
  export * from "./shield-maintenance.strategy";
346
373
  export * from "./shield-maintenance-hono.strategy";
347
374
  export * from "./shield-rate-limit.strategy";
@@ -359,6 +386,13 @@ export * from "./sleeper-noop.adapter";
359
386
  export * from "./sleeper-system.adapter";
360
387
  export * from "./slower.middleware";
361
388
  export * from "./slower-hono.middleware";
389
+ export * from "./sms.builder";
390
+ export * from "./sms.port";
391
+ export * from "./sms-collecting.adapter";
392
+ export * from "./sms-noop.adapter";
393
+ export * from "./sms-with-logger.adapter";
394
+ export * from "./sms-with-retry.adapter";
395
+ export * from "./sms-with-timeout.adapter";
362
396
  export * from "./smtp-host.vo";
363
397
  export * from "./smtp-pass.vo";
364
398
  export * from "./smtp-port.vo";
@@ -0,0 +1,13 @@
1
+ import { createFactory } from "hono/factory";
2
+ import type { HandlerHonoPort } from "./handler-hono.port";
3
+ import { LivenessHandler } from "./liveness.handler";
4
+
5
+ const factory = createFactory();
6
+
7
+ export class LivenessHonoHandler implements HandlerHonoPort {
8
+ private readonly handler = new LivenessHandler();
9
+
10
+ handle() {
11
+ return factory.createHandlers(async (c) => c.json(this.handler.execute(), 200));
12
+ }
13
+ }
@@ -0,0 +1,5 @@
1
+ export class LivenessHandler {
2
+ execute(): { ok: true } {
3
+ return { ok: true };
4
+ }
5
+ }
@@ -0,0 +1,14 @@
1
+ import type { MailerPort } from "./mailer.port";
2
+ import type { MailerTemplate } from "./mailer-template.vo";
3
+
4
+ export class MailerCollectingAdapter implements MailerPort {
5
+ messages: Array<MailerTemplate> = [];
6
+
7
+ async send(template: MailerTemplate): Promise<void> {
8
+ this.messages.push(template);
9
+ }
10
+
11
+ async verify(): Promise<boolean> {
12
+ return true;
13
+ }
14
+ }
@@ -0,0 +1,26 @@
1
+ import {
2
+ PrerequisiteVerification,
3
+ type PrerequisiteVerificationResult,
4
+ type PrerequisiteVerifierPort,
5
+ } from "./prerequisite-verifier.port";
6
+ import type { SmsPort } from "./sms.port";
7
+
8
+ type Dependencies = { Sms: SmsPort };
9
+
10
+ export class PrerequisiteVerifierSmsAdapter implements PrerequisiteVerifierPort {
11
+ constructor(private readonly deps: Dependencies) {}
12
+
13
+ async verify(): Promise<PrerequisiteVerificationResult> {
14
+ try {
15
+ await this.deps.Sms.verify();
16
+
17
+ return PrerequisiteVerification.success;
18
+ } catch (error) {
19
+ return PrerequisiteVerification.failure(error);
20
+ }
21
+ }
22
+
23
+ get kind(): string {
24
+ return "sms";
25
+ }
26
+ }
@@ -0,0 +1,9 @@
1
+ import type { RandomnessStrategy } from "./randomness.strategy";
2
+
3
+ export class RandomnessCryptoStrategy implements RandomnessStrategy {
4
+ next(): number {
5
+ const array = new Uint32Array(1);
6
+ crypto.getRandomValues(array);
7
+ return array[0]! / 0xffffffff;
8
+ }
9
+ }
@@ -0,0 +1,7 @@
1
+ import type { RandomnessStrategy } from "./randomness.strategy";
2
+
3
+ export class RandomnessMathStrategy implements RandomnessStrategy {
4
+ next(): number {
5
+ return Math.random();
6
+ }
7
+ }
@@ -0,0 +1,9 @@
1
+ import type { RandomnessStrategy } from "./randomness.strategy";
2
+
3
+ export class RandomnessNoopStrategy implements RandomnessStrategy {
4
+ constructor(private readonly value: number) {}
5
+
6
+ next(): number {
7
+ return this.value;
8
+ }
9
+ }
@@ -0,0 +1,3 @@
1
+ export interface RandomnessStrategy {
2
+ next(): number;
3
+ }
@@ -0,0 +1,22 @@
1
+ import { createFactory } from "hono/factory";
2
+ import type { HandlerHonoPort } from "./handler-hono.port";
3
+ import { type ReadinessConfig, ReadinessHandler } from "./readiness.handler";
4
+
5
+ const factory = createFactory();
6
+
7
+ export class ReadinessHonoHandler implements HandlerHonoPort {
8
+ private readonly handler: ReadinessHandler;
9
+
10
+ constructor(config: ReadinessConfig) {
11
+ this.handler = new ReadinessHandler(config);
12
+ }
13
+
14
+ handle() {
15
+ return factory.createHandlers(async (c) => {
16
+ const readiness = await this.handler.check();
17
+ const code = readiness.ok ? 200 : 503;
18
+
19
+ return c.json(readiness, code);
20
+ });
21
+ }
22
+ }
@@ -0,0 +1,33 @@
1
+ import type { Prerequisite, PrerequisiteLabelType } from "./prerequisite.vo";
2
+ import {
3
+ PrerequisiteVerificationOutcome,
4
+ type PrerequisiteVerificationResult,
5
+ } from "./prerequisite-verifier.port";
6
+
7
+ export type ReadinessConfig = { prerequisites: ReadonlyArray<Prerequisite> };
8
+
9
+ type ReadinessResult = {
10
+ ok: boolean;
11
+ details: ReadonlyArray<{ label: PrerequisiteLabelType; outcome: PrerequisiteVerificationResult }>;
12
+ };
13
+
14
+ export class ReadinessHandler {
15
+ constructor(private readonly config: ReadinessConfig) {}
16
+
17
+ async check(): Promise<ReadinessResult> {
18
+ const prerequisites = this.config.prerequisites
19
+ .filter((prerequisite) => prerequisite.enabled)
20
+ .filter((prerequisite) => prerequisite.kind !== "port");
21
+
22
+ const details = await Promise.all(
23
+ prerequisites.map(async (prerequisite) => ({
24
+ label: prerequisite.label,
25
+ outcome: await prerequisite.build().verify(),
26
+ })),
27
+ );
28
+
29
+ const ok = details.every((detail) => detail.outcome.outcome !== PrerequisiteVerificationOutcome.failure);
30
+
31
+ return { ok, details };
32
+ }
33
+ }
@@ -0,0 +1,15 @@
1
+ import * as tools from "@bgord/tools";
2
+ import * as v from "valibot";
3
+ import type { RandomnessStrategy } from "./randomness.strategy";
4
+ import type { RetryBackoffStrategy } from "./retry-backoff.strategy";
5
+
6
+ export class RetryBackoffJitterStrategy implements RetryBackoffStrategy {
7
+ constructor(
8
+ private readonly delay: tools.Duration,
9
+ private readonly randomness: RandomnessStrategy,
10
+ ) {}
11
+
12
+ next(attempt: tools.IntegerPositiveType): tools.Duration {
13
+ return this.delay.times(v.parse(tools.MultiplicationFactor, attempt * this.randomness.next()));
14
+ }
15
+ }
@@ -0,0 +1,30 @@
1
+ import type { MiddlewareHandler } from "hono";
2
+ import { HTTPException } from "hono/http-exception";
3
+ import type { MiddlewareHonoPort } from "./middleware-hono.port";
4
+ import { RequestContextHonoAdapter } from "./request-context-hono.adapter";
5
+ import {
6
+ type ShieldIpBlacklistConfig,
7
+ ShieldIpBlacklistStrategy,
8
+ ShieldIpBlacklistStrategyError,
9
+ } from "./shield-ip-blacklist.strategy";
10
+
11
+ export const ShieldIpBlacklistError = new HTTPException(403, {
12
+ message: ShieldIpBlacklistStrategyError.Rejected,
13
+ });
14
+
15
+ export class ShieldIpBlacklistHonoStrategy implements MiddlewareHonoPort {
16
+ private readonly strategy: ShieldIpBlacklistStrategy;
17
+
18
+ constructor(config: ShieldIpBlacklistConfig) {
19
+ this.strategy = new ShieldIpBlacklistStrategy(config);
20
+ }
21
+
22
+ handle(): MiddlewareHandler {
23
+ return async (c, next) => {
24
+ const context = new RequestContextHonoAdapter(c);
25
+
26
+ if (this.strategy.evaluate(context)) return next();
27
+ throw ShieldIpBlacklistError;
28
+ };
29
+ }
30
+ }
@@ -0,0 +1,18 @@
1
+ import * as v from "valibot";
2
+ import { ClientIp, type ClientIpType } from "./client-ip.vo";
3
+ import type { HasIdentityIp } from "./request-context.port";
4
+
5
+ export type ShieldIpBlacklistConfig = { blacklist: Array<ClientIpType> };
6
+
7
+ export const ShieldIpBlacklistStrategyError = { Rejected: "shield.ip.blacklist.rejected" };
8
+
9
+ export class ShieldIpBlacklistStrategy {
10
+ constructor(private readonly config: ShieldIpBlacklistConfig) {}
11
+
12
+ evaluate(context: HasIdentityIp): boolean {
13
+ const ip = v.safeParse(ClientIp, context.identity.ip());
14
+
15
+ if (!ip.success) return false;
16
+ return !this.config.blacklist.includes(ip.output);
17
+ }
18
+ }
@@ -0,0 +1,30 @@
1
+ import type { MiddlewareHandler } from "hono";
2
+ import { HTTPException } from "hono/http-exception";
3
+ import type { MiddlewareHonoPort } from "./middleware-hono.port";
4
+ import { RequestContextHonoAdapter } from "./request-context-hono.adapter";
5
+ import {
6
+ type ShieldIpWhitelistConfig,
7
+ ShieldIpWhitelistStrategy,
8
+ ShieldIpWhitelistStrategyError,
9
+ } from "./shield-ip-whitelist.strategy";
10
+
11
+ export const ShieldIpWhitelistError = new HTTPException(403, {
12
+ message: ShieldIpWhitelistStrategyError.Rejected,
13
+ });
14
+
15
+ export class ShieldIpWhitelistHonoStrategy implements MiddlewareHonoPort {
16
+ private readonly strategy: ShieldIpWhitelistStrategy;
17
+
18
+ constructor(config: ShieldIpWhitelistConfig) {
19
+ this.strategy = new ShieldIpWhitelistStrategy(config);
20
+ }
21
+
22
+ handle(): MiddlewareHandler {
23
+ return async (c, next) => {
24
+ const context = new RequestContextHonoAdapter(c);
25
+
26
+ if (this.strategy.evaluate(context)) return next();
27
+ throw ShieldIpWhitelistError;
28
+ };
29
+ }
30
+ }
@@ -0,0 +1,18 @@
1
+ import * as v from "valibot";
2
+ import { ClientIp, type ClientIpType } from "./client-ip.vo";
3
+ import type { HasIdentityIp } from "./request-context.port";
4
+
5
+ export type ShieldIpWhitelistConfig = { whitelist: Array<ClientIpType> };
6
+
7
+ export const ShieldIpWhitelistStrategyError = { Rejected: "shield.ip.whitelist.rejected" };
8
+
9
+ export class ShieldIpWhitelistStrategy {
10
+ constructor(private readonly config: ShieldIpWhitelistConfig) {}
11
+
12
+ evaluate(context: HasIdentityIp): boolean {
13
+ const ip = v.safeParse(ClientIp, context.identity.ip());
14
+
15
+ if (!ip.success) return false;
16
+ return this.config.whitelist.includes(ip.output);
17
+ }
18
+ }
@@ -0,0 +1,14 @@
1
+ import type * as tools from "@bgord/tools";
2
+ import type { SmsPort } from "./sms.port";
3
+
4
+ export class SmsCollectingAdapter implements SmsPort {
5
+ readonly messages: Array<tools.SmsMessage> = [];
6
+
7
+ async send(message: tools.SmsMessage): Promise<void> {
8
+ this.messages.push(message);
9
+ }
10
+
11
+ async verify(): Promise<boolean> {
12
+ return true;
13
+ }
14
+ }
@@ -0,0 +1,10 @@
1
+ import type * as tools from "@bgord/tools";
2
+ import type { SmsPort } from "./sms.port";
3
+
4
+ export class SmsNoopAdapter implements SmsPort {
5
+ async send(_message: tools.SmsMessage): Promise<void> {}
6
+
7
+ async verify(): Promise<boolean> {
8
+ return true;
9
+ }
10
+ }
@@ -0,0 +1,37 @@
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 { SmsPort } from "./sms.port";
5
+ import { Stopwatch } from "./stopwatch.service";
6
+
7
+ export type SmsWithLoggerAdapterDependencies = { inner: SmsPort; Logger: LoggerPort; Clock: ClockPort };
8
+
9
+ export class SmsWithLoggerAdapter implements SmsPort {
10
+ private readonly base = { component: "infra", operation: "sms" };
11
+
12
+ constructor(private readonly deps: SmsWithLoggerAdapterDependencies) {}
13
+
14
+ async send(message: tools.SmsMessage): Promise<void> {
15
+ const duration = new Stopwatch(this.deps);
16
+
17
+ try {
18
+ this.deps.Logger.info({ message: "SMS attempt", metadata: message.toJSON(), ...this.base });
19
+
20
+ await this.deps.inner.send(message);
21
+
22
+ this.deps.Logger.info({
23
+ message: "SMS success",
24
+ metadata: { message: message.toJSON(), duration: duration.stop() },
25
+ ...this.base,
26
+ });
27
+ } catch (error) {
28
+ this.deps.Logger.error({ message: "SMS error", error, metadata: duration.stop(), ...this.base });
29
+
30
+ throw error;
31
+ }
32
+ }
33
+
34
+ async verify(): Promise<boolean> {
35
+ return this.deps.inner.verify();
36
+ }
37
+ }
@@ -0,0 +1,22 @@
1
+ import type * as tools from "@bgord/tools";
2
+ import { Retry, type RetryConfig } from "./retry.service";
3
+ import type { SleeperPort } from "./sleeper.port";
4
+ import type { SmsPort } from "./sms.port";
5
+
6
+ export type SmsWithRetryAdapterDependencies = { Sleeper: SleeperPort; inner: SmsPort };
7
+ export type SmsWithRetryAdapterConfig = { retry: RetryConfig };
8
+
9
+ export class SmsWithRetryAdapter implements SmsPort {
10
+ constructor(
11
+ private readonly config: SmsWithRetryAdapterConfig,
12
+ private readonly deps: SmsWithRetryAdapterDependencies,
13
+ ) {}
14
+
15
+ async send(message: tools.SmsMessage): Promise<void> {
16
+ await new Retry(this.deps).run(async () => this.deps.inner.send(message), this.config.retry);
17
+ }
18
+
19
+ async verify(): Promise<boolean> {
20
+ return this.deps.inner.verify();
21
+ }
22
+ }
@@ -0,0 +1,21 @@
1
+ import type * as tools from "@bgord/tools";
2
+ import type { SmsPort } from "./sms.port";
3
+ import type { TimeoutRunnerPort } from "./timeout-runner.port";
4
+
5
+ export type SmsWithTimeoutAdapterDependencies = { TimeoutRunner: TimeoutRunnerPort; inner: SmsPort };
6
+ export type SmsWithTimeoutAdapterConfig = { timeout: tools.Duration };
7
+
8
+ export class SmsWithTimeoutAdapter implements SmsPort {
9
+ constructor(
10
+ private readonly config: SmsWithTimeoutAdapterConfig,
11
+ private readonly deps: SmsWithTimeoutAdapterDependencies,
12
+ ) {}
13
+
14
+ async send(message: tools.SmsMessage): Promise<void> {
15
+ await this.deps.TimeoutRunner.run(this.deps.inner.send(message), this.config.timeout);
16
+ }
17
+
18
+ async verify(): Promise<boolean> {
19
+ return this.deps.inner.verify();
20
+ }
21
+ }
@@ -0,0 +1,39 @@
1
+ import type { SmsPort } from "./sms.port";
2
+ import { SmsWithLoggerAdapter, type SmsWithLoggerAdapterDependencies } from "./sms-with-logger.adapter";
3
+ import {
4
+ SmsWithRetryAdapter,
5
+ type SmsWithRetryAdapterConfig,
6
+ type SmsWithRetryAdapterDependencies,
7
+ } from "./sms-with-retry.adapter";
8
+ import {
9
+ SmsWithTimeoutAdapter,
10
+ type SmsWithTimeoutAdapterConfig,
11
+ type SmsWithTimeoutAdapterDependencies,
12
+ } from "./sms-with-timeout.adapter";
13
+
14
+ export class SmsBuilder {
15
+ constructor(private inner: SmsPort) {}
16
+
17
+ static of(sms: SmsPort): SmsBuilder {
18
+ return new SmsBuilder(sms);
19
+ }
20
+
21
+ withLogger(deps: Omit<SmsWithLoggerAdapterDependencies, "inner">) {
22
+ this.inner = new SmsWithLoggerAdapter({ ...deps, inner: this.inner });
23
+ return this;
24
+ }
25
+
26
+ withRetry(config: SmsWithRetryAdapterConfig, deps: Omit<SmsWithRetryAdapterDependencies, "inner">) {
27
+ this.inner = new SmsWithRetryAdapter(config, { ...deps, inner: this.inner });
28
+ return this;
29
+ }
30
+
31
+ withTimeout(config: SmsWithTimeoutAdapterConfig, deps: Omit<SmsWithTimeoutAdapterDependencies, "inner">) {
32
+ this.inner = new SmsWithTimeoutAdapter(config, { ...deps, inner: this.inner });
33
+ return this;
34
+ }
35
+
36
+ build() {
37
+ return this.inner;
38
+ }
39
+ }
@@ -0,0 +1,6 @@
1
+ import type * as tools from "@bgord/tools";
2
+
3
+ export interface SmsPort {
4
+ send(message: tools.SmsMessage): Promise<void>;
5
+ verify(): Promise<boolean>;
6
+ }
@@ -1,6 +0,0 @@
1
- import type { HandlerHonoPort } from "./handler-hono.port";
2
- export declare class PingHonoHandler implements HandlerHonoPort {
3
- private readonly handler;
4
- handle(): [import("hono/types").H<import("hono").Env, string, {}, Promise<Response & import("hono").TypedResponse<"pong", 200, "text">>>];
5
- }
6
- //# sourceMappingURL=ping-hono.handler.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ping-hono.handler.d.ts","sourceRoot":"","sources":["../src/ping-hono.handler.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAK3D,qBAAa,eAAgB,YAAW,eAAe;IACrD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;IAE7C,MAAM;CAOP"}
@@ -1,13 +0,0 @@
1
- import { createFactory } from "hono/factory";
2
- import { PingHandler } from "./ping.handler";
3
- const factory = createFactory();
4
- export class PingHonoHandler {
5
- handler = new PingHandler();
6
- handle() {
7
- return factory.createHandlers(async (c) => {
8
- const result = this.handler.execute();
9
- return c.text(result, 200);
10
- });
11
- }
12
- }
13
- //# sourceMappingURL=ping-hono.handler.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ping-hono.handler.js","sourceRoot":"","sources":["../src/ping-hono.handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,MAAM,OAAO,GAAG,aAAa,EAAE,CAAC;AAEhC,MAAM,OAAO,eAAe;IACT,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;IAE7C,MAAM;QACJ,OAAO,OAAO,CAAC,cAAc,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE;YACxC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;YAEtC,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC7B,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
@@ -1,4 +0,0 @@
1
- export declare class PingHandler {
2
- execute(): "pong";
3
- }
4
- //# sourceMappingURL=ping.handler.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ping.handler.d.ts","sourceRoot":"","sources":["../src/ping.handler.ts"],"names":[],"mappings":"AAAA,qBAAa,WAAW;IACtB,OAAO,IAAI,MAAM;CAGlB"}
@@ -1,6 +0,0 @@
1
- export class PingHandler {
2
- execute() {
3
- return "pong";
4
- }
5
- }
6
- //# sourceMappingURL=ping.handler.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ping.handler.js","sourceRoot":"","sources":["../src/ping.handler.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,WAAW;IACtB,OAAO;QACL,OAAO,MAAM,CAAC;IAChB,CAAC;CACF"}
@@ -1,9 +0,0 @@
1
- import * as tools from "@bgord/tools";
2
- import type { RetryBackoffStrategy } from "./retry-backoff.strategy";
3
- export declare class RetryBackoffFibonacciStrategy implements RetryBackoffStrategy {
4
- private readonly delay;
5
- constructor(delay: tools.Duration);
6
- next(attempt: tools.IntegerPositiveType): tools.Duration;
7
- private fibonacci;
8
- }
9
- //# sourceMappingURL=retry-backoff-fibonacci.strategy.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"retry-backoff-fibonacci.strategy.d.ts","sourceRoot":"","sources":["../src/retry-backoff-fibonacci.strategy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AAEtC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAErE,qBAAa,6BAA8B,YAAW,oBAAoB;IAC5D,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAAL,KAAK,EAAE,KAAK,CAAC,QAAQ;IAElD,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,mBAAmB,GAAG,KAAK,CAAC,QAAQ;IAIxD,OAAO,CAAC,SAAS;CAKlB"}
@@ -1,19 +0,0 @@
1
- import * as tools from "@bgord/tools";
2
- import * as v from "valibot";
3
- export class RetryBackoffFibonacciStrategy {
4
- delay;
5
- constructor(delay) {
6
- this.delay = delay;
7
- }
8
- next(attempt) {
9
- return this.delay.times(v.parse(tools.MultiplicationFactor, this.fibonacci(attempt)));
10
- }
11
- fibonacci(n) {
12
- if (n === 0)
13
- return 0;
14
- if (n === 1)
15
- return 1;
16
- return this.fibonacci(n - 1) + this.fibonacci(n - 2);
17
- }
18
- }
19
- //# sourceMappingURL=retry-backoff-fibonacci.strategy.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"retry-backoff-fibonacci.strategy.js","sourceRoot":"","sources":["../src/retry-backoff-fibonacci.strategy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAC;AACtC,OAAO,KAAK,CAAC,MAAM,SAAS,CAAC;AAG7B,MAAM,OAAO,6BAA6B;IACX;IAA7B,YAA6B,KAAqB;QAArB,UAAK,GAAL,KAAK,CAAgB;IAAG,CAAC;IAEtD,IAAI,CAAC,OAAkC;QACrC,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,oBAAoB,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACxF,CAAC;IAEO,SAAS,CAAC,CAAS;QACzB,IAAI,CAAC,KAAK,CAAC;YAAE,OAAO,CAAC,CAAC;QACtB,IAAI,CAAC,KAAK,CAAC;YAAE,OAAO,CAAC,CAAC;QACtB,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACvD,CAAC;CACF"}
@@ -1,17 +0,0 @@
1
- import { createFactory } from "hono/factory";
2
- import type { HandlerHonoPort } from "./handler-hono.port";
3
- import { PingHandler } from "./ping.handler";
4
-
5
- const factory = createFactory();
6
-
7
- export class PingHonoHandler implements HandlerHonoPort {
8
- private readonly handler = new PingHandler();
9
-
10
- handle() {
11
- return factory.createHandlers(async (c) => {
12
- const result = this.handler.execute();
13
-
14
- return c.text(result, 200);
15
- });
16
- }
17
- }