@bgord/bun 1.5.8 → 1.5.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/dist/cache-repository-node-cache.adapter.d.ts +15 -0
  2. package/dist/cache-repository-node-cache.adapter.d.ts.map +1 -0
  3. package/dist/cache-repository-node-cache.adapter.js +31 -0
  4. package/dist/cache-repository-node-cache.adapter.js.map +1 -0
  5. package/dist/cache-repository-noop.adapter.d.ts +14 -0
  6. package/dist/cache-repository-noop.adapter.d.ts.map +1 -0
  7. package/dist/cache-repository-noop.adapter.js +16 -0
  8. package/dist/cache-repository-noop.adapter.js.map +1 -0
  9. package/dist/cache-repository.port.d.ts +10 -0
  10. package/dist/cache-repository.port.d.ts.map +1 -0
  11. package/dist/cache-repository.port.js +2 -0
  12. package/dist/cache-repository.port.js.map +1 -0
  13. package/dist/cache-resolver-simple.adapter.d.ts +18 -0
  14. package/dist/cache-resolver-simple.adapter.d.ts.map +1 -0
  15. package/dist/cache-resolver-simple.adapter.js +26 -0
  16. package/dist/cache-resolver-simple.adapter.js.map +1 -0
  17. package/dist/cache-resolver.port.d.ts +16 -0
  18. package/dist/cache-resolver.port.d.ts.map +1 -0
  19. package/dist/cache-resolver.port.js +6 -0
  20. package/dist/cache-resolver.port.js.map +1 -0
  21. package/dist/cache-response.middleware.d.ts +16 -4
  22. package/dist/cache-response.middleware.d.ts.map +1 -1
  23. package/dist/cache-response.middleware.js +21 -12
  24. package/dist/cache-response.middleware.js.map +1 -1
  25. package/dist/environment-loader-process-safe.adapter.d.ts +13 -6
  26. package/dist/environment-loader-process-safe.adapter.d.ts.map +1 -1
  27. package/dist/environment-loader-process-safe.adapter.js +7 -9
  28. package/dist/environment-loader-process-safe.adapter.js.map +1 -1
  29. package/dist/http-logger.middleware.js +2 -2
  30. package/dist/http-logger.middleware.js.map +1 -1
  31. package/dist/index.d.ts +5 -3
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +5 -3
  34. package/dist/index.js.map +1 -1
  35. package/dist/job-handler.service.js +1 -1
  36. package/dist/job-handler.service.js.map +1 -1
  37. package/dist/shield-rate-limit.adapter.d.ts +4 -4
  38. package/dist/shield-rate-limit.adapter.d.ts.map +1 -1
  39. package/dist/shield-rate-limit.adapter.js +5 -10
  40. package/dist/shield-rate-limit.adapter.js.map +1 -1
  41. package/dist/tsconfig.tsbuildinfo +1 -1
  42. package/package.json +2 -2
  43. package/readme.md +5 -3
  44. package/src/cache-repository-node-cache.adapter.ts +37 -0
  45. package/src/cache-repository-noop.adapter.ts +20 -0
  46. package/src/cache-repository.port.ts +11 -0
  47. package/src/cache-resolver-simple.adapter.ts +36 -0
  48. package/src/cache-resolver.port.ts +20 -0
  49. package/src/cache-response.middleware.ts +37 -11
  50. package/src/environment-loader-process-safe.adapter.ts +10 -10
  51. package/src/http-logger.middleware.ts +2 -2
  52. package/src/index.ts +5 -3
  53. package/src/job-handler.service.ts +1 -1
  54. package/src/shield-rate-limit.adapter.ts +11 -15
  55. package/dist/cache-resolver.service.d.ts +0 -47
  56. package/dist/cache-resolver.service.d.ts.map +0 -1
  57. package/dist/cache-resolver.service.js +0 -37
  58. package/dist/cache-resolver.service.js.map +0 -1
  59. package/dist/rate-limit-store-node-cache.adapter.d.ts +0 -11
  60. package/dist/rate-limit-store-node-cache.adapter.d.ts.map +0 -1
  61. package/dist/rate-limit-store-node-cache.adapter.js +0 -24
  62. package/dist/rate-limit-store-node-cache.adapter.js.map +0 -1
  63. package/dist/rate-limit-store.port.d.ts +0 -8
  64. package/dist/rate-limit-store.port.d.ts.map +0 -1
  65. package/dist/rate-limit-store.port.js +0 -2
  66. package/dist/rate-limit-store.port.js.map +0 -1
  67. package/src/cache-resolver.service.ts +0 -74
  68. package/src/rate-limit-store-node-cache.adapter.ts +0 -28
  69. package/src/rate-limit-store.port.ts +0 -9
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bgord/bun",
3
- "version": "1.5.8",
3
+ "version": "1.5.10",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "author": "Bartosz Gordon",
@@ -20,7 +20,7 @@
20
20
  "preinstall": "bunx only-allow bun"
21
21
  },
22
22
  "devDependencies": {
23
- "@biomejs/biome": "2.3.9",
23
+ "@biomejs/biome": "2.3.10",
24
24
  "@commitlint/cli": "20.2.0",
25
25
  "@commitlint/config-conventional": "20.2.0",
26
26
  "@types/bun": "1.3.4",
package/readme.md CHANGED
@@ -36,7 +36,11 @@ src/
36
36
  ├── bots.vo.ts
37
37
  ├── build-info-repository.service.ts
38
38
  ├── cache-file.service.ts
39
- ├── cache-resolver.service.ts
39
+ ├── cache-repository-node-cache.adapter.ts
40
+ ├── cache-repository-noop.adapter.ts
41
+ ├── cache-repository.port.ts
42
+ ├── cache-resolver-simple.adapter.ts
43
+ ├── cache-resolver.port.ts
40
44
  ├── cache-response.middleware.ts
41
45
  ├── certificate-inspector-noop.adapter.ts
42
46
  ├── certificate-inspector-tls.adapter.ts
@@ -226,8 +230,6 @@ src/
226
230
  │   ├── timezone-utc.ts
227
231
  │   └── translations.ts
228
232
  ├── prerequisites.service.ts
229
- ├── rate-limit-store-node-cache.adapter.ts
230
- ├── rate-limit-store.port.ts
231
233
  ├── recaptcha-secret-key.vo.ts
232
234
  ├── recaptcha-site-key.vo.ts
233
235
  ├── redactor-compact-array.adapter.ts
@@ -0,0 +1,37 @@
1
+ import type * as tools from "@bgord/tools";
2
+ import NodeCache from "node-cache";
3
+ import type { CacheRepositoryKeyType, CacheRepositoryPort } from "./cache-repository.port";
4
+
5
+ export class CacheRepositoryNodeCacheAdapter implements CacheRepositoryPort {
6
+ private readonly store: NodeCache;
7
+
8
+ constructor(private readonly config: { ttl: tools.Duration }) {
9
+ this.store = new NodeCache({
10
+ stdTTL: config.ttl.seconds,
11
+ checkperiod: config.ttl.seconds,
12
+ deleteOnExpire: true,
13
+ maxKeys: 100_000,
14
+ useClones: false,
15
+ });
16
+ }
17
+
18
+ async get<T>(key: CacheRepositoryKeyType): Promise<T | null> {
19
+ return this.store.get(key) ?? null;
20
+ }
21
+
22
+ async set<T>(key: CacheRepositoryKeyType, value: T) {
23
+ this.store.set(key, value);
24
+ }
25
+
26
+ async delete(key: CacheRepositoryKeyType) {
27
+ this.store.del(key);
28
+ }
29
+
30
+ async flush() {
31
+ this.store.flushAll();
32
+ }
33
+
34
+ get ttl() {
35
+ return this.config.ttl;
36
+ }
37
+ }
@@ -0,0 +1,20 @@
1
+ import type * as tools from "@bgord/tools";
2
+ import type { CacheRepositoryPort } from "./cache-repository.port";
3
+
4
+ export class CacheRepositoryNoopAdapter implements CacheRepositoryPort {
5
+ constructor(private readonly config: { ttl: tools.Duration }) {}
6
+
7
+ async get<T>(): Promise<T | null> {
8
+ return null;
9
+ }
10
+
11
+ async set() {}
12
+
13
+ async delete() {}
14
+
15
+ async flush() {}
16
+
17
+ get ttl() {
18
+ return this.config.ttl;
19
+ }
20
+ }
@@ -0,0 +1,11 @@
1
+ import type * as tools from "@bgord/tools";
2
+
3
+ export type CacheRepositoryKeyType = string;
4
+
5
+ export interface CacheRepositoryPort {
6
+ get<T>(key: CacheRepositoryKeyType): Promise<T | null>;
7
+ set<T>(key: CacheRepositoryKeyType, value: T): Promise<void>;
8
+ delete(key: CacheRepositoryKeyType): Promise<void>;
9
+ flush(): Promise<void>;
10
+ get ttl(): tools.Duration;
11
+ }
@@ -0,0 +1,36 @@
1
+ import type { CacheRepositoryKeyType, CacheRepositoryPort } from "./cache-repository.port";
2
+ import { type CacheResolverPort, CacheSourceEnum } from "./cache-resolver.port";
3
+
4
+ type Dependencies = { CacheRepository: CacheRepositoryPort };
5
+
6
+ export class CacheResolverSimpleAdapter implements CacheResolverPort {
7
+ constructor(private readonly deps: Dependencies) {}
8
+
9
+ async resolve<T>(key: CacheRepositoryKeyType, producer: () => Promise<T>): Promise<T> {
10
+ const result = await this.resolveWithContext(key, producer);
11
+
12
+ return result.value;
13
+ }
14
+
15
+ async resolveWithContext<T>(
16
+ key: CacheRepositoryKeyType,
17
+ producer: () => Promise<T>,
18
+ ): Promise<{ value: T; source: CacheSourceEnum }> {
19
+ const cached = await this.deps.CacheRepository.get<T>(key);
20
+
21
+ if (cached !== null) return { value: cached, source: CacheSourceEnum.hit };
22
+
23
+ const value = await producer();
24
+ await this.deps.CacheRepository.set(key, value);
25
+
26
+ return { value, source: CacheSourceEnum.miss };
27
+ }
28
+
29
+ async flush() {
30
+ await this.deps.CacheRepository.flush();
31
+ }
32
+
33
+ get ttl() {
34
+ return this.deps.CacheRepository.ttl;
35
+ }
36
+ }
@@ -0,0 +1,20 @@
1
+ import type * as tools from "@bgord/tools";
2
+ import type { CacheRepositoryKeyType } from "./cache-repository.port";
3
+
4
+ export enum CacheSourceEnum {
5
+ hit = "hit",
6
+ miss = "",
7
+ }
8
+
9
+ export interface CacheResolverPort {
10
+ resolve<T>(key: CacheRepositoryKeyType, producer: () => Promise<T>): Promise<T>;
11
+
12
+ resolveWithContext<T>(
13
+ key: CacheRepositoryKeyType,
14
+ producer: () => Promise<T>,
15
+ ): Promise<{ value: T; source: CacheSourceEnum }>;
16
+
17
+ flush(): Promise<void>;
18
+
19
+ get ttl(): tools.Duration;
20
+ }
@@ -1,28 +1,54 @@
1
+ import type { Context } from "hono";
1
2
  import { createMiddleware } from "hono/factory";
2
- import type NodeCache from "node-cache";
3
- import { CacheHitEnum } from "./cache-resolver.service";
3
+ import type { ContentfulStatusCode } from "hono/utils/http-status";
4
+ import type { CacheResolverPort } from "./cache-resolver.port";
5
+
6
+ type SubjectResolver = (c: Context) => string;
7
+
8
+ type Dependencies = { CacheResolver: CacheResolverPort };
9
+
10
+ type CacheResponseOptions = { enabled: boolean; subject: SubjectResolver };
11
+
12
+ export const CacheResponseSubjectUrl: SubjectResolver = (c: Context) => c.req.url;
13
+
14
+ type CachedResponse = {
15
+ body: string;
16
+ headers: Record<string, string>;
17
+ status: ContentfulStatusCode;
18
+ };
4
19
 
5
20
  export class CacheResponse {
6
21
  static readonly CACHE_HIT_HEADER = "Cache-Hit";
7
22
 
8
- constructor(private readonly cache: NodeCache) {}
23
+ constructor(
24
+ private readonly config: CacheResponseOptions,
25
+ private readonly deps: Dependencies,
26
+ ) {}
9
27
 
10
28
  handle = createMiddleware(async (c, next) => {
11
- const url = c.req.url;
29
+ if (!this.config.enabled) return next();
12
30
 
13
- if (this.cache.has(url)) {
14
- c.res.headers.set(CacheResponse.CACHE_HIT_HEADER, CacheHitEnum.hit);
31
+ const subject = this.config.subject(c);
15
32
 
16
- return c.json(this.cache.get(url));
17
- }
33
+ const result = await this.deps.CacheResolver.resolveWithContext<CachedResponse>(subject, async () => {
34
+ await next();
18
35
 
19
- c.res.headers.set(CacheResponse.CACHE_HIT_HEADER, CacheHitEnum.miss);
36
+ const response = c.res.clone();
20
37
 
21
- return next();
38
+ return {
39
+ body: await response.text(),
40
+ headers: response.headers.toJSON(),
41
+ status: response.status as ContentfulStatusCode,
42
+ };
43
+ });
44
+
45
+ c.header(CacheResponse.CACHE_HIT_HEADER, result.source);
46
+
47
+ return c.newResponse(result.value.body, result.value.status, result.value.headers);
22
48
  });
23
49
 
24
50
  clear = createMiddleware(async (_c, next) => {
25
- this.cache.flushAll();
51
+ await this.deps.CacheResolver.flush();
26
52
 
27
53
  return next();
28
54
  });
@@ -1,26 +1,26 @@
1
1
  import type { z } from "zod/v4";
2
2
  import type { NodeEnvironmentEnum } from "../src/node-env.vo";
3
- import type { EnvironmentLoaderPort, EnvironmentResultType } from "./environment-loader.port";
3
+ import type { CacheResolverPort } from "./cache-resolver.port";
4
+ import type { EnvironmentLoaderPort } from "./environment-loader.port";
5
+
6
+ type Dependencies = { CacheResolver: CacheResolverPort };
4
7
 
5
8
  export class EnvironmentLoaderProcessSafeAdapter<Schema extends z.ZodObject<any>>
6
9
  implements EnvironmentLoaderPort<Schema>
7
10
  {
8
- private cached: Readonly<EnvironmentResultType<Schema>> | null = null;
9
-
10
11
  constructor(
11
- private readonly config: { type: NodeEnvironmentEnum; Schema: Schema },
12
12
  private env: NodeJS.ProcessEnv,
13
+ private readonly config: { type: NodeEnvironmentEnum; Schema: Schema },
14
+ private readonly deps: Dependencies,
13
15
  ) {}
14
16
 
15
17
  async load() {
16
- if (this.cached) return this.cached;
17
-
18
- const result = this.config.Schema.parse(this.env);
18
+ const result = await this.deps.CacheResolver.resolve("env", async () =>
19
+ this.config.Schema.parse(this.env),
20
+ );
19
21
 
20
22
  for (const key of Object.keys(result)) delete process.env[key];
21
23
 
22
- this.cached = Object.freeze({ ...result, type: this.config.type });
23
-
24
- return this.cached;
24
+ return Object.freeze({ ...result, type: this.config.type });
25
25
  }
26
26
  }
@@ -1,6 +1,6 @@
1
1
  import * as tools from "@bgord/tools";
2
2
  import { createMiddleware } from "hono/factory";
3
- import { CacheHitEnum } from "./cache-resolver.service";
3
+ import { CacheSourceEnum } from "./cache-resolver.port";
4
4
  import { CacheResponse } from "./cache-response.middleware";
5
5
  import { ClientFromHonoAdapter } from "./client-from-hono.adapter";
6
6
  import type { ClockPort } from "./clock.port";
@@ -93,7 +93,7 @@ export class HttpLogger {
93
93
  status: response.status,
94
94
  durationMs: duration.ms,
95
95
  client,
96
- cacheHit: response.headers.get(CacheResponse.CACHE_HIT_HEADER) === CacheHitEnum.hit,
96
+ cacheHit: response.headers.get(CacheResponse.CACHE_HIT_HEADER) === CacheSourceEnum.hit,
97
97
  metadata: { response: await HttpLogger.parseJSON(response) },
98
98
  });
99
99
  });
package/src/index.ts CHANGED
@@ -9,7 +9,11 @@ export * from "./better-auth-logger.service";
9
9
  export * from "./binary.vo";
10
10
  export * from "./build-info-repository.service";
11
11
  export * from "./cache-file.service";
12
- export * from "./cache-resolver.service";
12
+ export * from "./cache-repository.port";
13
+ export * from "./cache-repository-node-cache.adapter";
14
+ export * from "./cache-repository-noop.adapter";
15
+ export * from "./cache-resolver.port";
16
+ export * from "./cache-resolver-simple.adapter";
13
17
  export * from "./cache-response.middleware";
14
18
  export * from "./certificate-inspector.port";
15
19
  export * from "./certificate-inspector-noop.adapter";
@@ -146,8 +150,6 @@ export * from "./pdf-generator-noop.adapter";
146
150
  export * from "./port.vo";
147
151
  export * from "./prerequisites/index";
148
152
  export * from "./prerequisites.service";
149
- export * from "./rate-limit-store.port";
150
- export * from "./rate-limit-store-node-cache.adapter";
151
153
  export * from "./recaptcha-secret-key.vo";
152
154
  export * from "./recaptcha-site-key.vo";
153
155
  export * from "./redactor.port";
@@ -28,7 +28,7 @@ export class JobHandler {
28
28
  try {
29
29
  this.deps.Logger.info({ message: `${uow.label} start`, correlationId, ...this.base });
30
30
 
31
- await CorrelationStorage.run(correlationId, uow.process);
31
+ await CorrelationStorage.run(correlationId, async () => uow.process());
32
32
 
33
33
  this.deps.Logger.info({
34
34
  message: `${uow.label} success`,
@@ -2,17 +2,17 @@ import * as tools from "@bgord/tools";
2
2
  import type { Context } from "hono";
3
3
  import { createMiddleware } from "hono/factory";
4
4
  import { HTTPException } from "hono/http-exception";
5
+ import type { CacheResolverPort } from "./cache-resolver.port";
5
6
  import type { ClockPort } from "./clock.port";
6
- import type { RateLimitStorePort } from "./rate-limit-store.port";
7
7
  import type { ShieldPort } from "./shield.port";
8
8
 
9
9
  type SubjectResolver = (c: Context) => string;
10
- type ShieldRateLimitOptionsType = { enabled: boolean; store: RateLimitStorePort; subject: SubjectResolver };
10
+ type ShieldRateLimitOptionsType = { enabled: boolean; subject: SubjectResolver };
11
11
 
12
- type Dependencies = { Clock: ClockPort };
12
+ type Dependencies = { Clock: ClockPort; CacheResolver: CacheResolverPort };
13
13
 
14
- export const AnonSubjectResolver: SubjectResolver = () => "anon";
15
- export const UserSubjectResolver: SubjectResolver = (c) => c.get("user")?.id ?? "anon";
14
+ export const RateLimitSubjectAnon: SubjectResolver = () => "anon";
15
+ export const RateLimitSubjectUser: SubjectResolver = (c) => c.get("user")?.id ?? "anon";
16
16
 
17
17
  export const TooManyRequestsError = new HTTPException(429, { message: "app.too_many_requests" });
18
18
 
@@ -27,18 +27,14 @@ export class ShieldRateLimitAdapter implements ShieldPort {
27
27
 
28
28
  const subject = this.options.subject(c);
29
29
 
30
- let limiter = await this.options.store.get(subject);
30
+ const limiter = await this.deps.CacheResolver.resolve(
31
+ subject,
32
+ async () => new tools.RateLimiter(this.deps.CacheResolver.ttl),
33
+ );
31
34
 
32
- if (!limiter) {
33
- limiter = new tools.RateLimiter(this.options.store.ttl);
34
- this.options.store.set(subject, limiter);
35
- }
35
+ const result = limiter.verify(this.deps.Clock.now());
36
36
 
37
- const check = limiter.verify(this.deps.Clock.now());
38
-
39
- if (!check.allowed) throw TooManyRequestsError;
40
-
41
- this.options.store.set(subject, limiter);
37
+ if (!result.allowed) throw TooManyRequestsError;
42
38
 
43
39
  return next();
44
40
  });
@@ -1,47 +0,0 @@
1
- import type { Context } from "hono";
2
- import type NodeCache from "node-cache";
3
- import type { Key } from "node-cache";
4
- type Resolver<T> = () => Promise<T>;
5
- type BaseOptions<T> = {
6
- key: Key;
7
- resolver: Resolver<T>;
8
- };
9
- type CacheResolverSimpleResult<T> = {
10
- data: T;
11
- };
12
- type CacheResolverWithMetadataResult<T> = {
13
- data: T;
14
- meta: {
15
- hit: CacheHitEnum;
16
- };
17
- };
18
- type CacheResolverRequestHeadersResult<T> = {
19
- data: T;
20
- header: {
21
- name: "cache-hit";
22
- value: CacheHitEnum;
23
- };
24
- respond: (c: Context) => Promise<void>;
25
- };
26
- export declare enum CacheHitEnum {
27
- hit = "hit",
28
- miss = "miss"
29
- }
30
- export declare enum CacheResolverStrategy {
31
- simple = "simple",
32
- with_metadata = "with_metadata",
33
- request_headers = "request_headers"
34
- }
35
- export declare class CacheResolver {
36
- static resolve<T>(cache: NodeCache, options: BaseOptions<T> & {
37
- strategy?: CacheResolverStrategy.simple;
38
- }): Promise<CacheResolverSimpleResult<T>>;
39
- static resolve<T>(cache: NodeCache, options: BaseOptions<T> & {
40
- strategy: CacheResolverStrategy.with_metadata;
41
- }): Promise<CacheResolverWithMetadataResult<T>>;
42
- static resolve<T>(cache: NodeCache, options: BaseOptions<T> & {
43
- strategy: CacheResolverStrategy.request_headers;
44
- }): Promise<CacheResolverRequestHeadersResult<T>>;
45
- }
46
- export {};
47
- //# sourceMappingURL=cache-resolver.service.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cache-resolver.service.d.ts","sourceRoot":"","sources":["../src/cache-resolver.service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACpC,OAAO,KAAK,SAAS,MAAM,YAAY,CAAC;AACxC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AAEtC,KAAK,QAAQ,CAAC,CAAC,IAAI,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC;AACpC,KAAK,WAAW,CAAC,CAAC,IAAI;IAAE,GAAG,EAAE,GAAG,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAA;CAAE,CAAC;AAC1D,KAAK,yBAAyB,CAAC,CAAC,IAAI;IAAE,IAAI,EAAE,CAAC,CAAA;CAAE,CAAC;AAChD,KAAK,+BAA+B,CAAC,CAAC,IAAI;IAAE,IAAI,EAAE,CAAC,CAAC;IAAC,IAAI,EAAE;QAAE,GAAG,EAAE,YAAY,CAAA;KAAE,CAAA;CAAE,CAAC;AACnF,KAAK,iCAAiC,CAAC,CAAC,IAAI;IAC1C,IAAI,EAAE,CAAC,CAAC;IACR,MAAM,EAAE;QAAE,IAAI,EAAE,WAAW,CAAC;QAAC,KAAK,EAAE,YAAY,CAAA;KAAE,CAAC;IACnD,OAAO,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACxC,CAAC;AAEF,oBAAY,YAAY;IACtB,GAAG,QAAQ;IACX,IAAI,SAAS;CACd;AAED,oBAAY,qBAAqB;IAC/B,MAAM,WAAW;IACjB,aAAa,kBAAkB;IAC/B,eAAe,oBAAoB;CACpC;AAED,qBAAa,aAAa;WACX,OAAO,CAAC,CAAC,EACpB,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG;QAAE,QAAQ,CAAC,EAAE,qBAAqB,CAAC,MAAM,CAAA;KAAE,GACpE,OAAO,CAAC,yBAAyB,CAAC,CAAC,CAAC,CAAC;WAE3B,OAAO,CAAC,CAAC,EACpB,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG;QAAE,QAAQ,EAAE,qBAAqB,CAAC,aAAa,CAAA;KAAE,GAC1E,OAAO,CAAC,+BAA+B,CAAC,CAAC,CAAC,CAAC;WAEjC,OAAO,CAAC,CAAC,EACpB,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG;QAAE,QAAQ,EAAE,qBAAqB,CAAC,eAAe,CAAA;KAAE,GAC5E,OAAO,CAAC,iCAAiC,CAAC,CAAC,CAAC,CAAC;CAkCjD"}
@@ -1,37 +0,0 @@
1
- export var CacheHitEnum;
2
- (function (CacheHitEnum) {
3
- CacheHitEnum["hit"] = "hit";
4
- CacheHitEnum["miss"] = "miss";
5
- })(CacheHitEnum || (CacheHitEnum = {}));
6
- export var CacheResolverStrategy;
7
- (function (CacheResolverStrategy) {
8
- CacheResolverStrategy["simple"] = "simple";
9
- CacheResolverStrategy["with_metadata"] = "with_metadata";
10
- CacheResolverStrategy["request_headers"] = "request_headers";
11
- })(CacheResolverStrategy || (CacheResolverStrategy = {}));
12
- export class CacheResolver {
13
- static async resolve(cache, options) {
14
- const strategy = options.strategy ?? CacheResolverStrategy.simple;
15
- const cached = cache.get(options.key);
16
- const hit = cached !== undefined;
17
- const data = hit ? cached : await options.resolver();
18
- if (!hit)
19
- cache.set(options.key, data);
20
- switch (strategy) {
21
- case CacheResolverStrategy.with_metadata:
22
- return { data, meta: { hit: hit ? CacheHitEnum.hit : CacheHitEnum.miss } };
23
- case CacheResolverStrategy.request_headers:
24
- return {
25
- data,
26
- respond: (c) => {
27
- c.header("cache-hit", hit ? CacheHitEnum.hit : CacheHitEnum.miss);
28
- return c.json(data);
29
- },
30
- header: { name: "cache-hit", value: hit ? CacheHitEnum.hit : CacheHitEnum.miss },
31
- };
32
- default:
33
- return { data };
34
- }
35
- }
36
- }
37
- //# sourceMappingURL=cache-resolver.service.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cache-resolver.service.js","sourceRoot":"","sources":["../src/cache-resolver.service.ts"],"names":[],"mappings":"AAcA,MAAM,CAAN,IAAY,YAGX;AAHD,WAAY,YAAY;IACtB,2BAAW,CAAA;IACX,6BAAa,CAAA;AACf,CAAC,EAHW,YAAY,KAAZ,YAAY,QAGvB;AAED,MAAM,CAAN,IAAY,qBAIX;AAJD,WAAY,qBAAqB;IAC/B,0CAAiB,CAAA;IACjB,wDAA+B,CAAA;IAC/B,4DAAmC,CAAA;AACrC,CAAC,EAJW,qBAAqB,KAArB,qBAAqB,QAIhC;AAED,MAAM,OAAO,aAAa;IAgBxB,MAAM,CAAC,KAAK,CAAC,OAAO,CAClB,KAAgB,EAChB,OAA8D;QAE9D,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,qBAAqB,CAAC,MAAM,CAAC;QAElE,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAI,OAAO,CAAC,GAAG,CAAC,CAAC;QAEzC,MAAM,GAAG,GAAG,MAAM,KAAK,SAAS,CAAC;QAEjC,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,OAAO,CAAC,QAAQ,EAAE,CAAC;QAErD,IAAI,CAAC,GAAG;YAAE,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAEvC,QAAQ,QAAQ,EAAE,CAAC;YACjB,KAAK,qBAAqB,CAAC,aAAa;gBACtC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,EAAE,EAAE,CAAC;YAE7E,KAAK,qBAAqB,CAAC,eAAe;gBACxC,OAAO;oBACL,IAAI;oBACJ,OAAO,EAAE,CAAC,CAAU,EAAE,EAAE;wBACtB,CAAC,CAAC,MAAM,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;wBAClE,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBACtB,CAAC;oBACD,MAAM,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,EAAE;iBACjF,CAAC;YAEJ;gBACE,OAAO,EAAE,IAAI,EAAE,CAAC;QACpB,CAAC;IACH,CAAC;CACF"}
@@ -1,11 +0,0 @@
1
- import type * as tools from "@bgord/tools";
2
- import type { RateLimitStorePort, RateLimitStoreSubjectType } from "./rate-limit-store.port";
3
- export declare class RateLimitStoreNodeCacheAdapter implements RateLimitStorePort {
4
- readonly ttl: tools.Duration;
5
- private readonly store;
6
- constructor(ttl: tools.Duration);
7
- get(subject: RateLimitStoreSubjectType): Promise<tools.RateLimiter | undefined>;
8
- set(subject: RateLimitStoreSubjectType, limiter: tools.RateLimiter): Promise<void>;
9
- flushAll(): void;
10
- }
11
- //# sourceMappingURL=rate-limit-store-node-cache.adapter.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"rate-limit-store-node-cache.adapter.d.ts","sourceRoot":"","sources":["../src/rate-limit-store-node-cache.adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,KAAK,MAAM,cAAc,CAAC;AAE3C,OAAO,KAAK,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AAE7F,qBAAa,8BAA+B,YAAW,kBAAkB;IAG3D,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,QAAQ;IAFxC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAY;gBAEb,GAAG,EAAE,KAAK,CAAC,QAAQ;IASlC,GAAG,CAAC,OAAO,EAAE,yBAAyB;IAItC,GAAG,CAAC,OAAO,EAAE,yBAAyB,EAAE,OAAO,EAAE,KAAK,CAAC,WAAW;IAIxE,QAAQ;CAGT"}
@@ -1,24 +0,0 @@
1
- import NodeCache from "node-cache";
2
- export class RateLimitStoreNodeCacheAdapter {
3
- ttl;
4
- store;
5
- constructor(ttl) {
6
- this.ttl = ttl;
7
- this.store = new NodeCache({
8
- stdTTL: this.ttl.seconds,
9
- checkperiod: this.ttl.seconds,
10
- deleteOnExpire: true,
11
- maxKeys: 100_000,
12
- });
13
- }
14
- async get(subject) {
15
- return this.store.get(subject);
16
- }
17
- async set(subject, limiter) {
18
- this.store.set(subject, limiter);
19
- }
20
- flushAll() {
21
- this.store.flushAll();
22
- }
23
- }
24
- //# sourceMappingURL=rate-limit-store-node-cache.adapter.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"rate-limit-store-node-cache.adapter.js","sourceRoot":"","sources":["../src/rate-limit-store-node-cache.adapter.ts"],"names":[],"mappings":"AACA,OAAO,SAAS,MAAM,YAAY,CAAC;AAGnC,MAAM,OAAO,8BAA8B;IAGpB;IAFJ,KAAK,CAAY;IAElC,YAAqB,GAAmB;QAAnB,QAAG,GAAH,GAAG,CAAgB;QACtC,IAAI,CAAC,KAAK,GAAG,IAAI,SAAS,CAAC;YACzB,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO;YACxB,WAAW,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO;YAC7B,cAAc,EAAE,IAAI;YACpB,OAAO,EAAE,OAAO;SACjB,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,OAAkC;QAC1C,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAoB,OAAO,CAAC,CAAC;IACpD,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,OAAkC,EAAE,OAA0B;QACtE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACnC,CAAC;IAED,QAAQ;QACN,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;IACxB,CAAC;CACF"}
@@ -1,8 +0,0 @@
1
- import type * as tools from "@bgord/tools";
2
- export type RateLimitStoreSubjectType = string;
3
- export interface RateLimitStorePort {
4
- readonly ttl: tools.Duration;
5
- get(subject: RateLimitStoreSubjectType): Promise<tools.RateLimiter | undefined>;
6
- set(subject: RateLimitStoreSubjectType, limiter: tools.RateLimiter): Promise<void>;
7
- }
8
- //# sourceMappingURL=rate-limit-store.port.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"rate-limit-store.port.d.ts","sourceRoot":"","sources":["../src/rate-limit-store.port.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,KAAK,MAAM,cAAc,CAAC;AAE3C,MAAM,MAAM,yBAAyB,GAAG,MAAM,CAAC;AAE/C,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,QAAQ,CAAC;IAC7B,GAAG,CAAC,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAAC,KAAK,CAAC,WAAW,GAAG,SAAS,CAAC,CAAC;IAChF,GAAG,CAAC,OAAO,EAAE,yBAAyB,EAAE,OAAO,EAAE,KAAK,CAAC,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACpF"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=rate-limit-store.port.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"rate-limit-store.port.js","sourceRoot":"","sources":["../src/rate-limit-store.port.ts"],"names":[],"mappings":""}
@@ -1,74 +0,0 @@
1
- import type { Context } from "hono";
2
- import type NodeCache from "node-cache";
3
- import type { Key } from "node-cache";
4
-
5
- type Resolver<T> = () => Promise<T>;
6
- type BaseOptions<T> = { key: Key; resolver: Resolver<T> };
7
- type CacheResolverSimpleResult<T> = { data: T };
8
- type CacheResolverWithMetadataResult<T> = { data: T; meta: { hit: CacheHitEnum } };
9
- type CacheResolverRequestHeadersResult<T> = {
10
- data: T;
11
- header: { name: "cache-hit"; value: CacheHitEnum };
12
- respond: (c: Context) => Promise<void>;
13
- };
14
-
15
- export enum CacheHitEnum {
16
- hit = "hit",
17
- miss = "miss",
18
- }
19
-
20
- export enum CacheResolverStrategy {
21
- simple = "simple",
22
- with_metadata = "with_metadata",
23
- request_headers = "request_headers",
24
- }
25
-
26
- export class CacheResolver {
27
- static async resolve<T>(
28
- cache: NodeCache,
29
- options: BaseOptions<T> & { strategy?: CacheResolverStrategy.simple },
30
- ): Promise<CacheResolverSimpleResult<T>>;
31
-
32
- static async resolve<T>(
33
- cache: NodeCache,
34
- options: BaseOptions<T> & { strategy: CacheResolverStrategy.with_metadata },
35
- ): Promise<CacheResolverWithMetadataResult<T>>;
36
-
37
- static async resolve<T>(
38
- cache: NodeCache,
39
- options: BaseOptions<T> & { strategy: CacheResolverStrategy.request_headers },
40
- ): Promise<CacheResolverRequestHeadersResult<T>>;
41
-
42
- static async resolve<T>(
43
- cache: NodeCache,
44
- options: BaseOptions<T> & { strategy?: CacheResolverStrategy },
45
- ): Promise<any> {
46
- const strategy = options.strategy ?? CacheResolverStrategy.simple;
47
-
48
- const cached = cache.get<T>(options.key);
49
-
50
- const hit = cached !== undefined;
51
-
52
- const data = hit ? cached : await options.resolver();
53
-
54
- if (!hit) cache.set(options.key, data);
55
-
56
- switch (strategy) {
57
- case CacheResolverStrategy.with_metadata:
58
- return { data, meta: { hit: hit ? CacheHitEnum.hit : CacheHitEnum.miss } };
59
-
60
- case CacheResolverStrategy.request_headers:
61
- return {
62
- data,
63
- respond: (c: Context) => {
64
- c.header("cache-hit", hit ? CacheHitEnum.hit : CacheHitEnum.miss);
65
- return c.json(data);
66
- },
67
- header: { name: "cache-hit", value: hit ? CacheHitEnum.hit : CacheHitEnum.miss },
68
- };
69
-
70
- default:
71
- return { data };
72
- }
73
- }
74
- }
@@ -1,28 +0,0 @@
1
- import type * as tools from "@bgord/tools";
2
- import NodeCache from "node-cache";
3
- import type { RateLimitStorePort, RateLimitStoreSubjectType } from "./rate-limit-store.port";
4
-
5
- export class RateLimitStoreNodeCacheAdapter implements RateLimitStorePort {
6
- private readonly store: NodeCache;
7
-
8
- constructor(readonly ttl: tools.Duration) {
9
- this.store = new NodeCache({
10
- stdTTL: this.ttl.seconds,
11
- checkperiod: this.ttl.seconds,
12
- deleteOnExpire: true,
13
- maxKeys: 100_000,
14
- });
15
- }
16
-
17
- async get(subject: RateLimitStoreSubjectType) {
18
- return this.store.get<tools.RateLimiter>(subject);
19
- }
20
-
21
- async set(subject: RateLimitStoreSubjectType, limiter: tools.RateLimiter) {
22
- this.store.set(subject, limiter);
23
- }
24
-
25
- flushAll() {
26
- this.store.flushAll();
27
- }
28
- }
@@ -1,9 +0,0 @@
1
- import type * as tools from "@bgord/tools";
2
-
3
- export type RateLimitStoreSubjectType = string;
4
-
5
- export interface RateLimitStorePort {
6
- readonly ttl: tools.Duration;
7
- get(subject: RateLimitStoreSubjectType): Promise<tools.RateLimiter | undefined>;
8
- set(subject: RateLimitStoreSubjectType, limiter: tools.RateLimiter): Promise<void>;
9
- }