@warlock.js/cache 5.34.1 → 5.34.3

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/CHANGELOG.md CHANGED
@@ -4,6 +4,18 @@ All notable changes to `@warlock.js/cache` are documented in this file.
4
4
 
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). `@warlock.js/*` packages are released in lockstep — every package shares the same version number, so a version below may list only the changes that affected this package.
6
6
 
7
+ ## 5.34.3 - 2026-10-20
8
+
9
+ ### Changed
10
+
11
+ - Condensed the package agent skill description to at most 450 characters, with API names and package routing guidance.
12
+
13
+ ## 5.34.2 - 2026-10-19
14
+
15
+ ### Fixed
16
+
17
+ - Merge package orientation into the grouped skill index and remove the duplicate overview topic; preserve that orientation in generated LLM projections. List the cache utility topic in the index and fix the orientation link.
18
+
7
19
  ## 5.32.0 - 2026-10-18
8
20
 
9
21
  ### Changed
package/llms-full.txt CHANGED
@@ -4,7 +4,57 @@
4
4
 
5
5
  > Generated artifact. Concatenates every SKILL.md and reference file under `@warlock.js/cache/skills/`. Re-run `node scripts/generate-llms.mjs` after any change.
6
6
 
7
- ## apply-cache-patterns `@warlock.js/cache/apply-cache-patterns/SKILL.md`
7
+ ## Package orientation
8
+
9
+ ---
10
+ description: 'Pluggable memory, LRU, file, Redis and Postgres caching: `cache`, `cached`, `CacheManager`, `TaggedCache`, `ScopedCache` and `MockCacheDriver`. Use for "cache this query", "invalidate a tenant", "stale-while-revalidate", "take a lock", tag invalidation or counters. Not this package → @warlock.js/core for HTTP response caching; @warlock.js/web for page caching; @warlock.js/cascade for persistent models.'
11
+ ---
12
+
13
+ # @warlock.js/cache
14
+
15
+ The `cache` singleton (a `CacheManager`) fronts one active driver. Everything, from `get`/`set` through `remember`, `swr`, `tags`, `namespace`, `lock` and `list`, works the same on any driver, so pick a driver once and write app code against `cache`.
16
+
17
+ ## The 80% path
18
+
19
+ 1. Start with `cache-basics.md`.
20
+ 2. Choose and configure a driver: `pick-cache-driver.md` (Postgres: `configure-pg-cache.md`; TTL and options: `configure-set-options.md`).
21
+ 3. Cache expensive reads with `remember` or the `cached` wrapper: `use-cached-hof.md`, `apply-cache-patterns.md`.
22
+ 4. Invalidate in groups: `use-cache-tags.md` or `use-cache-namespace.md`.
23
+ 5. Stampede protection and freshness: `use-swr.md`, `use-cache-lock.md`.
24
+ 6. TTL constants, key parsing and vector helpers: `use-cache-utils.md`.
25
+ 7. Test with the mock driver: `test-cache-code.md`; errors and metrics: `handle-cache-errors.md`, `observe-cache.md`.
26
+
27
+ ## Conventions and pitfalls
28
+
29
+ - Tags versus namespaces: tags are cross-cutting groups you flush together; a namespace is a key prefix you remove wholesale. Choose per invalidation need.
30
+ - Check `configure-set-options.md` for TTL units, and avoid `forever` for data that can go stale.
31
+ - Atomic counters, bulk ops, lists, merge and similarity have their own topics (`use-cache-atomic.md`, `use-cache-bulk.md`, `use-cache-list.md`, `use-cache-update-merge.md`, `use-cache-similarity.md`); do not hand-roll read-modify-write.
32
+ - Not every driver supports every feature; check the driver topic first.
33
+
34
+ ## When to reach for it
35
+
36
+ - You need a cache abstraction that swaps drivers per environment (memory in dev, Redis in prod) without changing call sites.
37
+ - You want more than get/set — tag-based bulk invalidation, locks for stampede safety, SWR for slow upstreams, or a semantic cache over vectors.
38
+ - You're inside a Warlock app (the framework wires the driver from config) — or standalone, calling `setCacheConfigurations` + `cache.init` yourself.
39
+
40
+ Skip if a plain `Map` covers your needs and you'll never need a second driver, TTLs, or invalidation.
41
+
42
+ ## The mental model in one paragraph
43
+
44
+ A single `cache` singleton fronts a configured driver. `cache.set(key, value, options?)` writes (TTL via `ttl`/`expiresAt`, inline `tags`, `onConflict`, a per-call `driver` override, or a `vector` for similarity); `cache.get` / `has` / `pull` / `remove` / `many` / `remember` read. Tags let you invalidate sets of keys you can't enumerate ahead of time; namespaces auto-prefix keys with shared TTL/tag defaults; locks serialize work across processes; SWR serves stale-but-instant while refreshing in the background; `update`/`merge` do atomic read-modify-write; `list<T>(key)` gives ordered collections; `similar(vector, …)` does nearest-neighbor retrieval. `cache.metrics()` and `cache.on(event, …)` make it observable.
45
+
46
+ ## What this package deliberately doesn't do
47
+
48
+ - **Be a database.** It's a cache — entries expire, drivers may evict. Don't store anything you can't recompute.
49
+ - **Guarantee cross-driver feature parity.** Vector similarity needs a memory-family driver (`memory` / `memoryExtended` / `lru`, brute force) or `pg` with pgvector; `redis` and `file` raise `CacheUnsupportedError`. Locks/tags behave per driver. Unsupported ops raise `CacheUnsupportedError` rather than silently degrading.
50
+ - **Own your Postgres pool.** The `pg` driver takes the `pg.Pool`/`Client` you already built and never closes it — connection lifecycle stays yours. (Redis is the opposite: you pass `url`/`host` options and the driver builds and owns the client, calling `quit()` on `disconnect()`.)
51
+
52
+ ## See also
53
+
54
+ - The `configure-app` topic of the `warlock-js-core` skill — wires the cache driver from `src/config/cache.ts` and exposes the singleton.
55
+
56
+
57
+ ## apply-cache-patterns `@warlock.js/cache/skills/apply-cache-patterns/SKILL.md`
8
58
 
9
59
  ---
10
60
  name: apply-cache-patterns
@@ -107,7 +157,7 @@ await cache.tags([`tenant-${tenantId}`]).invalidate();
107
157
  - The `use-cached-hof` topic — `cached()` HOF for declarative memoization
108
158
 
109
159
 
110
- ## cache-basics `@warlock.js/cache/cache-basics/SKILL.md`
160
+ ## cache-basics `@warlock.js/cache/skills/cache-basics/SKILL.md`
111
161
 
112
162
  ---
113
163
  name: cache-basics
@@ -238,7 +288,7 @@ const user = await cache.remember("user.1", "1h", async () => db.users.find(1));
238
288
  - Don't switch embedders without re-embedding the entire vector index.
239
289
 
240
290
 
241
- ## configure-pg-cache `@warlock.js/cache/configure-pg-cache/SKILL.md`
291
+ ## configure-pg-cache `@warlock.js/cache/skills/configure-pg-cache/SKILL.md`
242
292
 
243
293
  ---
244
294
  name: configure-pg-cache
@@ -358,7 +408,7 @@ See the `handle-cache-errors` topic for the full error class hierarchy.
358
408
  - The `pick-cache-driver` topic — comparing pg with memory / redis / file
359
409
 
360
410
 
361
- ## configure-set-options `@warlock.js/cache/configure-set-options/SKILL.md`
411
+ ## configure-set-options `@warlock.js/cache/skills/configure-set-options/SKILL.md`
362
412
 
363
413
  ---
364
414
  name: configure-set-options
@@ -464,7 +514,7 @@ await cache.set("k", v, undefined); // same as no TTL
464
514
  ```
465
515
 
466
516
 
467
- ## handle-cache-errors `@warlock.js/cache/handle-cache-errors/SKILL.md`
517
+ ## handle-cache-errors `@warlock.js/cache/skills/handle-cache-errors/SKILL.md`
468
518
 
469
519
  ---
470
520
  name: handle-cache-errors
@@ -560,7 +610,7 @@ try {
560
610
  - **Concurrent writes clobbering each other** — last-write-wins by default. Use `update()` or `onConflict: "create"` if you need protection.
561
611
 
562
612
 
563
- ## observe-cache `@warlock.js/cache/observe-cache/SKILL.md`
613
+ ## observe-cache `@warlock.js/cache/skills/observe-cache/SKILL.md`
564
614
 
565
615
  ---
566
616
  name: observe-cache
@@ -668,80 +718,7 @@ Drivers that never fire events stay absent from `byDriver` — guard with `?.` a
668
718
  - Don't forget to attach early. If startup metrics matter, call `cache.metrics()` right after `cache.init()`.
669
719
 
670
720
 
671
- ## overview `@warlock.js/cache/overview/SKILL.md`
672
-
673
- ---
674
- name: overview
675
- description: "@warlock.js/cache overview for orientation and choosing the focused skill for the task."
676
- ---
677
-
678
- # `@warlock.js/cache` — overview
679
-
680
- One cache API over many drivers. Pick a driver (memory, memoryExtended, LRU, file, Redis, Postgres, null, mock), wire it once, and call `cache.get` / `cache.set` / `cache.remember` everywhere. On top of the key-value basics it adds tag invalidation, key namespaces, distributed locks, stale-while-revalidate, atomic update/merge, ordered lists, vector similarity, and built-in metrics + events.
681
-
682
- ## When to reach for it
683
-
684
- - You need a cache abstraction that swaps drivers per environment (memory in dev, Redis in prod) without changing call sites.
685
- - You want more than get/set — tag-based bulk invalidation, locks for stampede safety, SWR for slow upstreams, or a semantic cache over vectors.
686
- - You're inside a Warlock app (the framework wires the driver from config) — or standalone, calling `setCacheConfigurations` + `cache.init` yourself.
687
-
688
- Skip if a plain `Map` covers your needs and you'll never need a second driver, TTLs, or invalidation.
689
-
690
- ## The mental model in one paragraph
691
-
692
- A single `cache` singleton fronts a configured driver. `cache.set(key, value, options?)` writes (TTL via `ttl`/`expiresAt`, inline `tags`, `onConflict`, a per-call `driver` override, or a `vector` for similarity); `cache.get` / `has` / `pull` / `remove` / `many` / `remember` read. Tags let you invalidate sets of keys you can't enumerate ahead of time; namespaces auto-prefix keys with shared TTL/tag defaults; locks serialize work across processes; SWR serves stale-but-instant while refreshing in the background; `update`/`merge` do atomic read-modify-write; `list<T>(key)` gives ordered collections; `similar(vector, …)` does nearest-neighbor retrieval. `cache.metrics()` and `cache.on(event, …)` make it observable.
693
-
694
- ## Skills index
695
-
696
- Nineteen task skills. Most apps start with `cache-basics` + `pick-cache-driver` + `configure-set-options`.
697
-
698
- ### Foundations
699
-
700
- - The `cache-basics` topic — the `cache` singleton, primary ops (`set`/`get`/`has`/`pull`/`remove`/`many`/`forever`/`increment`/`decrement`/`remember`), TTL shapes, init flow. **Start here.**
701
- - The `pick-cache-driver` topic — choose + configure a driver: `null` / `memory` / `memoryExtended` / `lru` / `file` / `redis` / `pg` / `mock`; `globalPrefix` for multi-tenant scoping.
702
- - The `configure-set-options` topic — `cache.set`'s third argument: `ttl`, `expiresAt`, `tags`, `onConflict` (create/update/upsert), `driver`, `vector`.
703
- - The `configure-pg-cache` topic — Postgres driver: KV-only (default) or pgvector mode; caller owns the `pg.Pool`, `driver.schema()` emits the DDL.
704
-
705
- ### Invalidation + scoping
706
-
707
- - The `use-cache-tags` topic — tag on write, `cache.tags([...]).invalidate()` drops every bound key.
708
- - The `use-cache-namespace` topic — `cache.namespace(prefix, options?)` auto-prefixes keys with scope-level TTL/tag defaults and nested scopes.
709
-
710
- ### Patterns
711
-
712
- - The `use-cached-hof` topic — `cached(fn, options)` wraps an async function; one declaration, many call sites, a bound `.invalidate(...args)`.
713
- - The `apply-cache-patterns` topic — `remember()` memoization, distributed locks via `onConflict: "create"`, negative caching, counters, per-tenant prefix, `CACHE_FOR.*` TTL constants.
714
- - The `use-cache-lock` topic — `cache.lock(key, ttl, fn)`: acquire → run → auto-release. For cron/imports/migrations and idempotent webhook/payment processing.
715
- - The `use-swr` topic — `cache.swr(key, { freshTtl, staleTtl }, fn)`: instant when fresh, instant + background refresh when stale, blocks only when fully expired.
716
- - The `use-cache-update-merge` topic — atomic read-modify-write via `cache.update(key, fn)` / `cache.merge(key, partial)`, serialized per key, TTL-preserving.
717
- - The `use-cache-atomic` topic — `cache.increment` / `cache.decrement` counters; per-driver atomicity + TTL behavior.
718
- - The `use-cache-bulk` topic — `cache.many(keys)` / `cache.setMany(record, ttl?)` for batch reads/writes.
719
- - The `use-cache-list` topic — `cache.list<T>(key)`: `push`/`unshift`/`pop`/`shift`/`slice`/`trim`/`clear` for queues, recent-N buffers, sliding windows.
720
- - The `use-cache-similarity` topic — `cache.similar(vector, { topK, threshold?, tags? })` for semantic caches, RAG retrieval, nearest-neighbor lookup.
721
-
722
- ### Operations
723
-
724
- - The `observe-cache` topic — `cache.metrics()` (hit rate, latency p50/p95/p99) + the event bus (`cache.on("hit" | "miss" | "set" | "removed" | "flushed" | "expired" | "connected" | "disconnected" | "error", …)`).
725
- - The `handle-cache-errors` topic — the error classes: `CacheError`, `CacheConfigurationError`, `CacheConnectionError`, `CacheDriverNotInitializedError`, `CacheUnsupportedError`, `CacheConcurrencyError`.
726
- - The `test-cache-code` topic — `MockCacheDriver` (behavioral assertions), `MemoryCacheDriver` (full-stack), `NullCacheDriver` (graceful degradation).
727
-
728
- ### Utilities
729
-
730
- - The `use-cache-utils` topic — low-level re-exports: `parseTtl`, `parseCacheKey`, `resolveTtl`, `expiresAtToTtl`, `mergeTagSets`, `injectTags`, `cosineSimilarity`, and the `CACHE_FOR` TTL enum.
731
-
732
- ## What this package deliberately doesn't do
733
-
734
- - **Be a database.** It's a cache — entries expire, drivers may evict. Don't store anything you can't recompute.
735
- - **Guarantee cross-driver feature parity.** Vector similarity needs a memory-family driver (`memory` / `memoryExtended` / `lru`, brute force) or `pg` with pgvector; `redis` and `file` raise `CacheUnsupportedError`. Locks/tags behave per driver. Unsupported ops raise `CacheUnsupportedError` rather than silently degrading.
736
- - **Own your Postgres pool.** The `pg` driver takes the `pg.Pool`/`Client` you already built and never closes it — connection lifecycle stays yours. (Redis is the opposite: you pass `url`/`host` options and the driver builds and owns the client, calling `quit()` on `disconnect()`.)
737
-
738
- ## See also
739
-
740
- - The `configure-app` topic of the `warlock-js-core` skill — wires the cache driver from `src/config/cache.ts` and exposes the singleton.
741
- - `mongez-agent-kit-authoring-skills` (load via agent-kit sync) — how this becomes `.claude/skills/warlock-js-cache/overview.md`.
742
-
743
-
744
- ## pick-cache-driver `@warlock.js/cache/pick-cache-driver/SKILL.md`
721
+ ## pick-cache-driver `@warlock.js/cache/skills/pick-cache-driver/SKILL.md`
745
722
 
746
723
  ---
747
724
  name: pick-cache-driver
@@ -875,7 +852,7 @@ The manager loads (and connects) the override driver lazily on first use, then r
875
852
  - The `test-cache-code` topic — `MockCacheDriver` and `NullCacheDriver` for tests
876
853
 
877
854
 
878
- ## test-cache-code `@warlock.js/cache/test-cache-code/SKILL.md`
855
+ ## test-cache-code `@warlock.js/cache/skills/test-cache-code/SKILL.md`
879
856
 
880
857
  ---
881
858
  name: test-cache-code
@@ -1103,7 +1080,7 @@ it("returns the most similar doc above threshold", async () => {
1103
1080
  The `pg` driver accepts any object satisfying `PgClientLike` (`{ query(text, values) }`). For unit tests, hand-roll a minimal Map-backed fake — see `src/drivers/pg-cache-driver.spec.ts` for a 60-line `FakePool` that recognizes the exact SQL shapes the driver issues. For integration coverage, gate a real-PG suite on a `POSTGRES_URL` env var and skip cleanly when unset.
1104
1081
 
1105
1082
 
1106
- ## use-cache-atomic `@warlock.js/cache/use-cache-atomic/SKILL.md`
1083
+ ## use-cache-atomic `@warlock.js/cache/skills/use-cache-atomic/SKILL.md`
1107
1084
 
1108
1085
  ---
1109
1086
  name: use-cache-atomic
@@ -1172,7 +1149,7 @@ if (remaining < 0) {
1172
1149
  - The `pick-cache-driver` topic — when you need cross-node atomicity
1173
1150
 
1174
1151
 
1175
- ## use-cache-bulk `@warlock.js/cache/use-cache-bulk/SKILL.md`
1152
+ ## use-cache-bulk `@warlock.js/cache/skills/use-cache-bulk/SKILL.md`
1176
1153
 
1177
1154
  ---
1178
1155
  name: use-cache-bulk
@@ -1236,7 +1213,7 @@ returned promise rejects.
1236
1213
  - The `use-cache-tags` topic — invalidate a batch by tag
1237
1214
 
1238
1215
 
1239
- ## use-cache-list `@warlock.js/cache/use-cache-list/SKILL.md`
1216
+ ## use-cache-list `@warlock.js/cache/skills/use-cache-list/SKILL.md`
1240
1217
 
1241
1218
  ---
1242
1219
  name: use-cache-list
@@ -1325,7 +1302,7 @@ const top = await stack.pop(); // LIFO
1325
1302
  These are tracked as candidates for v3.
1326
1303
 
1327
1304
 
1328
- ## use-cache-lock `@warlock.js/cache/use-cache-lock/SKILL.md`
1305
+ ## use-cache-lock `@warlock.js/cache/skills/use-cache-lock/SKILL.md`
1329
1306
 
1330
1307
  ---
1331
1308
  name: use-cache-lock
@@ -1436,7 +1413,7 @@ await cache.lock(
1436
1413
  - **Cross-server requires `redis` or `pg`.** Memory / LRU / file drivers don't coordinate across servers.
1437
1414
 
1438
1415
 
1439
- ## use-cache-namespace `@warlock.js/cache/use-cache-namespace/SKILL.md`
1416
+ ## use-cache-namespace `@warlock.js/cache/skills/use-cache-namespace/SKILL.md`
1440
1417
 
1441
1418
  ---
1442
1419
  name: use-cache-namespace
@@ -1526,7 +1503,7 @@ Note: scope `ttl` defaults are NOT applied to SWR — `freshTtl` / `staleTtl` al
1526
1503
  - Don't mix prefix separators. The convention is `.` (dot) — pick one and stick with it across scopes so nested prefixes compose predictably.
1527
1504
 
1528
1505
 
1529
- ## use-cache-similarity `@warlock.js/cache/use-cache-similarity/SKILL.md`
1506
+ ## use-cache-similarity `@warlock.js/cache/skills/use-cache-similarity/SKILL.md`
1530
1507
 
1531
1508
  ---
1532
1509
  name: use-cache-similarity
@@ -1624,7 +1601,7 @@ See the `configure-pg-cache` topic.
1624
1601
  - Don't use `topK: 0` or negative — `pg` rejects with `CacheConfigurationError`; memory drivers return `[]` but it's a code smell.
1625
1602
 
1626
1603
 
1627
- ## use-cache-tags `@warlock.js/cache/use-cache-tags/SKILL.md`
1604
+ ## use-cache-tags `@warlock.js/cache/skills/use-cache-tags/SKILL.md`
1628
1605
 
1629
1606
  ---
1630
1607
  name: use-cache-tags
@@ -1716,7 +1693,7 @@ See the `use-cached-hof` topic.
1716
1693
  - Don't use tags as a query mechanism. Tags drop keys; they don't list them. If you need "give me every user", store an index list separately.
1717
1694
 
1718
1695
 
1719
- ## use-cache-update-merge `@warlock.js/cache/use-cache-update-merge/SKILL.md`
1696
+ ## use-cache-update-merge `@warlock.js/cache/skills/use-cache-update-merge/SKILL.md`
1720
1697
 
1721
1698
  ---
1722
1699
  name: use-cache-update-merge
@@ -1804,7 +1781,7 @@ The per-key lock map lives on the driver instance and is cleared after each chai
1804
1781
  | "Read-then-delete atomically" | `pull()` |
1805
1782
 
1806
1783
 
1807
- ## use-cache-utils `@warlock.js/cache/use-cache-utils/SKILL.md`
1784
+ ## use-cache-utils `@warlock.js/cache/skills/use-cache-utils/SKILL.md`
1808
1785
 
1809
1786
  ---
1810
1787
  name: use-cache-utils
@@ -1897,7 +1874,7 @@ For most call sites the duration string (`"1h"`, `"7d"`) reads better.
1897
1874
  - The `pick-cache-driver` topic — building a custom driver where these help
1898
1875
 
1899
1876
 
1900
- ## use-cached-hof `@warlock.js/cache/use-cached-hof/SKILL.md`
1877
+ ## use-cached-hof `@warlock.js/cache/skills/use-cached-hof/SKILL.md`
1901
1878
 
1902
1879
  ---
1903
1880
  name: use-cached-hof
@@ -2005,7 +1982,7 @@ const getCategoryMeta = cached(
2005
1982
  - Don't include secrets in args — they'd land in cache keys. Project only the identifying fields into the key.
2006
1983
 
2007
1984
 
2008
- ## use-swr `@warlock.js/cache/use-swr/SKILL.md`
1985
+ ## use-swr `@warlock.js/cache/skills/use-swr/SKILL.md`
2009
1986
 
2010
1987
  ---
2011
1988
  name: use-swr
package/llms.txt CHANGED
@@ -6,23 +6,23 @@
6
6
 
7
7
  ## Skills
8
8
 
9
- - [apply-cache-patterns](@warlock.js/cache/apply-cache-patterns/SKILL.md): Compose cache primitives into real-world patterns — remember() memoization, cross-node stampede protection via a distributed lock (onConflict: 'create'), negative caching, and per-tenant scoping. Triggers: `cache.remember`, `cache.set` with `onConflict: "create"`, `globalPrefix`; "memoize this function", "prevent cache stampede across nodes", "cache not-found results", "per-tenant cache scoping"; typical import `import { cache } from "@warlock.js/cache"`. Skip: counters — the `use-cache-atomic` topic; bulk get/set — the `use-cache-bulk` topic; TTL constants/utilities — the `use-cache-utils` topic; named lock wrapper — the `use-cache-lock` topic; SWR — the `use-swr` topic; competing libs `lru-cache`, `node-cache`, `keyv`.
10
- - [cache-basics](@warlock.js/cache/cache-basics/SKILL.md): Start here for @warlock.js/cache drivers, key-value operations, and application cache configuration.
11
- - [configure-pg-cache](@warlock.js/cache/configure-pg-cache/SKILL.md): Postgres cache driver setup — KV-only mode (default) or pgvector mode (opt in via options.pg.vector). Caller owns the pg.Pool, driver exposes driver.schema() for one-time DDL. Triggers: `PgCacheDriver`, `driver.schema`, `options.pg.vector`, `pg.Pool`, `hnsw`, `ivfflat`; "use Postgres as cache backend", "set up pgvector semantic cache", "DDL for warlock cache table"; typical import `import { cache, PgCacheDriver } from "@warlock.js/cache"`. Skip: cross-driver similarity API — the `use-cache-similarity` topic; driver picker — the `pick-cache-driver` topic; competing libs `pg-mem`; raw `pg` / `node-postgres`.
12
- - [configure-set-options](@warlock.js/cache/configure-set-options/SKILL.md): Configure cache.set's third argument — ttl, expiresAt, tags, onConflict (create / update / upsert), driver, vector. Triggers: `cache.set`, `ttl`, `expiresAt`, `tags`, `onConflict`, `driver`, `vector`, `CacheSetResult`, `wasSet`; "set a key only if missing", "set with absolute deadline", "attach tags inline", "route one cache call to redis"; typical import `import { cache } from "@warlock.js/cache"`. Skip: tag fluent API — the `use-cache-tags` topic; vector queries — the `use-cache-similarity` topic; competing libs `keyv`, `ioredis`.
13
- - [handle-cache-errors](@warlock.js/cache/handle-cache-errors/SKILL.md): Cache error classes — CacheError base, CacheConfigurationError, CacheConnectionError, CacheDriverNotInitializedError, CacheUnsupportedError, CacheConcurrencyError. Triggers: `CacheError`, `CacheConfigurationError`, `CacheConnectionError`, `CacheDriverNotInitializedError`, `CacheUnsupportedError`, `CacheConcurrencyError`; "catch cache errors at the boundary", "degrade when update or merge throws", "what does CacheUnsupportedError mean", "fall back when redis is down"; typical import `import { CacheError, CacheConfigurationError, CacheUnsupportedError } from "@warlock.js/cache"`. Skip: choosing a supported driver — the `pick-cache-driver` topic; observing errors via events — the `observe-cache` topic; competing libs ignore — generic `Error` patterns.
14
- - [observe-cache](@warlock.js/cache/observe-cache/SKILL.md): Cache observability — cache.metrics() for aggregate hit rate / latency p50/p95/p99 + event bus (cache.on('hit' / 'miss' / 'set' / 'removed' / 'flushed' / 'expired' / 'error', ...)). Triggers: `cache.metrics`, `cache.resetMetrics`, `cache.on`, `hit`, `miss`, `removed`, `flushed`, `error`, `hitRate`, `latencyMs`; "show cache hit rate", "page on cache errors", "is my cache being hit", "export metrics to prometheus"; typical import `import { cache } from "@warlock.js/cache"`. Skip: error classes — the `handle-cache-errors` topic; competing libs `prom-client`, `statsd-client`.
15
- - [overview](@warlock.js/cache/overview/SKILL.md): @warlock.js/cache overview for orientation and choosing the focused skill for the task.
16
- - [pick-cache-driver](@warlock.js/cache/pick-cache-driver/SKILL.md): Pick a cache driver — null / memory / memoryExtended / lru / file / redis / pg / mock — and configure it. Triggers: `cache.setCacheConfigurations`, `BaseCacheDriver`, `cache.use`, `cache.load`, `cache.driver`, `globalPrefix`; "which cache driver should I use", "configure redis driver", "register custom cache driver", "multi-tenant scoping"; typical import `import { cache, BaseCacheDriver } from "@warlock.js/cache"`. Skip: cache CRUD — the `cache-basics` topic; pg setup — the `configure-pg-cache` topic; competing libs `lru-cache`, `node-cache`, `keyv`, `ioredis`; native `Map`.
17
- - [test-cache-code](@warlock.js/cache/test-cache-code/SKILL.md): Test code that touches cache — MockCacheDriver (behavioral assertions with wasCalled / callLog), MemoryCacheDriver (full-stack), NullCacheDriver (graceful-degradation). Triggers: `MockCacheDriver`, `MemoryCacheDriver`, `NullCacheDriver`, `wasCalled`, `callLog`, `getStored`, `reset`, `cache.on`; "assert cache was invalidated", "test code that uses cache.set", "mock cache in vitest", "test similarity without a real embedder", "stub the pg cache driver"; typical import `import { cache, MockCacheDriver, MemoryCacheDriver } from "@warlock.js/cache"`. Skip: real driver picks — the `pick-cache-driver` topic; competing libs `jest-mock`, `sinon`, `redis-mock`; native `vi.fn`.
18
- - [use-cache-atomic](@warlock.js/cache/use-cache-atomic/SKILL.md): Atomic counters via cache.increment(key, by=1, { ttl }?) / cache.decrement(key, by=1) — returns the new number, throws on non-numeric values. Triggers: `cache.increment`, `cache.decrement`, "view counter", "page views", "atomic counter", "decrement stock", "rate-limit counter", "INCRBY"; typical import `import { cache } from "@warlock.js/cache"`. Skip: read-modify-write of objects — the `use-cache-update-merge` topic; named-lock coordination — the `use-cache-lock` topic; competing libs `ioredis` `INCR`, native counters in a `Map`.
19
- - [use-cache-bulk](@warlock.js/cache/use-cache-bulk/SKILL.md): Bulk reads/writes via cache.many(keys[]) → values[] (nulls for misses, order preserved) and cache.setMany(record, ttl?) → void. Triggers: `cache.many`, `cache.setMany`, "get multiple keys at once", "batch read cache", "warm the cache", "preload many keys", "mget", "mset"; typical import `import { cache } from "@warlock.js/cache"`. Skip: tag-based bulk invalidation — the `use-cache-tags` topic; single-key ops — the `cache-basics` topic; competing libs `ioredis` `MGET`/`MSET`.
20
- - [use-cache-list](@warlock.js/cache/use-cache-list/SKILL.md): Ordered collections via cache.list<T>(key) — push / unshift / pop / shift / slice / all / length / trim / clear. Triggers: `cache.list`, `push`, `unshift`, `pop`, `shift`, `slice`, `trim`, `clear`; "job queue in cache", "keep most recent N events", "audit log buffer", "FIFO queue"; typical import `import { cache } from "@warlock.js/cache"`. Skip: locking around list writes — the `use-cache-lock` topic; competing libs `bullmq`, `bee-queue`, `bull`, `ioredis` `LPUSH`; native `Array.push`.
21
- - [use-cache-lock](@warlock.js/cache/use-cache-lock/SKILL.md): Distributed lock via cache.lock(key, ttl, fn) — acquire, run fn, auto-release. Returns {acquired: true, value} or {acquired: false}. Triggers: `cache.lock`, `LockOutcome`, `acquired`, `owner`; "run cron on only one server", "idempotent webhook handler", "dedup payment processing", "lock a task across nodes"; typical import `import { cache } from "@warlock.js/cache"`. Skip: raw `onConflict: "create"` recipe — the `apply-cache-patterns` topic; memoization — the `use-cached-hof` topic; competing libs `redlock`, `async-mutex`, `proper-lockfile`.
22
- - [use-cache-namespace](@warlock.js/cache/use-cache-namespace/SKILL.md): Scope cache keys via cache.namespace(prefix, options?) — every key auto-prefixed, scope-level ttl / tags defaults, nested scopes, .clear() sugar. Triggers: `cache.namespace`, `cache.removeNamespace`, `clear`, `globalPrefix`; "scope cache keys under a prefix", "share TTL across a whole prefix", "drop every key under user.1", "nested cache scopes"; typical import `import { cache } from "@warlock.js/cache"`. Skip: tag-based bulk drop — the `use-cache-tags` topic; multi-tenant driver-level prefix — the `pick-cache-driver` topic; SWR — the `use-swr` topic; competing libs `keyv` namespaces.
23
- - [use-cache-similarity](@warlock.js/cache/use-cache-similarity/SKILL.md): Vector retrieval via cache.similar(vector, {topK, threshold?, tags?}) — index with set(k, v, {vector}), query nearest by cosine similarity. Triggers: `cache.similar`, `cache.set` with `vector`, `topK`, `threshold`, `tags`, `cosineSimilarity`; "build a semantic cache for an LLM", "RAG retrieval from cache", "nearest-neighbor over cached entries", "skip the LLM when a similar answer exists"; typical import `import { cache } from "@warlock.js/cache"`. Skip: pgvector setup specifics — the `configure-pg-cache` topic; competing libs `pinecone`, `weaviate`, `chromadb`, `lancedb`, `faiss-node`.
24
- - [use-cache-tags](@warlock.js/cache/use-cache-tags/SKILL.md): Tag-based invalidation — attach tags on write, then cache.tags([...]).invalidate() drops every key bound to any of those tags. Triggers: `cache.tags`, `invalidate`, `cache.set` with `tags`; "invalidate every key tagged users", "drop everything for tenant 42", "bulk cache invalidation without knowing keys", "tag a cached value"; typical import `import { cache } from "@warlock.js/cache"`. Skip: prefix-based drop — the `use-cache-namespace` topic; HOF memoization with tags — the `use-cached-hof` topic; SWR — the `use-swr` topic; competing libs `cache-manager` tags, Next.js `revalidateTag`.
25
- - [use-cache-update-merge](@warlock.js/cache/use-cache-update-merge/SKILL.md): Atomic read-modify-write via cache.update(key, fn) (callback receives current) or cache.merge(key, partial) (shallow merge). Per-key chain lock serializes concurrent in-process callers. Triggers: `cache.update`, `cache.merge`, `cache.increment`, `cache.pull`; "atomically update a cached counter", "change one field on a cached object", "avoid get-spread-set race", "serialize concurrent cache writers"; typical import `import { cache } from "@warlock.js/cache"`. Skip: cross-process locking — the `use-cache-lock` topic; conditional create/update — the `configure-set-options` topic; competing libs `lodash.merge`, raw redis `WATCH`/`MULTI`.
26
- - [use-cache-utils](@warlock.js/cache/use-cache-utils/SKILL.md): Low-level cache utilities re-exported from @warlock.js/cache — parseTtl, expiresAtToTtl, resolveTtl, normalizeToOptions, normalizeToRememberOptions, parseCacheKey, mergeTagSets, injectTags, cosineSimilarity, and the CACHE_FOR TTL enum. Triggers: `parseTtl`, `parseCacheKey`, `resolveTtl`, `expiresAtToTtl`, `cosineSimilarity`, `mergeTagSets`, `injectTags`, `CACHE_FOR`; "parse a duration to seconds", "build a cache key from an object", "score two vectors", "common TTL constant"; typical import `import { parseTtl, CACHE_FOR } from "@warlock.js/cache"`. Skip: building a whole custom driver — the `pick-cache-driver` topic; the high-level set API — the `configure-set-options` topic.
27
- - [use-cached-hof](@warlock.js/cache/use-cached-hof/SKILL.md): Wrap an async function with cached(fn, options) — declare the caching strategy once, call from many sites, get a bound .invalidate(...args) helper. Triggers: `cached`, `invalidate`, `key`, `ttl`, `tags`, `driver`; "wrap a DB lookup with caching", "memoize a function and invalidate by args", "one declaration many call sites", "auto-derive cache key from args"; typical import `import { cached } from "@warlock.js/cache"`. Skip: one-shot memoization — the `apply-cache-patterns` topic (`cache.remember`); tag bulk drop — the `use-cache-tags` topic; competing libs `p-memoize`, `mem`, `lodash.memoize`.
28
- - [use-swr](@warlock.js/cache/use-swr/SKILL.md): Stale-while-revalidate via cache.swr(key, {freshTtl, staleTtl}, fn) — returns cached instantly when fresh, returns cached + background refresh when stale, blocks only when fully expired. Triggers: `cache.swr`, `freshTtl`, `staleTtl`, `tags`, `driver`, `stale_at`; "serve stale while refreshing", "degrade when upstream is down", "never block on cache miss"; typical import `import { cache } from "@warlock.js/cache"`. Skip: block-until-fresh memoization — the `apply-cache-patterns` topic; observing refresh failures — the `observe-cache` topic; competing libs `swr` (React, client-side).
9
+ - [Package orientation](@warlock.js/cache/skills/index.md): Pluggable memory, LRU, file, Redis and Postgres caching: `cache`, `cached`, `CacheManager`, `TaggedCache`, `ScopedCache` and `MockCacheDriver`. Use for "cache this query", "invalidate a tenant", "stale-while-revalidate", "take a lock", tag invalidation or counters. Not this package → @warlock.js/core for HTTP response caching; @warlock.js/web for page caching; @warlock.js/cascade for persistent models.
10
+ - [apply-cache-patterns](@warlock.js/cache/skills/apply-cache-patterns/SKILL.md): Compose cache primitives into real-world patterns — remember() memoization, cross-node stampede protection via a distributed lock (onConflict: 'create'), negative caching, and per-tenant scoping. Triggers: `cache.remember`, `cache.set` with `onConflict: "create"`, `globalPrefix`; "memoize this function", "prevent cache stampede across nodes", "cache not-found results", "per-tenant cache scoping"; typical import `import { cache } from "@warlock.js/cache"`. Skip: counters — the `use-cache-atomic` topic; bulk get/set — the `use-cache-bulk` topic; TTL constants/utilities — the `use-cache-utils` topic; named lock wrapper — the `use-cache-lock` topic; SWR — the `use-swr` topic; competing libs `lru-cache`, `node-cache`, `keyv`.
11
+ - [cache-basics](@warlock.js/cache/skills/cache-basics/SKILL.md): Start here for @warlock.js/cache drivers, key-value operations, and application cache configuration.
12
+ - [configure-pg-cache](@warlock.js/cache/skills/configure-pg-cache/SKILL.md): Postgres cache driver setup — KV-only mode (default) or pgvector mode (opt in via options.pg.vector). Caller owns the pg.Pool, driver exposes driver.schema() for one-time DDL. Triggers: `PgCacheDriver`, `driver.schema`, `options.pg.vector`, `pg.Pool`, `hnsw`, `ivfflat`; "use Postgres as cache backend", "set up pgvector semantic cache", "DDL for warlock cache table"; typical import `import { cache, PgCacheDriver } from "@warlock.js/cache"`. Skip: cross-driver similarity API — the `use-cache-similarity` topic; driver picker — the `pick-cache-driver` topic; competing libs `pg-mem`; raw `pg` / `node-postgres`.
13
+ - [configure-set-options](@warlock.js/cache/skills/configure-set-options/SKILL.md): Configure cache.set's third argument — ttl, expiresAt, tags, onConflict (create / update / upsert), driver, vector. Triggers: `cache.set`, `ttl`, `expiresAt`, `tags`, `onConflict`, `driver`, `vector`, `CacheSetResult`, `wasSet`; "set a key only if missing", "set with absolute deadline", "attach tags inline", "route one cache call to redis"; typical import `import { cache } from "@warlock.js/cache"`. Skip: tag fluent API — the `use-cache-tags` topic; vector queries — the `use-cache-similarity` topic; competing libs `keyv`, `ioredis`.
14
+ - [handle-cache-errors](@warlock.js/cache/skills/handle-cache-errors/SKILL.md): Cache error classes — CacheError base, CacheConfigurationError, CacheConnectionError, CacheDriverNotInitializedError, CacheUnsupportedError, CacheConcurrencyError. Triggers: `CacheError`, `CacheConfigurationError`, `CacheConnectionError`, `CacheDriverNotInitializedError`, `CacheUnsupportedError`, `CacheConcurrencyError`; "catch cache errors at the boundary", "degrade when update or merge throws", "what does CacheUnsupportedError mean", "fall back when redis is down"; typical import `import { CacheError, CacheConfigurationError, CacheUnsupportedError } from "@warlock.js/cache"`. Skip: choosing a supported driver — the `pick-cache-driver` topic; observing errors via events — the `observe-cache` topic; competing libs ignore — generic `Error` patterns.
15
+ - [observe-cache](@warlock.js/cache/skills/observe-cache/SKILL.md): Cache observability — cache.metrics() for aggregate hit rate / latency p50/p95/p99 + event bus (cache.on('hit' / 'miss' / 'set' / 'removed' / 'flushed' / 'expired' / 'error', ...)). Triggers: `cache.metrics`, `cache.resetMetrics`, `cache.on`, `hit`, `miss`, `removed`, `flushed`, `error`, `hitRate`, `latencyMs`; "show cache hit rate", "page on cache errors", "is my cache being hit", "export metrics to prometheus"; typical import `import { cache } from "@warlock.js/cache"`. Skip: error classes — the `handle-cache-errors` topic; competing libs `prom-client`, `statsd-client`.
16
+ - [pick-cache-driver](@warlock.js/cache/skills/pick-cache-driver/SKILL.md): Pick a cache driver — null / memory / memoryExtended / lru / file / redis / pg / mock — and configure it. Triggers: `cache.setCacheConfigurations`, `BaseCacheDriver`, `cache.use`, `cache.load`, `cache.driver`, `globalPrefix`; "which cache driver should I use", "configure redis driver", "register custom cache driver", "multi-tenant scoping"; typical import `import { cache, BaseCacheDriver } from "@warlock.js/cache"`. Skip: cache CRUD — the `cache-basics` topic; pg setup — the `configure-pg-cache` topic; competing libs `lru-cache`, `node-cache`, `keyv`, `ioredis`; native `Map`.
17
+ - [test-cache-code](@warlock.js/cache/skills/test-cache-code/SKILL.md): Test code that touches cache — MockCacheDriver (behavioral assertions with wasCalled / callLog), MemoryCacheDriver (full-stack), NullCacheDriver (graceful-degradation). Triggers: `MockCacheDriver`, `MemoryCacheDriver`, `NullCacheDriver`, `wasCalled`, `callLog`, `getStored`, `reset`, `cache.on`; "assert cache was invalidated", "test code that uses cache.set", "mock cache in vitest", "test similarity without a real embedder", "stub the pg cache driver"; typical import `import { cache, MockCacheDriver, MemoryCacheDriver } from "@warlock.js/cache"`. Skip: real driver picks — the `pick-cache-driver` topic; competing libs `jest-mock`, `sinon`, `redis-mock`; native `vi.fn`.
18
+ - [use-cache-atomic](@warlock.js/cache/skills/use-cache-atomic/SKILL.md): Atomic counters via cache.increment(key, by=1, { ttl }?) / cache.decrement(key, by=1) — returns the new number, throws on non-numeric values. Triggers: `cache.increment`, `cache.decrement`, "view counter", "page views", "atomic counter", "decrement stock", "rate-limit counter", "INCRBY"; typical import `import { cache } from "@warlock.js/cache"`. Skip: read-modify-write of objects — the `use-cache-update-merge` topic; named-lock coordination — the `use-cache-lock` topic; competing libs `ioredis` `INCR`, native counters in a `Map`.
19
+ - [use-cache-bulk](@warlock.js/cache/skills/use-cache-bulk/SKILL.md): Bulk reads/writes via cache.many(keys[]) → values[] (nulls for misses, order preserved) and cache.setMany(record, ttl?) → void. Triggers: `cache.many`, `cache.setMany`, "get multiple keys at once", "batch read cache", "warm the cache", "preload many keys", "mget", "mset"; typical import `import { cache } from "@warlock.js/cache"`. Skip: tag-based bulk invalidation — the `use-cache-tags` topic; single-key ops — the `cache-basics` topic; competing libs `ioredis` `MGET`/`MSET`.
20
+ - [use-cache-list](@warlock.js/cache/skills/use-cache-list/SKILL.md): Ordered collections via cache.list<T>(key) — push / unshift / pop / shift / slice / all / length / trim / clear. Triggers: `cache.list`, `push`, `unshift`, `pop`, `shift`, `slice`, `trim`, `clear`; "job queue in cache", "keep most recent N events", "audit log buffer", "FIFO queue"; typical import `import { cache } from "@warlock.js/cache"`. Skip: locking around list writes — the `use-cache-lock` topic; competing libs `bullmq`, `bee-queue`, `bull`, `ioredis` `LPUSH`; native `Array.push`.
21
+ - [use-cache-lock](@warlock.js/cache/skills/use-cache-lock/SKILL.md): Distributed lock via cache.lock(key, ttl, fn) — acquire, run fn, auto-release. Returns {acquired: true, value} or {acquired: false}. Triggers: `cache.lock`, `LockOutcome`, `acquired`, `owner`; "run cron on only one server", "idempotent webhook handler", "dedup payment processing", "lock a task across nodes"; typical import `import { cache } from "@warlock.js/cache"`. Skip: raw `onConflict: "create"` recipe — the `apply-cache-patterns` topic; memoization — the `use-cached-hof` topic; competing libs `redlock`, `async-mutex`, `proper-lockfile`.
22
+ - [use-cache-namespace](@warlock.js/cache/skills/use-cache-namespace/SKILL.md): Scope cache keys via cache.namespace(prefix, options?) — every key auto-prefixed, scope-level ttl / tags defaults, nested scopes, .clear() sugar. Triggers: `cache.namespace`, `cache.removeNamespace`, `clear`, `globalPrefix`; "scope cache keys under a prefix", "share TTL across a whole prefix", "drop every key under user.1", "nested cache scopes"; typical import `import { cache } from "@warlock.js/cache"`. Skip: tag-based bulk drop — the `use-cache-tags` topic; multi-tenant driver-level prefix — the `pick-cache-driver` topic; SWR — the `use-swr` topic; competing libs `keyv` namespaces.
23
+ - [use-cache-similarity](@warlock.js/cache/skills/use-cache-similarity/SKILL.md): Vector retrieval via cache.similar(vector, {topK, threshold?, tags?}) — index with set(k, v, {vector}), query nearest by cosine similarity. Triggers: `cache.similar`, `cache.set` with `vector`, `topK`, `threshold`, `tags`, `cosineSimilarity`; "build a semantic cache for an LLM", "RAG retrieval from cache", "nearest-neighbor over cached entries", "skip the LLM when a similar answer exists"; typical import `import { cache } from "@warlock.js/cache"`. Skip: pgvector setup specifics — the `configure-pg-cache` topic; competing libs `pinecone`, `weaviate`, `chromadb`, `lancedb`, `faiss-node`.
24
+ - [use-cache-tags](@warlock.js/cache/skills/use-cache-tags/SKILL.md): Tag-based invalidation — attach tags on write, then cache.tags([...]).invalidate() drops every key bound to any of those tags. Triggers: `cache.tags`, `invalidate`, `cache.set` with `tags`; "invalidate every key tagged users", "drop everything for tenant 42", "bulk cache invalidation without knowing keys", "tag a cached value"; typical import `import { cache } from "@warlock.js/cache"`. Skip: prefix-based drop — the `use-cache-namespace` topic; HOF memoization with tags — the `use-cached-hof` topic; SWR — the `use-swr` topic; competing libs `cache-manager` tags, Next.js `revalidateTag`.
25
+ - [use-cache-update-merge](@warlock.js/cache/skills/use-cache-update-merge/SKILL.md): Atomic read-modify-write via cache.update(key, fn) (callback receives current) or cache.merge(key, partial) (shallow merge). Per-key chain lock serializes concurrent in-process callers. Triggers: `cache.update`, `cache.merge`, `cache.increment`, `cache.pull`; "atomically update a cached counter", "change one field on a cached object", "avoid get-spread-set race", "serialize concurrent cache writers"; typical import `import { cache } from "@warlock.js/cache"`. Skip: cross-process locking — the `use-cache-lock` topic; conditional create/update — the `configure-set-options` topic; competing libs `lodash.merge`, raw redis `WATCH`/`MULTI`.
26
+ - [use-cache-utils](@warlock.js/cache/skills/use-cache-utils/SKILL.md): Low-level cache utilities re-exported from @warlock.js/cache — parseTtl, expiresAtToTtl, resolveTtl, normalizeToOptions, normalizeToRememberOptions, parseCacheKey, mergeTagSets, injectTags, cosineSimilarity, and the CACHE_FOR TTL enum. Triggers: `parseTtl`, `parseCacheKey`, `resolveTtl`, `expiresAtToTtl`, `cosineSimilarity`, `mergeTagSets`, `injectTags`, `CACHE_FOR`; "parse a duration to seconds", "build a cache key from an object", "score two vectors", "common TTL constant"; typical import `import { parseTtl, CACHE_FOR } from "@warlock.js/cache"`. Skip: building a whole custom driver — the `pick-cache-driver` topic; the high-level set API — the `configure-set-options` topic.
27
+ - [use-cached-hof](@warlock.js/cache/skills/use-cached-hof/SKILL.md): Wrap an async function with cached(fn, options) — declare the caching strategy once, call from many sites, get a bound .invalidate(...args) helper. Triggers: `cached`, `invalidate`, `key`, `ttl`, `tags`, `driver`; "wrap a DB lookup with caching", "memoize a function and invalidate by args", "one declaration many call sites", "auto-derive cache key from args"; typical import `import { cached } from "@warlock.js/cache"`. Skip: one-shot memoization — the `apply-cache-patterns` topic (`cache.remember`); tag bulk drop — the `use-cache-tags` topic; competing libs `p-memoize`, `mem`, `lodash.memoize`.
28
+ - [use-swr](@warlock.js/cache/skills/use-swr/SKILL.md): Stale-while-revalidate via cache.swr(key, {freshTtl, staleTtl}, fn) — returns cached instantly when fresh, returns cached + background refresh when stale, blocks only when fully expired. Triggers: `cache.swr`, `freshTtl`, `staleTtl`, `tags`, `driver`, `stale_at`; "serve stale while refreshing", "degrade when upstream is down", "never block on cache miss"; typical import `import { cache } from "@warlock.js/cache"`. Skip: block-until-fresh memoization — the `apply-cache-patterns` topic; observing refresh failures — the `observe-cache` topic; competing libs `swr` (React, client-side).
package/package.json CHANGED
@@ -5,9 +5,9 @@
5
5
  "environment": "server"
6
6
  },
7
7
  "dependencies": {
8
- "@warlock.js/fs": "5.34.1",
8
+ "@warlock.js/fs": "5.34.3",
9
9
  "@mongez/reinforcements": "^4.0.2",
10
- "@warlock.js/logger": "5.34.1",
10
+ "@warlock.js/logger": "5.34.3",
11
11
  "ms": "^2.1.3"
12
12
  },
13
13
  "peerDependencies": {
@@ -47,7 +47,7 @@
47
47
  ],
48
48
  "author": "hassanzohdy",
49
49
  "license": "MIT",
50
- "version": "5.34.1",
50
+ "version": "5.34.3",
51
51
  "main": "./cjs/index.cjs",
52
52
  "module": "./esm/index.mjs",
53
53
  "types": "./esm/index.d.mts",
package/skills/index.md CHANGED
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: 'Cache layer for Warlock apps with pluggable drivers (memory, LRU, file, Redis, Postgres). Exports `cache`, `CacheManager`, `cached`, `TaggedCache`, `ScopedCache`, `RedisCacheDriver`, `MemoryCacheDriver`, `MockCacheDriver`, `PgCacheDriver`. Use for: "cache this query for 5 minutes", "invalidate every key for tenant 42", "stale-while-revalidate", "take a lock so only one worker runs this", "tag keys and flush the tag", "increment a counter in cache". Not this package: HTTP response/page caching belongs to @warlock.js/core or web; persistent data is a @warlock.js/cascade model.'
2
+ description: 'Pluggable memory, LRU, file, Redis and Postgres caching: `cache`, `cached`, `CacheManager`, `TaggedCache`, `ScopedCache` and `MockCacheDriver`. Use for "cache this query", "invalidate a tenant", "stale-while-revalidate", "take a lock", tag invalidation or counters. Not this package → @warlock.js/core for HTTP response caching; @warlock.js/web for page caching; @warlock.js/cascade for persistent models.'
3
3
  ---
4
4
 
5
5
  # @warlock.js/cache
@@ -8,12 +8,13 @@ The `cache` singleton (a `CacheManager`) fronts one active driver. Everything, f
8
8
 
9
9
  ## The 80% path
10
10
 
11
- 1. Orient: `overview.md`, `cache-basics.md`.
11
+ 1. Start with `cache-basics.md`.
12
12
  2. Choose and configure a driver: `pick-cache-driver.md` (Postgres: `configure-pg-cache.md`; TTL and options: `configure-set-options.md`).
13
13
  3. Cache expensive reads with `remember` or the `cached` wrapper: `use-cached-hof.md`, `apply-cache-patterns.md`.
14
14
  4. Invalidate in groups: `use-cache-tags.md` or `use-cache-namespace.md`.
15
15
  5. Stampede protection and freshness: `use-swr.md`, `use-cache-lock.md`.
16
- 6. Test with the mock driver: `test-cache-code.md`; errors and metrics: `handle-cache-errors.md`, `observe-cache.md`.
16
+ 6. TTL constants, key parsing and vector helpers: `use-cache-utils.md`.
17
+ 7. Test with the mock driver: `test-cache-code.md`; errors and metrics: `handle-cache-errors.md`, `observe-cache.md`.
17
18
 
18
19
  ## Conventions and pitfalls
19
20
 
@@ -21,3 +22,25 @@ The `cache` singleton (a `CacheManager`) fronts one active driver. Everything, f
21
22
  - Check `configure-set-options.md` for TTL units, and avoid `forever` for data that can go stale.
22
23
  - Atomic counters, bulk ops, lists, merge and similarity have their own topics (`use-cache-atomic.md`, `use-cache-bulk.md`, `use-cache-list.md`, `use-cache-update-merge.md`, `use-cache-similarity.md`); do not hand-roll read-modify-write.
23
24
  - Not every driver supports every feature; check the driver topic first.
25
+
26
+ ## When to reach for it
27
+
28
+ - You need a cache abstraction that swaps drivers per environment (memory in dev, Redis in prod) without changing call sites.
29
+ - You want more than get/set — tag-based bulk invalidation, locks for stampede safety, SWR for slow upstreams, or a semantic cache over vectors.
30
+ - You're inside a Warlock app (the framework wires the driver from config) — or standalone, calling `setCacheConfigurations` + `cache.init` yourself.
31
+
32
+ Skip if a plain `Map` covers your needs and you'll never need a second driver, TTLs, or invalidation.
33
+
34
+ ## The mental model in one paragraph
35
+
36
+ A single `cache` singleton fronts a configured driver. `cache.set(key, value, options?)` writes (TTL via `ttl`/`expiresAt`, inline `tags`, `onConflict`, a per-call `driver` override, or a `vector` for similarity); `cache.get` / `has` / `pull` / `remove` / `many` / `remember` read. Tags let you invalidate sets of keys you can't enumerate ahead of time; namespaces auto-prefix keys with shared TTL/tag defaults; locks serialize work across processes; SWR serves stale-but-instant while refreshing in the background; `update`/`merge` do atomic read-modify-write; `list<T>(key)` gives ordered collections; `similar(vector, …)` does nearest-neighbor retrieval. `cache.metrics()` and `cache.on(event, …)` make it observable.
37
+
38
+ ## What this package deliberately doesn't do
39
+
40
+ - **Be a database.** It's a cache — entries expire, drivers may evict. Don't store anything you can't recompute.
41
+ - **Guarantee cross-driver feature parity.** Vector similarity needs a memory-family driver (`memory` / `memoryExtended` / `lru`, brute force) or `pg` with pgvector; `redis` and `file` raise `CacheUnsupportedError`. Locks/tags behave per driver. Unsupported ops raise `CacheUnsupportedError` rather than silently degrading.
42
+ - **Own your Postgres pool.** The `pg` driver takes the `pg.Pool`/`Client` you already built and never closes it — connection lifecycle stays yours. (Redis is the opposite: you pass `url`/`host` options and the driver builds and owns the client, calling `quit()` on `disconnect()`.)
43
+
44
+ ## See also
45
+
46
+ - The `configure-app` topic of the `warlock-js-core` skill — wires the cache driver from `src/config/cache.ts` and exposes the singleton.
@@ -1,69 +0,0 @@
1
- ---
2
- name: overview
3
- description: "@warlock.js/cache overview for orientation and choosing the focused skill for the task."
4
- ---
5
-
6
- # `@warlock.js/cache` — overview
7
-
8
- One cache API over many drivers. Pick a driver (memory, memoryExtended, LRU, file, Redis, Postgres, null, mock), wire it once, and call `cache.get` / `cache.set` / `cache.remember` everywhere. On top of the key-value basics it adds tag invalidation, key namespaces, distributed locks, stale-while-revalidate, atomic update/merge, ordered lists, vector similarity, and built-in metrics + events.
9
-
10
- ## When to reach for it
11
-
12
- - You need a cache abstraction that swaps drivers per environment (memory in dev, Redis in prod) without changing call sites.
13
- - You want more than get/set — tag-based bulk invalidation, locks for stampede safety, SWR for slow upstreams, or a semantic cache over vectors.
14
- - You're inside a Warlock app (the framework wires the driver from config) — or standalone, calling `setCacheConfigurations` + `cache.init` yourself.
15
-
16
- Skip if a plain `Map` covers your needs and you'll never need a second driver, TTLs, or invalidation.
17
-
18
- ## The mental model in one paragraph
19
-
20
- A single `cache` singleton fronts a configured driver. `cache.set(key, value, options?)` writes (TTL via `ttl`/`expiresAt`, inline `tags`, `onConflict`, a per-call `driver` override, or a `vector` for similarity); `cache.get` / `has` / `pull` / `remove` / `many` / `remember` read. Tags let you invalidate sets of keys you can't enumerate ahead of time; namespaces auto-prefix keys with shared TTL/tag defaults; locks serialize work across processes; SWR serves stale-but-instant while refreshing in the background; `update`/`merge` do atomic read-modify-write; `list<T>(key)` gives ordered collections; `similar(vector, …)` does nearest-neighbor retrieval. `cache.metrics()` and `cache.on(event, …)` make it observable.
21
-
22
- ## Skills index
23
-
24
- Nineteen task skills. Most apps start with `cache-basics` + `pick-cache-driver` + `configure-set-options`.
25
-
26
- ### Foundations
27
-
28
- - The `cache-basics` topic — the `cache` singleton, primary ops (`set`/`get`/`has`/`pull`/`remove`/`many`/`forever`/`increment`/`decrement`/`remember`), TTL shapes, init flow. **Start here.**
29
- - The `pick-cache-driver` topic — choose + configure a driver: `null` / `memory` / `memoryExtended` / `lru` / `file` / `redis` / `pg` / `mock`; `globalPrefix` for multi-tenant scoping.
30
- - The `configure-set-options` topic — `cache.set`'s third argument: `ttl`, `expiresAt`, `tags`, `onConflict` (create/update/upsert), `driver`, `vector`.
31
- - The `configure-pg-cache` topic — Postgres driver: KV-only (default) or pgvector mode; caller owns the `pg.Pool`, `driver.schema()` emits the DDL.
32
-
33
- ### Invalidation + scoping
34
-
35
- - The `use-cache-tags` topic — tag on write, `cache.tags([...]).invalidate()` drops every bound key.
36
- - The `use-cache-namespace` topic — `cache.namespace(prefix, options?)` auto-prefixes keys with scope-level TTL/tag defaults and nested scopes.
37
-
38
- ### Patterns
39
-
40
- - The `use-cached-hof` topic — `cached(fn, options)` wraps an async function; one declaration, many call sites, a bound `.invalidate(...args)`.
41
- - The `apply-cache-patterns` topic — `remember()` memoization, distributed locks via `onConflict: "create"`, negative caching, counters, per-tenant prefix, `CACHE_FOR.*` TTL constants.
42
- - The `use-cache-lock` topic — `cache.lock(key, ttl, fn)`: acquire → run → auto-release. For cron/imports/migrations and idempotent webhook/payment processing.
43
- - The `use-swr` topic — `cache.swr(key, { freshTtl, staleTtl }, fn)`: instant when fresh, instant + background refresh when stale, blocks only when fully expired.
44
- - The `use-cache-update-merge` topic — atomic read-modify-write via `cache.update(key, fn)` / `cache.merge(key, partial)`, serialized per key, TTL-preserving.
45
- - The `use-cache-atomic` topic — `cache.increment` / `cache.decrement` counters; per-driver atomicity + TTL behavior.
46
- - The `use-cache-bulk` topic — `cache.many(keys)` / `cache.setMany(record, ttl?)` for batch reads/writes.
47
- - The `use-cache-list` topic — `cache.list<T>(key)`: `push`/`unshift`/`pop`/`shift`/`slice`/`trim`/`clear` for queues, recent-N buffers, sliding windows.
48
- - The `use-cache-similarity` topic — `cache.similar(vector, { topK, threshold?, tags? })` for semantic caches, RAG retrieval, nearest-neighbor lookup.
49
-
50
- ### Operations
51
-
52
- - The `observe-cache` topic — `cache.metrics()` (hit rate, latency p50/p95/p99) + the event bus (`cache.on("hit" | "miss" | "set" | "removed" | "flushed" | "expired" | "connected" | "disconnected" | "error", …)`).
53
- - The `handle-cache-errors` topic — the error classes: `CacheError`, `CacheConfigurationError`, `CacheConnectionError`, `CacheDriverNotInitializedError`, `CacheUnsupportedError`, `CacheConcurrencyError`.
54
- - The `test-cache-code` topic — `MockCacheDriver` (behavioral assertions), `MemoryCacheDriver` (full-stack), `NullCacheDriver` (graceful degradation).
55
-
56
- ### Utilities
57
-
58
- - The `use-cache-utils` topic — low-level re-exports: `parseTtl`, `parseCacheKey`, `resolveTtl`, `expiresAtToTtl`, `mergeTagSets`, `injectTags`, `cosineSimilarity`, and the `CACHE_FOR` TTL enum.
59
-
60
- ## What this package deliberately doesn't do
61
-
62
- - **Be a database.** It's a cache — entries expire, drivers may evict. Don't store anything you can't recompute.
63
- - **Guarantee cross-driver feature parity.** Vector similarity needs a memory-family driver (`memory` / `memoryExtended` / `lru`, brute force) or `pg` with pgvector; `redis` and `file` raise `CacheUnsupportedError`. Locks/tags behave per driver. Unsupported ops raise `CacheUnsupportedError` rather than silently degrading.
64
- - **Own your Postgres pool.** The `pg` driver takes the `pg.Pool`/`Client` you already built and never closes it — connection lifecycle stays yours. (Redis is the opposite: you pass `url`/`host` options and the driver builds and owns the client, calling `quit()` on `disconnect()`.)
65
-
66
- ## See also
67
-
68
- - The `configure-app` topic of the `warlock-js-core` skill — wires the cache driver from `src/config/cache.ts` and exposes the singleton.
69
- - `mongez-agent-kit-authoring-skills` (load via agent-kit sync) — how this becomes `.claude/skills/warlock-js-cache/overview.md`.