@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.
- package/dist/antivirus-clamav.adapter.js +1 -1
- package/dist/antivirus-clamav.adapter.js.map +1 -1
- package/dist/antivirus-with-logger.adapter.d.ts +17 -0
- package/dist/antivirus-with-logger.adapter.d.ts.map +1 -0
- package/dist/antivirus-with-logger.adapter.js +35 -0
- package/dist/antivirus-with-logger.adapter.js.map +1 -0
- package/dist/antivirus-with-semaphore.adapter.d.ts +14 -0
- package/dist/antivirus-with-semaphore.adapter.d.ts.map +1 -0
- package/dist/antivirus-with-semaphore.adapter.js +10 -0
- package/dist/antivirus-with-semaphore.adapter.js.map +1 -0
- package/dist/csv-stringifier-noop.adapter.d.ts +5 -0
- package/dist/csv-stringifier-noop.adapter.d.ts.map +1 -0
- package/dist/csv-stringifier-noop.adapter.js +6 -0
- package/dist/csv-stringifier-noop.adapter.js.map +1 -0
- package/dist/environment-loader-encrypted.adapter.d.ts.map +1 -1
- package/dist/environment-loader-encrypted.adapter.js +0 -1
- package/dist/environment-loader-encrypted.adapter.js.map +1 -1
- package/dist/environment-loader-noop.adapter.d.ts.map +1 -1
- package/dist/environment-loader-noop.adapter.js +0 -1
- package/dist/environment-loader-noop.adapter.js.map +1 -1
- package/dist/environment-loader-process-safe.adapter.d.ts.map +1 -1
- package/dist/environment-loader-process-safe.adapter.js +0 -1
- package/dist/environment-loader-process-safe.adapter.js.map +1 -1
- package/dist/environment-loader-process.adapter.d.ts.map +1 -1
- package/dist/environment-loader-process.adapter.js +0 -1
- package/dist/environment-loader-process.adapter.js.map +1 -1
- package/dist/event-loop-lag.service.js +1 -1
- package/dist/event-loop-lag.service.js.map +1 -1
- package/dist/event-loop-utilization.service.d.ts.map +1 -1
- package/dist/event-loop-utilization.service.js +0 -2
- package/dist/event-loop-utilization.service.js.map +1 -1
- package/dist/event-store-with-logger.adapter.d.ts.map +1 -1
- package/dist/event-store-with-logger.adapter.js +0 -1
- package/dist/event-store-with-logger.adapter.js.map +1 -1
- package/dist/event-upcaster-chain.adapter.js +1 -1
- package/dist/event-upcaster-chain.adapter.js.map +1 -1
- package/dist/event-validator-registry.adapter.d.ts.map +1 -1
- package/dist/event-validator-registry.adapter.js +0 -1
- package/dist/event-validator-registry.adapter.js.map +1 -1
- package/dist/file-copier.adapter.d.ts.map +1 -1
- package/dist/file-copier.adapter.js +0 -2
- package/dist/file-copier.adapter.js.map +1 -1
- package/dist/file-writer-forgiving.adapter.d.ts +6 -0
- package/dist/file-writer-forgiving.adapter.d.ts.map +1 -0
- package/dist/file-writer-forgiving.adapter.js +10 -0
- package/dist/file-writer-forgiving.adapter.js.map +1 -0
- package/dist/graceful-shutdown.service.d.ts.map +1 -1
- package/dist/graceful-shutdown.service.js +1 -3
- package/dist/graceful-shutdown.service.js.map +1 -1
- package/dist/image-alpha-with-semaphore.adapter.d.ts +14 -0
- package/dist/image-alpha-with-semaphore.adapter.d.ts.map +1 -0
- package/dist/image-alpha-with-semaphore.adapter.js +10 -0
- package/dist/image-alpha-with-semaphore.adapter.js.map +1 -0
- package/dist/image-blur-with-semaphore.adapter.d.ts +14 -0
- package/dist/image-blur-with-semaphore.adapter.d.ts.map +1 -0
- package/dist/image-blur-with-semaphore.adapter.js +10 -0
- package/dist/image-blur-with-semaphore.adapter.js.map +1 -0
- package/dist/image-compressor-with-semaphore.adapter.d.ts +14 -0
- package/dist/image-compressor-with-semaphore.adapter.d.ts.map +1 -0
- package/dist/image-compressor-with-semaphore.adapter.js +10 -0
- package/dist/image-compressor-with-semaphore.adapter.js.map +1 -0
- package/dist/image-exif-clear-with-semaphore.adapter.d.ts +14 -0
- package/dist/image-exif-clear-with-semaphore.adapter.d.ts.map +1 -0
- package/dist/image-exif-clear-with-semaphore.adapter.js +10 -0
- package/dist/image-exif-clear-with-semaphore.adapter.js.map +1 -0
- package/dist/image-formatter-with-semaphore.adapter.d.ts +14 -0
- package/dist/image-formatter-with-semaphore.adapter.d.ts.map +1 -0
- package/dist/image-formatter-with-semaphore.adapter.js +10 -0
- package/dist/image-formatter-with-semaphore.adapter.js.map +1 -0
- package/dist/image-grayscale-with-semaphore.adapter.d.ts +14 -0
- package/dist/image-grayscale-with-semaphore.adapter.d.ts.map +1 -0
- package/dist/image-grayscale-with-semaphore.adapter.js +10 -0
- package/dist/image-grayscale-with-semaphore.adapter.js.map +1 -0
- package/dist/image-info-with-semaphore.adapter.d.ts +14 -0
- package/dist/image-info-with-semaphore.adapter.d.ts.map +1 -0
- package/dist/image-info-with-semaphore.adapter.js +10 -0
- package/dist/image-info-with-semaphore.adapter.js.map +1 -0
- package/dist/image-processor-with-semaphore.adapter.d.ts +14 -0
- package/dist/image-processor-with-semaphore.adapter.d.ts.map +1 -0
- package/dist/image-processor-with-semaphore.adapter.js +10 -0
- package/dist/image-processor-with-semaphore.adapter.js.map +1 -0
- package/dist/image-resizer-with-semaphore.adapter.d.ts +14 -0
- package/dist/image-resizer-with-semaphore.adapter.d.ts.map +1 -0
- package/dist/image-resizer-with-semaphore.adapter.js +10 -0
- package/dist/image-resizer-with-semaphore.adapter.js.map +1 -0
- package/dist/index.d.ts +15 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -1
- package/dist/index.js.map +1 -1
- package/dist/language-detector-header.strategy.d.ts.map +1 -1
- package/dist/language-detector-header.strategy.js +0 -2
- package/dist/language-detector-header.strategy.js.map +1 -1
- package/dist/logger.port.d.ts +1 -2
- package/dist/logger.port.d.ts.map +1 -1
- package/dist/logger.port.js.map +1 -1
- package/dist/prerequisite-verifier-dns.adapter.js +1 -1
- package/dist/prerequisite-verifier-dns.adapter.js.map +1 -1
- package/dist/prerequisite-verifier-with-retry.adapter.d.ts.map +1 -1
- package/dist/prerequisite-verifier-with-retry.adapter.js +0 -2
- package/dist/prerequisite-verifier-with-retry.adapter.js.map +1 -1
- package/dist/prerequisite-verifier.port.d.ts +2 -2
- package/dist/prerequisite-verifier.port.d.ts.map +1 -1
- package/dist/prerequisite-verifier.port.js +2 -2
- package/dist/prerequisite-verifier.port.js.map +1 -1
- package/dist/randomness-crypto.strategy.js +1 -1
- package/dist/randomness-crypto.strategy.js.map +1 -1
- package/dist/redactor-error-cause-depth-limit.strategy.d.ts.map +1 -1
- package/dist/redactor-error-cause-depth-limit.strategy.js +2 -6
- package/dist/redactor-error-cause-depth-limit.strategy.js.map +1 -1
- package/dist/redactor-error-stack-hide.strategy.d.ts.map +1 -1
- package/dist/redactor-error-stack-hide.strategy.js +3 -6
- package/dist/redactor-error-stack-hide.strategy.js.map +1 -1
- package/dist/redactor-mask.strategy.js +2 -2
- package/dist/redactor-mask.strategy.js.map +1 -1
- package/dist/redactor-metadata-compact-array.strategy.d.ts.map +1 -1
- package/dist/redactor-metadata-compact-array.strategy.js +2 -4
- package/dist/redactor-metadata-compact-array.strategy.js.map +1 -1
- package/dist/redactor-metadata-compact-object.strategy.d.ts.map +1 -1
- package/dist/redactor-metadata-compact-object.strategy.js +3 -5
- package/dist/redactor-metadata-compact-object.strategy.js.map +1 -1
- package/dist/remote-file-storage-noop.adapter.d.ts +4 -7
- package/dist/remote-file-storage-noop.adapter.d.ts.map +1 -1
- package/dist/remote-file-storage-noop.adapter.js +4 -26
- package/dist/remote-file-storage-noop.adapter.js.map +1 -1
- package/dist/remote-file-storage-with-logger.adapter.d.ts +21 -0
- package/dist/remote-file-storage-with-logger.adapter.d.ts.map +1 -0
- package/dist/remote-file-storage-with-logger.adapter.js +111 -0
- package/dist/remote-file-storage-with-logger.adapter.js.map +1 -0
- package/dist/retry.service.d.ts +0 -3
- package/dist/retry.service.d.ts.map +1 -1
- package/dist/retry.service.js +0 -3
- package/dist/retry.service.js.map +1 -1
- package/dist/semaphore.service.d.ts +10 -0
- package/dist/semaphore.service.d.ts.map +1 -0
- package/dist/semaphore.service.js +19 -0
- package/dist/semaphore.service.js.map +1 -0
- package/dist/setup-hono.service.d.ts.map +1 -1
- package/dist/setup-hono.service.js +1 -12
- package/dist/setup-hono.service.js.map +1 -1
- package/dist/shield-ip-whitelist.strategy.d.ts.map +1 -1
- package/dist/shield-ip-whitelist.strategy.js +0 -2
- package/dist/shield-ip-whitelist.strategy.js.map +1 -1
- package/dist/sse-registry.adapter.js +1 -1
- package/dist/sse-registry.adapter.js.map +1 -1
- package/dist/static-files-hono.service.d.ts.map +1 -1
- package/dist/static-files-hono.service.js +0 -2
- package/dist/static-files-hono.service.js.map +1 -1
- package/dist/translations-hono.handler.d.ts +1 -1
- package/dist/translations-hono.handler.d.ts.map +1 -1
- package/dist/translations-hono.handler.js.map +1 -1
- package/dist/woodchopper-diagnostics-collecting.strategy.js +2 -2
- package/dist/woodchopper-diagnostics-collecting.strategy.js.map +1 -1
- package/dist/woodchopper-diagnostics-console-error.strategy.js +2 -2
- package/dist/woodchopper-diagnostics-console-error.strategy.js.map +1 -1
- package/dist/woodchopper-dispatcher-async.strategy.d.ts.map +1 -1
- package/dist/woodchopper-dispatcher-async.strategy.js +0 -2
- package/dist/woodchopper-dispatcher-async.strategy.js.map +1 -1
- package/dist/woodchopper-sampling-correlation-id.strategy.js +1 -1
- package/dist/woodchopper-sampling-correlation-id.strategy.js.map +1 -1
- package/dist/woodchopper-sink-stderr.strategy.js +1 -1
- package/dist/woodchopper-sink-stderr.strategy.js.map +1 -1
- package/dist/woodchopper-sink-stdout-human.strategy.js +1 -1
- package/dist/woodchopper-sink-stdout-human.strategy.js.map +1 -1
- package/dist/woodchopper-sink-stdout.strategy.js +1 -1
- package/dist/woodchopper-sink-stdout.strategy.js.map +1 -1
- package/dist/woodchopper.d.ts.map +1 -1
- package/dist/woodchopper.js +1 -2
- package/dist/woodchopper.js.map +1 -1
- package/package.json +4 -3
- package/readme.md +15 -3
- package/src/antivirus-clamav.adapter.ts +1 -1
- package/src/antivirus-with-logger.adapter.ts +44 -0
- package/src/antivirus-with-semaphore.adapter.ts +13 -0
- package/src/csv-stringifier-noop.adapter.ts +7 -0
- package/src/environment-loader-encrypted.adapter.ts +0 -1
- package/src/environment-loader-noop.adapter.ts +0 -1
- package/src/environment-loader-process-safe.adapter.ts +0 -1
- package/src/environment-loader-process.adapter.ts +0 -1
- package/src/event-loop-lag.service.ts +1 -1
- package/src/event-loop-utilization.service.ts +0 -2
- package/src/event-store-with-logger.adapter.ts +0 -1
- package/src/event-upcaster-chain.adapter.ts +1 -1
- package/src/event-validator-registry.adapter.ts +0 -1
- package/src/file-copier.adapter.ts +0 -2
- package/src/file-writer-forgiving.adapter.ts +14 -0
- package/src/graceful-shutdown.service.ts +0 -2
- package/src/image-alpha-with-semaphore.adapter.ts +13 -0
- package/src/image-blur-with-semaphore.adapter.ts +13 -0
- package/src/image-compressor-with-semaphore.adapter.ts +13 -0
- package/src/image-exif-clear-with-semaphore.adapter.ts +13 -0
- package/src/image-formatter-with-semaphore.adapter.ts +13 -0
- package/src/image-grayscale-with-semaphore.adapter.ts +13 -0
- package/src/image-info-with-semaphore.adapter.ts +13 -0
- package/src/image-processor-with-semaphore.adapter.ts +13 -0
- package/src/image-resizer-with-semaphore.adapter.ts +13 -0
- package/src/index.ts +15 -1
- package/src/language-detector-header.strategy.ts +0 -2
- package/src/logger.port.ts +1 -2
- package/src/prerequisite-verifier-dns.adapter.ts +1 -1
- package/src/prerequisite-verifier-with-retry.adapter.ts +0 -2
- package/src/prerequisite-verifier.port.ts +3 -3
- package/src/randomness-crypto.strategy.ts +1 -1
- package/src/redactor-error-cause-depth-limit.strategy.ts +3 -7
- package/src/redactor-error-stack-hide.strategy.ts +4 -7
- package/src/redactor-mask.strategy.ts +2 -2
- package/src/redactor-metadata-compact-array.strategy.ts +2 -4
- package/src/redactor-metadata-compact-object.strategy.ts +3 -5
- package/src/remote-file-storage-noop.adapter.ts +5 -32
- package/src/remote-file-storage-with-logger.adapter.ts +140 -0
- package/src/retry.service.ts +0 -4
- package/src/semaphore.service.ts +26 -0
- package/src/setup-hono.service.ts +1 -12
- package/src/shield-ip-whitelist.strategy.ts +0 -2
- package/src/sse-registry.adapter.ts +1 -1
- package/src/static-files-hono.service.ts +0 -2
- package/src/translations-hono.handler.ts +1 -1
- package/src/woodchopper-diagnostics-collecting.strategy.ts +2 -2
- package/src/woodchopper-diagnostics-console-error.strategy.ts +2 -2
- package/src/woodchopper-dispatcher-async.strategy.ts +0 -2
- package/src/woodchopper-sampling-correlation-id.strategy.ts +1 -1
- package/src/woodchopper-sink-stderr.strategy.ts +1 -1
- package/src/woodchopper-sink-stdout-human.strategy.ts +1 -1
- package/src/woodchopper-sink-stdout.strategy.ts +1 -1
- package/src/woodchopper.ts +1 -2
- package/dist/deep-clone-with.d.ts +0 -4
- package/dist/deep-clone-with.d.ts.map +0 -1
- package/dist/deep-clone-with.js +0 -22
- package/dist/deep-clone-with.js.map +0 -1
- package/dist/error-normalizer.service.d.ts +0 -12
- package/dist/error-normalizer.service.d.ts.map +0 -1
- package/dist/error-normalizer.service.js +0 -24
- package/dist/error-normalizer.service.js.map +0 -1
- package/dist/is-plain-object.d.ts +0 -2
- package/dist/is-plain-object.d.ts.map +0 -1
- package/dist/is-plain-object.js +0 -7
- package/dist/is-plain-object.js.map +0 -1
- package/src/deep-clone-with.ts +0 -31
- package/src/error-normalizer.service.ts +0 -32
- 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
|
}
|
package/src/logger.port.ts
CHANGED
|
@@ -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
|
|
|
@@ -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
|
|
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
|
|
|
@@ -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
|
-
|
|
11
|
-
if (!
|
|
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
|
|
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
|
-
|
|
8
|
-
if (!
|
|
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
|
|
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 = {
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
+
}
|
package/src/retry.service.ts
CHANGED
|
@@ -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
|
-
|
|
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)
|
|
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(),
|