@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.
Files changed (213) hide show
  1. package/README.md +85 -0
  2. package/cjs/index.cjs +4088 -0
  3. package/cjs/index.cjs.map +1 -0
  4. package/esm/cache-manager.d.mts +314 -0
  5. package/esm/cache-manager.d.mts.map +1 -0
  6. package/esm/cache-manager.mjs +486 -0
  7. package/esm/cache-manager.mjs.map +1 -0
  8. package/esm/cached/auto-key.d.mts +25 -0
  9. package/esm/cached/auto-key.d.mts.map +1 -0
  10. package/esm/cached/auto-key.mjs +55 -0
  11. package/esm/cached/auto-key.mjs.map +1 -0
  12. package/esm/cached/cached.d.mts +54 -0
  13. package/esm/cached/cached.d.mts.map +1 -0
  14. package/esm/cached/cached.mjs +25 -0
  15. package/esm/cached/cached.mjs.map +1 -0
  16. package/esm/cached/index.d.mts +3 -0
  17. package/esm/cached/index.mjs +5 -0
  18. package/esm/cached/normalize-args.d.mts +51 -0
  19. package/esm/cached/normalize-args.d.mts.map +1 -0
  20. package/esm/cached/normalize-args.mjs +26 -0
  21. package/esm/cached/normalize-args.mjs.map +1 -0
  22. package/esm/drivers/base-cache-driver.d.mts +322 -0
  23. package/esm/drivers/base-cache-driver.d.mts.map +1 -0
  24. package/esm/drivers/base-cache-driver.mjs +522 -0
  25. package/esm/drivers/base-cache-driver.mjs.map +1 -0
  26. package/esm/drivers/file-cache-driver.d.mts +68 -0
  27. package/esm/drivers/file-cache-driver.d.mts.map +1 -0
  28. package/esm/drivers/file-cache-driver.mjs +174 -0
  29. package/esm/drivers/file-cache-driver.mjs.map +1 -0
  30. package/esm/drivers/index.d.mts +9 -0
  31. package/esm/drivers/index.mjs +11 -0
  32. package/esm/drivers/lru-memory-cache-driver.d.mts +136 -0
  33. package/esm/drivers/lru-memory-cache-driver.d.mts.map +1 -0
  34. package/esm/drivers/lru-memory-cache-driver.mjs +317 -0
  35. package/esm/drivers/lru-memory-cache-driver.mjs.map +1 -0
  36. package/esm/drivers/memory-cache-driver.d.mts +112 -0
  37. package/esm/drivers/memory-cache-driver.d.mts.map +1 -0
  38. package/esm/drivers/memory-cache-driver.mjs +241 -0
  39. package/esm/drivers/memory-cache-driver.mjs.map +1 -0
  40. package/esm/drivers/memory-extended-cache-driver.d.mts +17 -0
  41. package/esm/drivers/memory-extended-cache-driver.d.mts.map +1 -0
  42. package/esm/drivers/memory-extended-cache-driver.mjs +34 -0
  43. package/esm/drivers/memory-extended-cache-driver.mjs.map +1 -0
  44. package/esm/drivers/mock-cache-driver.d.mts +137 -0
  45. package/esm/drivers/mock-cache-driver.d.mts.map +1 -0
  46. package/esm/drivers/mock-cache-driver.mjs +226 -0
  47. package/esm/drivers/mock-cache-driver.mjs.map +1 -0
  48. package/esm/drivers/null-cache-driver.d.mts +69 -0
  49. package/esm/drivers/null-cache-driver.d.mts.map +1 -0
  50. package/esm/drivers/null-cache-driver.mjs +92 -0
  51. package/esm/drivers/null-cache-driver.mjs.map +1 -0
  52. package/esm/drivers/pg-cache-driver.d.mts +148 -0
  53. package/esm/drivers/pg-cache-driver.d.mts.map +1 -0
  54. package/esm/drivers/pg-cache-driver.mjs +437 -0
  55. package/esm/drivers/pg-cache-driver.mjs.map +1 -0
  56. package/esm/drivers/redis-cache-driver.d.mts +86 -0
  57. package/esm/drivers/redis-cache-driver.d.mts.map +1 -0
  58. package/esm/drivers/redis-cache-driver.mjs +312 -0
  59. package/esm/drivers/redis-cache-driver.mjs.map +1 -0
  60. package/esm/index.d.mts +21 -0
  61. package/esm/index.mjs +24 -0
  62. package/esm/list/index.d.mts +1 -0
  63. package/esm/list/memory-cache-list.d.mts +77 -0
  64. package/esm/list/memory-cache-list.d.mts.map +1 -0
  65. package/esm/list/memory-cache-list.mjs +119 -0
  66. package/esm/list/memory-cache-list.mjs.map +1 -0
  67. package/esm/metrics.d.mts +118 -0
  68. package/esm/metrics.d.mts.map +1 -0
  69. package/esm/metrics.mjs +197 -0
  70. package/esm/metrics.mjs.map +1 -0
  71. package/esm/scoped-cache.d.mts +205 -0
  72. package/esm/scoped-cache.d.mts.map +1 -0
  73. package/esm/scoped-cache.mjs +274 -0
  74. package/esm/scoped-cache.mjs.map +1 -0
  75. package/esm/tagged-cache.d.mts +89 -0
  76. package/esm/tagged-cache.d.mts.map +1 -0
  77. package/esm/tagged-cache.mjs +147 -0
  78. package/esm/tagged-cache.mjs.map +1 -0
  79. package/esm/tagged-scoped-cache.d.mts +111 -0
  80. package/esm/tagged-scoped-cache.d.mts.map +1 -0
  81. package/esm/tagged-scoped-cache.mjs +142 -0
  82. package/esm/tagged-scoped-cache.mjs.map +1 -0
  83. package/esm/types.d.mts +1067 -0
  84. package/esm/types.d.mts.map +1 -0
  85. package/esm/types.mjs +62 -0
  86. package/esm/types.mjs.map +1 -0
  87. package/esm/utils.d.mts +161 -0
  88. package/esm/utils.d.mts.map +1 -0
  89. package/esm/utils.mjs +222 -0
  90. package/esm/utils.mjs.map +1 -0
  91. package/llms-full.txt +2071 -0
  92. package/llms.txt +28 -0
  93. package/package.json +53 -39
  94. package/skills/apply-cache-patterns/SKILL.md +97 -0
  95. package/skills/cache-basics/SKILL.md +121 -0
  96. package/skills/configure-pg-cache/SKILL.md +115 -0
  97. package/skills/configure-set-options/SKILL.md +96 -0
  98. package/skills/handle-cache-errors/SKILL.md +91 -0
  99. package/skills/observe-cache/SKILL.md +103 -0
  100. package/skills/overview/SKILL.md +69 -0
  101. package/skills/pick-cache-driver/SKILL.md +115 -0
  102. package/skills/test-cache-code/SKILL.md +219 -0
  103. package/skills/use-cache-atomic/SKILL.md +67 -0
  104. package/skills/use-cache-bulk/SKILL.md +57 -0
  105. package/skills/use-cache-list/SKILL.md +85 -0
  106. package/skills/use-cache-lock/SKILL.md +104 -0
  107. package/skills/use-cache-namespace/SKILL.md +88 -0
  108. package/skills/use-cache-similarity/SKILL.md +94 -0
  109. package/skills/use-cache-tags/SKILL.md +85 -0
  110. package/skills/use-cache-update-merge/SKILL.md +84 -0
  111. package/skills/use-cache-utils/SKILL.md +89 -0
  112. package/skills/use-cached-hof/SKILL.md +102 -0
  113. package/skills/use-swr/SKILL.md +104 -0
  114. package/cjs/cache-manager.d.ts +0 -163
  115. package/cjs/cache-manager.d.ts.map +0 -1
  116. package/cjs/cache-manager.js +0 -322
  117. package/cjs/cache-manager.js.map +0 -1
  118. package/cjs/drivers/base-cache-driver.d.ts +0 -152
  119. package/cjs/drivers/base-cache-driver.d.ts.map +0 -1
  120. package/cjs/drivers/base-cache-driver.js +0 -321
  121. package/cjs/drivers/base-cache-driver.js.map +0 -1
  122. package/cjs/drivers/file-cache-driver.d.ts +0 -45
  123. package/cjs/drivers/file-cache-driver.d.ts.map +0 -1
  124. package/cjs/drivers/file-cache-driver.js +0 -133
  125. package/cjs/drivers/file-cache-driver.js.map +0 -1
  126. package/cjs/drivers/index.d.ts +0 -8
  127. package/cjs/drivers/index.d.ts.map +0 -1
  128. package/cjs/drivers/lru-memory-cache-driver.d.ts +0 -98
  129. package/cjs/drivers/lru-memory-cache-driver.d.ts.map +0 -1
  130. package/cjs/drivers/lru-memory-cache-driver.js +0 -252
  131. package/cjs/drivers/lru-memory-cache-driver.js.map +0 -1
  132. package/cjs/drivers/memory-cache-driver.d.ts +0 -82
  133. package/cjs/drivers/memory-cache-driver.d.ts.map +0 -1
  134. package/cjs/drivers/memory-cache-driver.js +0 -218
  135. package/cjs/drivers/memory-cache-driver.js.map +0 -1
  136. package/cjs/drivers/memory-extended-cache-driver.d.ts +0 -13
  137. package/cjs/drivers/memory-extended-cache-driver.d.ts.map +0 -1
  138. package/cjs/drivers/memory-extended-cache-driver.js +0 -25
  139. package/cjs/drivers/memory-extended-cache-driver.js.map +0 -1
  140. package/cjs/drivers/null-cache-driver.d.ts +0 -58
  141. package/cjs/drivers/null-cache-driver.d.ts.map +0 -1
  142. package/cjs/drivers/null-cache-driver.js +0 -84
  143. package/cjs/drivers/null-cache-driver.js.map +0 -1
  144. package/cjs/drivers/redis-cache-driver.d.ts +0 -57
  145. package/cjs/drivers/redis-cache-driver.d.ts.map +0 -1
  146. package/cjs/drivers/redis-cache-driver.js +0 -263
  147. package/cjs/drivers/redis-cache-driver.js.map +0 -1
  148. package/cjs/index.d.ts +0 -6
  149. package/cjs/index.d.ts.map +0 -1
  150. package/cjs/index.js +0 -1
  151. package/cjs/index.js.map +0 -1
  152. package/cjs/tagged-cache.d.ts +0 -77
  153. package/cjs/tagged-cache.d.ts.map +0 -1
  154. package/cjs/tagged-cache.js +0 -160
  155. package/cjs/tagged-cache.js.map +0 -1
  156. package/cjs/types.d.ts +0 -391
  157. package/cjs/types.d.ts.map +0 -1
  158. package/cjs/types.js +0 -36
  159. package/cjs/types.js.map +0 -1
  160. package/cjs/utils.d.ts +0 -50
  161. package/cjs/utils.d.ts.map +0 -1
  162. package/cjs/utils.js +0 -55
  163. package/cjs/utils.js.map +0 -1
  164. package/esm/cache-manager.d.ts +0 -163
  165. package/esm/cache-manager.d.ts.map +0 -1
  166. package/esm/cache-manager.js +0 -322
  167. package/esm/cache-manager.js.map +0 -1
  168. package/esm/drivers/base-cache-driver.d.ts +0 -152
  169. package/esm/drivers/base-cache-driver.d.ts.map +0 -1
  170. package/esm/drivers/base-cache-driver.js +0 -321
  171. package/esm/drivers/base-cache-driver.js.map +0 -1
  172. package/esm/drivers/file-cache-driver.d.ts +0 -45
  173. package/esm/drivers/file-cache-driver.d.ts.map +0 -1
  174. package/esm/drivers/file-cache-driver.js +0 -133
  175. package/esm/drivers/file-cache-driver.js.map +0 -1
  176. package/esm/drivers/index.d.ts +0 -8
  177. package/esm/drivers/index.d.ts.map +0 -1
  178. package/esm/drivers/lru-memory-cache-driver.d.ts +0 -98
  179. package/esm/drivers/lru-memory-cache-driver.d.ts.map +0 -1
  180. package/esm/drivers/lru-memory-cache-driver.js +0 -252
  181. package/esm/drivers/lru-memory-cache-driver.js.map +0 -1
  182. package/esm/drivers/memory-cache-driver.d.ts +0 -82
  183. package/esm/drivers/memory-cache-driver.d.ts.map +0 -1
  184. package/esm/drivers/memory-cache-driver.js +0 -218
  185. package/esm/drivers/memory-cache-driver.js.map +0 -1
  186. package/esm/drivers/memory-extended-cache-driver.d.ts +0 -13
  187. package/esm/drivers/memory-extended-cache-driver.d.ts.map +0 -1
  188. package/esm/drivers/memory-extended-cache-driver.js +0 -25
  189. package/esm/drivers/memory-extended-cache-driver.js.map +0 -1
  190. package/esm/drivers/null-cache-driver.d.ts +0 -58
  191. package/esm/drivers/null-cache-driver.d.ts.map +0 -1
  192. package/esm/drivers/null-cache-driver.js +0 -84
  193. package/esm/drivers/null-cache-driver.js.map +0 -1
  194. package/esm/drivers/redis-cache-driver.d.ts +0 -57
  195. package/esm/drivers/redis-cache-driver.d.ts.map +0 -1
  196. package/esm/drivers/redis-cache-driver.js +0 -263
  197. package/esm/drivers/redis-cache-driver.js.map +0 -1
  198. package/esm/index.d.ts +0 -6
  199. package/esm/index.d.ts.map +0 -1
  200. package/esm/index.js +0 -1
  201. package/esm/index.js.map +0 -1
  202. package/esm/tagged-cache.d.ts +0 -77
  203. package/esm/tagged-cache.d.ts.map +0 -1
  204. package/esm/tagged-cache.js +0 -160
  205. package/esm/tagged-cache.js.map +0 -1
  206. package/esm/types.d.ts +0 -391
  207. package/esm/types.d.ts.map +0 -1
  208. package/esm/types.js +0 -36
  209. package/esm/types.js.map +0 -1
  210. package/esm/utils.d.ts +0 -50
  211. package/esm/utils.d.ts.map +0 -1
  212. package/esm/utils.js +0 -55
  213. 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"}