@warlock.js/cache 5.29.0 → 5.30.0

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 (94) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/cjs/index.cjs +91 -47
  3. package/cjs/index.cjs.map +1 -1
  4. package/esm/cache-manager.d.mts +1 -1
  5. package/esm/cache-manager.d.mts.map +1 -1
  6. package/esm/cache-manager.mjs +1 -1
  7. package/esm/cache-manager.mjs.map +1 -1
  8. package/esm/cached/auto-key.d.mts +1 -1
  9. package/esm/cached/auto-key.d.mts.map +1 -1
  10. package/esm/cached/auto-key.mjs +1 -1
  11. package/esm/cached/auto-key.mjs.map +1 -1
  12. package/esm/cached/cached.d.mts +1 -1
  13. package/esm/cached/cached.d.mts.map +1 -1
  14. package/esm/cached/cached.mjs +1 -1
  15. package/esm/cached/cached.mjs.map +1 -1
  16. package/esm/cached/normalize-args.d.mts +1 -1
  17. package/esm/cached/normalize-args.d.mts.map +1 -1
  18. package/esm/cached/normalize-args.mjs +1 -1
  19. package/esm/cached/normalize-args.mjs.map +1 -1
  20. package/esm/drivers/base-cache-driver.d.mts +11 -5
  21. package/esm/drivers/base-cache-driver.d.mts.map +1 -1
  22. package/esm/drivers/base-cache-driver.mjs +29 -13
  23. package/esm/drivers/base-cache-driver.mjs.map +1 -1
  24. package/esm/drivers/file-cache-driver.d.mts +1 -1
  25. package/esm/drivers/file-cache-driver.d.mts.map +1 -1
  26. package/esm/drivers/file-cache-driver.mjs +2 -2
  27. package/esm/drivers/file-cache-driver.mjs.map +1 -1
  28. package/esm/drivers/in-memory-tag-index.d.mts +1 -1
  29. package/esm/drivers/in-memory-tag-index.d.mts.map +1 -1
  30. package/esm/drivers/in-memory-tag-index.mjs +1 -1
  31. package/esm/drivers/in-memory-tag-index.mjs.map +1 -1
  32. package/esm/drivers/index.d.mts +1 -1
  33. package/esm/drivers/index.mjs +1 -1
  34. package/esm/drivers/lru-memory-cache-driver.d.mts +1 -1
  35. package/esm/drivers/lru-memory-cache-driver.d.mts.map +1 -1
  36. package/esm/drivers/lru-memory-cache-driver.mjs +3 -2
  37. package/esm/drivers/lru-memory-cache-driver.mjs.map +1 -1
  38. package/esm/drivers/memory-cache-driver.d.mts +1 -1
  39. package/esm/drivers/memory-cache-driver.d.mts.map +1 -1
  40. package/esm/drivers/memory-cache-driver.mjs +3 -2
  41. package/esm/drivers/memory-cache-driver.mjs.map +1 -1
  42. package/esm/drivers/memory-extended-cache-driver.d.mts +1 -1
  43. package/esm/drivers/memory-extended-cache-driver.d.mts.map +1 -1
  44. package/esm/drivers/memory-extended-cache-driver.mjs +1 -1
  45. package/esm/drivers/memory-extended-cache-driver.mjs.map +1 -1
  46. package/esm/drivers/mock-cache-driver.d.mts +1 -1
  47. package/esm/drivers/mock-cache-driver.d.mts.map +1 -1
  48. package/esm/drivers/mock-cache-driver.mjs +3 -2
  49. package/esm/drivers/mock-cache-driver.mjs.map +1 -1
  50. package/esm/drivers/null-cache-driver.d.mts +5 -1
  51. package/esm/drivers/null-cache-driver.d.mts.map +1 -1
  52. package/esm/drivers/null-cache-driver.mjs +17 -10
  53. package/esm/drivers/null-cache-driver.mjs.map +1 -1
  54. package/esm/drivers/pg-cache-driver.d.mts +1 -1
  55. package/esm/drivers/pg-cache-driver.d.mts.map +1 -1
  56. package/esm/drivers/pg-cache-driver.mjs +3 -2
  57. package/esm/drivers/pg-cache-driver.mjs.map +1 -1
  58. package/esm/drivers/redis-cache-driver.d.mts +14 -2
  59. package/esm/drivers/redis-cache-driver.d.mts.map +1 -1
  60. package/esm/drivers/redis-cache-driver.mjs +24 -4
  61. package/esm/drivers/redis-cache-driver.mjs.map +1 -1
  62. package/esm/index.d.mts +2 -2
  63. package/esm/index.mjs +2 -2
  64. package/esm/list/memory-cache-list.d.mts +1 -1
  65. package/esm/list/memory-cache-list.d.mts.map +1 -1
  66. package/esm/list/memory-cache-list.mjs +1 -1
  67. package/esm/list/memory-cache-list.mjs.map +1 -1
  68. package/esm/metrics.d.mts +1 -1
  69. package/esm/metrics.d.mts.map +1 -1
  70. package/esm/metrics.mjs +1 -1
  71. package/esm/metrics.mjs.map +1 -1
  72. package/esm/scoped-cache.d.mts +1 -1
  73. package/esm/scoped-cache.d.mts.map +1 -1
  74. package/esm/scoped-cache.mjs +1 -1
  75. package/esm/scoped-cache.mjs.map +1 -1
  76. package/esm/tagged-cache.d.mts +1 -1
  77. package/esm/tagged-cache.d.mts.map +1 -1
  78. package/esm/tagged-cache.mjs +1 -1
  79. package/esm/tagged-cache.mjs.map +1 -1
  80. package/esm/tagged-scoped-cache.d.mts +1 -1
  81. package/esm/tagged-scoped-cache.d.mts.map +1 -1
  82. package/esm/tagged-scoped-cache.mjs +1 -1
  83. package/esm/tagged-scoped-cache.mjs.map +1 -1
  84. package/esm/types.d.mts +1 -1
  85. package/esm/types.d.mts.map +1 -1
  86. package/esm/types.mjs +1 -1
  87. package/esm/types.mjs.map +1 -1
  88. package/esm/utils.d.mts +1 -1
  89. package/esm/utils.d.mts.map +1 -1
  90. package/esm/utils.mjs +1 -1
  91. package/esm/utils.mjs.map +1 -1
  92. package/llms-full.txt +2 -0
  93. package/package.json +5 -4
  94. package/skills/cache-basics/SKILL.md +2 -0
@@ -1,8 +1,9 @@
1
1
  import { cosineSimilarity, parseTtl } from "../utils.mjs";
2
2
  import { BaseCacheDriver } from "./base-cache-driver.mjs";
3
3
  import { InMemoryTagIndex } from "./in-memory-tag-index.mjs";
4
+ import { maskEmailsInText } from "@warlock.js/logger";
4
5
 
5
- //#region ../cache/src/drivers/memory-cache-driver.ts
6
+ //#region ../../packages/cache/src/drivers/memory-cache-driver.ts
6
7
  /**
7
8
  * Clone non-primitive values so cached state can't be mutated through
8
9
  * references held by callers. Primitives are immutable and returned as-is.
@@ -178,7 +179,7 @@ var MemoryCacheDriver = class extends BaseCacheDriver {
178
179
  const parsedKey = this.parseKey(key);
179
180
  const entry = this.readLive(parsedKey);
180
181
  const current = entry ? entry.data : 0;
181
- if (typeof current !== "number") throw new Error(`Cannot increment non-numeric value for key: ${parsedKey}`);
182
+ if (typeof current !== "number") throw new Error(`Cannot increment non-numeric value for key: ${maskEmailsInText(parsedKey)}`);
182
183
  const newValue = current + value;
183
184
  if (entry) {
184
185
  entry.data = newValue;
@@ -1 +1 @@
1
- {"version":3,"file":"memory-cache-driver.mjs","names":[],"sources":["../../../../../../../cache/src/drivers/memory-cache-driver.ts"],"sourcesContent":["import type {\n CacheData,\n CacheDriver,\n CacheKey,\n CacheSetOptions,\n CacheSetResult,\n CacheSimilarHit,\n CacheSimilarOptions,\n CacheTtl,\n MemoryCacheOptions,\n} from \"../types\";\nimport { cosineSimilarity, parseTtl } from \"../utils\";\nimport { BaseCacheDriver } from \"./base-cache-driver\";\nimport { InMemoryTagIndex } from \"./in-memory-tag-index\";\n\n/**\n * Clone non-primitive values so cached state can't be mutated through\n * references held by callers. Primitives are immutable and returned as-is.\n */\nfunction cloneValue<T>(value: T): T {\n if (value === null || value === undefined) {\n return value;\n }\n\n const type = typeof value;\n\n if (type === \"string\" || type === \"number\" || type === \"boolean\") {\n return value;\n }\n\n return structuredClone(value);\n}\n\nexport class MemoryCacheDriver\n extends BaseCacheDriver<MemoryCacheDriver, MemoryCacheOptions>\n implements CacheDriver<MemoryCacheDriver, MemoryCacheOptions>\n{\n /**\n * {@inheritdoc}\n */\n public name = \"memory\";\n\n /**\n * Flat storage keyed by the parsed key. Insertion order doubles as LRU\n * order (least recently used first) — accessed entries are deleted and\n * re-inserted.\n */\n protected entries: Map<string, CacheData> = new Map();\n\n /**\n * Read-only object view of the stored entries, keyed by parsed key.\n * Kept for introspection; the values are the live stored wrappers.\n */\n public get data(): Record<string, CacheData> {\n return Object.fromEntries(this.entries);\n }\n\n /**\n * Expiry records for entries with a FINITE ttl only (parsed key => expiresAt ms).\n * The sweep iterates just these.\n */\n protected expiry: Map<string, number> = new Map();\n\n /**\n * Cleanup interval reference\n */\n protected cleanupInterval?: NodeJS.Timeout;\n\n /**\n * Parallel vector index keyed by parsedKey. Populated by `set({ vector })`,\n * scanned by `similar()`. Lifetime mirrors the main entry — cleared on\n * `remove`, `flush`, expiry, namespace clear, overwrite without a vector,\n * and LRU eviction.\n */\n protected vectorIndex: Map<string, number[]> = new Map();\n\n /**\n * Tag index, kept apart from `entries`: never evicted by `maxSize`, never\n * swept by TTL, and updated synchronously.\n */\n protected tagIndex: InMemoryTagIndex = new InMemoryTagIndex();\n\n /**\n * {@inheritdoc}\n */\n public constructor() {\n super();\n\n this.startCleanup();\n }\n\n /**\n * Start the cleanup process for entries that carry a finite ttl\n */\n public startCleanup() {\n // Clear existing interval if any\n if (this.cleanupInterval) {\n clearInterval(this.cleanupInterval);\n }\n\n this.cleanupInterval = setInterval(async () => {\n const now = Date.now();\n const expiredKeys: string[] = [];\n\n for (const [key, expiresAt] of this.expiry) {\n if (expiresAt <= now) {\n expiredKeys.push(key);\n }\n }\n\n for (const key of expiredKeys) {\n // the entry may have been rewritten/slid since the snapshot\n const expiresAt = this.expiry.get(key);\n\n if (expiresAt === undefined || expiresAt > now) {\n continue;\n }\n\n this.dropEntry(key);\n\n this.log(\"expired\", key);\n // Emit expired event\n await this.emit(\"expired\", { key });\n }\n }, 1000);\n\n // do not block the process from exiting\n this.cleanupInterval.unref();\n }\n\n /**\n * Delete an entry and every side record (expiry, vector). Synchronous.\n */\n protected dropEntry(parsedKey: string) {\n this.entries.delete(parsedKey);\n this.expiry.delete(parsedKey);\n this.vectorIndex.delete(parsedKey);\n }\n\n /**\n * Raw, synchronous read of a live entry. An expired entry is deleted and\n * reported as missing. Never slides TTLs, never emits, never touches LRU order.\n */\n protected readLive(parsedKey: string): CacheData | undefined {\n const entry = this.entries.get(parsedKey);\n\n if (!entry) {\n return undefined;\n }\n\n if (entry.expiresAt !== undefined && entry.expiresAt <= Date.now()) {\n this.dropEntry(parsedKey);\n return undefined;\n }\n\n return entry;\n }\n\n /**\n * Mark an entry as most recently used (only tracked when `maxSize` is set).\n */\n protected touch(parsedKey: string, entry: CacheData) {\n if (!this.options.maxSize) return;\n\n this.entries.delete(parsedKey);\n this.entries.set(parsedKey, entry);\n }\n\n /**\n * When true, every live read slides the entry's expiration forward by its\n * ttl (the `memoryExtended` driver). Set in a subclass constructor rather\n * than redeclared, so subclasses stay structurally compatible with this\n * class (the `client` type relies on that).\n */\n protected slidingExpiration = false;\n\n /**\n * Invoked on a live read hit, before the value is returned. Runs only from\n * `get()` after the expiry check, so an expired entry is never resurrected,\n * and never from the internal existence check used by `onConflict`.\n */\n protected onRead(parsedKey: string, entry: CacheData) {\n if (!this.slidingExpiration) {\n return;\n }\n\n const rawTtl = entry.ttl ?? this.options.ttl;\n const ttl = rawTtl !== undefined ? parseTtl(rawTtl) : undefined;\n\n if (ttl && Number.isFinite(ttl)) {\n entry.expiresAt = this.getExpiresAt(ttl);\n this.expiry.set(parsedKey, entry.expiresAt as number);\n }\n }\n\n /**\n * {@inheritdoc}\n */\n public async removeNamespace(namespace: string) {\n this.log(\"clearing\", namespace);\n\n namespace = this.parseKey(namespace);\n\n this.tagIndex.removeNamespace(namespace);\n\n if (namespace === \"\") {\n this.entries.clear();\n this.expiry.clear();\n this.vectorIndex.clear();\n } else {\n const prefix = namespace + \".\";\n\n for (const key of [...this.entries.keys()]) {\n if (key === namespace || key.startsWith(prefix)) {\n this.dropEntry(key);\n }\n }\n }\n\n this.log(\"cleared\", namespace);\n\n return this;\n }\n\n /**\n * {@inheritdoc}\n *\n * The conditional check and the write run with no `await` in between, so\n * `onConflict` decisions are atomic within the process.\n */\n public async set(\n key: CacheKey,\n value: any,\n ttlOrOptions?: CacheTtl | CacheSetOptions,\n ): Promise<any> {\n const parsedKey = this.parseKey(key);\n const { ttl, tags, onConflict, vector, staleAt } = this.resolveSetOptions(ttlOrOptions);\n\n this.log(\"caching\", parsedKey);\n\n // expired entries count as missing (readLive deletes them)\n const existing = onConflict === \"create\" || onConflict === \"update\" ? this.readLive(parsedKey) : undefined;\n\n if (onConflict === \"create\" && existing) {\n const result: CacheSetResult = { wasSet: false, existing: cloneValue(existing.data) };\n return result;\n }\n\n if (onConflict === \"update\" && !existing) {\n const result: CacheSetResult = { wasSet: false, existing: null };\n return result;\n }\n\n const data = this.prepareDataForStorage(cloneValue(value), ttl, staleAt);\n\n // delete + set moves the key to the most-recent position\n this.entries.delete(parsedKey);\n this.entries.set(parsedKey, data);\n\n if (data.expiresAt !== undefined && Number.isFinite(data.expiresAt)) {\n this.expiry.set(parsedKey, data.expiresAt);\n } else {\n this.expiry.delete(parsedKey);\n }\n\n if (vector) {\n this.vectorIndex.set(parsedKey, vector.slice());\n } else {\n this.vectorIndex.delete(parsedKey);\n }\n\n this.enforceMaxSize(parsedKey);\n\n if (tags && tags.length > 0) {\n await this.applyTags(key, tags);\n }\n\n this.log(\"cached\", parsedKey);\n\n await this.emit(\"set\", { key: parsedKey, value, ttl });\n\n if (onConflict === \"create\" || onConflict === \"update\") {\n const result: CacheSetResult = { wasSet: true, existing: null };\n return result;\n }\n\n return this;\n }\n\n /**\n * {@inheritdoc}\n *\n * The check and the delete run synchronously (no `await` between them), so\n * the compare-and-delete is atomic within the process.\n */\n protected async deleteIfEquals(key: CacheKey, expected: unknown): Promise<boolean> {\n const parsedKey = this.parseKey(key);\n const entry = this.readLive(parsedKey);\n\n if (!entry || entry.data !== expected) {\n return false;\n }\n\n await this.remove(key);\n\n return true;\n }\n\n /**\n * {@inheritdoc}\n *\n * Read, add and write run synchronously (no `await` in between), so\n * concurrent increments in this process never lose an update. An existing\n * entry keeps its expiry; a missing key starts from 0 with the default TTL.\n */\n public async increment(key: CacheKey, value: number = 1): Promise<number> {\n const parsedKey = this.parseKey(key);\n const entry = this.readLive(parsedKey);\n const current = entry ? entry.data : 0;\n\n if (typeof current !== \"number\") {\n throw new Error(`Cannot increment non-numeric value for key: ${parsedKey}`);\n }\n\n const newValue = current + value;\n\n if (entry) {\n entry.data = newValue;\n this.touch(parsedKey, entry);\n } else {\n const data = this.prepareDataForStorage(newValue, this.ttl);\n\n this.entries.set(parsedKey, data);\n\n if (data.expiresAt !== undefined && Number.isFinite(data.expiresAt)) {\n this.expiry.set(parsedKey, data.expiresAt);\n }\n\n this.enforceMaxSize(parsedKey);\n }\n\n await this.emit(\"set\", { key: parsedKey, value: newValue, ttl: entry?.ttl ?? this.ttl });\n\n return newValue;\n }\n\n /**\n * {@inheritdoc}\n *\n * Read and delete run synchronously, so a value is handed out exactly once\n * even when concurrent callers pull the same key.\n */\n public async pull(key: CacheKey): Promise<any | null> {\n const parsedKey = this.parseKey(key);\n const entry = this.readLive(parsedKey);\n\n if (!entry) {\n await this.emit(\"miss\", { key: parsedKey });\n\n return null;\n }\n\n this.dropEntry(parsedKey);\n\n const value = cloneValue(entry.data);\n\n await this.emit(\"hit\", { key: parsedKey, value });\n await this.emit(\"removed\", { key: parsedKey });\n\n return value;\n }\n\n /**\n * {@inheritdoc}\n */\n public async get(key: CacheKey) {\n const parsedKey = this.parseKey(key);\n\n this.log(\"fetching\", parsedKey);\n\n const entry = this.readLive(parsedKey);\n\n if (!entry) {\n this.log(\"notFound\", parsedKey);\n // Emit miss event\n await this.emit(\"miss\", { key: parsedKey });\n return null;\n }\n\n this.onRead(parsedKey, entry);\n this.touch(parsedKey, entry);\n\n const result = await this.parseCachedData(parsedKey, entry);\n\n // Emit hit event\n await this.emit(\"hit\", { key: parsedKey, value: result });\n\n return result;\n }\n\n /**\n * Read the raw {@link CacheData} wrapper (cloned), including `staleAt` metadata.\n * Returns `null` for missing or expired entries so the SWR flow can branch\n * cleanly. Does not emit `hit`/`miss` events — that's `get()`'s job.\n */\n protected async getEntry(key: CacheKey): Promise<CacheData | null> {\n const entry = this.readLive(this.parseKey(key));\n\n if (!entry) {\n return null;\n }\n\n return { ...entry, data: cloneValue(entry.data) };\n }\n\n /**\n * {@inheritdoc}\n */\n public async remove(key: CacheKey) {\n const parsedKey = this.parseKey(key);\n\n this.log(\"removing\", parsedKey);\n\n this.dropEntry(parsedKey);\n\n this.log(\"removed\", parsedKey);\n\n // Emit removed event\n await this.emit(\"removed\", { key: parsedKey });\n }\n\n /**\n * {@inheritdoc}\n *\n * Synchronous in-process set — concurrent tagged writes never drop members.\n */\n public async tagAdd(tagKey: CacheKey, members: string[]): Promise<void> {\n this.tagIndex.add(this.parseKey(tagKey), members);\n }\n\n /**\n * {@inheritdoc}\n */\n public async tagMembers(tagKey: CacheKey): Promise<string[]> {\n return this.tagIndex.members(this.parseKey(tagKey));\n }\n\n /**\n * {@inheritdoc}\n */\n public async tagRemove(tagKey: CacheKey, members: string[]): Promise<void> {\n this.tagIndex.remove(this.parseKey(tagKey), members);\n }\n\n /**\n * {@inheritdoc}\n */\n public async tagDelete(tagKey: CacheKey): Promise<void> {\n this.tagIndex.delete(this.parseKey(tagKey));\n }\n\n /**\n * {@inheritdoc}\n */\n public async flush() {\n this.log(\"flushing\");\n if (this.options.globalPrefix) {\n await this.removeNamespace(\"\");\n } else {\n this.entries.clear();\n this.expiry.clear();\n this.vectorIndex.clear();\n this.tagIndex.clear();\n }\n\n this.log(\"flushed\");\n\n // Emit flushed event\n await this.emit(\"flushed\");\n }\n\n /**\n * Evict least recently used entries (Map insertion order) until the size is\n * within `maxSize`. Never evicts `protectedKey` (the key just written).\n */\n protected enforceMaxSize(protectedKey: string) {\n const maxSize = this.options.maxSize;\n\n if (!maxSize) {\n return;\n }\n\n for (const lruKey of [...this.entries.keys()]) {\n if (this.entries.size <= maxSize) {\n break;\n }\n\n if (lruKey === protectedKey) {\n continue;\n }\n\n this.log(\"removing\", lruKey);\n this.dropEntry(lruKey);\n this.log(\"removed\", lruKey);\n }\n }\n\n /**\n * {@inheritdoc}\n *\n * Brute-force O(N) cosine similarity over every entry that was written with\n * `set({ vector })`. Suitable for development and small in-memory knowledge\n * bases — not for production beyond ~10k entries. Use the `pg` driver\n * (with pgvector) or `redis` (with RediSearch) at scale.\n *\n * @warning Dev-only — O(N) per query.\n */\n public async similar<T = any>(\n vector: number[],\n options: CacheSimilarOptions,\n ): Promise<CacheSimilarHit<T>[]> {\n const tagFilter = await this.getKeysForTags(options.tags);\n\n const hits: CacheSimilarHit<T>[] = [];\n\n for (const [parsedKey, stored] of [...this.vectorIndex]) {\n if (tagFilter && !tagFilter.has(parsedKey)) {\n continue;\n }\n\n // Read the entry directly by its already-parsed key — this.get() would\n // parse it again and apply globalPrefix twice, missing every entry.\n const entry = this.readLive(parsedKey);\n\n if (!entry) {\n continue;\n }\n\n const value: any = cloneValue(entry.data);\n\n const score = cosineSimilarity(vector, stored);\n\n if (options.threshold !== undefined && score < options.threshold) {\n continue;\n }\n\n hits.push({ key: parsedKey, value, score });\n }\n\n hits.sort((a, b) => b.score - a.score);\n\n if (options.topK >= 0 && hits.length > options.topK) {\n hits.length = options.topK;\n }\n\n return hits;\n }\n\n /**\n * {@inheritdoc}\n */\n public async disconnect() {\n // Clear the cleanup interval to prevent memory leaks\n if (this.cleanupInterval) {\n clearInterval(this.cleanupInterval);\n this.cleanupInterval = undefined;\n }\n\n await super.disconnect();\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"memory-cache-driver.mjs","names":[],"sources":["../../../../../../../../packages/cache/src/drivers/memory-cache-driver.ts"],"sourcesContent":["import { maskEmailsInText } from \"@warlock.js/logger\";\nimport type {\n CacheData,\n CacheDriver,\n CacheKey,\n CacheSetOptions,\n CacheSetResult,\n CacheSimilarHit,\n CacheSimilarOptions,\n CacheTtl,\n MemoryCacheOptions,\n} from \"../types\";\nimport { cosineSimilarity, parseTtl } from \"../utils\";\nimport { BaseCacheDriver } from \"./base-cache-driver\";\nimport { InMemoryTagIndex } from \"./in-memory-tag-index\";\n\n/**\n * Clone non-primitive values so cached state can't be mutated through\n * references held by callers. Primitives are immutable and returned as-is.\n */\nfunction cloneValue<T>(value: T): T {\n if (value === null || value === undefined) {\n return value;\n }\n\n const type = typeof value;\n\n if (type === \"string\" || type === \"number\" || type === \"boolean\") {\n return value;\n }\n\n return structuredClone(value);\n}\n\nexport class MemoryCacheDriver\n extends BaseCacheDriver<MemoryCacheDriver, MemoryCacheOptions>\n implements CacheDriver<MemoryCacheDriver, MemoryCacheOptions>\n{\n /**\n * {@inheritdoc}\n */\n public name = \"memory\";\n\n /**\n * Flat storage keyed by the parsed key. Insertion order doubles as LRU\n * order (least recently used first) — accessed entries are deleted and\n * re-inserted.\n */\n protected entries: Map<string, CacheData> = new Map();\n\n /**\n * Read-only object view of the stored entries, keyed by parsed key.\n * Kept for introspection; the values are the live stored wrappers.\n */\n public get data(): Record<string, CacheData> {\n return Object.fromEntries(this.entries);\n }\n\n /**\n * Expiry records for entries with a FINITE ttl only (parsed key => expiresAt ms).\n * The sweep iterates just these.\n */\n protected expiry: Map<string, number> = new Map();\n\n /**\n * Cleanup interval reference\n */\n protected cleanupInterval?: NodeJS.Timeout;\n\n /**\n * Parallel vector index keyed by parsedKey. Populated by `set({ vector })`,\n * scanned by `similar()`. Lifetime mirrors the main entry — cleared on\n * `remove`, `flush`, expiry, namespace clear, overwrite without a vector,\n * and LRU eviction.\n */\n protected vectorIndex: Map<string, number[]> = new Map();\n\n /**\n * Tag index, kept apart from `entries`: never evicted by `maxSize`, never\n * swept by TTL, and updated synchronously.\n */\n protected tagIndex: InMemoryTagIndex = new InMemoryTagIndex();\n\n /**\n * {@inheritdoc}\n */\n public constructor() {\n super();\n\n this.startCleanup();\n }\n\n /**\n * Start the cleanup process for entries that carry a finite ttl\n */\n public startCleanup() {\n // Clear existing interval if any\n if (this.cleanupInterval) {\n clearInterval(this.cleanupInterval);\n }\n\n this.cleanupInterval = setInterval(async () => {\n const now = Date.now();\n const expiredKeys: string[] = [];\n\n for (const [key, expiresAt] of this.expiry) {\n if (expiresAt <= now) {\n expiredKeys.push(key);\n }\n }\n\n for (const key of expiredKeys) {\n // the entry may have been rewritten/slid since the snapshot\n const expiresAt = this.expiry.get(key);\n\n if (expiresAt === undefined || expiresAt > now) {\n continue;\n }\n\n this.dropEntry(key);\n\n this.log(\"expired\", key);\n // Emit expired event\n await this.emit(\"expired\", { key });\n }\n }, 1000);\n\n // do not block the process from exiting\n this.cleanupInterval.unref();\n }\n\n /**\n * Delete an entry and every side record (expiry, vector). Synchronous.\n */\n protected dropEntry(parsedKey: string) {\n this.entries.delete(parsedKey);\n this.expiry.delete(parsedKey);\n this.vectorIndex.delete(parsedKey);\n }\n\n /**\n * Raw, synchronous read of a live entry. An expired entry is deleted and\n * reported as missing. Never slides TTLs, never emits, never touches LRU order.\n */\n protected readLive(parsedKey: string): CacheData | undefined {\n const entry = this.entries.get(parsedKey);\n\n if (!entry) {\n return undefined;\n }\n\n if (entry.expiresAt !== undefined && entry.expiresAt <= Date.now()) {\n this.dropEntry(parsedKey);\n return undefined;\n }\n\n return entry;\n }\n\n /**\n * Mark an entry as most recently used (only tracked when `maxSize` is set).\n */\n protected touch(parsedKey: string, entry: CacheData) {\n if (!this.options.maxSize) return;\n\n this.entries.delete(parsedKey);\n this.entries.set(parsedKey, entry);\n }\n\n /**\n * When true, every live read slides the entry's expiration forward by its\n * ttl (the `memoryExtended` driver). Set in a subclass constructor rather\n * than redeclared, so subclasses stay structurally compatible with this\n * class (the `client` type relies on that).\n */\n protected slidingExpiration = false;\n\n /**\n * Invoked on a live read hit, before the value is returned. Runs only from\n * `get()` after the expiry check, so an expired entry is never resurrected,\n * and never from the internal existence check used by `onConflict`.\n */\n protected onRead(parsedKey: string, entry: CacheData) {\n if (!this.slidingExpiration) {\n return;\n }\n\n const rawTtl = entry.ttl ?? this.options.ttl;\n const ttl = rawTtl !== undefined ? parseTtl(rawTtl) : undefined;\n\n if (ttl && Number.isFinite(ttl)) {\n entry.expiresAt = this.getExpiresAt(ttl);\n this.expiry.set(parsedKey, entry.expiresAt as number);\n }\n }\n\n /**\n * {@inheritdoc}\n */\n public async removeNamespace(namespace: string) {\n this.log(\"clearing\", namespace);\n\n namespace = this.parseKey(namespace);\n\n this.tagIndex.removeNamespace(namespace);\n\n if (namespace === \"\") {\n this.entries.clear();\n this.expiry.clear();\n this.vectorIndex.clear();\n } else {\n const prefix = namespace + \".\";\n\n for (const key of [...this.entries.keys()]) {\n if (key === namespace || key.startsWith(prefix)) {\n this.dropEntry(key);\n }\n }\n }\n\n this.log(\"cleared\", namespace);\n\n return this;\n }\n\n /**\n * {@inheritdoc}\n *\n * The conditional check and the write run with no `await` in between, so\n * `onConflict` decisions are atomic within the process.\n */\n public async set(\n key: CacheKey,\n value: any,\n ttlOrOptions?: CacheTtl | CacheSetOptions,\n ): Promise<any> {\n const parsedKey = this.parseKey(key);\n const { ttl, tags, onConflict, vector, staleAt } = this.resolveSetOptions(ttlOrOptions);\n\n this.log(\"caching\", parsedKey);\n\n // expired entries count as missing (readLive deletes them)\n const existing = onConflict === \"create\" || onConflict === \"update\" ? this.readLive(parsedKey) : undefined;\n\n if (onConflict === \"create\" && existing) {\n const result: CacheSetResult = { wasSet: false, existing: cloneValue(existing.data) };\n return result;\n }\n\n if (onConflict === \"update\" && !existing) {\n const result: CacheSetResult = { wasSet: false, existing: null };\n return result;\n }\n\n const data = this.prepareDataForStorage(cloneValue(value), ttl, staleAt);\n\n // delete + set moves the key to the most-recent position\n this.entries.delete(parsedKey);\n this.entries.set(parsedKey, data);\n\n if (data.expiresAt !== undefined && Number.isFinite(data.expiresAt)) {\n this.expiry.set(parsedKey, data.expiresAt);\n } else {\n this.expiry.delete(parsedKey);\n }\n\n if (vector) {\n this.vectorIndex.set(parsedKey, vector.slice());\n } else {\n this.vectorIndex.delete(parsedKey);\n }\n\n this.enforceMaxSize(parsedKey);\n\n if (tags && tags.length > 0) {\n await this.applyTags(key, tags);\n }\n\n this.log(\"cached\", parsedKey);\n\n await this.emit(\"set\", { key: parsedKey, value, ttl });\n\n if (onConflict === \"create\" || onConflict === \"update\") {\n const result: CacheSetResult = { wasSet: true, existing: null };\n return result;\n }\n\n return this;\n }\n\n /**\n * {@inheritdoc}\n *\n * The check and the delete run synchronously (no `await` between them), so\n * the compare-and-delete is atomic within the process.\n */\n protected async deleteIfEquals(key: CacheKey, expected: unknown): Promise<boolean> {\n const parsedKey = this.parseKey(key);\n const entry = this.readLive(parsedKey);\n\n if (!entry || entry.data !== expected) {\n return false;\n }\n\n await this.remove(key);\n\n return true;\n }\n\n /**\n * {@inheritdoc}\n *\n * Read, add and write run synchronously (no `await` in between), so\n * concurrent increments in this process never lose an update. An existing\n * entry keeps its expiry; a missing key starts from 0 with the default TTL.\n */\n public async increment(key: CacheKey, value: number = 1): Promise<number> {\n const parsedKey = this.parseKey(key);\n const entry = this.readLive(parsedKey);\n const current = entry ? entry.data : 0;\n\n if (typeof current !== \"number\") {\n throw new Error(`Cannot increment non-numeric value for key: ${maskEmailsInText(parsedKey)}`);\n }\n\n const newValue = current + value;\n\n if (entry) {\n entry.data = newValue;\n this.touch(parsedKey, entry);\n } else {\n const data = this.prepareDataForStorage(newValue, this.ttl);\n\n this.entries.set(parsedKey, data);\n\n if (data.expiresAt !== undefined && Number.isFinite(data.expiresAt)) {\n this.expiry.set(parsedKey, data.expiresAt);\n }\n\n this.enforceMaxSize(parsedKey);\n }\n\n await this.emit(\"set\", { key: parsedKey, value: newValue, ttl: entry?.ttl ?? this.ttl });\n\n return newValue;\n }\n\n /**\n * {@inheritdoc}\n *\n * Read and delete run synchronously, so a value is handed out exactly once\n * even when concurrent callers pull the same key.\n */\n public async pull(key: CacheKey): Promise<any | null> {\n const parsedKey = this.parseKey(key);\n const entry = this.readLive(parsedKey);\n\n if (!entry) {\n await this.emit(\"miss\", { key: parsedKey });\n\n return null;\n }\n\n this.dropEntry(parsedKey);\n\n const value = cloneValue(entry.data);\n\n await this.emit(\"hit\", { key: parsedKey, value });\n await this.emit(\"removed\", { key: parsedKey });\n\n return value;\n }\n\n /**\n * {@inheritdoc}\n */\n public async get(key: CacheKey) {\n const parsedKey = this.parseKey(key);\n\n this.log(\"fetching\", parsedKey);\n\n const entry = this.readLive(parsedKey);\n\n if (!entry) {\n this.log(\"notFound\", parsedKey);\n // Emit miss event\n await this.emit(\"miss\", { key: parsedKey });\n return null;\n }\n\n this.onRead(parsedKey, entry);\n this.touch(parsedKey, entry);\n\n const result = await this.parseCachedData(parsedKey, entry);\n\n // Emit hit event\n await this.emit(\"hit\", { key: parsedKey, value: result });\n\n return result;\n }\n\n /**\n * Read the raw {@link CacheData} wrapper (cloned), including `staleAt` metadata.\n * Returns `null` for missing or expired entries so the SWR flow can branch\n * cleanly. Does not emit `hit`/`miss` events — that's `get()`'s job.\n */\n protected async getEntry(key: CacheKey): Promise<CacheData | null> {\n const entry = this.readLive(this.parseKey(key));\n\n if (!entry) {\n return null;\n }\n\n return { ...entry, data: cloneValue(entry.data) };\n }\n\n /**\n * {@inheritdoc}\n */\n public async remove(key: CacheKey) {\n const parsedKey = this.parseKey(key);\n\n this.log(\"removing\", parsedKey);\n\n this.dropEntry(parsedKey);\n\n this.log(\"removed\", parsedKey);\n\n // Emit removed event\n await this.emit(\"removed\", { key: parsedKey });\n }\n\n /**\n * {@inheritdoc}\n *\n * Synchronous in-process set — concurrent tagged writes never drop members.\n */\n public async tagAdd(tagKey: CacheKey, members: string[]): Promise<void> {\n this.tagIndex.add(this.parseKey(tagKey), members);\n }\n\n /**\n * {@inheritdoc}\n */\n public async tagMembers(tagKey: CacheKey): Promise<string[]> {\n return this.tagIndex.members(this.parseKey(tagKey));\n }\n\n /**\n * {@inheritdoc}\n */\n public async tagRemove(tagKey: CacheKey, members: string[]): Promise<void> {\n this.tagIndex.remove(this.parseKey(tagKey), members);\n }\n\n /**\n * {@inheritdoc}\n */\n public async tagDelete(tagKey: CacheKey): Promise<void> {\n this.tagIndex.delete(this.parseKey(tagKey));\n }\n\n /**\n * {@inheritdoc}\n */\n public async flush() {\n this.log(\"flushing\");\n if (this.options.globalPrefix) {\n await this.removeNamespace(\"\");\n } else {\n this.entries.clear();\n this.expiry.clear();\n this.vectorIndex.clear();\n this.tagIndex.clear();\n }\n\n this.log(\"flushed\");\n\n // Emit flushed event\n await this.emit(\"flushed\");\n }\n\n /**\n * Evict least recently used entries (Map insertion order) until the size is\n * within `maxSize`. Never evicts `protectedKey` (the key just written).\n */\n protected enforceMaxSize(protectedKey: string) {\n const maxSize = this.options.maxSize;\n\n if (!maxSize) {\n return;\n }\n\n for (const lruKey of [...this.entries.keys()]) {\n if (this.entries.size <= maxSize) {\n break;\n }\n\n if (lruKey === protectedKey) {\n continue;\n }\n\n this.log(\"removing\", lruKey);\n this.dropEntry(lruKey);\n this.log(\"removed\", lruKey);\n }\n }\n\n /**\n * {@inheritdoc}\n *\n * Brute-force O(N) cosine similarity over every entry that was written with\n * `set({ vector })`. Suitable for development and small in-memory knowledge\n * bases — not for production beyond ~10k entries. Use the `pg` driver\n * (with pgvector) or `redis` (with RediSearch) at scale.\n *\n * @warning Dev-only — O(N) per query.\n */\n public async similar<T = any>(\n vector: number[],\n options: CacheSimilarOptions,\n ): Promise<CacheSimilarHit<T>[]> {\n const tagFilter = await this.getKeysForTags(options.tags);\n\n const hits: CacheSimilarHit<T>[] = [];\n\n for (const [parsedKey, stored] of [...this.vectorIndex]) {\n if (tagFilter && !tagFilter.has(parsedKey)) {\n continue;\n }\n\n // Read the entry directly by its already-parsed key — this.get() would\n // parse it again and apply globalPrefix twice, missing every entry.\n const entry = this.readLive(parsedKey);\n\n if (!entry) {\n continue;\n }\n\n const value: any = cloneValue(entry.data);\n\n const score = cosineSimilarity(vector, stored);\n\n if (options.threshold !== undefined && score < options.threshold) {\n continue;\n }\n\n hits.push({ key: parsedKey, value, score });\n }\n\n hits.sort((a, b) => b.score - a.score);\n\n if (options.topK >= 0 && hits.length > options.topK) {\n hits.length = options.topK;\n }\n\n return hits;\n }\n\n /**\n * {@inheritdoc}\n */\n public async disconnect() {\n // Clear the cleanup interval to prevent memory leaks\n if (this.cleanupInterval) {\n clearInterval(this.cleanupInterval);\n this.cleanupInterval = undefined;\n }\n\n await super.disconnect();\n }\n}\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { MemoryCacheDriver } from "./memory-cache-driver.mjs";
2
2
  import { CacheDriver, MemoryExtendedCacheOptions } from "../types.mjs";
3
3
 
4
- //#region ../cache/src/drivers/memory-extended-cache-driver.d.ts
4
+ //#region ../../packages/cache/src/drivers/memory-extended-cache-driver.d.ts
5
5
  /**
6
6
  * Memory driver with a sliding ttl: every live read pushes the entry's
7
7
  * expiration forward by its ttl. The sliding itself lives in
@@ -1 +1 @@
1
- {"version":3,"file":"memory-extended-cache-driver.d.mts","names":[],"sources":["../../../../../../../cache/src/drivers/memory-extended-cache-driver.ts"],"mappings":";;;;;;AAUA;;;;;cAAa,yBAAA,SACH,iBAAA,YACG,WAAA,CAAY,yBAAA,EAA2B,0BAAA;EAAvC;;;EAKJ,IAAA"}
1
+ {"version":3,"file":"memory-extended-cache-driver.d.mts","names":[],"sources":["../../../../../../../../packages/cache/src/drivers/memory-extended-cache-driver.ts"],"mappings":";;;;;;AAUA;;;;;cAAa,yBAAA,SACH,iBAAA,YACG,WAAA,CAAY,yBAAA,EAA2B,0BAAA;EAAvC;;;EAKJ,IAAA"}
@@ -1,6 +1,6 @@
1
1
  import { MemoryCacheDriver } from "./memory-cache-driver.mjs";
2
2
 
3
- //#region ../cache/src/drivers/memory-extended-cache-driver.ts
3
+ //#region ../../packages/cache/src/drivers/memory-extended-cache-driver.ts
4
4
  /**
5
5
  * Memory driver with a sliding ttl: every live read pushes the entry's
6
6
  * expiration forward by its ttl. The sliding itself lives in
@@ -1 +1 @@
1
- {"version":3,"file":"memory-extended-cache-driver.mjs","names":[],"sources":["../../../../../../../cache/src/drivers/memory-extended-cache-driver.ts"],"sourcesContent":["import type { CacheDriver, MemoryExtendedCacheOptions } from \"../types\";\nimport { MemoryCacheDriver } from \"./memory-cache-driver\";\n\n/**\n * Memory driver with a sliding ttl: every live read pushes the entry's\n * expiration forward by its ttl. The sliding itself lives in\n * `MemoryCacheDriver.onRead`, which checks expiry first, so an expired entry\n * is never resurrected and the internal `onConflict` existence check never\n * slides a held lock.\n */\nexport class MemoryExtendedCacheDriver\n extends MemoryCacheDriver\n implements CacheDriver<MemoryExtendedCacheDriver, MemoryExtendedCacheOptions>\n{\n /**\n * {@inheritdoc}\n */\n public name = \"memoryExtended\";\n\n public constructor() {\n super();\n\n this.slidingExpiration = true;\n }\n}\n"],"mappings":";;;;;;;;;;AAUA,IAAa,4BAAb,cACU,kBAEV;CAME,AAAO,cAAc;EACnB,MAAM;cAHM;EAKZ,KAAK,oBAAoB;CAC3B;AACF"}
1
+ {"version":3,"file":"memory-extended-cache-driver.mjs","names":[],"sources":["../../../../../../../../packages/cache/src/drivers/memory-extended-cache-driver.ts"],"sourcesContent":["import type { CacheDriver, MemoryExtendedCacheOptions } from \"../types\";\nimport { MemoryCacheDriver } from \"./memory-cache-driver\";\n\n/**\n * Memory driver with a sliding ttl: every live read pushes the entry's\n * expiration forward by its ttl. The sliding itself lives in\n * `MemoryCacheDriver.onRead`, which checks expiry first, so an expired entry\n * is never resurrected and the internal `onConflict` existence check never\n * slides a held lock.\n */\nexport class MemoryExtendedCacheDriver\n extends MemoryCacheDriver\n implements CacheDriver<MemoryExtendedCacheDriver, MemoryExtendedCacheOptions>\n{\n /**\n * {@inheritdoc}\n */\n public name = \"memoryExtended\";\n\n public constructor() {\n super();\n\n this.slidingExpiration = true;\n }\n}\n"],"mappings":";;;;;;;;;;AAUA,IAAa,4BAAb,cACU,kBAEV;CAME,AAAO,cAAc;EACnB,MAAM;cAHM;EAKZ,KAAK,oBAAoB;CAC3B;AACF"}
@@ -2,7 +2,7 @@ import { BaseCacheDriver } from "./base-cache-driver.mjs";
2
2
  import { InMemoryTagIndex } from "./in-memory-tag-index.mjs";
3
3
  import { CacheCall, CacheData, CacheDriver, CacheKey, CacheSetOptions, CacheTtl, MockCacheOptions } from "../types.mjs";
4
4
 
5
- //#region ../cache/src/drivers/mock-cache-driver.d.ts
5
+ //#region ../../packages/cache/src/drivers/mock-cache-driver.d.ts
6
6
  /**
7
7
  * In-memory cache driver with introspection helpers, intended for use as a
8
8
  * test double in downstream packages.
@@ -1 +1 @@
1
- {"version":3,"file":"mock-cache-driver.d.mts","names":[],"sources":["../../../../../../../cache/src/drivers/mock-cache-driver.ts"],"mappings":";;;;;;;AAsDA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAAa,eAAA,SACH,eAAA,CAAgB,eAAA,EAAiB,gBAAA,aAC9B,WAAA,CAAY,eAAA,EAAiB,gBAAA;EA6SqB;;;EAxStD,IAAA;EA4UmC;;;EAvUnC,OAAA,EAAS,gBAAA;EAVL;;;;EAAA,SAgBK,OAAA,EAAS,GAAA,SAAY,SAAA;EAjBI;;;EAAA,UAsB/B,QAAA,EAAU,gBAAA;EAhBb;;;;;EAAA,SAuBS,OAAA,EAAS,SAAA;EAPf;;;;EAaG,OAAA,IAAW,OAAA;EAAA;;;EAQX,UAAA,IAAc,OAAA;EASE;;;;EAAhB,eAAA,CAAgB,SAAA,WAAoB,OAAA;EAyB/C;;;;EAFW,GAAA,CACX,GAAA,EAAK,QAAA,EACL,KAAA,OACA,YAAA,GAAe,QAAA,GAAW,eAAA,GACzB,OAAA;EAoDO;;;EAAA,UAAA,UAAA,IAAc,KAAA,EAAO,CAAA,GAAI,CAAA;EAAA;;;;EAYtB,GAAA,UAAa,GAAA,EAAK,QAAA,GAAW,OAAA,CAAQ,CAAA;EAAR;;;;EAAA,UAkChC,SAAA,CAAU,SAAA,WAAoB,SAAA;EAoB3B;;;;EAAA,SAAA,CAAU,GAAA,EAAK,QAAA,EAAU,KAAA,YAAoB,OAAA;EA4B7C;;;EAAA,IAAA,UAAc,GAAA,EAAK,QAAA,GAAW,OAAA,CAAQ,CAAA;EAAR;;;;;EAAA,UA4B3B,QAAA,CAAS,GAAA,EAAK,QAAA,GAAW,OAAA,CAAQ,SAAA;EAAA;;;EAkBpC,MAAA,CAAO,GAAA,EAAK,QAAA,GAAW,OAAA;EAAA;;;;;EAiBvB,MAAA,CAAO,MAAA,EAAQ,QAAA,EAAU,OAAA,aAAoB,OAAA;EAO7C;;;EAAA,UAAA,CAAW,MAAA,EAAQ,QAAA,GAAW,OAAA;EAO9B;;;EAAA,SAAA,CAAU,MAAA,EAAQ,QAAA,EAAU,OAAA,aAAoB,OAAA;EAAA;;;EAOhD,SAAA,CAAU,MAAA,EAAQ,QAAA,GAAW,OAAA;EAAA;;;;EAQ7B,KAAA,IAAS,OAAA;EAqBoB;;;;;;;;;;EAAnC,SAAA,CAAU,SAAA,UAAmB,GAAA,GAAM,QAAA;EA+CxC;;AAAoB;;;;;EA5Bf,SAAA,UAAmB,GAAA,EAAK,QAAA,GAAW,CAAA;;;;;EAenC,KAAA;;;;;YAUG,UAAA,CACR,SAAA,UACA,GAAA,sBACA,IAAA;AAAA"}
1
+ {"version":3,"file":"mock-cache-driver.d.mts","names":[],"sources":["../../../../../../../../packages/cache/src/drivers/mock-cache-driver.ts"],"mappings":";;;;;;;AAuDA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAAa,eAAA,SACH,eAAA,CAAgB,eAAA,EAAiB,gBAAA,aAC9B,WAAA,CAAY,eAAA,EAAiB,gBAAA;EA6SqB;;;EAxStD,IAAA;EA4UmC;;;EAvUnC,OAAA,EAAS,gBAAA;EAVL;;;;EAAA,SAgBK,OAAA,EAAS,GAAA,SAAY,SAAA;EAjBI;;;EAAA,UAsB/B,QAAA,EAAU,gBAAA;EAhBb;;;;;EAAA,SAuBS,OAAA,EAAS,SAAA;EAPf;;;;EAaG,OAAA,IAAW,OAAA;EAAA;;;EAQX,UAAA,IAAc,OAAA;EASE;;;;EAAhB,eAAA,CAAgB,SAAA,WAAoB,OAAA;EAyB/C;;;;EAFW,GAAA,CACX,GAAA,EAAK,QAAA,EACL,KAAA,OACA,YAAA,GAAe,QAAA,GAAW,eAAA,GACzB,OAAA;EAoDO;;;EAAA,UAAA,UAAA,IAAc,KAAA,EAAO,CAAA,GAAI,CAAA;EAAA;;;;EAYtB,GAAA,UAAa,GAAA,EAAK,QAAA,GAAW,OAAA,CAAQ,CAAA;EAAR;;;;EAAA,UAkChC,SAAA,CAAU,SAAA,WAAoB,SAAA;EAoB3B;;;;EAAA,SAAA,CAAU,GAAA,EAAK,QAAA,EAAU,KAAA,YAAoB,OAAA;EA4B7C;;;EAAA,IAAA,UAAc,GAAA,EAAK,QAAA,GAAW,OAAA,CAAQ,CAAA;EAAR;;;;;EAAA,UA4B3B,QAAA,CAAS,GAAA,EAAK,QAAA,GAAW,OAAA,CAAQ,SAAA;EAAA;;;EAkBpC,MAAA,CAAO,GAAA,EAAK,QAAA,GAAW,OAAA;EAAA;;;;;EAiBvB,MAAA,CAAO,MAAA,EAAQ,QAAA,EAAU,OAAA,aAAoB,OAAA;EAO7C;;;EAAA,UAAA,CAAW,MAAA,EAAQ,QAAA,GAAW,OAAA;EAO9B;;;EAAA,SAAA,CAAU,MAAA,EAAQ,QAAA,EAAU,OAAA,aAAoB,OAAA;EAAA;;;EAOhD,SAAA,CAAU,MAAA,EAAQ,QAAA,GAAW,OAAA;EAAA;;;;EAQ7B,KAAA,IAAS,OAAA;EAqBoB;;;;;;;;;;EAAnC,SAAA,CAAU,SAAA,UAAmB,GAAA,GAAM,QAAA;EA+CxC;;AAAoB;;;;;EA5Bf,SAAA,UAAmB,GAAA,EAAK,QAAA,GAAW,CAAA;;;;;EAenC,KAAA;;;;;YAUG,UAAA,CACR,SAAA,UACA,GAAA,sBACA,IAAA;AAAA"}
@@ -1,7 +1,8 @@
1
1
  import { BaseCacheDriver } from "./base-cache-driver.mjs";
2
2
  import { InMemoryTagIndex } from "./in-memory-tag-index.mjs";
3
+ import { maskEmailsInText } from "@warlock.js/logger";
3
4
 
4
- //#region ../cache/src/drivers/mock-cache-driver.ts
5
+ //#region ../../packages/cache/src/drivers/mock-cache-driver.ts
5
6
  /**
6
7
  * In-memory cache driver with introspection helpers, intended for use as a
7
8
  * test double in downstream packages.
@@ -172,7 +173,7 @@ var MockCacheDriver = class extends BaseCacheDriver {
172
173
  this.recordCall("increment", parsedKey, [value]);
173
174
  const entry = this.liveEntry(parsedKey);
174
175
  const current = entry ? entry.data : 0;
175
- if (typeof current !== "number") throw new Error(`Cannot increment non-numeric value for key: ${parsedKey}`);
176
+ if (typeof current !== "number") throw new Error(`Cannot increment non-numeric value for key: ${maskEmailsInText(parsedKey)}`);
176
177
  const newValue = current + value;
177
178
  if (entry) entry.data = newValue;
178
179
  else this.storage.set(parsedKey, this.prepareDataForStorage(newValue, this.ttl));
@@ -1 +1 @@
1
- {"version":3,"file":"mock-cache-driver.mjs","names":[],"sources":["../../../../../../../cache/src/drivers/mock-cache-driver.ts"],"sourcesContent":["import type {\n CacheCall,\n CacheData,\n CacheDriver,\n CacheKey,\n CacheSetOptions,\n CacheSetResult,\n CacheTtl,\n MockCacheOptions,\n} from \"../types\";\nimport { BaseCacheDriver } from \"./base-cache-driver\";\nimport { InMemoryTagIndex } from \"./in-memory-tag-index\";\n\n/**\n * In-memory cache driver with introspection helpers, intended for use as a\n * test double in downstream packages.\n *\n * **Role.** Drop-in replacement for any real driver in test setups, with\n * extra surface that makes behavioral assertions easy: every public op gets\n * recorded into {@link MockCacheDriver.callLog}, and {@link wasCalled} /\n * {@link getStored} / {@link reset} let tests verify side effects without\n * pulling in a real Redis / Postgres / file system.\n *\n * **Responsibility.**\n * - Owns: in-memory storage backed by a `Map`, the `callLog`, TTL handling\n * via `parseCachedData`, `onConflict` policies, and tag-index storage.\n * - Does NOT own: similarity retrieval (vectors are recorded into the\n * `callLog` but `similar()` throws — use `MemoryCacheDriver` for tests\n * that need real nearest-neighbor scoring), connection lifecycle\n * (no-op `connect`/`disconnect`), or eviction (no `maxSize`).\n *\n * Register it like any other driver — sub-paths are not part of the\n * package's export convention; the same single barrel ships it next to\n * the production drivers.\n *\n * @example\n * import { cache, MockCacheDriver } from \"@warlock.js/cache\";\n *\n * beforeEach(async () => {\n * cache.setCacheConfigurations({\n * default: \"mock\",\n * drivers: { mock: MockCacheDriver },\n * options: { mock: {} },\n * });\n * await cache.init();\n * });\n *\n * it(\"invalidates the user cache after update\", async () => {\n * await userService.update(42, { name: \"Jane\" });\n *\n * const driver = cache.currentDriver as MockCacheDriver;\n * expect(driver.wasCalled(\"remove\", \"users.42\")).toBe(true);\n * });\n */\nexport class MockCacheDriver\n extends BaseCacheDriver<MockCacheDriver, MockCacheOptions>\n implements CacheDriver<MockCacheDriver, MockCacheOptions>\n{\n /**\n * {@inheritdoc}\n */\n public name = \"mock\";\n\n /**\n * {@inheritdoc}\n */\n public options: MockCacheOptions = {};\n\n /**\n * Storage backing the mock — keyed by post-`parseKey` string. Public-readonly\n * so tests can introspect raw entries when {@link getStored} isn't enough.\n */\n public readonly storage: Map<string, CacheData> = new Map();\n\n /**\n * Tag index, kept apart from {@link storage} (same model as the memory driver).\n */\n protected tagIndex: InMemoryTagIndex = new InMemoryTagIndex();\n\n /**\n * Ordered record of every public operation routed through this driver.\n * Pushed to before each op runs; tests assert via {@link wasCalled} or by\n * inspecting the array directly.\n */\n public readonly callLog: CacheCall[] = [];\n\n /**\n * Standard driver setup. Mirrors the null driver — no connection, no\n * resources to release.\n */\n public async connect(): Promise<void> {\n this.recordCall(\"connect\", undefined);\n await super.connect();\n }\n\n /**\n * Standard driver teardown.\n */\n public async disconnect(): Promise<void> {\n this.recordCall(\"disconnect\", undefined);\n await super.disconnect();\n }\n\n /**\n * Wipe everything under `namespace`. Matches `MemoryCacheDriver` semantics\n * — the namespace itself and any key with the namespace prefix is removed.\n */\n public async removeNamespace(namespace: string): Promise<void> {\n const parsed = this.parseKey(namespace);\n\n this.recordCall(\"removeNamespace\", parsed, [namespace]);\n this.log(\"clearing\", parsed);\n\n const prefix = parsed + \".\";\n\n this.tagIndex.removeNamespace(parsed);\n\n for (const key of [...this.storage.keys()]) {\n if (key === parsed || key.startsWith(prefix)) {\n this.storage.delete(key);\n }\n }\n\n this.log(\"cleared\", parsed);\n }\n\n /**\n * Standard `set` with full `onConflict` support. Honors scope-default TTL\n * via {@link BaseCacheDriver.resolveSetOptions}.\n */\n public async set(\n key: CacheKey,\n value: any,\n ttlOrOptions?: CacheTtl | CacheSetOptions,\n ): Promise<any> {\n const parsedKey = this.parseKey(key);\n const { ttl, tags, onConflict, staleAt } = this.resolveSetOptions(ttlOrOptions);\n\n this.recordCall(\"set\", parsedKey, [value, ttlOrOptions]);\n this.log(\"caching\", parsedKey);\n\n // Synchronous check + write (no await between) so onConflict is atomic.\n // Expired entries count as missing and are deleted.\n let existing = onConflict === \"create\" || onConflict === \"update\"\n ? this.storage.get(parsedKey)\n : undefined;\n\n if (existing && existing.expiresAt !== undefined && existing.expiresAt <= Date.now()) {\n this.storage.delete(parsedKey);\n existing = undefined;\n }\n\n if (onConflict === \"create\" && existing) {\n const result: CacheSetResult = { wasSet: false, existing: this.cloneValue(existing.data) };\n\n return result;\n }\n\n if (onConflict === \"update\" && !existing) {\n const result: CacheSetResult = { wasSet: false, existing: null };\n\n return result;\n }\n\n const data = this.prepareDataForStorage(this.cloneValue(value), ttl, staleAt);\n this.storage.set(parsedKey, data);\n\n if (tags && tags.length > 0) {\n await this.applyTags(key, tags);\n }\n\n this.log(\"cached\", parsedKey);\n await this.emit(\"set\", { key: parsedKey, value, ttl });\n\n if (onConflict === \"create\" || onConflict === \"update\") {\n const result: CacheSetResult = { wasSet: true, existing: null };\n\n return result;\n }\n\n return this;\n }\n\n /**\n * Clone non-primitive values so stored state can't be mutated by callers.\n */\n protected cloneValue<T>(value: T): T {\n if (value === null || value === undefined || typeof value !== \"object\") {\n return value;\n }\n\n return structuredClone(value);\n }\n\n /**\n * Standard `get` with TTL handling. Emits `hit` / `miss` events to keep\n * downstream metrics tests realistic.\n */\n public async get<T = any>(key: CacheKey): Promise<T | null> {\n const parsedKey = this.parseKey(key);\n\n this.recordCall(\"get\", parsedKey);\n this.log(\"fetching\", parsedKey);\n\n const data = this.storage.get(parsedKey);\n\n if (!data) {\n this.log(\"notFound\", parsedKey);\n await this.emit(\"miss\", { key: parsedKey });\n\n return null;\n }\n\n const value = await this.parseCachedData(parsedKey, data);\n\n if (value === null) {\n // expired — the parse helper already logged + queued the cleanup\n this.storage.delete(parsedKey);\n await this.emit(\"miss\", { key: parsedKey });\n\n return null;\n }\n\n await this.emit(\"hit\", { key: parsedKey, value });\n\n return value as T;\n }\n\n /**\n * Live entry for `parsedKey`, or `undefined` when missing / expired (an\n * expired entry is deleted). Synchronous.\n */\n protected liveEntry(parsedKey: string): CacheData | undefined {\n const entry = this.storage.get(parsedKey);\n\n if (!entry) {\n return undefined;\n }\n\n if (entry.expiresAt !== undefined && entry.expiresAt <= Date.now()) {\n this.storage.delete(parsedKey);\n\n return undefined;\n }\n\n return entry;\n }\n\n /**\n * Synchronous read-add-write (atomic within the process). Keeps an existing\n * entry's expiry; a missing key starts from 0 with the default TTL.\n */\n public async increment(key: CacheKey, value: number = 1): Promise<number> {\n const parsedKey = this.parseKey(key);\n\n this.recordCall(\"increment\", parsedKey, [value]);\n\n const entry = this.liveEntry(parsedKey);\n const current = entry ? entry.data : 0;\n\n if (typeof current !== \"number\") {\n throw new Error(`Cannot increment non-numeric value for key: ${parsedKey}`);\n }\n\n const newValue = current + value;\n\n if (entry) {\n entry.data = newValue;\n } else {\n this.storage.set(parsedKey, this.prepareDataForStorage(newValue, this.ttl));\n }\n\n await this.emit(\"set\", { key: parsedKey, value: newValue, ttl: this.ttl });\n\n return newValue;\n }\n\n /**\n * Synchronous read-and-delete: a value is handed out exactly once.\n */\n public async pull<T = any>(key: CacheKey): Promise<T | null> {\n const parsedKey = this.parseKey(key);\n\n this.recordCall(\"pull\", parsedKey);\n\n const entry = this.liveEntry(parsedKey);\n\n if (!entry) {\n await this.emit(\"miss\", { key: parsedKey });\n\n return null;\n }\n\n this.storage.delete(parsedKey);\n\n const value = this.cloneValue(entry.data) as T;\n\n await this.emit(\"hit\", { key: parsedKey, value });\n await this.emit(\"removed\", { key: parsedKey });\n\n return value;\n }\n\n /**\n * Read the raw {@link CacheData} wrapper from the in-memory `Map`,\n * including `staleAt` metadata. Returns `null` for missing or expired\n * entries — `swr()` consumes this to branch on freshness.\n */\n protected async getEntry(key: CacheKey): Promise<CacheData | null> {\n const parsedKey = this.parseKey(key);\n const entry = this.storage.get(parsedKey);\n\n if (!entry) {\n return null;\n }\n\n if (entry.expiresAt !== undefined && entry.expiresAt <= Date.now()) {\n return null;\n }\n\n return { ...entry, data: this.cloneValue(entry.data) };\n }\n\n /**\n * Standard `remove` — drops the entry and emits the `removed` event.\n */\n public async remove(key: CacheKey): Promise<void> {\n const parsedKey = this.parseKey(key);\n\n this.recordCall(\"remove\", parsedKey);\n this.log(\"removing\", parsedKey);\n\n this.storage.delete(parsedKey);\n\n this.log(\"removed\", parsedKey);\n await this.emit(\"removed\", { key: parsedKey });\n }\n\n /**\n * {@inheritdoc}\n *\n * Synchronous in-process set, never evicted or expired with the entries.\n */\n public async tagAdd(tagKey: CacheKey, members: string[]): Promise<void> {\n this.tagIndex.add(this.parseKey(tagKey), members);\n }\n\n /**\n * {@inheritdoc}\n */\n public async tagMembers(tagKey: CacheKey): Promise<string[]> {\n return this.tagIndex.members(this.parseKey(tagKey));\n }\n\n /**\n * {@inheritdoc}\n */\n public async tagRemove(tagKey: CacheKey, members: string[]): Promise<void> {\n this.tagIndex.remove(this.parseKey(tagKey), members);\n }\n\n /**\n * {@inheritdoc}\n */\n public async tagDelete(tagKey: CacheKey): Promise<void> {\n this.tagIndex.delete(this.parseKey(tagKey));\n }\n\n /**\n * Standard `flush` — wipes the entire mock store + tag index. Does NOT\n * touch the call log; use {@link reset} to clear that as well.\n */\n public async flush(): Promise<void> {\n this.recordCall(\"flush\", undefined);\n this.log(\"flushing\");\n\n this.storage.clear();\n this.tagIndex.clear();\n\n this.log(\"flushed\");\n await this.emit(\"flushed\");\n }\n\n /**\n * Was a given operation invoked? When `key` is provided, the match is\n * post-`parseKey` so callers pass the same key shape they used at the\n * call site — strings or objects, both resolve to the same parsed key.\n *\n * @example\n * driver.wasCalled(\"set\"); // any set\n * driver.wasCalled(\"set\", \"users.42\"); // set on this specific key\n * driver.wasCalled(\"set\", { id: 42 }); // same — object key normalized\n */\n public wasCalled(operation: string, key?: CacheKey): boolean {\n if (key === undefined) {\n return this.callLog.some((call) => call.operation === operation);\n }\n\n const parsedKey = this.parseKey(key);\n\n return this.callLog.some(\n (call) => call.operation === operation && call.key === parsedKey,\n );\n }\n\n /**\n * Return the raw stored value for `key`, bypassing TTL handling and clone\n * protection. Useful when a test wants to assert on the persisted shape\n * (or assert that an entry expired without going through `get`).\n *\n * Returns `undefined` when the key isn't present.\n */\n public getStored<T = any>(key: CacheKey): T | undefined {\n const parsedKey = this.parseKey(key);\n const entry = this.storage.get(parsedKey);\n\n if (!entry) {\n return undefined;\n }\n\n return entry.data as T;\n }\n\n /**\n * Wipe everything — storage, tag index, and the call log. Pair with\n * Vitest's `beforeEach` to get clean isolation between tests.\n */\n public reset(): void {\n this.storage.clear();\n this.tagIndex.clear();\n this.callLog.length = 0;\n }\n\n /**\n * Append a row to {@link callLog}. Internal helper called by every\n * recorded op before the actual work runs.\n */\n protected recordCall(\n operation: string,\n key: string | undefined,\n args: unknown[] = [],\n ): void {\n this.callLog.push({\n operation,\n key,\n args,\n timestamp: Date.now(),\n });\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"mock-cache-driver.mjs","names":[],"sources":["../../../../../../../../packages/cache/src/drivers/mock-cache-driver.ts"],"sourcesContent":["import { maskEmailsInText } from \"@warlock.js/logger\";\nimport type {\n CacheCall,\n CacheData,\n CacheDriver,\n CacheKey,\n CacheSetOptions,\n CacheSetResult,\n CacheTtl,\n MockCacheOptions,\n} from \"../types\";\nimport { BaseCacheDriver } from \"./base-cache-driver\";\nimport { InMemoryTagIndex } from \"./in-memory-tag-index\";\n\n/**\n * In-memory cache driver with introspection helpers, intended for use as a\n * test double in downstream packages.\n *\n * **Role.** Drop-in replacement for any real driver in test setups, with\n * extra surface that makes behavioral assertions easy: every public op gets\n * recorded into {@link MockCacheDriver.callLog}, and {@link wasCalled} /\n * {@link getStored} / {@link reset} let tests verify side effects without\n * pulling in a real Redis / Postgres / file system.\n *\n * **Responsibility.**\n * - Owns: in-memory storage backed by a `Map`, the `callLog`, TTL handling\n * via `parseCachedData`, `onConflict` policies, and tag-index storage.\n * - Does NOT own: similarity retrieval (vectors are recorded into the\n * `callLog` but `similar()` throws — use `MemoryCacheDriver` for tests\n * that need real nearest-neighbor scoring), connection lifecycle\n * (no-op `connect`/`disconnect`), or eviction (no `maxSize`).\n *\n * Register it like any other driver — sub-paths are not part of the\n * package's export convention; the same single barrel ships it next to\n * the production drivers.\n *\n * @example\n * import { cache, MockCacheDriver } from \"@warlock.js/cache\";\n *\n * beforeEach(async () => {\n * cache.setCacheConfigurations({\n * default: \"mock\",\n * drivers: { mock: MockCacheDriver },\n * options: { mock: {} },\n * });\n * await cache.init();\n * });\n *\n * it(\"invalidates the user cache after update\", async () => {\n * await userService.update(42, { name: \"Jane\" });\n *\n * const driver = cache.currentDriver as MockCacheDriver;\n * expect(driver.wasCalled(\"remove\", \"users.42\")).toBe(true);\n * });\n */\nexport class MockCacheDriver\n extends BaseCacheDriver<MockCacheDriver, MockCacheOptions>\n implements CacheDriver<MockCacheDriver, MockCacheOptions>\n{\n /**\n * {@inheritdoc}\n */\n public name = \"mock\";\n\n /**\n * {@inheritdoc}\n */\n public options: MockCacheOptions = {};\n\n /**\n * Storage backing the mock — keyed by post-`parseKey` string. Public-readonly\n * so tests can introspect raw entries when {@link getStored} isn't enough.\n */\n public readonly storage: Map<string, CacheData> = new Map();\n\n /**\n * Tag index, kept apart from {@link storage} (same model as the memory driver).\n */\n protected tagIndex: InMemoryTagIndex = new InMemoryTagIndex();\n\n /**\n * Ordered record of every public operation routed through this driver.\n * Pushed to before each op runs; tests assert via {@link wasCalled} or by\n * inspecting the array directly.\n */\n public readonly callLog: CacheCall[] = [];\n\n /**\n * Standard driver setup. Mirrors the null driver — no connection, no\n * resources to release.\n */\n public async connect(): Promise<void> {\n this.recordCall(\"connect\", undefined);\n await super.connect();\n }\n\n /**\n * Standard driver teardown.\n */\n public async disconnect(): Promise<void> {\n this.recordCall(\"disconnect\", undefined);\n await super.disconnect();\n }\n\n /**\n * Wipe everything under `namespace`. Matches `MemoryCacheDriver` semantics\n * — the namespace itself and any key with the namespace prefix is removed.\n */\n public async removeNamespace(namespace: string): Promise<void> {\n const parsed = this.parseKey(namespace);\n\n this.recordCall(\"removeNamespace\", parsed, [namespace]);\n this.log(\"clearing\", parsed);\n\n const prefix = parsed + \".\";\n\n this.tagIndex.removeNamespace(parsed);\n\n for (const key of [...this.storage.keys()]) {\n if (key === parsed || key.startsWith(prefix)) {\n this.storage.delete(key);\n }\n }\n\n this.log(\"cleared\", parsed);\n }\n\n /**\n * Standard `set` with full `onConflict` support. Honors scope-default TTL\n * via {@link BaseCacheDriver.resolveSetOptions}.\n */\n public async set(\n key: CacheKey,\n value: any,\n ttlOrOptions?: CacheTtl | CacheSetOptions,\n ): Promise<any> {\n const parsedKey = this.parseKey(key);\n const { ttl, tags, onConflict, staleAt } = this.resolveSetOptions(ttlOrOptions);\n\n this.recordCall(\"set\", parsedKey, [value, ttlOrOptions]);\n this.log(\"caching\", parsedKey);\n\n // Synchronous check + write (no await between) so onConflict is atomic.\n // Expired entries count as missing and are deleted.\n let existing = onConflict === \"create\" || onConflict === \"update\"\n ? this.storage.get(parsedKey)\n : undefined;\n\n if (existing && existing.expiresAt !== undefined && existing.expiresAt <= Date.now()) {\n this.storage.delete(parsedKey);\n existing = undefined;\n }\n\n if (onConflict === \"create\" && existing) {\n const result: CacheSetResult = { wasSet: false, existing: this.cloneValue(existing.data) };\n\n return result;\n }\n\n if (onConflict === \"update\" && !existing) {\n const result: CacheSetResult = { wasSet: false, existing: null };\n\n return result;\n }\n\n const data = this.prepareDataForStorage(this.cloneValue(value), ttl, staleAt);\n this.storage.set(parsedKey, data);\n\n if (tags && tags.length > 0) {\n await this.applyTags(key, tags);\n }\n\n this.log(\"cached\", parsedKey);\n await this.emit(\"set\", { key: parsedKey, value, ttl });\n\n if (onConflict === \"create\" || onConflict === \"update\") {\n const result: CacheSetResult = { wasSet: true, existing: null };\n\n return result;\n }\n\n return this;\n }\n\n /**\n * Clone non-primitive values so stored state can't be mutated by callers.\n */\n protected cloneValue<T>(value: T): T {\n if (value === null || value === undefined || typeof value !== \"object\") {\n return value;\n }\n\n return structuredClone(value);\n }\n\n /**\n * Standard `get` with TTL handling. Emits `hit` / `miss` events to keep\n * downstream metrics tests realistic.\n */\n public async get<T = any>(key: CacheKey): Promise<T | null> {\n const parsedKey = this.parseKey(key);\n\n this.recordCall(\"get\", parsedKey);\n this.log(\"fetching\", parsedKey);\n\n const data = this.storage.get(parsedKey);\n\n if (!data) {\n this.log(\"notFound\", parsedKey);\n await this.emit(\"miss\", { key: parsedKey });\n\n return null;\n }\n\n const value = await this.parseCachedData(parsedKey, data);\n\n if (value === null) {\n // expired — the parse helper already logged + queued the cleanup\n this.storage.delete(parsedKey);\n await this.emit(\"miss\", { key: parsedKey });\n\n return null;\n }\n\n await this.emit(\"hit\", { key: parsedKey, value });\n\n return value as T;\n }\n\n /**\n * Live entry for `parsedKey`, or `undefined` when missing / expired (an\n * expired entry is deleted). Synchronous.\n */\n protected liveEntry(parsedKey: string): CacheData | undefined {\n const entry = this.storage.get(parsedKey);\n\n if (!entry) {\n return undefined;\n }\n\n if (entry.expiresAt !== undefined && entry.expiresAt <= Date.now()) {\n this.storage.delete(parsedKey);\n\n return undefined;\n }\n\n return entry;\n }\n\n /**\n * Synchronous read-add-write (atomic within the process). Keeps an existing\n * entry's expiry; a missing key starts from 0 with the default TTL.\n */\n public async increment(key: CacheKey, value: number = 1): Promise<number> {\n const parsedKey = this.parseKey(key);\n\n this.recordCall(\"increment\", parsedKey, [value]);\n\n const entry = this.liveEntry(parsedKey);\n const current = entry ? entry.data : 0;\n\n if (typeof current !== \"number\") {\n throw new Error(`Cannot increment non-numeric value for key: ${maskEmailsInText(parsedKey)}`);\n }\n\n const newValue = current + value;\n\n if (entry) {\n entry.data = newValue;\n } else {\n this.storage.set(parsedKey, this.prepareDataForStorage(newValue, this.ttl));\n }\n\n await this.emit(\"set\", { key: parsedKey, value: newValue, ttl: this.ttl });\n\n return newValue;\n }\n\n /**\n * Synchronous read-and-delete: a value is handed out exactly once.\n */\n public async pull<T = any>(key: CacheKey): Promise<T | null> {\n const parsedKey = this.parseKey(key);\n\n this.recordCall(\"pull\", parsedKey);\n\n const entry = this.liveEntry(parsedKey);\n\n if (!entry) {\n await this.emit(\"miss\", { key: parsedKey });\n\n return null;\n }\n\n this.storage.delete(parsedKey);\n\n const value = this.cloneValue(entry.data) as T;\n\n await this.emit(\"hit\", { key: parsedKey, value });\n await this.emit(\"removed\", { key: parsedKey });\n\n return value;\n }\n\n /**\n * Read the raw {@link CacheData} wrapper from the in-memory `Map`,\n * including `staleAt` metadata. Returns `null` for missing or expired\n * entries — `swr()` consumes this to branch on freshness.\n */\n protected async getEntry(key: CacheKey): Promise<CacheData | null> {\n const parsedKey = this.parseKey(key);\n const entry = this.storage.get(parsedKey);\n\n if (!entry) {\n return null;\n }\n\n if (entry.expiresAt !== undefined && entry.expiresAt <= Date.now()) {\n return null;\n }\n\n return { ...entry, data: this.cloneValue(entry.data) };\n }\n\n /**\n * Standard `remove` — drops the entry and emits the `removed` event.\n */\n public async remove(key: CacheKey): Promise<void> {\n const parsedKey = this.parseKey(key);\n\n this.recordCall(\"remove\", parsedKey);\n this.log(\"removing\", parsedKey);\n\n this.storage.delete(parsedKey);\n\n this.log(\"removed\", parsedKey);\n await this.emit(\"removed\", { key: parsedKey });\n }\n\n /**\n * {@inheritdoc}\n *\n * Synchronous in-process set, never evicted or expired with the entries.\n */\n public async tagAdd(tagKey: CacheKey, members: string[]): Promise<void> {\n this.tagIndex.add(this.parseKey(tagKey), members);\n }\n\n /**\n * {@inheritdoc}\n */\n public async tagMembers(tagKey: CacheKey): Promise<string[]> {\n return this.tagIndex.members(this.parseKey(tagKey));\n }\n\n /**\n * {@inheritdoc}\n */\n public async tagRemove(tagKey: CacheKey, members: string[]): Promise<void> {\n this.tagIndex.remove(this.parseKey(tagKey), members);\n }\n\n /**\n * {@inheritdoc}\n */\n public async tagDelete(tagKey: CacheKey): Promise<void> {\n this.tagIndex.delete(this.parseKey(tagKey));\n }\n\n /**\n * Standard `flush` — wipes the entire mock store + tag index. Does NOT\n * touch the call log; use {@link reset} to clear that as well.\n */\n public async flush(): Promise<void> {\n this.recordCall(\"flush\", undefined);\n this.log(\"flushing\");\n\n this.storage.clear();\n this.tagIndex.clear();\n\n this.log(\"flushed\");\n await this.emit(\"flushed\");\n }\n\n /**\n * Was a given operation invoked? When `key` is provided, the match is\n * post-`parseKey` so callers pass the same key shape they used at the\n * call site — strings or objects, both resolve to the same parsed key.\n *\n * @example\n * driver.wasCalled(\"set\"); // any set\n * driver.wasCalled(\"set\", \"users.42\"); // set on this specific key\n * driver.wasCalled(\"set\", { id: 42 }); // same — object key normalized\n */\n public wasCalled(operation: string, key?: CacheKey): boolean {\n if (key === undefined) {\n return this.callLog.some((call) => call.operation === operation);\n }\n\n const parsedKey = this.parseKey(key);\n\n return this.callLog.some(\n (call) => call.operation === operation && call.key === parsedKey,\n );\n }\n\n /**\n * Return the raw stored value for `key`, bypassing TTL handling and clone\n * protection. Useful when a test wants to assert on the persisted shape\n * (or assert that an entry expired without going through `get`).\n *\n * Returns `undefined` when the key isn't present.\n */\n public getStored<T = any>(key: CacheKey): T | undefined {\n const parsedKey = this.parseKey(key);\n const entry = this.storage.get(parsedKey);\n\n if (!entry) {\n return undefined;\n }\n\n return entry.data as T;\n }\n\n /**\n * Wipe everything — storage, tag index, and the call log. Pair with\n * Vitest's `beforeEach` to get clean isolation between tests.\n */\n public reset(): void {\n this.storage.clear();\n this.tagIndex.clear();\n this.callLog.length = 0;\n }\n\n /**\n * Append a row to {@link callLog}. Internal helper called by every\n * recorded op before the actual work runs.\n */\n protected recordCall(\n operation: string,\n key: string | undefined,\n args: unknown[] = [],\n ): void {\n this.callLog.push({\n operation,\n key,\n args,\n timestamp: Date.now(),\n });\n }\n}\n"],"mappings":"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"}
@@ -2,7 +2,7 @@ import { BaseCacheDriver } from "./base-cache-driver.mjs";
2
2
  import { CacheDriver, CacheKey, CacheSetOptions, CacheTtl, NullCacheDriverOptions, RememberOptions } from "../types.mjs";
3
3
  import { GenericObject } from "@mongez/reinforcements";
4
4
 
5
- //#region ../cache/src/drivers/null-cache-driver.d.ts
5
+ //#region ../../packages/cache/src/drivers/null-cache-driver.d.ts
6
6
  declare class NullCacheDriver extends BaseCacheDriver<NullCacheDriver, NullCacheDriverOptions> implements CacheDriver<NullCacheDriver, NullCacheDriverOptions> {
7
7
  /**
8
8
  * Options list
@@ -42,6 +42,10 @@ declare class NullCacheDriver extends BaseCacheDriver<NullCacheDriver, NullCache
42
42
  * {@inheritdoc}
43
43
  */
44
44
  removeNamespace(namespace: string): Promise<this>;
45
+ /**
46
+ * The key as it may appear in a log line: parsed, with email addresses masked
47
+ */
48
+ protected loggableKey(key: CacheKey): string;
45
49
  /**
46
50
  * {@inheritdoc}
47
51
  */
@@ -1 +1 @@
1
- {"version":3,"file":"null-cache-driver.d.mts","names":[],"sources":["../../../../../../../cache/src/drivers/null-cache-driver.ts"],"mappings":";;;;;cAYa,eAAA,SACH,eAAA,CAAgB,eAAA,EAAiB,sBAAA,aAC9B,WAAA,CAAY,eAAA,EAAiB,sBAAA;;AAF1C;;EAOS,OAAA,EAAS,aAAA;EANQ;;;EAWjB,IAAA;EALS;;;EAUT,IAAA,EAAM,aAAA;EA4BQ;;;EAAA,IAvBV,MAAA;EAoCO;;;cA7BC,OAAA,GAAS,aAAA;EAmDV;;;EA3CX,UAAA,CAAW,OAAA,EAAS,aAAA;EAuDG;;;EA/CvB,QAAA,CAAS,GAAA,EAAK,QAAA;EA+EG;;;;;EArEX,QAAA,CACX,IAAA,EAAM,QAAA,EACN,aAAA,EAAe,QAAA,GAAW,eAAA,EAC1B,QAAA,QAAgB,OAAA,QACf,OAAA;EA1DK;;;EAiEK,eAAA,CAAgB,SAAA,WAAiB,OAAA;EAhEvB;;;EA2EV,GAAA,CACX,GAAA,EAAK,QAAA,EACL,MAAA,OACA,aAAA,GAAgB,QAAA,GAAW,eAAA,GAC1B,OAAA;EArEI;;;EAgFM,GAAA,CAAI,GAAA,EAAK,QAAA,GAAQ,OAAA;;;;EAWjB,MAAA,CAAO,GAAA,EAAK,QAAA,GAAQ,OAAA;EAlEN;;;EA2Ed,KAAA,IAAK,OAAA;EAnEF;;;;;;EA+EH,OAAA,IAAW,OAAA;EAlEN;;;EAyEL,OAAA,IAAO,OAAA;AAAA"}
1
+ {"version":3,"file":"null-cache-driver.d.mts","names":[],"sources":["../../../../../../../../packages/cache/src/drivers/null-cache-driver.ts"],"mappings":";;;;;cAYa,eAAA,SACH,eAAA,CAAgB,eAAA,EAAiB,sBAAA,aAC9B,WAAA,CAAY,eAAA,EAAiB,sBAAA;;AAF1C;;EAOS,OAAA,EAAS,aAAA;EANQ;;;EAWjB,IAAA;EALS;;;EAUT,IAAA,EAAM,aAAA;EA4BQ;;;EAAA,IAvBV,MAAA;EAoCO;;;cA7BC,OAAA,GAAS,aAAA;EA0DrB;;;EAlDA,UAAA,CAAW,OAAA,EAAS,aAAA;EAgEL;;;EAxDf,QAAA,CAAS,GAAA,EAAK,QAAA;EA4EH;;;;;EAlEL,QAAA,CACX,IAAA,EAAM,QAAA,EACN,aAAA,EAAe,QAAA,GAAW,eAAA,EAC1B,QAAA,QAAgB,OAAA,QACf,OAAA;EAzDmB;;;EAgET,eAAA,CAAgB,SAAA,WAAiB,OAAA;EAhEnC;;;EAAA,UA6ED,WAAA,CAAY,GAAA,EAAK,QAAA;EAxEX;;;EA+EH,GAAA,CACX,GAAA,EAAK,QAAA,EACL,MAAA,OACA,aAAA,GAAgB,QAAA,GAAW,eAAA,GAC1B,OAAA;EApEQ;;;EA+EE,GAAA,CAAI,GAAA,EAAK,QAAA,GAAQ,OAAA;EAhEvB;;;EA2EM,MAAA,CAAO,GAAA,EAAK,QAAA,GAAQ,OAAA;EAnEZ;;;EA4ER,KAAA,IAAK,OAAA;EAjEhB;;;;;;EA6EW,OAAA,IAAW,OAAA;EAnEX;;;EA0EA,OAAA,IAAO,OAAA;AAAA"}
@@ -1,7 +1,7 @@
1
1
  import { BaseCacheDriver } from "./base-cache-driver.mjs";
2
- import { log } from "@warlock.js/logger";
2
+ import { log, maskEmailsInText } from "@warlock.js/logger";
3
3
 
4
- //#region ../cache/src/drivers/null-cache-driver.ts
4
+ //#region ../../packages/cache/src/drivers/null-cache-driver.ts
5
5
  var NullCacheDriver = class extends BaseCacheDriver {
6
6
  /**
7
7
  * {@inheritdoc}
@@ -44,32 +44,39 @@ var NullCacheDriver = class extends BaseCacheDriver {
44
44
  * {@inheritdoc}
45
45
  */
46
46
  async removeNamespace(namespace) {
47
- log.info("cache", "clearing namespace", namespace);
48
- log.success("cache", "namespace cleared", namespace);
47
+ const loggableNamespace = maskEmailsInText(namespace);
48
+ log.info("cache", "clearing namespace", loggableNamespace);
49
+ log.success("cache", "namespace cleared", loggableNamespace);
49
50
  return this;
50
51
  }
51
52
  /**
53
+ * The key as it may appear in a log line: parsed, with email addresses masked
54
+ */
55
+ loggableKey(key) {
56
+ return maskEmailsInText(this.parseKey(key));
57
+ }
58
+ /**
52
59
  * {@inheritdoc}
53
60
  */
54
61
  async set(key, _value, _ttlOrOptions) {
55
- log.info("cache", "setting key", key);
56
- log.success("cache", "key set", key);
62
+ log.info("cache", "setting key", this.loggableKey(key));
63
+ log.success("cache", "key set", this.loggableKey(key));
57
64
  return this;
58
65
  }
59
66
  /**
60
67
  * {@inheritdoc}
61
68
  */
62
69
  async get(key) {
63
- log.info("cache", "fetching", key);
64
- log.success("cache", "fetched", key);
70
+ log.info("cache", "fetching", this.loggableKey(key));
71
+ log.success("cache", "fetched", this.loggableKey(key));
65
72
  return null;
66
73
  }
67
74
  /**
68
75
  * {@inheritdoc}
69
76
  */
70
77
  async remove(key) {
71
- log.info("cache", "removing", key);
72
- log.success("cache", "removed", key);
78
+ log.info("cache", "removing", this.loggableKey(key));
79
+ log.success("cache", "removed", this.loggableKey(key));
73
80
  }
74
81
  /**
75
82
  * {@inheritdoc}
@@ -1 +1 @@
1
- {"version":3,"file":"null-cache-driver.mjs","names":[],"sources":["../../../../../../../cache/src/drivers/null-cache-driver.ts"],"sourcesContent":["import type { GenericObject } from \"@mongez/reinforcements\";\nimport { log } from \"@warlock.js/logger\";\nimport type {\n CacheDriver,\n CacheKey,\n CacheSetOptions,\n CacheTtl,\n NullCacheDriverOptions,\n RememberOptions,\n} from \"../types\";\nimport { BaseCacheDriver } from \"./base-cache-driver\";\n\nexport class NullCacheDriver\n extends BaseCacheDriver<NullCacheDriver, NullCacheDriverOptions>\n implements CacheDriver<NullCacheDriver, NullCacheDriverOptions>\n{\n /**\n * Options list\n */\n public options: GenericObject = {};\n\n /**\n * {@inheritdoc}\n */\n public name = \"null\";\n\n /**\n * Cached data\n */\n public data: GenericObject = {};\n\n /**\n * {@inheritdoc}\n */\n public get client() {\n return this;\n }\n\n /**\n * Constructor\n */\n public constructor(options: GenericObject = {}) {\n super();\n this.setOptions(options);\n }\n\n /**\n * {@inheritdoc}\n */\n public setOptions(options: GenericObject) {\n this.options = options;\n return this;\n }\n\n /**\n * {@inheritdoc}\n */\n public parseKey(key: CacheKey) {\n // Real parsed key so the base lock map never merges distinct keys.\n return super.parseKey(key);\n }\n\n /**\n * {@inheritdoc}\n *\n * Nothing is stored, so always run the callback and return its own result.\n */\n public async remember(\n _key: CacheKey,\n _ttlOrOptions: CacheTtl | RememberOptions,\n callback: () => Promise<any>,\n ): Promise<any> {\n return callback();\n }\n\n /**\n * {@inheritdoc}\n */\n public async removeNamespace(namespace: string) {\n log.info(\"cache\", \"clearing namespace\", namespace);\n\n log.success(\"cache\", \"namespace cleared\", namespace);\n\n return this;\n }\n\n /**\n * {@inheritdoc}\n */\n public async set(\n key: CacheKey,\n _value: any,\n _ttlOrOptions?: CacheTtl | CacheSetOptions,\n ): Promise<any> {\n log.info(\"cache\", \"setting key\", key);\n\n log.success(\"cache\", \"key set\", key);\n\n return this;\n }\n\n /**\n * {@inheritdoc}\n */\n public async get(key: CacheKey) {\n log.info(\"cache\", \"fetching\", key);\n\n log.success(\"cache\", \"fetched\", key);\n\n return null;\n }\n\n /**\n * {@inheritdoc}\n */\n public async remove(key: CacheKey) {\n log.info(\"cache\", \"removing\", key);\n\n log.success(\"cache\", \"removed\", key);\n }\n\n /**\n * {@inheritdoc}\n */\n public async flush() {\n log.info(\"cache\", \"flushing\", \"all\");\n\n log.success(\"cache\", \"flushed\", \"all\");\n }\n\n /**\n * {@inheritdoc}\n *\n * The null driver is a black-hole — `similar()` mirrors `get()` and returns\n * an empty result set rather than throwing.\n */\n public async similar(): Promise<any[]> {\n return [];\n }\n\n /**\n * {@inheritdoc}\n */\n public async connect() {\n log.success(\"cache\", \"connected\", \"Connected to null cache driver\");\n }\n}\n"],"mappings":";;;;AAYA,IAAa,kBAAb,cACU,gBAEV;;;;CAmBE,IAAW,SAAS;EAClB,OAAO;CACT;;;;CAKA,AAAO,YAAY,UAAyB,CAAC,GAAG;EAC9C,MAAM;iBAvBwB,CAAC;cAKnB;cAKe,CAAC;EAc5B,KAAK,WAAW,OAAO;CACzB;;;;CAKA,AAAO,WAAW,SAAwB;EACxC,KAAK,UAAU;EACf,OAAO;CACT;;;;CAKA,AAAO,SAAS,KAAe;EAE7B,OAAO,MAAM,SAAS,GAAG;CAC3B;;;;;;CAOA,MAAa,SACX,MACA,eACA,UACc;EACd,OAAO,SAAS;CAClB;;;;CAKA,MAAa,gBAAgB,WAAmB;EAC9C,IAAI,KAAK,SAAS,sBAAsB,SAAS;EAEjD,IAAI,QAAQ,SAAS,qBAAqB,SAAS;EAEnD,OAAO;CACT;;;;CAKA,MAAa,IACX,KACA,QACA,eACc;EACd,IAAI,KAAK,SAAS,eAAe,GAAG;EAEpC,IAAI,QAAQ,SAAS,WAAW,GAAG;EAEnC,OAAO;CACT;;;;CAKA,MAAa,IAAI,KAAe;EAC9B,IAAI,KAAK,SAAS,YAAY,GAAG;EAEjC,IAAI,QAAQ,SAAS,WAAW,GAAG;EAEnC,OAAO;CACT;;;;CAKA,MAAa,OAAO,KAAe;EACjC,IAAI,KAAK,SAAS,YAAY,GAAG;EAEjC,IAAI,QAAQ,SAAS,WAAW,GAAG;CACrC;;;;CAKA,MAAa,QAAQ;EACnB,IAAI,KAAK,SAAS,YAAY,KAAK;EAEnC,IAAI,QAAQ,SAAS,WAAW,KAAK;CACvC;;;;;;;CAQA,MAAa,UAA0B;EACrC,OAAO,CAAC;CACV;;;;CAKA,MAAa,UAAU;EACrB,IAAI,QAAQ,SAAS,aAAa,gCAAgC;CACpE;AACF"}
1
+ {"version":3,"file":"null-cache-driver.mjs","names":[],"sources":["../../../../../../../../packages/cache/src/drivers/null-cache-driver.ts"],"sourcesContent":["import type { GenericObject } from \"@mongez/reinforcements\";\nimport { log, maskEmailsInText } from \"@warlock.js/logger\";\nimport type {\n CacheDriver,\n CacheKey,\n CacheSetOptions,\n CacheTtl,\n NullCacheDriverOptions,\n RememberOptions,\n} from \"../types\";\nimport { BaseCacheDriver } from \"./base-cache-driver\";\n\nexport class NullCacheDriver\n extends BaseCacheDriver<NullCacheDriver, NullCacheDriverOptions>\n implements CacheDriver<NullCacheDriver, NullCacheDriverOptions>\n{\n /**\n * Options list\n */\n public options: GenericObject = {};\n\n /**\n * {@inheritdoc}\n */\n public name = \"null\";\n\n /**\n * Cached data\n */\n public data: GenericObject = {};\n\n /**\n * {@inheritdoc}\n */\n public get client() {\n return this;\n }\n\n /**\n * Constructor\n */\n public constructor(options: GenericObject = {}) {\n super();\n this.setOptions(options);\n }\n\n /**\n * {@inheritdoc}\n */\n public setOptions(options: GenericObject) {\n this.options = options;\n return this;\n }\n\n /**\n * {@inheritdoc}\n */\n public parseKey(key: CacheKey) {\n // Real parsed key so the base lock map never merges distinct keys.\n return super.parseKey(key);\n }\n\n /**\n * {@inheritdoc}\n *\n * Nothing is stored, so always run the callback and return its own result.\n */\n public async remember(\n _key: CacheKey,\n _ttlOrOptions: CacheTtl | RememberOptions,\n callback: () => Promise<any>,\n ): Promise<any> {\n return callback();\n }\n\n /**\n * {@inheritdoc}\n */\n public async removeNamespace(namespace: string) {\n const loggableNamespace = maskEmailsInText(namespace);\n\n log.info(\"cache\", \"clearing namespace\", loggableNamespace);\n\n log.success(\"cache\", \"namespace cleared\", loggableNamespace);\n\n return this;\n }\n\n /**\n * The key as it may appear in a log line: parsed, with email addresses masked\n */\n protected loggableKey(key: CacheKey): string {\n return maskEmailsInText(this.parseKey(key));\n }\n\n /**\n * {@inheritdoc}\n */\n public async set(\n key: CacheKey,\n _value: any,\n _ttlOrOptions?: CacheTtl | CacheSetOptions,\n ): Promise<any> {\n log.info(\"cache\", \"setting key\", this.loggableKey(key));\n\n log.success(\"cache\", \"key set\", this.loggableKey(key));\n\n return this;\n }\n\n /**\n * {@inheritdoc}\n */\n public async get(key: CacheKey) {\n log.info(\"cache\", \"fetching\", this.loggableKey(key));\n\n log.success(\"cache\", \"fetched\", this.loggableKey(key));\n\n return null;\n }\n\n /**\n * {@inheritdoc}\n */\n public async remove(key: CacheKey) {\n log.info(\"cache\", \"removing\", this.loggableKey(key));\n\n log.success(\"cache\", \"removed\", this.loggableKey(key));\n }\n\n /**\n * {@inheritdoc}\n */\n public async flush() {\n log.info(\"cache\", \"flushing\", \"all\");\n\n log.success(\"cache\", \"flushed\", \"all\");\n }\n\n /**\n * {@inheritdoc}\n *\n * The null driver is a black-hole — `similar()` mirrors `get()` and returns\n * an empty result set rather than throwing.\n */\n public async similar(): Promise<any[]> {\n return [];\n }\n\n /**\n * {@inheritdoc}\n */\n public async connect() {\n log.success(\"cache\", \"connected\", \"Connected to null cache driver\");\n }\n}\n"],"mappings":";;;;AAYA,IAAa,kBAAb,cACU,gBAEV;;;;CAmBE,IAAW,SAAS;EAClB,OAAO;CACT;;;;CAKA,AAAO,YAAY,UAAyB,CAAC,GAAG;EAC9C,MAAM;iBAvBwB,CAAC;cAKnB;cAKe,CAAC;EAc5B,KAAK,WAAW,OAAO;CACzB;;;;CAKA,AAAO,WAAW,SAAwB;EACxC,KAAK,UAAU;EACf,OAAO;CACT;;;;CAKA,AAAO,SAAS,KAAe;EAE7B,OAAO,MAAM,SAAS,GAAG;CAC3B;;;;;;CAOA,MAAa,SACX,MACA,eACA,UACc;EACd,OAAO,SAAS;CAClB;;;;CAKA,MAAa,gBAAgB,WAAmB;EAC9C,MAAM,oBAAoB,iBAAiB,SAAS;EAEpD,IAAI,KAAK,SAAS,sBAAsB,iBAAiB;EAEzD,IAAI,QAAQ,SAAS,qBAAqB,iBAAiB;EAE3D,OAAO;CACT;;;;CAKA,AAAU,YAAY,KAAuB;EAC3C,OAAO,iBAAiB,KAAK,SAAS,GAAG,CAAC;CAC5C;;;;CAKA,MAAa,IACX,KACA,QACA,eACc;EACd,IAAI,KAAK,SAAS,eAAe,KAAK,YAAY,GAAG,CAAC;EAEtD,IAAI,QAAQ,SAAS,WAAW,KAAK,YAAY,GAAG,CAAC;EAErD,OAAO;CACT;;;;CAKA,MAAa,IAAI,KAAe;EAC9B,IAAI,KAAK,SAAS,YAAY,KAAK,YAAY,GAAG,CAAC;EAEnD,IAAI,QAAQ,SAAS,WAAW,KAAK,YAAY,GAAG,CAAC;EAErD,OAAO;CACT;;;;CAKA,MAAa,OAAO,KAAe;EACjC,IAAI,KAAK,SAAS,YAAY,KAAK,YAAY,GAAG,CAAC;EAEnD,IAAI,QAAQ,SAAS,WAAW,KAAK,YAAY,GAAG,CAAC;CACvD;;;;CAKA,MAAa,QAAQ;EACnB,IAAI,KAAK,SAAS,YAAY,KAAK;EAEnC,IAAI,QAAQ,SAAS,WAAW,KAAK;CACvC;;;;;;;CAQA,MAAa,UAA0B;EACrC,OAAO,CAAC;CACV;;;;CAKA,MAAa,UAAU;EACrB,IAAI,QAAQ,SAAS,aAAa,gCAAgC;CACpE;AACF"}
@@ -1,7 +1,7 @@
1
1
  import { BaseCacheDriver } from "./base-cache-driver.mjs";
2
2
  import { CacheData, CacheDriver, CacheKey, CacheSetOptions, CacheSimilarHit, CacheSimilarOptions, CacheTtl, PgCacheOptions, PgClientLike } from "../types.mjs";
3
3
 
4
- //#region ../cache/src/drivers/pg-cache-driver.d.ts
4
+ //#region ../../packages/cache/src/drivers/pg-cache-driver.d.ts
5
5
  /**
6
6
  * Postgres cache driver with optional pgvector similarity support.
7
7
  *
@@ -1 +1 @@
1
- {"version":3,"file":"pg-cache-driver.d.mts","names":[],"sources":["../../../../../../../cache/src/drivers/pg-cache-driver.ts"],"mappings":";;;;;;AAsDA;;;;;;;;;;;;;;;;;;;;;;;;;;cAAa,aAAA,SACH,eAAA,CAAgB,YAAA,EAAc,cAAA,aAC3B,WAAA,CAAY,YAAA,EAAc,cAAA;EAsfI;;;EAjflC,IAAA;EAqlB2B;;;;EAAA,UA/kBxB,WAAA;EAqnB8B;;;;;EA9mBjC,UAAA,CAAW,OAAA,EAAS,cAAA;EAotBmB;;;;;;EAAA,UA9qB9B,iBAAA,IAAqB,OAAA;EAxD1B;;;;;EAAA,UAqFD,YAAA,CAAa,MAAA;EArFZ;;;;EAAA,cA6FG,KAAA;EA3EP;;;;EAAA,cAmFO,QAAA,IAAY,YAAA;EAhBhB;;;;;EAAA,UAyBM,cAAA,CAAe,GAAA,EAAK,QAAA,EAAU,QAAA,YAAoB,OAAA;EAA9B;;;;;;;;;;;;;EAgCvB,MAAA,CAAO,MAAA,EAAQ,QAAA,EAAU,OAAA,aAAoB,OAAA;EAiEhD;;;;;;;EAhCG,SAAA,CAAU,MAAA,EAAQ,QAAA,EAAU,OAAA,aAAoB,OAAA;EA+GzC;;;;;EAAA,UA/EV,YAAA,CAAa,GAAA;EAsGrB;;;;EA1FW,KAAA,CAAM,KAAA,YAAe,OAAA;EAmOrB;;;EAAA,UAtNH,UAAA;EA8QM;;;;;;;EA/PT,MAAA;EAgUqB;;;EAzRf,OAAA,IAAO,OAAA;EA4TP;;;;;EA/SA,UAAA,IAAU,OAAA;EAoVhB;;;EA5UM,GAAA,CACX,GAAA,EAAK,QAAA,EACL,KAAA,OACA,YAAA,GAAe,QAAA,GAAW,eAAA,GACzB,OAAA;EAyU0B;;;EAlMhB,GAAA,CAAI,GAAA,EAAK,QAAA,GAAQ,OAAA;EAmMjB;;;;;EAAA,UA3IG,QAAA,CAAS,GAAA,EAAK,QAAA,GAAW,OAAA,CAAQ,SAAA;EA+NxB;;;;EAAA,UAlLf,UAAA,CAAW,KAAA;EAmMyB;;;;;;;;EA/KjC,SAAA,CAAU,GAAA,EAAK,QAAA,EAAU,KAAA,YAAoB,OAAA;EA2O/C;;;AAAiB;;;EAxMf,IAAA,CAAK,GAAA,EAAK,QAAA,GAAW,OAAA;;;;;;;;;;;;;EAoCrB,MAAA,UACX,GAAA,EAAK,QAAA,EACL,EAAA,GAAK,OAAA,EAAS,CAAA,YAAa,CAAA,UAAW,OAAA,CAAQ,CAAA,UAC9C,OAAA;IAAW,GAAA,GAAM,QAAA;EAAA,IAChB,OAAA,CAAQ,CAAA;;;;EAmFE,MAAA,CAAO,GAAA,EAAK,QAAA,GAAQ,OAAA;;;;;;;EAiBpB,eAAA,CAAgB,SAAA,WAAiB,OAAA;;;;;;;;EA4BjC,KAAA,IAAK,OAAA;;;;;;;;;;;;;;;;;EA6BL,OAAA,UACX,MAAA,YACA,OAAA,EAAS,mBAAA,GACR,OAAA,CAAQ,eAAA,CAAgB,CAAA;AAAA"}
1
+ {"version":3,"file":"pg-cache-driver.d.mts","names":[],"sources":["../../../../../../../../packages/cache/src/drivers/pg-cache-driver.ts"],"mappings":";;;;;;AAuDA;;;;;;;;;;;;;;;;;;;;;;;;;;cAAa,aAAA,SACH,eAAA,CAAgB,YAAA,EAAc,cAAA,aAC3B,WAAA,CAAY,YAAA,EAAc,cAAA;EAsfI;;;EAjflC,IAAA;EAqlB2B;;;;EAAA,UA/kBxB,WAAA;EAqnB8B;;;;;EA9mBjC,UAAA,CAAW,OAAA,EAAS,cAAA;EAotBmB;;;;;;EAAA,UA9qB9B,iBAAA,IAAqB,OAAA;EAxD1B;;;;;EAAA,UAqFD,YAAA,CAAa,MAAA;EArFZ;;;;EAAA,cA6FG,KAAA;EA3EP;;;;EAAA,cAmFO,QAAA,IAAY,YAAA;EAhBhB;;;;;EAAA,UAyBM,cAAA,CAAe,GAAA,EAAK,QAAA,EAAU,QAAA,YAAoB,OAAA;EAA9B;;;;;;;;;;;;;EAgCvB,MAAA,CAAO,MAAA,EAAQ,QAAA,EAAU,OAAA,aAAoB,OAAA;EAiEhD;;;;;;;EAhCG,SAAA,CAAU,MAAA,EAAQ,QAAA,EAAU,OAAA,aAAoB,OAAA;EA+GzC;;;;;EAAA,UA/EV,YAAA,CAAa,GAAA;EAsGrB;;;;EA1FW,KAAA,CAAM,KAAA,YAAe,OAAA;EAmOrB;;;EAAA,UAtNH,UAAA;EA8QM;;;;;;;EA/PT,MAAA;EAgUqB;;;EAzRf,OAAA,IAAO,OAAA;EA4TP;;;;;EA/SA,UAAA,IAAU,OAAA;EAoVhB;;;EA5UM,GAAA,CACX,GAAA,EAAK,QAAA,EACL,KAAA,OACA,YAAA,GAAe,QAAA,GAAW,eAAA,GACzB,OAAA;EAyU0B;;;EAlMhB,GAAA,CAAI,GAAA,EAAK,QAAA,GAAQ,OAAA;EAmMjB;;;;;EAAA,UA3IG,QAAA,CAAS,GAAA,EAAK,QAAA,GAAW,OAAA,CAAQ,SAAA;EA+NxB;;;;EAAA,UAlLf,UAAA,CAAW,KAAA;EAmMyB;;;;;;;;EA/KjC,SAAA,CAAU,GAAA,EAAK,QAAA,EAAU,KAAA,YAAoB,OAAA;EA2O/C;;;AAAiB;;;EAxMf,IAAA,CAAK,GAAA,EAAK,QAAA,GAAW,OAAA;;;;;;;;;;;;;EAoCrB,MAAA,UACX,GAAA,EAAK,QAAA,EACL,EAAA,GAAK,OAAA,EAAS,CAAA,YAAa,CAAA,UAAW,OAAA,CAAQ,CAAA,UAC9C,OAAA;IAAW,GAAA,GAAM,QAAA;EAAA,IAChB,OAAA,CAAQ,CAAA;;;;EAmFE,MAAA,CAAO,GAAA,EAAK,QAAA,GAAQ,OAAA;;;;;;;EAiBpB,eAAA,CAAgB,SAAA,WAAiB,OAAA;;;;;;;;EA4BjC,KAAA,IAAK,OAAA;;;;;;;;;;;;;;;;;EA6BL,OAAA,UACX,MAAA,YACA,OAAA,EAAS,mBAAA,GACR,OAAA,CAAQ,eAAA,CAAgB,CAAA;AAAA"}
@@ -1,8 +1,9 @@
1
1
  import { CacheConfigurationError, CacheError, CacheUnsupportedError } from "../types.mjs";
2
2
  import { parseTtl } from "../utils.mjs";
3
3
  import { BaseCacheDriver } from "./base-cache-driver.mjs";
4
+ import { maskEmailsInText } from "@warlock.js/logger";
4
5
 
5
- //#region ../cache/src/drivers/pg-cache-driver.ts
6
+ //#region ../../packages/cache/src/drivers/pg-cache-driver.ts
6
7
  /** Compare-and-set attempts before `update()` gives up under contention. */
7
8
  const PG_UPDATE_MAX_ATTEMPTS = 10;
8
9
  /**
@@ -454,7 +455,7 @@ var PgCacheDriver = class extends BaseCacheDriver {
454
455
  value,
455
456
  this.ttlToSeconds(this.ttl)
456
457
  ]);
457
- if (rows.length === 0) throw new Error(`Cannot increment non-numeric value for key: ${parsedKey}`);
458
+ if (rows.length === 0) throw new Error(`Cannot increment non-numeric value for key: ${maskEmailsInText(parsedKey)}`);
458
459
  const newValue = Number(this.decodeJson(rows[0].value));
459
460
  await this.emit("set", {
460
461
  key: parsedKey,