@warlock.js/cache 4.0.171 → 4.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +85 -0
- package/cjs/index.cjs +4088 -0
- package/cjs/index.cjs.map +1 -0
- package/esm/cache-manager.d.mts +314 -0
- package/esm/cache-manager.d.mts.map +1 -0
- package/esm/cache-manager.mjs +486 -0
- package/esm/cache-manager.mjs.map +1 -0
- package/esm/cached/auto-key.d.mts +25 -0
- package/esm/cached/auto-key.d.mts.map +1 -0
- package/esm/cached/auto-key.mjs +55 -0
- package/esm/cached/auto-key.mjs.map +1 -0
- package/esm/cached/cached.d.mts +54 -0
- package/esm/cached/cached.d.mts.map +1 -0
- package/esm/cached/cached.mjs +25 -0
- package/esm/cached/cached.mjs.map +1 -0
- package/esm/cached/index.d.mts +3 -0
- package/esm/cached/index.mjs +5 -0
- package/esm/cached/normalize-args.d.mts +51 -0
- package/esm/cached/normalize-args.d.mts.map +1 -0
- package/esm/cached/normalize-args.mjs +26 -0
- package/esm/cached/normalize-args.mjs.map +1 -0
- package/esm/drivers/base-cache-driver.d.mts +322 -0
- package/esm/drivers/base-cache-driver.d.mts.map +1 -0
- package/esm/drivers/base-cache-driver.mjs +522 -0
- package/esm/drivers/base-cache-driver.mjs.map +1 -0
- package/esm/drivers/file-cache-driver.d.mts +68 -0
- package/esm/drivers/file-cache-driver.d.mts.map +1 -0
- package/esm/drivers/file-cache-driver.mjs +174 -0
- package/esm/drivers/file-cache-driver.mjs.map +1 -0
- package/esm/drivers/index.d.mts +9 -0
- package/esm/drivers/index.mjs +11 -0
- package/esm/drivers/lru-memory-cache-driver.d.mts +136 -0
- package/esm/drivers/lru-memory-cache-driver.d.mts.map +1 -0
- package/esm/drivers/lru-memory-cache-driver.mjs +317 -0
- package/esm/drivers/lru-memory-cache-driver.mjs.map +1 -0
- package/esm/drivers/memory-cache-driver.d.mts +112 -0
- package/esm/drivers/memory-cache-driver.d.mts.map +1 -0
- package/esm/drivers/memory-cache-driver.mjs +241 -0
- package/esm/drivers/memory-cache-driver.mjs.map +1 -0
- package/esm/drivers/memory-extended-cache-driver.d.mts +17 -0
- package/esm/drivers/memory-extended-cache-driver.d.mts.map +1 -0
- package/esm/drivers/memory-extended-cache-driver.mjs +34 -0
- package/esm/drivers/memory-extended-cache-driver.mjs.map +1 -0
- package/esm/drivers/mock-cache-driver.d.mts +137 -0
- package/esm/drivers/mock-cache-driver.d.mts.map +1 -0
- package/esm/drivers/mock-cache-driver.mjs +226 -0
- package/esm/drivers/mock-cache-driver.mjs.map +1 -0
- package/esm/drivers/null-cache-driver.d.mts +69 -0
- package/esm/drivers/null-cache-driver.d.mts.map +1 -0
- package/esm/drivers/null-cache-driver.mjs +92 -0
- package/esm/drivers/null-cache-driver.mjs.map +1 -0
- package/esm/drivers/pg-cache-driver.d.mts +148 -0
- package/esm/drivers/pg-cache-driver.d.mts.map +1 -0
- package/esm/drivers/pg-cache-driver.mjs +437 -0
- package/esm/drivers/pg-cache-driver.mjs.map +1 -0
- package/esm/drivers/redis-cache-driver.d.mts +86 -0
- package/esm/drivers/redis-cache-driver.d.mts.map +1 -0
- package/esm/drivers/redis-cache-driver.mjs +312 -0
- package/esm/drivers/redis-cache-driver.mjs.map +1 -0
- package/esm/index.d.mts +21 -0
- package/esm/index.mjs +24 -0
- package/esm/list/index.d.mts +1 -0
- package/esm/list/memory-cache-list.d.mts +77 -0
- package/esm/list/memory-cache-list.d.mts.map +1 -0
- package/esm/list/memory-cache-list.mjs +119 -0
- package/esm/list/memory-cache-list.mjs.map +1 -0
- package/esm/metrics.d.mts +118 -0
- package/esm/metrics.d.mts.map +1 -0
- package/esm/metrics.mjs +197 -0
- package/esm/metrics.mjs.map +1 -0
- package/esm/scoped-cache.d.mts +205 -0
- package/esm/scoped-cache.d.mts.map +1 -0
- package/esm/scoped-cache.mjs +274 -0
- package/esm/scoped-cache.mjs.map +1 -0
- package/esm/tagged-cache.d.mts +89 -0
- package/esm/tagged-cache.d.mts.map +1 -0
- package/esm/tagged-cache.mjs +147 -0
- package/esm/tagged-cache.mjs.map +1 -0
- package/esm/tagged-scoped-cache.d.mts +111 -0
- package/esm/tagged-scoped-cache.d.mts.map +1 -0
- package/esm/tagged-scoped-cache.mjs +142 -0
- package/esm/tagged-scoped-cache.mjs.map +1 -0
- package/esm/types.d.mts +1067 -0
- package/esm/types.d.mts.map +1 -0
- package/esm/types.mjs +62 -0
- package/esm/types.mjs.map +1 -0
- package/esm/utils.d.mts +161 -0
- package/esm/utils.d.mts.map +1 -0
- package/esm/utils.mjs +222 -0
- package/esm/utils.mjs.map +1 -0
- package/llms-full.txt +2071 -0
- package/llms.txt +28 -0
- package/package.json +53 -39
- package/skills/apply-cache-patterns/SKILL.md +97 -0
- package/skills/cache-basics/SKILL.md +121 -0
- package/skills/configure-pg-cache/SKILL.md +115 -0
- package/skills/configure-set-options/SKILL.md +96 -0
- package/skills/handle-cache-errors/SKILL.md +91 -0
- package/skills/observe-cache/SKILL.md +103 -0
- package/skills/overview/SKILL.md +69 -0
- package/skills/pick-cache-driver/SKILL.md +115 -0
- package/skills/test-cache-code/SKILL.md +219 -0
- package/skills/use-cache-atomic/SKILL.md +67 -0
- package/skills/use-cache-bulk/SKILL.md +57 -0
- package/skills/use-cache-list/SKILL.md +85 -0
- package/skills/use-cache-lock/SKILL.md +104 -0
- package/skills/use-cache-namespace/SKILL.md +88 -0
- package/skills/use-cache-similarity/SKILL.md +94 -0
- package/skills/use-cache-tags/SKILL.md +85 -0
- package/skills/use-cache-update-merge/SKILL.md +84 -0
- package/skills/use-cache-utils/SKILL.md +89 -0
- package/skills/use-cached-hof/SKILL.md +102 -0
- package/skills/use-swr/SKILL.md +104 -0
- package/cjs/cache-manager.d.ts +0 -163
- package/cjs/cache-manager.d.ts.map +0 -1
- package/cjs/cache-manager.js +0 -322
- package/cjs/cache-manager.js.map +0 -1
- package/cjs/drivers/base-cache-driver.d.ts +0 -152
- package/cjs/drivers/base-cache-driver.d.ts.map +0 -1
- package/cjs/drivers/base-cache-driver.js +0 -321
- package/cjs/drivers/base-cache-driver.js.map +0 -1
- package/cjs/drivers/file-cache-driver.d.ts +0 -45
- package/cjs/drivers/file-cache-driver.d.ts.map +0 -1
- package/cjs/drivers/file-cache-driver.js +0 -133
- package/cjs/drivers/file-cache-driver.js.map +0 -1
- package/cjs/drivers/index.d.ts +0 -8
- package/cjs/drivers/index.d.ts.map +0 -1
- package/cjs/drivers/lru-memory-cache-driver.d.ts +0 -98
- package/cjs/drivers/lru-memory-cache-driver.d.ts.map +0 -1
- package/cjs/drivers/lru-memory-cache-driver.js +0 -252
- package/cjs/drivers/lru-memory-cache-driver.js.map +0 -1
- package/cjs/drivers/memory-cache-driver.d.ts +0 -82
- package/cjs/drivers/memory-cache-driver.d.ts.map +0 -1
- package/cjs/drivers/memory-cache-driver.js +0 -218
- package/cjs/drivers/memory-cache-driver.js.map +0 -1
- package/cjs/drivers/memory-extended-cache-driver.d.ts +0 -13
- package/cjs/drivers/memory-extended-cache-driver.d.ts.map +0 -1
- package/cjs/drivers/memory-extended-cache-driver.js +0 -25
- package/cjs/drivers/memory-extended-cache-driver.js.map +0 -1
- package/cjs/drivers/null-cache-driver.d.ts +0 -58
- package/cjs/drivers/null-cache-driver.d.ts.map +0 -1
- package/cjs/drivers/null-cache-driver.js +0 -84
- package/cjs/drivers/null-cache-driver.js.map +0 -1
- package/cjs/drivers/redis-cache-driver.d.ts +0 -57
- package/cjs/drivers/redis-cache-driver.d.ts.map +0 -1
- package/cjs/drivers/redis-cache-driver.js +0 -263
- package/cjs/drivers/redis-cache-driver.js.map +0 -1
- package/cjs/index.d.ts +0 -6
- package/cjs/index.d.ts.map +0 -1
- package/cjs/index.js +0 -1
- package/cjs/index.js.map +0 -1
- package/cjs/tagged-cache.d.ts +0 -77
- package/cjs/tagged-cache.d.ts.map +0 -1
- package/cjs/tagged-cache.js +0 -160
- package/cjs/tagged-cache.js.map +0 -1
- package/cjs/types.d.ts +0 -391
- package/cjs/types.d.ts.map +0 -1
- package/cjs/types.js +0 -36
- package/cjs/types.js.map +0 -1
- package/cjs/utils.d.ts +0 -50
- package/cjs/utils.d.ts.map +0 -1
- package/cjs/utils.js +0 -55
- package/cjs/utils.js.map +0 -1
- package/esm/cache-manager.d.ts +0 -163
- package/esm/cache-manager.d.ts.map +0 -1
- package/esm/cache-manager.js +0 -322
- package/esm/cache-manager.js.map +0 -1
- package/esm/drivers/base-cache-driver.d.ts +0 -152
- package/esm/drivers/base-cache-driver.d.ts.map +0 -1
- package/esm/drivers/base-cache-driver.js +0 -321
- package/esm/drivers/base-cache-driver.js.map +0 -1
- package/esm/drivers/file-cache-driver.d.ts +0 -45
- package/esm/drivers/file-cache-driver.d.ts.map +0 -1
- package/esm/drivers/file-cache-driver.js +0 -133
- package/esm/drivers/file-cache-driver.js.map +0 -1
- package/esm/drivers/index.d.ts +0 -8
- package/esm/drivers/index.d.ts.map +0 -1
- package/esm/drivers/lru-memory-cache-driver.d.ts +0 -98
- package/esm/drivers/lru-memory-cache-driver.d.ts.map +0 -1
- package/esm/drivers/lru-memory-cache-driver.js +0 -252
- package/esm/drivers/lru-memory-cache-driver.js.map +0 -1
- package/esm/drivers/memory-cache-driver.d.ts +0 -82
- package/esm/drivers/memory-cache-driver.d.ts.map +0 -1
- package/esm/drivers/memory-cache-driver.js +0 -218
- package/esm/drivers/memory-cache-driver.js.map +0 -1
- package/esm/drivers/memory-extended-cache-driver.d.ts +0 -13
- package/esm/drivers/memory-extended-cache-driver.d.ts.map +0 -1
- package/esm/drivers/memory-extended-cache-driver.js +0 -25
- package/esm/drivers/memory-extended-cache-driver.js.map +0 -1
- package/esm/drivers/null-cache-driver.d.ts +0 -58
- package/esm/drivers/null-cache-driver.d.ts.map +0 -1
- package/esm/drivers/null-cache-driver.js +0 -84
- package/esm/drivers/null-cache-driver.js.map +0 -1
- package/esm/drivers/redis-cache-driver.d.ts +0 -57
- package/esm/drivers/redis-cache-driver.d.ts.map +0 -1
- package/esm/drivers/redis-cache-driver.js +0 -263
- package/esm/drivers/redis-cache-driver.js.map +0 -1
- package/esm/index.d.ts +0 -6
- package/esm/index.d.ts.map +0 -1
- package/esm/index.js +0 -1
- package/esm/index.js.map +0 -1
- package/esm/tagged-cache.d.ts +0 -77
- package/esm/tagged-cache.d.ts.map +0 -1
- package/esm/tagged-cache.js +0 -160
- package/esm/tagged-cache.js.map +0 -1
- package/esm/types.d.ts +0 -391
- package/esm/types.d.ts.map +0 -1
- package/esm/types.js +0 -36
- package/esm/types.js.map +0 -1
- package/esm/utils.d.ts +0 -50
- package/esm/utils.d.ts.map +0 -1
- package/esm/utils.js +0 -55
- package/esm/utils.js.map +0 -1
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { CacheKey, CacheSetOptions, CacheTtl, RememberOptions, TaggedScopedCacheContract } from "./types.mjs";
|
|
2
|
+
import { ScopedCache } from "./scoped-cache.mjs";
|
|
3
|
+
|
|
4
|
+
//#region ../../@warlock.js/cache/src/tagged-scoped-cache.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* One-shot tagged write handle on top of a {@link ScopedCache}.
|
|
7
|
+
*
|
|
8
|
+
* **Role.** Returned by `scope.tags([...])`. Adds a fixed list of tags to
|
|
9
|
+
* every write produced through this handle, on top of any tags the parent
|
|
10
|
+
* scope already contributes. Stateless except for the captured tag list.
|
|
11
|
+
*
|
|
12
|
+
* **Responsibility.**
|
|
13
|
+
* - Owns: appending the handle's tags to writes, delegating tag-index
|
|
14
|
+
* bookkeeping for `setNX` (which lacks an inline `tags` knob on the driver
|
|
15
|
+
* contract), and computing the union for `invalidate()` calls.
|
|
16
|
+
* - Does NOT own: storage, prefix-prepending (delegated to the scope),
|
|
17
|
+
* default `ttl` (delegated to the scope), or any kind of long-lived state.
|
|
18
|
+
*
|
|
19
|
+
* Tags compose additively: scope tags + handle tags + per-call tags, all
|
|
20
|
+
* unioned and deduped. The handle never replaces scope tags — `invalidate()`
|
|
21
|
+
* always sees the full union.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* // Inside application code — scope provides the per-user tag automatically:
|
|
25
|
+
* const feed = cache.namespace(`feed.${userId}`, { tags: [`user.${userId}`] });
|
|
26
|
+
*
|
|
27
|
+
* await feed.tags(["unread"]).set("messages.1", message);
|
|
28
|
+
* // → tagged with [user.<id>, unread]
|
|
29
|
+
*
|
|
30
|
+
* await feed.tags(["unread"]).invalidate();
|
|
31
|
+
* // → wipes everything tagged with user.<id> OR unread.
|
|
32
|
+
*/
|
|
33
|
+
declare class TaggedScopedCache implements TaggedScopedCacheContract {
|
|
34
|
+
/**
|
|
35
|
+
* The {@link ScopedCache} this handle delegates to. Held by reference so
|
|
36
|
+
* scope-default changes (none today, but the option is preserved for the
|
|
37
|
+
* future) are visible without rebuilding the handle.
|
|
38
|
+
*/
|
|
39
|
+
protected readonly scope: ScopedCache;
|
|
40
|
+
/**
|
|
41
|
+
* Tags this handle contributes to every write. Cloned at the call site so
|
|
42
|
+
* later mutation of the input array doesn't leak in.
|
|
43
|
+
*/
|
|
44
|
+
protected readonly handleTags: string[];
|
|
45
|
+
/**
|
|
46
|
+
* Build a tagged handle. Constructed via `scope.tags([...])` — users never
|
|
47
|
+
* call this directly.
|
|
48
|
+
*/
|
|
49
|
+
constructor(scope: ScopedCache, handleTags: string[]);
|
|
50
|
+
/**
|
|
51
|
+
* Write the scoped key with the handle's tags appended to whatever the
|
|
52
|
+
* caller passed. Scope-level tags are added on top by the scope itself.
|
|
53
|
+
*/
|
|
54
|
+
set(key: CacheKey, value: any, ttlOrOptions?: CacheTtl | CacheSetOptions): Promise<any>;
|
|
55
|
+
/**
|
|
56
|
+
* Read the scoped key. Tags don't affect reads — pass-through.
|
|
57
|
+
*/
|
|
58
|
+
get<T = any>(key: CacheKey): Promise<T | null>;
|
|
59
|
+
/**
|
|
60
|
+
* Check presence of the scoped key.
|
|
61
|
+
*/
|
|
62
|
+
has(key: CacheKey): Promise<boolean>;
|
|
63
|
+
/**
|
|
64
|
+
* Remove the scoped key. The tag-index entry will eventually be cleaned up
|
|
65
|
+
* by `invalidate()`; we don't proactively rewrite it here for cost reasons.
|
|
66
|
+
*/
|
|
67
|
+
remove(key: CacheKey): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* Read-and-remove the scoped key.
|
|
70
|
+
*/
|
|
71
|
+
pull<T = any>(key: CacheKey): Promise<T | null>;
|
|
72
|
+
/**
|
|
73
|
+
* Permanent write with handle tags applied. Bypasses both the scope's and
|
|
74
|
+
* the caller's TTL (forever means forever) — only tags get injected.
|
|
75
|
+
*/
|
|
76
|
+
forever<T = any>(key: CacheKey, value: T): Promise<T>;
|
|
77
|
+
/**
|
|
78
|
+
* Atomic create-or-skip with the handle's tags applied on success. The
|
|
79
|
+
* driver contract has no inline `tags` knob on `setNX`, so we register the
|
|
80
|
+
* tag relationship manually after a successful write.
|
|
81
|
+
*/
|
|
82
|
+
setNX(key: CacheKey, value: any, ttl?: number): Promise<boolean>;
|
|
83
|
+
/**
|
|
84
|
+
* Read-or-compute with handle tags appended on the cache-miss write.
|
|
85
|
+
*/
|
|
86
|
+
remember<T = any>(key: CacheKey, ttlOrOptions: CacheTtl | RememberOptions, callback: () => Promise<T>): Promise<T>;
|
|
87
|
+
/**
|
|
88
|
+
* Atomic counter increment on the scoped key. Tags aren't applied to
|
|
89
|
+
* subsequent increments — they're attached at first-write time.
|
|
90
|
+
*/
|
|
91
|
+
increment(key: CacheKey, value?: number): Promise<number>;
|
|
92
|
+
/**
|
|
93
|
+
* Atomic counter decrement on the scoped key. See {@link increment}.
|
|
94
|
+
*/
|
|
95
|
+
decrement(key: CacheKey, value?: number): Promise<number>;
|
|
96
|
+
/**
|
|
97
|
+
* Wipe every entry tagged with the union of (scope tags + handle tags).
|
|
98
|
+
* Tags are global across the package, so this reaches outside the scope's
|
|
99
|
+
* prefix when scope tags are also used elsewhere.
|
|
100
|
+
*/
|
|
101
|
+
invalidate(): Promise<void>;
|
|
102
|
+
/**
|
|
103
|
+
* Compute the source-side key the same way `ScopedCache.scopedKey` does —
|
|
104
|
+
* needed for `setNX`, where we have to register the tag relationship by
|
|
105
|
+
* hand because the driver contract doesn't accept inline tags there.
|
|
106
|
+
*/
|
|
107
|
+
protected buildScopedKey(key: CacheKey): string;
|
|
108
|
+
}
|
|
109
|
+
//#endregion
|
|
110
|
+
export { TaggedScopedCache };
|
|
111
|
+
//# sourceMappingURL=tagged-scoped-cache.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tagged-scoped-cache.d.mts","names":[],"sources":["../../../../../@warlock.js/cache/src/tagged-scoped-cache.ts"],"mappings":";;;;;;AA4CA;;;;;;;;;;;;;;;;;;;;;;;;;;cAAa,iBAAA,YAA6B,yBAAA;EA+Gb;;;;;EAAA,mBAzGR,KAAA,EAAO,WAAA;EAwHuB;;;;EAAA,mBAlH9B,UAAA;EAZqB;;;;cAkBrB,KAAA,EAAO,WAAA,EAAa,UAAA;EAZb;;;;EAqBnB,GAAA,CACL,GAAA,EAAK,QAAA,EACL,KAAA,OACA,YAAA,GAAe,QAAA,GAAW,eAAA,GACzB,OAAA;EAboC;;;EAsBhC,GAAA,SAAA,CAAa,GAAA,EAAK,QAAA,GAAW,OAAA,CAAQ,CAAA;EAX1C;;;EAkBK,GAAA,CAAI,GAAA,EAAK,QAAA,GAAW,OAAA;EAhBxB;;;;EAwBI,MAAA,CAAO,GAAA,EAAK,QAAA,GAAW,OAAA;EAfM;;;EAsB7B,IAAA,SAAA,CAAc,GAAA,EAAK,QAAA,GAAW,OAAA,CAAQ,CAAA;EAflC;;;;EAuBJ,OAAA,SAAA,CAAiB,GAAA,EAAK,QAAA,EAAU,KAAA,EAAO,CAAA,GAAI,OAAA,CAAQ,CAAA;EAf5B;;;;;EA2BjB,KAAA,CAAM,GAAA,EAAK,QAAA,EAAU,KAAA,OAAY,GAAA,YAAe,OAAA;EApBhB;;;EA+CtC,QAAA,SAAA,CACL,GAAA,EAAK,QAAA,EACL,YAAA,EAAc,QAAA,GAAW,eAAA,EACzB,QAAA,QAAgB,OAAA,CAAQ,CAAA,IACvB,OAAA,CAAQ,CAAA;EA3Ca;;;;EAwDjB,SAAA,CAAU,GAAA,EAAK,QAAA,EAAU,KAAA,YAAiB,OAAA;EA5CpC;;;EAmDN,SAAA,CAAU,GAAA,EAAK,QAAA,EAAU,KAAA,YAAiB,OAAA;EAnDH;;;;;EA4DjC,UAAA,CAAA,GAAc,OAAA;EA/BX;;;;;EAAA,UA8CN,cAAA,CAAe,GAAA,EAAK,QAAA;AAAA"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { injectTags, mergeTagSets, normalizeToOptions, normalizeToRememberOptions, parseCacheKey } from "./utils.mjs";
|
|
2
|
+
|
|
3
|
+
//#region ../../@warlock.js/cache/src/tagged-scoped-cache.ts
|
|
4
|
+
/**
|
|
5
|
+
* One-shot tagged write handle on top of a {@link ScopedCache}.
|
|
6
|
+
*
|
|
7
|
+
* **Role.** Returned by `scope.tags([...])`. Adds a fixed list of tags to
|
|
8
|
+
* every write produced through this handle, on top of any tags the parent
|
|
9
|
+
* scope already contributes. Stateless except for the captured tag list.
|
|
10
|
+
*
|
|
11
|
+
* **Responsibility.**
|
|
12
|
+
* - Owns: appending the handle's tags to writes, delegating tag-index
|
|
13
|
+
* bookkeeping for `setNX` (which lacks an inline `tags` knob on the driver
|
|
14
|
+
* contract), and computing the union for `invalidate()` calls.
|
|
15
|
+
* - Does NOT own: storage, prefix-prepending (delegated to the scope),
|
|
16
|
+
* default `ttl` (delegated to the scope), or any kind of long-lived state.
|
|
17
|
+
*
|
|
18
|
+
* Tags compose additively: scope tags + handle tags + per-call tags, all
|
|
19
|
+
* unioned and deduped. The handle never replaces scope tags — `invalidate()`
|
|
20
|
+
* always sees the full union.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* // Inside application code — scope provides the per-user tag automatically:
|
|
24
|
+
* const feed = cache.namespace(`feed.${userId}`, { tags: [`user.${userId}`] });
|
|
25
|
+
*
|
|
26
|
+
* await feed.tags(["unread"]).set("messages.1", message);
|
|
27
|
+
* // → tagged with [user.<id>, unread]
|
|
28
|
+
*
|
|
29
|
+
* await feed.tags(["unread"]).invalidate();
|
|
30
|
+
* // → wipes everything tagged with user.<id> OR unread.
|
|
31
|
+
*/
|
|
32
|
+
var TaggedScopedCache = class {
|
|
33
|
+
/**
|
|
34
|
+
* Build a tagged handle. Constructed via `scope.tags([...])` — users never
|
|
35
|
+
* call this directly.
|
|
36
|
+
*/
|
|
37
|
+
constructor(scope, handleTags) {
|
|
38
|
+
this.scope = scope;
|
|
39
|
+
this.handleTags = [...handleTags];
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Write the scoped key with the handle's tags appended to whatever the
|
|
43
|
+
* caller passed. Scope-level tags are added on top by the scope itself.
|
|
44
|
+
*/
|
|
45
|
+
set(key, value, ttlOrOptions) {
|
|
46
|
+
const options = injectTags(normalizeToOptions(ttlOrOptions), this.handleTags);
|
|
47
|
+
return this.scope.set(key, value, options);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Read the scoped key. Tags don't affect reads — pass-through.
|
|
51
|
+
*/
|
|
52
|
+
get(key) {
|
|
53
|
+
return this.scope.get(key);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Check presence of the scoped key.
|
|
57
|
+
*/
|
|
58
|
+
has(key) {
|
|
59
|
+
return this.scope.has(key);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Remove the scoped key. The tag-index entry will eventually be cleaned up
|
|
63
|
+
* by `invalidate()`; we don't proactively rewrite it here for cost reasons.
|
|
64
|
+
*/
|
|
65
|
+
remove(key) {
|
|
66
|
+
return this.scope.remove(key);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Read-and-remove the scoped key.
|
|
70
|
+
*/
|
|
71
|
+
pull(key) {
|
|
72
|
+
return this.scope.pull(key);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Permanent write with handle tags applied. Bypasses both the scope's and
|
|
76
|
+
* the caller's TTL (forever means forever) — only tags get injected.
|
|
77
|
+
*/
|
|
78
|
+
forever(key, value) {
|
|
79
|
+
return this.scope.set(key, value, {
|
|
80
|
+
ttl: Infinity,
|
|
81
|
+
tags: this.handleTags
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Atomic create-or-skip with the handle's tags applied on success. The
|
|
86
|
+
* driver contract has no inline `tags` knob on `setNX`, so we register the
|
|
87
|
+
* tag relationship manually after a successful write.
|
|
88
|
+
*/
|
|
89
|
+
async setNX(key, value, ttl) {
|
|
90
|
+
if (!await this.scope.setNX(key, value, ttl)) return false;
|
|
91
|
+
const allTags = mergeTagSets(this.scope.defaults.tags, this.handleTags);
|
|
92
|
+
if (!allTags || allTags.length === 0) return true;
|
|
93
|
+
const scopedKey = this.buildScopedKey(key);
|
|
94
|
+
const parsedKey = this.scope.source.parseKey(scopedKey);
|
|
95
|
+
await this.scope.source.tags(allTags).storeTagRelationship(parsedKey);
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Read-or-compute with handle tags appended on the cache-miss write.
|
|
100
|
+
*/
|
|
101
|
+
remember(key, ttlOrOptions, callback) {
|
|
102
|
+
const options = injectTags(normalizeToRememberOptions(ttlOrOptions), this.handleTags);
|
|
103
|
+
return this.scope.remember(key, options, callback);
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Atomic counter increment on the scoped key. Tags aren't applied to
|
|
107
|
+
* subsequent increments — they're attached at first-write time.
|
|
108
|
+
*/
|
|
109
|
+
increment(key, value) {
|
|
110
|
+
return this.scope.increment(key, value);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Atomic counter decrement on the scoped key. See {@link increment}.
|
|
114
|
+
*/
|
|
115
|
+
decrement(key, value) {
|
|
116
|
+
return this.scope.decrement(key, value);
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Wipe every entry tagged with the union of (scope tags + handle tags).
|
|
120
|
+
* Tags are global across the package, so this reaches outside the scope's
|
|
121
|
+
* prefix when scope tags are also used elsewhere.
|
|
122
|
+
*/
|
|
123
|
+
async invalidate() {
|
|
124
|
+
const allTags = mergeTagSets(this.scope.defaults.tags, this.handleTags);
|
|
125
|
+
if (!allTags || allTags.length === 0) return;
|
|
126
|
+
await this.scope.source.tags(allTags).invalidate();
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Compute the source-side key the same way `ScopedCache.scopedKey` does —
|
|
130
|
+
* needed for `setNX`, where we have to register the tag relationship by
|
|
131
|
+
* hand because the driver contract doesn't accept inline tags there.
|
|
132
|
+
*/
|
|
133
|
+
buildScopedKey(key) {
|
|
134
|
+
const keyString = typeof key === "string" ? key : parseCacheKey(key);
|
|
135
|
+
if (!keyString) return this.scope.prefix;
|
|
136
|
+
return `${this.scope.prefix}.${keyString}`;
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
//#endregion
|
|
141
|
+
export { TaggedScopedCache };
|
|
142
|
+
//# sourceMappingURL=tagged-scoped-cache.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tagged-scoped-cache.mjs","names":[],"sources":["../../../../../@warlock.js/cache/src/tagged-scoped-cache.ts"],"sourcesContent":["import type { ScopedCache } from \"./scoped-cache\";\nimport type {\n CacheKey,\n CacheSetOptions,\n CacheTtl,\n RememberOptions,\n TaggedScopedCacheContract,\n} from \"./types\";\nimport {\n injectTags,\n mergeTagSets,\n normalizeToOptions,\n normalizeToRememberOptions,\n parseCacheKey,\n} from \"./utils\";\n\n/**\n * One-shot tagged write handle on top of a {@link ScopedCache}.\n *\n * **Role.** Returned by `scope.tags([...])`. Adds a fixed list of tags to\n * every write produced through this handle, on top of any tags the parent\n * scope already contributes. Stateless except for the captured tag list.\n *\n * **Responsibility.**\n * - Owns: appending the handle's tags to writes, delegating tag-index\n * bookkeeping for `setNX` (which lacks an inline `tags` knob on the driver\n * contract), and computing the union for `invalidate()` calls.\n * - Does NOT own: storage, prefix-prepending (delegated to the scope),\n * default `ttl` (delegated to the scope), or any kind of long-lived state.\n *\n * Tags compose additively: scope tags + handle tags + per-call tags, all\n * unioned and deduped. The handle never replaces scope tags — `invalidate()`\n * always sees the full union.\n *\n * @example\n * // Inside application code — scope provides the per-user tag automatically:\n * const feed = cache.namespace(`feed.${userId}`, { tags: [`user.${userId}`] });\n *\n * await feed.tags([\"unread\"]).set(\"messages.1\", message);\n * // → tagged with [user.<id>, unread]\n *\n * await feed.tags([\"unread\"]).invalidate();\n * // → wipes everything tagged with user.<id> OR unread.\n */\nexport class TaggedScopedCache implements TaggedScopedCacheContract {\n /**\n * The {@link ScopedCache} this handle delegates to. Held by reference so\n * scope-default changes (none today, but the option is preserved for the\n * future) are visible without rebuilding the handle.\n */\n protected readonly scope: ScopedCache;\n\n /**\n * Tags this handle contributes to every write. Cloned at the call site so\n * later mutation of the input array doesn't leak in.\n */\n protected readonly handleTags: string[];\n\n /**\n * Build a tagged handle. Constructed via `scope.tags([...])` — users never\n * call this directly.\n */\n public constructor(scope: ScopedCache, handleTags: string[]) {\n this.scope = scope;\n this.handleTags = [...handleTags];\n }\n\n /**\n * Write the scoped key with the handle's tags appended to whatever the\n * caller passed. Scope-level tags are added on top by the scope itself.\n */\n public set(\n key: CacheKey,\n value: any,\n ttlOrOptions?: CacheTtl | CacheSetOptions,\n ): Promise<any> {\n const options = injectTags(normalizeToOptions(ttlOrOptions), this.handleTags);\n\n return this.scope.set(key, value, options);\n }\n\n /**\n * Read the scoped key. Tags don't affect reads — pass-through.\n */\n public get<T = any>(key: CacheKey): Promise<T | null> {\n return this.scope.get<T>(key);\n }\n\n /**\n * Check presence of the scoped key.\n */\n public has(key: CacheKey): Promise<boolean> {\n return this.scope.has(key);\n }\n\n /**\n * Remove the scoped key. The tag-index entry will eventually be cleaned up\n * by `invalidate()`; we don't proactively rewrite it here for cost reasons.\n */\n public remove(key: CacheKey): Promise<void> {\n return this.scope.remove(key);\n }\n\n /**\n * Read-and-remove the scoped key.\n */\n public pull<T = any>(key: CacheKey): Promise<T | null> {\n return this.scope.pull<T>(key);\n }\n\n /**\n * Permanent write with handle tags applied. Bypasses both the scope's and\n * the caller's TTL (forever means forever) — only tags get injected.\n */\n public forever<T = any>(key: CacheKey, value: T): Promise<T> {\n return this.scope.set(key, value, {\n ttl: Infinity,\n tags: this.handleTags,\n }) as Promise<T>;\n }\n\n /**\n * Atomic create-or-skip with the handle's tags applied on success. The\n * driver contract has no inline `tags` knob on `setNX`, so we register the\n * tag relationship manually after a successful write.\n */\n public async setNX(key: CacheKey, value: any, ttl?: number): Promise<boolean> {\n const wasSet = await this.scope.setNX(key, value, ttl);\n\n if (!wasSet) {\n return false;\n }\n\n const allTags = mergeTagSets(this.scope.defaults.tags, this.handleTags);\n\n if (!allTags || allTags.length === 0) {\n return true;\n }\n\n const scopedKey = this.buildScopedKey(key);\n const parsedKey = this.scope.source.parseKey(scopedKey);\n const tagged = this.scope.source.tags(allTags) as unknown as {\n storeTagRelationship: (parsed: string) => Promise<void>;\n };\n\n await tagged.storeTagRelationship(parsedKey);\n\n return true;\n }\n\n /**\n * Read-or-compute with handle tags appended on the cache-miss write.\n */\n public remember<T = any>(\n key: CacheKey,\n ttlOrOptions: CacheTtl | RememberOptions,\n callback: () => Promise<T>,\n ): Promise<T> {\n const options = injectTags(\n normalizeToRememberOptions(ttlOrOptions),\n this.handleTags,\n );\n\n return this.scope.remember<T>(key, options, callback);\n }\n\n /**\n * Atomic counter increment on the scoped key. Tags aren't applied to\n * subsequent increments — they're attached at first-write time.\n */\n public increment(key: CacheKey, value?: number): Promise<number> {\n return this.scope.increment(key, value);\n }\n\n /**\n * Atomic counter decrement on the scoped key. See {@link increment}.\n */\n public decrement(key: CacheKey, value?: number): Promise<number> {\n return this.scope.decrement(key, value);\n }\n\n /**\n * Wipe every entry tagged with the union of (scope tags + handle tags).\n * Tags are global across the package, so this reaches outside the scope's\n * prefix when scope tags are also used elsewhere.\n */\n public async invalidate(): Promise<void> {\n const allTags = mergeTagSets(this.scope.defaults.tags, this.handleTags);\n\n if (!allTags || allTags.length === 0) {\n return;\n }\n\n await this.scope.source.tags(allTags).invalidate();\n }\n\n /**\n * Compute the source-side key the same way `ScopedCache.scopedKey` does —\n * needed for `setNX`, where we have to register the tag relationship by\n * hand because the driver contract doesn't accept inline tags there.\n */\n protected buildScopedKey(key: CacheKey): string {\n const keyString = typeof key === \"string\" ? key : parseCacheKey(key);\n\n if (!keyString) {\n return this.scope.prefix;\n }\n\n return `${this.scope.prefix}.${keyString}`;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4CA,IAAa,oBAAb,MAAoE;;;;;CAkBlE,AAAO,YAAY,OAAoB,YAAsB;EAC3D,KAAK,QAAQ;EACb,KAAK,aAAa,CAAC,GAAG,UAAU;CAClC;;;;;CAMA,AAAO,IACL,KACA,OACA,cACc;EACd,MAAM,UAAU,WAAW,mBAAmB,YAAY,GAAG,KAAK,UAAU;EAE5E,OAAO,KAAK,MAAM,IAAI,KAAK,OAAO,OAAO;CAC3C;;;;CAKA,AAAO,IAAa,KAAkC;EACpD,OAAO,KAAK,MAAM,IAAO,GAAG;CAC9B;;;;CAKA,AAAO,IAAI,KAAiC;EAC1C,OAAO,KAAK,MAAM,IAAI,GAAG;CAC3B;;;;;CAMA,AAAO,OAAO,KAA8B;EAC1C,OAAO,KAAK,MAAM,OAAO,GAAG;CAC9B;;;;CAKA,AAAO,KAAc,KAAkC;EACrD,OAAO,KAAK,MAAM,KAAQ,GAAG;CAC/B;;;;;CAMA,AAAO,QAAiB,KAAe,OAAsB;EAC3D,OAAO,KAAK,MAAM,IAAI,KAAK,OAAO;GAChC,KAAK;GACL,MAAM,KAAK;EACb,CAAC;CACH;;;;;;CAOA,MAAa,MAAM,KAAe,OAAY,KAAgC;EAG5E,IAAI,CAAC,MAFgB,KAAK,MAAM,MAAM,KAAK,OAAO,GAAG,GAGnD,OAAO;EAGT,MAAM,UAAU,aAAa,KAAK,MAAM,SAAS,MAAM,KAAK,UAAU;EAEtE,IAAI,CAAC,WAAW,QAAQ,WAAW,GACjC,OAAO;EAGT,MAAM,YAAY,KAAK,eAAe,GAAG;EACzC,MAAM,YAAY,KAAK,MAAM,OAAO,SAAS,SAAS;EAKtD,MAJe,KAAK,MAAM,OAAO,KAAK,OAI3B,EAAE,qBAAqB,SAAS;EAE3C,OAAO;CACT;;;;CAKA,AAAO,SACL,KACA,cACA,UACY;EACZ,MAAM,UAAU,WACd,2BAA2B,YAAY,GACvC,KAAK,UACP;EAEA,OAAO,KAAK,MAAM,SAAY,KAAK,SAAS,QAAQ;CACtD;;;;;CAMA,AAAO,UAAU,KAAe,OAAiC;EAC/D,OAAO,KAAK,MAAM,UAAU,KAAK,KAAK;CACxC;;;;CAKA,AAAO,UAAU,KAAe,OAAiC;EAC/D,OAAO,KAAK,MAAM,UAAU,KAAK,KAAK;CACxC;;;;;;CAOA,MAAa,aAA4B;EACvC,MAAM,UAAU,aAAa,KAAK,MAAM,SAAS,MAAM,KAAK,UAAU;EAEtE,IAAI,CAAC,WAAW,QAAQ,WAAW,GACjC;EAGF,MAAM,KAAK,MAAM,OAAO,KAAK,OAAO,EAAE,WAAW;CACnD;;;;;;CAOA,AAAU,eAAe,KAAuB;EAC9C,MAAM,YAAY,OAAO,QAAQ,WAAW,MAAM,cAAc,GAAG;EAEnE,IAAI,CAAC,WACH,OAAO,KAAK,MAAM;EAGpB,OAAO,GAAG,KAAK,MAAM,OAAO,GAAG;CACjC;AACF"}
|