@bgord/bun 1.15.3 → 1.15.4
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/cache-repository-redis.adapter.d.ts +13 -0
- package/dist/cache-repository-redis.adapter.d.ts.map +1 -0
- package/dist/cache-repository-redis.adapter.js +27 -0
- package/dist/cache-repository-redis.adapter.js.map +1 -0
- package/dist/healthcheck-hono.handler.d.ts +3 -2
- package/dist/healthcheck-hono.handler.d.ts.map +1 -1
- package/dist/healthcheck-hono.handler.js +1 -2
- package/dist/healthcheck-hono.handler.js.map +1 -1
- package/dist/healthcheck.handler.d.ts +12 -1
- package/dist/healthcheck.handler.d.ts.map +1 -1
- package/dist/healthcheck.handler.js +20 -2
- package/dist/healthcheck.handler.js.map +1 -1
- package/dist/image-grayscale-noop.adapter.d.ts +6 -0
- package/dist/image-grayscale-noop.adapter.d.ts.map +1 -0
- package/dist/image-grayscale-noop.adapter.js +6 -0
- package/dist/image-grayscale-noop.adapter.js.map +1 -0
- package/dist/image-grayscale-sharp.adapter.d.ts +19 -0
- package/dist/image-grayscale-sharp.adapter.d.ts.map +1 -0
- package/dist/image-grayscale-sharp.adapter.js +28 -0
- package/dist/image-grayscale-sharp.adapter.js.map +1 -0
- package/dist/image-grayscale.port.d.ts +15 -0
- package/dist/image-grayscale.port.d.ts.map +1 -0
- package/dist/image-grayscale.port.js +2 -0
- package/dist/image-grayscale.port.js.map +1 -0
- package/dist/index.d.ts +17 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -3
- package/dist/index.js.map +1 -1
- package/dist/liveness-hono.handler.d.ts +8 -0
- package/dist/liveness-hono.handler.d.ts.map +1 -0
- package/dist/liveness-hono.handler.js +10 -0
- package/dist/liveness-hono.handler.js.map +1 -0
- package/dist/liveness.handler.d.ts +6 -0
- package/dist/liveness.handler.d.ts.map +1 -0
- package/dist/liveness.handler.js +6 -0
- package/dist/liveness.handler.js.map +1 -0
- package/dist/randomness-crypto.strategy.d.ts +5 -0
- package/dist/randomness-crypto.strategy.d.ts.map +1 -0
- package/dist/randomness-crypto.strategy.js +8 -0
- package/dist/randomness-crypto.strategy.js.map +1 -0
- package/dist/randomness-math.strategy.d.ts +5 -0
- package/dist/randomness-math.strategy.d.ts.map +1 -0
- package/dist/randomness-math.strategy.js +6 -0
- package/dist/randomness-math.strategy.js.map +1 -0
- package/dist/randomness-noop.strategy.d.ts +7 -0
- package/dist/randomness-noop.strategy.d.ts.map +1 -0
- package/dist/randomness-noop.strategy.js +10 -0
- package/dist/randomness-noop.strategy.js.map +1 -0
- package/dist/randomness.strategy.d.ts +4 -0
- package/dist/randomness.strategy.d.ts.map +1 -0
- package/dist/randomness.strategy.js +2 -0
- package/dist/randomness.strategy.js.map +1 -0
- package/dist/readiness-hono.handler.d.ts +26 -0
- package/dist/readiness-hono.handler.d.ts.map +1 -0
- package/dist/readiness-hono.handler.js +17 -0
- package/dist/readiness-hono.handler.js.map +1 -0
- package/dist/readiness.handler.d.ts +19 -0
- package/dist/readiness.handler.d.ts.map +1 -0
- package/dist/readiness.handler.js +19 -0
- package/dist/readiness.handler.js.map +1 -0
- package/dist/retry-backoff-jitter.strategy.d.ts +10 -0
- package/dist/retry-backoff-jitter.strategy.d.ts.map +1 -0
- package/dist/retry-backoff-jitter.strategy.js +14 -0
- package/dist/retry-backoff-jitter.strategy.js.map +1 -0
- package/dist/shield-ip-blacklist-hono.strategy.d.ts +11 -0
- package/dist/shield-ip-blacklist-hono.strategy.d.ts.map +1 -0
- package/dist/shield-ip-blacklist-hono.strategy.js +21 -0
- package/dist/shield-ip-blacklist-hono.strategy.js.map +1 -0
- package/dist/shield-ip-blacklist.strategy.d.ts +14 -0
- package/dist/shield-ip-blacklist.strategy.d.ts.map +1 -0
- package/dist/shield-ip-blacklist.strategy.js +16 -0
- package/dist/shield-ip-blacklist.strategy.js.map +1 -0
- package/dist/shield-ip-whitelist-hono.strategy.d.ts +11 -0
- package/dist/shield-ip-whitelist-hono.strategy.d.ts.map +1 -0
- package/dist/shield-ip-whitelist-hono.strategy.js +21 -0
- package/dist/shield-ip-whitelist-hono.strategy.js.map +1 -0
- package/dist/shield-ip-whitelist.strategy.d.ts +14 -0
- package/dist/shield-ip-whitelist.strategy.d.ts.map +1 -0
- package/dist/shield-ip-whitelist.strategy.js +16 -0
- package/dist/shield-ip-whitelist.strategy.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +9 -9
- package/readme.md +17 -3
- package/src/cache-repository-redis.adapter.ts +31 -0
- package/src/healthcheck-hono.handler.ts +1 -2
- package/src/healthcheck.handler.ts +28 -3
- package/src/image-grayscale-noop.adapter.ts +8 -0
- package/src/image-grayscale-sharp.adapter.ts +45 -0
- package/src/image-grayscale.port.ts +16 -0
- package/src/index.ts +17 -3
- package/src/liveness-hono.handler.ts +13 -0
- package/src/liveness.handler.ts +5 -0
- package/src/randomness-crypto.strategy.ts +9 -0
- package/src/randomness-math.strategy.ts +7 -0
- package/src/randomness-noop.strategy.ts +9 -0
- package/src/randomness.strategy.ts +3 -0
- package/src/readiness-hono.handler.ts +22 -0
- package/src/readiness.handler.ts +33 -0
- package/src/retry-backoff-jitter.strategy.ts +15 -0
- package/src/shield-ip-blacklist-hono.strategy.ts +30 -0
- package/src/shield-ip-blacklist.strategy.ts +18 -0
- package/src/shield-ip-whitelist-hono.strategy.ts +30 -0
- package/src/shield-ip-whitelist.strategy.ts +18 -0
- package/dist/ping-hono.handler.d.ts +0 -6
- package/dist/ping-hono.handler.d.ts.map +0 -1
- package/dist/ping-hono.handler.js +0 -13
- package/dist/ping-hono.handler.js.map +0 -1
- package/dist/ping.handler.d.ts +0 -4
- package/dist/ping.handler.d.ts.map +0 -1
- package/dist/ping.handler.js +0 -6
- package/dist/ping.handler.js.map +0 -1
- package/dist/retry-backoff-fibonacci.strategy.d.ts +0 -9
- package/dist/retry-backoff-fibonacci.strategy.d.ts.map +0 -1
- package/dist/retry-backoff-fibonacci.strategy.js +0 -19
- package/dist/retry-backoff-fibonacci.strategy.js.map +0 -1
- package/src/ping-hono.handler.ts +0 -17
- package/src/ping.handler.ts +0 -5
- package/src/retry-backoff-fibonacci.strategy.ts +0 -17
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bgord/bun",
|
|
3
|
-
"version": "1.15.
|
|
3
|
+
"version": "1.15.4",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "Bartosz Gordon",
|
|
@@ -20,21 +20,21 @@
|
|
|
20
20
|
"preinstall": "bunx only-allow bun"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
|
-
"@biomejs/biome": "2.4.
|
|
23
|
+
"@biomejs/biome": "2.4.8",
|
|
24
24
|
"@commitlint/cli": "20.5.0",
|
|
25
25
|
"@commitlint/config-conventional": "20.5.0",
|
|
26
26
|
"@standard-schema/spec": "1.1.0",
|
|
27
27
|
"@stryker-mutator/core": "9.6.0",
|
|
28
|
-
"@types/bun": "1.3.
|
|
28
|
+
"@types/bun": "1.3.11",
|
|
29
29
|
"@types/nodemailer": "7.0.11",
|
|
30
30
|
"@types/yazl": "3.3.0",
|
|
31
31
|
"better-auth": "1.5.5",
|
|
32
32
|
"cspell": "9.7.0",
|
|
33
|
-
"csv": "6.5.
|
|
34
|
-
"knip": "
|
|
33
|
+
"csv": "6.5.1",
|
|
34
|
+
"knip": "6.0.0",
|
|
35
35
|
"lefthook": "2.1.4",
|
|
36
36
|
"lockfile-lint": "5.0.0",
|
|
37
|
-
"nodemailer": "8.0.
|
|
37
|
+
"nodemailer": "8.0.3",
|
|
38
38
|
"only-allow": "1.2.2",
|
|
39
39
|
"resend": "6.9.4",
|
|
40
40
|
"sharp": "0.34.5",
|
|
@@ -43,15 +43,15 @@
|
|
|
43
43
|
"yazl": "3.3.1"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@bgord/tools": "1.4.
|
|
46
|
+
"@bgord/tools": "1.4.3",
|
|
47
47
|
"emittery": "2.0.0",
|
|
48
48
|
"hono": "4.12.8",
|
|
49
49
|
"node-cache": "5.1.2"
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|
|
52
52
|
"better-auth": "1.5.5",
|
|
53
|
-
"csv": "6.5.
|
|
54
|
-
"nodemailer": "8.0.
|
|
53
|
+
"csv": "6.5.1",
|
|
54
|
+
"nodemailer": "8.0.3",
|
|
55
55
|
"resend": "6.9.4",
|
|
56
56
|
"sharp": "0.34.5",
|
|
57
57
|
"yazl": "3.3.1"
|
package/readme.md
CHANGED
|
@@ -57,6 +57,7 @@ src/
|
|
|
57
57
|
├── cache-file.service.ts
|
|
58
58
|
├── cache-repository-node-cache.adapter.ts
|
|
59
59
|
├── cache-repository-noop.adapter.ts
|
|
60
|
+
├── cache-repository-redis.adapter.ts
|
|
60
61
|
├── cache-repository.port.ts
|
|
61
62
|
├── cache-resolver-simple.strategy.ts
|
|
62
63
|
├── cache-resolver.strategy.ts
|
|
@@ -209,6 +210,9 @@ src/
|
|
|
209
210
|
├── image-formatter-noop.adapter.ts
|
|
210
211
|
├── image-formatter-sharp.adapter.ts
|
|
211
212
|
├── image-formatter.port.ts
|
|
213
|
+
├── image-grayscale-noop.adapter.ts
|
|
214
|
+
├── image-grayscale-sharp.adapter.ts
|
|
215
|
+
├── image-grayscale.port.ts
|
|
212
216
|
├── image-info-noop.adapter.ts
|
|
213
217
|
├── image-info-sharp.adapter.ts
|
|
214
218
|
├── image-info.port.ts
|
|
@@ -237,6 +241,8 @@ src/
|
|
|
237
241
|
├── language-detector.middleware.ts
|
|
238
242
|
├── language-detector.strategy.ts
|
|
239
243
|
├── languages.vo.ts
|
|
244
|
+
├── liveness-hono.handler.ts
|
|
245
|
+
├── liveness.handler.ts
|
|
240
246
|
├── logger-collecting.adapter.ts
|
|
241
247
|
├── logger-noop.adapter.ts
|
|
242
248
|
├── logger-stats-provider-noop.adapter.ts
|
|
@@ -319,8 +325,6 @@ src/
|
|
|
319
325
|
├── pdf-generator-noop.adapter.ts
|
|
320
326
|
├── pdf-generator-with-logger.adapter.ts
|
|
321
327
|
├── pdf-generator.port.ts
|
|
322
|
-
├── ping-hono.handler.ts
|
|
323
|
-
├── ping.handler.ts
|
|
324
328
|
├── port.vo.ts
|
|
325
329
|
├── prerequisite-runner-startup.service.ts
|
|
326
330
|
├── prerequisite-verifier-binary.adapter.ts
|
|
@@ -353,6 +357,12 @@ src/
|
|
|
353
357
|
├── prerequisite-verifier.decorator.ts
|
|
354
358
|
├── prerequisite-verifier.port.ts
|
|
355
359
|
├── prerequisite.vo.ts
|
|
360
|
+
├── randomness-crypto.strategy.ts
|
|
361
|
+
├── randomness-math.strategy.ts
|
|
362
|
+
├── randomness-noop.strategy.ts
|
|
363
|
+
├── randomness.strategy.ts
|
|
364
|
+
├── readiness-hono.handler.ts
|
|
365
|
+
├── readiness.handler.ts
|
|
356
366
|
├── recaptcha-secret-key.vo.ts
|
|
357
367
|
├── recaptcha-site-key.vo.ts
|
|
358
368
|
├── redactor-composite.strategy.ts
|
|
@@ -369,7 +379,7 @@ src/
|
|
|
369
379
|
├── request-context-hono.adapter.ts
|
|
370
380
|
├── request-context.port.ts
|
|
371
381
|
├── retry-backoff-exponential.strategy.ts
|
|
372
|
-
├── retry-backoff-
|
|
382
|
+
├── retry-backoff-jitter.strategy.ts
|
|
373
383
|
├── retry-backoff-linear.strategy.ts
|
|
374
384
|
├── retry-backoff-noop.strategy.ts
|
|
375
385
|
├── retry-backoff.strategy.ts
|
|
@@ -413,6 +423,10 @@ src/
|
|
|
413
423
|
├── shield-hcaptcha-hono-local.strategy.ts
|
|
414
424
|
├── shield-hcaptcha-hono.strategy.ts
|
|
415
425
|
├── shield-hcaptcha.strategy.ts
|
|
426
|
+
├── shield-ip-blacklist-hono.strategy.ts
|
|
427
|
+
├── shield-ip-blacklist.strategy.ts
|
|
428
|
+
├── shield-ip-whitelist-hono.strategy.ts
|
|
429
|
+
├── shield-ip-whitelist.strategy.ts
|
|
416
430
|
├── shield-maintenance-hono.strategy.ts
|
|
417
431
|
├── shield-maintenance.strategy.ts
|
|
418
432
|
├── shield-rate-limit-hono.strategy.ts
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { RedisClient } from "bun";
|
|
2
|
+
import type { CacheRepositoryPort, CacheRepositoryTtlType } from "./cache-repository.port";
|
|
3
|
+
import type { Hash } from "./hash.vo";
|
|
4
|
+
|
|
5
|
+
export class CacheRepositoryRedisAdapter implements CacheRepositoryPort {
|
|
6
|
+
constructor(
|
|
7
|
+
private readonly client: RedisClient,
|
|
8
|
+
private readonly config: CacheRepositoryTtlType,
|
|
9
|
+
) {}
|
|
10
|
+
|
|
11
|
+
async get<T>(subject: Hash): Promise<T | null> {
|
|
12
|
+
const value = await this.client.get(subject.get());
|
|
13
|
+
if (value === null) return null;
|
|
14
|
+
return JSON.parse(value) as T;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async set<T>(subject: Hash, value: T): Promise<void> {
|
|
18
|
+
await this.client.set(subject.get(), JSON.stringify(value));
|
|
19
|
+
if (this.config.type === "finite") {
|
|
20
|
+
await this.client.expire(subject.get(), this.config.ttl.seconds);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async delete(subject: Hash): Promise<void> {
|
|
25
|
+
await this.client.del(subject.get());
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async flush(): Promise<void> {
|
|
29
|
+
await this.client.send("FLUSHALL", []);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -23,9 +23,8 @@ export class HealthcheckHonoHandler implements HandlerHonoPort {
|
|
|
23
23
|
handle() {
|
|
24
24
|
return factory.createHandlers(async (c) => {
|
|
25
25
|
const healthcheck = await this.handler.check();
|
|
26
|
-
const code = healthcheck.ok ? 200 : 424;
|
|
27
26
|
|
|
28
|
-
return c.json(healthcheck, code);
|
|
27
|
+
return c.json(healthcheck, healthcheck.code);
|
|
29
28
|
});
|
|
30
29
|
}
|
|
31
30
|
}
|
|
@@ -19,6 +19,12 @@ import type { RedactorStrategy } from "./redactor.strategy";
|
|
|
19
19
|
import { Stopwatch } from "./stopwatch.service";
|
|
20
20
|
import { Uptime, type UptimeResultType } from "./uptime.service";
|
|
21
21
|
|
|
22
|
+
export enum HealthcheckStatusEnum {
|
|
23
|
+
healthy = "healthy",
|
|
24
|
+
degraded = "degraded",
|
|
25
|
+
unhealthy = "unhealthy",
|
|
26
|
+
}
|
|
27
|
+
|
|
22
28
|
type Dependencies = {
|
|
23
29
|
Clock: ClockPort;
|
|
24
30
|
BuildInfoRepository: BuildInfoRepositoryStrategy;
|
|
@@ -33,8 +39,15 @@ export type HealthcheckConfig = {
|
|
|
33
39
|
|
|
34
40
|
const self = new Prerequisite("self", new PrerequisiteVerifierSelfAdapter());
|
|
35
41
|
|
|
42
|
+
export const HealthcheckStatusCode = {
|
|
43
|
+
[HealthcheckStatusEnum.healthy]: 200,
|
|
44
|
+
[HealthcheckStatusEnum.degraded]: 207,
|
|
45
|
+
[HealthcheckStatusEnum.unhealthy]: 424,
|
|
46
|
+
} as const;
|
|
47
|
+
|
|
36
48
|
export type HealthcheckResult = {
|
|
37
|
-
|
|
49
|
+
status: HealthcheckStatusEnum;
|
|
50
|
+
code: (typeof HealthcheckStatusCode)[keyof typeof HealthcheckStatusCode];
|
|
38
51
|
deployment: {
|
|
39
52
|
version: string;
|
|
40
53
|
timestamp: tools.TimestampValueType;
|
|
@@ -99,7 +112,18 @@ export class HealthcheckHandler {
|
|
|
99
112
|
}),
|
|
100
113
|
);
|
|
101
114
|
|
|
102
|
-
const
|
|
115
|
+
const hasFailure = details.some(
|
|
116
|
+
(result) => result.outcome.outcome === PrerequisiteVerificationOutcome.failure,
|
|
117
|
+
);
|
|
118
|
+
const hasUndetermined = details.some(
|
|
119
|
+
(result) => result.outcome.outcome === PrerequisiteVerificationOutcome.undetermined,
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
const status = hasFailure
|
|
123
|
+
? HealthcheckStatusEnum.unhealthy
|
|
124
|
+
: hasUndetermined
|
|
125
|
+
? HealthcheckStatusEnum.degraded
|
|
126
|
+
: HealthcheckStatusEnum.healthy;
|
|
103
127
|
|
|
104
128
|
const build = await this.deps.BuildInfoRepository.extract();
|
|
105
129
|
const uptime = Uptime.get(this.deps.Clock);
|
|
@@ -107,7 +131,8 @@ export class HealthcheckHandler {
|
|
|
107
131
|
const memory = MemoryConsumption.snapshot();
|
|
108
132
|
|
|
109
133
|
return {
|
|
110
|
-
|
|
134
|
+
status,
|
|
135
|
+
code: HealthcheckStatusCode[status],
|
|
111
136
|
details,
|
|
112
137
|
deployment: {
|
|
113
138
|
version: build.version.toString(),
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type * as tools from "@bgord/tools";
|
|
2
|
+
import type { ImageGrayscalePort, ImageGrayscaleStrategy } from "./image-grayscale.port";
|
|
3
|
+
|
|
4
|
+
export class ImageGrayscaleNoopAdapter implements ImageGrayscalePort {
|
|
5
|
+
async grayscale(recipe: ImageGrayscaleStrategy): Promise<tools.FilePathRelative | tools.FilePathAbsolute> {
|
|
6
|
+
return recipe.strategy === "output_path" ? recipe.output : recipe.input;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type * as tools from "@bgord/tools";
|
|
2
|
+
import type sharp from "sharp";
|
|
3
|
+
import { DynamicImport } from "./dynamic-import.service";
|
|
4
|
+
import type { FileRenamerPort } from "./file-renamer.port";
|
|
5
|
+
import type { ImageGrayscalePort, ImageGrayscaleStrategy } from "./image-grayscale.port";
|
|
6
|
+
|
|
7
|
+
export const ImageGrayscaleSharpAdapterError = {
|
|
8
|
+
MissingDependency: "image.grayscale.sharp.adapter.error.missing.dependency",
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
type Dependencies = { FileRenamer: FileRenamerPort };
|
|
12
|
+
type Sharp = typeof sharp;
|
|
13
|
+
|
|
14
|
+
export class ImageGrayscaleSharpAdapter implements ImageGrayscalePort {
|
|
15
|
+
private static readonly importer = DynamicImport.for<{ default: Sharp }>(
|
|
16
|
+
"sharp",
|
|
17
|
+
ImageGrayscaleSharpAdapterError.MissingDependency,
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
private constructor(
|
|
21
|
+
private readonly sharp: Sharp,
|
|
22
|
+
private readonly deps: Dependencies,
|
|
23
|
+
) {}
|
|
24
|
+
|
|
25
|
+
static async build(deps: Dependencies): Promise<ImageGrayscaleSharpAdapter> {
|
|
26
|
+
const library = await ImageGrayscaleSharpAdapter.importer.resolve();
|
|
27
|
+
|
|
28
|
+
return new ImageGrayscaleSharpAdapter(library.default, deps);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async grayscale(recipe: ImageGrayscaleStrategy): Promise<tools.FilePathRelative | tools.FilePathAbsolute> {
|
|
32
|
+
const final = recipe.strategy === "output_path" ? recipe.output : recipe.input;
|
|
33
|
+
|
|
34
|
+
const filename = final.getFilename();
|
|
35
|
+
const temporary = final.withFilename(filename.withSuffix("-grayscale"));
|
|
36
|
+
|
|
37
|
+
const pipeline = this.sharp(recipe.input.get());
|
|
38
|
+
using _sharp_ = { [Symbol.dispose]: () => pipeline.destroy() };
|
|
39
|
+
|
|
40
|
+
await pipeline.rotate().grayscale().toFile(temporary.get());
|
|
41
|
+
await this.deps.FileRenamer.rename(temporary, final);
|
|
42
|
+
|
|
43
|
+
return final;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type * as tools from "@bgord/tools";
|
|
2
|
+
|
|
3
|
+
export type ImageGrayscaleOutputPathStrategy = {
|
|
4
|
+
strategy: "output_path";
|
|
5
|
+
input: tools.FilePathRelative | tools.FilePathAbsolute;
|
|
6
|
+
output: tools.FilePathRelative | tools.FilePathAbsolute;
|
|
7
|
+
};
|
|
8
|
+
export type ImageGrayscaleInPlaceStrategy = {
|
|
9
|
+
strategy: "in_place";
|
|
10
|
+
input: tools.FilePathRelative | tools.FilePathAbsolute;
|
|
11
|
+
};
|
|
12
|
+
export type ImageGrayscaleStrategy = ImageGrayscaleInPlaceStrategy | ImageGrayscaleOutputPathStrategy;
|
|
13
|
+
|
|
14
|
+
export interface ImageGrayscalePort {
|
|
15
|
+
grayscale(recipe: ImageGrayscaleStrategy): Promise<tools.FilePathRelative | tools.FilePathAbsolute>;
|
|
16
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -32,6 +32,7 @@ export * from "./cache-file.service";
|
|
|
32
32
|
export * from "./cache-repository.port";
|
|
33
33
|
export * from "./cache-repository-node-cache.adapter";
|
|
34
34
|
export * from "./cache-repository-noop.adapter";
|
|
35
|
+
export * from "./cache-repository-redis.adapter";
|
|
35
36
|
export * from "./cache-resolver.strategy";
|
|
36
37
|
export * from "./cache-resolver-simple.strategy";
|
|
37
38
|
export * from "./cache-response.middleware";
|
|
@@ -182,6 +183,9 @@ export * from "./image-exif-clear-sharp.adapter";
|
|
|
182
183
|
export * from "./image-formatter.port";
|
|
183
184
|
export * from "./image-formatter-noop.adapter";
|
|
184
185
|
export * from "./image-formatter-sharp.adapter";
|
|
186
|
+
export * from "./image-grayscale.port";
|
|
187
|
+
export * from "./image-grayscale-noop.adapter";
|
|
188
|
+
export * from "./image-grayscale-sharp.adapter";
|
|
185
189
|
export * from "./image-info.port";
|
|
186
190
|
export * from "./image-info-noop.adapter";
|
|
187
191
|
export * from "./image-info-sharp.adapter";
|
|
@@ -208,6 +212,8 @@ export * from "./language-detector-header.strategy";
|
|
|
208
212
|
export * from "./language-detector-hono.middleware";
|
|
209
213
|
export * from "./language-detector-query.strategy";
|
|
210
214
|
export * from "./languages.vo";
|
|
215
|
+
export * from "./liveness.handler";
|
|
216
|
+
export * from "./liveness-hono.handler";
|
|
211
217
|
export * from "./logger.port";
|
|
212
218
|
export * from "./logger-collecting.adapter";
|
|
213
219
|
export * from "./logger-noop.adapter";
|
|
@@ -253,8 +259,6 @@ export * from "./nonce-value.vo";
|
|
|
253
259
|
export * from "./pdf-generator.port";
|
|
254
260
|
export * from "./pdf-generator-noop.adapter";
|
|
255
261
|
export * from "./pdf-generator-with-logger.adapter";
|
|
256
|
-
export * from "./ping.handler";
|
|
257
|
-
export * from "./ping-hono.handler";
|
|
258
262
|
export * from "./port.vo";
|
|
259
263
|
export * from "./prerequisite.vo";
|
|
260
264
|
export * from "./prerequisite-runner-startup.service";
|
|
@@ -282,6 +286,12 @@ export * from "./prerequisite-verifier-sqlite.adapter";
|
|
|
282
286
|
export * from "./prerequisite-verifier-ssl-certificate-expiry.adapter";
|
|
283
287
|
export * from "./prerequisite-verifier-timezone-utc.adapter";
|
|
284
288
|
export * from "./prerequisite-verifier-translations.adapter";
|
|
289
|
+
export * from "./randomness.strategy";
|
|
290
|
+
export * from "./randomness-crypto.strategy";
|
|
291
|
+
export * from "./randomness-math.strategy";
|
|
292
|
+
export * from "./randomness-noop.strategy";
|
|
293
|
+
export * from "./readiness.handler";
|
|
294
|
+
export * from "./readiness-hono.handler";
|
|
285
295
|
export * from "./recaptcha-secret-key.vo";
|
|
286
296
|
export * from "./recaptcha-site-key.vo";
|
|
287
297
|
export * from "./redactor.strategy";
|
|
@@ -300,7 +310,7 @@ export * from "./request-context-hono.adapter";
|
|
|
300
310
|
export * from "./retry.service";
|
|
301
311
|
export * from "./retry-backoff.strategy";
|
|
302
312
|
export * from "./retry-backoff-exponential.strategy";
|
|
303
|
-
export * from "./retry-backoff-
|
|
313
|
+
export * from "./retry-backoff-jitter.strategy";
|
|
304
314
|
export * from "./retry-backoff-linear.strategy";
|
|
305
315
|
export * from "./retry-backoff-noop.strategy";
|
|
306
316
|
export * from "./sealer.port";
|
|
@@ -342,6 +352,10 @@ export * from "./shield-csrf-hono.strategy";
|
|
|
342
352
|
export * from "./shield-hcaptcha.strategy";
|
|
343
353
|
export * from "./shield-hcaptcha-hono.strategy";
|
|
344
354
|
export * from "./shield-hcaptcha-hono-local.strategy";
|
|
355
|
+
export * from "./shield-ip-blacklist.strategy";
|
|
356
|
+
export * from "./shield-ip-blacklist-hono.strategy";
|
|
357
|
+
export * from "./shield-ip-whitelist.strategy";
|
|
358
|
+
export * from "./shield-ip-whitelist-hono.strategy";
|
|
345
359
|
export * from "./shield-maintenance.strategy";
|
|
346
360
|
export * from "./shield-maintenance-hono.strategy";
|
|
347
361
|
export * from "./shield-rate-limit.strategy";
|
|
@@ -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,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,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
|
+
}
|
|
@@ -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"}
|
package/dist/ping.handler.d.ts
DELETED
|
@@ -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"}
|
package/dist/ping.handler.js
DELETED
package/dist/ping.handler.js.map
DELETED
|
@@ -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
|