@burdenoff/be-sdk 2026.510.79

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 (220) hide show
  1. package/README.md +173 -0
  2. package/configs/eslint/index.js +492 -0
  3. package/configs/tsconfig/tsconfig.json +53 -0
  4. package/dist/EventQueueFactory-6NMSGECR.js +8 -0
  5. package/dist/EventQueueFactory-6NMSGECR.js.map +1 -0
  6. package/dist/auth/index.d.ts +66 -0
  7. package/dist/auth/index.js +8 -0
  8. package/dist/auth/index.js.map +1 -0
  9. package/dist/cache/index.d.ts +2 -0
  10. package/dist/cache/index.js +6 -0
  11. package/dist/cache/index.js.map +1 -0
  12. package/dist/captcha/index.d.ts +1 -0
  13. package/dist/captcha/index.js +4 -0
  14. package/dist/captcha/index.js.map +1 -0
  15. package/dist/chunk-2HANKZZM.js +245 -0
  16. package/dist/chunk-2HANKZZM.js.map +1 -0
  17. package/dist/chunk-2SD5L2F2.js +816 -0
  18. package/dist/chunk-2SD5L2F2.js.map +1 -0
  19. package/dist/chunk-3O2RQOPV.js +1068 -0
  20. package/dist/chunk-3O2RQOPV.js.map +1 -0
  21. package/dist/chunk-4B43DZIS.js +560 -0
  22. package/dist/chunk-4B43DZIS.js.map +1 -0
  23. package/dist/chunk-4XAEES25.js +2444 -0
  24. package/dist/chunk-4XAEES25.js.map +1 -0
  25. package/dist/chunk-4XGGWW36.js +1405 -0
  26. package/dist/chunk-4XGGWW36.js.map +1 -0
  27. package/dist/chunk-5LXDPGDH.js +245 -0
  28. package/dist/chunk-5LXDPGDH.js.map +1 -0
  29. package/dist/chunk-AI7L22ZJ.js +472 -0
  30. package/dist/chunk-AI7L22ZJ.js.map +1 -0
  31. package/dist/chunk-CBZNP6RF.js +286 -0
  32. package/dist/chunk-CBZNP6RF.js.map +1 -0
  33. package/dist/chunk-ELLX3K54.js +613 -0
  34. package/dist/chunk-ELLX3K54.js.map +1 -0
  35. package/dist/chunk-F5XEAGHQ.js +1875 -0
  36. package/dist/chunk-F5XEAGHQ.js.map +1 -0
  37. package/dist/chunk-FNZEQOJY.js +628 -0
  38. package/dist/chunk-FNZEQOJY.js.map +1 -0
  39. package/dist/chunk-GTEMQXCA.js +516 -0
  40. package/dist/chunk-GTEMQXCA.js.map +1 -0
  41. package/dist/chunk-HIWTWIGQ.js +226 -0
  42. package/dist/chunk-HIWTWIGQ.js.map +1 -0
  43. package/dist/chunk-IYE2NTRX.js +764 -0
  44. package/dist/chunk-IYE2NTRX.js.map +1 -0
  45. package/dist/chunk-J26YGR2U.js +1484 -0
  46. package/dist/chunk-J26YGR2U.js.map +1 -0
  47. package/dist/chunk-JG2FTZPI.js +509 -0
  48. package/dist/chunk-JG2FTZPI.js.map +1 -0
  49. package/dist/chunk-JVBTNSPG.js +1551 -0
  50. package/dist/chunk-JVBTNSPG.js.map +1 -0
  51. package/dist/chunk-L7ZMN2FJ.js +12 -0
  52. package/dist/chunk-L7ZMN2FJ.js.map +1 -0
  53. package/dist/chunk-M5IMU3US.js +473 -0
  54. package/dist/chunk-M5IMU3US.js.map +1 -0
  55. package/dist/chunk-MLW2HPS5.js +1267 -0
  56. package/dist/chunk-MLW2HPS5.js.map +1 -0
  57. package/dist/chunk-MNCGUYLJ.js +269 -0
  58. package/dist/chunk-MNCGUYLJ.js.map +1 -0
  59. package/dist/chunk-MOCUBSTW.js +373 -0
  60. package/dist/chunk-MOCUBSTW.js.map +1 -0
  61. package/dist/chunk-NGMEI42S.js +103 -0
  62. package/dist/chunk-NGMEI42S.js.map +1 -0
  63. package/dist/chunk-NUB5GQTU.js +270 -0
  64. package/dist/chunk-NUB5GQTU.js.map +1 -0
  65. package/dist/chunk-OVSYMNCI.js +145 -0
  66. package/dist/chunk-OVSYMNCI.js.map +1 -0
  67. package/dist/chunk-QLVKMWFA.js +94 -0
  68. package/dist/chunk-QLVKMWFA.js.map +1 -0
  69. package/dist/chunk-SAG6ZYWQ.js +89 -0
  70. package/dist/chunk-SAG6ZYWQ.js.map +1 -0
  71. package/dist/chunk-SAK2JCA7.js +198 -0
  72. package/dist/chunk-SAK2JCA7.js.map +1 -0
  73. package/dist/chunk-SBS4S2PJ.js +100 -0
  74. package/dist/chunk-SBS4S2PJ.js.map +1 -0
  75. package/dist/chunk-SNEOLWXT.js +148 -0
  76. package/dist/chunk-SNEOLWXT.js.map +1 -0
  77. package/dist/chunk-TKBD2ONF.js +564 -0
  78. package/dist/chunk-TKBD2ONF.js.map +1 -0
  79. package/dist/chunk-UBXFIIAW.js +127 -0
  80. package/dist/chunk-UBXFIIAW.js.map +1 -0
  81. package/dist/chunk-VI4VSNTI.js +57 -0
  82. package/dist/chunk-VI4VSNTI.js.map +1 -0
  83. package/dist/chunk-VWCN5PMD.js +268 -0
  84. package/dist/chunk-VWCN5PMD.js.map +1 -0
  85. package/dist/chunk-XC2YD6CF.js +913 -0
  86. package/dist/chunk-XC2YD6CF.js.map +1 -0
  87. package/dist/chunk-XE4OXN2W.js +10 -0
  88. package/dist/chunk-XE4OXN2W.js.map +1 -0
  89. package/dist/chunk-YMZEUTD2.js +110 -0
  90. package/dist/chunk-YMZEUTD2.js.map +1 -0
  91. package/dist/chunk-Z4IRLBWO.js +758 -0
  92. package/dist/chunk-Z4IRLBWO.js.map +1 -0
  93. package/dist/client/internal-client.d.ts +7 -0
  94. package/dist/client/internal-client.js +5 -0
  95. package/dist/client/internal-client.js.map +1 -0
  96. package/dist/client-CSjIrYKS.d.ts +77 -0
  97. package/dist/config-UKE2E3BW.js +4 -0
  98. package/dist/config-UKE2E3BW.js.map +1 -0
  99. package/dist/crypto/index.d.ts +1 -0
  100. package/dist/crypto/index.js +4 -0
  101. package/dist/crypto/index.js.map +1 -0
  102. package/dist/database/index.d.ts +117 -0
  103. package/dist/database/index.js +7 -0
  104. package/dist/database/index.js.map +1 -0
  105. package/dist/dataloader/index.d.ts +1 -0
  106. package/dist/dataloader/index.js +4 -0
  107. package/dist/dataloader/index.js.map +1 -0
  108. package/dist/esm-K6H7EIWK.js +1450 -0
  109. package/dist/esm-K6H7EIWK.js.map +1 -0
  110. package/dist/event-queue/index.d.ts +6 -0
  111. package/dist/event-queue/index.js +10 -0
  112. package/dist/event-queue/index.js.map +1 -0
  113. package/dist/export/index.d.ts +2 -0
  114. package/dist/export/index.js +9 -0
  115. package/dist/export/index.js.map +1 -0
  116. package/dist/feature-flags/index.d.ts +1 -0
  117. package/dist/feature-flags/index.js +4 -0
  118. package/dist/feature-flags/index.js.map +1 -0
  119. package/dist/gateway/index.d.ts +4 -0
  120. package/dist/gateway/index.js +8 -0
  121. package/dist/gateway/index.js.map +1 -0
  122. package/dist/gateway/security/index.d.ts +2 -0
  123. package/dist/gateway/security/index.js +5 -0
  124. package/dist/gateway/security/index.js.map +1 -0
  125. package/dist/graph/index.d.ts +9 -0
  126. package/dist/graph/index.js +13 -0
  127. package/dist/graph/index.js.map +1 -0
  128. package/dist/graph-emitter-Bk0FqD53.d.ts +47 -0
  129. package/dist/graphql/index.d.ts +2 -0
  130. package/dist/graphql/index.js +7 -0
  131. package/dist/graphql/index.js.map +1 -0
  132. package/dist/graphql/services/index.d.ts +24 -0
  133. package/dist/graphql/services/index.js +5 -0
  134. package/dist/graphql/services/index.js.map +1 -0
  135. package/dist/graphql-BAVrUgBF.d.ts +22 -0
  136. package/dist/i18n/index.d.ts +2 -0
  137. package/dist/i18n/index.js +5 -0
  138. package/dist/i18n/index.js.map +1 -0
  139. package/dist/i18n-DA6IPnYy.d.ts +101 -0
  140. package/dist/index-4gKQKZ2B.d.ts +71 -0
  141. package/dist/index-B18rrFru.d.ts +42 -0
  142. package/dist/index-B70b5mYS.d.ts +33 -0
  143. package/dist/index-BMq3lFjj.d.ts +247 -0
  144. package/dist/index-BODgvRtL.d.ts +316 -0
  145. package/dist/index-BS2idbnr.d.ts +874 -0
  146. package/dist/index-BV3G48cH.d.ts +124 -0
  147. package/dist/index-CHbVw5M7.d.ts +73 -0
  148. package/dist/index-Cq_xNjcv.d.ts +602 -0
  149. package/dist/index-CrQgidpx.d.ts +77 -0
  150. package/dist/index-CyVEg86m.d.ts +309 -0
  151. package/dist/index-DOcBnmMe.d.ts +166 -0
  152. package/dist/index-DSOpj8DI.d.ts +17 -0
  153. package/dist/index-DW9q22GH.d.ts +75 -0
  154. package/dist/index-DlFDFyWD.d.ts +55 -0
  155. package/dist/index-DoK0bjhH.d.ts +607 -0
  156. package/dist/index-Dtf6FBaD.d.ts +199 -0
  157. package/dist/index-KVWGHMbS.d.ts +415 -0
  158. package/dist/index-PaojfSdd.d.ts +71 -0
  159. package/dist/index-RU_M5c74.d.ts +163 -0
  160. package/dist/index-UhkH2eaB.d.ts +192 -0
  161. package/dist/index-e_18DzAg.d.ts +18 -0
  162. package/dist/index-jOuh_TKn.d.ts +59 -0
  163. package/dist/index.d.ts +584 -0
  164. package/dist/index.js +2626 -0
  165. package/dist/index.js.map +1 -0
  166. package/dist/init/index.d.ts +2 -0
  167. package/dist/init/index.js +12 -0
  168. package/dist/init/index.js.map +1 -0
  169. package/dist/instrumentation/index.d.ts +3 -0
  170. package/dist/instrumentation/index.js +5 -0
  171. package/dist/instrumentation/index.js.map +1 -0
  172. package/dist/layer/index.d.ts +2 -0
  173. package/dist/layer/index.js +6 -0
  174. package/dist/layer/index.js.map +1 -0
  175. package/dist/layer-DDip18KY.d.ts +67 -0
  176. package/dist/logger/index.d.ts +2 -0
  177. package/dist/logger/index.js +4 -0
  178. package/dist/logger/index.js.map +1 -0
  179. package/dist/middleware/index.d.ts +3 -0
  180. package/dist/middleware/index.js +5 -0
  181. package/dist/middleware/index.js.map +1 -0
  182. package/dist/notifications/index.d.ts +4 -0
  183. package/dist/notifications/index.js +7 -0
  184. package/dist/notifications/index.js.map +1 -0
  185. package/dist/observability/index.d.ts +3 -0
  186. package/dist/observability/index.js +5 -0
  187. package/dist/observability/index.js.map +1 -0
  188. package/dist/pino-logger-RYLGXPHZ.js +5 -0
  189. package/dist/pino-logger-RYLGXPHZ.js.map +1 -0
  190. package/dist/prisma/generator/index.d.ts +1 -0
  191. package/dist/prisma/generator/index.js +228 -0
  192. package/dist/prisma/generator/index.js.map +1 -0
  193. package/dist/prisma/index.d.ts +5 -0
  194. package/dist/prisma/index.js +12 -0
  195. package/dist/prisma/index.js.map +1 -0
  196. package/dist/prisma-extension-krXnYnrN.d.ts +30 -0
  197. package/dist/rbac/index.d.ts +116 -0
  198. package/dist/rbac/index.js +7 -0
  199. package/dist/rbac/index.js.map +1 -0
  200. package/dist/sdk-THO3IWEE.js +136 -0
  201. package/dist/sdk-THO3IWEE.js.map +1 -0
  202. package/dist/server/index.d.ts +359 -0
  203. package/dist/server/index.js +884 -0
  204. package/dist/server/index.js.map +1 -0
  205. package/dist/telemetry/index.d.ts +83 -0
  206. package/dist/telemetry/index.js +209 -0
  207. package/dist/telemetry/index.js.map +1 -0
  208. package/dist/temporal/index.d.ts +148 -0
  209. package/dist/temporal/index.js +6 -0
  210. package/dist/temporal/index.js.map +1 -0
  211. package/dist/tracker/index.d.ts +5 -0
  212. package/dist/tracker/index.js +9 -0
  213. package/dist/tracker/index.js.map +1 -0
  214. package/dist/types-Bo2wkjSP.d.ts +35 -0
  215. package/dist/utils/index.d.ts +1 -0
  216. package/dist/utils/index.js +4 -0
  217. package/dist/utils/index.js.map +1 -0
  218. package/dist/workspace-guard-LHBNK4TG.js +5 -0
  219. package/dist/workspace-guard-LHBNK4TG.js.map +1 -0
  220. package/package.json +241 -0
@@ -0,0 +1,1405 @@
1
+ import { DEFAULT_LAYER_RESOURCES } from './chunk-NGMEI42S.js';
2
+ import { logger } from './chunk-CBZNP6RF.js';
3
+ import { __export, __name } from './chunk-XE4OXN2W.js';
4
+
5
+ // src/cache/index.ts
6
+ var cache_exports = {};
7
+ __export(cache_exports, {
8
+ CacheFactory: () => CacheFactory,
9
+ CacheProviderType: () => CacheProviderType,
10
+ MemoryCacheProvider: () => MemoryCacheProvider,
11
+ ValkeyGlideProvider: () => ValkeyGlideProvider,
12
+ closeAllCaches: () => closeAllCaches,
13
+ createCache: () => createCache,
14
+ getCache: () => getCache,
15
+ getValkeyClient: () => getValkeyClient
16
+ });
17
+
18
+ // src/cache/implementations/memory/MemoryCacheProvider.ts
19
+ var MemoryCacheProvider = class {
20
+ static {
21
+ __name(this, "MemoryCacheProvider");
22
+ }
23
+ cache = /* @__PURE__ */ new Map();
24
+ namespace;
25
+ defaultTTL;
26
+ maxSize;
27
+ enableLogging;
28
+ connected = false;
29
+ // Statistics
30
+ stats = {
31
+ hits: 0,
32
+ misses: 0,
33
+ sets: 0,
34
+ deletes: 0,
35
+ evictions: 0
36
+ };
37
+ constructor(config, namespace = "default") {
38
+ this.namespace = namespace;
39
+ this.defaultTTL = config.defaultTTL || 300;
40
+ this.maxSize = config.maxSize || 1e3;
41
+ this.enableLogging = config.enableLogging ?? false;
42
+ this.startCleanupInterval();
43
+ }
44
+ /**
45
+ * Connect (no-op for memory cache)
46
+ */
47
+ async connect() {
48
+ await Promise.resolve();
49
+ this.connected = true;
50
+ if (this.enableLogging) {
51
+ logger.info(`[MemoryCacheProvider:${this.namespace}] Connected (in-memory)`);
52
+ }
53
+ }
54
+ /**
55
+ * Disconnect (cleanup)
56
+ */
57
+ async disconnect() {
58
+ await Promise.resolve();
59
+ this.connected = false;
60
+ this.cache.clear();
61
+ if (this.enableLogging) {
62
+ logger.info(`[MemoryCacheProvider:${this.namespace}] Disconnected`);
63
+ }
64
+ }
65
+ /**
66
+ * Check if connected
67
+ */
68
+ isConnected() {
69
+ return this.connected;
70
+ }
71
+ /**
72
+ * Health check
73
+ */
74
+ async healthCheck() {
75
+ await Promise.resolve();
76
+ return {
77
+ status: "healthy",
78
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
79
+ connected: this.connected,
80
+ latencyMs: 0,
81
+ details: {
82
+ provider: "memory",
83
+ cacheSize: this.cache.size,
84
+ maxSize: this.maxSize
85
+ }
86
+ };
87
+ }
88
+ /**
89
+ * Get statistics
90
+ */
91
+ async getStatistics() {
92
+ await Promise.resolve();
93
+ const totalOperations = this.stats.hits + this.stats.misses;
94
+ const hitRate = totalOperations > 0 ? this.stats.hits / totalOperations : 0;
95
+ const memoryUsed = this.cache.size * 500;
96
+ return {
97
+ hits: this.stats.hits,
98
+ misses: this.stats.misses,
99
+ hitRate,
100
+ keyCount: this.cache.size,
101
+ memoryUsed,
102
+ totalOperations,
103
+ details: {
104
+ sets: this.stats.sets,
105
+ deletes: this.stats.deletes,
106
+ evictions: this.stats.evictions,
107
+ maxSize: this.maxSize
108
+ }
109
+ };
110
+ }
111
+ /**
112
+ * Build cache key with namespace
113
+ */
114
+ buildKey(key) {
115
+ return `${this.namespace}:${key}`;
116
+ }
117
+ /**
118
+ * Check if entry is expired
119
+ */
120
+ isExpired(expiresAt) {
121
+ return Date.now() > expiresAt;
122
+ }
123
+ /**
124
+ * Evict LRU entry if cache is full
125
+ */
126
+ evictIfNeeded() {
127
+ if (this.cache.size >= this.maxSize) {
128
+ const firstKey = this.cache.keys().next().value;
129
+ if (firstKey) {
130
+ this.cache.delete(firstKey);
131
+ this.stats.evictions++;
132
+ }
133
+ }
134
+ }
135
+ /**
136
+ * Cleanup expired entries
137
+ */
138
+ cleanup() {
139
+ let cleaned = 0;
140
+ for (const [key, value] of this.cache.entries()) {
141
+ if (this.isExpired(value.expiresAt)) {
142
+ this.cache.delete(key);
143
+ cleaned++;
144
+ }
145
+ }
146
+ if (cleaned > 0 && this.enableLogging) {
147
+ logger.debug(`[MemoryCacheProvider:${this.namespace}] Cleaned up ${cleaned} expired entries`);
148
+ }
149
+ }
150
+ /**
151
+ * Start cleanup interval
152
+ */
153
+ startCleanupInterval() {
154
+ setInterval(() => this.cleanup(), 6e4);
155
+ }
156
+ /**
157
+ * Get value from cache
158
+ */
159
+ async get(key, _options) {
160
+ await Promise.resolve();
161
+ const cacheKey = this.buildKey(key);
162
+ const cached = this.cache.get(cacheKey);
163
+ if (!cached) {
164
+ this.stats.misses++;
165
+ if (this.enableLogging) {
166
+ logger.debug(`[MemoryCacheProvider:${this.namespace}] Cache miss`, {
167
+ key
168
+ });
169
+ }
170
+ return null;
171
+ }
172
+ if (this.isExpired(cached.expiresAt)) {
173
+ this.cache.delete(cacheKey);
174
+ this.stats.misses++;
175
+ if (this.enableLogging) {
176
+ logger.debug(`[MemoryCacheProvider:${this.namespace}] Cache miss (expired)`, {
177
+ key
178
+ });
179
+ }
180
+ return null;
181
+ }
182
+ this.stats.hits++;
183
+ if (this.enableLogging) {
184
+ logger.debug(`[MemoryCacheProvider:${this.namespace}] Cache hit`, {
185
+ key
186
+ });
187
+ }
188
+ this.cache.delete(cacheKey);
189
+ this.cache.set(cacheKey, cached);
190
+ return cached.entry.data;
191
+ }
192
+ /**
193
+ * Set value in cache
194
+ */
195
+ async set(key, value, options) {
196
+ await Promise.resolve();
197
+ const cacheKey = this.buildKey(key);
198
+ const ttlSeconds = options?.ttl || this.defaultTTL;
199
+ this.evictIfNeeded();
200
+ const entry = {
201
+ data: value,
202
+ timestamp: Date.now(),
203
+ ttl: ttlSeconds,
204
+ metadata: options?.metadata
205
+ };
206
+ this.cache.set(cacheKey, {
207
+ entry,
208
+ expiresAt: Date.now() + ttlSeconds * 1e3
209
+ });
210
+ this.stats.sets++;
211
+ if (this.enableLogging) {
212
+ logger.debug(`[MemoryCacheProvider:${this.namespace}] Cache set`, {
213
+ key,
214
+ ttl: ttlSeconds
215
+ });
216
+ }
217
+ return true;
218
+ }
219
+ /**
220
+ * Delete value from cache
221
+ */
222
+ async delete(key) {
223
+ await Promise.resolve();
224
+ const cacheKey = this.buildKey(key);
225
+ const deleted = this.cache.delete(cacheKey);
226
+ if (deleted) {
227
+ this.stats.deletes++;
228
+ if (this.enableLogging) {
229
+ logger.debug(`[MemoryCacheProvider:${this.namespace}] Cache delete`, {
230
+ key
231
+ });
232
+ }
233
+ }
234
+ return deleted;
235
+ }
236
+ /**
237
+ * Check if key exists
238
+ */
239
+ async has(key) {
240
+ await Promise.resolve();
241
+ const cacheKey = this.buildKey(key);
242
+ const cached = this.cache.get(cacheKey);
243
+ if (!cached) {
244
+ return false;
245
+ }
246
+ if (this.isExpired(cached.expiresAt)) {
247
+ this.cache.delete(cacheKey);
248
+ return false;
249
+ }
250
+ return true;
251
+ }
252
+ /**
253
+ * Get TTL for key
254
+ */
255
+ async ttl(key) {
256
+ await Promise.resolve();
257
+ const cacheKey = this.buildKey(key);
258
+ const cached = this.cache.get(cacheKey);
259
+ if (!cached) {
260
+ return -2;
261
+ }
262
+ const remaining = Math.floor((cached.expiresAt - Date.now()) / 1e3);
263
+ if (remaining <= 0) {
264
+ this.cache.delete(cacheKey);
265
+ return -2;
266
+ }
267
+ return remaining;
268
+ }
269
+ /**
270
+ * Update TTL for key
271
+ */
272
+ async expire(key, ttl) {
273
+ await Promise.resolve();
274
+ const cacheKey = this.buildKey(key);
275
+ const cached = this.cache.get(cacheKey);
276
+ if (!cached) {
277
+ return false;
278
+ }
279
+ cached.expiresAt = Date.now() + ttl * 1e3;
280
+ cached.entry.ttl = ttl;
281
+ return true;
282
+ }
283
+ /**
284
+ * Get multiple values (batch operation)
285
+ */
286
+ async mget(keys, _options) {
287
+ const result = /* @__PURE__ */ new Map();
288
+ for (const key of keys) {
289
+ const value = await this.get(key);
290
+ if (value !== null) {
291
+ result.set(key, value);
292
+ }
293
+ }
294
+ return result;
295
+ }
296
+ /**
297
+ * Set multiple values (batch operation)
298
+ */
299
+ async mset(entries, options) {
300
+ for (const [key, value] of entries) {
301
+ await this.set(key, value, options);
302
+ }
303
+ return true;
304
+ }
305
+ /**
306
+ * Delete multiple keys (batch operation)
307
+ */
308
+ async mdel(keys) {
309
+ let deleted = 0;
310
+ for (const key of keys) {
311
+ const result = await this.delete(key);
312
+ if (result) {
313
+ deleted++;
314
+ }
315
+ }
316
+ return deleted;
317
+ }
318
+ /**
319
+ * Match key against pattern (supports * wildcard)
320
+ */
321
+ matchPattern(key, pattern) {
322
+ if (!pattern.includes("*")) {
323
+ return key === pattern;
324
+ }
325
+ const parts = pattern.split("*");
326
+ let position = 0;
327
+ for (let i = 0; i < parts.length; i++) {
328
+ const part = parts[i];
329
+ if (!part || part === "") continue;
330
+ const index = key.indexOf(part, position);
331
+ if (index === -1) return false;
332
+ if (i === 0 && index !== 0) return false;
333
+ position = index + part.length;
334
+ }
335
+ const lastPart = parts[parts.length - 1];
336
+ return !lastPart || lastPart === "" || key.endsWith(lastPart);
337
+ }
338
+ /**
339
+ * Clear keys by pattern
340
+ */
341
+ async clearPattern(pattern) {
342
+ await Promise.resolve();
343
+ const searchPattern = this.buildKey(pattern);
344
+ let deleted = 0;
345
+ for (const key of this.cache.keys()) {
346
+ if (this.matchPattern(key, searchPattern)) {
347
+ this.cache.delete(key);
348
+ deleted++;
349
+ }
350
+ }
351
+ if (this.enableLogging) {
352
+ logger.debug(`[MemoryCacheProvider:${this.namespace}] Pattern cleared`, {
353
+ pattern,
354
+ deleted
355
+ });
356
+ }
357
+ return deleted;
358
+ }
359
+ /**
360
+ * Get keys by pattern
361
+ */
362
+ async keys(options) {
363
+ await Promise.resolve();
364
+ const searchPattern = this.buildKey(options.pattern);
365
+ const matchedKeys = [];
366
+ const prefix = `${this.namespace}:`;
367
+ for (const key of this.cache.keys()) {
368
+ if (this.matchPattern(key, searchPattern)) {
369
+ matchedKeys.push(key.replace(prefix, ""));
370
+ }
371
+ }
372
+ const limitedKeys = options.limit ? matchedKeys.slice(0, options.limit) : matchedKeys;
373
+ return {
374
+ keys: limitedKeys,
375
+ nextCursor: null,
376
+ totalCount: matchedKeys.length
377
+ };
378
+ }
379
+ /**
380
+ * Clear all keys in namespace
381
+ */
382
+ async clear() {
383
+ await Promise.resolve();
384
+ const prefix = `${this.namespace}:`;
385
+ let cleared = 0;
386
+ for (const key of Array.from(this.cache.keys())) {
387
+ if (key.startsWith(prefix)) {
388
+ this.cache.delete(key);
389
+ cleared++;
390
+ }
391
+ }
392
+ if (this.enableLogging) {
393
+ logger.info(`[MemoryCacheProvider:${this.namespace}] Cleared ${cleared} keys`);
394
+ }
395
+ return true;
396
+ }
397
+ /**
398
+ * Increment numeric value
399
+ */
400
+ async increment(key, amount = 1) {
401
+ const current = await this.get(key);
402
+ const newValue = (current || 0) + amount;
403
+ await this.set(key, newValue);
404
+ return newValue;
405
+ }
406
+ /**
407
+ * Decrement numeric value
408
+ */
409
+ async decrement(key, amount = 1) {
410
+ const current = await this.get(key);
411
+ const newValue = (current || 0) - amount;
412
+ await this.set(key, newValue);
413
+ return newValue;
414
+ }
415
+ /**
416
+ * Get or set value
417
+ */
418
+ async getOrSet(key, fetcher, options) {
419
+ const cached = await this.get(key, options);
420
+ if (cached !== null) {
421
+ return cached;
422
+ }
423
+ const value = await fetcher();
424
+ await this.set(key, value, options);
425
+ return value;
426
+ }
427
+ /**
428
+ * Invalidate by tags
429
+ */
430
+ async invalidateTags(tags) {
431
+ let totalDeleted = 0;
432
+ for (const tag of tags) {
433
+ const pattern = `*:tag:${tag}:*`;
434
+ const deleted = await this.clearPattern(pattern);
435
+ totalDeleted += deleted;
436
+ }
437
+ return totalDeleted;
438
+ }
439
+ };
440
+
441
+ // src/cache/implementations/valkey/ValkeyGlideProvider.ts
442
+ var ValkeyGlideProvider = class {
443
+ static {
444
+ __name(this, "ValkeyGlideProvider");
445
+ }
446
+ client = null;
447
+ clusterScanCursor = null;
448
+ clientIsCluster = false;
449
+ connected = false;
450
+ config;
451
+ namespace;
452
+ defaultTTL;
453
+ enableLogging;
454
+ // Statistics
455
+ stats = {
456
+ hits: 0,
457
+ misses: 0,
458
+ sets: 0,
459
+ deletes: 0,
460
+ errors: 0
461
+ };
462
+ constructor(config, namespace = "default") {
463
+ this.config = config;
464
+ this.namespace = namespace;
465
+ this.defaultTTL = config.defaultTTL || 300;
466
+ this.enableLogging = config.enableLogging ?? process.env["NODE_ENV"] === "development";
467
+ }
468
+ async serverReportsCluster(client) {
469
+ try {
470
+ const info = await client.info("cluster");
471
+ return /(?:^|\n)cluster_enabled:1(?:\r?\n|$)/.test(info);
472
+ } catch {
473
+ return false;
474
+ }
475
+ }
476
+ async scanClusterKeys(pattern) {
477
+ if (!this.client || !this.clientIsCluster || !this.clusterScanCursor) {
478
+ return [];
479
+ }
480
+ const clusterClient = this.client;
481
+ let cursor = new this.clusterScanCursor();
482
+ const keys = [];
483
+ do {
484
+ const [nextCursor, batch] = await clusterClient.scan(cursor, {
485
+ match: pattern,
486
+ count: 1e3
487
+ });
488
+ keys.push(...batch);
489
+ cursor = nextCursor;
490
+ } while (!cursor.isFinished());
491
+ return keys;
492
+ }
493
+ async getKeys(pattern) {
494
+ if (!this.client) {
495
+ throw new Error("Not connected");
496
+ }
497
+ if (this.clientIsCluster) {
498
+ return this.scanClusterKeys(pattern);
499
+ }
500
+ if (!this.client.keys) {
501
+ throw new Error("KEYS command is not available on this Valkey client");
502
+ }
503
+ return this.client.keys(pattern);
504
+ }
505
+ /**
506
+ * Connect to Valkey server using @valkey/valkey-glide
507
+ */
508
+ async connect() {
509
+ if (this.connected && this.client) {
510
+ return;
511
+ }
512
+ try {
513
+ const glideModule = await import('@valkey/valkey-glide');
514
+ const GlideClient = glideModule.GlideClient || glideModule.default;
515
+ const GlideClusterClient = glideModule.GlideClusterClient;
516
+ this.clusterScanCursor = glideModule.ClusterScanCursor ?? null;
517
+ if (!GlideClient) {
518
+ throw new Error("Valkey GLIDE standalone client is unavailable");
519
+ }
520
+ let host = this.config.host || "localhost";
521
+ let port = this.config.port || 6379;
522
+ let password = this.config.password;
523
+ let username = this.config.username;
524
+ if (this.config.url) {
525
+ const url = new URL(this.config.url.replace("valkey://", "redis://"));
526
+ host = url.hostname;
527
+ port = parseInt(url.port || "6379", 10);
528
+ if (!password && url.password) {
529
+ try {
530
+ password = decodeURIComponent(url.password);
531
+ } catch {
532
+ password = url.password;
533
+ }
534
+ }
535
+ if (!username && url.username) {
536
+ try {
537
+ username = decodeURIComponent(url.username);
538
+ } catch {
539
+ username = url.username;
540
+ }
541
+ }
542
+ }
543
+ const addresses = this.config.clusterNodes?.length ? this.config.clusterNodes : [
544
+ {
545
+ host,
546
+ port
547
+ }
548
+ ];
549
+ const baseClientConfig = {
550
+ addresses,
551
+ useTLS: this.config.useTLS,
552
+ credentials: password || username ? {
553
+ password,
554
+ username
555
+ } : void 0,
556
+ clientName: this.config.name || `valkey-glide-${this.namespace}`,
557
+ databaseId: this.config.db,
558
+ connectionTimeout: this.config.connectionTimeout,
559
+ readFrom: "primary"
560
+ };
561
+ if (this.config.cluster === true) {
562
+ if (!GlideClusterClient) {
563
+ throw new Error("Valkey GLIDE cluster client is unavailable");
564
+ }
565
+ this.client = await GlideClusterClient.createClient({
566
+ ...baseClientConfig,
567
+ periodicChecks: {
568
+ duration_in_sec: 30
569
+ },
570
+ advancedConfiguration: {
571
+ refreshTopologyFromInitialNodes: true
572
+ }
573
+ });
574
+ this.clientIsCluster = true;
575
+ } else {
576
+ const standaloneClient = await GlideClient.createClient(baseClientConfig);
577
+ if (this.config.cluster !== false && await this.serverReportsCluster(standaloneClient)) {
578
+ if (!GlideClusterClient) {
579
+ throw new Error("Valkey server is clustered but GLIDE cluster client is unavailable");
580
+ }
581
+ await standaloneClient.close();
582
+ this.client = await GlideClusterClient.createClient({
583
+ ...baseClientConfig,
584
+ periodicChecks: {
585
+ duration_in_sec: 30
586
+ },
587
+ advancedConfiguration: {
588
+ refreshTopologyFromInitialNodes: true
589
+ }
590
+ });
591
+ this.clientIsCluster = true;
592
+ } else {
593
+ this.client = standaloneClient;
594
+ this.clientIsCluster = false;
595
+ }
596
+ }
597
+ this.connected = true;
598
+ if (this.enableLogging) {
599
+ logger.info(`[ValkeyGlideProvider:${this.namespace}] Connected to Valkey`, {
600
+ host,
601
+ port,
602
+ cluster: this.clientIsCluster
603
+ });
604
+ }
605
+ } catch (error) {
606
+ this.stats.errors++;
607
+ logger.error(`[ValkeyGlideProvider:${this.namespace}] Failed to connect:`, error);
608
+ throw error;
609
+ }
610
+ }
611
+ /**
612
+ * Disconnect from Valkey server
613
+ */
614
+ async disconnect() {
615
+ if (this.client) {
616
+ await this.client.close();
617
+ this.client = null;
618
+ this.clientIsCluster = false;
619
+ this.connected = false;
620
+ if (this.enableLogging) {
621
+ logger.info(`[ValkeyGlideProvider:${this.namespace}] Disconnected`);
622
+ }
623
+ }
624
+ }
625
+ /**
626
+ * Check if connected
627
+ */
628
+ isConnected() {
629
+ return this.connected && this.client !== null;
630
+ }
631
+ /**
632
+ * Health check
633
+ */
634
+ async healthCheck() {
635
+ const startTime = Date.now();
636
+ try {
637
+ if (!this.client) {
638
+ return {
639
+ status: "unhealthy",
640
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
641
+ connected: false,
642
+ error: "Not connected"
643
+ };
644
+ }
645
+ const result = await this.client.ping();
646
+ const latencyMs = Date.now() - startTime;
647
+ if (result === "PONG") {
648
+ return {
649
+ status: "healthy",
650
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
651
+ connected: true,
652
+ latencyMs
653
+ };
654
+ }
655
+ return {
656
+ status: "unhealthy",
657
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
658
+ connected: false,
659
+ error: "Unexpected ping response"
660
+ };
661
+ } catch (error) {
662
+ return {
663
+ status: "unhealthy",
664
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
665
+ connected: false,
666
+ error: error instanceof Error ? error.message : "Unknown error",
667
+ latencyMs: Date.now() - startTime
668
+ };
669
+ }
670
+ }
671
+ /**
672
+ * Get statistics
673
+ */
674
+ async getStatistics() {
675
+ const totalOperations = this.stats.hits + this.stats.misses;
676
+ const hitRate = totalOperations > 0 ? this.stats.hits / totalOperations : 0;
677
+ try {
678
+ if (!this.client) {
679
+ throw new Error("Not connected");
680
+ }
681
+ const info = await this.client.info("memory");
682
+ const memoryRegex = /used_memory:(\d+)/;
683
+ const memoryMatch = memoryRegex.exec(info);
684
+ const memoryUsed = memoryMatch && memoryMatch[1] ? parseInt(memoryMatch[1], 10) : void 0;
685
+ const keyCount = await this.client.dbsize();
686
+ return {
687
+ hits: this.stats.hits,
688
+ misses: this.stats.misses,
689
+ hitRate,
690
+ keyCount,
691
+ memoryUsed,
692
+ totalOperations,
693
+ details: {
694
+ sets: this.stats.sets,
695
+ deletes: this.stats.deletes,
696
+ errors: this.stats.errors
697
+ }
698
+ };
699
+ } catch (error) {
700
+ logger.error(`[ValkeyGlideProvider:${this.namespace}] Failed to get statistics:`, error);
701
+ return {
702
+ hits: this.stats.hits,
703
+ misses: this.stats.misses,
704
+ hitRate,
705
+ totalOperations,
706
+ details: {
707
+ sets: this.stats.sets,
708
+ deletes: this.stats.deletes,
709
+ errors: this.stats.errors
710
+ }
711
+ };
712
+ }
713
+ }
714
+ /**
715
+ * Build cache key with namespace
716
+ */
717
+ buildKey(key) {
718
+ return `${this.namespace}:${key}`;
719
+ }
720
+ /**
721
+ * Get value from cache
722
+ */
723
+ async get(key, _options) {
724
+ try {
725
+ if (!this.client) {
726
+ throw new Error("Not connected");
727
+ }
728
+ const cacheKey = this.buildKey(key);
729
+ const value = await this.client.get(cacheKey);
730
+ if (value === null) {
731
+ this.stats.misses++;
732
+ if (this.enableLogging) {
733
+ logger.debug(`[ValkeyGlideProvider:${this.namespace}] Cache miss`, {
734
+ key
735
+ });
736
+ }
737
+ return null;
738
+ }
739
+ this.stats.hits++;
740
+ if (this.enableLogging) {
741
+ logger.debug(`[ValkeyGlideProvider:${this.namespace}] Cache hit`, {
742
+ key
743
+ });
744
+ }
745
+ const entry = JSON.parse(value);
746
+ return entry.data;
747
+ } catch (error) {
748
+ this.stats.errors++;
749
+ logger.error(`[ValkeyGlideProvider:${this.namespace}] Error getting cache key:`, error);
750
+ return null;
751
+ }
752
+ }
753
+ /**
754
+ * Set value in cache
755
+ */
756
+ async set(key, value, options) {
757
+ try {
758
+ if (!this.client) {
759
+ throw new Error("Not connected");
760
+ }
761
+ const cacheKey = this.buildKey(key);
762
+ const ttlSeconds = options?.ttl || this.defaultTTL;
763
+ const entry = {
764
+ data: value,
765
+ timestamp: Date.now(),
766
+ ttl: ttlSeconds,
767
+ metadata: options?.metadata
768
+ };
769
+ await this.client.set(cacheKey, JSON.stringify(entry), {
770
+ expiry: {
771
+ type: "EX",
772
+ count: ttlSeconds
773
+ }
774
+ });
775
+ this.stats.sets++;
776
+ if (this.enableLogging) {
777
+ logger.debug(`[ValkeyGlideProvider:${this.namespace}] Cache set`, {
778
+ key,
779
+ ttl: ttlSeconds
780
+ });
781
+ }
782
+ return true;
783
+ } catch (error) {
784
+ this.stats.errors++;
785
+ logger.error(`[ValkeyGlideProvider:${this.namespace}] Error setting cache key:`, error);
786
+ return false;
787
+ }
788
+ }
789
+ /**
790
+ * Delete value from cache
791
+ */
792
+ async delete(key) {
793
+ try {
794
+ if (!this.client) {
795
+ throw new Error("Not connected");
796
+ }
797
+ const cacheKey = this.buildKey(key);
798
+ const result = await this.client.del([
799
+ cacheKey
800
+ ]);
801
+ this.stats.deletes++;
802
+ if (this.enableLogging) {
803
+ logger.debug(`[ValkeyGlideProvider:${this.namespace}] Cache delete`, {
804
+ key,
805
+ deleted: result > 0
806
+ });
807
+ }
808
+ return result > 0;
809
+ } catch (error) {
810
+ this.stats.errors++;
811
+ logger.error(`[ValkeyGlideProvider:${this.namespace}] Error deleting cache key:`, error);
812
+ return false;
813
+ }
814
+ }
815
+ /**
816
+ * Check if key exists
817
+ */
818
+ async has(key) {
819
+ try {
820
+ if (!this.client) {
821
+ throw new Error("Not connected");
822
+ }
823
+ const cacheKey = this.buildKey(key);
824
+ const exists = await this.client.exists([
825
+ cacheKey
826
+ ]);
827
+ return exists === 1;
828
+ } catch (error) {
829
+ this.stats.errors++;
830
+ logger.error(`[ValkeyGlideProvider:${this.namespace}] Error checking cache key:`, error);
831
+ return false;
832
+ }
833
+ }
834
+ /**
835
+ * Get TTL for key
836
+ */
837
+ async ttl(key) {
838
+ try {
839
+ if (!this.client) {
840
+ throw new Error("Not connected");
841
+ }
842
+ const cacheKey = this.buildKey(key);
843
+ return await this.client.ttl(cacheKey);
844
+ } catch (error) {
845
+ this.stats.errors++;
846
+ logger.error(`[ValkeyGlideProvider:${this.namespace}] Error getting TTL:`, error);
847
+ return -2;
848
+ }
849
+ }
850
+ /**
851
+ * Update TTL for key
852
+ */
853
+ async expire(key, ttl) {
854
+ try {
855
+ if (!this.client) {
856
+ throw new Error("Not connected");
857
+ }
858
+ const cacheKey = this.buildKey(key);
859
+ return await this.client.expire(cacheKey, ttl);
860
+ } catch (error) {
861
+ this.stats.errors++;
862
+ logger.error(`[ValkeyGlideProvider:${this.namespace}] Error setting expiration:`, error);
863
+ return false;
864
+ }
865
+ }
866
+ /**
867
+ * Get multiple values (batch operation)
868
+ */
869
+ async mget(keys, _options) {
870
+ const result = /* @__PURE__ */ new Map();
871
+ if (keys.length === 0) {
872
+ return result;
873
+ }
874
+ try {
875
+ if (!this.client) {
876
+ throw new Error("Not connected");
877
+ }
878
+ const cacheKeys = keys.map((key) => this.buildKey(key));
879
+ const values = await this.client.mget(cacheKeys);
880
+ for (let i = 0; i < keys.length; i++) {
881
+ const key = keys[i];
882
+ if (!key) continue;
883
+ if (values[i] !== null) {
884
+ const entry = JSON.parse(values[i]);
885
+ result.set(key, entry.data);
886
+ this.stats.hits++;
887
+ } else {
888
+ this.stats.misses++;
889
+ }
890
+ }
891
+ if (this.enableLogging) {
892
+ logger.debug(`[ValkeyGlideProvider:${this.namespace}] Batch get`, {
893
+ requested: keys.length,
894
+ found: result.size
895
+ });
896
+ }
897
+ return result;
898
+ } catch (error) {
899
+ this.stats.errors++;
900
+ logger.error(`[ValkeyGlideProvider:${this.namespace}] Error in batch get:`, error);
901
+ return result;
902
+ }
903
+ }
904
+ /**
905
+ * Set multiple values (batch operation)
906
+ */
907
+ async mset(entries, options) {
908
+ if (entries.size === 0) {
909
+ return true;
910
+ }
911
+ try {
912
+ if (!this.client) {
913
+ throw new Error("Not connected");
914
+ }
915
+ const ttlSeconds = options?.ttl || this.defaultTTL;
916
+ const keyValuePairs = {};
917
+ for (const [key, value] of entries) {
918
+ const cacheKey = this.buildKey(key);
919
+ const entry = {
920
+ data: value,
921
+ timestamp: Date.now(),
922
+ ttl: ttlSeconds,
923
+ metadata: options?.metadata
924
+ };
925
+ keyValuePairs[cacheKey] = JSON.stringify(entry);
926
+ }
927
+ await this.client.mset(keyValuePairs);
928
+ for (const cacheKey of Object.keys(keyValuePairs)) {
929
+ await this.client.expire(cacheKey, ttlSeconds);
930
+ }
931
+ this.stats.sets += entries.size;
932
+ if (this.enableLogging) {
933
+ logger.debug(`[ValkeyGlideProvider:${this.namespace}] Batch set`, {
934
+ count: entries.size,
935
+ ttl: ttlSeconds
936
+ });
937
+ }
938
+ return true;
939
+ } catch (error) {
940
+ this.stats.errors++;
941
+ logger.error(`[ValkeyGlideProvider:${this.namespace}] Error in batch set:`, error);
942
+ return false;
943
+ }
944
+ }
945
+ /**
946
+ * Delete multiple keys (batch operation)
947
+ */
948
+ async mdel(keys) {
949
+ if (keys.length === 0) {
950
+ return 0;
951
+ }
952
+ try {
953
+ if (!this.client) {
954
+ throw new Error("Not connected");
955
+ }
956
+ const cacheKeys = keys.map((key) => this.buildKey(key));
957
+ const result = await this.client.del(cacheKeys);
958
+ this.stats.deletes += result;
959
+ if (this.enableLogging) {
960
+ logger.debug(`[ValkeyGlideProvider:${this.namespace}] Batch delete`, {
961
+ requested: keys.length,
962
+ deleted: result
963
+ });
964
+ }
965
+ return result;
966
+ } catch (error) {
967
+ this.stats.errors++;
968
+ logger.error(`[ValkeyGlideProvider:${this.namespace}] Error in batch delete:`, error);
969
+ return 0;
970
+ }
971
+ }
972
+ /**
973
+ * Clear keys by pattern
974
+ */
975
+ async clearPattern(pattern) {
976
+ try {
977
+ if (!this.client) {
978
+ throw new Error("Not connected");
979
+ }
980
+ const searchPattern = this.buildKey(pattern);
981
+ const keys = await this.getKeys(searchPattern);
982
+ if (keys.length === 0) {
983
+ return 0;
984
+ }
985
+ const result = await this.client.del(keys);
986
+ if (this.enableLogging) {
987
+ logger.debug(`[ValkeyGlideProvider:${this.namespace}] Pattern cleared`, {
988
+ pattern,
989
+ deleted: result
990
+ });
991
+ }
992
+ return result;
993
+ } catch (error) {
994
+ this.stats.errors++;
995
+ logger.error(`[ValkeyGlideProvider:${this.namespace}] Error clearing pattern:`, error);
996
+ return 0;
997
+ }
998
+ }
999
+ /**
1000
+ * Get keys by pattern
1001
+ */
1002
+ async keys(options) {
1003
+ try {
1004
+ if (!this.client) {
1005
+ throw new Error("Not connected");
1006
+ }
1007
+ const searchPattern = this.buildKey(options.pattern);
1008
+ const keys = await this.getKeys(searchPattern);
1009
+ const prefix = `${this.namespace}:`;
1010
+ const cleanKeys = keys.map((key) => key.replace(prefix, ""));
1011
+ const limitedKeys = options.limit ? cleanKeys.slice(0, options.limit) : cleanKeys;
1012
+ return {
1013
+ keys: limitedKeys,
1014
+ nextCursor: null,
1015
+ totalCount: cleanKeys.length
1016
+ };
1017
+ } catch (error) {
1018
+ this.stats.errors++;
1019
+ logger.error(`[ValkeyGlideProvider:${this.namespace}] Error getting keys:`, error);
1020
+ return {
1021
+ keys: [],
1022
+ nextCursor: null,
1023
+ totalCount: 0
1024
+ };
1025
+ }
1026
+ }
1027
+ /**
1028
+ * Clear all keys in namespace
1029
+ */
1030
+ async clear() {
1031
+ try {
1032
+ if (!this.client) {
1033
+ throw new Error("Not connected");
1034
+ }
1035
+ const pattern = this.buildKey("*");
1036
+ const keys = await this.getKeys(pattern);
1037
+ if (keys.length > 0) {
1038
+ await this.client.del(keys);
1039
+ if (this.enableLogging) {
1040
+ logger.info(`[ValkeyGlideProvider:${this.namespace}] Cleared ${keys.length} keys`);
1041
+ }
1042
+ }
1043
+ return true;
1044
+ } catch (error) {
1045
+ this.stats.errors++;
1046
+ logger.error(`[ValkeyGlideProvider:${this.namespace}] Error clearing cache:`, error);
1047
+ return false;
1048
+ }
1049
+ }
1050
+ /**
1051
+ * Increment numeric value
1052
+ */
1053
+ async increment(key, amount = 1) {
1054
+ try {
1055
+ if (!this.client) {
1056
+ throw new Error("Not connected");
1057
+ }
1058
+ const cacheKey = this.buildKey(key);
1059
+ return await this.client.incrBy(cacheKey, amount);
1060
+ } catch (error) {
1061
+ this.stats.errors++;
1062
+ logger.error(`[ValkeyGlideProvider:${this.namespace}] Error incrementing:`, error);
1063
+ throw error;
1064
+ }
1065
+ }
1066
+ /**
1067
+ * Decrement numeric value
1068
+ */
1069
+ async decrement(key, amount = 1) {
1070
+ try {
1071
+ if (!this.client) {
1072
+ throw new Error("Not connected");
1073
+ }
1074
+ const cacheKey = this.buildKey(key);
1075
+ return await this.client.decrBy(cacheKey, amount);
1076
+ } catch (error) {
1077
+ this.stats.errors++;
1078
+ logger.error(`[ValkeyGlideProvider:${this.namespace}] Error decrementing:`, error);
1079
+ throw error;
1080
+ }
1081
+ }
1082
+ /**
1083
+ * Get or set value
1084
+ */
1085
+ async getOrSet(key, fetcher, options) {
1086
+ const cached = await this.get(key, options);
1087
+ if (cached !== null) {
1088
+ return cached;
1089
+ }
1090
+ const value = await fetcher();
1091
+ await this.set(key, value, options);
1092
+ return value;
1093
+ }
1094
+ /**
1095
+ * Invalidate by tags
1096
+ */
1097
+ async invalidateTags(tags) {
1098
+ try {
1099
+ let totalDeleted = 0;
1100
+ for (const tag of tags) {
1101
+ const pattern = `*:tag:${tag}:*`;
1102
+ const deleted = await this.clearPattern(pattern);
1103
+ totalDeleted += deleted;
1104
+ }
1105
+ if (this.enableLogging) {
1106
+ logger.debug(`[ValkeyGlideProvider:${this.namespace}] Tags invalidated`, {
1107
+ tags,
1108
+ deleted: totalDeleted
1109
+ });
1110
+ }
1111
+ return totalDeleted;
1112
+ } catch (error) {
1113
+ this.stats.errors++;
1114
+ logger.error(`[ValkeyGlideProvider:${this.namespace}] Error invalidating tags:`, error);
1115
+ return 0;
1116
+ }
1117
+ }
1118
+ };
1119
+
1120
+ // src/cache/factory/CacheFactory.ts
1121
+ var CacheFactory = class _CacheFactory {
1122
+ static {
1123
+ __name(this, "CacheFactory");
1124
+ }
1125
+ static instances = /* @__PURE__ */ new Map();
1126
+ static parseBoolean(value) {
1127
+ if (value === void 0) return void 0;
1128
+ const normalized = value.trim().toLowerCase();
1129
+ if ([
1130
+ "1",
1131
+ "true",
1132
+ "yes",
1133
+ "on"
1134
+ ].includes(normalized)) return true;
1135
+ if ([
1136
+ "0",
1137
+ "false",
1138
+ "no",
1139
+ "off"
1140
+ ].includes(normalized)) return false;
1141
+ return void 0;
1142
+ }
1143
+ static parseClusterNodes(value) {
1144
+ if (!value) return void 0;
1145
+ const nodes = value.split(",").map((node) => node.trim()).filter(Boolean).map((node) => {
1146
+ const [host, rawPort] = node.replace(/^redis:\/\//, "").replace(/^valkey:\/\//, "").split(":");
1147
+ if (!host) return null;
1148
+ return {
1149
+ host,
1150
+ port: rawPort ? parseInt(rawPort, 10) : 6379
1151
+ };
1152
+ }).filter((node) => node !== null && Number.isFinite(node.port));
1153
+ return nodes.length > 0 ? nodes : void 0;
1154
+ }
1155
+ /**
1156
+ * Resolve port from multiple environment variable sources
1157
+ * @param layerPort - Layer-specific port environment variable value
1158
+ * @param genericPort - Generic port environment variable value
1159
+ * @param defaultPort - Default port if none provided
1160
+ * @returns Resolved port number
1161
+ */
1162
+ static resolvePort(layerPort, genericPort, defaultPort = 6379) {
1163
+ if (layerPort) {
1164
+ return parseInt(layerPort, 10);
1165
+ }
1166
+ if (genericPort) {
1167
+ return parseInt(genericPort, 10);
1168
+ }
1169
+ return defaultPort;
1170
+ }
1171
+ /**
1172
+ * Create a cache provider based on configuration
1173
+ */
1174
+ static createCache(config, namespace = "default") {
1175
+ logger.info("[CacheFactory] Creating cache provider", {
1176
+ type: config.type,
1177
+ namespace
1178
+ });
1179
+ switch (config.type) {
1180
+ case "valkey":
1181
+ case "redis":
1182
+ return new ValkeyGlideProvider({
1183
+ type: "valkey-glide",
1184
+ url: config.url,
1185
+ host: config.host,
1186
+ port: config.port,
1187
+ password: config.password,
1188
+ username: config.username,
1189
+ db: config.db,
1190
+ keyPrefix: config.keyPrefix,
1191
+ defaultTTL: config.defaultTTL,
1192
+ enableLogging: config.enableLogging,
1193
+ maxReconnectAttempts: config.maxReconnectAttempts,
1194
+ reconnectTimeWait: config.reconnectTimeWait,
1195
+ connectionTimeout: config.connectionTimeout,
1196
+ name: config.name,
1197
+ useTLS: config.tls?.enabled,
1198
+ cluster: config.cluster,
1199
+ clusterNodes: config.clusterNodes
1200
+ }, namespace);
1201
+ case "memory":
1202
+ return new MemoryCacheProvider(config, namespace);
1203
+ // Future implementations can be added here
1204
+ // case 'memcached':
1205
+ // return new MemcachedCacheProvider(config as MemcachedCacheConfig, namespace);
1206
+ default:
1207
+ throw new Error(`Unsupported cache provider type: ${config.type}`);
1208
+ }
1209
+ }
1210
+ /**
1211
+ * Create a cache from environment variables
1212
+ */
1213
+ static createCacheFromEnv(namespace = "default") {
1214
+ const envType = process.env["CACHE_PROVIDER_TYPE"];
1215
+ const type = envType === "memory" ? "memory" : "valkey";
1216
+ const config = type === "valkey" ? {
1217
+ type: "valkey",
1218
+ url: process.env["VALKEY_URL"],
1219
+ host: process.env["VALKEY_HOST"] || "localhost",
1220
+ port: process.env["VALKEY_PORT"] ? parseInt(process.env["VALKEY_PORT"], 10) : 6379,
1221
+ password: process.env["VALKEY_PASSWORD"],
1222
+ db: process.env["VALKEY_DB"] ? parseInt(process.env["VALKEY_DB"], 10) : 0,
1223
+ username: process.env["VALKEY_USERNAME"],
1224
+ keyPrefix: process.env["CACHE_KEY_PREFIX"] || "cache",
1225
+ defaultTTL: process.env["CACHE_DEFAULT_TTL"] ? parseInt(process.env["CACHE_DEFAULT_TTL"], 10) : 300,
1226
+ enableLogging: process.env["CACHE_ENABLE_LOGGING"] === "true",
1227
+ maxReconnectAttempts: process.env["VALKEY_MAX_RECONNECT_ATTEMPTS"] ? parseInt(process.env["VALKEY_MAX_RECONNECT_ATTEMPTS"], 10) : -1,
1228
+ reconnectTimeWait: process.env["VALKEY_RECONNECT_TIME_WAIT"] ? parseInt(process.env["VALKEY_RECONNECT_TIME_WAIT"], 10) : 2e3,
1229
+ connectionTimeout: process.env["VALKEY_CONNECTION_TIMEOUT"] ? parseInt(process.env["VALKEY_CONNECTION_TIMEOUT"], 10) : 1e4,
1230
+ name: process.env["CACHE_CLIENT_NAME"] || `cache-${namespace}`,
1231
+ cluster: _CacheFactory.parseBoolean(process.env["VALKEY_CLUSTER"] || process.env["CACHE_CLUSTER"]),
1232
+ clusterNodes: _CacheFactory.parseClusterNodes(process.env["VALKEY_CLUSTER_NODES"] || process.env["CACHE_CLUSTER_NODES"])
1233
+ } : {
1234
+ type: "memory",
1235
+ maxSize: process.env["CACHE_MAX_SIZE"] ? parseInt(process.env["CACHE_MAX_SIZE"], 10) : 1e3,
1236
+ defaultTTL: process.env["CACHE_DEFAULT_TTL"] ? parseInt(process.env["CACHE_DEFAULT_TTL"], 10) : 300,
1237
+ enableLogging: process.env["CACHE_ENABLE_LOGGING"] === "true",
1238
+ keyPrefix: process.env["CACHE_KEY_PREFIX"] || "cache"
1239
+ };
1240
+ return _CacheFactory.createCache(config, namespace);
1241
+ }
1242
+ /**
1243
+ * Get or create a singleton cache instance for a namespace
1244
+ */
1245
+ static getInstance(namespace = "default", config) {
1246
+ const instanceKey = `${config?.type || "default"}:${namespace}`;
1247
+ if (!_CacheFactory.instances.has(instanceKey)) {
1248
+ const cache = config ? _CacheFactory.createCache(config, namespace) : _CacheFactory.createCacheFromEnv(namespace);
1249
+ _CacheFactory.instances.set(instanceKey, cache);
1250
+ }
1251
+ return _CacheFactory.instances.get(instanceKey);
1252
+ }
1253
+ /**
1254
+ * Close a specific cache instance
1255
+ */
1256
+ static async closeInstance(namespace) {
1257
+ for (const [key, cache] of _CacheFactory.instances.entries()) {
1258
+ if (key.endsWith(`:${namespace}`)) {
1259
+ await cache.disconnect();
1260
+ _CacheFactory.instances.delete(key);
1261
+ logger.info("[CacheFactory] Closed cache instance", {
1262
+ namespace
1263
+ });
1264
+ }
1265
+ }
1266
+ }
1267
+ /**
1268
+ * Close all cache instances
1269
+ * Call this during application shutdown
1270
+ */
1271
+ static async closeAll() {
1272
+ const promises = Array.from(_CacheFactory.instances.values()).map(async (cache) => cache.disconnect());
1273
+ await Promise.all(promises);
1274
+ _CacheFactory.instances.clear();
1275
+ logger.info("[CacheFactory] All cache instances closed");
1276
+ }
1277
+ // ========================================================================
1278
+ // Layer-Aware Factory Methods
1279
+ // ========================================================================
1280
+ /**
1281
+ * Create a cache provider for a specific layer
1282
+ *
1283
+ * @param layer - Service layer ('wspace' or 'global')
1284
+ * @param serviceName - Service name for identification
1285
+ * @param namespace - Cache namespace (default: 'default')
1286
+ * @returns Cache provider configured for the layer
1287
+ *
1288
+ * @example
1289
+ * ```typescript
1290
+ * const cache = CacheFactory.createCacheForLayer('wspace', 'wspace-tags-svc');
1291
+ * await cache.connect();
1292
+ * await cache.set('key', { data: 'value' });
1293
+ * ```
1294
+ */
1295
+ static createCacheForLayer(layer, serviceName, namespace = "default") {
1296
+ const envPrefix = layer.toUpperCase();
1297
+ const defaults = DEFAULT_LAYER_RESOURCES[layer];
1298
+ const url = process.env[`${envPrefix}_VALKEY_URL`] || process.env["VALKEY_URL"] || defaults.valkeyUrl;
1299
+ const resolvedPort = _CacheFactory.resolvePort(process.env[`${envPrefix}_VALKEY_PORT`], process.env["VALKEY_PORT"]);
1300
+ const config = {
1301
+ type: "valkey",
1302
+ url,
1303
+ host: process.env[`${envPrefix}_VALKEY_HOST`] || process.env["VALKEY_HOST"] || "localhost",
1304
+ port: resolvedPort,
1305
+ password: process.env["VALKEY_PASSWORD"],
1306
+ db: process.env["VALKEY_DB"] ? parseInt(process.env["VALKEY_DB"], 10) : 0,
1307
+ username: process.env["VALKEY_USERNAME"],
1308
+ keyPrefix: process.env["CACHE_KEY_PREFIX"] || `${layer}-cache`,
1309
+ defaultTTL: process.env["CACHE_DEFAULT_TTL"] ? parseInt(process.env["CACHE_DEFAULT_TTL"], 10) : 300,
1310
+ enableLogging: process.env["CACHE_ENABLE_LOGGING"] === "true",
1311
+ maxReconnectAttempts: process.env["VALKEY_MAX_RECONNECT_ATTEMPTS"] ? parseInt(process.env["VALKEY_MAX_RECONNECT_ATTEMPTS"], 10) : -1,
1312
+ reconnectTimeWait: process.env["VALKEY_RECONNECT_TIME_WAIT"] ? parseInt(process.env["VALKEY_RECONNECT_TIME_WAIT"], 10) : 2e3,
1313
+ connectionTimeout: process.env["VALKEY_CONNECTION_TIMEOUT"] ? parseInt(process.env["VALKEY_CONNECTION_TIMEOUT"], 10) : 1e4,
1314
+ name: serviceName,
1315
+ cluster: _CacheFactory.parseBoolean(process.env[`${envPrefix}_VALKEY_CLUSTER`] || process.env["VALKEY_CLUSTER"] || process.env["CACHE_CLUSTER"]),
1316
+ clusterNodes: _CacheFactory.parseClusterNodes(process.env[`${envPrefix}_VALKEY_CLUSTER_NODES`] || process.env["VALKEY_CLUSTER_NODES"] || process.env["CACHE_CLUSTER_NODES"])
1317
+ };
1318
+ logger.info("[CacheFactory] Creating layer cache", {
1319
+ layer,
1320
+ serviceName,
1321
+ namespace,
1322
+ url: config.url
1323
+ });
1324
+ return _CacheFactory.createCache(config, namespace);
1325
+ }
1326
+ /**
1327
+ * Get or create a singleton cache instance for a layer
1328
+ *
1329
+ * @param layer - Service layer ('wspace' or 'global')
1330
+ * @param serviceName - Service name for identification
1331
+ * @param namespace - Cache namespace (default: 'default')
1332
+ * @returns Singleton cache provider for the layer
1333
+ */
1334
+ static getInstanceForLayer(layer, serviceName, namespace = "default") {
1335
+ const instanceKey = `${layer}:${serviceName}:${namespace}`;
1336
+ if (!_CacheFactory.instances.has(instanceKey)) {
1337
+ const cache = _CacheFactory.createCacheForLayer(layer, serviceName, namespace);
1338
+ _CacheFactory.instances.set(instanceKey, cache);
1339
+ }
1340
+ return _CacheFactory.instances.get(instanceKey);
1341
+ }
1342
+ };
1343
+
1344
+ // src/cache/types/config.ts
1345
+ var CacheProviderType = /* @__PURE__ */ (function(CacheProviderType2) {
1346
+ CacheProviderType2["VALKEY"] = "valkey";
1347
+ CacheProviderType2["MEMORY"] = "memory";
1348
+ CacheProviderType2["MEMCACHED"] = "memcached";
1349
+ return CacheProviderType2;
1350
+ })({});
1351
+
1352
+ // src/cache/index.ts
1353
+ function createCache(namespace = "default") {
1354
+ return CacheFactory.createCacheFromEnv(namespace);
1355
+ }
1356
+ __name(createCache, "createCache");
1357
+ function getCache(namespace = "default", config) {
1358
+ return CacheFactory.getInstance(namespace, config);
1359
+ }
1360
+ __name(getCache, "getCache");
1361
+ async function getValkeyClient(config) {
1362
+ const glideModule = await import('@valkey/valkey-glide');
1363
+ const GlideClient = glideModule.GlideClient || glideModule.default;
1364
+ const valkeyConfig = config || {
1365
+ type: CacheProviderType.VALKEY,
1366
+ url: process.env["VALKEY_URL"],
1367
+ host: process.env["VALKEY_HOST"] || "localhost",
1368
+ port: process.env["VALKEY_PORT"] ? parseInt(process.env["VALKEY_PORT"], 10) : 6379,
1369
+ password: process.env["VALKEY_PASSWORD"],
1370
+ db: process.env["VALKEY_DB"] ? parseInt(process.env["VALKEY_DB"], 10) : 0,
1371
+ username: process.env["VALKEY_USERNAME"]
1372
+ };
1373
+ let host = valkeyConfig.host || "localhost";
1374
+ let port = valkeyConfig.port || 6379;
1375
+ if (valkeyConfig.url) {
1376
+ const url = new URL(valkeyConfig.url.replace("valkey://", "redis://"));
1377
+ host = url.hostname;
1378
+ port = parseInt(url.port || "6379", 10);
1379
+ }
1380
+ const createClient = GlideClient;
1381
+ return createClient.createClient({
1382
+ addresses: [
1383
+ {
1384
+ host,
1385
+ port
1386
+ }
1387
+ ],
1388
+ useTLS: valkeyConfig.useTLS,
1389
+ credentials: valkeyConfig.password ? {
1390
+ password: valkeyConfig.password,
1391
+ username: valkeyConfig.username
1392
+ } : void 0,
1393
+ clientName: valkeyConfig.name || "valkey-glide-client",
1394
+ readFrom: "primary"
1395
+ });
1396
+ }
1397
+ __name(getValkeyClient, "getValkeyClient");
1398
+ async function closeAllCaches() {
1399
+ await CacheFactory.closeAll();
1400
+ }
1401
+ __name(closeAllCaches, "closeAllCaches");
1402
+
1403
+ export { CacheFactory, CacheProviderType, MemoryCacheProvider, ValkeyGlideProvider, cache_exports, closeAllCaches, createCache, getCache, getValkeyClient };
1404
+ //# sourceMappingURL=chunk-4XGGWW36.js.map
1405
+ //# sourceMappingURL=chunk-4XGGWW36.js.map