@nexusts/cache 0.7.2 → 0.7.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -572,5 +572,5 @@ export {
572
572
  CACHEABLE_META
573
573
  };
574
574
 
575
- //# debugId=9C5F48EB1132DDC864756E2164756E21
575
+ //# debugId=93358EE69A14896364756E2164756E21
576
576
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -4,12 +4,12 @@
4
4
  "sourcesContent": [
5
5
  "/**\n * `nexusjs/cache` — application-level caching.\n *\n * Two backends ship out of the box:\n * - `MemoryStore` — single-process LRU with TTL eviction\n * - `RedisStore` — multi-pod via ioredis (peer dep, optional)\n *\n * const cache = new CacheService({ store: new MemoryStore({ max: 10_000 }) });\n * await cache.set('user:42', user, 60); // 60-second TTL\n * const u = await cache.get<User>('user:42');\n *\n * Decorators are also provided for service methods:\n *\n * @Cacheable('user', (id: string) => id, 60)\n * async findById(id: string) { ... }\n */\n\nimport \"reflect-metadata\";\nimport { METADATA_KEY } from \"@nexusts/core\";\n\n/** A single cache entry. */\nexport interface CacheEntry<T = unknown> {\n\tvalue: T;\n\t/** Unix-ms timestamp when this entry expires. 0 = never. */\n\texpiresAt: number;\n\t/** Stash tags for invalidation. */\n\ttags?: string[];\n}\n\n/** Storage backend for cache entries. */\nexport interface CacheStore {\n\treadonly kind: string;\n\t/** Get a value. Returns `undefined` if missing or expired. */\n\tget<T = unknown>(key: string): Promise<T | undefined>;\n\t/** Set a value with optional TTL (seconds) and tags. */\n\tset<T = unknown>(\n\t\tkey: string,\n\t\tvalue: T,\n\t\topts?: CacheSetOptions,\n\t): Promise<void>;\n\t/** Delete a single key. */\n\tdelete(key: string): Promise<boolean>;\n\t/** Delete every key matching `pattern` (glob: `*`, `**`). */\n\tclear(pattern?: string): Promise<number>;\n\t/** Wrap a function with cache-or-compute semantics. */\n\twrap<T>(key: string, fn: () => Promise<T>, ttl?: number): Promise<T>;\n\t/**\n\t * Remove every entry tagged with `tag`. Backends without a tag\n\t * index (e.g. MemoryStore) return 0.\n\t */\n\tinvalidateByTag?(tag: string): Promise<number>;\n\t/** Sweep expired entries. Backends without a sweep loop return 0. */\n\tgc?(): Promise<number>;\n\t/** Optional: free resources. */\n\tclose?(): Promise<void>;\n}\n\n/** Options for `set()`. */\nexport interface CacheSetOptions {\n\t/** Time-to-live in seconds. 0 = forever. */\n\tttl?: number;\n\t/** Tags for grouped invalidation. */\n\ttags?: string[];\n}\n\nexport interface CacheConfig {\n\t/** Storage backend. Default: in-memory LRU. */\n\tstore?: CacheStore;\n\t/** Default TTL in seconds when none is provided. Default: 60. */\n\tdefaultTtl?: number;\n\t/** Prefix prepended to all keys. Default: 'nexusjs'. */\n\tprefix?: string;\n}\n\n/** Internal metadata key. */\nexport const CACHEABLE_META = \"nexus:cache:cacheable\";\nexport const CACHE_INVALIDATE_META = \"nexus:cache:invalidate\";\n\n/** @Cacheable decorator. Caches the result of a method. */\nexport function Cacheable(\n\tprefix: string,\n\tkeyFn: (...args: any[]) => string,\n\tttlSeconds = 60,\n): MethodDecorator {\n\treturn (\n\t\ttarget: any,\n\t\tpropertyKey: string | symbol,\n\t\tdescriptor: PropertyDescriptor,\n\t) => {\n\t\tconst existing: CacheableSpec[] =\n\t\t\tReflect.getMetadata(CACHEABLE_META, target.constructor) ?? [];\n\t\texisting.push({\n\t\t\tprefix,\n\t\t\tkeyFn,\n\t\t\tttl: ttlSeconds,\n\t\t\tpropertyKey,\n\t\t\toriginal: descriptor.value,\n\t\t});\n\t\tReflect.defineMetadata(CACHEABLE_META, existing, target.constructor);\n\t};\n}\n\n/** @CacheInvalidate decorator. Removes matching keys after a method runs. */\nexport function CacheInvalidate(\n\tprefix: string,\n\tkeyFn: (...args: any[]) => string,\n): MethodDecorator {\n\treturn (\n\t\ttarget: any,\n\t\tpropertyKey: string | symbol,\n\t\tdescriptor: PropertyDescriptor,\n\t) => {\n\t\tconst existing: CacheInvalidateSpec[] =\n\t\t\tReflect.getMetadata(CACHE_INVALIDATE_META, target.constructor) ?? [];\n\t\texisting.push({ prefix, keyFn, propertyKey, original: descriptor.value });\n\t\tReflect.defineMetadata(CACHE_INVALIDATE_META, existing, target.constructor);\n\t};\n}\n\nexport interface CacheableSpec {\n\tprefix: string;\n\tkeyFn: (...args: any[]) => string;\n\tttl: number;\n\tpropertyKey: string | symbol;\n\toriginal: (...args: any[]) => any;\n}\n\nexport interface CacheInvalidateSpec {\n\tprefix: string;\n\tkeyFn: (...args: any[]) => string;\n\tpropertyKey: string | symbol;\n\toriginal: (...args: any[]) => any;\n}\n\nexport function getCacheableSpecs(target: any): CacheableSpec[] {\n\treturn Reflect.getMetadata(CACHEABLE_META, target) ?? [];\n}\nexport function getCacheInvalidateSpecs(target: any): CacheInvalidateSpec[] {\n\treturn Reflect.getMetadata(CACHE_INVALIDATE_META, target) ?? [];\n}\n\nexport { METADATA_KEY };\n",
6
6
  "/**\n * In-memory LRU cache store with TTL eviction.\n *\n * Simple and fast; not cluster-safe. Use `RedisStore` for shared state\n * across multiple Bun processes.\n */\nimport type { CacheEntry, CacheSetOptions, CacheStore } from \"../types.js\";\n\nexport interface MemoryStoreOptions {\n\t/** Maximum number of entries. Default: 10_000. */\n\tmax?: number;\n\t/** Sweep interval for expired entries. Default: 30_000 ms. 0 = no sweep. */\n\tsweepIntervalMs?: number;\n}\n\nexport class MemoryStore implements CacheStore {\n\treadonly kind = \"memory\";\n\tprivate data = new Map<string, CacheEntry>();\n\tprivate tagIndex = new Map<string, Set<string>>();\n\tprivate readonly max: number;\n\tprivate sweepTimer: ReturnType<typeof setInterval> | null = null;\n\n\tconstructor(opts: MemoryStoreOptions = {}) {\n\t\tthis.max = opts.max ?? 10_000;\n\t\tconst sweepMs = opts.sweepIntervalMs ?? 30_000;\n\t\tif (sweepMs > 0) {\n\t\t\tthis.sweepTimer = setInterval(() => this.sweepExpired(), sweepMs);\n\t\t\t// Don't keep the event loop alive for the sweep timer.\n\t\t\tif (typeof this.sweepTimer === \"object\" && this.sweepTimer !== null) {\n\t\t\t\t(this.sweepTimer as any).unref?.();\n\t\t\t}\n\t\t}\n\t}\n\n\tasync get<T = unknown>(key: string): Promise<T | undefined> {\n\t\tconst e = this.data.get(key);\n\t\tif (!e) return undefined;\n\t\tif (e.expiresAt > 0 && e.expiresAt <= Date.now()) {\n\t\t\tthis.data.delete(key);\n\t\t\treturn undefined;\n\t\t}\n\t\t// Touch for LRU.\n\t\tthis.data.delete(key);\n\t\tthis.data.set(key, e);\n\t\treturn e.value as T;\n\t}\n\n\tasync set<T = unknown>(\n\t\tkey: string,\n\t\tvalue: T,\n\t\topts: CacheSetOptions = {},\n\t): Promise<void> {\n\t\tconst ttl = opts.ttl ?? 0;\n\t\tconst entry: CacheEntry<T> = {\n\t\t\tvalue,\n\t\t\texpiresAt: ttl > 0 ? Date.now() + ttl * 1000 : 0,\n\t\t\ttags: opts.tags,\n\t\t};\n\t\t// Insert (and possibly evict).\n\t\tif (!this.data.has(key) && this.data.size >= this.max) {\n\t\t\t// Evict oldest (first key in iteration order).\n\t\t\tconst oldest = this.data.keys().next().value;\n\t\t\tif (oldest !== undefined) {\n\t\t\t\tthis.data.delete(oldest);\n\t\t\t\tfor (const keys of this.tagIndex.values()) keys.delete(oldest);\n\t\t\t}\n\t\t}\n\t\tthis.data.set(key, entry);\n\t\t// Refresh tag index: remove old tag associations for this key, then add new ones.\n\t\tif (opts.tags) {\n\t\t\tfor (const [, keys] of this.tagIndex.entries()) keys.delete(key);\n\t\t\tfor (const tag of opts.tags) {\n\t\t\t\tlet set = this.tagIndex.get(tag);\n\t\t\t\tif (!set) {\n\t\t\t\t\tset = new Set();\n\t\t\t\t\tthis.tagIndex.set(tag, set);\n\t\t\t\t}\n\t\t\t\tset.add(key);\n\t\t\t}\n\t\t}\n\t}\n\n\tasync delete(key: string): Promise<boolean> {\n\t\tconst deleted = this.data.delete(key);\n\t\t// Remove this key from every tag index.\n\t\tfor (const keys of this.tagIndex.values()) keys.delete(key);\n\t\treturn deleted;\n\t}\n\n\tasync clear(pattern?: string): Promise<number> {\n\t\tif (!pattern) {\n\t\t\tconst n = this.data.size;\n\t\t\tthis.data.clear();\n\t\t\tthis.tagIndex.clear();\n\t\t\treturn n;\n\t\t}\n\t\tconst rx = globToRegExp(pattern);\n\t\tlet n = 0;\n\t\tfor (const k of [...this.data.keys()]) {\n\t\t\tif (rx.test(k)) {\n\t\t\t\tthis.data.delete(k);\n\t\t\t\tfor (const keys of this.tagIndex.values()) keys.delete(k);\n\t\t\t\tn++;\n\t\t\t}\n\t\t}\n\t\treturn n;\n\t}\n\n\tasync wrap<T>(key: string, fn: () => Promise<T>, ttl?: number): Promise<T> {\n\t\tconst v = await this.get<T>(key);\n\t\tif (v !== undefined) return v;\n\t\tconst result = await fn();\n\t\tawait this.set(key, result, { ttl });\n\t\treturn result;\n\t}\n\n\t/**\n\t * Tag-based invalidation. Maintains a `tag -> Set<key>` index in\n\t * addition to the main map. Returns the number of keys removed.\n\t */\n\tasync invalidateByTag(tag: string): Promise<number> {\n\t\tconst keys = this.tagIndex.get(tag);\n\t\tif (!keys) return 0;\n\t\tlet n = 0;\n\t\tfor (const k of keys) {\n\t\t\tif (this.data.delete(k)) n++;\n\t\t}\n\t\tthis.tagIndex.delete(tag);\n\t\treturn n;\n\t}\n\n\tasync close(): Promise<void> {\n\t\tif (this.sweepTimer) clearInterval(this.sweepTimer);\n\t\tthis.sweepTimer = null;\n\t\tthis.data.clear();\n\t\tthis.tagIndex.clear();\n\t}\n\n\tprivate sweepExpired(): void {\n\t\tconst now = Date.now();\n\t\tfor (const [k, e] of this.data.entries()) {\n\t\t\tif (e.expiresAt > 0 && e.expiresAt <= now) this.data.delete(k);\n\t\t}\n\t\t// Drop tags whose keys are all gone.\n\t\tfor (const [tag, keys] of this.tagIndex.entries()) {\n\t\t\tfor (const k of keys) {\n\t\t\t\tif (!this.data.has(k)) keys.delete(k);\n\t\t\t}\n\t\t\tif (keys.size === 0) this.tagIndex.delete(tag);\n\t\t}\n\t}\n}\n\nfunction globToRegExp(pattern: string): RegExp {\n\treturn new RegExp(\n\t\t\"^\" +\n\t\t\tpattern\n\t\t\t\t.replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\")\n\t\t\t\t.replace(/\\*\\*/g, \"::DBL::\")\n\t\t\t\t.replace(/\\*/g, \"[^:]+\")\n\t\t\t\t.replace(/::DBL::/g, \".*\") +\n\t\t\t\"$\",\n\t);\n}\n",
7
- "/**\n * `DrizzleCacheStore` — cache entries backed by any Drizzle database.\n *\n * import { DrizzleService } from 'nexusjs/drizzle';\n * import { DrizzleCacheStore } from 'nexusjs/cache';\n *\n * const db = new DrizzleService({ dialect: 'postgres', connection: {...} });\n * await db.open();\n *\n * const store = new DrizzleCacheStore(db, {\n * tableName: 'nexus_cache',\n * });\n *\n * CacheModule.forRoot({ store, defaultTtl: 300 });\n *\n * Schema (managed by your migration):\n *\n * CREATE TABLE nexus_cache (\n * key TEXT PRIMARY KEY,\n * value TEXT NOT NULL, -- JSON-encoded\n * expires_at TEXT, -- ISO timestamp, null = never\n * created_at TEXT NOT NULL,\n * updated_at TEXT NOT NULL\n * );\n *\n * CREATE TABLE nexus_cache_tags ( -- tag → key index\n * tag TEXT NOT NULL,\n * key TEXT NOT NULL,\n * PRIMARY KEY (tag, key)\n * );\n * CREATE INDEX nexus_cache_tags_key_idx ON nexus_cache_tags(key);\n *\n * Why a tag table? It enables true `invalidateByTag('users')` that\n * removes every entry tagged 'users' in a single statement, regardless\n * of how many keys share the tag.\n */\nimport type { DrizzleService } from \"../../drizzle/drizzle.service.js\";\nimport type { CacheSetOptions, CacheStore } from \"../types.js\";\n\nexport interface DrizzleCacheOptions {\n\tdb: DrizzleService;\n\t/** Cache row table. Default: 'nexus_cache'. */\n\ttableName?: string;\n\t/** Tag index table. Default: 'nexus_cache_tags'. */\n\ttagsTableName?: string;\n\t/** Column names — override to match your schema. */\n\tcolumns?: {\n\t\tkey?: string;\n\t\tvalue?: string;\n\t\texpiresAt?: string;\n\t\tcreatedAt?: string;\n\t\tupdatedAt?: string;\n\t\ttag?: string;\n\t};\n}\n\ntype CacheRow = Record<string, string | null>;\ntype TagRow = Record<string, string>;\n\nexport class DrizzleCacheStore implements CacheStore {\n\treadonly kind = \"drizzle\" as const;\n\n\tprivate db: DrizzleService;\n\tprivate t: string;\n\tprivate tagsT: string;\n\tprivate c: {\n\t\tkey: string;\n\t\tvalue: string;\n\t\texpiresAt: string;\n\t\tcreatedAt: string;\n\t\tupdatedAt: string;\n\t\ttag: string;\n\t};\n\n\tconstructor(db: DrizzleService, options: Omit<DrizzleCacheOptions, \"db\"> = {}) {\n\t\tthis.db = db;\n\t\tthis.t = options.tableName ?? \"nexus_cache\";\n\t\tthis.tagsT = options.tagsTableName ?? \"nexus_cache_tags\";\n\t\tthis.c = {\n\t\t\tkey: options.columns?.key ?? \"key\",\n\t\t\tvalue: options.columns?.value ?? \"value\",\n\t\t\texpiresAt: options.columns?.expiresAt ?? \"expires_at\",\n\t\t\tcreatedAt: options.columns?.createdAt ?? \"created_at\",\n\t\t\tupdatedAt: options.columns?.updatedAt ?? \"updated_at\",\n\t\t\ttag: options.columns?.tag ?? \"tag\",\n\t\t};\n\t}\n\n\tasync get<T = unknown>(key: string): Promise<T | undefined> {\n\t\tconst rows = await this.db.rawQuery<CacheRow>(\n\t\t\t`SELECT * FROM ${this.t} WHERE ${this.c.key} = ? LIMIT 1`,\n\t\t\t[key],\n\t\t);\n\t\tconst row = rows[0];\n\t\tif (!row) return undefined;\n\t\tconst expiresAt = row[this.c.expiresAt];\n\t\tif (expiresAt && new Date(expiresAt).getTime() <= Date.now()) {\n\t\t\t// Expired — clean up lazily.\n\t\t\tawait this.delete(key);\n\t\t\treturn undefined;\n\t\t}\n\t\tconst raw = row[this.c.value];\n\t\tif (raw === null || raw === undefined) return undefined;\n\t\ttry {\n\t\t\treturn JSON.parse(String(raw)) as T;\n\t\t} catch {\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\tasync set<T = unknown>(\n\t\tkey: string,\n\t\tvalue: T,\n\t\topts: CacheSetOptions = {},\n\t): Promise<void> {\n\t\tconst now = new Date().toISOString();\n\t\tconst expiresAt =\n\t\t\topts.ttl && opts.ttl > 0\n\t\t\t\t? new Date(Date.now() + opts.ttl * 1000).toISOString()\n\t\t\t\t: null;\n\t\tconst serialized = JSON.stringify(value);\n\n\t\t// Upsert the cache row. Different dialects use different syntax;\n\t\t// we use the simple INSERT ... ON CONFLICT pattern (works in\n\t\t// sqlite, postgres, mysql 8+).\n\t\tawait this.db.rawQuery(\n\t\t\t`INSERT INTO ${this.t} (${this.c.key}, ${this.c.value}, ${this.c.expiresAt}, ${this.c.createdAt}, ${this.c.updatedAt})\n\t\t\t VALUES (?, ?, ?, ?, ?)\n\t\t\t ON CONFLICT (${this.c.key}) DO UPDATE SET\n\t\t\t ${this.c.value} = excluded.${this.c.value},\n\t\t\t ${this.c.expiresAt} = excluded.${this.c.expiresAt},\n\t\t\t ${this.c.updatedAt} = excluded.${this.c.updatedAt}`,\n\t\t\t[key, serialized, expiresAt, now, now],\n\t\t);\n\n\t\t// Refresh tag index: delete old tags, then insert new ones.\n\t\tif (opts.tags && opts.tags.length > 0) {\n\t\t\tawait this.db.rawQuery(\n\t\t\t\t`DELETE FROM ${this.tagsT} WHERE ${this.c.key} = ?`,\n\t\t\t\t[key],\n\t\t\t);\n\t\t\tfor (const tag of opts.tags) {\n\t\t\t\tawait this.db.rawQuery(\n\t\t\t\t\t`INSERT OR IGNORE INTO ${this.tagsT} (${this.c.tag}, ${this.c.key}) VALUES (?, ?)`,\n\t\t\t\t\t[tag, key],\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tasync delete(key: string): Promise<boolean> {\n\t\t// Cheap probe: does the row exist at all (even expired)?\n\t\tconst probe = await this.db.rawQuery<CacheRow>(\n\t\t\t`SELECT ${this.c.key} FROM ${this.t} WHERE ${this.c.key} = ? LIMIT 1`,\n\t\t\t[key],\n\t\t);\n\t\tif (probe.length === 0) return false;\n\t\tawait this.db.rawQuery(`DELETE FROM ${this.t} WHERE ${this.c.key} = ?`, [key]);\n\t\tawait this.db.rawQuery(\n\t\t\t`DELETE FROM ${this.tagsT} WHERE ${this.c.key} = ?`,\n\t\t\t[key],\n\t\t);\n\t\treturn true;\n\t}\n\n\tasync clear(pattern?: string): Promise<number> {\n\t\tif (!pattern) {\n\t\t\tawait this.db.rawQuery(`DELETE FROM ${this.tagsT}`);\n\t\t\tconst before = await this.db.rawQuery<unknown>(\n\t\t\t\t`SELECT COUNT(*) as n FROM ${this.t}`,\n\t\t\t);\n\t\t\tawait this.db.rawQuery(`DELETE FROM ${this.t}`);\n\t\t\tconst n = Number((before[0] as { n?: number } | undefined)?.n ?? 0);\n\t\t\treturn n;\n\t\t}\n\t\t// Translate glob to SQL LIKE. `*` -> `%`.\n\t\tconst likePattern = pattern\n\t\t\t.replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\")\n\t\t\t.replace(/\\*\\*/g, \"%\")\n\t\t\t.replace(/\\*/g, \"%\");\n\t\tconst before = await this.db.rawQuery<unknown>(\n\t\t\t`SELECT COUNT(*) as n FROM ${this.t} WHERE ${this.c.key} LIKE ? ESCAPE '\\\\'`,\n\t\t\t[likePattern],\n\t\t);\n\t\tawait this.db.rawQuery(\n\t\t\t`DELETE FROM ${this.t} WHERE ${this.c.key} LIKE ? ESCAPE '\\\\'`,\n\t\t\t[likePattern],\n\t\t);\n\t\treturn Number((before[0] as { n?: number } | undefined)?.n ?? 0);\n\t}\n\n\tasync wrap<T>(key: string, fn: () => Promise<T>, ttl?: number): Promise<T> {\n\t\tconst hit = await this.get<T>(key);\n\t\tif (hit !== undefined) return hit;\n\t\tconst v = await fn();\n\t\tawait this.set(key, v, { ttl });\n\t\treturn v;\n\t}\n\n\t/**\n\t * Remove every cache entry that has been tagged with `tag`.\n\t * Returns the number of keys removed.\n\t */\n\tasync invalidateByTag(tag: string): Promise<number> {\n\t\tconst tagRows = await this.db.rawQuery<TagRow>(\n\t\t\t`SELECT ${this.c.key} FROM ${this.tagsT} WHERE ${this.c.tag} = ?`,\n\t\t\t[tag],\n\t\t);\n\t\tconst keys = tagRows.map((r) => r[this.c.key]);\n\t\tif (keys.length === 0) return 0;\n\t\t// Use a parameter list to safely delete. We chunk in case there\n\t\t// are many keys (some DBs cap the parameter count).\n\t\tconst chunkSize = 100;\n\t\tlet removed = 0;\n\t\tfor (let i = 0; i < keys.length; i += chunkSize) {\n\t\t\tconst chunk = keys.slice(i, i + chunkSize);\n\t\t\tconst placeholders = chunk.map(() => \"?\").join(\", \");\n\t\t\tconst r1 = await this.db.rawQuery<unknown>(\n\t\t\t\t`DELETE FROM ${this.t} WHERE ${this.c.key} IN (${placeholders})`,\n\t\t\t\tchunk,\n\t\t\t);\n\t\t\tconst r2 = await this.db.rawQuery<unknown>(\n\t\t\t\t`DELETE FROM ${this.tagsT} WHERE ${this.c.key} IN (${placeholders})`,\n\t\t\t\tchunk,\n\t\t\t);\n\t\t\tremoved += Math.max(r1.length, r2.length, chunk.length);\n\t\t}\n\t\treturn removed;\n\t}\n\n\t/** Clean up expired entries. */\n\tasync gc(): Promise<number> {\n\t\tconst now = new Date().toISOString();\n\t\tconst before = await this.db.rawQuery<unknown>(\n\t\t\t`SELECT COUNT(*) as n FROM ${this.t} WHERE ${this.c.expiresAt} IS NOT NULL AND ${this.c.expiresAt} <= ?`,\n\t\t\t[now],\n\t\t);\n\t\tawait this.db.rawQuery(\n\t\t\t`DELETE FROM ${this.t} WHERE ${this.c.expiresAt} IS NOT NULL AND ${this.c.expiresAt} <= ?`,\n\t\t\t[now],\n\t\t);\n\t\t// Drop dangling tag rows.\n\t\tawait this.db.rawQuery(\n\t\t\t`DELETE FROM ${this.tagsT} WHERE ${this.c.key} NOT IN (SELECT ${this.c.key} FROM ${this.t})`,\n\t\t);\n\t\treturn Number((before[0] as { n?: number } | undefined)?.n ?? 0);\n\t}\n\n\tasync close(): Promise<void> {\n\t\t// No resources to release — the underlying db is owned by the user.\n\t}\n}\n",
7
+ "/**\n * `DrizzleCacheStore` — cache entries backed by any Drizzle database.\n *\n * import { DrizzleService } from 'nexusjs/drizzle';\n * import { DrizzleCacheStore } from 'nexusjs/cache';\n *\n * const db = new DrizzleService({ dialect: 'postgres', connection: {...} });\n * await db.open();\n *\n * const store = new DrizzleCacheStore(db, {\n * tableName: 'nexus_cache',\n * });\n *\n * CacheModule.forRoot({ store, defaultTtl: 300 });\n *\n * Schema (managed by your migration):\n *\n * CREATE TABLE nexus_cache (\n * key TEXT PRIMARY KEY,\n * value TEXT NOT NULL, -- JSON-encoded\n * expires_at TEXT, -- ISO timestamp, null = never\n * created_at TEXT NOT NULL,\n * updated_at TEXT NOT NULL\n * );\n *\n * CREATE TABLE nexus_cache_tags ( -- tag → key index\n * tag TEXT NOT NULL,\n * key TEXT NOT NULL,\n * PRIMARY KEY (tag, key)\n * );\n * CREATE INDEX nexus_cache_tags_key_idx ON nexus_cache_tags(key);\n *\n * Why a tag table? It enables true `invalidateByTag('users')` that\n * removes every entry tagged 'users' in a single statement, regardless\n * of how many keys share the tag.\n */\nimport type { DrizzleService } from \"@nexusts/drizzle\";\nimport type { CacheSetOptions, CacheStore } from \"../types.js\";\n\nexport interface DrizzleCacheOptions {\n\tdb: DrizzleService;\n\t/** Cache row table. Default: 'nexus_cache'. */\n\ttableName?: string;\n\t/** Tag index table. Default: 'nexus_cache_tags'. */\n\ttagsTableName?: string;\n\t/** Column names — override to match your schema. */\n\tcolumns?: {\n\t\tkey?: string;\n\t\tvalue?: string;\n\t\texpiresAt?: string;\n\t\tcreatedAt?: string;\n\t\tupdatedAt?: string;\n\t\ttag?: string;\n\t};\n}\n\ntype CacheRow = Record<string, string | null>;\ntype TagRow = Record<string, string>;\n\nexport class DrizzleCacheStore implements CacheStore {\n\treadonly kind = \"drizzle\" as const;\n\n\tprivate db: DrizzleService;\n\tprivate t: string;\n\tprivate tagsT: string;\n\tprivate c: {\n\t\tkey: string;\n\t\tvalue: string;\n\t\texpiresAt: string;\n\t\tcreatedAt: string;\n\t\tupdatedAt: string;\n\t\ttag: string;\n\t};\n\n\tconstructor(db: DrizzleService, options: Omit<DrizzleCacheOptions, \"db\"> = {}) {\n\t\tthis.db = db;\n\t\tthis.t = options.tableName ?? \"nexus_cache\";\n\t\tthis.tagsT = options.tagsTableName ?? \"nexus_cache_tags\";\n\t\tthis.c = {\n\t\t\tkey: options.columns?.key ?? \"key\",\n\t\t\tvalue: options.columns?.value ?? \"value\",\n\t\t\texpiresAt: options.columns?.expiresAt ?? \"expires_at\",\n\t\t\tcreatedAt: options.columns?.createdAt ?? \"created_at\",\n\t\t\tupdatedAt: options.columns?.updatedAt ?? \"updated_at\",\n\t\t\ttag: options.columns?.tag ?? \"tag\",\n\t\t};\n\t}\n\n\tasync get<T = unknown>(key: string): Promise<T | undefined> {\n\t\tconst rows = await this.db.rawQuery<CacheRow>(\n\t\t\t`SELECT * FROM ${this.t} WHERE ${this.c.key} = ? LIMIT 1`,\n\t\t\t[key],\n\t\t);\n\t\tconst row = rows[0];\n\t\tif (!row) return undefined;\n\t\tconst expiresAt = row[this.c.expiresAt];\n\t\tif (expiresAt && new Date(expiresAt).getTime() <= Date.now()) {\n\t\t\t// Expired — clean up lazily.\n\t\t\tawait this.delete(key);\n\t\t\treturn undefined;\n\t\t}\n\t\tconst raw = row[this.c.value];\n\t\tif (raw === null || raw === undefined) return undefined;\n\t\ttry {\n\t\t\treturn JSON.parse(String(raw)) as T;\n\t\t} catch {\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\tasync set<T = unknown>(\n\t\tkey: string,\n\t\tvalue: T,\n\t\topts: CacheSetOptions = {},\n\t): Promise<void> {\n\t\tconst now = new Date().toISOString();\n\t\tconst expiresAt =\n\t\t\topts.ttl && opts.ttl > 0\n\t\t\t\t? new Date(Date.now() + opts.ttl * 1000).toISOString()\n\t\t\t\t: null;\n\t\tconst serialized = JSON.stringify(value);\n\n\t\t// Upsert the cache row. Different dialects use different syntax;\n\t\t// we use the simple INSERT ... ON CONFLICT pattern (works in\n\t\t// sqlite, postgres, mysql 8+).\n\t\tawait this.db.rawQuery(\n\t\t\t`INSERT INTO ${this.t} (${this.c.key}, ${this.c.value}, ${this.c.expiresAt}, ${this.c.createdAt}, ${this.c.updatedAt})\n\t\t\t VALUES (?, ?, ?, ?, ?)\n\t\t\t ON CONFLICT (${this.c.key}) DO UPDATE SET\n\t\t\t ${this.c.value} = excluded.${this.c.value},\n\t\t\t ${this.c.expiresAt} = excluded.${this.c.expiresAt},\n\t\t\t ${this.c.updatedAt} = excluded.${this.c.updatedAt}`,\n\t\t\t[key, serialized, expiresAt, now, now],\n\t\t);\n\n\t\t// Refresh tag index: delete old tags, then insert new ones.\n\t\tif (opts.tags && opts.tags.length > 0) {\n\t\t\tawait this.db.rawQuery(\n\t\t\t\t`DELETE FROM ${this.tagsT} WHERE ${this.c.key} = ?`,\n\t\t\t\t[key],\n\t\t\t);\n\t\t\tfor (const tag of opts.tags) {\n\t\t\t\tawait this.db.rawQuery(\n\t\t\t\t\t`INSERT OR IGNORE INTO ${this.tagsT} (${this.c.tag}, ${this.c.key}) VALUES (?, ?)`,\n\t\t\t\t\t[tag, key],\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tasync delete(key: string): Promise<boolean> {\n\t\t// Cheap probe: does the row exist at all (even expired)?\n\t\tconst probe = await this.db.rawQuery<CacheRow>(\n\t\t\t`SELECT ${this.c.key} FROM ${this.t} WHERE ${this.c.key} = ? LIMIT 1`,\n\t\t\t[key],\n\t\t);\n\t\tif (probe.length === 0) return false;\n\t\tawait this.db.rawQuery(`DELETE FROM ${this.t} WHERE ${this.c.key} = ?`, [key]);\n\t\tawait this.db.rawQuery(\n\t\t\t`DELETE FROM ${this.tagsT} WHERE ${this.c.key} = ?`,\n\t\t\t[key],\n\t\t);\n\t\treturn true;\n\t}\n\n\tasync clear(pattern?: string): Promise<number> {\n\t\tif (!pattern) {\n\t\t\tawait this.db.rawQuery(`DELETE FROM ${this.tagsT}`);\n\t\t\tconst before = await this.db.rawQuery<unknown>(\n\t\t\t\t`SELECT COUNT(*) as n FROM ${this.t}`,\n\t\t\t);\n\t\t\tawait this.db.rawQuery(`DELETE FROM ${this.t}`);\n\t\t\tconst n = Number((before[0] as { n?: number } | undefined)?.n ?? 0);\n\t\t\treturn n;\n\t\t}\n\t\t// Translate glob to SQL LIKE. `*` -> `%`.\n\t\tconst likePattern = pattern\n\t\t\t.replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\")\n\t\t\t.replace(/\\*\\*/g, \"%\")\n\t\t\t.replace(/\\*/g, \"%\");\n\t\tconst before = await this.db.rawQuery<unknown>(\n\t\t\t`SELECT COUNT(*) as n FROM ${this.t} WHERE ${this.c.key} LIKE ? ESCAPE '\\\\'`,\n\t\t\t[likePattern],\n\t\t);\n\t\tawait this.db.rawQuery(\n\t\t\t`DELETE FROM ${this.t} WHERE ${this.c.key} LIKE ? ESCAPE '\\\\'`,\n\t\t\t[likePattern],\n\t\t);\n\t\treturn Number((before[0] as { n?: number } | undefined)?.n ?? 0);\n\t}\n\n\tasync wrap<T>(key: string, fn: () => Promise<T>, ttl?: number): Promise<T> {\n\t\tconst hit = await this.get<T>(key);\n\t\tif (hit !== undefined) return hit;\n\t\tconst v = await fn();\n\t\tawait this.set(key, v, { ttl });\n\t\treturn v;\n\t}\n\n\t/**\n\t * Remove every cache entry that has been tagged with `tag`.\n\t * Returns the number of keys removed.\n\t */\n\tasync invalidateByTag(tag: string): Promise<number> {\n\t\tconst tagRows = await this.db.rawQuery<TagRow>(\n\t\t\t`SELECT ${this.c.key} FROM ${this.tagsT} WHERE ${this.c.tag} = ?`,\n\t\t\t[tag],\n\t\t);\n\t\tconst keys = tagRows.map((r) => r[this.c.key]);\n\t\tif (keys.length === 0) return 0;\n\t\t// Use a parameter list to safely delete. We chunk in case there\n\t\t// are many keys (some DBs cap the parameter count).\n\t\tconst chunkSize = 100;\n\t\tlet removed = 0;\n\t\tfor (let i = 0; i < keys.length; i += chunkSize) {\n\t\t\tconst chunk = keys.slice(i, i + chunkSize);\n\t\t\tconst placeholders = chunk.map(() => \"?\").join(\", \");\n\t\t\tconst r1 = await this.db.rawQuery<unknown>(\n\t\t\t\t`DELETE FROM ${this.t} WHERE ${this.c.key} IN (${placeholders})`,\n\t\t\t\tchunk,\n\t\t\t);\n\t\t\tconst r2 = await this.db.rawQuery<unknown>(\n\t\t\t\t`DELETE FROM ${this.tagsT} WHERE ${this.c.key} IN (${placeholders})`,\n\t\t\t\tchunk,\n\t\t\t);\n\t\t\tremoved += Math.max(r1.length, r2.length, chunk.length);\n\t\t}\n\t\treturn removed;\n\t}\n\n\t/** Clean up expired entries. */\n\tasync gc(): Promise<number> {\n\t\tconst now = new Date().toISOString();\n\t\tconst before = await this.db.rawQuery<unknown>(\n\t\t\t`SELECT COUNT(*) as n FROM ${this.t} WHERE ${this.c.expiresAt} IS NOT NULL AND ${this.c.expiresAt} <= ?`,\n\t\t\t[now],\n\t\t);\n\t\tawait this.db.rawQuery(\n\t\t\t`DELETE FROM ${this.t} WHERE ${this.c.expiresAt} IS NOT NULL AND ${this.c.expiresAt} <= ?`,\n\t\t\t[now],\n\t\t);\n\t\t// Drop dangling tag rows.\n\t\tawait this.db.rawQuery(\n\t\t\t`DELETE FROM ${this.tagsT} WHERE ${this.c.key} NOT IN (SELECT ${this.c.key} FROM ${this.t})`,\n\t\t);\n\t\treturn Number((before[0] as { n?: number } | undefined)?.n ?? 0);\n\t}\n\n\tasync close(): Promise<void> {\n\t\t// No resources to release — the underlying db is owned by the user.\n\t}\n}\n",
8
8
  "/**\n * `RedisCacheStore` — a `CacheStore` backed by `nexusjs/redis`.\n *\n * Works on **Bun** (`Bun.redis`), **Node** (`ioredis`), and\n * **Cloudflare Workers KV** (via `CloudflareKVAdapter`). The\n * same adapter selection applies as for sessions.\n *\n * import { CacheService } from 'nexusjs/cache';\n * import { RedisCacheStore, createRedisClient } from 'nexusjs/redis';\n *\n * const cache = new CacheService({\n * store: new RedisCacheStore(createRedisClient({ url: 'redis://localhost:6379' }), {\n * keyPrefix: 'cache:',\n * }),\n * });\n *\n * Values are JSON-serialized. The store uses the KV backend's\n * own TTL (Redis `EX` / KV `expirationTtl`).\n *\n * Tag-based invalidation is supported on the Redis and Node\n * adapters (a per-tag Set is maintained as a separate KV key).\n * On Cloudflare KV, tag invalidation degrades to a SCAN — slower\n * but correct.\n */\n\nimport type { RedisClient } from \"@nexusts/redis\";\nimport type { CacheEntry, CacheSetOptions, CacheStore } from \"../types.js\";\n\nconst DEFAULT_KEY_PREFIX = \"cache:\";\n\nexport interface RedisCacheStoreOptions {\n\t/** Key prefix. Default: \"cache:\". */\n\tkeyPrefix?: string;\n}\n\nexport class RedisCacheStore implements CacheStore {\n\treadonly kind = \"redis\";\n\t#client: RedisClient;\n\t#keyPrefix: string;\n\t#tagKeyPrefix: string;\n\n\tconstructor(client: RedisClient, options: RedisCacheStoreOptions = {}) {\n\t\tthis.#client = client;\n\t\tthis.#keyPrefix = options.keyPrefix ?? DEFAULT_KEY_PREFIX;\n\t\tthis.#tagKeyPrefix = `${this.#keyPrefix}tag:`;\n\t}\n\n\t#key(key: string): string {\n\t\treturn `${this.#keyPrefix}${key}`;\n\t}\n\n\t#tagKey(tag: string): string {\n\t\treturn `${this.#tagKeyPrefix}${crc32(tag)}`;\n\t}\n\n\tasync get<T = unknown>(key: string): Promise<T | undefined> {\n\t\tconst raw = await this.#client.get(this.#key(key));\n\t\tif (raw === null) return undefined;\n\t\ttry {\n\t\t\tconst entry = JSON.parse(raw) as CacheEntry<T>;\n\t\t\tif (entry.expiresAt && entry.expiresAt <= Date.now()) {\n\t\t\t\tawait this.#client.del(this.#key(key));\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\treturn entry.value;\n\t\t} catch {\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\tasync set<T = unknown>(\n\t\tkey: string,\n\t\tvalue: T,\n\t\topts?: CacheSetOptions,\n\t): Promise<void> {\n\t\tconst ttl = opts?.ttl ?? 0;\n\t\tconst tags = opts?.tags ?? [];\n\t\tconst entry: CacheEntry<T> = {\n\t\t\tvalue,\n\t\t\texpiresAt: ttl > 0 ? Date.now() + ttl * 1000 : 0,\n\t\t\t...(tags.length > 0 ? { tags } : {}),\n\t\t};\n\t\tconst fullKey = this.#key(key);\n\t\tconst ex = ttl > 0 ? ttl : undefined;\n\t\tawait this.#client.set(fullKey, JSON.stringify(entry), ex ? { ex } : undefined);\n\t\t// Update per-tag indexes.\n\t\tfor (const tag of tags) {\n\t\t\tawait this.#addToTagIndex(tag, key);\n\t\t}\n\t}\n\n\tasync delete(key: string): Promise<boolean> {\n\t\tconst fullKey = this.#key(key);\n\t\tconst existed = (await this.#client.get(fullKey)) !== null;\n\t\tawait this.#client.del(fullKey);\n\t\t// The tag indexes are best-effort — leave them; gc() will\n\t\t// eventually prune orphans. (A full implementation would\n\t\t// need to read the entry to find its tags before deleting,\n\t\t// which is an extra round-trip.)\n\t\treturn existed;\n\t}\n\n\tasync has(key: string): Promise<boolean> {\n\t\treturn this.#client.exists(this.#key(key));\n\t}\n\n\tasync clear(): Promise<number> {\n\t\tlet n = 0;\n\t\tlet cursor: string | number = \"0\";\n\t\tdo {\n\t\t\tconst res = await this.#client.scan({\n\t\t\t\tmatch: `${this.#keyPrefix}*`,\n\t\t\t\tcursor,\n\t\t\t\tcount: 100,\n\t\t\t});\n\t\t\tfor (const k of res.keys) {\n\t\t\t\tawait this.#client.del(this.#keyPrefix + k);\n\t\t\t\tn++;\n\t\t\t}\n\t\t\tcursor = res.cursor;\n\t\t} while (cursor !== \"0\" && cursor !== 0);\n\t\treturn n;\n\t}\n\n\tasync gc(): Promise<number> {\n\t\t// The KV store evicts on TTL. Here we clean up orphan tag\n\t\t// indexes — keys in the tag set that no longer exist in\n\t\t// the value store.\n\t\tlet removed = 0;\n\t\tlet cursor: string | number = \"0\";\n\t\tdo {\n\t\t\tconst res = await this.#client.scan({\n\t\t\t\tmatch: `${this.#tagKeyPrefix}*`,\n\t\t\t\tcursor,\n\t\t\t\tcount: 100,\n\t\t\t});\n\t\t\tfor (const k of res.keys) {\n\t\t\t\tconst raw = await this.#client.get(this.#keyPrefix + k);\n\t\t\t\tconst ids = raw ? safeParseStringArray(raw) : [];\n\t\t\t\tconst live: string[] = [];\n\t\t\t\tfor (const id of ids) {\n\t\t\t\t\tif (await this.#client.exists(this.#key(id))) live.push(id);\n\t\t\t\t}\n\t\t\t\tif (live.length === 0) {\n\t\t\t\t\tawait this.#client.del(this.#keyPrefix + k);\n\t\t\t\t\tremoved++;\n\t\t\t\t} else if (live.length !== ids.length) {\n\t\t\t\t\tawait this.#client.set(\n\t\t\t\t\t\tthis.#keyPrefix + k,\n\t\t\t\t\t\tJSON.stringify(live),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tcursor = res.cursor;\n\t\t} while (cursor !== \"0\" && cursor !== 0);\n\t\treturn removed;\n\t}\n\n\tasync invalidateByTag(tag: string): Promise<number> {\n\t\tconst tagK = this.#tagKey(tag);\n\t\tconst raw = await this.#client.get(tagK);\n\t\tif (!raw) return 0;\n\t\tconst keys = safeParseStringArray(raw);\n\t\tlet n = 0;\n\t\tfor (const k of keys) {\n\t\t\tawait this.#client.del(this.#key(k));\n\t\t\tn++;\n\t\t}\n\t\tawait this.#client.del(tagK);\n\t\treturn n;\n\t}\n\n\tasync invalidateByTags(tags: string[]): Promise<number> {\n\t\tlet n = 0;\n\t\tfor (const t of tags) n += await this.invalidateByTag(t);\n\t\treturn n;\n\t}\n\n\tasync wrap<T>(key: string, fn: () => Promise<T>, ttl?: number): Promise<T> {\n\t\tconst hit = await this.get<T>(key);\n\t\tif (hit !== undefined) return hit;\n\t\tconst value = await fn();\n\t\tawait this.set(key, value, ttl !== undefined ? { ttl } : undefined);\n\t\treturn value;\n\t}\n\n\tasync close(): Promise<void> {\n\t\tawait this.#client.close();\n\t}\n\n\tasync #addToTagIndex(tag: string, key: string): Promise<void> {\n\t\tconst k = this.#tagKey(tag);\n\t\tconst raw = await this.#client.get(k);\n\t\tconst ids = raw ? safeParseStringArray(raw) : [];\n\t\tif (!ids.includes(key)) ids.push(key);\n\t\tawait this.#client.set(k, JSON.stringify(ids));\n\t}\n}\n\nfunction safeParseStringArray(raw: string): string[] {\n\ttry {\n\t\tconst v = JSON.parse(raw);\n\t\treturn Array.isArray(v) ? v.filter((x) => typeof x === \"string\") : [];\n\t} catch {\n\t\treturn [];\n\t}\n}\n\nfunction crc32(s: string): string {\n\tlet c = 0xffffffff;\n\tfor (let i = 0; i < s.length; i++) {\n\t\tc ^= s.charCodeAt(i);\n\t\tfor (let k = 0; k < 8; k++) {\n\t\t\tc = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;\n\t\t}\n\t}\n\treturn (c ^ 0xffffffff).toString(16);\n}\n",
9
9
  "/**\n * `CacheService` — main entry point for caching.\n *\n * const cache = new CacheService({ store: new MemoryStore() });\n * await cache.set('user:42', user, { ttl: 60 });\n * const u = await cache.get<User>('user:42');\n *\n * Provides:\n * - `get`, `set`, `delete`, `clear` — direct key operations\n * - `wrap` — cache-or-compute\n * - `getOrSet` — alias for wrap with a default TTL\n * - `invalidateByTag`, `invalidateByPrefix` — bulk removal\n * - `applyDecorators(target)` — wires @Cacheable / @CacheInvalidate\n * onto an existing service instance.\n */\nimport { Inject, Injectable } from \"@nexusts/core\";\nimport { MemoryStore } from \"./stores/memory.js\";\nimport type { CacheConfig, CacheStore } from \"./types.js\";\nimport {\n\tgetCacheableSpecs,\n\tgetCacheInvalidateSpecs,\n} from \"./types.js\";\n\n@Injectable()\nexport class CacheService {\n\t/** DI token. */\n\tstatic readonly TOKEN = Symbol.for(\"nexus:CacheService\");\n\n\tstore: CacheStore;\n\tdefaultTtl: number;\n\tprefix: string;\n\n\tconstructor(@Inject(\"CACHE_CONFIG\") config: CacheConfig = {}) {\n\t\tthis.store = config.store ?? new MemoryStore();\n\t\tthis.defaultTtl = config.defaultTtl ?? 60;\n\t\tthis.prefix = config.prefix ?? \"nexusjs\";\n\t}\n\n\tprivate key(k: string): string {\n\t\treturn `${this.prefix}:${k}`;\n\t}\n\n\tasync get<T = unknown>(k: string): Promise<T | undefined> {\n\t\treturn this.store.get<T>(this.key(k));\n\t}\n\n\tasync set<T = unknown>(k: string, value: T, ttl?: number): Promise<void>;\n\tasync set<T = unknown>(k: string, value: T, opts: { ttl?: number; tags?: string[] }): Promise<void>;\n\tasync set<T = unknown>(\n\t\tk: string,\n\t\tvalue: T,\n\t\toptsOrTtl: number | { ttl?: number; tags?: string[] } = this.defaultTtl,\n\t): Promise<void> {\n\t\tconst opts =\n\t\t\ttypeof optsOrTtl === \"number\"\n\t\t\t\t? { ttl: optsOrTtl }\n\t\t\t\t: { ttl: optsOrTtl.ttl ?? this.defaultTtl, tags: optsOrTtl.tags };\n\t\tawait this.store.set<T>(this.key(k), value, opts);\n\t}\n\n\tasync delete(k: string): Promise<boolean> {\n\t\treturn this.store.delete(this.key(k));\n\t}\n\n\tasync clear(pattern?: string): Promise<number> {\n\t\treturn this.store.clear(pattern ? `${this.prefix}:${pattern}` : undefined);\n\t}\n\n\t/** Get or compute-and-store. */\n\tasync wrap<T>(k: string, fn: () => Promise<T>, ttl?: number): Promise<T> {\n\t\treturn this.store.wrap<T>(this.key(k), fn, ttl ?? this.defaultTtl);\n\t}\n\n\t/**\n\t * Tag-based invalidation. Delegates to the underlying store.\n\t * Stores without a tag index (the default `MemoryStore`) return 0.\n\t * Use `DrizzleCacheStore` (or implement `invalidateByTag` on a\n\t * custom store) for true tag-based removal.\n\t */\n\tasync invalidateByTag(tag: string): Promise<number> {\n\t\tif (typeof (this.store as any).invalidateByTag === \"function\") {\n\t\t\treturn await (this.store as any).invalidateByTag(this.prefixedTag(tag));\n\t\t}\n\t\treturn 0;\n\t}\n\n\t/** Sweep expired entries. No-op on stores that don't implement `gc()`. */\n\tasync gc(): Promise<number> {\n\t\tif (typeof this.store.gc === \"function\") {\n\t\t\treturn await this.store.gc();\n\t\t}\n\t\treturn 0;\n\t}\n\n\t/** Apply the configured prefix to a tag name. */\n\tprivate prefixedTag(tag: string): string {\n\t\treturn `${this.prefix}:${tag}`;\n\t}\n\n\t/**\n\t * Apply @Cacheable / @CacheInvalidate decorators to an existing service\n\t * instance. The framework's DI container does this automatically.\n\t */\n\tapplyDecorators(target: any): void {\n\t\tconst ctor = target.constructor;\n\t\tconst cacheables = getCacheableSpecs(ctor);\n\t\tfor (const spec of cacheables) {\n\t\t\tconst original = spec.original;\n\t\t\t(target as any)[spec.propertyKey] = async (...args: any[]) => {\n\t\t\t\tconst subKey = spec.keyFn(...args);\n\t\t\t\treturn this.wrap(`${spec.prefix}:${subKey}`, () =>\n\t\t\t\t\toriginal.apply(target, args),\n\t\t\t\t);\n\t\t\t};\n\t\t}\n\t\tconst invalidates = getCacheInvalidateSpecs(ctor);\n\t\tfor (const spec of invalidates) {\n\t\t\tconst original = spec.original;\n\t\t\t(target as any)[spec.propertyKey] = async (...args: any[]) => {\n\t\t\t\tconst result = await original.apply(target, args);\n\t\t\t\tconst subKey = spec.keyFn(...args);\n\t\t\t\tawait this.clear(`${spec.prefix}:${subKey}*`);\n\t\t\t\treturn result;\n\t\t\t};\n\t\t}\n\t}\n}\n",
10
10
  "/**\n * `CacheModule` — drop-in caching.\n *\n * @Module({\n * imports: [\n * CacheModule.forRoot({\n * store: new MemoryStore({ max: 50_000 }),\n * defaultTtl: 300, // 5 min\n * prefix: 'myapp',\n * }),\n * ],\n * })\n * export class AppModule {}\n */\nimport \"reflect-metadata\";\nimport { Module } from \"@nexusts/core\";\nimport { CacheService } from \"./cache.service.js\";\nimport { MemoryStore } from \"./stores/memory.js\";\nimport type { CacheConfig } from \"./types.js\";\n\n@Module({\n\tproviders: [\n\t\tCacheService,\n\t\t{ provide: CacheService.TOKEN, useExisting: CacheService },\n\t],\n\texports: [CacheService, CacheService.TOKEN],\n})\nexport class CacheModule {\n\tstatic forRoot(config: CacheConfig = {}) {\n\t\tconst cfg: CacheConfig = {\n\t\t\tstore: new MemoryStore(),\n\t\t\t...config,\n\t\t};\n\t\t@Module({\n\t\t\tproviders: [\n\t\t\t\tCacheService,\n\t\t\t\t{ provide: CacheService.TOKEN, useExisting: CacheService },\n\t\t\t\t{ provide: \"CACHE_CONFIG\", useValue: cfg },\n\t\t\t],\n\t\t\texports: [CacheService, CacheService.TOKEN],\n\t\t})\n\t\tclass ConfiguredCacheModule {}\n\t\tObject.defineProperty(ConfiguredCacheModule, \"name\", {\n\t\t\tvalue: \"ConfiguredCacheModule\",\n\t\t});\n\t\treturn ConfiguredCacheModule;\n\t}\n}\n"
11
11
  ],
12
12
  "mappings": "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",
13
- "debugId": "9C5F48EB1132DDC864756E2164756E21",
13
+ "debugId": "93358EE69A14896364756E2164756E21",
14
14
  "names": []
15
15
  }
@@ -34,7 +34,7 @@
34
34
  * removes every entry tagged 'users' in a single statement, regardless
35
35
  * of how many keys share the tag.
36
36
  */
37
- import type { DrizzleService } from "../../drizzle/drizzle.service.js";
37
+ import type { DrizzleService } from "@nexusts/drizzle";
38
38
  import type { CacheSetOptions, CacheStore } from "../types.js";
39
39
  export interface DrizzleCacheOptions {
40
40
  db: DrizzleService;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nexusts/cache",
3
- "version": "0.7.2",
3
+ "version": "0.7.4",
4
4
  "description": "Application cache (memory / Drizzle backends)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -26,6 +26,6 @@
26
26
  ],
27
27
  "license": "MIT",
28
28
  "dependencies": {
29
- "@nexusts/core": "^0.7.2"
29
+ "@nexusts/core": "^0.7.4"
30
30
  }
31
31
  }