@kuckit/infrastructure 2.0.0 → 2.0.1

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 (36) hide show
  1. package/dist/cache/in-memory-cache-store.d.ts +2 -2
  2. package/dist/cache/in-memory-cache-store.js +2 -2
  3. package/dist/cache/index.d.ts +2 -2
  4. package/dist/cache/index.js +2 -2
  5. package/dist/{core.module-B1TdC0yX.d.ts → core.module-_mfoxc8b.d.ts} +2 -2
  6. package/dist/{core.module-DMtIkTcz.js → core.module-ehJ0bdNr.js} +8 -8
  7. package/dist/core.module-ehJ0bdNr.js.map +1 -0
  8. package/dist/{in-memory-cache-store-oClww-8m.js → in-memory-cache-store-BA-Eqsf0.js} +24 -4
  9. package/dist/in-memory-cache-store-BA-Eqsf0.js.map +1 -0
  10. package/dist/{in-memory-cache-store-BaRxM--K.d.ts → in-memory-cache-store-DSdz35Ve.d.ts} +17 -3
  11. package/dist/{in-memory-rate-limiter-BDSHZXxf.js → in-memory-rate-limiter-DKOwxFD7.js} +24 -4
  12. package/dist/in-memory-rate-limiter-DKOwxFD7.js.map +1 -0
  13. package/dist/{in-memory-rate-limiter-DJsxdZZR.d.ts → in-memory-rate-limiter-DZqM4MOS.d.ts} +17 -3
  14. package/dist/index.d.ts +7 -7
  15. package/dist/index.js +4 -4
  16. package/dist/logging/index.d.ts +2 -2
  17. package/dist/logging/structured-logger.d.ts +2 -2
  18. package/dist/modules/core.module.d.ts +3 -3
  19. package/dist/modules/core.module.js +3 -3
  20. package/dist/modules/index.d.ts +4 -4
  21. package/dist/modules/index.js +3 -3
  22. package/dist/modules/types.d.ts +2 -2
  23. package/dist/modules/types.js +0 -1
  24. package/dist/modules/user.module.d.ts +3 -3
  25. package/dist/rate-limiter/in-memory-rate-limiter.d.ts +2 -2
  26. package/dist/rate-limiter/in-memory-rate-limiter.js +2 -2
  27. package/dist/rate-limiter/index.d.ts +2 -2
  28. package/dist/rate-limiter/index.js +2 -2
  29. package/dist/structured-logger-BsxDI9zX.js.map +1 -1
  30. package/dist/{structured-logger-Dz06Uz-u.d.ts → structured-logger-DyrZwR3S.d.ts} +2 -2
  31. package/dist/{types-65aFqB5L.d.ts → types-BnE7rffD.d.ts} +9 -5
  32. package/dist/{user.module-D3lVJ98T.d.ts → user.module-DqTfy_MM.d.ts} +2 -2
  33. package/package.json +4 -4
  34. package/dist/core.module-DMtIkTcz.js.map +0 -1
  35. package/dist/in-memory-cache-store-oClww-8m.js.map +0 -1
  36. package/dist/in-memory-rate-limiter-BDSHZXxf.js.map +0 -1
@@ -1,2 +1,2 @@
1
- import { t as InMemoryCacheStore } from "../in-memory-cache-store-BaRxM--K.js";
2
- export { InMemoryCacheStore };
1
+ import { n as makeInMemoryCacheStore, t as InMemoryCacheStore } from "../in-memory-cache-store-DSdz35Ve.js";
2
+ export { InMemoryCacheStore, makeInMemoryCacheStore };
@@ -1,3 +1,3 @@
1
- import { t as InMemoryCacheStore } from "../in-memory-cache-store-oClww-8m.js";
1
+ import { n as makeInMemoryCacheStore, t as InMemoryCacheStore } from "../in-memory-cache-store-BA-Eqsf0.js";
2
2
 
3
- export { InMemoryCacheStore };
3
+ export { InMemoryCacheStore, makeInMemoryCacheStore };
@@ -1,3 +1,3 @@
1
- import { t as InMemoryCacheStore } from "../in-memory-cache-store-BaRxM--K.js";
1
+ import { n as makeInMemoryCacheStore, t as InMemoryCacheStore } from "../in-memory-cache-store-DSdz35Ve.js";
2
2
  import { t as CacheStore } from "../index-C6nYd7xV.js";
3
- export { CacheStore, InMemoryCacheStore };
3
+ export { CacheStore, InMemoryCacheStore, makeInMemoryCacheStore };
@@ -1,4 +1,4 @@
1
- import { t as InMemoryCacheStore } from "../in-memory-cache-store-oClww-8m.js";
1
+ import { n as makeInMemoryCacheStore, t as InMemoryCacheStore } from "../in-memory-cache-store-BA-Eqsf0.js";
2
2
  import "../cache-BjdZ-Ye4.js";
3
3
 
4
- export { InMemoryCacheStore };
4
+ export { InMemoryCacheStore, makeInMemoryCacheStore };
@@ -1,4 +1,4 @@
1
- import { n as Cradle } from "./types-65aFqB5L.js";
1
+ import { n as Cradle } from "./types-BnE7rffD.js";
2
2
  import { AwilixContainer } from "awilix";
3
3
 
4
4
  //#region src/modules/core.module.d.ts
@@ -14,4 +14,4 @@ import { AwilixContainer } from "awilix";
14
14
  declare const registerCoreModule: (container: AwilixContainer<Cradle>) => void;
15
15
  //#endregion
16
16
  export { registerCoreModule as t };
17
- //# sourceMappingURL=core.module-B1TdC0yX.d.ts.map
17
+ //# sourceMappingURL=core.module-_mfoxc8b.d.ts.map
@@ -3,12 +3,12 @@ import { n as makeStructuredLogger } from "./structured-logger-BsxDI9zX.js";
3
3
  import { t as makeRequestLogger } from "./request-logger-Cw1XQWTV.js";
4
4
  import { n as makeErrorHandler } from "./error-handler-D4s_TTI1.js";
5
5
  import { t as InMemoryEventBus } from "./in-memory-event-bus-BCyPrNAE.js";
6
- import { t as InMemoryCacheStore } from "./in-memory-cache-store-oClww-8m.js";
7
- import { t as InMemoryRateLimiterStore } from "./in-memory-rate-limiter-BDSHZXxf.js";
8
- import { asClass, asFunction, asValue } from "awilix";
6
+ import { t as InMemoryCacheStore } from "./in-memory-cache-store-BA-Eqsf0.js";
7
+ import { t as InMemoryRateLimiterStore } from "./in-memory-rate-limiter-DKOwxFD7.js";
8
+ import { asFunction, asValue } from "awilix";
9
9
  import { SystemClock } from "@kuckit/domain/ports/clock";
10
10
  import { google } from "@ai-sdk/google";
11
- import { auth } from "@kuckit/auth";
11
+ import { createAuth } from "@kuckit/auth";
12
12
 
13
13
  //#region src/modules/core.module.ts
14
14
  /**
@@ -30,11 +30,11 @@ const registerCoreModule = (container) => {
30
30
  minLevel: config.logLevel
31
31
  })).singleton(),
32
32
  errorHandler: asFunction(({ logger }) => makeErrorHandler(logger)).singleton(),
33
- auth: asValue(auth),
33
+ auth: asFunction(({ db }) => createAuth({ db })).singleton(),
34
34
  aiProvider: asFunction(() => google("gemini-2.5-flash")).singleton(),
35
35
  eventBus: asFunction(({ logger }) => new InMemoryEventBus(logger)).singleton(),
36
- cacheStore: asClass(InMemoryCacheStore).singleton(),
37
- rateLimiterStore: asClass(InMemoryRateLimiterStore).singleton(),
36
+ cacheStore: asFunction(() => new InMemoryCacheStore()).singleton(),
37
+ rateLimiterStore: asFunction(() => new InMemoryRateLimiterStore()).singleton(),
38
38
  requestLogger: asFunction(({ logger, requestId, session }) => makeRequestLogger({
39
39
  requestId,
40
40
  userId: session?.user?.id,
@@ -45,4 +45,4 @@ const registerCoreModule = (container) => {
45
45
 
46
46
  //#endregion
47
47
  export { registerCoreModule as t };
48
- //# sourceMappingURL=core.module-DMtIkTcz.js.map
48
+ //# sourceMappingURL=core.module-ehJ0bdNr.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"core.module-ehJ0bdNr.js","names":[],"sources":["../src/modules/core.module.ts"],"sourcesContent":["import { asFunction, asValue, type AwilixContainer } from 'awilix'\nimport { SystemClock } from '@kuckit/domain/ports/clock'\nimport { google } from '@ai-sdk/google'\nimport { createAuth } from '@kuckit/auth'\nimport { createDbPool, createDb } from '../db/drizzle/db'\nimport { makeStructuredLogger, makeRequestLogger, type LogLevel } from '../logging'\nimport { makeErrorHandler } from '../errors'\nimport { InMemoryEventBus } from '../events/in-memory-event-bus'\nimport { InMemoryCacheStore } from '../cache/in-memory-cache-store'\nimport { InMemoryRateLimiterStore } from '../rate-limiter/in-memory-rate-limiter'\nimport type { Cradle } from './types'\n\n/**\n * Core module: singleton registrations for infrastructure\n * - Database pool and connection\n * - Clock\n * - Logger (structured, Loki/Prometheus compatible)\n * - AI provider\n * - Auth\n */\nexport const registerCoreModule = (container: AwilixContainer<Cradle>): void => {\n\tcontainer.register({\n\t\t// Database\n\t\tdbPool: asFunction(({ config }) => createDbPool(config.databaseUrl)).singleton(),\n\n\t\tdb: asFunction(({ dbPool }) => createDb(dbPool)).singleton(),\n\n\t\t// Core services\n\t\tclock: asValue(new SystemClock()),\n\n\t\tlogger: asFunction(({ config }) =>\n\t\t\tmakeStructuredLogger({\n\t\t\t\tenableFile: config.enableFileLogging,\n\t\t\t\tlogDir: config.logDir,\n\t\t\t\tminLevel: config.logLevel as LogLevel,\n\t\t\t})\n\t\t).singleton(),\n\n\t\terrorHandler: asFunction(({ logger }) => makeErrorHandler(logger)).singleton(),\n\n\t\t// External integrations\n\t\tauth: asFunction(({ db }) => createAuth({ db })).singleton(),\n\n\t\taiProvider: asFunction(() => google('gemini-2.5-flash')).singleton(),\n\n\t\t// Event bus\n\t\teventBus: asFunction(({ logger }) => new InMemoryEventBus(logger)).singleton(),\n\n\t\t// Cache store (no DI deps, use asFunction to avoid PROXY mode issues)\n\t\tcacheStore: asFunction(() => new InMemoryCacheStore()).singleton(),\n\n\t\t// Rate limiter store (no DI deps, use asFunction to avoid PROXY mode issues)\n\t\trateLimiterStore: asFunction(() => new InMemoryRateLimiterStore()).singleton(),\n\n\t\t// Request-scoped logger (enriched with requestId and userId)\n\t\trequestLogger: asFunction(({ logger, requestId, session }) =>\n\t\t\tmakeRequestLogger({\n\t\t\t\trequestId,\n\t\t\t\tuserId: session?.user?.id,\n\t\t\t\tbaseLogger: logger,\n\t\t\t})\n\t\t).scoped(),\n\t})\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAoBA,MAAa,sBAAsB,cAA6C;AAC/E,WAAU,SAAS;EAElB,QAAQ,YAAY,EAAE,aAAa,aAAa,OAAO,YAAY,CAAC,CAAC,WAAW;EAEhF,IAAI,YAAY,EAAE,aAAa,SAAS,OAAO,CAAC,CAAC,WAAW;EAG5D,OAAO,QAAQ,IAAI,aAAa,CAAC;EAEjC,QAAQ,YAAY,EAAE,aACrB,qBAAqB;GACpB,YAAY,OAAO;GACnB,QAAQ,OAAO;GACf,UAAU,OAAO;GACjB,CAAC,CACF,CAAC,WAAW;EAEb,cAAc,YAAY,EAAE,aAAa,iBAAiB,OAAO,CAAC,CAAC,WAAW;EAG9E,MAAM,YAAY,EAAE,SAAS,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC,WAAW;EAE5D,YAAY,iBAAiB,OAAO,mBAAmB,CAAC,CAAC,WAAW;EAGpE,UAAU,YAAY,EAAE,aAAa,IAAI,iBAAiB,OAAO,CAAC,CAAC,WAAW;EAG9E,YAAY,iBAAiB,IAAI,oBAAoB,CAAC,CAAC,WAAW;EAGlE,kBAAkB,iBAAiB,IAAI,0BAA0B,CAAC,CAAC,WAAW;EAG9E,eAAe,YAAY,EAAE,QAAQ,WAAW,cAC/C,kBAAkB;GACjB;GACA,QAAQ,SAAS,MAAM;GACvB,YAAY;GACZ,CAAC,CACF,CAAC,QAAQ;EACV,CAAC"}
@@ -3,13 +3,15 @@
3
3
  * In-memory cache store implementation
4
4
  * Suitable for single-process applications or development
5
5
  * For distributed systems, use Redis adapter
6
+ *
7
+ * NOTE: Call startCleanup() after construction to enable background cleanup,
8
+ * or use makeInMemoryCacheStore() factory which does this automatically.
6
9
  */
7
10
  var InMemoryCacheStore = class {
8
11
  cache = /* @__PURE__ */ new Map();
9
12
  cleanupTimer = null;
10
13
  constructor(cleanupIntervalMs = 6e4) {
11
14
  this.cleanupIntervalMs = cleanupIntervalMs;
12
- this.startCleanup();
13
15
  }
14
16
  async get(key) {
15
17
  const entry = this.cache.get(key);
@@ -44,8 +46,10 @@ var InMemoryCacheStore = class {
44
46
  }
45
47
  /**
46
48
  * Start background cleanup of expired entries
49
+ * Call this after construction to enable automatic cleanup.
47
50
  */
48
51
  startCleanup() {
52
+ if (this.cleanupTimer) return;
49
53
  this.cleanupTimer = setInterval(() => {
50
54
  const now = Date.now();
51
55
  let expired = 0;
@@ -59,14 +63,30 @@ var InMemoryCacheStore = class {
59
63
  /**
60
64
  * Stop cleanup timer
61
65
  */
62
- destroy() {
66
+ stopCleanup() {
63
67
  if (this.cleanupTimer) {
64
68
  clearInterval(this.cleanupTimer);
65
69
  this.cleanupTimer = null;
66
70
  }
67
71
  }
72
+ /**
73
+ * Stop cleanup timer (alias for stopCleanup)
74
+ * @deprecated Use stopCleanup() instead
75
+ */
76
+ destroy() {
77
+ this.stopCleanup();
78
+ }
68
79
  };
80
+ /**
81
+ * Factory function that creates an InMemoryCacheStore with cleanup started.
82
+ * Use this in DI container registrations.
83
+ */
84
+ function makeInMemoryCacheStore(cleanupIntervalMs = 6e4) {
85
+ const store = new InMemoryCacheStore(cleanupIntervalMs);
86
+ store.startCleanup();
87
+ return store;
88
+ }
69
89
 
70
90
  //#endregion
71
- export { InMemoryCacheStore as t };
72
- //# sourceMappingURL=in-memory-cache-store-oClww-8m.js.map
91
+ export { makeInMemoryCacheStore as n, InMemoryCacheStore as t };
92
+ //# sourceMappingURL=in-memory-cache-store-BA-Eqsf0.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"in-memory-cache-store-BA-Eqsf0.js","names":["cleanupIntervalMs: number","entry: CacheEntry<T>"],"sources":["../src/cache/in-memory-cache-store.ts"],"sourcesContent":["import type { CacheStore } from '@kuckit/domain'\n\ninterface CacheEntry<T> {\n\tvalue: T\n\texpiresAt?: number\n}\n\n/**\n * In-memory cache store implementation\n * Suitable for single-process applications or development\n * For distributed systems, use Redis adapter\n *\n * NOTE: Call startCleanup() after construction to enable background cleanup,\n * or use makeInMemoryCacheStore() factory which does this automatically.\n */\nexport class InMemoryCacheStore implements CacheStore {\n\tprivate cache = new Map<string, CacheEntry<unknown>>()\n\tprivate cleanupTimer: NodeJS.Timeout | null = null\n\n\tconstructor(private cleanupIntervalMs: number = 60000) {\n\t\t// Timer is NOT started in constructor to avoid side effects on import.\n\t\t// Call startCleanup() explicitly after construction.\n\t}\n\n\tasync get<T>(key: string): Promise<T | undefined> {\n\t\tconst entry = this.cache.get(key)\n\n\t\tif (!entry) {\n\t\t\treturn undefined\n\t\t}\n\n\t\t// Check if expired\n\t\tif (entry.expiresAt && entry.expiresAt < Date.now()) {\n\t\t\tthis.cache.delete(key)\n\t\t\treturn undefined\n\t\t}\n\n\t\treturn entry.value as T\n\t}\n\n\tasync set<T>(key: string, value: T, ttlMs?: number): Promise<void> {\n\t\tconst entry: CacheEntry<T> = {\n\t\t\tvalue,\n\t\t\texpiresAt: ttlMs ? Date.now() + ttlMs : undefined,\n\t\t}\n\n\t\tthis.cache.set(key, entry)\n\t}\n\n\tasync del(key: string): Promise<void> {\n\t\tthis.cache.delete(key)\n\t}\n\n\tasync clear(): Promise<void> {\n\t\tthis.cache.clear()\n\t}\n\n\tasync has(key: string): Promise<boolean> {\n\t\tconst entry = this.cache.get(key)\n\n\t\tif (!entry) {\n\t\t\treturn false\n\t\t}\n\n\t\t// Check if expired\n\t\tif (entry.expiresAt && entry.expiresAt < Date.now()) {\n\t\t\tthis.cache.delete(key)\n\t\t\treturn false\n\t\t}\n\n\t\treturn true\n\t}\n\n\t/**\n\t * Start background cleanup of expired entries\n\t * Call this after construction to enable automatic cleanup.\n\t */\n\tstartCleanup(): void {\n\t\tif (this.cleanupTimer) return // Already running\n\n\t\tthis.cleanupTimer = setInterval(() => {\n\t\t\tconst now = Date.now()\n\t\t\tlet expired = 0\n\n\t\t\tfor (const [key, entry] of this.cache.entries()) {\n\t\t\t\tif (entry.expiresAt && entry.expiresAt < now) {\n\t\t\t\t\tthis.cache.delete(key)\n\t\t\t\t\texpired++\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Optionally log cleanup metrics\n\t\t\tif (expired > 0) {\n\t\t\t\t// console.debug(`Cache cleanup: removed ${expired} expired entries`)\n\t\t\t}\n\t\t}, this.cleanupIntervalMs)\n\t}\n\n\t/**\n\t * Stop cleanup timer\n\t */\n\tstopCleanup(): void {\n\t\tif (this.cleanupTimer) {\n\t\t\tclearInterval(this.cleanupTimer)\n\t\t\tthis.cleanupTimer = null\n\t\t}\n\t}\n\n\t/**\n\t * Stop cleanup timer (alias for stopCleanup)\n\t * @deprecated Use stopCleanup() instead\n\t */\n\tdestroy(): void {\n\t\tthis.stopCleanup()\n\t}\n}\n\n/**\n * Factory function that creates an InMemoryCacheStore with cleanup started.\n * Use this in DI container registrations.\n */\nexport function makeInMemoryCacheStore(cleanupIntervalMs = 60000): InMemoryCacheStore {\n\tconst store = new InMemoryCacheStore(cleanupIntervalMs)\n\tstore.startCleanup()\n\treturn store\n}\n"],"mappings":";;;;;;;;;AAeA,IAAa,qBAAb,MAAsD;CACrD,AAAQ,wBAAQ,IAAI,KAAkC;CACtD,AAAQ,eAAsC;CAE9C,YAAY,AAAQA,oBAA4B,KAAO;EAAnC;;CAKpB,MAAM,IAAO,KAAqC;EACjD,MAAM,QAAQ,KAAK,MAAM,IAAI,IAAI;AAEjC,MAAI,CAAC,MACJ;AAID,MAAI,MAAM,aAAa,MAAM,YAAY,KAAK,KAAK,EAAE;AACpD,QAAK,MAAM,OAAO,IAAI;AACtB;;AAGD,SAAO,MAAM;;CAGd,MAAM,IAAO,KAAa,OAAU,OAA+B;EAClE,MAAMC,QAAuB;GAC5B;GACA,WAAW,QAAQ,KAAK,KAAK,GAAG,QAAQ;GACxC;AAED,OAAK,MAAM,IAAI,KAAK,MAAM;;CAG3B,MAAM,IAAI,KAA4B;AACrC,OAAK,MAAM,OAAO,IAAI;;CAGvB,MAAM,QAAuB;AAC5B,OAAK,MAAM,OAAO;;CAGnB,MAAM,IAAI,KAA+B;EACxC,MAAM,QAAQ,KAAK,MAAM,IAAI,IAAI;AAEjC,MAAI,CAAC,MACJ,QAAO;AAIR,MAAI,MAAM,aAAa,MAAM,YAAY,KAAK,KAAK,EAAE;AACpD,QAAK,MAAM,OAAO,IAAI;AACtB,UAAO;;AAGR,SAAO;;;;;;CAOR,eAAqB;AACpB,MAAI,KAAK,aAAc;AAEvB,OAAK,eAAe,kBAAkB;GACrC,MAAM,MAAM,KAAK,KAAK;GACtB,IAAI,UAAU;AAEd,QAAK,MAAM,CAAC,KAAK,UAAU,KAAK,MAAM,SAAS,CAC9C,KAAI,MAAM,aAAa,MAAM,YAAY,KAAK;AAC7C,SAAK,MAAM,OAAO,IAAI;AACtB;;AAKF,OAAI,UAAU,GAAG;KAGf,KAAK,kBAAkB;;;;;CAM3B,cAAoB;AACnB,MAAI,KAAK,cAAc;AACtB,iBAAc,KAAK,aAAa;AAChC,QAAK,eAAe;;;;;;;CAQtB,UAAgB;AACf,OAAK,aAAa;;;;;;;AAQpB,SAAgB,uBAAuB,oBAAoB,KAA2B;CACrF,MAAM,QAAQ,IAAI,mBAAmB,kBAAkB;AACvD,OAAM,cAAc;AACpB,QAAO"}
@@ -6,6 +6,9 @@ import { CacheStore } from "@kuckit/domain";
6
6
  * In-memory cache store implementation
7
7
  * Suitable for single-process applications or development
8
8
  * For distributed systems, use Redis adapter
9
+ *
10
+ * NOTE: Call startCleanup() after construction to enable background cleanup,
11
+ * or use makeInMemoryCacheStore() factory which does this automatically.
9
12
  */
10
13
  declare class InMemoryCacheStore implements CacheStore {
11
14
  private cleanupIntervalMs;
@@ -19,13 +22,24 @@ declare class InMemoryCacheStore implements CacheStore {
19
22
  has(key: string): Promise<boolean>;
20
23
  /**
21
24
  * Start background cleanup of expired entries
25
+ * Call this after construction to enable automatic cleanup.
22
26
  */
23
- private startCleanup;
27
+ startCleanup(): void;
24
28
  /**
25
29
  * Stop cleanup timer
26
30
  */
31
+ stopCleanup(): void;
32
+ /**
33
+ * Stop cleanup timer (alias for stopCleanup)
34
+ * @deprecated Use stopCleanup() instead
35
+ */
27
36
  destroy(): void;
28
37
  }
38
+ /**
39
+ * Factory function that creates an InMemoryCacheStore with cleanup started.
40
+ * Use this in DI container registrations.
41
+ */
42
+ declare function makeInMemoryCacheStore(cleanupIntervalMs?: number): InMemoryCacheStore;
29
43
  //#endregion
30
- export { InMemoryCacheStore as t };
31
- //# sourceMappingURL=in-memory-cache-store-BaRxM--K.d.ts.map
44
+ export { makeInMemoryCacheStore as n, InMemoryCacheStore as t };
45
+ //# sourceMappingURL=in-memory-cache-store-DSdz35Ve.d.ts.map
@@ -3,13 +3,15 @@
3
3
  * In-memory rate limiter using token bucket algorithm
4
4
  * Suitable for single-process applications or development
5
5
  * For distributed systems, use Redis adapter
6
+ *
7
+ * NOTE: Call startCleanup() after construction to enable background cleanup,
8
+ * or use makeInMemoryRateLimiterStore() factory which does this automatically.
6
9
  */
7
10
  var InMemoryRateLimiterStore = class {
8
11
  buckets = /* @__PURE__ */ new Map();
9
12
  cleanupTimer = null;
10
13
  constructor(cleanupIntervalMs = 6e4) {
11
14
  this.cleanupIntervalMs = cleanupIntervalMs;
12
- this.startCleanup();
13
15
  }
14
16
  async checkLimit(key, capacity, refillPerSecond) {
15
17
  const now = Date.now();
@@ -43,8 +45,10 @@ var InMemoryRateLimiterStore = class {
43
45
  /**
44
46
  * Start background cleanup of old buckets
45
47
  * Removes buckets that haven't been used in a long time
48
+ * Call this after construction to enable automatic cleanup.
46
49
  */
47
50
  startCleanup() {
51
+ if (this.cleanupTimer) return;
48
52
  this.cleanupTimer = setInterval(() => {
49
53
  const now = Date.now();
50
54
  const maxAgeMs = 36e5;
@@ -59,14 +63,30 @@ var InMemoryRateLimiterStore = class {
59
63
  /**
60
64
  * Stop cleanup timer
61
65
  */
62
- destroy() {
66
+ stopCleanup() {
63
67
  if (this.cleanupTimer) {
64
68
  clearInterval(this.cleanupTimer);
65
69
  this.cleanupTimer = null;
66
70
  }
67
71
  }
72
+ /**
73
+ * Stop cleanup timer (alias for stopCleanup)
74
+ * @deprecated Use stopCleanup() instead
75
+ */
76
+ destroy() {
77
+ this.stopCleanup();
78
+ }
68
79
  };
80
+ /**
81
+ * Factory function that creates an InMemoryRateLimiterStore with cleanup started.
82
+ * Use this in DI container registrations.
83
+ */
84
+ function makeInMemoryRateLimiterStore(cleanupIntervalMs = 6e4) {
85
+ const store = new InMemoryRateLimiterStore(cleanupIntervalMs);
86
+ store.startCleanup();
87
+ return store;
88
+ }
69
89
 
70
90
  //#endregion
71
- export { InMemoryRateLimiterStore as t };
72
- //# sourceMappingURL=in-memory-rate-limiter-BDSHZXxf.js.map
91
+ export { makeInMemoryRateLimiterStore as n, InMemoryRateLimiterStore as t };
92
+ //# sourceMappingURL=in-memory-rate-limiter-DKOwxFD7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"in-memory-rate-limiter-DKOwxFD7.js","names":["cleanupIntervalMs: number"],"sources":["../src/rate-limiter/in-memory-rate-limiter.ts"],"sourcesContent":["import type { RateLimiterStore } from '@kuckit/domain'\n\ninterface TokenBucket {\n\ttokens: number\n\tlastRefillAt: number\n}\n\n/**\n * In-memory rate limiter using token bucket algorithm\n * Suitable for single-process applications or development\n * For distributed systems, use Redis adapter\n *\n * NOTE: Call startCleanup() after construction to enable background cleanup,\n * or use makeInMemoryRateLimiterStore() factory which does this automatically.\n */\nexport class InMemoryRateLimiterStore implements RateLimiterStore {\n\tprivate buckets = new Map<string, TokenBucket>()\n\tprivate cleanupTimer: NodeJS.Timeout | null = null\n\n\tconstructor(private cleanupIntervalMs: number = 60000) {\n\t\t// Timer is NOT started in constructor to avoid side effects on import.\n\t\t// Call startCleanup() explicitly after construction.\n\t}\n\n\tasync checkLimit(\n\t\tkey: string,\n\t\tcapacity: number,\n\t\trefillPerSecond: number\n\t): Promise<{\n\t\tallowed: boolean\n\t\ttokensRemaining: number\n\t\tresetAt: Date\n\t}> {\n\t\tconst now = Date.now()\n\t\tlet bucket = this.buckets.get(key)\n\n\t\t// Initialize bucket if not exists\n\t\tif (!bucket) {\n\t\t\tbucket = {\n\t\t\t\ttokens: capacity,\n\t\t\t\tlastRefillAt: now,\n\t\t\t}\n\t\t\tthis.buckets.set(key, bucket)\n\t\t}\n\n\t\t// Calculate refill amount based on time passed\n\t\tconst timeSinceRefillMs = now - bucket.lastRefillAt\n\t\tconst timeSinceRefillSec = timeSinceRefillMs / 1000\n\t\tconst tokensToAdd = timeSinceRefillSec * refillPerSecond\n\n\t\t// Refill tokens (capped at capacity)\n\t\tbucket.tokens = Math.min(capacity, bucket.tokens + tokensToAdd)\n\t\tbucket.lastRefillAt = now\n\n\t\t// Check if request is allowed\n\t\tconst allowed = bucket.tokens >= 1\n\n\t\tif (allowed) {\n\t\t\tbucket.tokens -= 1\n\t\t}\n\n\t\t// Calculate reset time (when we'll have 1 token again)\n\t\tconst tokensNeeded = Math.max(0, 1 - bucket.tokens)\n\t\tconst secondsToReset = tokensNeeded / refillPerSecond\n\t\tconst resetAt = new Date(now + secondsToReset * 1000)\n\n\t\treturn {\n\t\t\tallowed,\n\t\t\ttokensRemaining: Math.floor(bucket.tokens),\n\t\t\tresetAt,\n\t\t}\n\t}\n\n\tasync reset(key: string): Promise<void> {\n\t\tthis.buckets.delete(key)\n\t}\n\n\tasync clear(): Promise<void> {\n\t\tthis.buckets.clear()\n\t}\n\n\t/**\n\t * Start background cleanup of old buckets\n\t * Removes buckets that haven't been used in a long time\n\t * Call this after construction to enable automatic cleanup.\n\t */\n\tstartCleanup(): void {\n\t\tif (this.cleanupTimer) return // Already running\n\n\t\tthis.cleanupTimer = setInterval(() => {\n\t\t\tconst now = Date.now()\n\t\t\tconst maxAgeMs = 3600000 // 1 hour\n\t\t\tlet removed = 0\n\n\t\t\tfor (const [key, bucket] of this.buckets.entries()) {\n\t\t\t\tif (now - bucket.lastRefillAt > maxAgeMs) {\n\t\t\t\t\tthis.buckets.delete(key)\n\t\t\t\t\tremoved++\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Optionally log cleanup metrics\n\t\t\tif (removed > 0) {\n\t\t\t\t// console.debug(`RateLimiter cleanup: removed ${removed} old buckets`)\n\t\t\t}\n\t\t}, this.cleanupIntervalMs)\n\t}\n\n\t/**\n\t * Stop cleanup timer\n\t */\n\tstopCleanup(): void {\n\t\tif (this.cleanupTimer) {\n\t\t\tclearInterval(this.cleanupTimer)\n\t\t\tthis.cleanupTimer = null\n\t\t}\n\t}\n\n\t/**\n\t * Stop cleanup timer (alias for stopCleanup)\n\t * @deprecated Use stopCleanup() instead\n\t */\n\tdestroy(): void {\n\t\tthis.stopCleanup()\n\t}\n}\n\n/**\n * Factory function that creates an InMemoryRateLimiterStore with cleanup started.\n * Use this in DI container registrations.\n */\nexport function makeInMemoryRateLimiterStore(cleanupIntervalMs = 60000): InMemoryRateLimiterStore {\n\tconst store = new InMemoryRateLimiterStore(cleanupIntervalMs)\n\tstore.startCleanup()\n\treturn store\n}\n"],"mappings":";;;;;;;;;AAeA,IAAa,2BAAb,MAAkE;CACjE,AAAQ,0BAAU,IAAI,KAA0B;CAChD,AAAQ,eAAsC;CAE9C,YAAY,AAAQA,oBAA4B,KAAO;EAAnC;;CAKpB,MAAM,WACL,KACA,UACA,iBAKE;EACF,MAAM,MAAM,KAAK,KAAK;EACtB,IAAI,SAAS,KAAK,QAAQ,IAAI,IAAI;AAGlC,MAAI,CAAC,QAAQ;AACZ,YAAS;IACR,QAAQ;IACR,cAAc;IACd;AACD,QAAK,QAAQ,IAAI,KAAK,OAAO;;EAM9B,MAAM,eAFoB,MAAM,OAAO,gBACQ,MACN;AAGzC,SAAO,SAAS,KAAK,IAAI,UAAU,OAAO,SAAS,YAAY;AAC/D,SAAO,eAAe;EAGtB,MAAM,UAAU,OAAO,UAAU;AAEjC,MAAI,QACH,QAAO,UAAU;EAKlB,MAAM,iBADe,KAAK,IAAI,GAAG,IAAI,OAAO,OAAO,GACb;EACtC,MAAM,UAAU,IAAI,KAAK,MAAM,iBAAiB,IAAK;AAErD,SAAO;GACN;GACA,iBAAiB,KAAK,MAAM,OAAO,OAAO;GAC1C;GACA;;CAGF,MAAM,MAAM,KAA4B;AACvC,OAAK,QAAQ,OAAO,IAAI;;CAGzB,MAAM,QAAuB;AAC5B,OAAK,QAAQ,OAAO;;;;;;;CAQrB,eAAqB;AACpB,MAAI,KAAK,aAAc;AAEvB,OAAK,eAAe,kBAAkB;GACrC,MAAM,MAAM,KAAK,KAAK;GACtB,MAAM,WAAW;GACjB,IAAI,UAAU;AAEd,QAAK,MAAM,CAAC,KAAK,WAAW,KAAK,QAAQ,SAAS,CACjD,KAAI,MAAM,OAAO,eAAe,UAAU;AACzC,SAAK,QAAQ,OAAO,IAAI;AACxB;;AAKF,OAAI,UAAU,GAAG;KAGf,KAAK,kBAAkB;;;;;CAM3B,cAAoB;AACnB,MAAI,KAAK,cAAc;AACtB,iBAAc,KAAK,aAAa;AAChC,QAAK,eAAe;;;;;;;CAQtB,UAAgB;AACf,OAAK,aAAa;;;;;;;AAQpB,SAAgB,6BAA6B,oBAAoB,KAAiC;CACjG,MAAM,QAAQ,IAAI,yBAAyB,kBAAkB;AAC7D,OAAM,cAAc;AACpB,QAAO"}
@@ -6,6 +6,9 @@ import { RateLimiterStore } from "@kuckit/domain";
6
6
  * In-memory rate limiter using token bucket algorithm
7
7
  * Suitable for single-process applications or development
8
8
  * For distributed systems, use Redis adapter
9
+ *
10
+ * NOTE: Call startCleanup() after construction to enable background cleanup,
11
+ * or use makeInMemoryRateLimiterStore() factory which does this automatically.
9
12
  */
10
13
  declare class InMemoryRateLimiterStore implements RateLimiterStore {
11
14
  private cleanupIntervalMs;
@@ -22,13 +25,24 @@ declare class InMemoryRateLimiterStore implements RateLimiterStore {
22
25
  /**
23
26
  * Start background cleanup of old buckets
24
27
  * Removes buckets that haven't been used in a long time
28
+ * Call this after construction to enable automatic cleanup.
25
29
  */
26
- private startCleanup;
30
+ startCleanup(): void;
27
31
  /**
28
32
  * Stop cleanup timer
29
33
  */
34
+ stopCleanup(): void;
35
+ /**
36
+ * Stop cleanup timer (alias for stopCleanup)
37
+ * @deprecated Use stopCleanup() instead
38
+ */
30
39
  destroy(): void;
31
40
  }
41
+ /**
42
+ * Factory function that creates an InMemoryRateLimiterStore with cleanup started.
43
+ * Use this in DI container registrations.
44
+ */
45
+ declare function makeInMemoryRateLimiterStore(cleanupIntervalMs?: number): InMemoryRateLimiterStore;
32
46
  //#endregion
33
- export { InMemoryRateLimiterStore as t };
34
- //# sourceMappingURL=in-memory-rate-limiter-DJsxdZZR.d.ts.map
47
+ export { makeInMemoryRateLimiterStore as n, InMemoryRateLimiterStore as t };
48
+ //# sourceMappingURL=in-memory-rate-limiter-DZqM4MOS.d.ts.map
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { t as InMemoryCacheStore } from "./in-memory-cache-store-BaRxM--K.js";
1
+ import { n as makeInMemoryCacheStore, t as InMemoryCacheStore } from "./in-memory-cache-store-DSdz35Ve.js";
2
2
  import { t as CacheStore } from "./index-C6nYd7xV.js";
3
3
  import { n as createDbPool, t as createDb } from "./db-tAPHBDyL.js";
4
4
  import { t as makeDrizzleUserRepository } from "./user.drizzle-9kkstnkV.js";
@@ -17,13 +17,13 @@ import { t as makeEventPublisherAdapter } from "./event-publisher-adapter-CpxK0O
17
17
  import { t as InMemoryEventBus } from "./in-memory-event-bus-CqIBLRze.js";
18
18
  import { t as makeInMemoryEventPublisher } from "./in-memory-event-publisher-CxOQ-hnq.js";
19
19
  import "./index-C0yeuOwC.js";
20
- import { n as makeStructuredLogger, t as StructuredLogger } from "./structured-logger-Dz06Uz-u.js";
20
+ import { n as StructuredLogger, r as makeStructuredLogger, t as LogLevel } from "./structured-logger-DyrZwR3S.js";
21
21
  import { n as makeRequestLogger, t as RequestLoggerOptions } from "./request-logger-CK3SOnoz.js";
22
22
  import "./index-DVGDAddE.js";
23
- import { t as InMemoryRateLimiterStore } from "./in-memory-rate-limiter-DJsxdZZR.js";
23
+ import { n as makeInMemoryRateLimiterStore, t as InMemoryRateLimiterStore } from "./in-memory-rate-limiter-DZqM4MOS.js";
24
24
  import { t as RateLimiterStore } from "./index-BH67NKRs.js";
25
- import { n as Cradle, t as Config } from "./types-65aFqB5L.js";
26
- import { t as registerCoreModule } from "./core.module-B1TdC0yX.js";
27
- import { t as registerUserModule } from "./user.module-D3lVJ98T.js";
25
+ import { n as Cradle, t as Config } from "./types-BnE7rffD.js";
26
+ import { t as registerCoreModule } from "./core.module-_mfoxc8b.js";
27
+ import { t as registerUserModule } from "./user.module-DqTfy_MM.js";
28
28
  import "./index-B7z6dpFd.js";
29
- export { CacheStore, type Config, type Cradle, DecoratorContext, ErrorHandler, InMemoryCacheStore, InMemoryEventBus, InMemoryRateLimiterStore, PerformanceMetrics, RateLimitError, RateLimiterStore, RequestLoggerOptions, SerializedError, StructuredLogger, type TransactionFn, UseCase, WithCachingOptions, WithRateLimitOptions, WithRetryOptions, applyDecorators, createDb, createDbPool, decorateUseCase, makeDecoratedUseCase, makeDrizzleUserRepository, makeErrorHandler, makeEventPublisherAdapter, makeInMemoryEventPublisher, makeRequestLogger, makeStructuredLogger, registerCoreModule, registerUserModule, runInTransaction, withCaching, withErrorHandling, withPerformanceMonitoring, withRateLimit, withRequestTracing, withRetry };
29
+ export { CacheStore, type Config, type Cradle, DecoratorContext, ErrorHandler, InMemoryCacheStore, InMemoryEventBus, InMemoryRateLimiterStore, LogLevel, PerformanceMetrics, RateLimitError, RateLimiterStore, RequestLoggerOptions, SerializedError, StructuredLogger, type TransactionFn, UseCase, WithCachingOptions, WithRateLimitOptions, WithRetryOptions, applyDecorators, createDb, createDbPool, decorateUseCase, makeDecoratedUseCase, makeDrizzleUserRepository, makeErrorHandler, makeEventPublisherAdapter, makeInMemoryCacheStore, makeInMemoryEventPublisher, makeInMemoryRateLimiterStore, makeRequestLogger, makeStructuredLogger, registerCoreModule, registerUserModule, runInTransaction, withCaching, withErrorHandling, withPerformanceMonitoring, withRateLimit, withRequestTracing, withRetry };
package/dist/index.js CHANGED
@@ -12,9 +12,9 @@ import { t as InMemoryEventBus } from "./in-memory-event-bus-BCyPrNAE.js";
12
12
  import { t as makeEventPublisherAdapter } from "./event-publisher-adapter-B02oKEmP.js";
13
13
  import { t as makeInMemoryEventPublisher } from "./in-memory-event-publisher-BdOlxfkx.js";
14
14
  import "./events-Dqynhuj2.js";
15
- import { t as InMemoryCacheStore } from "./in-memory-cache-store-oClww-8m.js";
15
+ import { n as makeInMemoryCacheStore, t as InMemoryCacheStore } from "./in-memory-cache-store-BA-Eqsf0.js";
16
16
  import "./cache-BjdZ-Ye4.js";
17
- import { t as InMemoryRateLimiterStore } from "./in-memory-rate-limiter-BDSHZXxf.js";
17
+ import { n as makeInMemoryRateLimiterStore, t as InMemoryRateLimiterStore } from "./in-memory-rate-limiter-DKOwxFD7.js";
18
18
  import "./rate-limiter-BnvPGJOK.js";
19
19
  import { a as withRequestTracing, i as withPerformanceMonitoring, n as makeDecoratedUseCase, r as withErrorHandling, t as decorateUseCase } from "./use-case-decorator-GmDeYViz.js";
20
20
  import { t as applyDecorators } from "./apply-decorators-CaHIAL5X.js";
@@ -22,8 +22,8 @@ import { t as withCaching } from "./with-caching-NmBxu7vJ.js";
22
22
  import { t as withRetry } from "./with-retry-coyYPiX1.js";
23
23
  import { n as withRateLimit, t as RateLimitError } from "./with-rate-limit-Cp2V1RHn.js";
24
24
  import "./decorators-CqyPE9AQ.js";
25
- import { t as registerCoreModule } from "./core.module-DMtIkTcz.js";
25
+ import { t as registerCoreModule } from "./core.module-ehJ0bdNr.js";
26
26
  import { t as registerUserModule } from "./user.module-BEpCbKsU.js";
27
27
  import "./modules-C_2SF3he.js";
28
28
 
29
- export { ErrorHandler, InMemoryCacheStore, InMemoryEventBus, InMemoryRateLimiterStore, RateLimitError, StructuredLogger, applyDecorators, createDb, createDbPool, decorateUseCase, makeDecoratedUseCase, makeDrizzleUserRepository, makeErrorHandler, makeEventPublisherAdapter, makeInMemoryEventPublisher, makeRequestLogger, makeStructuredLogger, registerCoreModule, registerUserModule, runInTransaction, withCaching, withErrorHandling, withPerformanceMonitoring, withRateLimit, withRequestTracing, withRetry };
29
+ export { ErrorHandler, InMemoryCacheStore, InMemoryEventBus, InMemoryRateLimiterStore, RateLimitError, StructuredLogger, applyDecorators, createDb, createDbPool, decorateUseCase, makeDecoratedUseCase, makeDrizzleUserRepository, makeErrorHandler, makeEventPublisherAdapter, makeInMemoryCacheStore, makeInMemoryEventPublisher, makeInMemoryRateLimiterStore, makeRequestLogger, makeStructuredLogger, registerCoreModule, registerUserModule, runInTransaction, withCaching, withErrorHandling, withPerformanceMonitoring, withRateLimit, withRequestTracing, withRetry };
@@ -1,5 +1,5 @@
1
1
  import "../logger-Bl10drB8.js";
2
- import { n as makeStructuredLogger, t as StructuredLogger } from "../structured-logger-Dz06Uz-u.js";
2
+ import { n as StructuredLogger, r as makeStructuredLogger, t as LogLevel } from "../structured-logger-DyrZwR3S.js";
3
3
  import { n as makeRequestLogger, t as RequestLoggerOptions } from "../request-logger-CK3SOnoz.js";
4
4
  import "../index-DVGDAddE.js";
5
- export { RequestLoggerOptions, StructuredLogger, makeRequestLogger, makeStructuredLogger };
5
+ export { LogLevel, RequestLoggerOptions, StructuredLogger, makeRequestLogger, makeStructuredLogger };
@@ -1,3 +1,3 @@
1
1
  import "../logger-Bl10drB8.js";
2
- import { n as makeStructuredLogger, t as StructuredLogger } from "../structured-logger-Dz06Uz-u.js";
3
- export { StructuredLogger, makeStructuredLogger };
2
+ import { n as StructuredLogger, r as makeStructuredLogger, t as LogLevel } from "../structured-logger-DyrZwR3S.js";
3
+ export { LogLevel, StructuredLogger, makeStructuredLogger };
@@ -2,9 +2,9 @@ import "../db-tAPHBDyL.js";
2
2
  import "../logger-Bl10drB8.js";
3
3
  import "../error-handler-BDid7SIZ.js";
4
4
  import "../index-LKrIp3Oo.js";
5
- import "../structured-logger-Dz06Uz-u.js";
5
+ import "../structured-logger-DyrZwR3S.js";
6
6
  import "../request-logger-CK3SOnoz.js";
7
7
  import "../index-DVGDAddE.js";
8
- import "../types-65aFqB5L.js";
9
- import { t as registerCoreModule } from "../core.module-B1TdC0yX.js";
8
+ import "../types-BnE7rffD.js";
9
+ import { t as registerCoreModule } from "../core.module-_mfoxc8b.js";
10
10
  export { registerCoreModule };
@@ -6,8 +6,8 @@ import "../errors-BB_jeye8.js";
6
6
  import "../error-handler-D4s_TTI1.js";
7
7
  import "../errors-DfkerzdO.js";
8
8
  import "../in-memory-event-bus-BCyPrNAE.js";
9
- import "../in-memory-cache-store-oClww-8m.js";
10
- import "../in-memory-rate-limiter-BDSHZXxf.js";
11
- import { t as registerCoreModule } from "../core.module-DMtIkTcz.js";
9
+ import "../in-memory-cache-store-BA-Eqsf0.js";
10
+ import "../in-memory-rate-limiter-DKOwxFD7.js";
11
+ import { t as registerCoreModule } from "../core.module-ehJ0bdNr.js";
12
12
 
13
13
  export { registerCoreModule };
@@ -2,11 +2,11 @@ import "../db-tAPHBDyL.js";
2
2
  import "../logger-Bl10drB8.js";
3
3
  import "../error-handler-BDid7SIZ.js";
4
4
  import "../index-LKrIp3Oo.js";
5
- import "../structured-logger-Dz06Uz-u.js";
5
+ import "../structured-logger-DyrZwR3S.js";
6
6
  import "../request-logger-CK3SOnoz.js";
7
7
  import "../index-DVGDAddE.js";
8
- import { n as Cradle, t as Config } from "../types-65aFqB5L.js";
9
- import { t as registerCoreModule } from "../core.module-B1TdC0yX.js";
10
- import { t as registerUserModule } from "../user.module-D3lVJ98T.js";
8
+ import { n as Cradle, t as Config } from "../types-BnE7rffD.js";
9
+ import { t as registerCoreModule } from "../core.module-_mfoxc8b.js";
10
+ import { t as registerUserModule } from "../user.module-DqTfy_MM.js";
11
11
  import "../index-B7z6dpFd.js";
12
12
  export { Config, Cradle, registerCoreModule, registerUserModule };
@@ -7,9 +7,9 @@ import "../errors-BB_jeye8.js";
7
7
  import "../error-handler-D4s_TTI1.js";
8
8
  import "../errors-DfkerzdO.js";
9
9
  import "../in-memory-event-bus-BCyPrNAE.js";
10
- import "../in-memory-cache-store-oClww-8m.js";
11
- import "../in-memory-rate-limiter-BDSHZXxf.js";
12
- import { t as registerCoreModule } from "../core.module-DMtIkTcz.js";
10
+ import "../in-memory-cache-store-BA-Eqsf0.js";
11
+ import "../in-memory-rate-limiter-DKOwxFD7.js";
12
+ import { t as registerCoreModule } from "../core.module-ehJ0bdNr.js";
13
13
  import { t as registerUserModule } from "../user.module-BEpCbKsU.js";
14
14
  import "../modules-C_2SF3he.js";
15
15
 
@@ -2,8 +2,8 @@ import "../db-tAPHBDyL.js";
2
2
  import "../logger-Bl10drB8.js";
3
3
  import "../error-handler-BDid7SIZ.js";
4
4
  import "../index-LKrIp3Oo.js";
5
- import "../structured-logger-Dz06Uz-u.js";
5
+ import "../structured-logger-DyrZwR3S.js";
6
6
  import "../request-logger-CK3SOnoz.js";
7
7
  import "../index-DVGDAddE.js";
8
- import { n as Cradle, t as Config } from "../types-65aFqB5L.js";
8
+ import { n as Cradle, t as Config } from "../types-BnE7rffD.js";
9
9
  export { Config, Cradle };
@@ -1,6 +1,5 @@
1
1
  import "../db-C4IcCT04.js";
2
2
  import { Pool } from "pg";
3
3
  import { google } from "@ai-sdk/google";
4
- import { auth } from "@kuckit/auth";
5
4
 
6
5
  export { };
@@ -2,9 +2,9 @@ import "../db-tAPHBDyL.js";
2
2
  import "../logger-Bl10drB8.js";
3
3
  import "../error-handler-BDid7SIZ.js";
4
4
  import "../index-LKrIp3Oo.js";
5
- import "../structured-logger-Dz06Uz-u.js";
5
+ import "../structured-logger-DyrZwR3S.js";
6
6
  import "../request-logger-CK3SOnoz.js";
7
7
  import "../index-DVGDAddE.js";
8
- import "../types-65aFqB5L.js";
9
- import { t as registerUserModule } from "../user.module-D3lVJ98T.js";
8
+ import "../types-BnE7rffD.js";
9
+ import { t as registerUserModule } from "../user.module-DqTfy_MM.js";
10
10
  export { registerUserModule };
@@ -1,2 +1,2 @@
1
- import { t as InMemoryRateLimiterStore } from "../in-memory-rate-limiter-DJsxdZZR.js";
2
- export { InMemoryRateLimiterStore };
1
+ import { n as makeInMemoryRateLimiterStore, t as InMemoryRateLimiterStore } from "../in-memory-rate-limiter-DZqM4MOS.js";
2
+ export { InMemoryRateLimiterStore, makeInMemoryRateLimiterStore };
@@ -1,3 +1,3 @@
1
- import { t as InMemoryRateLimiterStore } from "../in-memory-rate-limiter-BDSHZXxf.js";
1
+ import { n as makeInMemoryRateLimiterStore, t as InMemoryRateLimiterStore } from "../in-memory-rate-limiter-DKOwxFD7.js";
2
2
 
3
- export { InMemoryRateLimiterStore };
3
+ export { InMemoryRateLimiterStore, makeInMemoryRateLimiterStore };
@@ -1,3 +1,3 @@
1
- import { t as InMemoryRateLimiterStore } from "../in-memory-rate-limiter-DJsxdZZR.js";
1
+ import { n as makeInMemoryRateLimiterStore, t as InMemoryRateLimiterStore } from "../in-memory-rate-limiter-DZqM4MOS.js";
2
2
  import { t as RateLimiterStore } from "../index-BH67NKRs.js";
3
- export { InMemoryRateLimiterStore, RateLimiterStore };
3
+ export { InMemoryRateLimiterStore, RateLimiterStore, makeInMemoryRateLimiterStore };
@@ -1,4 +1,4 @@
1
- import { t as InMemoryRateLimiterStore } from "../in-memory-rate-limiter-BDSHZXxf.js";
1
+ import { n as makeInMemoryRateLimiterStore, t as InMemoryRateLimiterStore } from "../in-memory-rate-limiter-DKOwxFD7.js";
2
2
  import "../rate-limiter-BnvPGJOK.js";
3
3
 
4
- export { InMemoryRateLimiterStore };
4
+ export { InMemoryRateLimiterStore, makeInMemoryRateLimiterStore };
@@ -1 +1 @@
1
- {"version":3,"file":"structured-logger-BsxDI9zX.js","names":["options: {\n\t\t\tlogDir?: string\n\t\t\tenableFile?: boolean\n\t\t\tminLevel?: LogLevel\n\t\t}","levels: LogLevel[]","logObject: Record<string, any>","lines: string[]"],"sources":["../src/logging/structured-logger.ts"],"sourcesContent":["import { createWriteStream, existsSync, mkdirSync } from 'fs'\nimport path from 'path'\nimport type { Logger, LogContext } from '../../../domain/src/ports/logger'\n\ntype LogLevel = 'DEBUG' | 'INFO' | 'WARN' | 'ERROR'\n\n/**\n * Structured logger implementation\n * - JSON logs compatible with Loki\n * - File + stdout support\n * - Prometheus metrics collection\n */\nexport class StructuredLogger implements Logger {\n\tprivate fileStream: ReturnType<typeof createWriteStream> | null = null\n\tprivate metrics: MetricsCollector\n\n\tconstructor(\n\t\tprivate options: {\n\t\t\tlogDir?: string\n\t\t\tenableFile?: boolean\n\t\t\tminLevel?: LogLevel\n\t\t} = {}\n\t) {\n\t\tthis.metrics = new MetricsCollector()\n\n\t\tif (options.enableFile && options.logDir) {\n\t\t\tthis.initFileStream(options.logDir)\n\t\t}\n\t}\n\n\tprivate initFileStream(logDir: string): void {\n\t\tif (!existsSync(logDir)) {\n\t\t\tmkdirSync(logDir, { recursive: true })\n\t\t}\n\n\t\tconst logFile = path.join(logDir, `app-${new Date().toISOString().split('T')[0]}.log`)\n\t\tthis.fileStream = createWriteStream(logFile, { flags: 'a' })\n\t}\n\n\tdebug(message: string, meta?: LogContext): void {\n\t\tthis.log('DEBUG', message, meta)\n\t}\n\n\tinfo(message: string, meta?: LogContext): void {\n\t\tthis.log('INFO', message, meta)\n\t}\n\n\twarn(message: string, meta?: LogContext): void {\n\t\tthis.log('WARN', message, meta)\n\t}\n\n\terror(message: string, meta?: LogContext | Error): void {\n\t\tconst context = meta instanceof Error ? { error: meta.message, stack: meta.stack } : meta\n\t\tthis.log('ERROR', message, context)\n\t}\n\n\tprivate log(level: LogLevel, message: string, meta?: any): void {\n\t\tif (this.shouldSkip(level)) return\n\n\t\tconst timestamp = new Date().toISOString()\n\t\tconst logEntry = this.formatLog(level, message, meta, timestamp)\n\n\t\t// stdout\n\t\tconsole.log(logEntry)\n\n\t\t// file\n\t\tif (this.fileStream) {\n\t\t\tthis.fileStream.write(logEntry + '\\n')\n\t\t}\n\n\t\t// metrics\n\t\tthis.metrics.recordLog(level, meta?.feature)\n\t}\n\n\tprivate shouldSkip(level: LogLevel): boolean {\n\t\tconst levels: LogLevel[] = ['DEBUG', 'INFO', 'WARN', 'ERROR']\n\t\tconst minLevel = this.options.minLevel || 'DEBUG'\n\t\treturn levels.indexOf(level) < levels.indexOf(minLevel)\n\t}\n\n\tprivate formatLog(level: LogLevel, message: string, meta: any, timestamp: string): string {\n\t\tconst logObject: Record<string, any> = {\n\t\t\ttimestamp,\n\t\t\tlevel,\n\t\t\tmessage,\n\t\t\t...meta,\n\t\t}\n\n\t\t// Loki labels (structured fields at root level)\n\t\tif (meta?.requestId) logObject.requestId = meta.requestId\n\t\tif (meta?.userId) logObject.userId = meta.userId\n\t\tif (meta?.feature) logObject.feature = meta.feature\n\n\t\treturn JSON.stringify(logObject)\n\t}\n\n\t/**\n\t * Get metrics in Prometheus text format\n\t */\n\tgetMetrics(): string {\n\t\treturn this.metrics.toPrometheusFormat()\n\t}\n\n\t/**\n\t * Cleanup resources\n\t */\n\tasync dispose(): Promise<void> {\n\t\treturn new Promise((resolve) => {\n\t\t\tif (this.fileStream) {\n\t\t\t\tthis.fileStream.end(() => resolve())\n\t\t\t} else {\n\t\t\t\tresolve()\n\t\t\t}\n\t\t})\n\t}\n}\n\n/**\n * Prometheus metrics collector\n */\nclass MetricsCollector {\n\tprivate logCount: Map<LogLevel, number> = new Map([\n\t\t['DEBUG', 0],\n\t\t['INFO', 0],\n\t\t['WARN', 0],\n\t\t['ERROR', 0],\n\t])\n\tprivate featureCount: Map<string, number> = new Map()\n\n\trecordLog(level: LogLevel, feature?: string): void {\n\t\tthis.logCount.set(level, (this.logCount.get(level) || 0) + 1)\n\t\tif (feature) {\n\t\t\tthis.featureCount.set(feature, (this.featureCount.get(feature) || 0) + 1)\n\t\t}\n\t}\n\n\ttoPrometheusFormat(): string {\n\t\tconst lines: string[] = [\n\t\t\t'# HELP app_logs_total Total number of logs by level',\n\t\t\t'# TYPE app_logs_total counter',\n\t\t]\n\n\t\t// Log counters by level\n\t\tfor (const [level, count] of this.logCount) {\n\t\t\tlines.push(`app_logs_total{level=\"${level}\"} ${count}`)\n\t\t}\n\n\t\tlines.push('')\n\t\tlines.push('# HELP app_feature_logs_total Total logs by feature')\n\t\tlines.push('# TYPE app_feature_logs_total counter')\n\n\t\t// Log counters by feature\n\t\tfor (const [feature, count] of this.featureCount) {\n\t\t\tlines.push(`app_feature_logs_total{feature=\"${feature}\"} ${count}`)\n\t\t}\n\n\t\treturn lines.join('\\n')\n\t}\n}\n\n/**\n * Create logger instance\n */\nexport const makeStructuredLogger = (options?: {\n\tlogDir?: string\n\tenableFile?: boolean\n\tminLevel?: LogLevel\n}): StructuredLogger => {\n\treturn new StructuredLogger(options)\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"structured-logger-BsxDI9zX.js","names":["options: {\n\t\t\tlogDir?: string\n\t\t\tenableFile?: boolean\n\t\t\tminLevel?: LogLevel\n\t\t}","levels: LogLevel[]","logObject: Record<string, unknown>","lines: string[]"],"sources":["../src/logging/structured-logger.ts"],"sourcesContent":["import { createWriteStream, existsSync, mkdirSync } from 'fs'\nimport path from 'path'\nimport type { Logger, LogContext } from '../../../domain/src/ports/logger'\n\nexport type LogLevel = 'DEBUG' | 'INFO' | 'WARN' | 'ERROR'\n\n/**\n * Structured logger implementation\n * - JSON logs compatible with Loki\n * - File + stdout support\n * - Prometheus metrics collection\n */\nexport class StructuredLogger implements Logger {\n\tprivate fileStream: ReturnType<typeof createWriteStream> | null = null\n\tprivate metrics: MetricsCollector\n\n\tconstructor(\n\t\tprivate options: {\n\t\t\tlogDir?: string\n\t\t\tenableFile?: boolean\n\t\t\tminLevel?: LogLevel\n\t\t} = {}\n\t) {\n\t\tthis.metrics = new MetricsCollector()\n\n\t\tif (options.enableFile && options.logDir) {\n\t\t\tthis.initFileStream(options.logDir)\n\t\t}\n\t}\n\n\tprivate initFileStream(logDir: string): void {\n\t\tif (!existsSync(logDir)) {\n\t\t\tmkdirSync(logDir, { recursive: true })\n\t\t}\n\n\t\tconst logFile = path.join(logDir, `app-${new Date().toISOString().split('T')[0]}.log`)\n\t\tthis.fileStream = createWriteStream(logFile, { flags: 'a' })\n\t}\n\n\tdebug(message: string, meta?: LogContext): void {\n\t\tthis.log('DEBUG', message, meta)\n\t}\n\n\tinfo(message: string, meta?: LogContext): void {\n\t\tthis.log('INFO', message, meta)\n\t}\n\n\twarn(message: string, meta?: LogContext): void {\n\t\tthis.log('WARN', message, meta)\n\t}\n\n\terror(message: string, meta?: LogContext | Error): void {\n\t\tconst context = meta instanceof Error ? { error: meta.message, stack: meta.stack } : meta\n\t\tthis.log('ERROR', message, context)\n\t}\n\n\tprivate log(level: LogLevel, message: string, meta?: LogContext): void {\n\t\tif (this.shouldSkip(level)) return\n\n\t\tconst timestamp = new Date().toISOString()\n\t\tconst logEntry = this.formatLog(level, message, meta, timestamp)\n\n\t\t// stdout\n\t\tconsole.log(logEntry)\n\n\t\t// file\n\t\tif (this.fileStream) {\n\t\t\tthis.fileStream.write(logEntry + '\\n')\n\t\t}\n\n\t\t// metrics\n\t\tthis.metrics.recordLog(level, meta?.feature)\n\t}\n\n\tprivate shouldSkip(level: LogLevel): boolean {\n\t\tconst levels: LogLevel[] = ['DEBUG', 'INFO', 'WARN', 'ERROR']\n\t\tconst minLevel = this.options.minLevel || 'DEBUG'\n\t\treturn levels.indexOf(level) < levels.indexOf(minLevel)\n\t}\n\n\tprivate formatLog(\n\t\tlevel: LogLevel,\n\t\tmessage: string,\n\t\tmeta: LogContext | undefined,\n\t\ttimestamp: string\n\t): string {\n\t\tconst logObject: Record<string, unknown> = {\n\t\t\ttimestamp,\n\t\t\tlevel,\n\t\t\tmessage,\n\t\t\t...meta,\n\t\t}\n\n\t\t// Loki labels (structured fields at root level)\n\t\tif (meta?.requestId) logObject.requestId = meta.requestId\n\t\tif (meta?.userId) logObject.userId = meta.userId\n\t\tif (meta?.feature) logObject.feature = meta.feature\n\n\t\treturn JSON.stringify(logObject)\n\t}\n\n\t/**\n\t * Get metrics in Prometheus text format\n\t */\n\tgetMetrics(): string {\n\t\treturn this.metrics.toPrometheusFormat()\n\t}\n\n\t/**\n\t * Cleanup resources\n\t */\n\tasync dispose(): Promise<void> {\n\t\treturn new Promise((resolve) => {\n\t\t\tif (this.fileStream) {\n\t\t\t\tthis.fileStream.end(() => resolve())\n\t\t\t} else {\n\t\t\t\tresolve()\n\t\t\t}\n\t\t})\n\t}\n}\n\n/**\n * Prometheus metrics collector\n */\nclass MetricsCollector {\n\tprivate logCount: Map<LogLevel, number> = new Map([\n\t\t['DEBUG', 0],\n\t\t['INFO', 0],\n\t\t['WARN', 0],\n\t\t['ERROR', 0],\n\t])\n\tprivate featureCount: Map<string, number> = new Map()\n\n\trecordLog(level: LogLevel, feature?: string): void {\n\t\tthis.logCount.set(level, (this.logCount.get(level) || 0) + 1)\n\t\tif (feature) {\n\t\t\tthis.featureCount.set(feature, (this.featureCount.get(feature) || 0) + 1)\n\t\t}\n\t}\n\n\ttoPrometheusFormat(): string {\n\t\tconst lines: string[] = [\n\t\t\t'# HELP app_logs_total Total number of logs by level',\n\t\t\t'# TYPE app_logs_total counter',\n\t\t]\n\n\t\t// Log counters by level\n\t\tfor (const [level, count] of this.logCount) {\n\t\t\tlines.push(`app_logs_total{level=\"${level}\"} ${count}`)\n\t\t}\n\n\t\tlines.push('')\n\t\tlines.push('# HELP app_feature_logs_total Total logs by feature')\n\t\tlines.push('# TYPE app_feature_logs_total counter')\n\n\t\t// Log counters by feature\n\t\tfor (const [feature, count] of this.featureCount) {\n\t\t\tlines.push(`app_feature_logs_total{feature=\"${feature}\"} ${count}`)\n\t\t}\n\n\t\treturn lines.join('\\n')\n\t}\n}\n\n/**\n * Create logger instance\n */\nexport const makeStructuredLogger = (options?: {\n\tlogDir?: string\n\tenableFile?: boolean\n\tminLevel?: LogLevel\n}): StructuredLogger => {\n\treturn new StructuredLogger(options)\n}\n"],"mappings":"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"}
@@ -43,5 +43,5 @@ declare const makeStructuredLogger: (options?: {
43
43
  minLevel?: LogLevel;
44
44
  }) => StructuredLogger;
45
45
  //#endregion
46
- export { makeStructuredLogger as n, StructuredLogger as t };
47
- //# sourceMappingURL=structured-logger-Dz06Uz-u.d.ts.map
46
+ export { StructuredLogger as n, makeStructuredLogger as r, LogLevel as t };
47
+ //# sourceMappingURL=structured-logger-DyrZwR3S.d.ts.map
@@ -1,10 +1,10 @@
1
1
  import { t as createDb } from "./db-tAPHBDyL.js";
2
2
  import { t as ErrorHandler } from "./error-handler-BDid7SIZ.js";
3
- import { t as StructuredLogger } from "./structured-logger-Dz06Uz-u.js";
3
+ import { n as StructuredLogger } from "./structured-logger-DyrZwR3S.js";
4
4
  import { Pool } from "pg";
5
5
  import { CacheStore, Clock, EventBus, EventPublisher, Logger, RateLimiterStore, User, UserRepository } from "@kuckit/domain";
6
6
  import { google } from "@ai-sdk/google";
7
- import { auth } from "@kuckit/auth";
7
+ import { Auth } from "@kuckit/auth";
8
8
 
9
9
  //#region src/modules/types.d.ts
10
10
 
@@ -31,7 +31,7 @@ interface Cradle {
31
31
  clock: Clock;
32
32
  logger: Logger & StructuredLogger;
33
33
  errorHandler: ErrorHandler;
34
- auth: typeof auth;
34
+ auth: Auth;
35
35
  aiProvider: ReturnType<typeof google>;
36
36
  eventBus: EventBus;
37
37
  cacheStore: CacheStore;
@@ -53,10 +53,14 @@ interface Cradle {
53
53
  emailVerified: boolean;
54
54
  }) => Promise<User>;
55
55
  eventPublisher: EventPublisher;
56
- session?: any;
56
+ session?: {
57
+ user?: {
58
+ id?: string;
59
+ };
60
+ } | null;
57
61
  requestId: string;
58
62
  requestLogger: Logger;
59
63
  }
60
64
  //#endregion
61
65
  export { Cradle as n, Config as t };
62
- //# sourceMappingURL=types-65aFqB5L.d.ts.map
66
+ //# sourceMappingURL=types-BnE7rffD.d.ts.map
@@ -1,4 +1,4 @@
1
- import { n as Cradle } from "./types-65aFqB5L.js";
1
+ import { n as Cradle } from "./types-BnE7rffD.js";
2
2
  import { AwilixContainer } from "awilix";
3
3
 
4
4
  //#region src/modules/user.module.d.ts
@@ -12,4 +12,4 @@ import { AwilixContainer } from "awilix";
12
12
  declare const registerUserModule: (container: AwilixContainer<Cradle>) => void;
13
13
  //#endregion
14
14
  export { registerUserModule as t };
15
- //# sourceMappingURL=user.module-D3lVJ98T.d.ts.map
15
+ //# sourceMappingURL=user.module-DqTfy_MM.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kuckit/infrastructure",
3
- "version": "2.0.0",
3
+ "version": "2.0.1",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -22,9 +22,9 @@
22
22
  "prepublishOnly": "npm run build && node ../../scripts/resolve-workspace-protocols.cjs && node ../../scripts/check-no-workspace-protocol.cjs"
23
23
  },
24
24
  "dependencies": {
25
- "@kuckit/domain": "^2.0.0",
26
- "@kuckit/db": "^2.0.0",
27
- "@kuckit/auth": "^2.0.0",
25
+ "@kuckit/domain": "^2.0.1",
26
+ "@kuckit/db": "^2.0.1",
27
+ "@kuckit/auth": "^2.0.1",
28
28
  "@ai-sdk/google": "^2.0.13",
29
29
  "awilix": "^10.0.2",
30
30
  "drizzle-orm": "^0.44.2",
@@ -1 +0,0 @@
1
- {"version":3,"file":"core.module-DMtIkTcz.js","names":[],"sources":["../src/modules/core.module.ts"],"sourcesContent":["import { asClass, asFunction, asValue, type AwilixContainer } from 'awilix'\nimport { SystemClock } from '@kuckit/domain/ports/clock'\nimport { google } from '@ai-sdk/google'\nimport { auth } from '@kuckit/auth'\nimport { createDbPool, createDb } from '../db/drizzle/db'\nimport { makeStructuredLogger, makeRequestLogger } from '../logging'\nimport { makeErrorHandler } from '../errors'\nimport { InMemoryEventBus } from '../events/in-memory-event-bus'\nimport { InMemoryCacheStore } from '../cache/in-memory-cache-store'\nimport { InMemoryRateLimiterStore } from '../rate-limiter/in-memory-rate-limiter'\nimport type { Cradle } from './types'\n\n/**\n * Core module: singleton registrations for infrastructure\n * - Database pool and connection\n * - Clock\n * - Logger (structured, Loki/Prometheus compatible)\n * - AI provider\n * - Auth\n */\nexport const registerCoreModule = (container: AwilixContainer<Cradle>): void => {\n\tcontainer.register({\n\t\t// Database\n\t\tdbPool: asFunction(({ config }) => createDbPool(config.databaseUrl)).singleton(),\n\n\t\tdb: asFunction(({ dbPool }) => createDb(dbPool)).singleton(),\n\n\t\t// Core services\n\t\tclock: asValue(new SystemClock()),\n\n\t\tlogger: asFunction(({ config }) =>\n\t\t\tmakeStructuredLogger({\n\t\t\t\tenableFile: config.enableFileLogging,\n\t\t\t\tlogDir: config.logDir,\n\t\t\t\tminLevel: config.logLevel as any,\n\t\t\t})\n\t\t).singleton(),\n\n\t\terrorHandler: asFunction(({ logger }) => makeErrorHandler(logger)).singleton(),\n\n\t\t// External integrations\n\t\tauth: asValue(auth),\n\n\t\taiProvider: asFunction(() => google('gemini-2.5-flash')).singleton(),\n\n\t\t// Event bus\n\t\teventBus: asFunction(({ logger }) => new InMemoryEventBus(logger)).singleton(),\n\n\t\t// Cache store\n\t\tcacheStore: asClass(InMemoryCacheStore).singleton(),\n\n\t\t// Rate limiter store\n\t\trateLimiterStore: asClass(InMemoryRateLimiterStore).singleton(),\n\n\t\t// Request-scoped logger (enriched with requestId and userId)\n\t\trequestLogger: asFunction(({ logger, requestId, session }) =>\n\t\t\tmakeRequestLogger({\n\t\t\t\trequestId,\n\t\t\t\tuserId: session?.user?.id,\n\t\t\t\tbaseLogger: logger,\n\t\t\t})\n\t\t).scoped(),\n\t})\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAoBA,MAAa,sBAAsB,cAA6C;AAC/E,WAAU,SAAS;EAElB,QAAQ,YAAY,EAAE,aAAa,aAAa,OAAO,YAAY,CAAC,CAAC,WAAW;EAEhF,IAAI,YAAY,EAAE,aAAa,SAAS,OAAO,CAAC,CAAC,WAAW;EAG5D,OAAO,QAAQ,IAAI,aAAa,CAAC;EAEjC,QAAQ,YAAY,EAAE,aACrB,qBAAqB;GACpB,YAAY,OAAO;GACnB,QAAQ,OAAO;GACf,UAAU,OAAO;GACjB,CAAC,CACF,CAAC,WAAW;EAEb,cAAc,YAAY,EAAE,aAAa,iBAAiB,OAAO,CAAC,CAAC,WAAW;EAG9E,MAAM,QAAQ,KAAK;EAEnB,YAAY,iBAAiB,OAAO,mBAAmB,CAAC,CAAC,WAAW;EAGpE,UAAU,YAAY,EAAE,aAAa,IAAI,iBAAiB,OAAO,CAAC,CAAC,WAAW;EAG9E,YAAY,QAAQ,mBAAmB,CAAC,WAAW;EAGnD,kBAAkB,QAAQ,yBAAyB,CAAC,WAAW;EAG/D,eAAe,YAAY,EAAE,QAAQ,WAAW,cAC/C,kBAAkB;GACjB;GACA,QAAQ,SAAS,MAAM;GACvB,YAAY;GACZ,CAAC,CACF,CAAC,QAAQ;EACV,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"in-memory-cache-store-oClww-8m.js","names":["cleanupIntervalMs: number","entry: CacheEntry<T>"],"sources":["../src/cache/in-memory-cache-store.ts"],"sourcesContent":["import type { CacheStore } from '@kuckit/domain'\n\ninterface CacheEntry<T> {\n\tvalue: T\n\texpiresAt?: number\n}\n\n/**\n * In-memory cache store implementation\n * Suitable for single-process applications or development\n * For distributed systems, use Redis adapter\n */\nexport class InMemoryCacheStore implements CacheStore {\n\tprivate cache = new Map<string, CacheEntry<any>>()\n\tprivate cleanupTimer: NodeJS.Timeout | null = null\n\n\tconstructor(private cleanupIntervalMs: number = 60000) {\n\t\tthis.startCleanup()\n\t}\n\n\tasync get<T>(key: string): Promise<T | undefined> {\n\t\tconst entry = this.cache.get(key)\n\n\t\tif (!entry) {\n\t\t\treturn undefined\n\t\t}\n\n\t\t// Check if expired\n\t\tif (entry.expiresAt && entry.expiresAt < Date.now()) {\n\t\t\tthis.cache.delete(key)\n\t\t\treturn undefined\n\t\t}\n\n\t\treturn entry.value as T\n\t}\n\n\tasync set<T>(key: string, value: T, ttlMs?: number): Promise<void> {\n\t\tconst entry: CacheEntry<T> = {\n\t\t\tvalue,\n\t\t\texpiresAt: ttlMs ? Date.now() + ttlMs : undefined,\n\t\t}\n\n\t\tthis.cache.set(key, entry)\n\t}\n\n\tasync del(key: string): Promise<void> {\n\t\tthis.cache.delete(key)\n\t}\n\n\tasync clear(): Promise<void> {\n\t\tthis.cache.clear()\n\t}\n\n\tasync has(key: string): Promise<boolean> {\n\t\tconst entry = this.cache.get(key)\n\n\t\tif (!entry) {\n\t\t\treturn false\n\t\t}\n\n\t\t// Check if expired\n\t\tif (entry.expiresAt && entry.expiresAt < Date.now()) {\n\t\t\tthis.cache.delete(key)\n\t\t\treturn false\n\t\t}\n\n\t\treturn true\n\t}\n\n\t/**\n\t * Start background cleanup of expired entries\n\t */\n\tprivate startCleanup(): void {\n\t\tthis.cleanupTimer = setInterval(() => {\n\t\t\tconst now = Date.now()\n\t\t\tlet expired = 0\n\n\t\t\tfor (const [key, entry] of this.cache.entries()) {\n\t\t\t\tif (entry.expiresAt && entry.expiresAt < now) {\n\t\t\t\t\tthis.cache.delete(key)\n\t\t\t\t\texpired++\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Optionally log cleanup metrics\n\t\t\tif (expired > 0) {\n\t\t\t\t// console.debug(`Cache cleanup: removed ${expired} expired entries`)\n\t\t\t}\n\t\t}, this.cleanupIntervalMs)\n\t}\n\n\t/**\n\t * Stop cleanup timer\n\t */\n\tdestroy(): void {\n\t\tif (this.cleanupTimer) {\n\t\t\tclearInterval(this.cleanupTimer)\n\t\t\tthis.cleanupTimer = null\n\t\t}\n\t}\n}\n"],"mappings":";;;;;;AAYA,IAAa,qBAAb,MAAsD;CACrD,AAAQ,wBAAQ,IAAI,KAA8B;CAClD,AAAQ,eAAsC;CAE9C,YAAY,AAAQA,oBAA4B,KAAO;EAAnC;AACnB,OAAK,cAAc;;CAGpB,MAAM,IAAO,KAAqC;EACjD,MAAM,QAAQ,KAAK,MAAM,IAAI,IAAI;AAEjC,MAAI,CAAC,MACJ;AAID,MAAI,MAAM,aAAa,MAAM,YAAY,KAAK,KAAK,EAAE;AACpD,QAAK,MAAM,OAAO,IAAI;AACtB;;AAGD,SAAO,MAAM;;CAGd,MAAM,IAAO,KAAa,OAAU,OAA+B;EAClE,MAAMC,QAAuB;GAC5B;GACA,WAAW,QAAQ,KAAK,KAAK,GAAG,QAAQ;GACxC;AAED,OAAK,MAAM,IAAI,KAAK,MAAM;;CAG3B,MAAM,IAAI,KAA4B;AACrC,OAAK,MAAM,OAAO,IAAI;;CAGvB,MAAM,QAAuB;AAC5B,OAAK,MAAM,OAAO;;CAGnB,MAAM,IAAI,KAA+B;EACxC,MAAM,QAAQ,KAAK,MAAM,IAAI,IAAI;AAEjC,MAAI,CAAC,MACJ,QAAO;AAIR,MAAI,MAAM,aAAa,MAAM,YAAY,KAAK,KAAK,EAAE;AACpD,QAAK,MAAM,OAAO,IAAI;AACtB,UAAO;;AAGR,SAAO;;;;;CAMR,AAAQ,eAAqB;AAC5B,OAAK,eAAe,kBAAkB;GACrC,MAAM,MAAM,KAAK,KAAK;GACtB,IAAI,UAAU;AAEd,QAAK,MAAM,CAAC,KAAK,UAAU,KAAK,MAAM,SAAS,CAC9C,KAAI,MAAM,aAAa,MAAM,YAAY,KAAK;AAC7C,SAAK,MAAM,OAAO,IAAI;AACtB;;AAKF,OAAI,UAAU,GAAG;KAGf,KAAK,kBAAkB;;;;;CAM3B,UAAgB;AACf,MAAI,KAAK,cAAc;AACtB,iBAAc,KAAK,aAAa;AAChC,QAAK,eAAe"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"in-memory-rate-limiter-BDSHZXxf.js","names":["cleanupIntervalMs: number"],"sources":["../src/rate-limiter/in-memory-rate-limiter.ts"],"sourcesContent":["import type { RateLimiterStore } from '@kuckit/domain'\n\ninterface TokenBucket {\n\ttokens: number\n\tlastRefillAt: number\n}\n\n/**\n * In-memory rate limiter using token bucket algorithm\n * Suitable for single-process applications or development\n * For distributed systems, use Redis adapter\n */\nexport class InMemoryRateLimiterStore implements RateLimiterStore {\n\tprivate buckets = new Map<string, TokenBucket>()\n\tprivate cleanupTimer: NodeJS.Timeout | null = null\n\n\tconstructor(private cleanupIntervalMs: number = 60000) {\n\t\tthis.startCleanup()\n\t}\n\n\tasync checkLimit(\n\t\tkey: string,\n\t\tcapacity: number,\n\t\trefillPerSecond: number\n\t): Promise<{\n\t\tallowed: boolean\n\t\ttokensRemaining: number\n\t\tresetAt: Date\n\t}> {\n\t\tconst now = Date.now()\n\t\tlet bucket = this.buckets.get(key)\n\n\t\t// Initialize bucket if not exists\n\t\tif (!bucket) {\n\t\t\tbucket = {\n\t\t\t\ttokens: capacity,\n\t\t\t\tlastRefillAt: now,\n\t\t\t}\n\t\t\tthis.buckets.set(key, bucket)\n\t\t}\n\n\t\t// Calculate refill amount based on time passed\n\t\tconst timeSinceRefillMs = now - bucket.lastRefillAt\n\t\tconst timeSinceRefillSec = timeSinceRefillMs / 1000\n\t\tconst tokensToAdd = timeSinceRefillSec * refillPerSecond\n\n\t\t// Refill tokens (capped at capacity)\n\t\tbucket.tokens = Math.min(capacity, bucket.tokens + tokensToAdd)\n\t\tbucket.lastRefillAt = now\n\n\t\t// Check if request is allowed\n\t\tconst allowed = bucket.tokens >= 1\n\n\t\tif (allowed) {\n\t\t\tbucket.tokens -= 1\n\t\t}\n\n\t\t// Calculate reset time (when we'll have 1 token again)\n\t\tconst tokensNeeded = Math.max(0, 1 - bucket.tokens)\n\t\tconst secondsToReset = tokensNeeded / refillPerSecond\n\t\tconst resetAt = new Date(now + secondsToReset * 1000)\n\n\t\treturn {\n\t\t\tallowed,\n\t\t\ttokensRemaining: Math.floor(bucket.tokens),\n\t\t\tresetAt,\n\t\t}\n\t}\n\n\tasync reset(key: string): Promise<void> {\n\t\tthis.buckets.delete(key)\n\t}\n\n\tasync clear(): Promise<void> {\n\t\tthis.buckets.clear()\n\t}\n\n\t/**\n\t * Start background cleanup of old buckets\n\t * Removes buckets that haven't been used in a long time\n\t */\n\tprivate startCleanup(): void {\n\t\tthis.cleanupTimer = setInterval(() => {\n\t\t\tconst now = Date.now()\n\t\t\tconst maxAgeMs = 3600000 // 1 hour\n\t\t\tlet removed = 0\n\n\t\t\tfor (const [key, bucket] of this.buckets.entries()) {\n\t\t\t\tif (now - bucket.lastRefillAt > maxAgeMs) {\n\t\t\t\t\tthis.buckets.delete(key)\n\t\t\t\t\tremoved++\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Optionally log cleanup metrics\n\t\t\tif (removed > 0) {\n\t\t\t\t// console.debug(`RateLimiter cleanup: removed ${removed} old buckets`)\n\t\t\t}\n\t\t}, this.cleanupIntervalMs)\n\t}\n\n\t/**\n\t * Stop cleanup timer\n\t */\n\tdestroy(): void {\n\t\tif (this.cleanupTimer) {\n\t\t\tclearInterval(this.cleanupTimer)\n\t\t\tthis.cleanupTimer = null\n\t\t}\n\t}\n}\n"],"mappings":";;;;;;AAYA,IAAa,2BAAb,MAAkE;CACjE,AAAQ,0BAAU,IAAI,KAA0B;CAChD,AAAQ,eAAsC;CAE9C,YAAY,AAAQA,oBAA4B,KAAO;EAAnC;AACnB,OAAK,cAAc;;CAGpB,MAAM,WACL,KACA,UACA,iBAKE;EACF,MAAM,MAAM,KAAK,KAAK;EACtB,IAAI,SAAS,KAAK,QAAQ,IAAI,IAAI;AAGlC,MAAI,CAAC,QAAQ;AACZ,YAAS;IACR,QAAQ;IACR,cAAc;IACd;AACD,QAAK,QAAQ,IAAI,KAAK,OAAO;;EAM9B,MAAM,eAFoB,MAAM,OAAO,gBACQ,MACN;AAGzC,SAAO,SAAS,KAAK,IAAI,UAAU,OAAO,SAAS,YAAY;AAC/D,SAAO,eAAe;EAGtB,MAAM,UAAU,OAAO,UAAU;AAEjC,MAAI,QACH,QAAO,UAAU;EAKlB,MAAM,iBADe,KAAK,IAAI,GAAG,IAAI,OAAO,OAAO,GACb;EACtC,MAAM,UAAU,IAAI,KAAK,MAAM,iBAAiB,IAAK;AAErD,SAAO;GACN;GACA,iBAAiB,KAAK,MAAM,OAAO,OAAO;GAC1C;GACA;;CAGF,MAAM,MAAM,KAA4B;AACvC,OAAK,QAAQ,OAAO,IAAI;;CAGzB,MAAM,QAAuB;AAC5B,OAAK,QAAQ,OAAO;;;;;;CAOrB,AAAQ,eAAqB;AAC5B,OAAK,eAAe,kBAAkB;GACrC,MAAM,MAAM,KAAK,KAAK;GACtB,MAAM,WAAW;GACjB,IAAI,UAAU;AAEd,QAAK,MAAM,CAAC,KAAK,WAAW,KAAK,QAAQ,SAAS,CACjD,KAAI,MAAM,OAAO,eAAe,UAAU;AACzC,SAAK,QAAQ,OAAO,IAAI;AACxB;;AAKF,OAAI,UAAU,GAAG;KAGf,KAAK,kBAAkB;;;;;CAM3B,UAAgB;AACf,MAAI,KAAK,cAAc;AACtB,iBAAc,KAAK,aAAa;AAChC,QAAK,eAAe"}