@bloomneo/appkit 1.2.9

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 (262) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +902 -0
  3. package/bin/appkit.js +71 -0
  4. package/bin/commands/generate.js +1050 -0
  5. package/bin/templates/backend/README.md.template +39 -0
  6. package/bin/templates/backend/api.http.template +0 -0
  7. package/bin/templates/backend/docs/APPKIT_CLI.md +507 -0
  8. package/bin/templates/backend/docs/APPKIT_COMMENTS_GUIDELINES.md +61 -0
  9. package/bin/templates/backend/docs/APPKIT_LLM_GUIDE.md +2539 -0
  10. package/bin/templates/backend/package.json.template +34 -0
  11. package/bin/templates/backend/src/api/features/welcome/welcome.http.template +29 -0
  12. package/bin/templates/backend/src/api/features/welcome/welcome.route.ts.template +36 -0
  13. package/bin/templates/backend/src/api/features/welcome/welcome.service.ts.template +88 -0
  14. package/bin/templates/backend/src/api/features/welcome/welcome.types.ts.template +18 -0
  15. package/bin/templates/backend/src/api/lib/api-router.ts.template +84 -0
  16. package/bin/templates/backend/src/api/server.ts.template +188 -0
  17. package/bin/templates/backend/tsconfig.api.json.template +24 -0
  18. package/bin/templates/backend/tsconfig.json.template +40 -0
  19. package/bin/templates/feature/feature.http.template +63 -0
  20. package/bin/templates/feature/feature.route.ts.template +36 -0
  21. package/bin/templates/feature/feature.service.ts.template +81 -0
  22. package/bin/templates/feature/feature.types.ts.template +23 -0
  23. package/bin/templates/feature-db/feature.http.template +63 -0
  24. package/bin/templates/feature-db/feature.model.ts.template +74 -0
  25. package/bin/templates/feature-db/feature.route.ts.template +58 -0
  26. package/bin/templates/feature-db/feature.service.ts.template +231 -0
  27. package/bin/templates/feature-db/feature.types.ts.template +25 -0
  28. package/bin/templates/feature-db/schema-addition.prisma.template +9 -0
  29. package/bin/templates/feature-db/seeding/README.md.template +57 -0
  30. package/bin/templates/feature-db/seeding/feature.seed.js.template +67 -0
  31. package/bin/templates/feature-user/schema-addition.prisma.template +19 -0
  32. package/bin/templates/feature-user/user.http.template +157 -0
  33. package/bin/templates/feature-user/user.model.ts.template +244 -0
  34. package/bin/templates/feature-user/user.route.ts.template +379 -0
  35. package/bin/templates/feature-user/user.seed.js.template +182 -0
  36. package/bin/templates/feature-user/user.service.ts.template +426 -0
  37. package/bin/templates/feature-user/user.types.ts.template +127 -0
  38. package/dist/auth/auth.d.ts +182 -0
  39. package/dist/auth/auth.d.ts.map +1 -0
  40. package/dist/auth/auth.js +477 -0
  41. package/dist/auth/auth.js.map +1 -0
  42. package/dist/auth/defaults.d.ts +104 -0
  43. package/dist/auth/defaults.d.ts.map +1 -0
  44. package/dist/auth/defaults.js +374 -0
  45. package/dist/auth/defaults.js.map +1 -0
  46. package/dist/auth/index.d.ts +70 -0
  47. package/dist/auth/index.d.ts.map +1 -0
  48. package/dist/auth/index.js +94 -0
  49. package/dist/auth/index.js.map +1 -0
  50. package/dist/cache/cache.d.ts +118 -0
  51. package/dist/cache/cache.d.ts.map +1 -0
  52. package/dist/cache/cache.js +249 -0
  53. package/dist/cache/cache.js.map +1 -0
  54. package/dist/cache/defaults.d.ts +63 -0
  55. package/dist/cache/defaults.d.ts.map +1 -0
  56. package/dist/cache/defaults.js +193 -0
  57. package/dist/cache/defaults.js.map +1 -0
  58. package/dist/cache/index.d.ts +101 -0
  59. package/dist/cache/index.d.ts.map +1 -0
  60. package/dist/cache/index.js +203 -0
  61. package/dist/cache/index.js.map +1 -0
  62. package/dist/cache/strategies/memory.d.ts +138 -0
  63. package/dist/cache/strategies/memory.d.ts.map +1 -0
  64. package/dist/cache/strategies/memory.js +348 -0
  65. package/dist/cache/strategies/memory.js.map +1 -0
  66. package/dist/cache/strategies/redis.d.ts +105 -0
  67. package/dist/cache/strategies/redis.d.ts.map +1 -0
  68. package/dist/cache/strategies/redis.js +318 -0
  69. package/dist/cache/strategies/redis.js.map +1 -0
  70. package/dist/config/config.d.ts +62 -0
  71. package/dist/config/config.d.ts.map +1 -0
  72. package/dist/config/config.js +107 -0
  73. package/dist/config/config.js.map +1 -0
  74. package/dist/config/defaults.d.ts +44 -0
  75. package/dist/config/defaults.d.ts.map +1 -0
  76. package/dist/config/defaults.js +217 -0
  77. package/dist/config/defaults.js.map +1 -0
  78. package/dist/config/index.d.ts +105 -0
  79. package/dist/config/index.d.ts.map +1 -0
  80. package/dist/config/index.js +163 -0
  81. package/dist/config/index.js.map +1 -0
  82. package/dist/database/adapters/mongoose.d.ts +106 -0
  83. package/dist/database/adapters/mongoose.d.ts.map +1 -0
  84. package/dist/database/adapters/mongoose.js +480 -0
  85. package/dist/database/adapters/mongoose.js.map +1 -0
  86. package/dist/database/adapters/prisma.d.ts +106 -0
  87. package/dist/database/adapters/prisma.d.ts.map +1 -0
  88. package/dist/database/adapters/prisma.js +494 -0
  89. package/dist/database/adapters/prisma.js.map +1 -0
  90. package/dist/database/defaults.d.ts +87 -0
  91. package/dist/database/defaults.d.ts.map +1 -0
  92. package/dist/database/defaults.js +271 -0
  93. package/dist/database/defaults.js.map +1 -0
  94. package/dist/database/index.d.ts +137 -0
  95. package/dist/database/index.d.ts.map +1 -0
  96. package/dist/database/index.js +490 -0
  97. package/dist/database/index.js.map +1 -0
  98. package/dist/email/defaults.d.ts +100 -0
  99. package/dist/email/defaults.d.ts.map +1 -0
  100. package/dist/email/defaults.js +400 -0
  101. package/dist/email/defaults.js.map +1 -0
  102. package/dist/email/email.d.ts +139 -0
  103. package/dist/email/email.d.ts.map +1 -0
  104. package/dist/email/email.js +316 -0
  105. package/dist/email/email.js.map +1 -0
  106. package/dist/email/index.d.ts +176 -0
  107. package/dist/email/index.d.ts.map +1 -0
  108. package/dist/email/index.js +251 -0
  109. package/dist/email/index.js.map +1 -0
  110. package/dist/email/strategies/console.d.ts +90 -0
  111. package/dist/email/strategies/console.d.ts.map +1 -0
  112. package/dist/email/strategies/console.js +268 -0
  113. package/dist/email/strategies/console.js.map +1 -0
  114. package/dist/email/strategies/resend.d.ts +84 -0
  115. package/dist/email/strategies/resend.d.ts.map +1 -0
  116. package/dist/email/strategies/resend.js +266 -0
  117. package/dist/email/strategies/resend.js.map +1 -0
  118. package/dist/email/strategies/smtp.d.ts +77 -0
  119. package/dist/email/strategies/smtp.d.ts.map +1 -0
  120. package/dist/email/strategies/smtp.js +286 -0
  121. package/dist/email/strategies/smtp.js.map +1 -0
  122. package/dist/error/defaults.d.ts +40 -0
  123. package/dist/error/defaults.d.ts.map +1 -0
  124. package/dist/error/defaults.js +75 -0
  125. package/dist/error/defaults.js.map +1 -0
  126. package/dist/error/error.d.ts +140 -0
  127. package/dist/error/error.d.ts.map +1 -0
  128. package/dist/error/error.js +200 -0
  129. package/dist/error/error.js.map +1 -0
  130. package/dist/error/index.d.ts +145 -0
  131. package/dist/error/index.d.ts.map +1 -0
  132. package/dist/error/index.js +145 -0
  133. package/dist/error/index.js.map +1 -0
  134. package/dist/event/defaults.d.ts +111 -0
  135. package/dist/event/defaults.d.ts.map +1 -0
  136. package/dist/event/defaults.js +378 -0
  137. package/dist/event/defaults.js.map +1 -0
  138. package/dist/event/event.d.ts +171 -0
  139. package/dist/event/event.d.ts.map +1 -0
  140. package/dist/event/event.js +391 -0
  141. package/dist/event/event.js.map +1 -0
  142. package/dist/event/index.d.ts +173 -0
  143. package/dist/event/index.d.ts.map +1 -0
  144. package/dist/event/index.js +302 -0
  145. package/dist/event/index.js.map +1 -0
  146. package/dist/event/strategies/memory.d.ts +122 -0
  147. package/dist/event/strategies/memory.d.ts.map +1 -0
  148. package/dist/event/strategies/memory.js +331 -0
  149. package/dist/event/strategies/memory.js.map +1 -0
  150. package/dist/event/strategies/redis.d.ts +115 -0
  151. package/dist/event/strategies/redis.d.ts.map +1 -0
  152. package/dist/event/strategies/redis.js +434 -0
  153. package/dist/event/strategies/redis.js.map +1 -0
  154. package/dist/index.d.ts +58 -0
  155. package/dist/index.d.ts.map +1 -0
  156. package/dist/index.js +72 -0
  157. package/dist/index.js.map +1 -0
  158. package/dist/logger/defaults.d.ts +67 -0
  159. package/dist/logger/defaults.d.ts.map +1 -0
  160. package/dist/logger/defaults.js +213 -0
  161. package/dist/logger/defaults.js.map +1 -0
  162. package/dist/logger/index.d.ts +84 -0
  163. package/dist/logger/index.d.ts.map +1 -0
  164. package/dist/logger/index.js +101 -0
  165. package/dist/logger/index.js.map +1 -0
  166. package/dist/logger/logger.d.ts +165 -0
  167. package/dist/logger/logger.d.ts.map +1 -0
  168. package/dist/logger/logger.js +843 -0
  169. package/dist/logger/logger.js.map +1 -0
  170. package/dist/logger/transports/console.d.ts +102 -0
  171. package/dist/logger/transports/console.d.ts.map +1 -0
  172. package/dist/logger/transports/console.js +276 -0
  173. package/dist/logger/transports/console.js.map +1 -0
  174. package/dist/logger/transports/database.d.ts +153 -0
  175. package/dist/logger/transports/database.d.ts.map +1 -0
  176. package/dist/logger/transports/database.js +539 -0
  177. package/dist/logger/transports/database.js.map +1 -0
  178. package/dist/logger/transports/file.d.ts +146 -0
  179. package/dist/logger/transports/file.d.ts.map +1 -0
  180. package/dist/logger/transports/file.js +464 -0
  181. package/dist/logger/transports/file.js.map +1 -0
  182. package/dist/logger/transports/http.d.ts +128 -0
  183. package/dist/logger/transports/http.d.ts.map +1 -0
  184. package/dist/logger/transports/http.js +401 -0
  185. package/dist/logger/transports/http.js.map +1 -0
  186. package/dist/logger/transports/webhook.d.ts +152 -0
  187. package/dist/logger/transports/webhook.d.ts.map +1 -0
  188. package/dist/logger/transports/webhook.js +485 -0
  189. package/dist/logger/transports/webhook.js.map +1 -0
  190. package/dist/queue/defaults.d.ts +66 -0
  191. package/dist/queue/defaults.d.ts.map +1 -0
  192. package/dist/queue/defaults.js +205 -0
  193. package/dist/queue/defaults.js.map +1 -0
  194. package/dist/queue/index.d.ts +124 -0
  195. package/dist/queue/index.d.ts.map +1 -0
  196. package/dist/queue/index.js +116 -0
  197. package/dist/queue/index.js.map +1 -0
  198. package/dist/queue/queue.d.ts +156 -0
  199. package/dist/queue/queue.d.ts.map +1 -0
  200. package/dist/queue/queue.js +387 -0
  201. package/dist/queue/queue.js.map +1 -0
  202. package/dist/queue/transports/database.d.ts +165 -0
  203. package/dist/queue/transports/database.d.ts.map +1 -0
  204. package/dist/queue/transports/database.js +595 -0
  205. package/dist/queue/transports/database.js.map +1 -0
  206. package/dist/queue/transports/memory.d.ts +143 -0
  207. package/dist/queue/transports/memory.d.ts.map +1 -0
  208. package/dist/queue/transports/memory.js +415 -0
  209. package/dist/queue/transports/memory.js.map +1 -0
  210. package/dist/queue/transports/redis.d.ts +203 -0
  211. package/dist/queue/transports/redis.d.ts.map +1 -0
  212. package/dist/queue/transports/redis.js +744 -0
  213. package/dist/queue/transports/redis.js.map +1 -0
  214. package/dist/security/defaults.d.ts +64 -0
  215. package/dist/security/defaults.d.ts.map +1 -0
  216. package/dist/security/defaults.js +159 -0
  217. package/dist/security/defaults.js.map +1 -0
  218. package/dist/security/index.d.ts +110 -0
  219. package/dist/security/index.d.ts.map +1 -0
  220. package/dist/security/index.js +160 -0
  221. package/dist/security/index.js.map +1 -0
  222. package/dist/security/security.d.ts +138 -0
  223. package/dist/security/security.d.ts.map +1 -0
  224. package/dist/security/security.js +419 -0
  225. package/dist/security/security.js.map +1 -0
  226. package/dist/storage/defaults.d.ts +79 -0
  227. package/dist/storage/defaults.d.ts.map +1 -0
  228. package/dist/storage/defaults.js +358 -0
  229. package/dist/storage/defaults.js.map +1 -0
  230. package/dist/storage/index.d.ts +153 -0
  231. package/dist/storage/index.d.ts.map +1 -0
  232. package/dist/storage/index.js +242 -0
  233. package/dist/storage/index.js.map +1 -0
  234. package/dist/storage/storage.d.ts +151 -0
  235. package/dist/storage/storage.d.ts.map +1 -0
  236. package/dist/storage/storage.js +439 -0
  237. package/dist/storage/storage.js.map +1 -0
  238. package/dist/storage/strategies/local.d.ts +117 -0
  239. package/dist/storage/strategies/local.d.ts.map +1 -0
  240. package/dist/storage/strategies/local.js +368 -0
  241. package/dist/storage/strategies/local.js.map +1 -0
  242. package/dist/storage/strategies/r2.d.ts +130 -0
  243. package/dist/storage/strategies/r2.d.ts.map +1 -0
  244. package/dist/storage/strategies/r2.js +470 -0
  245. package/dist/storage/strategies/r2.js.map +1 -0
  246. package/dist/storage/strategies/s3.d.ts +121 -0
  247. package/dist/storage/strategies/s3.d.ts.map +1 -0
  248. package/dist/storage/strategies/s3.js +461 -0
  249. package/dist/storage/strategies/s3.js.map +1 -0
  250. package/dist/util/defaults.d.ts +77 -0
  251. package/dist/util/defaults.d.ts.map +1 -0
  252. package/dist/util/defaults.js +193 -0
  253. package/dist/util/defaults.js.map +1 -0
  254. package/dist/util/index.d.ts +97 -0
  255. package/dist/util/index.d.ts.map +1 -0
  256. package/dist/util/index.js +165 -0
  257. package/dist/util/index.js.map +1 -0
  258. package/dist/util/util.d.ts +145 -0
  259. package/dist/util/util.d.ts.map +1 -0
  260. package/dist/util/util.js +481 -0
  261. package/dist/util/util.js.map +1 -0
  262. package/package.json +234 -0
@@ -0,0 +1,193 @@
1
+ /**
2
+ * Smart defaults and environment validation for caching
3
+ * @module @bloomneo/appkit/cache
4
+ * @file src/cache/defaults.ts
5
+ *
6
+ * @llm-rule WHEN: App startup - need to configure cache behavior and connection strategy
7
+ * @llm-rule AVOID: Calling multiple times - expensive environment parsing, use lazy loading in get()
8
+ * @llm-rule NOTE: Called once at startup, cached globally for performance
9
+ */
10
+ /**
11
+ * Gets smart defaults using environment variables with auto-strategy detection
12
+ * @llm-rule WHEN: App startup to get production-ready cache configuration
13
+ * @llm-rule AVOID: Calling repeatedly - expensive validation, cache the result
14
+ * @llm-rule NOTE: Auto-detects Redis vs Memory based on REDIS_URL environment variable
15
+ */
16
+ export function getSmartDefaults() {
17
+ validateEnvironment();
18
+ const nodeEnv = process.env.NODE_ENV || 'development';
19
+ const isDevelopment = nodeEnv === 'development';
20
+ const isProduction = nodeEnv === 'production';
21
+ const isTest = nodeEnv === 'test';
22
+ // Auto-detect strategy from environment
23
+ const strategy = detectCacheStrategy();
24
+ return {
25
+ // Strategy selection with smart detection
26
+ strategy,
27
+ // Key management with service identification
28
+ keyPrefix: process.env.VOILA_CACHE_PREFIX || process.env.VOILA_SERVICE_NAME || 'app',
29
+ namespace: process.env.VOILA_CACHE_NAMESPACE || 'default',
30
+ // TTL configuration with environment awareness
31
+ defaultTTL: parseInt(process.env.VOILA_CACHE_TTL || (isProduction ? '3600' : '300')), // 1hr prod, 5min dev
32
+ // Redis configuration (only used when strategy is 'redis')
33
+ redis: {
34
+ url: process.env.REDIS_URL || 'redis://localhost:6379',
35
+ password: process.env.REDIS_PASSWORD,
36
+ maxRetries: parseInt(process.env.VOILA_CACHE_REDIS_RETRIES || '3'),
37
+ retryDelay: parseInt(process.env.VOILA_CACHE_REDIS_RETRY_DELAY || '1000'),
38
+ connectTimeout: parseInt(process.env.VOILA_CACHE_REDIS_CONNECT_TIMEOUT || '10000'),
39
+ commandTimeout: parseInt(process.env.VOILA_CACHE_REDIS_COMMAND_TIMEOUT || '5000'),
40
+ },
41
+ // Memory configuration (only used when strategy is 'memory')
42
+ memory: {
43
+ maxItems: parseInt(process.env.VOILA_CACHE_MEMORY_MAX_ITEMS || '10000'),
44
+ maxSizeBytes: parseInt(process.env.VOILA_CACHE_MEMORY_MAX_SIZE || '100000000'), // 100MB
45
+ checkInterval: parseInt(process.env.VOILA_CACHE_MEMORY_CHECK_INTERVAL || '60000'), // 1 minute
46
+ },
47
+ // Environment information
48
+ environment: {
49
+ isDevelopment,
50
+ isProduction,
51
+ isTest,
52
+ nodeEnv,
53
+ },
54
+ };
55
+ }
56
+ /**
57
+ * Auto-detect cache strategy from environment variables
58
+ * @llm-rule WHEN: Determining which cache strategy to use automatically
59
+ * @llm-rule AVOID: Manual strategy selection - environment detection handles most cases
60
+ * @llm-rule NOTE: REDIS_URL = Redis, no REDIS_URL = Memory (perfect for dev/test)
61
+ */
62
+ function detectCacheStrategy() {
63
+ // Explicit override wins (for testing/debugging)
64
+ const explicit = process.env.VOILA_CACHE_STRATEGY?.toLowerCase();
65
+ if (explicit === 'redis' || explicit === 'memory') {
66
+ return explicit;
67
+ }
68
+ // Auto-detection logic
69
+ if (process.env.REDIS_URL) {
70
+ return 'redis'; // Redis URL available
71
+ }
72
+ if (process.env.NODE_ENV === 'production') {
73
+ console.warn('[VoilaJSX AppKit] No REDIS_URL found in production. ' +
74
+ 'Using memory cache which will not persist across server restarts. ' +
75
+ 'Set REDIS_URL for production caching.');
76
+ }
77
+ return 'memory'; // Default to memory for development/testing
78
+ }
79
+ /**
80
+ * Validates environment variables for cache configuration
81
+ * @llm-rule WHEN: App startup to ensure proper cache environment configuration
82
+ * @llm-rule AVOID: Skipping validation - improper config causes silent cache failures
83
+ * @llm-rule NOTE: Validates Redis URLs, numeric values, and production requirements
84
+ */
85
+ function validateEnvironment() {
86
+ // Validate Redis URL if provided
87
+ const redisUrl = process.env.REDIS_URL;
88
+ if (redisUrl && !isValidRedisUrl(redisUrl)) {
89
+ throw new Error(`Invalid REDIS_URL: "${redisUrl}". Must start with redis:// or rediss://`);
90
+ }
91
+ // Validate cache strategy if explicitly set
92
+ const strategy = process.env.VOILA_CACHE_STRATEGY;
93
+ if (strategy && !['redis', 'memory'].includes(strategy.toLowerCase())) {
94
+ throw new Error(`Invalid VOILA_CACHE_STRATEGY: "${strategy}". Must be "redis" or "memory"`);
95
+ }
96
+ // Validate numeric values
97
+ validateNumericEnv('VOILA_CACHE_TTL', 1, 86400 * 7); // 1 second to 1 week
98
+ validateNumericEnv('VOILA_CACHE_REDIS_RETRIES', 0, 10);
99
+ validateNumericEnv('VOILA_CACHE_REDIS_RETRY_DELAY', 100, 10000);
100
+ validateNumericEnv('VOILA_CACHE_REDIS_CONNECT_TIMEOUT', 1000, 60000);
101
+ validateNumericEnv('VOILA_CACHE_REDIS_COMMAND_TIMEOUT', 1000, 30000);
102
+ validateNumericEnv('VOILA_CACHE_MEMORY_MAX_ITEMS', 100, 1000000);
103
+ validateNumericEnv('VOILA_CACHE_MEMORY_MAX_SIZE', 1000000, 1000000000); // 1MB to 1GB
104
+ validateNumericEnv('VOILA_CACHE_MEMORY_CHECK_INTERVAL', 10000, 300000); // 10s to 5min
105
+ // Validate key prefix
106
+ const keyPrefix = process.env.VOILA_CACHE_PREFIX;
107
+ if (keyPrefix && !/^[a-zA-Z0-9_-]+$/.test(keyPrefix)) {
108
+ throw new Error(`Invalid VOILA_CACHE_PREFIX: "${keyPrefix}". Must contain only letters, numbers, underscores, and hyphens`);
109
+ }
110
+ // Validate namespace
111
+ const namespace = process.env.VOILA_CACHE_NAMESPACE;
112
+ if (namespace && !/^[a-zA-Z0-9_-]+$/.test(namespace)) {
113
+ throw new Error(`Invalid VOILA_CACHE_NAMESPACE: "${namespace}". Must contain only letters, numbers, underscores, and hyphens`);
114
+ }
115
+ // Production-specific validations
116
+ const nodeEnv = process.env.NODE_ENV;
117
+ if (nodeEnv === 'production') {
118
+ if (!redisUrl) {
119
+ console.warn('[VoilaJSX AppKit] Production environment detected without REDIS_URL. ' +
120
+ 'Memory cache will not persist across server restarts. ' +
121
+ 'Consider setting REDIS_URL for production deployments.');
122
+ }
123
+ }
124
+ // Validate NODE_ENV
125
+ if (nodeEnv && !['development', 'production', 'test', 'staging'].includes(nodeEnv)) {
126
+ console.warn(`[VoilaJSX AppKit] Unusual NODE_ENV: "${nodeEnv}". ` +
127
+ `Expected: development, production, test, or staging`);
128
+ }
129
+ }
130
+ /**
131
+ * Validates Redis URL format
132
+ * @llm-rule WHEN: Checking Redis connection string validity
133
+ * @llm-rule AVOID: Using invalid Redis URLs - causes connection failures
134
+ */
135
+ function isValidRedisUrl(url) {
136
+ try {
137
+ const parsed = new URL(url);
138
+ return ['redis:', 'rediss:'].includes(parsed.protocol);
139
+ }
140
+ catch {
141
+ return false;
142
+ }
143
+ }
144
+ /**
145
+ * Validates numeric environment variable within acceptable range
146
+ * @llm-rule WHEN: Validating cache configuration numeric values
147
+ * @llm-rule AVOID: Using values outside safe ranges - causes performance or memory issues
148
+ */
149
+ function validateNumericEnv(name, min, max) {
150
+ const value = process.env[name];
151
+ if (!value)
152
+ return;
153
+ const num = parseInt(value);
154
+ if (isNaN(num) || num < min || num > max) {
155
+ throw new Error(`Invalid ${name}: "${value}". Must be a number between ${min} and ${max}`);
156
+ }
157
+ }
158
+ /**
159
+ * Gets cache configuration summary for debugging and health checks
160
+ * @llm-rule WHEN: Debugging cache configuration or building health check endpoints
161
+ * @llm-rule AVOID: Exposing sensitive connection details - this only shows safe info
162
+ */
163
+ export function getConfigSummary() {
164
+ const config = getSmartDefaults();
165
+ return {
166
+ strategy: config.strategy,
167
+ keyPrefix: config.keyPrefix,
168
+ namespace: config.namespace,
169
+ defaultTTL: config.defaultTTL,
170
+ redisConnected: config.strategy === 'redis' && !!config.redis?.url,
171
+ environment: config.environment.nodeEnv,
172
+ };
173
+ }
174
+ /**
175
+ * Validates that required cache configuration is present for production
176
+ * @llm-rule WHEN: App startup validation for production deployments
177
+ * @llm-rule AVOID: Skipping validation - missing cache config causes runtime issues
178
+ */
179
+ export function validateProductionRequirements() {
180
+ const config = getSmartDefaults();
181
+ if (config.environment.isProduction) {
182
+ if (config.strategy === 'memory') {
183
+ console.warn('[VoilaJSX AppKit] Using memory cache in production. ' +
184
+ 'Data will not persist across server restarts. ' +
185
+ 'Set REDIS_URL for persistent caching.');
186
+ }
187
+ if (config.strategy === 'redis' && !config.redis?.url) {
188
+ throw new Error('Redis strategy selected but REDIS_URL not configured. ' +
189
+ 'Set REDIS_URL environment variable for Redis caching.');
190
+ }
191
+ }
192
+ }
193
+ //# sourceMappingURL=defaults.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/cache/defaults.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Ultra-simple caching that just works with automatic Redis/Memory strategy selection
3
+ * @module @bloomneo/appkit/cache
4
+ * @file src/cache/index.ts
5
+ *
6
+ * @llm-rule WHEN: Building apps that need caching with zero configuration
7
+ * @llm-rule AVOID: Complex cache setups - this auto-detects Redis vs Memory from environment
8
+ * @llm-rule NOTE: Uses cacheClass.get(namespace) pattern like auth - get() → cache.set() → done
9
+ * @llm-rule NOTE: Common pattern - cacheClass.get('users') → cache.set('user:123', data) → cache.get('user:123')
10
+ */
11
+ import { type CacheConfig } from './defaults.js';
12
+ export interface Cache {
13
+ get(key: string): Promise<any>;
14
+ set(key: string, value: any, ttl?: number): Promise<boolean>;
15
+ delete(key: string): Promise<boolean>;
16
+ clear(): Promise<boolean>;
17
+ getOrSet(key: string, factory: () => Promise<any>, ttl?: number): Promise<any>;
18
+ getStrategy(): string;
19
+ getConfig(): any;
20
+ }
21
+ /**
22
+ * Get cache instance for specific namespace - the only function you need to learn
23
+ * Strategy auto-detected from environment (REDIS_URL = Redis, no REDIS_URL = Memory)
24
+ * @llm-rule WHEN: Need caching in any part of your app - this is your main entry point
25
+ * @llm-rule AVOID: Creating CacheClass directly - always use this function
26
+ * @llm-rule NOTE: Typical flow - get(namespace) → cache.set() → cache.get() → cached data
27
+ */
28
+ declare function get(namespace?: string): Cache;
29
+ /**
30
+ * Clear all cache instances and disconnect - essential for testing
31
+ * @llm-rule WHEN: Testing cache logic with different configurations or app shutdown
32
+ * @llm-rule AVOID: Using in production except for graceful shutdown
33
+ */
34
+ declare function clear(): Promise<void>;
35
+ /**
36
+ * Reset cache configuration (useful for testing)
37
+ * @llm-rule WHEN: Testing cache logic with different environment configurations
38
+ * @llm-rule AVOID: Using in production - only for tests and development
39
+ */
40
+ declare function reset(newConfig?: Partial<CacheConfig>): Promise<void>;
41
+ /**
42
+ * Get active cache strategy for debugging
43
+ * @llm-rule WHEN: Debugging or health checks to see which strategy is active (Redis vs Memory)
44
+ * @llm-rule AVOID: Using for application logic - cache should be transparent
45
+ */
46
+ declare function getStrategy(): string;
47
+ /**
48
+ * Get all active cache namespaces
49
+ * @llm-rule WHEN: Debugging or monitoring which cache namespaces are active
50
+ * @llm-rule AVOID: Using for business logic - this is for observability only
51
+ */
52
+ declare function getActiveNamespaces(): string[];
53
+ /**
54
+ * Get cache configuration summary for debugging
55
+ * @llm-rule WHEN: Health checks or debugging cache configuration
56
+ * @llm-rule AVOID: Exposing sensitive connection details - this only shows safe info
57
+ */
58
+ declare function getConfig(): {
59
+ strategy: string;
60
+ keyPrefix: string;
61
+ defaultTTL: number;
62
+ activeNamespaces: string[];
63
+ environment: string;
64
+ };
65
+ /**
66
+ * Check if Redis is available and configured
67
+ * @llm-rule WHEN: Conditional logic based on cache capabilities
68
+ * @llm-rule AVOID: Complex cache detection - just use cache normally, it handles strategy
69
+ */
70
+ declare function hasRedis(): boolean;
71
+ /**
72
+ * Flush all caches across all namespaces (dangerous)
73
+ * @llm-rule WHEN: Testing or emergency cache clearing across all namespaces
74
+ * @llm-rule AVOID: Using in production - this clears ALL cached data in ALL namespaces
75
+ * @llm-rule NOTE: Only use for testing or emergency situations
76
+ */
77
+ declare function flushAll(): Promise<boolean>;
78
+ /**
79
+ * Graceful shutdown for all cache instances
80
+ * @llm-rule WHEN: App shutdown or process termination
81
+ * @llm-rule AVOID: Abrupt process exit - graceful shutdown prevents data loss
82
+ */
83
+ declare function shutdown(): Promise<void>;
84
+ /**
85
+ * Single caching export with minimal API (like auth module)
86
+ */
87
+ export declare const cacheClass: {
88
+ readonly get: typeof get;
89
+ readonly clear: typeof clear;
90
+ readonly reset: typeof reset;
91
+ readonly getStrategy: typeof getStrategy;
92
+ readonly getActiveNamespaces: typeof getActiveNamespaces;
93
+ readonly getConfig: typeof getConfig;
94
+ readonly hasRedis: typeof hasRedis;
95
+ readonly flushAll: typeof flushAll;
96
+ readonly shutdown: typeof shutdown;
97
+ };
98
+ export type { CacheConfig } from './defaults.js';
99
+ export { CacheClass } from './cache.js';
100
+ export default cacheClass;
101
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cache/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAoB,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAMnE,MAAM,WAAW,KAAK;IACpB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAC/B,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7D,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACtC,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1B,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAC/E,WAAW,IAAI,MAAM,CAAC;IACtB,SAAS,IAAI,GAAG,CAAC;CAClB;AAED;;;;;;GAMG;AACH,iBAAS,GAAG,CAAC,SAAS,GAAE,MAAc,GAAG,KAAK,CA8B7C;AAED;;;;GAIG;AACH,iBAAe,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAcpC;AAED;;;;GAIG;AACH,iBAAe,KAAK,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAWpE;AAED;;;;GAIG;AACH,iBAAS,WAAW,IAAI,MAAM,CAK7B;AAED;;;;GAIG;AACH,iBAAS,mBAAmB,IAAI,MAAM,EAAE,CAEvC;AAED;;;;GAIG;AACH,iBAAS,SAAS,IAAI;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,WAAW,EAAE,MAAM,CAAC;CACrB,CAYA;AAED;;;;GAIG;AACH,iBAAS,QAAQ,IAAI,OAAO,CAE3B;AAED;;;;;GAKG;AACH,iBAAe,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC,CAc1C;AAED;;;;GAIG;AACH,iBAAe,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CASvC;AAED;;GAEG;AACH,eAAO,MAAM,UAAU;;;;;;;;;;CAab,CAAC;AAGX,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAGxC,eAAe,UAAU,CAAC"}
@@ -0,0 +1,203 @@
1
+ /**
2
+ * Ultra-simple caching that just works with automatic Redis/Memory strategy selection
3
+ * @module @bloomneo/appkit/cache
4
+ * @file src/cache/index.ts
5
+ *
6
+ * @llm-rule WHEN: Building apps that need caching with zero configuration
7
+ * @llm-rule AVOID: Complex cache setups - this auto-detects Redis vs Memory from environment
8
+ * @llm-rule NOTE: Uses cacheClass.get(namespace) pattern like auth - get() → cache.set() → done
9
+ * @llm-rule NOTE: Common pattern - cacheClass.get('users') → cache.set('user:123', data) → cache.get('user:123')
10
+ */
11
+ import { CacheClass } from './cache.js';
12
+ import { getSmartDefaults } from './defaults.js';
13
+ // Global cache instances for performance (like auth module)
14
+ let globalConfig = null;
15
+ const namedCaches = new Map();
16
+ /**
17
+ * Get cache instance for specific namespace - the only function you need to learn
18
+ * Strategy auto-detected from environment (REDIS_URL = Redis, no REDIS_URL = Memory)
19
+ * @llm-rule WHEN: Need caching in any part of your app - this is your main entry point
20
+ * @llm-rule AVOID: Creating CacheClass directly - always use this function
21
+ * @llm-rule NOTE: Typical flow - get(namespace) → cache.set() → cache.get() → cached data
22
+ */
23
+ function get(namespace = 'app') {
24
+ // Validate namespace
25
+ if (!namespace || typeof namespace !== 'string') {
26
+ throw new Error('Cache namespace must be a non-empty string');
27
+ }
28
+ if (!/^[a-zA-Z0-9_-]+$/.test(namespace)) {
29
+ throw new Error('Cache namespace must contain only letters, numbers, underscores, and hyphens');
30
+ }
31
+ // Lazy initialization - parse environment once (like auth)
32
+ if (!globalConfig) {
33
+ globalConfig = getSmartDefaults();
34
+ }
35
+ // Return cached instance if exists
36
+ if (namedCaches.has(namespace)) {
37
+ return namedCaches.get(namespace);
38
+ }
39
+ // Create new cache instance for namespace
40
+ const cacheInstance = new CacheClass(globalConfig, namespace);
41
+ // Auto-connect on first use
42
+ cacheInstance.connect().catch((error) => {
43
+ console.error(`[AppKit] Cache auto-connect failed for namespace "${namespace}":`, error.message);
44
+ });
45
+ namedCaches.set(namespace, cacheInstance);
46
+ return cacheInstance;
47
+ }
48
+ /**
49
+ * Clear all cache instances and disconnect - essential for testing
50
+ * @llm-rule WHEN: Testing cache logic with different configurations or app shutdown
51
+ * @llm-rule AVOID: Using in production except for graceful shutdown
52
+ */
53
+ async function clear() {
54
+ const disconnectPromises = [];
55
+ for (const [namespace, cache] of namedCaches) {
56
+ disconnectPromises.push(cache.disconnect().catch((error) => {
57
+ console.error(`[AppKit] Cache disconnect failed for namespace "${namespace}":`, error.message);
58
+ }));
59
+ }
60
+ await Promise.all(disconnectPromises);
61
+ namedCaches.clear();
62
+ globalConfig = null;
63
+ }
64
+ /**
65
+ * Reset cache configuration (useful for testing)
66
+ * @llm-rule WHEN: Testing cache logic with different environment configurations
67
+ * @llm-rule AVOID: Using in production - only for tests and development
68
+ */
69
+ async function reset(newConfig) {
70
+ // Clear existing instances
71
+ await clear();
72
+ // Reset configuration
73
+ if (newConfig) {
74
+ const defaults = getSmartDefaults();
75
+ globalConfig = { ...defaults, ...newConfig };
76
+ }
77
+ else {
78
+ globalConfig = null; // Will reload from environment on next get()
79
+ }
80
+ }
81
+ /**
82
+ * Get active cache strategy for debugging
83
+ * @llm-rule WHEN: Debugging or health checks to see which strategy is active (Redis vs Memory)
84
+ * @llm-rule AVOID: Using for application logic - cache should be transparent
85
+ */
86
+ function getStrategy() {
87
+ if (!globalConfig) {
88
+ globalConfig = getSmartDefaults();
89
+ }
90
+ return globalConfig.strategy;
91
+ }
92
+ /**
93
+ * Get all active cache namespaces
94
+ * @llm-rule WHEN: Debugging or monitoring which cache namespaces are active
95
+ * @llm-rule AVOID: Using for business logic - this is for observability only
96
+ */
97
+ function getActiveNamespaces() {
98
+ return Array.from(namedCaches.keys());
99
+ }
100
+ /**
101
+ * Get cache configuration summary for debugging
102
+ * @llm-rule WHEN: Health checks or debugging cache configuration
103
+ * @llm-rule AVOID: Exposing sensitive connection details - this only shows safe info
104
+ */
105
+ function getConfig() {
106
+ if (!globalConfig) {
107
+ globalConfig = getSmartDefaults();
108
+ }
109
+ return {
110
+ strategy: globalConfig.strategy,
111
+ keyPrefix: globalConfig.keyPrefix,
112
+ defaultTTL: globalConfig.defaultTTL,
113
+ activeNamespaces: getActiveNamespaces(),
114
+ environment: globalConfig.environment.nodeEnv,
115
+ };
116
+ }
117
+ /**
118
+ * Check if Redis is available and configured
119
+ * @llm-rule WHEN: Conditional logic based on cache capabilities
120
+ * @llm-rule AVOID: Complex cache detection - just use cache normally, it handles strategy
121
+ */
122
+ function hasRedis() {
123
+ return !!process.env.REDIS_URL;
124
+ }
125
+ /**
126
+ * Flush all caches across all namespaces (dangerous)
127
+ * @llm-rule WHEN: Testing or emergency cache clearing across all namespaces
128
+ * @llm-rule AVOID: Using in production - this clears ALL cached data in ALL namespaces
129
+ * @llm-rule NOTE: Only use for testing or emergency situations
130
+ */
131
+ async function flushAll() {
132
+ try {
133
+ const clearPromises = [];
134
+ for (const cache of namedCaches.values()) {
135
+ clearPromises.push(cache.clear());
136
+ }
137
+ const results = await Promise.all(clearPromises);
138
+ return results.every(result => result === true);
139
+ }
140
+ catch (error) {
141
+ console.error('[AppKit] Cache flushAll error:', error.message);
142
+ return false;
143
+ }
144
+ }
145
+ /**
146
+ * Graceful shutdown for all cache instances
147
+ * @llm-rule WHEN: App shutdown or process termination
148
+ * @llm-rule AVOID: Abrupt process exit - graceful shutdown prevents data loss
149
+ */
150
+ async function shutdown() {
151
+ console.log('🔄 [AppKit] Cache graceful shutdown...');
152
+ try {
153
+ await clear();
154
+ console.log('✅ [AppKit] Cache shutdown complete');
155
+ }
156
+ catch (error) {
157
+ console.error('❌ [AppKit] Cache shutdown error:', error.message);
158
+ }
159
+ }
160
+ /**
161
+ * Single caching export with minimal API (like auth module)
162
+ */
163
+ export const cacheClass = {
164
+ // Core method (like auth.get())
165
+ get,
166
+ // Utility methods
167
+ clear,
168
+ reset,
169
+ getStrategy,
170
+ getActiveNamespaces,
171
+ getConfig,
172
+ hasRedis,
173
+ flushAll,
174
+ shutdown,
175
+ };
176
+ export { CacheClass } from './cache.js';
177
+ // Default export
178
+ export default cacheClass;
179
+ // Auto-setup graceful shutdown handlers
180
+ if (typeof process !== 'undefined') {
181
+ // Handle graceful shutdown
182
+ const shutdownHandler = () => {
183
+ shutdown().finally(() => {
184
+ process.exit(0);
185
+ });
186
+ };
187
+ process.on('SIGTERM', shutdownHandler);
188
+ process.on('SIGINT', shutdownHandler);
189
+ // Handle uncaught errors
190
+ process.on('uncaughtException', (error) => {
191
+ console.error('[AppKit] Uncaught exception during cache operation:', error);
192
+ shutdown().finally(() => {
193
+ process.exit(1);
194
+ });
195
+ });
196
+ process.on('unhandledRejection', (reason) => {
197
+ console.error('[AppKit] Unhandled rejection during cache operation:', reason);
198
+ shutdown().finally(() => {
199
+ process.exit(1);
200
+ });
201
+ });
202
+ }
203
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cache/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Memory cache strategy with LRU eviction and TTL expiration
3
+ * @module @bloomneo/appkit/cache
4
+ * @file src/cache/strategies/memory.ts
5
+ *
6
+ * @llm-rule WHEN: No REDIS_URL environment variable - perfect for development and testing
7
+ * @llm-rule AVOID: Production use without Redis - memory cache doesn't persist across restarts
8
+ * @llm-rule NOTE: LRU eviction, TTL cleanup, memory limits, thread-safe operations
9
+ */
10
+ import type { CacheStrategy } from '../cache.js';
11
+ import type { CacheConfig } from '../defaults.js';
12
+ /**
13
+ * Memory cache strategy with intelligent eviction and cleanup
14
+ */
15
+ export declare class MemoryStrategy implements CacheStrategy {
16
+ private config;
17
+ private cache;
18
+ private totalSize;
19
+ private cleanupInterval;
20
+ private connected;
21
+ /**
22
+ * Creates memory strategy with direct environment access (like auth pattern)
23
+ * @llm-rule WHEN: Cache initialization without Redis URL - automatic fallback
24
+ * @llm-rule AVOID: Manual memory configuration - environment detection handles this
25
+ */
26
+ constructor(config: CacheConfig);
27
+ /**
28
+ * Connects memory cache (starts cleanup intervals)
29
+ * @llm-rule WHEN: Cache initialization - sets up automatic TTL cleanup
30
+ * @llm-rule AVOID: Manual memory management - this handles TTL and size limits automatically
31
+ */
32
+ connect(): Promise<void>;
33
+ /**
34
+ * Disconnects memory cache (stops cleanup intervals)
35
+ * @llm-rule WHEN: App shutdown or cache cleanup
36
+ * @llm-rule AVOID: Memory leaks - always stop intervals on shutdown
37
+ */
38
+ disconnect(): Promise<void>;
39
+ /**
40
+ * Gets value from memory cache with TTL checking
41
+ * @llm-rule WHEN: Retrieving cached data from in-memory storage
42
+ * @llm-rule AVOID: Manual TTL checking - this handles expiration automatically
43
+ */
44
+ get(key: string): Promise<any>;
45
+ /**
46
+ * Sets value in memory cache with TTL and automatic eviction
47
+ * @llm-rule WHEN: Storing data in memory cache with size and TTL management
48
+ * @llm-rule AVOID: Manual memory management - this handles LRU eviction automatically
49
+ */
50
+ set(key: string, value: any, ttl: number): Promise<boolean>;
51
+ /**
52
+ * Deletes key from memory cache
53
+ * @llm-rule WHEN: Cache invalidation or removing specific cached data
54
+ * @llm-rule AVOID: Manual memory cleanup - this handles size tracking automatically
55
+ */
56
+ delete(key: string): Promise<boolean>;
57
+ /**
58
+ * Clears entire memory cache
59
+ * @llm-rule WHEN: Full cache invalidation or testing cleanup
60
+ * @llm-rule AVOID: Using in production without consideration - clears all cached data
61
+ */
62
+ clear(): Promise<boolean>;
63
+ /**
64
+ * Checks if key exists in memory cache
65
+ * @llm-rule WHEN: Checking cache key existence without retrieving value
66
+ * @llm-rule AVOID: Using get() then checking null - this is more efficient
67
+ */
68
+ has(key: string): Promise<boolean>;
69
+ /**
70
+ * Gets all keys matching pattern (supports wildcards)
71
+ * @llm-rule WHEN: Finding all keys in namespace for bulk operations
72
+ * @llm-rule AVOID: Complex pattern matching - simple wildcards only
73
+ */
74
+ keys(pattern?: string): Promise<string[]>;
75
+ /**
76
+ * Deletes multiple keys efficiently
77
+ * @llm-rule WHEN: Bulk deletion operations like namespace clearing
78
+ * @llm-rule AVOID: Individual delete calls in loops - this batches operations
79
+ */
80
+ deleteMany(keys: string[]): Promise<number>;
81
+ /**
82
+ * Deletes single item and updates size tracking
83
+ */
84
+ private deleteItem;
85
+ /**
86
+ * Checks if cache item has expired
87
+ */
88
+ private isExpired;
89
+ /**
90
+ * Evicts items when memory limits are exceeded
91
+ */
92
+ private evictIfNeeded;
93
+ /**
94
+ * Evicts least recently used item
95
+ */
96
+ private evictLRU;
97
+ /**
98
+ * Calculates memory size of value (approximate)
99
+ */
100
+ private calculateSize;
101
+ /**
102
+ * Deep clones value to prevent external mutations
103
+ */
104
+ private deepClone;
105
+ /**
106
+ * Converts glob pattern to regex for key matching
107
+ */
108
+ private patternToRegex;
109
+ /**
110
+ * Starts automatic cleanup interval for TTL expiration
111
+ */
112
+ private startCleanupInterval;
113
+ /**
114
+ * Stops cleanup interval
115
+ */
116
+ private stopCleanupInterval;
117
+ /**
118
+ * Removes expired items from cache
119
+ */
120
+ private cleanupExpired;
121
+ /**
122
+ * Formats bytes for human-readable display
123
+ */
124
+ private formatBytes;
125
+ /**
126
+ * Gets memory cache statistics for debugging
127
+ */
128
+ getStats(): {
129
+ itemCount: number;
130
+ totalSize: number;
131
+ totalSizeFormatted: string;
132
+ maxItems: number;
133
+ maxSize: number;
134
+ maxSizeFormatted: string;
135
+ memoryUsage: number;
136
+ };
137
+ }
138
+ //# sourceMappingURL=memory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../../src/cache/strategies/memory.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAUlD;;GAEG;AACH,qBAAa,cAAe,YAAW,aAAa;IAClD,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,KAAK,CAAgC;IAC7C,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,eAAe,CAA+B;IACtD,OAAO,CAAC,SAAS,CAAS;IAE1B;;;;OAIG;gBACS,MAAM,EAAE,WAAW;IAI/B;;;;OAIG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAY9B;;;;OAIG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAajC;;;;OAIG;IACG,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAmBpC;;;;OAIG;IACG,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAwCjE;;;;OAIG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAI3C;;;;OAIG;IACG,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC;IAM/B;;;;OAIG;IACG,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAgBxC;;;;OAIG;IACG,IAAI,CAAC,OAAO,GAAE,MAAY,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAmBpD;;;;OAIG;IACG,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAcjD;;OAEG;IACH,OAAO,CAAC,UAAU;IASlB;;OAEG;IACH,OAAO,CAAC,SAAS;IAIjB;;OAEG;IACH,OAAO,CAAC,aAAa;IAgBrB;;OAEG;IACH,OAAO,CAAC,QAAQ;IAsBhB;;OAEG;IACH,OAAO,CAAC,aAAa;IAWrB;;OAEG;IACH,OAAO,CAAC,SAAS;IASjB;;OAEG;IACH,OAAO,CAAC,cAAc;IActB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAa5B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAO3B;;OAEG;IACH,OAAO,CAAC,cAAc;IAoBtB;;OAEG;IACH,OAAO,CAAC,WAAW;IAUnB;;OAEG;IACH,QAAQ,IAAI;QACV,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,kBAAkB,EAAE,MAAM,CAAC;QAC3B,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,gBAAgB,EAAE,MAAM,CAAC;QACzB,WAAW,EAAE,MAAM,CAAC;KACrB;CAaF"}