@bgord/bun 1.19.12 → 1.19.14
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/ab-hono-noop.middleware.d.ts +2 -3
- package/dist/ab-hono-noop.middleware.d.ts.map +1 -1
- package/dist/ab-hono-noop.middleware.js +4 -9
- package/dist/ab-hono-noop.middleware.js.map +1 -1
- package/dist/ab-variant-name.vo.d.ts +9 -0
- package/dist/ab-variant-name.vo.d.ts.map +1 -0
- package/dist/ab-variant-name.vo.js +10 -0
- package/dist/ab-variant-name.vo.js.map +1 -0
- package/dist/ab-variant.vo.d.ts +2 -1
- package/dist/ab-variant.vo.d.ts.map +1 -1
- package/dist/ab-variant.vo.js.map +1 -1
- package/dist/basic-auth-password.vo.d.ts +2 -1
- package/dist/basic-auth-password.vo.d.ts.map +1 -1
- package/dist/basic-auth-password.vo.js +2 -1
- package/dist/basic-auth-password.vo.js.map +1 -1
- package/dist/basic-auth-username.vo.d.ts +2 -1
- package/dist/basic-auth-username.vo.d.ts.map +1 -1
- package/dist/basic-auth-username.vo.js +2 -1
- package/dist/basic-auth-username.vo.js.map +1 -1
- package/dist/cache-repository-redis.adapter.d.ts +1 -2
- package/dist/cache-repository-redis.adapter.d.ts.map +1 -1
- package/dist/cache-repository-redis.adapter.js.map +1 -1
- package/dist/certificate-inspector-noop.adapter.d.ts +2 -1
- package/dist/certificate-inspector-noop.adapter.d.ts.map +1 -1
- package/dist/certificate-inspector-noop.adapter.js.map +1 -1
- package/dist/certificate-inspector-tls.adapter.d.ts +2 -1
- package/dist/certificate-inspector-tls.adapter.d.ts.map +1 -1
- package/dist/certificate-inspector-tls.adapter.js.map +1 -1
- package/dist/certificate-inspector.port.d.ts +2 -1
- package/dist/certificate-inspector.port.d.ts.map +1 -1
- package/dist/csv-stringifier.adapter.d.ts.map +1 -1
- package/dist/csv-stringifier.adapter.js +1 -0
- package/dist/csv-stringifier.adapter.js.map +1 -1
- package/dist/environment-loader-encrypted.adapter.d.ts +1 -1
- package/dist/environment-loader-encrypted.adapter.d.ts.map +1 -1
- package/dist/environment-loader-encrypted.adapter.js +5 -7
- package/dist/environment-loader-encrypted.adapter.js.map +1 -1
- package/dist/environment-loader-noop.adapter.d.ts +1 -1
- package/dist/environment-loader-noop.adapter.d.ts.map +1 -1
- package/dist/environment-loader-noop.adapter.js +5 -7
- package/dist/environment-loader-noop.adapter.js.map +1 -1
- package/dist/environment-loader-process-safe.adapter.d.ts +1 -1
- package/dist/environment-loader-process-safe.adapter.d.ts.map +1 -1
- package/dist/environment-loader-process-safe.adapter.js +2 -9
- package/dist/environment-loader-process-safe.adapter.js.map +1 -1
- package/dist/environment-loader-process.adapter.d.ts +1 -1
- package/dist/environment-loader-process.adapter.d.ts.map +1 -1
- package/dist/environment-loader-process.adapter.js +5 -7
- package/dist/environment-loader-process.adapter.js.map +1 -1
- package/dist/environment-loader.port.d.ts +0 -3
- package/dist/environment-loader.port.d.ts.map +1 -1
- package/dist/environment-loader.port.js +1 -1
- package/dist/environment-loader.port.js.map +1 -1
- package/dist/event-upcaster-chain.adapter.d.ts.map +1 -1
- package/dist/event-upcaster-chain.adapter.js +5 -0
- package/dist/event-upcaster-chain.adapter.js.map +1 -1
- package/dist/event-validator-registry.adapter.d.ts +1 -1
- package/dist/event-validator-registry.adapter.d.ts.map +1 -1
- package/dist/event-validator-registry.adapter.js +2 -7
- package/dist/event-validator-registry.adapter.js.map +1 -1
- package/dist/event-validator-registry.port.d.ts +0 -3
- package/dist/event-validator-registry.port.d.ts.map +1 -1
- package/dist/event-validator-registry.port.js +1 -1
- package/dist/event-validator-registry.port.js.map +1 -1
- package/dist/file-uploader-hono.middleware.d.ts.map +1 -1
- package/dist/file-uploader-hono.middleware.js +4 -13
- package/dist/file-uploader-hono.middleware.js.map +1 -1
- package/dist/file-uploader.middleware.d.ts.map +1 -1
- package/dist/file-uploader.middleware.js +1 -0
- package/dist/file-uploader.middleware.js.map +1 -1
- package/dist/graceful-shutdown.service.d.ts +8 -4
- package/dist/graceful-shutdown.service.d.ts.map +1 -1
- package/dist/graceful-shutdown.service.js +27 -26
- package/dist/graceful-shutdown.service.js.map +1 -1
- package/dist/hostname.vo.d.ts +8 -0
- package/dist/hostname.vo.d.ts.map +1 -0
- package/dist/hostname.vo.js +9 -0
- package/dist/hostname.vo.js.map +1 -0
- package/dist/http-logger.middleware.js +1 -1
- package/dist/http-logger.middleware.js.map +1 -1
- package/dist/image-blur.adapter.d.ts +2 -0
- package/dist/image-blur.adapter.d.ts.map +1 -1
- package/dist/image-blur.adapter.js +1 -1
- package/dist/image-blur.adapter.js.map +1 -1
- package/dist/image-compressor.adapter.d.ts +2 -0
- package/dist/image-compressor.adapter.d.ts.map +1 -1
- package/dist/image-compressor.adapter.js +1 -1
- package/dist/image-compressor.adapter.js.map +1 -1
- package/dist/image-exif-clear.adapter.d.ts +2 -0
- package/dist/image-exif-clear.adapter.d.ts.map +1 -1
- package/dist/image-exif-clear.adapter.js +1 -1
- package/dist/image-exif-clear.adapter.js.map +1 -1
- package/dist/image-formatter.adapter.d.ts +2 -0
- package/dist/image-formatter.adapter.d.ts.map +1 -1
- package/dist/image-formatter.adapter.js +1 -1
- package/dist/image-formatter.adapter.js.map +1 -1
- package/dist/image-generator-web-view.adapter.d.ts.map +1 -1
- package/dist/image-generator-web-view.adapter.js +1 -0
- package/dist/image-generator-web-view.adapter.js.map +1 -1
- package/dist/image-grayscale.adapter.d.ts +2 -0
- package/dist/image-grayscale.adapter.d.ts.map +1 -1
- package/dist/image-grayscale.adapter.js +1 -1
- package/dist/image-grayscale.adapter.js.map +1 -1
- package/dist/image-processor.adapter.d.ts +2 -0
- package/dist/image-processor.adapter.d.ts.map +1 -1
- package/dist/image-processor.adapter.js +1 -1
- package/dist/image-processor.adapter.js.map +1 -1
- package/dist/image-resizer.adapter.d.ts +2 -0
- package/dist/image-resizer.adapter.d.ts.map +1 -1
- package/dist/image-resizer.adapter.js +1 -1
- package/dist/image-resizer.adapter.js.map +1 -1
- package/dist/image.types.d.ts +1 -1
- package/dist/image.types.d.ts.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/job-registry.adapter.d.ts +1 -1
- package/dist/job-registry.adapter.d.ts.map +1 -1
- package/dist/job-registry.adapter.js +2 -7
- package/dist/job-registry.adapter.js.map +1 -1
- package/dist/job-registry.port.d.ts +0 -3
- package/dist/job-registry.port.d.ts.map +1 -1
- package/dist/job-registry.port.js +1 -1
- package/dist/job-registry.port.js.map +1 -1
- package/dist/prerequisite-verifier-binary.adapter.js +1 -1
- package/dist/prerequisite-verifier-binary.adapter.js.map +1 -1
- package/dist/prerequisite-verifier-dns.adapter.d.ts +2 -1
- package/dist/prerequisite-verifier-dns.adapter.d.ts.map +1 -1
- package/dist/prerequisite-verifier-dns.adapter.js.map +1 -1
- package/dist/prerequisite-verifier-ssl-certificate-expiry.adapter.d.ts +2 -1
- package/dist/prerequisite-verifier-ssl-certificate-expiry.adapter.d.ts.map +1 -1
- package/dist/prerequisite-verifier-ssl-certificate-expiry.adapter.js.map +1 -1
- package/dist/prerequisite-verifier-translations.adapter.js +5 -5
- package/dist/prerequisite-verifier-translations.adapter.js.map +1 -1
- package/dist/reactive-config-file-json.adapter.d.ts +1 -1
- package/dist/reactive-config-file-json.adapter.d.ts.map +1 -1
- package/dist/reactive-config-file-json.adapter.js +2 -7
- package/dist/reactive-config-file-json.adapter.js.map +1 -1
- package/dist/reactive-config-noop.adapter.d.ts +1 -1
- package/dist/reactive-config-noop.adapter.d.ts.map +1 -1
- package/dist/reactive-config-noop.adapter.js +2 -7
- package/dist/reactive-config-noop.adapter.js.map +1 -1
- package/dist/reactive-config-with-fallback.adapter.d.ts +1 -1
- package/dist/reactive-config-with-fallback.adapter.d.ts.map +1 -1
- package/dist/reactive-config-with-fallback.adapter.js +2 -7
- package/dist/reactive-config-with-fallback.adapter.js.map +1 -1
- package/dist/reactive-config.port.d.ts +0 -3
- package/dist/reactive-config.port.d.ts.map +1 -1
- package/dist/reactive-config.port.js +1 -1
- package/dist/reactive-config.port.js.map +1 -1
- package/dist/remote-file-storage-disk.adapter.d.ts +2 -0
- package/dist/remote-file-storage-disk.adapter.d.ts.map +1 -1
- package/dist/remote-file-storage-disk.adapter.js +1 -1
- package/dist/remote-file-storage-disk.adapter.js.map +1 -1
- package/dist/shield-api-key.strategy.d.ts.map +1 -1
- package/dist/shield-api-key.strategy.js +6 -1
- package/dist/shield-api-key.strategy.js.map +1 -1
- package/dist/shield-basic-auth.strategy.d.ts.map +1 -1
- package/dist/shield-basic-auth.strategy.js +3 -2
- package/dist/shield-basic-auth.strategy.js.map +1 -1
- package/dist/shield-recaptcha.strategy.js +1 -1
- package/dist/shield-recaptcha.strategy.js.map +1 -1
- package/dist/sitemap-entry.vo.d.ts +1 -0
- package/dist/sitemap-entry.vo.d.ts.map +1 -1
- package/dist/sitemap-entry.vo.js +9 -1
- package/dist/sitemap-entry.vo.js.map +1 -1
- package/dist/standard-schema-validator.service.d.ts +5 -0
- package/dist/standard-schema-validator.service.d.ts.map +1 -0
- package/dist/standard-schema-validator.service.js +14 -0
- package/dist/standard-schema-validator.service.js.map +1 -0
- package/dist/subject-application-resolver.vo.d.ts +0 -1
- package/dist/subject-application-resolver.vo.d.ts.map +1 -1
- package/dist/subject-application-resolver.vo.js +2 -3
- package/dist/subject-application-resolver.vo.js.map +1 -1
- package/dist/subject-request-resolver.vo.d.ts +0 -1
- package/dist/subject-request-resolver.vo.d.ts.map +1 -1
- package/dist/subject-request-resolver.vo.js +2 -3
- package/dist/subject-request-resolver.vo.js.map +1 -1
- package/dist/temporary-file-absolute.adapter.d.ts +2 -0
- package/dist/temporary-file-absolute.adapter.d.ts.map +1 -1
- package/dist/temporary-file-absolute.adapter.js +1 -1
- package/dist/temporary-file-absolute.adapter.js.map +1 -1
- package/dist/timing.middleware.d.ts.map +1 -1
- package/dist/timing.middleware.js +1 -2
- package/dist/timing.middleware.js.map +1 -1
- package/dist/woodchopper-sampling-every-nth.strategy.d.ts.map +1 -1
- package/dist/woodchopper-sampling-every-nth.strategy.js +1 -3
- package/dist/woodchopper-sampling-every-nth.strategy.js.map +1 -1
- package/package.json +7 -7
- package/readme.md +3 -0
- package/src/ab-hono-noop.middleware.ts +2 -13
- package/src/ab-variant-name.vo.ts +17 -0
- package/src/ab-variant.vo.ts +2 -1
- package/src/basic-auth-password.vo.ts +5 -0
- package/src/basic-auth-username.vo.ts +5 -0
- package/src/cache-repository-redis.adapter.ts +1 -2
- package/src/certificate-inspector-noop.adapter.ts +2 -1
- package/src/certificate-inspector-tls.adapter.ts +2 -1
- package/src/certificate-inspector.port.ts +2 -1
- package/src/csv-stringifier.adapter.ts +1 -0
- package/src/environment-loader-encrypted.adapter.ts +9 -9
- package/src/environment-loader-noop.adapter.ts +9 -9
- package/src/environment-loader-process-safe.adapter.ts +8 -11
- package/src/environment-loader-process.adapter.ts +9 -9
- package/src/environment-loader.port.ts +0 -2
- package/src/event-upcaster-chain.adapter.ts +5 -0
- package/src/event-validator-registry.adapter.ts +3 -9
- package/src/event-validator-registry.port.ts +0 -2
- package/src/file-uploader-hono.middleware.ts +3 -17
- package/src/file-uploader.middleware.ts +1 -0
- package/src/graceful-shutdown.service.ts +27 -28
- package/src/hostname.vo.ts +15 -0
- package/src/http-logger.middleware.ts +1 -1
- package/src/image-blur.adapter.ts +9 -2
- package/src/image-compressor.adapter.ts +9 -2
- package/src/image-exif-clear.adapter.ts +9 -2
- package/src/image-formatter.adapter.ts +5 -1
- package/src/image-generator-web-view.adapter.ts +1 -0
- package/src/image-grayscale.adapter.ts +9 -2
- package/src/image-processor.adapter.ts +5 -1
- package/src/image-resizer.adapter.ts +9 -2
- package/src/image.types.ts +1 -1
- package/src/index.ts +2 -0
- package/src/job-registry.adapter.ts +3 -6
- package/src/job-registry.port.ts +0 -2
- package/src/prerequisite-verifier-binary.adapter.ts +1 -1
- package/src/prerequisite-verifier-dns.adapter.ts +2 -1
- package/src/prerequisite-verifier-ssl-certificate-expiry.adapter.ts +2 -1
- package/src/prerequisite-verifier-translations.adapter.ts +4 -4
- package/src/reactive-config-file-json.adapter.ts +3 -9
- package/src/reactive-config-noop.adapter.ts +3 -9
- package/src/reactive-config-with-fallback.adapter.ts +3 -9
- package/src/reactive-config.port.ts +0 -2
- package/src/remote-file-storage-disk.adapter.ts +5 -1
- package/src/shield-api-key.strategy.ts +7 -1
- package/src/shield-basic-auth.strategy.ts +4 -2
- package/src/shield-recaptcha.strategy.ts +1 -1
- package/src/sitemap-entry.vo.ts +11 -4
- package/src/standard-schema-validator.service.ts +15 -0
- package/src/subject-application-resolver.vo.ts +2 -6
- package/src/subject-request-resolver.vo.ts +2 -6
- package/src/temporary-file-absolute.adapter.ts +6 -1
- package/src/timing.middleware.ts +1 -3
- package/src/woodchopper-sampling-every-nth.strategy.ts +1 -2
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
type EnvironmentResultType,
|
|
1
|
+
import type {
|
|
2
|
+
EnvironmentLoaderConfig,
|
|
3
|
+
EnvironmentLoaderPort,
|
|
4
|
+
EnvironmentResultType,
|
|
6
5
|
} from "./environment-loader.port";
|
|
6
|
+
import { StandardSchemaValidator } from "./standard-schema-validator.service";
|
|
7
7
|
|
|
8
8
|
export class EnvironmentLoaderNoopAdapter<T extends object> implements EnvironmentLoaderPort<T> {
|
|
9
9
|
constructor(
|
|
@@ -12,9 +12,9 @@ export class EnvironmentLoaderNoopAdapter<T extends object> implements Environme
|
|
|
12
12
|
) {}
|
|
13
13
|
|
|
14
14
|
async load(): Promise<Readonly<EnvironmentResultType<T>>> {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
return Object.freeze({
|
|
16
|
+
...StandardSchemaValidator.validate(this.config.EnvironmentSchema, this.deterministic),
|
|
17
|
+
type: this.config.type,
|
|
18
|
+
});
|
|
19
19
|
}
|
|
20
20
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { CacheResolverStrategy } from "./cache-resolver.strategy";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
type EnvironmentResultType,
|
|
2
|
+
import type {
|
|
3
|
+
EnvironmentLoaderConfig,
|
|
4
|
+
EnvironmentLoaderPort,
|
|
5
|
+
EnvironmentResultType,
|
|
7
6
|
} from "./environment-loader.port";
|
|
8
7
|
import type { HashContentStrategy } from "./hash-content.strategy";
|
|
8
|
+
import { StandardSchemaValidator } from "./standard-schema-validator.service";
|
|
9
9
|
import { SubjectApplicationResolver } from "./subject-application-resolver.vo";
|
|
10
10
|
import { SubjectSegmentFixedStrategy } from "./subject-segment-fixed.strategy";
|
|
11
11
|
|
|
@@ -22,12 +22,9 @@ export class EnvironmentLoaderProcessSafeAdapter<T extends object> implements En
|
|
|
22
22
|
const resolver = new SubjectApplicationResolver([new SubjectSegmentFixedStrategy("env")], this.deps);
|
|
23
23
|
const subject = await resolver.resolve();
|
|
24
24
|
|
|
25
|
-
const parsed = await this.deps.CacheResolver.resolve(subject.hex, async () =>
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
if (result.issues) throw new Error(result.issues[0]?.message);
|
|
29
|
-
return result.value;
|
|
30
|
-
});
|
|
25
|
+
const parsed = await this.deps.CacheResolver.resolve(subject.hex, async () =>
|
|
26
|
+
StandardSchemaValidator.validate(this.config.EnvironmentSchema, this.env),
|
|
27
|
+
);
|
|
31
28
|
|
|
32
29
|
for (const key of Object.keys(parsed)) delete process.env[key];
|
|
33
30
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
type EnvironmentResultType,
|
|
1
|
+
import type {
|
|
2
|
+
EnvironmentLoaderConfig,
|
|
3
|
+
EnvironmentLoaderPort,
|
|
4
|
+
EnvironmentResultType,
|
|
6
5
|
} from "./environment-loader.port";
|
|
6
|
+
import { StandardSchemaValidator } from "./standard-schema-validator.service";
|
|
7
7
|
|
|
8
8
|
export class EnvironmentLoaderProcessAdapter<T extends object> implements EnvironmentLoaderPort<T> {
|
|
9
9
|
constructor(
|
|
@@ -12,9 +12,9 @@ export class EnvironmentLoaderProcessAdapter<T extends object> implements Enviro
|
|
|
12
12
|
) {}
|
|
13
13
|
|
|
14
14
|
async load(): Promise<Readonly<EnvironmentResultType<T>>> {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
return Object.freeze({
|
|
16
|
+
...StandardSchemaValidator.validate(this.config.EnvironmentSchema, this.env),
|
|
17
|
+
type: this.config.type,
|
|
18
|
+
});
|
|
19
19
|
}
|
|
20
20
|
}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import type { StandardSchemaV1 } from "@standard-schema/spec";
|
|
2
2
|
import type { NodeEnvironmentEnum } from "../src/node-env.vo";
|
|
3
3
|
|
|
4
|
-
export const EnvironmentLoaderError = { NoAsyncSchema: "environment.loader.no.async.schema" };
|
|
5
|
-
|
|
6
4
|
export type EnvironmentLoaderConfig<T extends object> = {
|
|
7
5
|
type: NodeEnvironmentEnum;
|
|
8
6
|
EnvironmentSchema: StandardSchemaV1<unknown, T>;
|
|
@@ -6,6 +6,7 @@ import type { EventUpcasterStep } from "./event-upcaster-step.vo";
|
|
|
6
6
|
const EventUpcasterChainAdapterError = {
|
|
7
7
|
DuplicateStep: "event.upcaster.chain.duplicate.step",
|
|
8
8
|
GapInChain: "event.upcaster.chain.gap",
|
|
9
|
+
StartOffset: "event.upcaster.chain.start.offset",
|
|
9
10
|
};
|
|
10
11
|
|
|
11
12
|
type EventUpcasterChainConfig = Record<GenericEvent["name"], ReadonlyArray<EventUpcasterStep<any, any>>>;
|
|
@@ -21,6 +22,10 @@ export class EventUpcasterChainAdapter implements EventUpcasterPort {
|
|
|
21
22
|
]),
|
|
22
23
|
);
|
|
23
24
|
|
|
25
|
+
for (const [_, chain] of Object.entries(this.upcasters)) {
|
|
26
|
+
if (chain[0]?.config.fromVersion !== 1) throw new Error(EventUpcasterChainAdapterError.StartOffset);
|
|
27
|
+
}
|
|
28
|
+
|
|
24
29
|
for (const chain of Object.values(this.upcasters)) {
|
|
25
30
|
const versions = chain.map((step) => step.config.fromVersion);
|
|
26
31
|
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import type { StandardSchemaV1 } from "@standard-schema/spec";
|
|
2
2
|
import type { GenericEvent } from "./event.types";
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
type EventValidatorRegistryPort,
|
|
6
|
-
} from "./event-validator-registry.port";
|
|
3
|
+
import type { EventValidatorRegistryPort } from "./event-validator-registry.port";
|
|
4
|
+
import { StandardSchemaValidator } from "./standard-schema-validator.service";
|
|
7
5
|
|
|
8
6
|
export type GenericEventSchemaRegistry<Event> = Readonly<
|
|
9
7
|
Record<GenericEvent["name"], StandardSchemaV1<unknown, Event>>
|
|
@@ -34,10 +32,6 @@ export class EventValidatorRegistryAdapter<Event> implements EventValidatorRegis
|
|
|
34
32
|
const schema = this.map.get(name);
|
|
35
33
|
if (!schema) throw new Error(EventValidatorRegistryAdapterError.UnknownEvent);
|
|
36
34
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
if (result instanceof Promise) throw new Error(EventValidatorRegistryError.NoAsyncSchema);
|
|
40
|
-
if (result.issues) throw new Error(result.issues[0]?.message);
|
|
41
|
-
return result.value;
|
|
35
|
+
return StandardSchemaValidator.validate(schema, raw);
|
|
42
36
|
}
|
|
43
37
|
}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import type { GenericEvent } from "./event.types";
|
|
2
2
|
|
|
3
|
-
export const EventValidatorRegistryError = { NoAsyncSchema: "event.validator.registry.no.async.schema" };
|
|
4
|
-
|
|
5
3
|
export interface EventValidatorRegistryPort<Event> {
|
|
6
4
|
readonly names: ReadonlyArray<GenericEvent["name"]>;
|
|
7
5
|
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import { createMiddleware } from "hono/factory";
|
|
2
2
|
import { HTTPException } from "hono/http-exception";
|
|
3
|
-
import {
|
|
4
|
-
type FileUploaderConfig,
|
|
5
|
-
FileUploaderError,
|
|
6
|
-
FileUploaderMiddleware,
|
|
7
|
-
} from "./file-uploader.middleware";
|
|
3
|
+
import { type FileUploaderConfig, FileUploaderMiddleware } from "./file-uploader.middleware";
|
|
8
4
|
import type { MiddlewareHonoPort } from "./middleware-hono.port";
|
|
9
5
|
|
|
10
6
|
export class FileUploaderHonoMiddleware implements MiddlewareHonoPort {
|
|
@@ -21,18 +17,8 @@ export class FileUploaderHonoMiddleware implements MiddlewareHonoPort {
|
|
|
21
17
|
|
|
22
18
|
const result = this.middleware.validate(file instanceof File ? file : null);
|
|
23
19
|
|
|
24
|
-
if (result.valid)
|
|
25
|
-
|
|
26
|
-
switch (result.error) {
|
|
27
|
-
case FileUploaderError.MissingFile:
|
|
28
|
-
throw new HTTPException(400, { message: FileUploaderError.MissingFile });
|
|
29
|
-
case FileUploaderError.EmptyFile:
|
|
30
|
-
throw new HTTPException(400, { message: FileUploaderError.EmptyFile });
|
|
31
|
-
case FileUploaderError.SizeLimit:
|
|
32
|
-
throw new HTTPException(400, { message: FileUploaderError.SizeLimit });
|
|
33
|
-
case FileUploaderError.InvalidMime:
|
|
34
|
-
throw new HTTPException(400, { message: FileUploaderError.InvalidMime });
|
|
35
|
-
}
|
|
20
|
+
if (result.valid === false) throw new HTTPException(400, { message: result.error });
|
|
21
|
+
return next();
|
|
36
22
|
});
|
|
37
23
|
}
|
|
38
24
|
}
|
|
@@ -24,6 +24,7 @@ export class FileUploaderMiddleware {
|
|
|
24
24
|
|
|
25
25
|
if (size.isGreaterThan(this.config.maxSize)) return { valid: false, error: FileUploaderError.SizeLimit };
|
|
26
26
|
|
|
27
|
+
// TODO: MIME spoofing possible by reading client-supplied file.type
|
|
27
28
|
const mime = tools.Mime.fromString(file.type);
|
|
28
29
|
|
|
29
30
|
if (!this.config.MimeRegistry.hasMime(mime)) {
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import * as tools from "@bgord/tools";
|
|
2
2
|
import type { LoggerPort } from "./logger.port";
|
|
3
3
|
|
|
4
|
-
type ServerType = ReturnType<typeof Bun.serve>;
|
|
4
|
+
export type ServerType = ReturnType<typeof Bun.serve>;
|
|
5
5
|
|
|
6
6
|
type Dependencies = { Logger: LoggerPort };
|
|
7
|
+
type Config = { cleanup: () => Promise<void> | void; exit?: (code: number) => never };
|
|
7
8
|
|
|
8
9
|
export class GracefulShutdown {
|
|
9
10
|
private readonly base = { operation: "shutdown", component: "infra" } as const;
|
|
@@ -11,10 +12,10 @@ export class GracefulShutdown {
|
|
|
11
12
|
|
|
12
13
|
constructor(
|
|
13
14
|
private readonly deps: Dependencies,
|
|
14
|
-
private readonly
|
|
15
|
+
private readonly config: Config = { cleanup: tools.noop, exit: process.exit },
|
|
15
16
|
) {}
|
|
16
17
|
|
|
17
|
-
private shutdown(server: ServerType,
|
|
18
|
+
private async shutdown(server: ServerType, exitCode: number) {
|
|
18
19
|
// Stryker disable all
|
|
19
20
|
if (this.isShuttingDown) return;
|
|
20
21
|
this.isShuttingDown = true;
|
|
@@ -26,32 +27,30 @@ export class GracefulShutdown {
|
|
|
26
27
|
this.deps.Logger.error({ message: "Server stop failed", error, ...this.base });
|
|
27
28
|
}
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
.
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
.
|
|
30
|
+
try {
|
|
31
|
+
await this.config.cleanup();
|
|
32
|
+
this.deps.Logger.info({ message: "HTTP server closed", ...this.base });
|
|
33
|
+
} catch (error) {
|
|
34
|
+
this.deps.Logger.error({ message: "Cleanup hook failed", error, ...this.base });
|
|
35
|
+
} finally {
|
|
36
|
+
this.config.exit?.(exitCode);
|
|
37
|
+
}
|
|
34
38
|
}
|
|
35
39
|
|
|
36
|
-
applyTo(server: ServerType
|
|
37
|
-
|
|
38
|
-
this.deps.Logger.info({ message:
|
|
39
|
-
this.shutdown(server,
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
this.deps.Logger.
|
|
44
|
-
this.shutdown(server,
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
process.once("
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
process.once("uncaughtException", (error) => {
|
|
53
|
-
this.deps.Logger.error({ message: "UncaughtException received", error, ...this.base });
|
|
54
|
-
this.shutdown(server, cleanup, 1);
|
|
55
|
-
});
|
|
40
|
+
applyTo(server: ServerType) {
|
|
41
|
+
const graceful = (signal: string) => () => {
|
|
42
|
+
this.deps.Logger.info({ message: `${signal} received`, ...this.base });
|
|
43
|
+
this.shutdown(server, 0);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const fatal = (event: string) => (error: unknown) => {
|
|
47
|
+
this.deps.Logger.error({ message: `${event} received`, error, ...this.base });
|
|
48
|
+
this.shutdown(server, 1);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
process.once("SIGTERM", graceful("SIGTERM"));
|
|
52
|
+
process.once("SIGINT", graceful("SIGINT"));
|
|
53
|
+
process.once("unhandledRejection", fatal("UnhandledRejection"));
|
|
54
|
+
process.once("uncaughtException", fatal("UncaughtException"));
|
|
56
55
|
}
|
|
57
56
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import * as v from "valibot";
|
|
2
|
+
|
|
3
|
+
export const HostnameError = {
|
|
4
|
+
Type: "hostname.type",
|
|
5
|
+
Invalid: "hostname.invalid",
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export const Hostname = v.pipe(
|
|
9
|
+
v.string(HostnameError.Type),
|
|
10
|
+
v.domain(HostnameError.Invalid),
|
|
11
|
+
// Stryker disable next-line StringLiteral
|
|
12
|
+
v.brand("Hostname"),
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
export type HostnameType = v.InferOutput<typeof Hostname>;
|
|
@@ -44,7 +44,7 @@ export class HttpLoggerMiddleware {
|
|
|
44
44
|
) {}
|
|
45
45
|
|
|
46
46
|
shouldSkip(context: HasRequestPath & HasRequestHeader): boolean {
|
|
47
|
-
if (context.request.header("accept")
|
|
47
|
+
if (context.request.header("accept")?.toLowerCase().startsWith("text/event-stream")) return true;
|
|
48
48
|
|
|
49
49
|
return (
|
|
50
50
|
this.config?.skip?.some((rule) => {
|
|
@@ -3,8 +3,13 @@ import type { FileRenamerPort } from "./file-renamer.port";
|
|
|
3
3
|
import type { FileWriterPort } from "./file-writer.port";
|
|
4
4
|
import type { ImageSupportedType } from "./image.types";
|
|
5
5
|
import type { ImageBlurPort, ImageBlurStrategy } from "./image-blur.port";
|
|
6
|
+
import type { NonceProviderPort } from "./nonce-provider.port";
|
|
6
7
|
|
|
7
|
-
type Dependencies = {
|
|
8
|
+
type Dependencies = {
|
|
9
|
+
FileRenamer: FileRenamerPort;
|
|
10
|
+
FileWriter: FileWriterPort;
|
|
11
|
+
NonceProvider: NonceProviderPort;
|
|
12
|
+
};
|
|
8
13
|
|
|
9
14
|
export class ImageBlurAdapter implements ImageBlurPort {
|
|
10
15
|
constructor(private readonly deps: Dependencies) {}
|
|
@@ -13,7 +18,9 @@ export class ImageBlurAdapter implements ImageBlurPort {
|
|
|
13
18
|
const final = recipe.strategy === "output_path" ? recipe.output : recipe.input;
|
|
14
19
|
|
|
15
20
|
const filename = final.getFilename();
|
|
16
|
-
const temporary = final.withFilename(
|
|
21
|
+
const temporary = final.withFilename(
|
|
22
|
+
filename.withSuffix(`-blurred-${this.deps.NonceProvider.generate()}`),
|
|
23
|
+
);
|
|
17
24
|
|
|
18
25
|
const extension = final.getFilename().getExtension();
|
|
19
26
|
const format = (extension === "jpg" ? "jpeg" : extension) as ImageSupportedType;
|
|
@@ -3,8 +3,13 @@ import type { FileRenamerPort } from "./file-renamer.port";
|
|
|
3
3
|
import type { FileWriterPort } from "./file-writer.port";
|
|
4
4
|
import type { ImageSupportedType } from "./image.types";
|
|
5
5
|
import type { ImageCompressorPort, ImageCompressorStrategy } from "./image-compressor.port";
|
|
6
|
+
import type { NonceProviderPort } from "./nonce-provider.port";
|
|
6
7
|
|
|
7
|
-
type Dependencies = {
|
|
8
|
+
type Dependencies = {
|
|
9
|
+
FileRenamer: FileRenamerPort;
|
|
10
|
+
FileWriter: FileWriterPort;
|
|
11
|
+
NonceProvider: NonceProviderPort;
|
|
12
|
+
};
|
|
8
13
|
|
|
9
14
|
export class ImageCompressorAdapter implements ImageCompressorPort {
|
|
10
15
|
private static readonly DEFAULT_QUALITY = 85;
|
|
@@ -16,7 +21,9 @@ export class ImageCompressorAdapter implements ImageCompressorPort {
|
|
|
16
21
|
|
|
17
22
|
const final = recipe.strategy === "output_path" ? recipe.output : recipe.input;
|
|
18
23
|
const filename = final.getFilename();
|
|
19
|
-
const temporary = final.withFilename(
|
|
24
|
+
const temporary = final.withFilename(
|
|
25
|
+
filename.withSuffix(`-compressed-${this.deps.NonceProvider.generate()}`),
|
|
26
|
+
);
|
|
20
27
|
|
|
21
28
|
const extension = final.getFilename().getExtension();
|
|
22
29
|
const format = (extension === "jpg" ? "jpeg" : extension) as ImageSupportedType;
|
|
@@ -4,15 +4,22 @@ import type { FileRenamerPort } from "./file-renamer.port";
|
|
|
4
4
|
import type { FileWriterPort } from "./file-writer.port";
|
|
5
5
|
import type { ImageSupportedType } from "./image.types";
|
|
6
6
|
import type { ImageExifClearPort, ImageExifClearStrategy } from "./image-exif-clear.port";
|
|
7
|
+
import type { NonceProviderPort } from "./nonce-provider.port";
|
|
7
8
|
|
|
8
|
-
type Dependencies = {
|
|
9
|
+
type Dependencies = {
|
|
10
|
+
FileRenamer: FileRenamerPort;
|
|
11
|
+
FileWriter: FileWriterPort;
|
|
12
|
+
NonceProvider: NonceProviderPort;
|
|
13
|
+
};
|
|
9
14
|
|
|
10
15
|
export class ImageExifClearAdapter implements ImageExifClearPort {
|
|
11
16
|
constructor(private readonly deps: Dependencies) {}
|
|
12
17
|
|
|
13
18
|
async clear(recipe: ImageExifClearStrategy): Promise<tools.FilePathRelative | tools.FilePathAbsolute> {
|
|
14
19
|
const final = recipe.strategy === "output_path" ? recipe.output : recipe.input;
|
|
15
|
-
const temporary = final.withFilename(
|
|
20
|
+
const temporary = final.withFilename(
|
|
21
|
+
final.getFilename().withSuffix(`-exif-cleared-${this.deps.NonceProvider.generate()}`),
|
|
22
|
+
);
|
|
16
23
|
|
|
17
24
|
const extension = final.getFilename().getExtension();
|
|
18
25
|
const format = (extension === "jpg" ? "jpeg" : extension) as ImageSupportedType;
|
|
@@ -4,11 +4,13 @@ import type { FileRenamerPort } from "./file-renamer.port";
|
|
|
4
4
|
import type { FileWriterPort } from "./file-writer.port";
|
|
5
5
|
import type { ImageSupportedType } from "./image.types";
|
|
6
6
|
import type { ImageFormatterPort, ImageFormatterStrategy } from "./image-formatter.port";
|
|
7
|
+
import type { NonceProviderPort } from "./nonce-provider.port";
|
|
7
8
|
|
|
8
9
|
type Dependencies = {
|
|
9
10
|
FileCleaner: FileCleanerPort;
|
|
10
11
|
FileRenamer: FileRenamerPort;
|
|
11
12
|
FileWriter: FileWriterPort;
|
|
13
|
+
NonceProvider: NonceProviderPort;
|
|
12
14
|
};
|
|
13
15
|
|
|
14
16
|
export class ImageFormatterAdapter implements ImageFormatterPort {
|
|
@@ -20,7 +22,9 @@ export class ImageFormatterAdapter implements ImageFormatterPort {
|
|
|
20
22
|
? recipe.output
|
|
21
23
|
: recipe.input.withFilename(recipe.input.getFilename().withExtension(recipe.to));
|
|
22
24
|
|
|
23
|
-
const temporary = final.withFilename(
|
|
25
|
+
const temporary = final.withFilename(
|
|
26
|
+
final.getFilename().withSuffix(`-formatted-${this.deps.NonceProvider.generate()}`),
|
|
27
|
+
);
|
|
24
28
|
|
|
25
29
|
const extension = final.getFilename().getExtension();
|
|
26
30
|
const format = (extension === "jpg" ? "jpeg" : extension) as ImageSupportedType;
|
|
@@ -8,6 +8,7 @@ export class ImageGeneratorWebViewAdapter implements ImageGeneratorPort {
|
|
|
8
8
|
async generate(config: ImageGeneratorConfig): Promise<Uint8Array<ArrayBuffer>> {
|
|
9
9
|
await using view = new Bun.WebView(config);
|
|
10
10
|
|
|
11
|
+
// TODO: Potential XSS risk
|
|
11
12
|
await view.navigate(`data:text/html;charset=utf-8,${encodeURIComponent(config.template)}`);
|
|
12
13
|
|
|
13
14
|
const image = await view.screenshot({
|
|
@@ -4,8 +4,13 @@ import type { FileRenamerPort } from "./file-renamer.port";
|
|
|
4
4
|
import type { FileWriterPort } from "./file-writer.port";
|
|
5
5
|
import type { ImageSupportedType } from "./image.types";
|
|
6
6
|
import type { ImageGrayscalePort, ImageGrayscaleStrategy } from "./image-grayscale.port";
|
|
7
|
+
import type { NonceProviderPort } from "./nonce-provider.port";
|
|
7
8
|
|
|
8
|
-
type Dependencies = {
|
|
9
|
+
type Dependencies = {
|
|
10
|
+
FileRenamer: FileRenamerPort;
|
|
11
|
+
FileWriter: FileWriterPort;
|
|
12
|
+
NonceProvider: NonceProviderPort;
|
|
13
|
+
};
|
|
9
14
|
|
|
10
15
|
export class ImageGrayscaleAdapter implements ImageGrayscalePort {
|
|
11
16
|
constructor(private readonly deps: Dependencies) {}
|
|
@@ -14,7 +19,9 @@ export class ImageGrayscaleAdapter implements ImageGrayscalePort {
|
|
|
14
19
|
const final = recipe.strategy === "output_path" ? recipe.output : recipe.input;
|
|
15
20
|
|
|
16
21
|
const filename = final.getFilename();
|
|
17
|
-
const temporary = final.withFilename(
|
|
22
|
+
const temporary = final.withFilename(
|
|
23
|
+
filename.withSuffix(`-grayscale-${this.deps.NonceProvider.generate()}`),
|
|
24
|
+
);
|
|
18
25
|
|
|
19
26
|
const extension = final.getFilename().getExtension();
|
|
20
27
|
const format = (extension === "jpg" ? "jpeg" : extension) as ImageSupportedType;
|
|
@@ -4,11 +4,13 @@ import type { FileRenamerPort } from "./file-renamer.port";
|
|
|
4
4
|
import type { FileWriterPort } from "./file-writer.port";
|
|
5
5
|
import type { ImageSupportedType } from "./image.types";
|
|
6
6
|
import type { ImageProcessorPort, ImageProcessorStrategy } from "./image-processor.port";
|
|
7
|
+
import type { NonceProviderPort } from "./nonce-provider.port";
|
|
7
8
|
|
|
8
9
|
type Dependencies = {
|
|
9
10
|
FileCleaner: FileCleanerPort;
|
|
10
11
|
FileRenamer: FileRenamerPort;
|
|
11
12
|
FileWriter: FileWriterPort;
|
|
13
|
+
NonceProvider: NonceProviderPort;
|
|
12
14
|
};
|
|
13
15
|
|
|
14
16
|
export class ImageProcessorAdapter implements ImageProcessorPort {
|
|
@@ -22,7 +24,9 @@ export class ImageProcessorAdapter implements ImageProcessorPort {
|
|
|
22
24
|
? recipe.output
|
|
23
25
|
: recipe.input.withFilename(recipe.input.getFilename().withExtension(recipe.to));
|
|
24
26
|
|
|
25
|
-
const temporary = final.withFilename(
|
|
27
|
+
const temporary = final.withFilename(
|
|
28
|
+
final.getFilename().withSuffix(`-processed-${this.deps.NonceProvider.generate()}`),
|
|
29
|
+
);
|
|
26
30
|
const extension = final.getFilename().getExtension();
|
|
27
31
|
const format = (extension === "jpg" ? "jpeg" : extension) as ImageSupportedType;
|
|
28
32
|
const quality = recipe.quality ?? ImageProcessorAdapter.DEFAULT_QUALITY;
|
|
@@ -4,8 +4,13 @@ import type { FileRenamerPort } from "./file-renamer.port";
|
|
|
4
4
|
import type { FileWriterPort } from "./file-writer.port";
|
|
5
5
|
import type { ImageSupportedType } from "./image.types";
|
|
6
6
|
import type { ImageResizerPort, ImageResizerStrategy } from "./image-resizer.port";
|
|
7
|
+
import type { NonceProviderPort } from "./nonce-provider.port";
|
|
7
8
|
|
|
8
|
-
type Dependencies = {
|
|
9
|
+
type Dependencies = {
|
|
10
|
+
FileWriter: FileWriterPort;
|
|
11
|
+
FileRenamer: FileRenamerPort;
|
|
12
|
+
NonceProvider: NonceProviderPort;
|
|
13
|
+
};
|
|
9
14
|
|
|
10
15
|
export class ImageResizerAdapter implements ImageResizerPort {
|
|
11
16
|
constructor(private readonly deps: Dependencies) {}
|
|
@@ -13,7 +18,9 @@ export class ImageResizerAdapter implements ImageResizerPort {
|
|
|
13
18
|
async resize(recipe: ImageResizerStrategy): Promise<tools.FilePathRelative | tools.FilePathAbsolute> {
|
|
14
19
|
const final = recipe.strategy === "output_path" ? recipe.output : recipe.input;
|
|
15
20
|
const filename = final.getFilename();
|
|
16
|
-
const temporary = final.withFilename(
|
|
21
|
+
const temporary = final.withFilename(
|
|
22
|
+
filename.withSuffix(`-resized-${this.deps.NonceProvider.generate()}`),
|
|
23
|
+
);
|
|
17
24
|
|
|
18
25
|
const extension = final.getFilename().getExtension();
|
|
19
26
|
const format = (extension === "jpg" ? "jpeg" : extension) as ImageSupportedType;
|
package/src/image.types.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export type ImageSupportedType =
|
|
1
|
+
export type ImageSupportedType = "jpeg" | "png" | "webp";
|
package/src/index.ts
CHANGED
|
@@ -10,6 +10,7 @@ export * from "./ab-assignment-query.strategy";
|
|
|
10
10
|
export * from "./ab-hono.middleware";
|
|
11
11
|
export * from "./ab-hono-noop.middleware";
|
|
12
12
|
export * from "./ab-variant.vo";
|
|
13
|
+
export * from "./ab-variant-name.vo";
|
|
13
14
|
export * from "./ab-variant-selector.service";
|
|
14
15
|
export * from "./ab-variant-weight.vo";
|
|
15
16
|
export * from "./ab-variants.vo";
|
|
@@ -201,6 +202,7 @@ export * from "./hcaptcha-secret-key.vo";
|
|
|
201
202
|
export * from "./hcaptcha-site-key.vo";
|
|
202
203
|
export * from "./healthcheck.handler";
|
|
203
204
|
export * from "./healthcheck-hono.handler";
|
|
205
|
+
export * from "./hostname.vo";
|
|
204
206
|
export * from "./http-logger.middleware";
|
|
205
207
|
export * from "./http-logger-hono.middleware";
|
|
206
208
|
export * from "./id-provider.port";
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { StandardSchemaV1 } from "@standard-schema/spec";
|
|
2
2
|
import type { GenericJob } from "./job.types";
|
|
3
|
-
import {
|
|
3
|
+
import type { JobHandler, JobRegistryPort } from "./job-registry.port";
|
|
4
4
|
import type { JobRetryPolicyStrategy } from "./job-retry-policy.strategy";
|
|
5
|
+
import { StandardSchemaValidator } from "./standard-schema-validator.service";
|
|
5
6
|
|
|
6
7
|
export type JobRegistryEntry<Specific extends GenericJob> = {
|
|
7
8
|
schema: StandardSchemaV1<unknown, Specific>;
|
|
@@ -38,11 +39,7 @@ export class JobRegistryAdapter<Job extends GenericJob> implements JobRegistryPo
|
|
|
38
39
|
const entry = this.map.get(name);
|
|
39
40
|
if (!entry) throw new Error(JobRegistryAdapterError.UnknownJob);
|
|
40
41
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
if (result instanceof Promise) throw new Error(JobRegistryError.NoAsyncSchema);
|
|
44
|
-
if (result.issues) throw new Error(result.issues[0]?.message);
|
|
45
|
-
return result.value;
|
|
42
|
+
return StandardSchemaValidator.validate(entry.schema, raw);
|
|
46
43
|
}
|
|
47
44
|
|
|
48
45
|
getRetryPolicy(name: GenericJob["name"]): JobRetryPolicyStrategy {
|
package/src/job-registry.port.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import type { GenericJob } from "./job.types";
|
|
2
2
|
import type { JobRetryPolicyStrategy } from "./job-retry-policy.strategy";
|
|
3
3
|
|
|
4
|
-
export const JobRegistryError = { NoAsyncSchema: "job.registry.no.async.schema" };
|
|
5
|
-
|
|
6
4
|
export type JobHandler<Job extends GenericJob> = (job: Job) => Promise<void>;
|
|
7
5
|
|
|
8
6
|
export interface JobRegistryPort<Job extends GenericJob> {
|
|
@@ -15,7 +15,7 @@ export class PrerequisiteVerifierBinaryAdapter implements PrerequisiteVerifierPo
|
|
|
15
15
|
const result = Bun.which(this.config.binary);
|
|
16
16
|
|
|
17
17
|
if (result) return PrerequisiteVerification.success;
|
|
18
|
-
return PrerequisiteVerification.failure();
|
|
18
|
+
return PrerequisiteVerification.failure("Binary not present");
|
|
19
19
|
} catch (error) {
|
|
20
20
|
return PrerequisiteVerification.failure(error);
|
|
21
21
|
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import dns from "node:dns/promises";
|
|
2
|
+
import type { HostnameType } from "./hostname.vo";
|
|
2
3
|
import {
|
|
3
4
|
PrerequisiteVerification,
|
|
4
5
|
type PrerequisiteVerificationResult,
|
|
5
6
|
type PrerequisiteVerifierPort,
|
|
6
7
|
} from "./prerequisite-verifier.port";
|
|
7
8
|
|
|
8
|
-
type Config = { hostname:
|
|
9
|
+
type Config = { hostname: HostnameType };
|
|
9
10
|
|
|
10
11
|
export class PrerequisiteVerifierDnsAdapter implements PrerequisiteVerifierPort {
|
|
11
12
|
constructor(private readonly config: Config) {}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type * as tools from "@bgord/tools";
|
|
2
2
|
import type { CertificateInspectorPort } from "./certificate-inspector.port";
|
|
3
|
+
import type { HostnameType } from "./hostname.vo";
|
|
3
4
|
import {
|
|
4
5
|
PrerequisiteVerification,
|
|
5
6
|
type PrerequisiteVerificationResult,
|
|
@@ -8,7 +9,7 @@ import {
|
|
|
8
9
|
|
|
9
10
|
type Dependencies = { CertificateInspector: CertificateInspectorPort };
|
|
10
11
|
|
|
11
|
-
type Config = { hostname:
|
|
12
|
+
type Config = { hostname: HostnameType; minimum: tools.Duration };
|
|
12
13
|
|
|
13
14
|
export class PrerequisiteVerifierSSLCertificateExpiryAdapter implements PrerequisiteVerifierPort {
|
|
14
15
|
constructor(
|
|
@@ -41,14 +41,14 @@ export class PrerequisiteVerifierTranslationsAdapter<T extends tools.LanguageTyp
|
|
|
41
41
|
|
|
42
42
|
for (const language in dictionary) {
|
|
43
43
|
// Stryker disable all
|
|
44
|
-
const
|
|
44
|
+
const translations = dictionary[language] ?? [];
|
|
45
45
|
// Stryker restore all
|
|
46
46
|
|
|
47
|
-
for (const
|
|
47
|
+
for (const key of translations) {
|
|
48
48
|
for (const supportedLanguage of languages) {
|
|
49
|
-
const
|
|
49
|
+
const exists = new Set(dictionary[supportedLanguage]).has(key);
|
|
50
50
|
|
|
51
|
-
if (!
|
|
51
|
+
if (!exists) problems.push({ key, existsIn: language, missingIn: supportedLanguage });
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
}
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import type * as tools from "@bgord/tools";
|
|
2
2
|
import type { FileReaderJsonPort } from "./file-reader-json.port";
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
type ReactiveConfigPort,
|
|
6
|
-
type ReactiveConfigSchema,
|
|
7
|
-
} from "./reactive-config.port";
|
|
3
|
+
import type { ReactiveConfigPort, ReactiveConfigSchema } from "./reactive-config.port";
|
|
4
|
+
import { StandardSchemaValidator } from "./standard-schema-validator.service";
|
|
8
5
|
|
|
9
6
|
type Dependencies = { FileReaderJson: FileReaderJsonPort };
|
|
10
7
|
|
|
@@ -18,9 +15,6 @@ export class ReactiveConfigFileJsonAdapter<T extends object> implements Reactive
|
|
|
18
15
|
async get(): Promise<Readonly<T>> {
|
|
19
16
|
const raw = await this.deps.FileReaderJson.read(this.path);
|
|
20
17
|
|
|
21
|
-
|
|
22
|
-
if (result instanceof Promise) throw new Error(ReactiveConfigError.NoAsyncSchema);
|
|
23
|
-
if (result.issues) throw new Error(result.issues[0]?.message);
|
|
24
|
-
return Object.freeze(result.value);
|
|
18
|
+
return Object.freeze(StandardSchemaValidator.validate(this.schema, raw));
|
|
25
19
|
}
|
|
26
20
|
}
|